From 4eb43ed5b3f0b87bf2345dd68437dc6908912787 Mon Sep 17 00:00:00 2001 From: Maximilian Breithecker <72022235+mbreithecker@users.noreply.github.com> Date: Thu, 6 Jul 2023 15:08:12 +0200 Subject: [PATCH] feat: use weighted round-robin for uploader selection (#99) --- CHANGELOG.md | 1 + proto/kyve/bundles/v1beta1/bundles.proto | 16 + proto/kyve/bundles/v1beta1/genesis.proto | 2 + x/bundles/genesis.go | 6 + x/bundles/keeper/getters_round_robin.go | 41 ++ .../keeper_suite_dropped_bundles_test.go | 2 +- .../keeper_suite_zero_delegation_test.go | 2 +- x/bundles/keeper/logic_bundles.go | 101 +--- .../logic_end_block_handle_upload_timeout.go | 4 +- x/bundles/keeper/logic_round_robin.go | 259 +++++++++ x/bundles/keeper/logic_round_robin_test.go | 396 +++++++++++++ .../keeper/msg_server_skip_uploader_role.go | 22 +- .../msg_server_skip_uploader_role_test.go | 6 +- .../msg_server_submit_bundle_proposal.go | 22 +- x/bundles/spec/02_state.md | 32 ++ x/bundles/types/bundles.pb.go | 524 ++++++++++++++++-- x/bundles/types/genesis.pb.go | 106 +++- x/bundles/types/keys.go | 7 + x/query/keeper/grpc_query_can_propose_test.go | 32 +- 19 files changed, 1377 insertions(+), 204 deletions(-) create mode 100644 x/bundles/keeper/getters_round_robin.go create mode 100644 x/bundles/keeper/logic_round_robin.go create mode 100644 x/bundles/keeper/logic_round_robin_test.go diff --git a/CHANGELOG.md b/CHANGELOG.md index f3870ee0..9f8d379c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ ### Features - (ibc) [#30](https://github.com/KYVENetwork/chain/pull/30) Integrate [Packet Forward Middleware](https://github.com/strangelove-ventures/packet-forward-middleware). +- (`x/bundles`) [#99](https://github.com/KYVENetwork/chain/pull/99) Use weighted round-robin approach for uploader selection. ### Improvements diff --git a/proto/kyve/bundles/v1beta1/bundles.proto b/proto/kyve/bundles/v1beta1/bundles.proto index cefd8b25..e99dbf1d 100644 --- a/proto/kyve/bundles/v1beta1/bundles.proto +++ b/proto/kyve/bundles/v1beta1/bundles.proto @@ -100,3 +100,19 @@ message FinalizedAt { // timestamp ... uint64 timestamp = 2; } + +// RoundRobinSingleValidatorProgress ... +message RoundRobinSingleValidatorProgress { + // address ... + string address = 1; + // progress ... + int64 progress = 2; +} + +// RoundRobinProgress ... +message RoundRobinProgress { + // pool_id ... + uint64 pool_id = 1; + // progress_list ... + repeated RoundRobinSingleValidatorProgress progress_list = 2; +} diff --git a/proto/kyve/bundles/v1beta1/genesis.proto b/proto/kyve/bundles/v1beta1/genesis.proto index 620274cb..1c31792a 100644 --- a/proto/kyve/bundles/v1beta1/genesis.proto +++ b/proto/kyve/bundles/v1beta1/genesis.proto @@ -16,4 +16,6 @@ message GenesisState { repeated BundleProposal bundle_proposal_list = 2 [(gogoproto.nullable) = false]; // finalized_bundle_list ... repeated FinalizedBundle finalized_bundle_list = 3 [(gogoproto.nullable) = false]; + // round_robin_progress_list ... + repeated RoundRobinProgress round_robin_progress_list = 4 [(gogoproto.nullable) = false]; } diff --git a/x/bundles/genesis.go b/x/bundles/genesis.go index fbe90d98..bbc38d06 100644 --- a/x/bundles/genesis.go +++ b/x/bundles/genesis.go @@ -19,6 +19,10 @@ func InitGenesis(ctx sdk.Context, k keeper.Keeper, genState types.GenesisState) for _, entry := range genState.FinalizedBundleList { k.SetFinalizedBundle(ctx, entry) } + + for _, entry := range genState.RoundRobinProgressList { + k.SetRoundRobinProgress(ctx, entry) + } } // ExportGenesis returns the capability module's exported genesis. @@ -30,5 +34,7 @@ func ExportGenesis(ctx sdk.Context, k keeper.Keeper) *types.GenesisState { genesis.FinalizedBundleList = k.GetAllFinalizedBundles(ctx) + genesis.RoundRobinProgressList = k.GetAllRoundRobinProgress(ctx) + return genesis } diff --git a/x/bundles/keeper/getters_round_robin.go b/x/bundles/keeper/getters_round_robin.go new file mode 100644 index 00000000..a53e247b --- /dev/null +++ b/x/bundles/keeper/getters_round_robin.go @@ -0,0 +1,41 @@ +package keeper + +import ( + "github.com/KYVENetwork/chain/x/bundles/types" + "github.com/cosmos/cosmos-sdk/store/prefix" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// SetRoundRobinProgress stores the round-robin progress for a pool +func (k Keeper) SetRoundRobinProgress(ctx sdk.Context, roundRobinProgress types.RoundRobinProgress) { + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.RoundRobinProgressPrefix) + b := k.cdc.MustMarshal(&roundRobinProgress) + store.Set(types.RoundRobinProgressKey(roundRobinProgress.PoolId), b) +} + +// GetRoundRobinProgress returns the round-robin progress for a pool +func (k Keeper) GetRoundRobinProgress(ctx sdk.Context, poolId uint64) (val types.RoundRobinProgress, found bool) { + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.RoundRobinProgressPrefix) + + b := store.Get(types.RoundRobinProgressKey(poolId)) + if b == nil { + return val, false + } + + k.cdc.MustUnmarshal(b, &val) + return val, true +} + +// GetAllRoundRobinProgress returns the round-robin progress of all pools +func (k Keeper) GetAllRoundRobinProgress(ctx sdk.Context) (list []types.RoundRobinProgress) { + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.RoundRobinProgressPrefix) + iterator := sdk.KVStorePrefixIterator(store, []byte{}) + + for ; iterator.Valid(); iterator.Next() { + var val types.RoundRobinProgress + k.cdc.MustUnmarshal(iterator.Value(), &val) + list = append(list, val) + } + + return +} diff --git a/x/bundles/keeper/keeper_suite_dropped_bundles_test.go b/x/bundles/keeper/keeper_suite_dropped_bundles_test.go index 63c34752..f59064dd 100644 --- a/x/bundles/keeper/keeper_suite_dropped_bundles_test.go +++ b/x/bundles/keeper/keeper_suite_dropped_bundles_test.go @@ -138,7 +138,7 @@ var _ = Describe("dropped bundles", Ordered, func() { Expect(bundleProposal.PoolId).To(Equal(uint64(0))) Expect(bundleProposal.StorageId).To(BeEmpty()) Expect(bundleProposal.Uploader).To(BeEmpty()) - Expect(bundleProposal.NextUploader).To(Equal(i.STAKER_1)) + Expect(bundleProposal.NextUploader).To(Equal(i.STAKER_0)) Expect(bundleProposal.DataSize).To(BeZero()) Expect(bundleProposal.DataHash).To(BeEmpty()) Expect(bundleProposal.BundleSize).To(BeZero()) diff --git a/x/bundles/keeper/keeper_suite_zero_delegation_test.go b/x/bundles/keeper/keeper_suite_zero_delegation_test.go index e2a60931..d1b45f83 100644 --- a/x/bundles/keeper/keeper_suite_zero_delegation_test.go +++ b/x/bundles/keeper/keeper_suite_zero_delegation_test.go @@ -23,7 +23,7 @@ TEST CASES - zero delegation */ -var _ = Describe("valid bundles", Ordered, func() { +var _ = Describe("zero delegation", Ordered, func() { s := i.NewCleanChain() initialBalanceStaker0 := s.GetBalanceFromAddress(i.STAKER_0) diff --git a/x/bundles/keeper/logic_bundles.go b/x/bundles/keeper/logic_bundles.go index f513408f..7597dcfc 100644 --- a/x/bundles/keeper/logic_bundles.go +++ b/x/bundles/keeper/logic_bundles.go @@ -1,9 +1,6 @@ package keeper import ( - "math/rand" - "sort" - "cosmossdk.io/errors" delegationTypes "github.com/KYVENetwork/chain/x/delegation/types" @@ -369,12 +366,7 @@ func (k Keeper) finalizeCurrentBundleProposal(ctx sdk.Context, poolId uint64, vo // a required quorum on the validity of the data. When the proposal is dropped // the same next uploader as before can submit his proposal since it is not his // fault, that the last one did not reach any quorum. -func (k Keeper) dropCurrentBundleProposal( - ctx sdk.Context, - poolId uint64, - voteDistribution types.VoteDistribution, - nextUploader string, -) { +func (k Keeper) dropCurrentBundleProposal(ctx sdk.Context, poolId uint64, voteDistribution types.VoteDistribution, nextUploader string) { pool, _ := k.poolKeeper.GetPool(ctx, poolId) bundleProposal, _ := k.GetBundleProposal(ctx, poolId) @@ -412,82 +404,35 @@ func (k Keeper) calculateVotingPower(delegation uint64) (votingPower uint64) { return } -// RandomChoiceCandidate holds the voting power of a candidate for the -// next uploader selection -type RandomChoiceCandidate struct { - Account string - VotingPower uint64 -} - -// getWeightedRandomChoice is an internal function that returns a weighted random -// selection out of a list of candidates based on their voting power. -func (k Keeper) getWeightedRandomChoice(candidates []RandomChoiceCandidate, seed int64) string { - type WeightedRandomChoice struct { - Elements []string - Weights []uint64 - TotalWeight uint64 - } - - wrc := WeightedRandomChoice{} - - for _, candidate := range candidates { - i := sort.Search(len(wrc.Weights), func(i int) bool { return wrc.Weights[i] > candidate.VotingPower }) - wrc.Weights = append(wrc.Weights, 0) - wrc.Elements = append(wrc.Elements, "") - copy(wrc.Weights[i+1:], wrc.Weights[i:]) - copy(wrc.Elements[i+1:], wrc.Elements[i:]) - wrc.Weights[i] = candidate.VotingPower - wrc.Elements[i] = candidate.Account - wrc.TotalWeight += candidate.VotingPower - } - - if wrc.TotalWeight == 0 { - return "" - } - - value := rand.New(rand.NewSource(seed)).Uint64() % wrc.TotalWeight - - for key, weight := range wrc.Weights { - if weight > value { - return wrc.Elements[key] - } - - value -= weight - } - - return "" +// chooseNextUploader selects the next uploader based on a fixed set of stakers in a pool. +// It is guaranteed that someone is chosen deterministically if the round-robin set itself is not empty. +func (k Keeper) chooseNextUploader(ctx sdk.Context, poolId uint64, excluded ...string) (nextUploader string) { + vs := k.LoadRoundRobinValidatorSet(ctx, poolId) + nextUploader = vs.NextProposer(excluded...) + k.SaveRoundRobinValidatorSet(ctx, vs) + return } -// chooseNextUploaderFromSelectedStakers selects the next uploader based on a -// fixed set of stakers in a pool. It is guaranteed that someone is chosen -// deterministically -func (k Keeper) chooseNextUploaderFromSelectedStakers(ctx sdk.Context, poolId uint64, addresses []string) (nextUploader string) { - var _candidates []RandomChoiceCandidate +// chooseNextUploader selects the next uploader based on a fixed set of stakers in a pool. +// It is guaranteed that someone is chosen deterministically if the round-robin set itself is not empty. +func (k Keeper) chooseNextUploaderFromList(ctx sdk.Context, poolId uint64, included []string) (nextUploader string) { + vs := k.LoadRoundRobinValidatorSet(ctx, poolId) - if len(addresses) == 0 { - return "" + // Calculate set difference to obtain excluded + includedMap := make(map[string]bool) + for _, entry := range included { + includedMap[entry] = true } - - for _, s := range addresses { - if k.stakerKeeper.DoesValaccountExist(ctx, poolId, s) { - delegation := k.delegationKeeper.GetDelegationAmount(ctx, s) - - _candidates = append(_candidates, RandomChoiceCandidate{ - Account: s, - VotingPower: k.calculateVotingPower(delegation), - }) + excluded := make([]string, 0) + for _, entry := range vs.Validators { + if !includedMap[entry.Address] { + excluded = append(excluded, entry.Address) } } - return k.getWeightedRandomChoice(_candidates, ctx.BlockHeader().Height) -} - -// chooseNextUploaderFromAllStakers selects the next uploader based on all -// stakers in a pool. It is guaranteed that someone is chosen -// deterministically -func (k Keeper) chooseNextUploaderFromAllStakers(ctx sdk.Context, poolId uint64) (nextUploader string) { - stakers := k.stakerKeeper.GetAllStakerAddressesOfPool(ctx, poolId) - return k.chooseNextUploaderFromSelectedStakers(ctx, poolId, stakers) + nextUploader = vs.NextProposer(excluded...) + k.SaveRoundRobinValidatorSet(ctx, vs) + return } // GetVoteDistribution is an internal function evaluates the quorum status diff --git a/x/bundles/keeper/logic_end_block_handle_upload_timeout.go b/x/bundles/keeper/logic_end_block_handle_upload_timeout.go index ca5d1e3c..fe668431 100644 --- a/x/bundles/keeper/logic_end_block_handle_upload_timeout.go +++ b/x/bundles/keeper/logic_end_block_handle_upload_timeout.go @@ -54,7 +54,7 @@ func (k Keeper) HandleUploadTimeout(goCtx context.Context) { k.handleNonVoters(ctx, pool.Id) // Get next uploader from all pool stakers - nextUploader := k.chooseNextUploaderFromAllStakers(ctx, pool.Id) + nextUploader := k.chooseNextUploader(ctx, pool.Id) // If consensus wasn't reached, we drop the bundle and emit an event. k.dropCurrentBundleProposal(ctx, pool.Id, voteDistribution, nextUploader) @@ -76,7 +76,7 @@ func (k Keeper) HandleUploadTimeout(goCtx context.Context) { } // Update bundle proposal and choose next uploader - bundleProposal.NextUploader = k.chooseNextUploaderFromAllStakers(ctx, pool.Id) + bundleProposal.NextUploader = k.chooseNextUploader(ctx, pool.Id) bundleProposal.UpdatedAt = uint64(ctx.BlockTime().Unix()) k.SetBundleProposal(ctx, bundleProposal) diff --git a/x/bundles/keeper/logic_round_robin.go b/x/bundles/keeper/logic_round_robin.go new file mode 100644 index 00000000..fa2c4601 --- /dev/null +++ b/x/bundles/keeper/logic_round_robin.go @@ -0,0 +1,259 @@ +package keeper + +import ( + "sort" + + "github.com/KYVENetwork/chain/x/bundles/types" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +/* + +Weighted Round Robin Uploader Selection + +This file implements all necessary logic for a weighted round-robin algorithm. An example introduction can be found +[here](https://learnblockchain.cn/docs/tendermint/spec/reactors/consensus/proposer-selection.html). + +Our implementation additionally has the option of temporarily skipping participants for single rounds. +They do not advance in the round-robin progress and can not be selected as an uploader. +The frequencies of uploader selection with respect to the excluded ones can be described as follows. + +Let $R$ denote the number of total rounds and $r$ the index of the current round. +Let $N$ denote the number of total validators and $n$ the index of the n-th validator. + +The stake (+ delegation) of each validator for each round is given by + $s(n, r)$ + +Then the total stake for round r is given by + $S(r) = \sum_{i=1}^N s(i, r)$ + +Ignoring the existing progress, the likeliness of being selected in the next round is given by + $p(n, r) = s(n, r) / S(r)$ + +Using this value one can obtain the frequencies for uploader selection over all rounds, which is + $P(n) = 1/R * \sum_{r=1}^R p(n, r)$ + +Except for rounding errors $P(n)$ is independent from $R$ if $p(n, r)$ is constant. +If validator $i$ is excluded for round $k$, this is denoted by $s(i, k) = 0$. So in general $S(r)$ is +dependent on validator exclusions and validators set changes. + +*/ + +// RoundRobinValidatorPower contains the total delegation of a protocol validator. It is used as a cache +// because the calculation of the total delegation needs to access the KV-Store and therefore +// consumes gas everytime it is called. +// This value is only stored for the current round and only lives inside the memory. +type RoundRobinValidatorPower struct { + Address string + Power int64 +} + +// RoundRobinValidatorSet is the in memory-object for working with the round-robin state +// It can not be stored to the KV-Store as the Go map iterator is non-deterministic. +// To obtain a deterministic state of the current state call GetRoundRobinProgress(). +type RoundRobinValidatorSet struct { + PoolId uint64 + Validators []RoundRobinValidatorPower + Progress map[string]int64 +} + +// LoadRoundRobinValidatorSet initialises a validator set for the given pool id. +// If available it fetches the current round-robin state. Then it iterates all current pool +// validators and initialises the set accordingly. +// If a validator left the pool, the progress will be ignored. +// If new validators joined the pool, their progress will -1.125 * total_pool_delegation. +// The -1 is necessary to put them at the end of the queue (as the queue is centered around zero). +// The additional -0.125 are added as a penalty factor. +func (k Keeper) LoadRoundRobinValidatorSet(ctx sdk.Context, poolId uint64) RoundRobinValidatorSet { + vs := RoundRobinValidatorSet{} + vs.PoolId = poolId + vs.Progress = make(map[string]int64, 0) + totalDelegation := int64(0) + // Used for calculating the set difference of active validators and existing round-robin set + newValidators := make(map[string]bool, 0) + // Add all current pool validators to the round-robin set + for _, address := range k.stakerKeeper.GetAllStakerAddressesOfPool(ctx, poolId) { + delegation := k.delegationKeeper.GetDelegationAmount(ctx, address) + if delegation > 0 { + // If a validator has no delegation do not add to the round-robin set. Validator is basically non-existent. + vs.Validators = append(vs.Validators, RoundRobinValidatorPower{ + Address: address, + Power: int64(delegation), + }) + vs.Progress[address] = 0 + totalDelegation += int64(delegation) + newValidators[address] = true + } + } + + // Fetch stored progress + roundRobinProgress, _ := k.GetRoundRobinProgress(ctx, poolId) + for _, progress := range roundRobinProgress.ProgressList { + _, ok := vs.Progress[progress.Address] + // If the address is not found it means that the validator left the pool. + // Therefore, this entry can be ignored. + if ok { + vs.Progress[progress.Address] += progress.Progress + } + + // Progress already exists, validator can not be new. + newValidators[progress.Address] = false + } + + for newAddress, isNew := range newValidators { + if isNew { + // Put new validators at the end of the queue with an additional penalty factor. + vs.Progress[newAddress] = sdk.MustNewDecFromStr("-1.125").MulInt64(totalDelegation).TruncateInt64() + } + } + + vs.normalize() + return vs +} + +// SaveRoundRobinValidatorSet saves the current round-robin progress for the given poolId to the KV-Store +func (k Keeper) SaveRoundRobinValidatorSet(ctx sdk.Context, vs RoundRobinValidatorSet) { + roundRobinProgress := types.RoundRobinProgress{ + PoolId: vs.PoolId, + ProgressList: vs.GetRoundRobinProgress(), + } + k.SetRoundRobinProgress(ctx, roundRobinProgress) +} + +// GetRoundRobinProgress returns a deterministic (sorted) list of the current round-robin progress. +// Due to the fact that maps have no order in Go, we must introduce one by ourselves. +// This is done by sorting all entries by their addresses alphabetically. +func (vs *RoundRobinValidatorSet) GetRoundRobinProgress() []*types.RoundRobinSingleValidatorProgress { + // Convert map to list + result := make([]*types.RoundRobinSingleValidatorProgress, 0) + for address, progress := range vs.Progress { + singleProgress := types.RoundRobinSingleValidatorProgress{ + Address: address, + Progress: progress, + } + result = append(result, &singleProgress) + } + // Sort addresses alphabetically + sort.Slice( + result, func(i, j int) bool { + return result[i].Address < result[j].Address + }, + ) + return result +} + +// getTotalDelegation returns the total delegation power of the current set. +func (vs *RoundRobinValidatorSet) getTotalDelegation() (total int64) { + for _, vp := range vs.Validators { + total += vp.Power + } + return +} + +// getTotalDelegation returns the sum of all progresses of each validator. +// This value is supposed to always be zero. However, if new validators join or leave this +// value might no longer be 0. Have a look at normalize(). +func (vs *RoundRobinValidatorSet) getTotalProgress() (total int64) { + for _, vp := range vs.Progress { + total += vp + } + return +} + +// getMinMaxDifference returns the difference of progresses of the two validators with the +// most and least progress. +func (vs *RoundRobinValidatorSet) getMinMaxDifference() int64 { + if len(vs.Validators) == 0 { + return 0 + } + max := vs.Progress[vs.Validators[0].Address] + min := max + for _, p := range vs.Progress { + if p > max { + max = p + } + if p < min { + min = p + } + } + return max - min +} + +// size returns the number of participants in the current round-robin set. +func (vs *RoundRobinValidatorSet) size() int64 { + return int64(len(vs.Validators)) +} + +// normalize scales down the progress set to a maximum difference of 2 * total_delegation. +// This is necessary if validator join or leave the set, to adjust the existing progress. +// It then centers the entire progress around 0. +func (vs *RoundRobinValidatorSet) normalize() { + if vs.size() == 0 { + return + } + + diff := vs.getMinMaxDifference() + + totalProgress := vs.getTotalProgress() + threshold := 2 * vs.getTotalDelegation() + if diff > threshold { + + totalProgress = 0 + for _, val := range vs.Validators { + decProgress := sdk.NewDec(vs.Progress[val.Address]) + vs.Progress[val.Address] = decProgress.MulInt64(threshold).QuoInt64(diff).TruncateInt64() + totalProgress += vs.Progress[val.Address] + } + } + + // center priorities around zero and update + avg := sdk.NewDec(totalProgress).QuoInt64(vs.size()).TruncateInt64() + for key := range vs.Progress { + vs.Progress[key] -= avg + } +} + +// NextProposer advances the current round-robin state by one round, i.e. adjusting the progress +// of all (non-excluded) validators of the set. It then picks the top validator (if not excluded) +// and puts it to the end of the queue. This validator is the then returned as the "nextProposer". +// If the entire set is excluded then the algorithm proceeds as if nobody were excluded. +func (vs *RoundRobinValidatorSet) NextProposer(excludedAddresses ...string) string { + if vs.size() == 0 { + return "" + } + + vs.normalize() + + // If all addresses are excluded, then no address should be excluded + if len(excludedAddresses) == len(vs.Validators) { + excludedAddresses = make([]string, 0) + } + + mapExcludedAddresses := make(map[string]bool) + for _, excluded := range excludedAddresses { + mapExcludedAddresses[excluded] = true + } + + // update + excludedPower := int64(0) + for _, validator := range vs.Validators { + if !mapExcludedAddresses[validator.Address] { + vs.Progress[validator.Address] += validator.Power + } else { + excludedPower += validator.Power + } + } + + currentMaxValidator := vs.Validators[0].Address + for _, validator := range vs.Validators { + if !mapExcludedAddresses[validator.Address] { + if vs.Progress[validator.Address] > vs.Progress[currentMaxValidator] { + currentMaxValidator = validator.Address + } + } + } + + vs.Progress[currentMaxValidator] -= vs.getTotalDelegation() - excludedPower + + return currentMaxValidator +} diff --git a/x/bundles/keeper/logic_round_robin_test.go b/x/bundles/keeper/logic_round_robin_test.go new file mode 100644 index 00000000..ed2cefe0 --- /dev/null +++ b/x/bundles/keeper/logic_round_robin_test.go @@ -0,0 +1,396 @@ +package keeper_test + +import ( + "sort" + + i "github.com/KYVENetwork/chain/testutil/integration" + pooltypes "github.com/KYVENetwork/chain/x/pool/types" + stakertypes "github.com/KYVENetwork/chain/x/stakers/types" + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" +) + +/* + +TEST CASES - logic_bundles.go + +* Correctly load round-robin state +* Correctly save and load round-robin state +* Empty round-robin set +* Partially filled round-robin set (one staker with 0 delegation) +* Frequency analysis +* Frequency analysis (rounding) +* Frequency analysis (excluded) +* Exclude everybody +* Exclude all but one +* Leave set +* Join set + +*/ + +func joinDummy(s *i.KeeperTestSuite, index, kyveAmount uint64) { + s.RunTxStakersSuccess(&stakertypes.MsgCreateStaker{ + Creator: i.DUMMY[index], + Amount: kyveAmount * i.KYVE, + }) + + s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ + Creator: i.DUMMY[index], + PoolId: 0, + Valaddress: i.VALDUMMY[index], + Amount: 0, + }) +} + +func leaveDummy(s *i.KeeperTestSuite, index uint64) { + s.RunTxStakersSuccess(&stakertypes.MsgLeavePool{ + Creator: i.DUMMY[index], + PoolId: 0, + }) + s.CommitAfterSeconds(s.App().StakersKeeper.GetLeavePoolTime(s.Ctx())) + s.CommitAfterSeconds(1) +} + +var _ = Describe("logic_round_robin.go", Ordered, func() { + s := i.NewCleanChain() + + BeforeEach(func() { + // init new clean chain + s = i.NewCleanChain() + + // sort dummy accounts alphabetically + sort.Slice(i.DUMMY, func(k, j int) bool { + return i.DUMMY[k] < i.DUMMY[j] + }) + + s.App().PoolKeeper.AppendPool(s.Ctx(), pooltypes.Pool{ + Name: "PoolTest", + UploadInterval: 60, + OperatingCost: 2 * i.KYVE, + MinDelegation: 100 * i.KYVE, + MaxBundleSize: 100, + Protocol: &pooltypes.Protocol{ + Version: "0.0.0", + Binaries: "{}", + LastUpgrade: uint64(s.Ctx().BlockTime().Unix()), + }, + UpgradePlan: &pooltypes.UpgradePlan{ + Version: "1.0.0", + Binaries: "{}", + ScheduledAt: uint64(s.Ctx().BlockTime().Unix()), + Duration: 60, + }, + }) + }) + + AfterEach(func() { + s.PerformValidityChecks() + }) + + It("Correctly load round-robin state", func() { + // ARRANGE + joinDummy(s, 0, 100) + joinDummy(s, 1, 200) + joinDummy(s, 2, 300) + + // ACT + rrvs := s.App().BundlesKeeper.LoadRoundRobinValidatorSet(s.Ctx(), 0) + + // ASSERT + Expect(rrvs.Validators).To(HaveLen(3)) + Expect(rrvs.Validators[0].Address).To(Equal(i.DUMMY[0])) + Expect(rrvs.Validators[0].Power).To(Equal(100 * int64(i.KYVE))) + Expect(rrvs.Validators[1].Address).To(Equal(i.DUMMY[1])) + Expect(rrvs.Validators[1].Power).To(Equal(200 * int64(i.KYVE))) + Expect(rrvs.Validators[2].Address).To(Equal(i.DUMMY[2])) + Expect(rrvs.Validators[2].Power).To(Equal(300 * int64(i.KYVE))) + + Expect(rrvs.Progress).To(HaveLen(3)) + Expect(rrvs.Progress[i.DUMMY[0]]).To(Equal(int64(0))) + Expect(rrvs.Progress[i.DUMMY[1]]).To(Equal(int64(0))) + Expect(rrvs.Progress[i.DUMMY[2]]).To(Equal(int64(0))) + }) + + It("Correctly save and load round-robin state", func() { + // ARRANGE + joinDummy(s, 0, 100) + joinDummy(s, 1, 200) + joinDummy(s, 2, 300) + + // ACT + rrvs1 := s.App().BundlesKeeper.LoadRoundRobinValidatorSet(s.Ctx(), 0) + rrvs1.Progress[i.DUMMY[0]] = 1 + rrvs1.Progress[i.DUMMY[1]] = 2 + rrvs1.Progress[i.DUMMY[2]] = 3 + s.App().BundlesKeeper.SaveRoundRobinValidatorSet(s.Ctx(), rrvs1) + + state := rrvs1.GetRoundRobinProgress() + // loading round-robin performs normalising, which shifts values from 1,2,3 to -1,0,1 + rrvs := s.App().BundlesKeeper.LoadRoundRobinValidatorSet(s.Ctx(), 0) + + // ASSERT + Expect(state[0].Address).To(Equal(i.DUMMY[0])) + Expect(state[0].Progress).To(Equal(int64(1))) + Expect(state[1].Address).To(Equal(i.DUMMY[1])) + Expect(state[1].Progress).To(Equal(int64(2))) + Expect(state[2].Address).To(Equal(i.DUMMY[2])) + Expect(state[2].Progress).To(Equal(int64(3))) + + Expect(rrvs.Validators).To(HaveLen(3)) + Expect(rrvs.Validators[0].Address).To(Equal(i.DUMMY[0])) + Expect(rrvs.Validators[1].Address).To(Equal(i.DUMMY[1])) + Expect(rrvs.Validators[2].Address).To(Equal(i.DUMMY[2])) + + Expect(rrvs.Progress).To(HaveLen(3)) + Expect(rrvs.Progress[i.DUMMY[0]]).To(Equal(int64(-1))) + Expect(rrvs.Progress[i.DUMMY[1]]).To(Equal(int64(0))) + Expect(rrvs.Progress[i.DUMMY[2]]).To(Equal(int64(1))) + }) + + It("Empty round-robin set", func() { + // ARRANGE + joinDummy(s, 0, 0) + joinDummy(s, 1, 0) + joinDummy(s, 2, 0) + + // ACT + rrvs := s.App().BundlesKeeper.LoadRoundRobinValidatorSet(s.Ctx(), 0) + state := rrvs.GetRoundRobinProgress() + + nextProposer := rrvs.NextProposer() + + // ASSERT + Expect(rrvs.Validators).To(HaveLen(0)) + Expect(rrvs.Progress).To(HaveLen(0)) + + Expect(state).To(HaveLen(0)) + + Expect(nextProposer).To(BeEmpty()) + }) + + It("Partially filled round-robin set (one staker with 0 delegation)", func() { + // ARRANGE + joinDummy(s, 0, 0) + joinDummy(s, 1, 10) + joinDummy(s, 2, 5) + + // ACT + rrvs := s.App().BundlesKeeper.LoadRoundRobinValidatorSet(s.Ctx(), 0) + state := rrvs.GetRoundRobinProgress() + + nextProposer := rrvs.NextProposer() + + // ASSERT + Expect(rrvs.Validators).To(HaveLen(2)) + Expect(rrvs.Progress).To(HaveLen(2)) + + Expect(state).To(HaveLen(2)) + + Expect(nextProposer).To(Equal(i.DUMMY[1])) + }) + + It("Frequency analysis", func() { + // ARRANGE + joinDummy(s, 0, 2) + joinDummy(s, 1, 31) + joinDummy(s, 2, 67) + + // ACT + rrvs := s.App().BundlesKeeper.LoadRoundRobinValidatorSet(s.Ctx(), 0) + + frequency1 := make(map[string]int, 0) + for i := 0; i < 10; i++ { + frequency1[rrvs.NextProposer()] += 1 + } + + frequency2 := make(map[string]int, 0) + for i := 0; i < 100; i++ { + frequency2[rrvs.NextProposer()] += 1 + } + + frequency3 := make(map[string]int, 0) + for i := 0; i < 100000; i++ { + frequency3[rrvs.NextProposer()] += 1 + } + + // ASSERT + + Expect(frequency1[i.DUMMY[0]]).To(Equal(0)) + Expect(frequency1[i.DUMMY[1]]).To(Equal(3)) + Expect(frequency1[i.DUMMY[2]]).To(Equal(7)) + + Expect(frequency2[i.DUMMY[0]]).To(Equal(2)) + Expect(frequency2[i.DUMMY[1]]).To(Equal(31)) + Expect(frequency2[i.DUMMY[2]]).To(Equal(67)) + + Expect(frequency3[i.DUMMY[0]]).To(Equal(2000)) + Expect(frequency3[i.DUMMY[1]]).To(Equal(31000)) + Expect(frequency3[i.DUMMY[2]]).To(Equal(67000)) + }) + + It("Frequency analysis (rounding)", func() { + // ARRANGE + joinDummy(s, 0, 1) + joinDummy(s, 1, 1) + joinDummy(s, 2, 1) + + // ACT + rrvs := s.App().BundlesKeeper.LoadRoundRobinValidatorSet(s.Ctx(), 0) + + frequency1 := make(map[string]int, 0) + for i := 0; i < 10; i++ { + frequency1[rrvs.NextProposer()] += 1 + } + + frequency2 := make(map[string]int, 0) + for i := 0; i < 100; i++ { + frequency2[rrvs.NextProposer()] += 1 + } + + frequency3 := make(map[string]int, 0) + for i := 0; i < 100000; i++ { + frequency3[rrvs.NextProposer()] += 1 + } + + // ASSERT + + // First one is selected one more time, because of alphabetical order + Expect(frequency1[i.DUMMY[0]]).To(Equal(4)) + Expect(frequency1[i.DUMMY[1]]).To(Equal(3)) + Expect(frequency1[i.DUMMY[2]]).To(Equal(3)) + + Expect(frequency2[i.DUMMY[0]]).To(Equal(33)) + // The state is not reset between rounds, the first one already got selected one more time in + // the previous round, hence its progress is already reset. Therefore, the second one is slected + // one more than the others. + Expect(frequency2[i.DUMMY[1]]).To(Equal(34)) + Expect(frequency2[i.DUMMY[2]]).To(Equal(33)) + + Expect(frequency3[i.DUMMY[0]]).To(Equal(33333)) + Expect(frequency3[i.DUMMY[1]]).To(Equal(33333)) + // Same argument as above + Expect(frequency3[i.DUMMY[2]]).To(Equal(33334)) + }) + + It("Frequency analysis (excluded)", func() { + // ARRANGE + joinDummy(s, 0, 5) + joinDummy(s, 1, 10) + joinDummy(s, 2, 15) + // total stake = 30 + // Do 1000 rounds, in the first 500 exclude Dummy0, in the second 500 exclude Dummy1 + // Frequencies for all three validators: + // P(0) = 1/1000 * (0 + 500 * 5/(5+15)) = 0.125 + // P(1) = 1/1000 * (500 * 10/(10+15) + 0) = 0.2 + // P(2) = 1/1000 * (500 * 15/(10+15) + 500 * 15/(5+15)) = 0.675 + // P(1) + P(2) + P(3) = 1 + + // ACT + rrvs := s.App().BundlesKeeper.LoadRoundRobinValidatorSet(s.Ctx(), 0) + + frequency := make(map[string]int, 0) + for j := 0; j < 500; j++ { + frequency[rrvs.NextProposer(i.DUMMY[0])] += 1 + } + for j := 0; j < 500; j++ { + frequency[rrvs.NextProposer(i.DUMMY[1])] += 1 + } + + // ASSERT + Expect(frequency[i.DUMMY[0]]).To(Equal(125)) + Expect(frequency[i.DUMMY[1]]).To(Equal(200)) + Expect(frequency[i.DUMMY[2]]).To(Equal(675)) + }) + + It("Exclude everybody", func() { + // ARRANGE + joinDummy(s, 0, 5) + joinDummy(s, 1, 10) + joinDummy(s, 2, 15) + + // ACT + rrvs := s.App().BundlesKeeper.LoadRoundRobinValidatorSet(s.Ctx(), 0) + nextProposer := rrvs.NextProposer(i.DUMMY[0], i.DUMMY[1], i.DUMMY[2]) + + // ASSERT + Expect(nextProposer).To(Equal(i.DUMMY[2])) + Expect(rrvs.Progress[i.DUMMY[0]]).To(Equal(5 * int64(i.KYVE))) + Expect(rrvs.Progress[i.DUMMY[1]]).To(Equal(10 * int64(i.KYVE))) + Expect(rrvs.Progress[i.DUMMY[2]]).To(Equal(-15 * int64(i.KYVE))) + }) + + It("Exclude all but one", func() { + // ARRANGE + joinDummy(s, 0, 5) + joinDummy(s, 1, 10) + joinDummy(s, 2, 15) + + // ACT + rrvs := s.App().BundlesKeeper.LoadRoundRobinValidatorSet(s.Ctx(), 0) + nextProposer := rrvs.NextProposer(i.DUMMY[1], i.DUMMY[2]) + + // ASSERT + Expect(nextProposer).To(Equal(i.DUMMY[0])) + Expect(rrvs.Progress[i.DUMMY[0]]).To(Equal(0 * int64(i.KYVE))) + Expect(rrvs.Progress[i.DUMMY[1]]).To(Equal(0 * int64(i.KYVE))) + Expect(rrvs.Progress[i.DUMMY[2]]).To(Equal(0 * int64(i.KYVE))) + }) + + It("Leave set", func() { + // ARRANGE + joinDummy(s, 0, 1000) + joinDummy(s, 1, 1000) + joinDummy(s, 2, 1000) + joinDummy(s, 3, 1000) + joinDummy(s, 4, 1000) + + rrvs := s.App().BundlesKeeper.LoadRoundRobinValidatorSet(s.Ctx(), 0) + nextProposer := rrvs.NextProposer() + s.App().BundlesKeeper.SaveRoundRobinValidatorSet(s.Ctx(), rrvs) + Expect(nextProposer).To(Equal(i.DUMMY[0])) + leaveDummy(s, 2) + leaveDummy(s, 3) + leaveDummy(s, 4) + + // ACT, ASSERT + rrvs = s.App().BundlesKeeper.LoadRoundRobinValidatorSet(s.Ctx(), 0) + Expect(rrvs.Progress[i.DUMMY[0]]).To(Equal(-2000 * int64(i.KYVE))) + Expect(rrvs.Progress[i.DUMMY[1]]).To(Equal(2000 * int64(i.KYVE))) + + nextProposer = rrvs.NextProposer() + Expect(nextProposer).To(Equal(i.DUMMY[1])) + Expect(rrvs.Progress[i.DUMMY[0]]).To(Equal(-1000 * int64(i.KYVE))) + Expect(rrvs.Progress[i.DUMMY[1]]).To(Equal(1000 * int64(i.KYVE))) + + nextProposer = rrvs.NextProposer() + Expect(nextProposer).To(Equal(i.DUMMY[1])) + Expect(rrvs.Progress[i.DUMMY[0]]).To(Equal(0 * int64(i.KYVE))) + Expect(rrvs.Progress[i.DUMMY[1]]).To(Equal(0 * int64(i.KYVE))) + }) + + It("Join set", func() { + // ARRANGE + joinDummy(s, 0, 100) + joinDummy(s, 1, 200) + joinDummy(s, 2, 300) + + rrvs := s.App().BundlesKeeper.LoadRoundRobinValidatorSet(s.Ctx(), 0) + nextProposer := rrvs.NextProposer() + Expect(nextProposer).To(Equal(i.DUMMY[2])) + Expect(rrvs.Progress[i.DUMMY[0]]).To(Equal(100 * int64(i.KYVE))) + Expect(rrvs.Progress[i.DUMMY[1]]).To(Equal(200 * int64(i.KYVE))) + Expect(rrvs.Progress[i.DUMMY[2]]).To(Equal(-300 * int64(i.KYVE))) + s.App().BundlesKeeper.SaveRoundRobinValidatorSet(s.Ctx(), rrvs) + + // ACT + joinDummy(s, 3, 400) + rrvs = s.App().BundlesKeeper.LoadRoundRobinValidatorSet(s.Ctx(), 0) + shift := int64(1125_000_000_000 / 4) + + // Assert + Expect(rrvs.Progress[i.DUMMY[0]]).To(Equal(100*int64(i.KYVE) + shift)) + Expect(rrvs.Progress[i.DUMMY[1]]).To(Equal(200*int64(i.KYVE) + shift)) + Expect(rrvs.Progress[i.DUMMY[2]]).To(Equal(-300*int64(i.KYVE) + shift)) + Expect(rrvs.Progress[i.DUMMY[3]]).To(Equal(-1125*int64(i.KYVE) + shift)) + }) +}) diff --git a/x/bundles/keeper/msg_server_skip_uploader_role.go b/x/bundles/keeper/msg_server_skip_uploader_role.go index de9a0db4..34bff46f 100644 --- a/x/bundles/keeper/msg_server_skip_uploader_role.go +++ b/x/bundles/keeper/msg_server_skip_uploader_role.go @@ -8,9 +8,7 @@ import ( ) // SkipUploaderRole handles the logic of an SDK message that allows protocol nodes to skip an upload. -func (k msgServer) SkipUploaderRole( - goCtx context.Context, msg *types.MsgSkipUploaderRole, -) (*types.MsgSkipUploaderRoleResponse, error) { +func (k msgServer) SkipUploaderRole(goCtx context.Context, msg *types.MsgSkipUploaderRole) (*types.MsgSkipUploaderRoleResponse, error) { ctx := sdk.UnwrapSDKContext(goCtx) if err := k.AssertCanPropose(ctx, msg.PoolId, msg.Staker, msg.Creator, msg.FromIndex); err != nil { @@ -23,22 +21,8 @@ func (k msgServer) SkipUploaderRole( // reset points of uploader as node has proven to be active k.resetPoints(ctx, msg.PoolId, msg.Staker) - // Get next uploader from stakers voted - stakers := make([]string, 0) - nextUploader := "" - - // exclude the staker who skips the uploader role - for _, staker := range k.stakerKeeper.GetAllStakerAddressesOfPool(ctx, msg.PoolId) { - if staker != msg.Staker { - stakers = append(stakers, staker) - } - } - - if len(stakers) > 0 { - nextUploader = k.chooseNextUploaderFromSelectedStakers(ctx, msg.PoolId, stakers) - } else { - nextUploader = k.chooseNextUploaderFromAllStakers(ctx, msg.PoolId) - } + // Get next uploader, except the one who skipped + nextUploader := k.chooseNextUploader(ctx, msg.PoolId, msg.Staker) bundleProposal.NextUploader = nextUploader bundleProposal.UpdatedAt = uint64(ctx.BlockTime().Unix()) 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 d86e01c2..d06df361 100644 --- a/x/bundles/keeper/msg_server_skip_uploader_role_test.go +++ b/x/bundles/keeper/msg_server_skip_uploader_role_test.go @@ -239,8 +239,8 @@ var _ = Describe("msg_server_skip_uploader_role.go", Ordered, func() { // ACT s.RunTxBundlesSuccess(&bundletypes.MsgSkipUploaderRole{ - Creator: i.VALADDRESS_1, - Staker: i.STAKER_1, + Creator: i.VALADDRESS_0, + Staker: i.STAKER_0, PoolId: 0, FromIndex: 0, }) @@ -264,6 +264,6 @@ var _ = Describe("msg_server_skip_uploader_role.go", Ordered, func() { Expect(bundleProposal.VotersAbstain).To(BeEmpty()) // here the next uploader should be always be different after skipping - Expect(bundleProposal.NextUploader).To(Equal(i.STAKER_0)) + Expect(bundleProposal.NextUploader).To(Equal(i.STAKER_1)) }) }) diff --git a/x/bundles/keeper/msg_server_submit_bundle_proposal.go b/x/bundles/keeper/msg_server_submit_bundle_proposal.go index 5307fa36..1f64fc5a 100644 --- a/x/bundles/keeper/msg_server_submit_bundle_proposal.go +++ b/x/bundles/keeper/msg_server_submit_bundle_proposal.go @@ -16,9 +16,7 @@ import ( ) // SubmitBundleProposal handles the logic of an SDK message that allows protocol nodes to submit a new bundle proposal. -func (k msgServer) SubmitBundleProposal( - goCtx context.Context, msg *types.MsgSubmitBundleProposal, -) (*types.MsgSubmitBundleProposalResponse, error) { +func (k msgServer) SubmitBundleProposal(goCtx context.Context, msg *types.MsgSubmitBundleProposal) (*types.MsgSubmitBundleProposalResponse, error) { ctx := sdk.UnwrapSDKContext(goCtx) if err := k.AssertCanPropose(ctx, msg.PoolId, msg.Staker, msg.Creator, msg.FromIndex); err != nil { @@ -38,7 +36,7 @@ func (k msgServer) SubmitBundleProposal( // If previous bundle was dropped just register the new bundle. // No previous round needs to be evaluated if bundleProposal.StorageId == "" { - nextUploader := k.chooseNextUploaderFromAllStakers(ctx, msg.PoolId) + nextUploader := k.chooseNextUploader(ctx, msg.PoolId) k.registerBundleProposalFromUploader(ctx, msg, nextUploader) @@ -115,20 +113,8 @@ func (k msgServer) SubmitBundleProposal( // Determine next uploader and register next bundle - // Get next uploader from stakers who voted `valid` and are still active - activeVoters := make([]string, 0) - nextUploader := "" - for _, voter := range bundleProposal.VotersValid { - if k.stakerKeeper.DoesValaccountExist(ctx, msg.PoolId, voter) { - activeVoters = append(activeVoters, voter) - } - } - - if len(activeVoters) > 0 { - nextUploader = k.chooseNextUploaderFromSelectedStakers(ctx, msg.PoolId, activeVoters) - } else { - nextUploader = k.chooseNextUploaderFromAllStakers(ctx, msg.PoolId) - } + // Get next uploader from stakers who voted `valid` + nextUploader := k.chooseNextUploaderFromList(ctx, msg.PoolId, bundleProposal.VotersValid) k.finalizeCurrentBundleProposal(ctx, pool.Id, voteDistribution, bundleReward, nextUploader) diff --git a/x/bundles/spec/02_state.md b/x/bundles/spec/02_state.md index 2bebce16..8e876188 100644 --- a/x/bundles/spec/02_state.md +++ b/x/bundles/spec/02_state.md @@ -65,3 +65,35 @@ type FinalizedBundle struct { CompressionId uint32 } ``` + + +## Round-Robin +For correctly determining the next uploader the current round-robin +progress needs to be saved in the KV-Store. Every pool keeps track of its +own round-robin state. + +### RoundRobinSingleValidatorProgress +This struct is not stored directly in the KV-Store but used by the +RoundRobinProgress struct. + +```go +type RoundRobinSingleValidatorProgress struct { + // address of the validator + Address string + // progress within the current round-robin set + Progress int64 +} +``` + +### RoundRobinProgress +RoundRobinProgress stores the current state of the round-robin selection for a +given pool. + +- RoundRobinProgress `0x03 | PoolId -> ProtocolBuffer(roundRobinProgress)` + +```go +message RoundRobinProgress { + PoolId uint64 + ProgressList []RoundRobinSingleValidatorProgress +} +``` \ No newline at end of file diff --git a/x/bundles/types/bundles.pb.go b/x/bundles/types/bundles.pb.go index 9343757f..a957bea1 100644 --- a/x/bundles/types/bundles.pb.go +++ b/x/bundles/types/bundles.pb.go @@ -460,11 +460,123 @@ func (m *FinalizedAt) GetTimestamp() uint64 { return 0 } +// RoundRobinSingleValidatorProgress ... +type RoundRobinSingleValidatorProgress struct { + // address ... + Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` + // progress ... + Progress int64 `protobuf:"varint,2,opt,name=progress,proto3" json:"progress,omitempty"` +} + +func (m *RoundRobinSingleValidatorProgress) Reset() { *m = RoundRobinSingleValidatorProgress{} } +func (m *RoundRobinSingleValidatorProgress) String() string { return proto.CompactTextString(m) } +func (*RoundRobinSingleValidatorProgress) ProtoMessage() {} +func (*RoundRobinSingleValidatorProgress) Descriptor() ([]byte, []int) { + return fileDescriptor_889cf76d77a4de2b, []int{3} +} +func (m *RoundRobinSingleValidatorProgress) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *RoundRobinSingleValidatorProgress) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_RoundRobinSingleValidatorProgress.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *RoundRobinSingleValidatorProgress) XXX_Merge(src proto.Message) { + xxx_messageInfo_RoundRobinSingleValidatorProgress.Merge(m, src) +} +func (m *RoundRobinSingleValidatorProgress) XXX_Size() int { + return m.Size() +} +func (m *RoundRobinSingleValidatorProgress) XXX_DiscardUnknown() { + xxx_messageInfo_RoundRobinSingleValidatorProgress.DiscardUnknown(m) +} + +var xxx_messageInfo_RoundRobinSingleValidatorProgress proto.InternalMessageInfo + +func (m *RoundRobinSingleValidatorProgress) GetAddress() string { + if m != nil { + return m.Address + } + return "" +} + +func (m *RoundRobinSingleValidatorProgress) GetProgress() int64 { + if m != nil { + return m.Progress + } + return 0 +} + +// RoundRobinProgress ... +type RoundRobinProgress struct { + // pool_id ... + PoolId uint64 `protobuf:"varint,1,opt,name=pool_id,json=poolId,proto3" json:"pool_id,omitempty"` + // progress_list ... + ProgressList []*RoundRobinSingleValidatorProgress `protobuf:"bytes,2,rep,name=progress_list,json=progressList,proto3" json:"progress_list,omitempty"` +} + +func (m *RoundRobinProgress) Reset() { *m = RoundRobinProgress{} } +func (m *RoundRobinProgress) String() string { return proto.CompactTextString(m) } +func (*RoundRobinProgress) ProtoMessage() {} +func (*RoundRobinProgress) Descriptor() ([]byte, []int) { + return fileDescriptor_889cf76d77a4de2b, []int{4} +} +func (m *RoundRobinProgress) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *RoundRobinProgress) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_RoundRobinProgress.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *RoundRobinProgress) XXX_Merge(src proto.Message) { + xxx_messageInfo_RoundRobinProgress.Merge(m, src) +} +func (m *RoundRobinProgress) XXX_Size() int { + return m.Size() +} +func (m *RoundRobinProgress) XXX_DiscardUnknown() { + xxx_messageInfo_RoundRobinProgress.DiscardUnknown(m) +} + +var xxx_messageInfo_RoundRobinProgress proto.InternalMessageInfo + +func (m *RoundRobinProgress) GetPoolId() uint64 { + if m != nil { + return m.PoolId + } + return 0 +} + +func (m *RoundRobinProgress) GetProgressList() []*RoundRobinSingleValidatorProgress { + if m != nil { + return m.ProgressList + } + return nil +} + func init() { proto.RegisterEnum("kyve.bundles.v1beta1.BundleStatus", BundleStatus_name, BundleStatus_value) proto.RegisterType((*BundleProposal)(nil), "kyve.bundles.v1beta1.BundleProposal") proto.RegisterType((*FinalizedBundle)(nil), "kyve.bundles.v1beta1.FinalizedBundle") proto.RegisterType((*FinalizedAt)(nil), "kyve.bundles.v1beta1.FinalizedAt") + proto.RegisterType((*RoundRobinSingleValidatorProgress)(nil), "kyve.bundles.v1beta1.RoundRobinSingleValidatorProgress") + proto.RegisterType((*RoundRobinProgress)(nil), "kyve.bundles.v1beta1.RoundRobinProgress") } func init() { @@ -472,52 +584,57 @@ func init() { } var fileDescriptor_889cf76d77a4de2b = []byte{ - // 710 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x94, 0xcd, 0x6e, 0x1a, 0x49, - 0x14, 0x85, 0x69, 0xc0, 0x40, 0x5f, 0x7e, 0xcc, 0x94, 0xff, 0xda, 0x78, 0xcc, 0x60, 0x8f, 0x46, - 0x42, 0xa3, 0x11, 0xc8, 0x33, 0x4f, 0x00, 0x06, 0x34, 0x2d, 0x7b, 0xb0, 0x07, 0x8c, 0xa5, 0x64, - 0xd3, 0x2a, 0xdc, 0x65, 0x28, 0x19, 0xba, 0x5a, 0xdd, 0x05, 0x31, 0x7e, 0x82, 0x2c, 0xf3, 0x0e, - 0xc9, 0x63, 0x64, 0x95, 0x55, 0x96, 0x5e, 0x66, 0x19, 0xd9, 0x2f, 0x12, 0x55, 0x55, 0x37, 0x06, - 0xdb, 0x89, 0xbc, 0xc9, 0x8e, 0xfb, 0x9d, 0x53, 0x54, 0xdd, 0xba, 0xa7, 0x0b, 0xf6, 0xaf, 0x66, - 0x53, 0x52, 0xed, 0x4f, 0x1c, 0x7b, 0x44, 0xfc, 0xea, 0xf4, 0xa0, 0x4f, 0x38, 0x3e, 0x08, 0xeb, - 0x8a, 0xeb, 0x31, 0xce, 0xd0, 0xba, 0xf0, 0x54, 0x42, 0x16, 0x78, 0x0a, 0xeb, 0x03, 0x36, 0x60, - 0xd2, 0x50, 0x15, 0xbf, 0x94, 0x77, 0xff, 0x43, 0x1c, 0x72, 0x75, 0xe9, 0x3c, 0xf5, 0x98, 0xcb, - 0x7c, 0x3c, 0x42, 0x5b, 0x90, 0x74, 0x19, 0x1b, 0x59, 0xd4, 0x36, 0xb4, 0x92, 0x56, 0x8e, 0x77, - 0x12, 0xa2, 0x34, 0x6d, 0xb4, 0x0b, 0xe0, 0x73, 0xe6, 0xe1, 0x01, 0x11, 0x5a, 0xb4, 0xa4, 0x95, - 0xf5, 0x8e, 0x1e, 0x10, 0xd3, 0x46, 0x05, 0x48, 0x4d, 0xdc, 0x11, 0xc3, 0x36, 0xf1, 0x8c, 0x98, - 0x14, 0xe7, 0x35, 0xfa, 0x1d, 0xb2, 0x0e, 0xb9, 0xe6, 0xd6, 0xdc, 0x10, 0x97, 0x86, 0x8c, 0x80, - 0xbd, 0xd0, 0xb4, 0x03, 0xba, 0x8d, 0x39, 0xb6, 0x7c, 0x7a, 0x43, 0x8c, 0x15, 0xb9, 0x75, 0x4a, - 0x80, 0x2e, 0xbd, 0x21, 0xe8, 0x37, 0x48, 0xab, 0x8e, 0x94, 0x9c, 0x90, 0x32, 0x28, 0x24, 0x0d, - 0x1b, 0x90, 0xe0, 0xcc, 0xba, 0x22, 0x33, 0x23, 0x29, 0xff, 0x7b, 0x85, 0xb3, 0x23, 0x32, 0x43, - 0x7f, 0x40, 0x2e, 0x5c, 0x37, 0x19, 0x8f, 0xb1, 0x37, 0x33, 0x52, 0x52, 0xce, 0x06, 0x4b, 0x15, - 0x9c, 0xef, 0x3d, 0xc4, 0xfe, 0xd0, 0xd0, 0xd5, 0xe9, 0x05, 0xf8, 0x17, 0xfb, 0x43, 0xd1, 0xf8, - 0xc4, 0xb5, 0x31, 0x27, 0xb6, 0x85, 0xb9, 0x01, 0x72, 0x6b, 0x3d, 0x20, 0x35, 0x8e, 0xf6, 0x20, - 0x33, 0x65, 0x9c, 0x78, 0xbe, 0x35, 0xc5, 0x23, 0x6a, 0x1b, 0xe9, 0x52, 0xac, 0xac, 0x77, 0xd2, - 0x8a, 0x9d, 0x0b, 0x24, 0x4e, 0x11, 0x58, 0xa8, 0xa3, 0x4c, 0x19, 0x69, 0xca, 0x2a, 0x6a, 0x2a, - 0xb8, 0x60, 0xc3, 0x7d, 0x9f, 0x63, 0xea, 0x18, 0xd9, 0x45, 0x5b, 0x4d, 0x41, 0xb4, 0x0d, 0xa9, - 0x4b, 0x8f, 0x8d, 0x65, 0xb3, 0x39, 0x79, 0xd6, 0xa4, 0xa8, 0x45, 0xbb, 0x15, 0x58, 0x0b, 0x67, - 0xe4, 0x7a, 0x6c, 0x4a, 0x6d, 0xe2, 0x89, 0x61, 0xad, 0x96, 0xb4, 0x72, 0xb6, 0xf3, 0x4b, 0x20, - 0x9d, 0x06, 0x8a, 0x29, 0x77, 0xbc, 0x60, 0x63, 0xd7, 0x23, 0xbe, 0x4f, 0x99, 0x23, 0xac, 0x79, - 0x69, 0xcd, 0x2e, 0x50, 0xd3, 0xde, 0xff, 0x14, 0x83, 0xd5, 0x16, 0x75, 0xf0, 0x88, 0xde, 0x10, - 0x5b, 0xe5, 0xe5, 0xfb, 0x39, 0xc9, 0x41, 0x34, 0xc8, 0x47, 0xbc, 0x13, 0xa5, 0x8f, 0x73, 0x13, - 0xfb, 0x51, 0x6e, 0xe2, 0x8f, 0x72, 0xb3, 0x0b, 0x20, 0x3b, 0xa5, 0x8e, 0x4d, 0xae, 0x83, 0x4c, - 0xe8, 0x82, 0x98, 0x02, 0x88, 0x8b, 0xe0, 0x2c, 0x10, 0x55, 0x22, 0x92, 0x9c, 0x29, 0xe9, 0x27, - 0xc6, 0xa1, 0x01, 0x99, 0xcb, 0xf0, 0x2e, 0xc2, 0x40, 0xa4, 0xff, 0xde, 0xab, 0x3c, 0xf7, 0xd9, - 0x55, 0xe6, 0xb7, 0x56, 0xe3, 0x9d, 0xf4, 0xe5, 0x43, 0xb1, 0x34, 0xc4, 0xf4, 0x8b, 0x86, 0x98, - 0x79, 0xf9, 0x10, 0xb3, 0xcf, 0x0d, 0xf1, 0x10, 0xd2, 0x0b, 0xa7, 0x41, 0x9b, 0x90, 0x18, 0x12, - 0x3a, 0x18, 0xf2, 0x70, 0x7c, 0xaa, 0x42, 0xbf, 0x82, 0xce, 0xe9, 0x98, 0xf8, 0x1c, 0x8f, 0xdd, - 0x60, 0x8a, 0x0f, 0xe0, 0xcf, 0x8f, 0x1a, 0x64, 0x54, 0x00, 0xba, 0x1c, 0xf3, 0x89, 0x8f, 0x76, - 0x61, 0xbb, 0xde, 0x6b, 0x37, 0x8e, 0x9b, 0x56, 0xf7, 0xac, 0x76, 0xd6, 0xeb, 0x5a, 0xbd, 0x76, - 0xf7, 0xb4, 0x79, 0x68, 0xb6, 0xcc, 0x66, 0x23, 0x1f, 0x41, 0x5b, 0xb0, 0xb6, 0x2c, 0x9f, 0xd7, - 0x8e, 0xcd, 0x46, 0x5e, 0x43, 0xdb, 0xb0, 0xb1, 0x2c, 0x98, 0x6d, 0x25, 0x45, 0x51, 0x01, 0x36, - 0x97, 0xa5, 0xf6, 0x89, 0xd5, 0xea, 0xb5, 0x1b, 0xdd, 0x7c, 0x0c, 0xed, 0xc0, 0xd6, 0x13, 0xed, - 0xff, 0xde, 0x49, 0xa7, 0xf7, 0x5f, 0x3e, 0xfe, 0x74, 0x61, 0xc3, 0xec, 0xd6, 0xea, 0xc7, 0xcd, - 0x46, 0x7e, 0xa5, 0x10, 0x7f, 0xfb, 0xbe, 0x18, 0xa9, 0xb7, 0x3e, 0xdf, 0x15, 0xb5, 0xdb, 0xbb, - 0xa2, 0xf6, 0xf5, 0xae, 0xa8, 0xbd, 0xbb, 0x2f, 0x46, 0x6e, 0xef, 0x8b, 0x91, 0x2f, 0xf7, 0xc5, - 0xc8, 0xeb, 0xbf, 0x06, 0x94, 0x0f, 0x27, 0xfd, 0xca, 0x05, 0x1b, 0x57, 0x8f, 0x5e, 0x9d, 0x37, - 0xdb, 0x84, 0xbf, 0x61, 0xde, 0x55, 0xf5, 0x62, 0x88, 0xa9, 0x53, 0xbd, 0x9e, 0xbf, 0xb9, 0x7c, - 0xe6, 0x12, 0xbf, 0x9f, 0x90, 0xcf, 0xe7, 0x3f, 0xdf, 0x02, 0x00, 0x00, 0xff, 0xff, 0xed, 0x76, - 0x9f, 0x61, 0x90, 0x05, 0x00, 0x00, + // 800 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x55, 0xcf, 0x6f, 0xe2, 0x46, + 0x14, 0xc6, 0x40, 0x20, 0x7e, 0xc6, 0x59, 0x3a, 0xfb, 0x23, 0x4e, 0xb6, 0xa1, 0x84, 0xaa, 0x12, + 0xaa, 0x2a, 0xd0, 0x6e, 0x0f, 0x3d, 0x93, 0x85, 0xa8, 0xd6, 0xa6, 0x6c, 0x6a, 0x2f, 0x91, 0xb6, + 0xaa, 0x64, 0x0d, 0x99, 0x09, 0x8c, 0x62, 0x3c, 0x96, 0x3d, 0xd0, 0x90, 0xbf, 0xa0, 0x52, 0x2f, + 0xfd, 0x1f, 0xda, 0x3f, 0xa3, 0xa7, 0x9e, 0x7a, 0xdc, 0x63, 0x8f, 0x55, 0xf2, 0x8f, 0x54, 0x33, + 0x63, 0x93, 0xb0, 0x9b, 0x6d, 0x73, 0xd9, 0x1b, 0xef, 0xfb, 0xbe, 0x79, 0xf3, 0xde, 0x7c, 0x1f, + 0x32, 0xb4, 0xce, 0x97, 0x0b, 0xda, 0x1d, 0xcf, 0x23, 0x12, 0xd2, 0xb4, 0xbb, 0x78, 0x36, 0xa6, + 0x02, 0x3f, 0xcb, 0xeb, 0x4e, 0x9c, 0x70, 0xc1, 0xd1, 0x23, 0xa9, 0xe9, 0xe4, 0x58, 0xa6, 0xd9, + 0x7d, 0x34, 0xe1, 0x13, 0xae, 0x04, 0x5d, 0xf9, 0x4b, 0x6b, 0x5b, 0xbf, 0x97, 0x61, 0xeb, 0x40, + 0x29, 0x8f, 0x13, 0x1e, 0xf3, 0x14, 0x87, 0x68, 0x1b, 0xaa, 0x31, 0xe7, 0x61, 0xc0, 0x88, 0x63, + 0x34, 0x8d, 0x76, 0xd9, 0xab, 0xc8, 0xd2, 0x25, 0x68, 0x0f, 0x20, 0x15, 0x3c, 0xc1, 0x13, 0x2a, + 0xb9, 0x62, 0xd3, 0x68, 0x9b, 0x9e, 0x99, 0x21, 0x2e, 0x41, 0xbb, 0xb0, 0x39, 0x8f, 0x43, 0x8e, + 0x09, 0x4d, 0x9c, 0x92, 0x22, 0x57, 0x35, 0xfa, 0x1c, 0xec, 0x88, 0x5e, 0x88, 0x60, 0x25, 0x28, + 0x2b, 0x41, 0x4d, 0x82, 0xa3, 0x5c, 0xf4, 0x14, 0x4c, 0x82, 0x05, 0x0e, 0x52, 0x76, 0x49, 0x9d, + 0x0d, 0x75, 0xf5, 0xa6, 0x04, 0x7c, 0x76, 0x49, 0xd1, 0x67, 0x60, 0xe9, 0x8d, 0x34, 0x5d, 0x51, + 0x34, 0x68, 0x48, 0x09, 0x1e, 0x43, 0x45, 0xf0, 0xe0, 0x9c, 0x2e, 0x9d, 0xaa, 0xea, 0xbd, 0x21, + 0xf8, 0x4b, 0xba, 0x44, 0x5f, 0xc0, 0x56, 0x7e, 0x6e, 0x3e, 0x9b, 0xe1, 0x64, 0xe9, 0x6c, 0x2a, + 0xda, 0xce, 0x8e, 0x6a, 0x70, 0x75, 0xf7, 0x14, 0xa7, 0x53, 0xc7, 0xd4, 0xd3, 0x4b, 0xe0, 0x5b, + 0x9c, 0x4e, 0xe5, 0xe2, 0xf3, 0x98, 0x60, 0x41, 0x49, 0x80, 0x85, 0x03, 0xea, 0x6a, 0x33, 0x43, + 0x7a, 0x02, 0xed, 0x43, 0x6d, 0xc1, 0x05, 0x4d, 0xd2, 0x60, 0x81, 0x43, 0x46, 0x1c, 0xab, 0x59, + 0x6a, 0x9b, 0x9e, 0xa5, 0xb1, 0x13, 0x09, 0xc9, 0x29, 0x32, 0x09, 0x8b, 0xb4, 0xa8, 0xa6, 0x44, + 0xb6, 0x46, 0x5d, 0x0d, 0xde, 0x92, 0xe1, 0x71, 0x2a, 0x30, 0x8b, 0x1c, 0xfb, 0xb6, 0xac, 0xa7, + 0x41, 0xb4, 0x03, 0x9b, 0x67, 0x09, 0x9f, 0xa9, 0x65, 0xb7, 0xd4, 0xac, 0x55, 0x59, 0xcb, 0x75, + 0x3b, 0xf0, 0x30, 0xf7, 0x28, 0x4e, 0xf8, 0x82, 0x11, 0x9a, 0x48, 0xb3, 0x1e, 0x34, 0x8d, 0xb6, + 0xed, 0x7d, 0x92, 0x51, 0xc7, 0x19, 0xe3, 0xaa, 0x1b, 0x4f, 0xf9, 0x2c, 0x4e, 0x68, 0x9a, 0x32, + 0x1e, 0x49, 0x69, 0x5d, 0x49, 0xed, 0x5b, 0xa8, 0x4b, 0x5a, 0x7f, 0x96, 0xe0, 0xc1, 0x21, 0x8b, + 0x70, 0xc8, 0x2e, 0x29, 0xd1, 0x79, 0xf9, 0x70, 0x4e, 0xb6, 0xa0, 0x98, 0xe5, 0xa3, 0xec, 0x15, + 0xd9, 0xbb, 0xb9, 0x29, 0xfd, 0x57, 0x6e, 0xca, 0xef, 0xe4, 0x66, 0x0f, 0x40, 0x6d, 0xca, 0x22, + 0x42, 0x2f, 0xb2, 0x4c, 0x98, 0x12, 0x71, 0x25, 0x20, 0x1f, 0x42, 0xf0, 0x8c, 0xd4, 0x89, 0xa8, + 0x0a, 0xae, 0xa9, 0x8f, 0x18, 0x87, 0x3e, 0xd4, 0xce, 0xf2, 0xb7, 0xc8, 0x03, 0x61, 0x3d, 0xdf, + 0xef, 0xdc, 0xf5, 0xb7, 0xeb, 0xac, 0x5e, 0xad, 0x27, 0x3c, 0xeb, 0xec, 0xa6, 0x58, 0x33, 0xd1, + 0xba, 0x97, 0x89, 0xb5, 0xfb, 0x9b, 0x68, 0xdf, 0x65, 0xe2, 0x0b, 0xb0, 0x6e, 0x4d, 0x83, 0x9e, + 0x40, 0x65, 0x4a, 0xd9, 0x64, 0x2a, 0x72, 0xfb, 0x74, 0x85, 0x3e, 0x05, 0x53, 0xb0, 0x19, 0x4d, + 0x05, 0x9e, 0xc5, 0x99, 0x8b, 0x37, 0x40, 0xeb, 0x0d, 0xec, 0x7b, 0x7c, 0x1e, 0x11, 0x8f, 0x8f, + 0x59, 0xe4, 0xb3, 0x68, 0x12, 0x52, 0x15, 0x71, 0x2c, 0x78, 0x72, 0x9c, 0xf0, 0x89, 0xbc, 0x0e, + 0x39, 0x50, 0xc5, 0x84, 0xc8, 0x9f, 0xaa, 0xb7, 0xe9, 0xe5, 0xa5, 0x34, 0x3b, 0xce, 0x54, 0xaa, + 0x77, 0xc9, 0x5b, 0xd5, 0xad, 0x5f, 0x0c, 0x40, 0x37, 0xbd, 0x57, 0xcd, 0x3e, 0x98, 0xb3, 0x1f, + 0xc1, 0xce, 0xcf, 0x06, 0x21, 0x4b, 0x85, 0x53, 0x6c, 0x96, 0xda, 0xd6, 0xf3, 0x6f, 0xee, 0x36, + 0xe2, 0x7f, 0xa7, 0xf6, 0x6a, 0x79, 0xb7, 0x23, 0x96, 0x8a, 0x2f, 0xff, 0x30, 0xa0, 0xa6, 0x93, + 0xee, 0x0b, 0x2c, 0xe6, 0x29, 0xda, 0x83, 0x9d, 0x83, 0xd1, 0xb0, 0x7f, 0x34, 0x08, 0xfc, 0xd7, + 0xbd, 0xd7, 0x23, 0x3f, 0x18, 0x0d, 0xfd, 0xe3, 0xc1, 0x0b, 0xf7, 0xd0, 0x1d, 0xf4, 0xeb, 0x05, + 0xb4, 0x0d, 0x0f, 0xd7, 0xe9, 0x93, 0xde, 0x91, 0xdb, 0xaf, 0x1b, 0x68, 0x07, 0x1e, 0xaf, 0x13, + 0xee, 0x50, 0x53, 0x45, 0xb4, 0x0b, 0x4f, 0xd6, 0xa9, 0xe1, 0xab, 0xe0, 0x70, 0x34, 0xec, 0xfb, + 0xf5, 0x12, 0x7a, 0x0a, 0xdb, 0xef, 0x71, 0xdf, 0x8f, 0x5e, 0x79, 0xa3, 0xef, 0xea, 0xe5, 0xf7, + 0x0f, 0xf6, 0x5d, 0xbf, 0x77, 0x70, 0x34, 0xe8, 0xd7, 0x37, 0x76, 0xcb, 0x3f, 0xff, 0xd6, 0x28, + 0x1c, 0x1c, 0xfe, 0x75, 0xd5, 0x30, 0xde, 0x5e, 0x35, 0x8c, 0x7f, 0xae, 0x1a, 0xc6, 0xaf, 0xd7, + 0x8d, 0xc2, 0xdb, 0xeb, 0x46, 0xe1, 0xef, 0xeb, 0x46, 0xe1, 0x87, 0xaf, 0x26, 0x4c, 0x4c, 0xe7, + 0xe3, 0xce, 0x29, 0x9f, 0x75, 0x5f, 0xbe, 0x39, 0x19, 0x0c, 0xa9, 0xf8, 0x89, 0x27, 0xe7, 0xdd, + 0xd3, 0x29, 0x66, 0x51, 0xf7, 0x62, 0xf5, 0x71, 0x11, 0xcb, 0x98, 0xa6, 0xe3, 0x8a, 0xfa, 0x4e, + 0x7c, 0xfd, 0x6f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x74, 0x5f, 0x6b, 0xe1, 0x79, 0x06, 0x00, 0x00, } func (m *BundleProposal) Marshal() (dAtA []byte, err error) { @@ -791,6 +908,83 @@ func (m *FinalizedAt) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *RoundRobinSingleValidatorProgress) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *RoundRobinSingleValidatorProgress) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *RoundRobinSingleValidatorProgress) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Progress != 0 { + i = encodeVarintBundles(dAtA, i, uint64(m.Progress)) + i-- + dAtA[i] = 0x10 + } + if len(m.Address) > 0 { + i -= len(m.Address) + copy(dAtA[i:], m.Address) + i = encodeVarintBundles(dAtA, i, uint64(len(m.Address))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *RoundRobinProgress) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *RoundRobinProgress) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *RoundRobinProgress) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.ProgressList) > 0 { + for iNdEx := len(m.ProgressList) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.ProgressList[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintBundles(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + } + if m.PoolId != 0 { + i = encodeVarintBundles(dAtA, i, uint64(m.PoolId)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + func encodeVarintBundles(dAtA []byte, offset int, v uint64) int { offset -= sovBundles(v) base := offset @@ -945,6 +1139,40 @@ func (m *FinalizedAt) Size() (n int) { return n } +func (m *RoundRobinSingleValidatorProgress) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Address) + if l > 0 { + n += 1 + l + sovBundles(uint64(l)) + } + if m.Progress != 0 { + n += 1 + sovBundles(uint64(m.Progress)) + } + return n +} + +func (m *RoundRobinProgress) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.PoolId != 0 { + n += 1 + sovBundles(uint64(m.PoolId)) + } + if len(m.ProgressList) > 0 { + for _, e := range m.ProgressList { + l = e.Size() + n += 1 + l + sovBundles(uint64(l)) + } + } + return n +} + func sovBundles(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -1915,6 +2143,210 @@ func (m *FinalizedAt) Unmarshal(dAtA []byte) error { } return nil } +func (m *RoundRobinSingleValidatorProgress) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBundles + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: RoundRobinSingleValidatorProgress: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: RoundRobinSingleValidatorProgress: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBundles + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthBundles + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthBundles + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Address = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Progress", wireType) + } + m.Progress = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBundles + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Progress |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipBundles(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthBundles + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *RoundRobinProgress) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBundles + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: RoundRobinProgress: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: RoundRobinProgress: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field PoolId", wireType) + } + m.PoolId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBundles + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.PoolId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ProgressList", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBundles + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthBundles + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthBundles + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ProgressList = append(m.ProgressList, &RoundRobinSingleValidatorProgress{}) + if err := m.ProgressList[len(m.ProgressList)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipBundles(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthBundles + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func skipBundles(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 diff --git a/x/bundles/types/genesis.pb.go b/x/bundles/types/genesis.pb.go index abd26aa3..699c1a92 100644 --- a/x/bundles/types/genesis.pb.go +++ b/x/bundles/types/genesis.pb.go @@ -31,6 +31,8 @@ type GenesisState struct { BundleProposalList []BundleProposal `protobuf:"bytes,2,rep,name=bundle_proposal_list,json=bundleProposalList,proto3" json:"bundle_proposal_list"` // finalized_bundle_list ... FinalizedBundleList []FinalizedBundle `protobuf:"bytes,3,rep,name=finalized_bundle_list,json=finalizedBundleList,proto3" json:"finalized_bundle_list"` + // round_robin_progress_list ... + RoundRobinProgressList []RoundRobinProgress `protobuf:"bytes,4,rep,name=round_robin_progress_list,json=roundRobinProgressList,proto3" json:"round_robin_progress_list"` } func (m *GenesisState) Reset() { *m = GenesisState{} } @@ -87,6 +89,13 @@ func (m *GenesisState) GetFinalizedBundleList() []FinalizedBundle { return nil } +func (m *GenesisState) GetRoundRobinProgressList() []RoundRobinProgress { + if m != nil { + return m.RoundRobinProgressList + } + return nil +} + func init() { proto.RegisterType((*GenesisState)(nil), "kyve.bundles.v1beta1.GenesisState") } @@ -96,26 +105,29 @@ func init() { } var fileDescriptor_21c07b409d3bb015 = []byte{ - // 301 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0xca, 0xae, 0x2c, 0x4b, - 0xd5, 0x4f, 0x2a, 0xcd, 0x4b, 0xc9, 0x49, 0x2d, 0xd6, 0x2f, 0x33, 0x4c, 0x4a, 0x2d, 0x49, 0x34, - 0xd4, 0x4f, 0x4f, 0xcd, 0x4b, 0x2d, 0xce, 0x2c, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, - 0x01, 0xa9, 0xd1, 0x83, 0xaa, 0xd1, 0x83, 0xaa, 0x91, 0x12, 0x49, 0xcf, 0x4f, 0xcf, 0x07, 0x2b, - 0xd0, 0x07, 0xb1, 0x20, 0x6a, 0xa5, 0xb0, 0x9b, 0x07, 0xd3, 0x0b, 0x51, 0xa3, 0x88, 0x55, 0x4d, - 0x41, 0x62, 0x51, 0x62, 0x2e, 0x54, 0x89, 0x52, 0x27, 0x13, 0x17, 0x8f, 0x3b, 0xc4, 0x11, 0xc1, - 0x25, 0x89, 0x25, 0xa9, 0x42, 0x56, 0x5c, 0x6c, 0x10, 0x05, 0x12, 0x8c, 0x0a, 0x8c, 0x1a, 0xdc, - 0x46, 0x32, 0x7a, 0xd8, 0x1c, 0xa5, 0x17, 0x00, 0x56, 0xe3, 0xc4, 0x72, 0xe2, 0x9e, 0x3c, 0x43, - 0x10, 0x54, 0x87, 0x50, 0x0c, 0x97, 0x08, 0x44, 0x5d, 0x7c, 0x41, 0x51, 0x7e, 0x41, 0x7e, 0x71, - 0x62, 0x4e, 0x7c, 0x4e, 0x66, 0x71, 0x89, 0x04, 0x93, 0x02, 0xb3, 0x06, 0xb7, 0x91, 0x0a, 0x76, - 0x93, 0x9c, 0xc0, 0xfc, 0x00, 0xa8, 0x06, 0xa8, 0x89, 0x42, 0x49, 0x28, 0xa2, 0x3e, 0x99, 0xc5, - 0x25, 0x42, 0xf1, 0x5c, 0xa2, 0x69, 0x99, 0x79, 0x89, 0x39, 0x99, 0x55, 0xa9, 0x29, 0xf1, 0x50, - 0x7b, 0xc0, 0xc6, 0x33, 0x83, 0x8d, 0x57, 0xc5, 0x6e, 0xbc, 0x1b, 0x4c, 0x0b, 0xc4, 0x1e, 0xa8, - 0xf9, 0xc2, 0x69, 0xa8, 0xc2, 0x20, 0x0b, 0x9c, 0xdc, 0x4e, 0x3c, 0x92, 0x63, 0xbc, 0xf0, 0x48, - 0x8e, 0xf1, 0xc1, 0x23, 0x39, 0xc6, 0x09, 0x8f, 0xe5, 0x18, 0x2e, 0x3c, 0x96, 0x63, 0xb8, 0xf1, - 0x58, 0x8e, 0x21, 0x4a, 0x27, 0x3d, 0xb3, 0x24, 0xa3, 0x34, 0x49, 0x2f, 0x39, 0x3f, 0x57, 0xdf, - 0x3b, 0x32, 0xcc, 0xd5, 0x2f, 0xb5, 0xa4, 0x3c, 0xbf, 0x28, 0x5b, 0x3f, 0x39, 0x23, 0x31, 0x33, - 0x4f, 0xbf, 0x02, 0x1e, 0xc4, 0x25, 0x95, 0x05, 0xa9, 0xc5, 0x49, 0x6c, 0xe0, 0xa0, 0x35, 0x06, - 0x04, 0x00, 0x00, 0xff, 0xff, 0xbf, 0xed, 0x45, 0xe0, 0xf3, 0x01, 0x00, 0x00, + // 342 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x91, 0x4f, 0x4b, 0x02, 0x41, + 0x18, 0xc6, 0x77, 0x55, 0x3c, 0xac, 0x9d, 0x36, 0x0b, 0x93, 0xd8, 0x4c, 0x0a, 0x3c, 0xc4, 0x0e, + 0xda, 0xad, 0xa3, 0x90, 0x1d, 0x8a, 0x10, 0x83, 0xa0, 0x08, 0x96, 0x59, 0x1d, 0xd7, 0xc1, 0x75, + 0x66, 0x99, 0x19, 0x2d, 0xfb, 0x14, 0x7d, 0x2c, 0x8f, 0x1e, 0x3b, 0x45, 0xb8, 0x5f, 0xa1, 0x0f, + 0x10, 0xf3, 0xc7, 0x40, 0x9a, 0xdb, 0xee, 0xbb, 0xbf, 0xe7, 0xf9, 0xbd, 0xcb, 0xeb, 0x35, 0xa7, + 0xcb, 0x05, 0x02, 0xf1, 0x9c, 0x8c, 0x52, 0xc4, 0xc1, 0xa2, 0x1d, 0x23, 0x01, 0xdb, 0x20, 0x41, + 0x04, 0x71, 0xcc, 0xc3, 0x8c, 0x51, 0x41, 0xfd, 0xaa, 0x64, 0x42, 0xc3, 0x84, 0x86, 0xa9, 0x57, + 0x13, 0x9a, 0x50, 0x05, 0x00, 0xf9, 0xa4, 0xd9, 0xba, 0xbd, 0x6f, 0x9b, 0xd5, 0xcc, 0xa9, 0x95, + 0xc9, 0x20, 0x83, 0x33, 0x83, 0x34, 0x7f, 0x0a, 0xde, 0xde, 0x8d, 0x5e, 0xe2, 0x41, 0x40, 0x81, + 0xfc, 0x2b, 0xaf, 0xac, 0x81, 0x9a, 0xdb, 0x70, 0x5b, 0x95, 0xce, 0x71, 0x68, 0x5b, 0x2a, 0xec, + 0x2b, 0xa6, 0x5b, 0x5a, 0x7d, 0x9d, 0x38, 0x03, 0x93, 0xf0, 0x5f, 0xbc, 0xaa, 0xe6, 0xa2, 0x8c, + 0xd1, 0x8c, 0x72, 0x98, 0x46, 0x29, 0xe6, 0xa2, 0x56, 0x68, 0x14, 0x5b, 0x95, 0xce, 0x99, 0xbd, + 0xa9, 0xab, 0xde, 0xfb, 0x26, 0x60, 0x1a, 0xfd, 0x78, 0x67, 0x7a, 0x87, 0xb9, 0xf0, 0x23, 0xef, + 0x60, 0x8c, 0x09, 0x4c, 0xf1, 0x3b, 0x1a, 0x45, 0xc6, 0xa3, 0xea, 0x8b, 0xaa, 0xfe, 0xdc, 0x5e, + 0xdf, 0xdb, 0x46, 0xb4, 0xc7, 0xf4, 0xef, 0x8f, 0x77, 0xc7, 0x4a, 0x80, 0xbd, 0x23, 0x46, 0xe7, + 0x64, 0x14, 0x31, 0x1a, 0x63, 0x22, 0xff, 0x21, 0x61, 0x88, 0x73, 0x2d, 0x29, 0x29, 0x49, 0xcb, + 0x2e, 0x19, 0xc8, 0xd8, 0x40, 0xa6, 0xfa, 0x26, 0x64, 0x3c, 0x87, 0xec, 0xdf, 0x17, 0xa9, 0xea, + 0xf6, 0x56, 0x9b, 0xc0, 0x5d, 0x6f, 0x02, 0xf7, 0x7b, 0x13, 0xb8, 0x1f, 0x79, 0xe0, 0xac, 0xf3, + 0xc0, 0xf9, 0xcc, 0x03, 0xe7, 0xf9, 0x22, 0xc1, 0x62, 0x32, 0x8f, 0xc3, 0x21, 0x9d, 0x81, 0xdb, + 0xa7, 0xc7, 0xeb, 0x7b, 0x24, 0x5e, 0x29, 0x9b, 0x82, 0xe1, 0x04, 0x62, 0x02, 0xde, 0xfe, 0xae, + 0x29, 0x96, 0x19, 0xe2, 0x71, 0x59, 0x5d, 0xf1, 0xf2, 0x37, 0x00, 0x00, 0xff, 0xff, 0xa1, 0xc8, + 0xa7, 0xad, 0x5e, 0x02, 0x00, 0x00, } func (m *GenesisState) Marshal() (dAtA []byte, err error) { @@ -138,6 +150,20 @@ func (m *GenesisState) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if len(m.RoundRobinProgressList) > 0 { + for iNdEx := len(m.RoundRobinProgressList) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.RoundRobinProgressList[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + } + } if len(m.FinalizedBundleList) > 0 { for iNdEx := len(m.FinalizedBundleList) - 1; iNdEx >= 0; iNdEx-- { { @@ -210,6 +236,12 @@ func (m *GenesisState) Size() (n int) { n += 1 + l + sovGenesis(uint64(l)) } } + if len(m.RoundRobinProgressList) > 0 { + for _, e := range m.RoundRobinProgressList { + l = e.Size() + n += 1 + l + sovGenesis(uint64(l)) + } + } return n } @@ -349,6 +381,40 @@ func (m *GenesisState) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field RoundRobinProgressList", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.RoundRobinProgressList = append(m.RoundRobinProgressList, RoundRobinProgress{}) + if err := m.RoundRobinProgressList[len(m.RoundRobinProgressList)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipGenesis(dAtA[iNdEx:]) diff --git a/x/bundles/types/keys.go b/x/bundles/types/keys.go index 0c5597bf..df18f4ca 100644 --- a/x/bundles/types/keys.go +++ b/x/bundles/types/keys.go @@ -25,6 +25,8 @@ var ( BundleKeyPrefix = []byte{1} // FinalizedBundlePrefix ... FinalizedBundlePrefix = []byte{2} + // RoundRobinProgressPrefix ... + RoundRobinProgressPrefix = []byte{3} FinalizedBundleByHeightPrefix = []byte{11} ) @@ -39,6 +41,11 @@ func FinalizedBundleKey(poolId uint64, id uint64) []byte { return util.GetByteKey(poolId, id) } +// RoundRobinProgressKey ... +func RoundRobinProgressKey(poolId uint64) []byte { + return util.GetByteKey(poolId) +} + // FinalizedBundleByHeightKey ... func FinalizedBundleByHeightKey(poolId uint64, height uint64) []byte { return util.GetByteKey(poolId, height) diff --git a/x/query/keeper/grpc_query_can_propose_test.go b/x/query/keeper/grpc_query_can_propose_test.go index 85f8971e..f9455053 100644 --- a/x/query/keeper/grpc_query_can_propose_test.go +++ b/x/query/keeper/grpc_query_can_propose_test.go @@ -428,8 +428,8 @@ var _ = Describe("grpc_query_can_propose.go", Ordered, func() { // ACT canPropose, err := s.App().QueryKeeper.CanPropose(sdk.WrapSDKContext(s.Ctx()), &querytypes.QueryCanProposeRequest{ PoolId: 0, - Staker: i.STAKER_0, - Proposer: i.VALADDRESS_0, + Staker: i.STAKER_1, + Proposer: i.VALADDRESS_1, FromIndex: 100, }) @@ -442,8 +442,8 @@ var _ = Describe("grpc_query_can_propose.go", Ordered, func() { Expect(canPropose.Reason).To(Equal(errors.Wrapf(bundletypes.ErrUploadInterval, "expected %v < %v", s.Ctx().BlockTime().Unix(), bundleProposal.UpdatedAt+pool.UploadInterval).Error())) _, txErr := s.RunTx(&bundletypes.MsgSubmitBundleProposal{ - Creator: i.VALADDRESS_0, - Staker: i.STAKER_0, + Creator: i.VALADDRESS_1, + Staker: i.STAKER_1, PoolId: 0, StorageId: "test_storage_id", DataSize: 100, @@ -463,15 +463,15 @@ var _ = Describe("grpc_query_can_propose.go", Ordered, func() { // ACT canPropose_1, err_1 := s.App().QueryKeeper.CanPropose(sdk.WrapSDKContext(s.Ctx()), &querytypes.QueryCanProposeRequest{ PoolId: 0, - Staker: i.STAKER_0, - Proposer: i.VALADDRESS_0, + Staker: i.STAKER_1, + Proposer: i.VALADDRESS_1, FromIndex: 99, }) canPropose_2, err_2 := s.App().QueryKeeper.CanPropose(sdk.WrapSDKContext(s.Ctx()), &querytypes.QueryCanProposeRequest{ PoolId: 0, - Staker: i.STAKER_0, - Proposer: i.VALADDRESS_0, + Staker: i.STAKER_1, + Proposer: i.VALADDRESS_1, FromIndex: 101, }) @@ -489,8 +489,8 @@ var _ = Describe("grpc_query_can_propose.go", Ordered, func() { Expect(canPropose_2.Reason).To(Equal(errors.Wrapf(bundletypes.ErrFromIndex, "expected %v received %v", pool.CurrentIndex+bundleProposal.BundleSize, 101).Error())) _, txErr_1 := s.RunTx(&bundletypes.MsgSubmitBundleProposal{ - Creator: i.VALADDRESS_0, - Staker: i.STAKER_0, + Creator: i.VALADDRESS_1, + Staker: i.STAKER_1, PoolId: 0, StorageId: "test_storage_id", DataSize: 100, @@ -506,8 +506,8 @@ var _ = Describe("grpc_query_can_propose.go", Ordered, func() { Expect(txErr_1.Error()).To(Equal(canPropose_1.Reason)) _, txErr_2 := s.RunTx(&bundletypes.MsgSubmitBundleProposal{ - Creator: i.VALADDRESS_0, - Staker: i.STAKER_0, + Creator: i.VALADDRESS_1, + Staker: i.STAKER_1, PoolId: 0, StorageId: "test_storage_id", DataSize: 100, @@ -527,8 +527,8 @@ var _ = Describe("grpc_query_can_propose.go", Ordered, func() { // ACT canPropose, err := s.App().QueryKeeper.CanPropose(sdk.WrapSDKContext(s.Ctx()), &querytypes.QueryCanProposeRequest{ PoolId: 0, - Staker: i.STAKER_0, - Proposer: i.VALADDRESS_0, + Staker: i.STAKER_1, + Proposer: i.VALADDRESS_1, FromIndex: 100, }) @@ -539,8 +539,8 @@ var _ = Describe("grpc_query_can_propose.go", Ordered, func() { Expect(canPropose.Reason).To(BeEmpty()) _, txErr := s.RunTx(&bundletypes.MsgSubmitBundleProposal{ - Creator: i.VALADDRESS_0, - Staker: i.STAKER_0, + Creator: i.VALADDRESS_1, + Staker: i.STAKER_1, PoolId: 0, StorageId: "test_storage_id", DataSize: 100,