diff --git a/x/rewards/keeper/helpers_test.go b/x/rewards/keeper/helpers_test.go index 8ab23dd586..6ccd1b8b81 100644 --- a/x/rewards/keeper/helpers_test.go +++ b/x/rewards/keeper/helpers_test.go @@ -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" @@ -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) { diff --git a/x/rewards/keeper/iprpc_test.go b/x/rewards/keeper/iprpc_test.go index 19f7efceb7..fd94755a6b 100644 --- a/x/rewards/keeper/iprpc_test.go +++ b/x/rewards/keeper/iprpc_test.go @@ -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