From 43dd9582c1afdc85e206991f1d65ac93dc04c9d9 Mon Sep 17 00:00:00 2001 From: Troy Kessler Date: Wed, 24 Jul 2024 17:06:27 +0200 Subject: [PATCH 1/6] fix: added test case for points --- config.yml | 12 ++++++------ x/bundles/keeper/logic_bundles.go | 7 +++++-- .../keeper/msg_server_skip_uploader_role_test.go | 7 +++++++ 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/config.yml b/config.yml index c715770e..491fc596 100644 --- a/config.yml +++ b/config.yml @@ -141,25 +141,25 @@ genesis: max_voting_power_per_pool: "1" pool_count: "1" pool_list: - - config: "{\"network\":\"kyve-1\",\"rpc\":\"https://rpc.kyve.network\"}" + - config: "{\"network\":\"archway-1\",\"rpc\":\"http://ovh-protocol-4:21002\"}" current_compression_id: "1" current_index: "0" current_key: "" current_storage_provider_id: "3" current_summary: "" id: "0" - logo: "ar://WOiYR7qF7G_dp6eO0bFC7AorS7601qgek3X_IeAZook" + logo: "ar://hKb8dVx4E1NCUJ_BlhNOcyfQEta5r38SBXqsfPnAsWE" max_bundle_size: "100" min_delegation: "100000000" - name: "KYVE" + name: "Archway" inflation_share_weight: "1" disabled: false runtime: '@kyvejs/tendermint' - start_key: "1" + start_key: "5626500" total_bundles: "0" upload_interval: "60" protocol: - version: "1.1.6" + version: "1.2.0" binaries: "{\"kyve-linux-arm64\":\"https://github.com/KYVENetwork/kyvejs/releases/download/%40kyvejs%2Ftendermint%401.1.6/kyve-linux-arm64.zip\",\"kyve-linux-x64\":\"https://github.com/KYVENetwork/kyvejs/releases/download/%40kyvejs%2Ftendermint%401.1.6/kyve-linux-x64.zip\",\"kyve-macos-x64\":\"https://github.com/KYVENetwork/kyvejs/releases/download/%40kyvejs%2Ftendermint%401.1.6/kyve-macos-x64.zip\"}" last_upgrade: "0" upgrade_plan: @@ -224,4 +224,4 @@ validators: config: consensus: timeout_commit: "2s" - timeout_propose: "2s" \ No newline at end of file + timeout_propose: "2s" diff --git a/x/bundles/keeper/logic_bundles.go b/x/bundles/keeper/logic_bundles.go index a9b30c71..f1afd337 100644 --- a/x/bundles/keeper/logic_bundles.go +++ b/x/bundles/keeper/logic_bundles.go @@ -565,9 +565,12 @@ func (k Keeper) GetVoteDistribution(ctx sdk.Context, poolId uint64) (voteDistrib // tallyBundleProposal evaluates the votes of a bundle proposal and determines the outcome func (k Keeper) tallyBundleProposal(ctx sdk.Context, bundleProposal types.BundleProposal, poolId uint64) (types.TallyResult, error) { - // Increase points of stakers who did not vote at all + slash + remove if necessary. + // Increase points of stakers who did not vote at all + slash + remove if there is a bundle proposal. // The protocol requires everybody to stay always active. - k.handleNonVoters(ctx, poolId) + // TODO why does this not fix the unit test? + if bundleProposal.StorageId != "" { + k.handleNonVoters(ctx, poolId) + } // evaluate all votes and determine status based on the votes weighted with stake + delegation voteDistribution := k.GetVoteDistribution(ctx, poolId) diff --git a/x/bundles/keeper/msg_server_skip_uploader_role_test.go b/x/bundles/keeper/msg_server_skip_uploader_role_test.go index 7ab91d7c..6bb9fb94 100644 --- a/x/bundles/keeper/msg_server_skip_uploader_role_test.go +++ b/x/bundles/keeper/msg_server_skip_uploader_role_test.go @@ -252,6 +252,13 @@ var _ = Describe("msg_server_skip_uploader_role.go", Ordered, func() { // check that the bundle is not finalized _, found = s.App().BundlesKeeper.GetFinalizedBundle(s.Ctx(), 0, 0) Expect(found).To(BeFalse()) + + // check if no validator got a point + // TODO: make this work + valaccounts := s.App().StakersKeeper.GetAllValaccountsOfPool(s.Ctx(), 0) + for _, valaccount := range valaccounts { + Expect(valaccount.Points).To(BeZero()) + } }) It("Skip uploader role on data bundle with current round containing a valid bundle", func() { From 102df190a63e7de48cc9b8f2a661d0758869f7be Mon Sep 17 00:00:00 2001 From: rapha Date: Mon, 29 Jul 2024 17:04:11 +0200 Subject: [PATCH 2/6] test: extend msg_server_skip_uploader_role_test.go to check for validator points --- .../msg_server_skip_uploader_role_test.go | 38 +++++++++++++++++-- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/x/bundles/keeper/msg_server_skip_uploader_role_test.go b/x/bundles/keeper/msg_server_skip_uploader_role_test.go index 6bb9fb94..9f0ac3d0 100644 --- a/x/bundles/keeper/msg_server_skip_uploader_role_test.go +++ b/x/bundles/keeper/msg_server_skip_uploader_role_test.go @@ -9,6 +9,7 @@ import ( stakertypes "github.com/KYVENetwork/chain/x/stakers/types" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" + "slices" ) /* @@ -203,12 +204,22 @@ var _ = Describe("msg_server_skip_uploader_role.go", Ordered, func() { Expect(bundleProposal.VotersInvalid).To(BeEmpty()) Expect(bundleProposal.VotersAbstain).To(BeEmpty()) - // here the next uploader should be always be different after skipping + // here the next uploader should always be different after skipping Expect(bundleProposal.NextUploader).NotTo(Equal(i.STAKER_0)) // check that the bundle is not finalized _, found = s.App().BundlesKeeper.GetFinalizedBundle(s.Ctx(), 0, 0) Expect(found).To(BeFalse()) + + // check if no validator got a point for the second round + valaccounts := s.App().StakersKeeper.GetAllValaccountsOfPool(s.Ctx(), 0) + for _, valaccount := range valaccounts { + if valaccount.Staker == i.STAKER_0 { + Expect(valaccount.Points).To(BeZero()) + } else { + Expect(valaccount.Points).To(Equal(uint64(2))) // from the first and second round + } + } }) It("Skip uploader role on dropped bundle", func() { @@ -253,11 +264,14 @@ var _ = Describe("msg_server_skip_uploader_role.go", Ordered, func() { _, found = s.App().BundlesKeeper.GetFinalizedBundle(s.Ctx(), 0, 0) Expect(found).To(BeFalse()) - // check if no validator got a point - // TODO: make this work + // check if no validator got a point for the second round valaccounts := s.App().StakersKeeper.GetAllValaccountsOfPool(s.Ctx(), 0) for _, valaccount := range valaccounts { - Expect(valaccount.Points).To(BeZero()) + if valaccount.Staker == i.STAKER_0 { + Expect(valaccount.Points).To(BeZero()) + } else { + Expect(valaccount.Points).To(Equal(uint64(1))) // from the first round + } } }) @@ -307,6 +321,16 @@ var _ = Describe("msg_server_skip_uploader_role.go", Ordered, func() { Expect(finalizedBundle.PoolId).To(Equal(uint64(0))) Expect(finalizedBundle.Uploader).To(Equal(i.STAKER_0)) + + // check if no validator got a point for the second round + valaccounts := s.App().StakersKeeper.GetAllValaccountsOfPool(s.Ctx(), 0) + for _, valaccount := range valaccounts { + if slices.Contains([]string{i.STAKER_0, i.STAKER_1}, valaccount.Staker) { + Expect(valaccount.Points).To(BeZero()) + } else { + Expect(valaccount.Points).To(Equal(uint64(1))) // from the first round + } + } }) It("Skip uploader role on data bundle with current round containing an invalid bundle", func() { @@ -359,5 +383,11 @@ var _ = Describe("msg_server_skip_uploader_role.go", Ordered, func() { // check that the bundle is not finalized _, found = s.App().BundlesKeeper.GetFinalizedBundle(s.Ctx(), 0, 0) Expect(found).To(BeFalse()) + + // check that no validator got a point + valaccounts := s.App().StakersKeeper.GetAllValaccountsOfPool(s.Ctx(), 0) + for _, valaccount := range valaccounts { + Expect(valaccount.Points).To(BeZero()) + } }) }) From b963de9f57dc2de2cbfb1295ac8351430cf86b29 Mon Sep 17 00:00:00 2001 From: rapha Date: Tue, 30 Jul 2024 11:51:53 +0200 Subject: [PATCH 3/6] chore: remove todo --- x/bundles/keeper/logic_bundles.go | 1 - 1 file changed, 1 deletion(-) diff --git a/x/bundles/keeper/logic_bundles.go b/x/bundles/keeper/logic_bundles.go index f1afd337..764dd198 100644 --- a/x/bundles/keeper/logic_bundles.go +++ b/x/bundles/keeper/logic_bundles.go @@ -567,7 +567,6 @@ func (k Keeper) GetVoteDistribution(ctx sdk.Context, poolId uint64) (voteDistrib func (k Keeper) tallyBundleProposal(ctx sdk.Context, bundleProposal types.BundleProposal, poolId uint64) (types.TallyResult, error) { // Increase points of stakers who did not vote at all + slash + remove if there is a bundle proposal. // The protocol requires everybody to stay always active. - // TODO why does this not fix the unit test? if bundleProposal.StorageId != "" { k.handleNonVoters(ctx, poolId) } From dfd70e297c197402f00762b359053432d821b995 Mon Sep 17 00:00:00 2001 From: rapha Date: Wed, 31 Jul 2024 11:31:02 +0200 Subject: [PATCH 4/6] fix: return early for empty bundles in SkipUploaderRole --- x/bundles/keeper/logic_bundles.go | 6 ++---- .../keeper/msg_server_skip_uploader_role.go | 16 ++++++++++++++++ 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/x/bundles/keeper/logic_bundles.go b/x/bundles/keeper/logic_bundles.go index 764dd198..a9b30c71 100644 --- a/x/bundles/keeper/logic_bundles.go +++ b/x/bundles/keeper/logic_bundles.go @@ -565,11 +565,9 @@ func (k Keeper) GetVoteDistribution(ctx sdk.Context, poolId uint64) (voteDistrib // tallyBundleProposal evaluates the votes of a bundle proposal and determines the outcome func (k Keeper) tallyBundleProposal(ctx sdk.Context, bundleProposal types.BundleProposal, poolId uint64) (types.TallyResult, error) { - // Increase points of stakers who did not vote at all + slash + remove if there is a bundle proposal. + // Increase points of stakers who did not vote at all + slash + remove if necessary. // The protocol requires everybody to stay always active. - if bundleProposal.StorageId != "" { - k.handleNonVoters(ctx, poolId) - } + k.handleNonVoters(ctx, poolId) // evaluate all votes and determine status based on the votes weighted with stake + delegation voteDistribution := k.GetVoteDistribution(ctx, poolId) diff --git a/x/bundles/keeper/msg_server_skip_uploader_role.go b/x/bundles/keeper/msg_server_skip_uploader_role.go index bc5d41e1..66da8df7 100644 --- a/x/bundles/keeper/msg_server_skip_uploader_role.go +++ b/x/bundles/keeper/msg_server_skip_uploader_role.go @@ -20,6 +20,22 @@ func (k msgServer) SkipUploaderRole(goCtx context.Context, msg *types.MsgSkipUpl // reset points of uploader as node has proven to be active k.resetPoints(ctx, msg.PoolId, msg.Staker) + // If previous bundle was dropped just skip uploader role + // No previous round needs to be evaluated + if bundleProposal.StorageId == "" { + nextUploader := k.chooseNextUploader(ctx, msg.PoolId) + + // Register empty bundle with next uploader + bundleProposal = types.BundleProposal{ + PoolId: msg.PoolId, + NextUploader: nextUploader, + UpdatedAt: uint64(ctx.BlockTime().Unix()), + } + k.SetBundleProposal(ctx, bundleProposal) + + return &types.MsgSkipUploaderRoleResponse{}, nil + } + // Previous round contains a bundle which needs to be validated now result, err := k.tallyBundleProposal(ctx, bundleProposal, msg.PoolId) if err != nil { From 3c0260d7f5345093897298826fde76fca1c98617 Mon Sep 17 00:00:00 2001 From: rapha Date: Thu, 1 Aug 2024 09:04:29 +0200 Subject: [PATCH 5/6] test: add points check --- .../keeper/msg_server_skip_uploader_role_test.go | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/x/bundles/keeper/msg_server_skip_uploader_role_test.go b/x/bundles/keeper/msg_server_skip_uploader_role_test.go index 9f0ac3d0..ef706865 100644 --- a/x/bundles/keeper/msg_server_skip_uploader_role_test.go +++ b/x/bundles/keeper/msg_server_skip_uploader_role_test.go @@ -161,6 +161,16 @@ var _ = Describe("msg_server_skip_uploader_role.go", Ordered, func() { // check that the bundle is not finalized _, found = s.App().BundlesKeeper.GetFinalizedBundle(s.Ctx(), 0, 0) Expect(found).To(BeFalse()) + + // check that no validator got a point for the second round + valaccounts := s.App().StakersKeeper.GetAllValaccountsOfPool(s.Ctx(), 0) + for _, valaccount := range valaccounts { + if valaccount.Staker == i.STAKER_0 { + Expect(valaccount.Points).To(BeZero()) + } else { + Expect(valaccount.Points).To(Equal(uint64(1))) // from the first round + } + } }) It("Skip uploader on data bundle after uploader role has already been skipped", func() { @@ -211,7 +221,7 @@ var _ = Describe("msg_server_skip_uploader_role.go", Ordered, func() { _, found = s.App().BundlesKeeper.GetFinalizedBundle(s.Ctx(), 0, 0) Expect(found).To(BeFalse()) - // check if no validator got a point for the second round + // check that no validator got a point for the second round valaccounts := s.App().StakersKeeper.GetAllValaccountsOfPool(s.Ctx(), 0) for _, valaccount := range valaccounts { if valaccount.Staker == i.STAKER_0 { @@ -264,7 +274,7 @@ var _ = Describe("msg_server_skip_uploader_role.go", Ordered, func() { _, found = s.App().BundlesKeeper.GetFinalizedBundle(s.Ctx(), 0, 0) Expect(found).To(BeFalse()) - // check if no validator got a point for the second round + // check that no validator got a point for the second round valaccounts := s.App().StakersKeeper.GetAllValaccountsOfPool(s.Ctx(), 0) for _, valaccount := range valaccounts { if valaccount.Staker == i.STAKER_0 { From 5cdad0cbd14d2cff9d19c3d6ff6951efbceac689 Mon Sep 17 00:00:00 2001 From: Troy Kessler Date: Mon, 12 Aug 2024 16:59:23 +0200 Subject: [PATCH 6/6] chore: reset config.yml and cleaned skip uploader role tests --- config.yml | 12 ++-- .../msg_server_skip_uploader_role_test.go | 71 +++++++++++++------ 2 files changed, 57 insertions(+), 26 deletions(-) diff --git a/config.yml b/config.yml index 491fc596..c715770e 100644 --- a/config.yml +++ b/config.yml @@ -141,25 +141,25 @@ genesis: max_voting_power_per_pool: "1" pool_count: "1" pool_list: - - config: "{\"network\":\"archway-1\",\"rpc\":\"http://ovh-protocol-4:21002\"}" + - config: "{\"network\":\"kyve-1\",\"rpc\":\"https://rpc.kyve.network\"}" current_compression_id: "1" current_index: "0" current_key: "" current_storage_provider_id: "3" current_summary: "" id: "0" - logo: "ar://hKb8dVx4E1NCUJ_BlhNOcyfQEta5r38SBXqsfPnAsWE" + logo: "ar://WOiYR7qF7G_dp6eO0bFC7AorS7601qgek3X_IeAZook" max_bundle_size: "100" min_delegation: "100000000" - name: "Archway" + name: "KYVE" inflation_share_weight: "1" disabled: false runtime: '@kyvejs/tendermint' - start_key: "5626500" + start_key: "1" total_bundles: "0" upload_interval: "60" protocol: - version: "1.2.0" + version: "1.1.6" binaries: "{\"kyve-linux-arm64\":\"https://github.com/KYVENetwork/kyvejs/releases/download/%40kyvejs%2Ftendermint%401.1.6/kyve-linux-arm64.zip\",\"kyve-linux-x64\":\"https://github.com/KYVENetwork/kyvejs/releases/download/%40kyvejs%2Ftendermint%401.1.6/kyve-linux-x64.zip\",\"kyve-macos-x64\":\"https://github.com/KYVENetwork/kyvejs/releases/download/%40kyvejs%2Ftendermint%401.1.6/kyve-macos-x64.zip\"}" last_upgrade: "0" upgrade_plan: @@ -224,4 +224,4 @@ validators: config: consensus: timeout_commit: "2s" - timeout_propose: "2s" + timeout_propose: "2s" \ No newline at end of file diff --git a/x/bundles/keeper/msg_server_skip_uploader_role_test.go b/x/bundles/keeper/msg_server_skip_uploader_role_test.go index ef706865..5bc09f8c 100644 --- a/x/bundles/keeper/msg_server_skip_uploader_role_test.go +++ b/x/bundles/keeper/msg_server_skip_uploader_role_test.go @@ -9,7 +9,6 @@ import ( stakertypes "github.com/KYVENetwork/chain/x/stakers/types" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" - "slices" ) /* @@ -51,7 +50,7 @@ var _ = Describe("msg_server_skip_uploader_role.go", Ordered, func() { } s.RunTxPoolSuccess(msg) - //// create funders + // create funders s.RunTxFundersSuccess(&funderstypes.MsgCreateFunder{ Creator: i.ALICE, Moniker: "Alice", @@ -126,6 +125,22 @@ var _ = Describe("msg_server_skip_uploader_role.go", Ordered, func() { It("Skip uploader role on data bundle if staker is next uploader", func() { // ARRANGE + s.RunTxBundlesSuccess(&bundletypes.MsgVoteBundleProposal{ + Creator: i.VALADDRESS_1_A, + Staker: i.STAKER_1, + PoolId: 0, + StorageId: "y62A3tfbSNcNYDGoL-eXwzyV-Zc9Q0OVtDvR1biJmNI", + Vote: bundletypes.VOTE_TYPE_ABSTAIN, + }) + + s.RunTxBundlesSuccess(&bundletypes.MsgVoteBundleProposal{ + Creator: i.VALADDRESS_2_A, + Staker: i.STAKER_2, + PoolId: 0, + StorageId: "y62A3tfbSNcNYDGoL-eXwzyV-Zc9Q0OVtDvR1biJmNI", + Vote: bundletypes.VOTE_TYPE_ABSTAIN, + }) + s.Commit() s.WaitSeconds(60) @@ -153,7 +168,8 @@ var _ = Describe("msg_server_skip_uploader_role.go", Ordered, func() { Expect(bundleProposal.UpdatedAt).NotTo(BeZero()) Expect(bundleProposal.VotersValid).To(ContainElement(i.STAKER_0)) Expect(bundleProposal.VotersInvalid).To(BeEmpty()) - Expect(bundleProposal.VotersAbstain).To(BeEmpty()) + Expect(bundleProposal.VotersAbstain).To(ContainElement(i.STAKER_1)) + Expect(bundleProposal.VotersAbstain).To(ContainElement(i.STAKER_2)) // here the next uploader should be always be different after skipping Expect(bundleProposal.NextUploader).To(Equal(i.STAKER_0)) @@ -165,16 +181,28 @@ var _ = Describe("msg_server_skip_uploader_role.go", Ordered, func() { // check that no validator got a point for the second round valaccounts := s.App().StakersKeeper.GetAllValaccountsOfPool(s.Ctx(), 0) for _, valaccount := range valaccounts { - if valaccount.Staker == i.STAKER_0 { - Expect(valaccount.Points).To(BeZero()) - } else { - Expect(valaccount.Points).To(Equal(uint64(1))) // from the first round - } + Expect(valaccount.Points).To(BeZero()) } }) It("Skip uploader on data bundle after uploader role has already been skipped", func() { // ARRANGE + s.RunTxBundlesSuccess(&bundletypes.MsgVoteBundleProposal{ + Creator: i.VALADDRESS_1_A, + Staker: i.STAKER_1, + PoolId: 0, + StorageId: "y62A3tfbSNcNYDGoL-eXwzyV-Zc9Q0OVtDvR1biJmNI", + Vote: bundletypes.VOTE_TYPE_ABSTAIN, + }) + + s.RunTxBundlesSuccess(&bundletypes.MsgVoteBundleProposal{ + Creator: i.VALADDRESS_2_A, + Staker: i.STAKER_2, + PoolId: 0, + StorageId: "y62A3tfbSNcNYDGoL-eXwzyV-Zc9Q0OVtDvR1biJmNI", + Vote: bundletypes.VOTE_TYPE_ABSTAIN, + }) + s.Commit() s.WaitSeconds(60) @@ -212,7 +240,8 @@ var _ = Describe("msg_server_skip_uploader_role.go", Ordered, func() { Expect(bundleProposal.UpdatedAt).NotTo(BeZero()) Expect(bundleProposal.VotersValid).To(ContainElement(i.STAKER_0)) Expect(bundleProposal.VotersInvalid).To(BeEmpty()) - Expect(bundleProposal.VotersAbstain).To(BeEmpty()) + Expect(bundleProposal.VotersAbstain).To(ContainElement(i.STAKER_1)) + Expect(bundleProposal.VotersAbstain).To(ContainElement(i.STAKER_2)) // here the next uploader should always be different after skipping Expect(bundleProposal.NextUploader).NotTo(Equal(i.STAKER_0)) @@ -224,11 +253,7 @@ var _ = Describe("msg_server_skip_uploader_role.go", Ordered, func() { // check that no validator got a point for the second round valaccounts := s.App().StakersKeeper.GetAllValaccountsOfPool(s.Ctx(), 0) for _, valaccount := range valaccounts { - if valaccount.Staker == i.STAKER_0 { - Expect(valaccount.Points).To(BeZero()) - } else { - Expect(valaccount.Points).To(Equal(uint64(2))) // from the first and second round - } + Expect(valaccount.Points).To(BeZero()) } }) @@ -280,7 +305,8 @@ var _ = Describe("msg_server_skip_uploader_role.go", Ordered, func() { if valaccount.Staker == i.STAKER_0 { Expect(valaccount.Points).To(BeZero()) } else { - Expect(valaccount.Points).To(Equal(uint64(1))) // from the first round + // All others have one point because they did not vote at all + Expect(valaccount.Points).To(Equal(uint64(1))) } } }) @@ -295,6 +321,14 @@ var _ = Describe("msg_server_skip_uploader_role.go", Ordered, func() { Vote: bundletypes.VOTE_TYPE_VALID, }) + s.RunTxBundlesSuccess(&bundletypes.MsgVoteBundleProposal{ + Creator: i.VALADDRESS_2_A, + Staker: i.STAKER_2, + PoolId: 0, + StorageId: "y62A3tfbSNcNYDGoL-eXwzyV-Zc9Q0OVtDvR1biJmNI", + Vote: bundletypes.VOTE_TYPE_VALID, + }) + s.Commit() s.WaitSeconds(60) @@ -335,11 +369,7 @@ var _ = Describe("msg_server_skip_uploader_role.go", Ordered, func() { // check if no validator got a point for the second round valaccounts := s.App().StakersKeeper.GetAllValaccountsOfPool(s.Ctx(), 0) for _, valaccount := range valaccounts { - if slices.Contains([]string{i.STAKER_0, i.STAKER_1}, valaccount.Staker) { - Expect(valaccount.Points).To(BeZero()) - } else { - Expect(valaccount.Points).To(Equal(uint64(1))) // from the first round - } + Expect(valaccount.Points).To(BeZero()) } }) @@ -352,6 +382,7 @@ var _ = Describe("msg_server_skip_uploader_role.go", Ordered, func() { StorageId: "y62A3tfbSNcNYDGoL-eXwzyV-Zc9Q0OVtDvR1biJmNI", Vote: bundletypes.VOTE_TYPE_INVALID, }) + s.RunTxBundlesSuccess(&bundletypes.MsgVoteBundleProposal{ Creator: i.VALADDRESS_2_A, Staker: i.STAKER_2,