Skip to content

Commit

Permalink
fix: CNS-972: enhanced the unit test for iprpc subscriptions (#1455)
Browse files Browse the repository at this point in the history
* CNS-972: enhanced the unit test for iprpc subscriptions

* CNS-972: fix lint
  • Loading branch information
oren-lava authored May 31, 2024
1 parent c0a6a5c commit 604af55
Show file tree
Hide file tree
Showing 2 changed files with 111 additions and 49 deletions.
49 changes: 49 additions & 0 deletions x/rewards/keeper/helpers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ import (
commontypes "github.com/lavanet/lava/common/types"
"github.com/lavanet/lava/testutil/common"
testkeeper "github.com/lavanet/lava/testutil/keeper"
"github.com/lavanet/lava/utils/sigs"
planstypes "github.com/lavanet/lava/x/plans/types"
"github.com/lavanet/lava/x/projects/types"
rewardstypes "github.com/lavanet/lava/x/rewards/types"
spectypes "github.com/lavanet/lava/x/spec/types"
"github.com/stretchr/testify/require"
Expand Down Expand Up @@ -138,6 +140,53 @@ func (ts *tester) setupForIprpcTests(fundIprpcPool bool) {
}
}

// getConsumersForIprpcSubTest is a helper function specifically for the TestIprpcEligibleSubscriptions unit test
// this function returns two consumer addresses to test depending on the input mode:
//
// SUB_OWNERS = 0
// DEVELOPERS_ADMIN_PROJECT = 1
// DEVELOPERS_REGULAR_PROJECT = 2
//
// this function assumes that ts.setupForIprpcTests ran before it
func (ts *tester) getConsumersForIprpcSubTest(mode int) (sigs.Account, sigs.Account) {
switch mode {
case 0:
sub1Acc, _ := ts.GetAccount(common.CONSUMER, 0)
sub2Acc, _ := ts.GetAccount(common.CONSUMER, 1)
return sub1Acc, sub2Acc
case 1:
sub1Acc, _ := ts.GetAccount(common.CONSUMER, 0)
sub2Acc, _ := ts.GetAccount(common.CONSUMER, 1)
adminDev1, _ := ts.AddAccount(common.CONSUMER, 2, testBalance*10000)
adminDev2, _ := ts.AddAccount(common.CONSUMER, 3, testBalance*10000)
res1, err := ts.QueryProjectDeveloper(sub1Acc.Addr.String())
require.NoError(ts.T, err)
res2, err := ts.QueryProjectDeveloper(sub2Acc.Addr.String())
require.NoError(ts.T, err)
err = ts.TxProjectAddKeys(res1.Project.Index, sub1Acc.Addr.String(), types.ProjectDeveloperKey(adminDev1.Addr.String()))
require.NoError(ts.T, err)
err = ts.TxProjectAddKeys(res2.Project.Index, sub2Acc.Addr.String(), types.ProjectDeveloperKey(adminDev2.Addr.String()))
require.NoError(ts.T, err)
return adminDev1, adminDev2
case 2:
sub1Acc, _ := ts.GetAccount(common.CONSUMER, 0)
sub2Acc, _ := ts.GetAccount(common.CONSUMER, 1)
dev1, _ := ts.AddAccount(common.CONSUMER, 2, testBalance*10000)
dev2, _ := ts.AddAccount(common.CONSUMER, 3, testBalance*10000)
err := ts.TxSubscriptionAddProject(sub1Acc.Addr.String(), types.ProjectData{
Name: "test1", Enabled: true, ProjectKeys: []types.ProjectKey{{Key: dev1.Addr.String(), Kinds: 2}},
})
require.NoError(ts.T, err)
err = ts.TxSubscriptionAddProject(sub2Acc.Addr.String(), types.ProjectData{
Name: "test2", Enabled: true, ProjectKeys: []types.ProjectKey{{Key: dev2.Addr.String(), Kinds: 2}},
})
require.NoError(ts.T, err)
return dev1, dev2
}

return sigs.Account{}, sigs.Account{}
}

// deductParticipationFees calculates the validators and community participation
// fees and returns the providers reward after deducting them
func (ts *tester) DeductParticipationFees(reward math.Int) (updatedReward math.Int, valParticipation math.Int, communityParticipation math.Int) {
Expand Down
111 changes: 62 additions & 49 deletions x/rewards/keeper/iprpc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -539,65 +539,78 @@ func TestIprpcMinCost(t *testing.T) {
// 1. p1 provides service for both consumers, p2 provides service for c1 -> IPRPC reward should divide equally between p1 and p2
// 2. both providers provide service for c2 -> No IPRPC rewards should be given
func TestIprpcEligibleSubscriptions(t *testing.T) {
ts := newTester(t, true)
ts.setupForIprpcTests(true) // setup creates consumers and providers and funds IPRPC pool for mock2 spec
// do the test for the following consumers:
// 1. subscription owners
// 2. developers in the admin project
// 3. developers in a regular project that belongs to the subscriptions
const (
SUB_OWNERS = 0
DEVELOPERS_ADMIN_PROJECT = 1
DEVELOPERS_REGULAR_PROJECT = 2
)
modes := []int{SUB_OWNERS, DEVELOPERS_ADMIN_PROJECT, DEVELOPERS_REGULAR_PROJECT}

c1Acc, c1 := ts.GetAccount(common.CONSUMER, 0)
c2Acc, _ := ts.GetAccount(common.CONSUMER, 1)
_, p1 := ts.GetAccount(common.PROVIDER, 0)
_, p2 := ts.GetAccount(common.PROVIDER, 1)
for _, mode := range modes {
ts := newTester(t, true)
ts.setupForIprpcTests(true) // setup creates consumers and providers and funds IPRPC pool for mock2 spec

// p1 provides service for both consumers, p2 provides service for c1
msg := ts.SendRelay(p1, c1Acc, []string{mockSpec2}, 100)
_, err := ts.TxPairingRelayPayment(msg.Creator, msg.Relays...)
require.NoError(t, err)
// add developers to the admin project of the subscription and add an additional project with developers
c1Acc, c2Acc := ts.getConsumersForIprpcSubTest(mode)

msg = ts.SendRelay(p1, c2Acc, []string{mockSpec2}, 100)
_, err = ts.TxPairingRelayPayment(msg.Creator, msg.Relays...)
require.NoError(t, err)
// p1 provides service for both consumers, p2 provides service for c1
_, p1 := ts.GetAccount(common.PROVIDER, 0)
_, p2 := ts.GetAccount(common.PROVIDER, 1)
msg := ts.SendRelay(p1, c1Acc, []string{mockSpec2}, 100)
_, err := ts.TxPairingRelayPayment(msg.Creator, msg.Relays...)
require.NoError(t, err)

msg = ts.SendRelay(p2, c1Acc, []string{mockSpec2}, 100)
_, err = ts.TxPairingRelayPayment(msg.Creator, msg.Relays...)
require.NoError(t, err)
msg = ts.SendRelay(p1, c2Acc, []string{mockSpec2}, 100)
_, err = ts.TxPairingRelayPayment(msg.Creator, msg.Relays...)
require.NoError(t, err)

// check expected reward for each provider, it should be equal (the service for c1 was equal)
res1, err := ts.QueryRewardsIprpcProviderRewardEstimation(p1)
require.NoError(t, err)
res2, err := ts.QueryRewardsIprpcProviderRewardEstimation(p2)
require.NoError(t, err)
require.True(t, res1.SpecFunds[0].Fund.IsEqual(res2.SpecFunds[0].Fund))
require.True(t, iprpcFunds.Sub(minIprpcCost).QuoInt(sdk.NewInt(2)).IsEqual(res1.SpecFunds[0].Fund))
msg = ts.SendRelay(p2, c1Acc, []string{mockSpec2}, 100)
_, err = ts.TxPairingRelayPayment(msg.Creator, msg.Relays...)
require.NoError(t, err)

// fund the pool again (advance month to apply)
_, err = ts.TxRewardsFundIprpc(c1, mockSpec2, 1, sdk.NewCoins(minIprpcCost.AddAmount(sdk.NewInt(10))))
require.NoError(ts.T, err)
ts.AdvanceMonths(1).AdvanceEpoch()
// check expected reward for each provider, it should be equal (the service for c1 was equal)
res1, err := ts.QueryRewardsIprpcProviderRewardEstimation(p1)
require.NoError(t, err)
res2, err := ts.QueryRewardsIprpcProviderRewardEstimation(p2)
require.NoError(t, err)
require.True(t, res1.SpecFunds[0].Fund.IsEqual(res2.SpecFunds[0].Fund))
require.True(t, iprpcFunds.Sub(minIprpcCost).QuoInt(sdk.NewInt(2)).IsEqual(res1.SpecFunds[0].Fund))

// provide service only for c2
msg = ts.SendRelay(p1, c2Acc, []string{mockSpec2}, 100)
_, err = ts.TxPairingRelayPayment(msg.Creator, msg.Relays...)
require.NoError(t, err)
// fund the pool again (advance month to apply)
_, err = ts.TxRewardsFundIprpc(c1Acc.Addr.String(), mockSpec2, 1, sdk.NewCoins(minIprpcCost.AddAmount(sdk.NewInt(10))))
require.NoError(ts.T, err)
ts.AdvanceMonths(1).AdvanceEpoch()

msg = ts.SendRelay(p2, c2Acc, []string{mockSpec2}, 100)
_, err = ts.TxPairingRelayPayment(msg.Creator, msg.Relays...)
require.NoError(t, err)
// provide service only for c2
msg = ts.SendRelay(p1, c2Acc, []string{mockSpec2}, 100)
_, err = ts.TxPairingRelayPayment(msg.Creator, msg.Relays...)
require.NoError(t, err)

// check none of the providers should get rewards
res1, err = ts.QueryRewardsIprpcProviderRewardEstimation(p1)
require.NoError(t, err)
res2, err = ts.QueryRewardsIprpcProviderRewardEstimation(p2)
require.NoError(t, err)
require.Len(t, res1.SpecFunds, 0)
require.Len(t, res2.SpecFunds, 0)
msg = ts.SendRelay(p2, c2Acc, []string{mockSpec2}, 100)
_, err = ts.TxPairingRelayPayment(msg.Creator, msg.Relays...)
require.NoError(t, err)

// advance another month and see there are still no rewards
ts.AdvanceMonths(1).AdvanceEpoch()
res1, err = ts.QueryRewardsIprpcProviderRewardEstimation(p1)
require.NoError(t, err)
res2, err = ts.QueryRewardsIprpcProviderRewardEstimation(p2)
require.NoError(t, err)
require.Len(t, res1.SpecFunds, 0)
require.Len(t, res2.SpecFunds, 0)
// check none of the providers should get rewards
res1, err = ts.QueryRewardsIprpcProviderRewardEstimation(p1)
require.NoError(t, err)
res2, err = ts.QueryRewardsIprpcProviderRewardEstimation(p2)
require.NoError(t, err)
require.Len(t, res1.SpecFunds, 0)
require.Len(t, res2.SpecFunds, 0)

// advance another month and see there are still no rewards
ts.AdvanceMonths(1).AdvanceEpoch()
res1, err = ts.QueryRewardsIprpcProviderRewardEstimation(p1)
require.NoError(t, err)
res2, err = ts.QueryRewardsIprpcProviderRewardEstimation(p2)
require.NoError(t, err)
require.Len(t, res1.SpecFunds, 0)
require.Len(t, res2.SpecFunds, 0)
}
}

// TestMultipleIprpcSpec checks that rewards are distributed correctly when multiple specs are configured in the IPRPC pool
Expand Down

0 comments on commit 604af55

Please sign in to comment.