From 8c4d87ff9b829eb7019a03ce77810777f6927a22 Mon Sep 17 00:00:00 2001
From: Philip Offtermatt <57488781+p-offtermatt@users.noreply.github.com>
Date: Wed, 1 May 2024 16:59:05 +0200
Subject: [PATCH] feat!: Introduce Partial Set Security (#1809)
* cleanup ./changelog entries
* docs: changelog and release notes for v4.0.0 (#1564)
* add v4.0.0 section to changelog
* add release notes
* fix!: Validation of SlashAcks fails due to marshaling to Bech32 (backport #1570) (#1577)
fix!: Validation of SlashAcks fails due to marshaling to Bech32 (#1570)
* add different Bech32Prefix for consumer and provider
* separate app encoding and params
* remove ConsumerValPubKey from ValidatorConfig
* update addresses in tests
* make SlashAcks consistent across chains
* add comments for clarity
* Regenerate traces
* Fix argument order
* set bech32prefix for provider to cosmos
* add changelog entries
* add consumer-double-downtime e2e test
* update nightly-e2e workflow
* fix typo
* add consumer-double-downtime to testConfigs
* remove changes on provider
* skip invalid SlashAcks
* seal the config
* clear the outstanding downtime flag for new vals
* add info on upgrading to v4.0.0
* fix upgrade handler
* fix changeover e2e test
* Update tests/e2e/config.go
Co-authored-by: Philip Offtermatt <57488781+p-offtermatt@users.noreply.github.com>
* Update tests/e2e/config.go
Co-authored-by: Philip Offtermatt <57488781+p-offtermatt@users.noreply.github.com>
* add AccountPrefix to ChainConfig
* fix docstrings
* update AccountAddressPrefix in app.go
* fix consumer-misb e2e test
---------
Co-authored-by: Philip Offtermatt
Co-authored-by: Simon Noetzlin
Co-authored-by: Philip Offtermatt <57488781+p-offtermatt@users.noreply.github.com>
(cherry picked from commit 86046926502f7b0ba795bebcdd1fdc97ac776573)
Co-authored-by: Marius Poke
* docs: update changelog for v4.0.0 (#1578)
update changelog
* docs: prepare for v4.0.0 (#1581)
* unclog build
* update release notes
* update release date
* feat!: enable Opt In and Top N chains through gov proposals (#1615)
* init commit
* added test
* fixed tests
* added changelog entry and comment
* Update x/ccv/provider/keeper/proposal_test.go
Co-authored-by: Philip Offtermatt <57488781+p-offtermatt@users.noreply.github.com>
* Update .changelog/unreleased/features/1587-enable-opt-in-chains-through-gov-proposals.md
Co-authored-by: Philip Offtermatt <57488781+p-offtermatt@users.noreply.github.com>
* Update proto/interchain_security/ccv/provider/v1/provider.proto
Co-authored-by: Philip Offtermatt <57488781+p-offtermatt@users.noreply.github.com>
* Update proto/interchain_security/ccv/provider/v1/provider.proto
Co-authored-by: Philip Offtermatt <57488781+p-offtermatt@users.noreply.github.com>
* Update proto/interchain_security/ccv/provider/v1/provider.proto
Co-authored-by: Philip Offtermatt <57488781+p-offtermatt@users.noreply.github.com>
* Update proto/interchain_security/ccv/provider/v1/provider.proto
Co-authored-by: Philip Offtermatt <57488781+p-offtermatt@users.noreply.github.com>
* Update x/ccv/provider/keeper/keeper.go
Co-authored-by: Philip Offtermatt <57488781+p-offtermatt@users.noreply.github.com>
* changed to tabular test
---------
Co-authored-by: insumity
Co-authored-by: Philip Offtermatt <57488781+p-offtermatt@users.noreply.github.com>
* feat!: introduce MsgOptIn and MsgOptOut (#1620)
* init commit
* cleaning up
* changed cons to val address
* Revert "changed cons to val address"
This reverts commit a32e8829fee3cbbe50e363a0aa91ad62117a8a1d.
* Update x/ccv/provider/keeper/keeper.go
Co-authored-by: Simon Noetzlin
* took into account comments
* added key assignment
* add contraint such that opt out only works if the chain is running
---------
Co-authored-by: insumity
Co-authored-by: Simon Noetzlin
* test: MBT: Add partial set security to model (feature branch version) (#1627)
* Port changes from branch to main
* Add model analysis changes to Makefile
* test: Ports key assignment to the driver on the PSS feature branch (#1628)
* Port key assignment to MBT driver
* Add comment and make var names clearer
* feat!: automatically opt in validators that vote Yes on consumer addition proposals (#1629)
* init commit
* changed providerKeeper.GetProposedConsumerChain to return a bool
* add logging mesages
* one more log message
* fix comment
* added one more test case of NO vote and made tabular test
* test: Add driver for PSS (#1636)
* Port key assignment to MBT driver
* Add PSS trace generation
* Add PSS trace gen to longer trace gen
* Start handling top N parameter for new consumers
* Finish merge
* Add handling for optin/optout steps
* Remove expected error from OptIn, which should not error
* set top N parameter during path setup
* Add comment to setup.go
* feat!: add PSS reward distribution spike (#1632)
* PSS reward distribution
* "add optin mapping to test"
* Update app/provider/app.go
Co-authored-by: Philip Offtermatt <57488781+p-offtermatt@users.noreply.github.com>
* docs
* add TODO
* fix Dos vector in IBCMiddlewarea
* add reformat
* fix DOS issue and make integration tests pass
* doc
* add integration test
* doc
* Compute total vp per consumer
* add comments
* remove opt-in comments and add TODOs
* format
* Update x/ccv/provider/keeper/distribution.go
Co-authored-by: insumity
* add UT + doc
* Update tests/integration/distribution.go
Co-authored-by: insumity
* Update tests/integration/distribution.go
Co-authored-by: insumity
* nits
* Update x/ccv/provider/ibc_middleware.go
Co-authored-by: Marius Poke
* add panics in IBC Middleware ICS4wrapper funcs
* address comments
---------
Co-authored-by: Philip Offtermatt <57488781+p-offtermatt@users.noreply.github.com>
Co-authored-by: insumity
Co-authored-by: Marius Poke
* feat! use protos to serialize opted-in validators (#1659)
move OptedInValidators to proto
Co-authored-by: insumity
* feat!: PSS enable per-consumer chain commission (#1657)
* add draft commission
* implement consumer commission draft
* formatting
* add msg handling
* improve UT
* nits
* Update x/ccv/provider/keeper/keeper.go
Co-authored-by: insumity
* Update proto/interchain_security/ccv/provider/v1/tx.proto
Co-authored-by: Marius Poke
* optimize keys
* Update x/ccv/provider/keeper/keeper.go
Co-authored-by: insumity
* address comments
* address comments
* remove unnecessary check
* Revert "remove unnecessary check"
This reverts commit 2951e9bace04f6436d6ad1e4a11efcedd0be8cb1.
* fix minor bug in StopConsumerChain
---------
Co-authored-by: insumity
Co-authored-by: Marius Poke
* test: update integration test suite for PSS (#1687)
* draft multi consumer transfer setup and test
* format multi consumer distribution test
* update test for democ consumer chains
* nits
* nit
* docs: changelog and release notes for v4.0.0 (#1564)
* add v4.0.0 section to changelog
* add release notes
* fix!: Validation of SlashAcks fails due to marshaling to Bech32 (backport #1570) (#1577)
fix!: Validation of SlashAcks fails due to marshaling to Bech32 (#1570)
* add different Bech32Prefix for consumer and provider
* separate app encoding and params
* remove ConsumerValPubKey from ValidatorConfig
* update addresses in tests
* make SlashAcks consistent across chains
* add comments for clarity
* Regenerate traces
* Fix argument order
* set bech32prefix for provider to cosmos
* add changelog entries
* add consumer-double-downtime e2e test
* update nightly-e2e workflow
* fix typo
* add consumer-double-downtime to testConfigs
* remove changes on provider
* skip invalid SlashAcks
* seal the config
* clear the outstanding downtime flag for new vals
* add info on upgrading to v4.0.0
* fix upgrade handler
* fix changeover e2e test
* Update tests/e2e/config.go
Co-authored-by: Philip Offtermatt <57488781+p-offtermatt@users.noreply.github.com>
* Update tests/e2e/config.go
Co-authored-by: Philip Offtermatt <57488781+p-offtermatt@users.noreply.github.com>
* add AccountPrefix to ChainConfig
* fix docstrings
* update AccountAddressPrefix in app.go
* fix consumer-misb e2e test
---------
Co-authored-by: Philip Offtermatt
Co-authored-by: Simon Noetzlin
Co-authored-by: Philip Offtermatt <57488781+p-offtermatt@users.noreply.github.com>
(cherry picked from commit 86046926502f7b0ba795bebcdd1fdc97ac776573)
Co-authored-by: Marius Poke
* docs: update changelog for v4.0.0 (#1578)
update changelog
* feat!: enable Opt In and Top N chains through gov proposals (#1615)
* init commit
* added test
* fixed tests
* added changelog entry and comment
* Update x/ccv/provider/keeper/proposal_test.go
Co-authored-by: Philip Offtermatt <57488781+p-offtermatt@users.noreply.github.com>
* Update .changelog/unreleased/features/1587-enable-opt-in-chains-through-gov-proposals.md
Co-authored-by: Philip Offtermatt <57488781+p-offtermatt@users.noreply.github.com>
* Update proto/interchain_security/ccv/provider/v1/provider.proto
Co-authored-by: Philip Offtermatt <57488781+p-offtermatt@users.noreply.github.com>
* Update proto/interchain_security/ccv/provider/v1/provider.proto
Co-authored-by: Philip Offtermatt <57488781+p-offtermatt@users.noreply.github.com>
* Update proto/interchain_security/ccv/provider/v1/provider.proto
Co-authored-by: Philip Offtermatt <57488781+p-offtermatt@users.noreply.github.com>
* Update proto/interchain_security/ccv/provider/v1/provider.proto
Co-authored-by: Philip Offtermatt <57488781+p-offtermatt@users.noreply.github.com>
* Update x/ccv/provider/keeper/keeper.go
Co-authored-by: Philip Offtermatt <57488781+p-offtermatt@users.noreply.github.com>
* changed to tabular test
---------
Co-authored-by: insumity
Co-authored-by: Philip Offtermatt <57488781+p-offtermatt@users.noreply.github.com>
* feat!: introduce MsgOptIn and MsgOptOut (#1620)
* init commit
* cleaning up
* changed cons to val address
* Revert "changed cons to val address"
This reverts commit a32e8829fee3cbbe50e363a0aa91ad62117a8a1d.
* Update x/ccv/provider/keeper/keeper.go
Co-authored-by: Simon Noetzlin
* took into account comments
* added key assignment
* add contraint such that opt out only works if the chain is running
---------
Co-authored-by: insumity
Co-authored-by: Simon Noetzlin
* test: MBT: Add partial set security to model (feature branch version) (#1627)
* Port changes from branch to main
* Add model analysis changes to Makefile
* feat!: add PSS reward distribution spike (#1632)
* PSS reward distribution
* "add optin mapping to test"
* Update app/provider/app.go
Co-authored-by: Philip Offtermatt <57488781+p-offtermatt@users.noreply.github.com>
* docs
* add TODO
* fix Dos vector in IBCMiddlewarea
* add reformat
* fix DOS issue and make integration tests pass
* doc
* add integration test
* doc
* Compute total vp per consumer
* add comments
* remove opt-in comments and add TODOs
* format
* Update x/ccv/provider/keeper/distribution.go
Co-authored-by: insumity
* add UT + doc
* Update tests/integration/distribution.go
Co-authored-by: insumity
* Update tests/integration/distribution.go
Co-authored-by: insumity
* nits
* Update x/ccv/provider/ibc_middleware.go
Co-authored-by: Marius Poke
* add panics in IBC Middleware ICS4wrapper funcs
* address comments
---------
Co-authored-by: Philip Offtermatt <57488781+p-offtermatt@users.noreply.github.com>
Co-authored-by: insumity
Co-authored-by: Marius Poke
* feat!: PSS enable per-consumer chain commission (#1657)
* add draft commission
* implement consumer commission draft
* formatting
* add msg handling
* improve UT
* nits
* Update x/ccv/provider/keeper/keeper.go
Co-authored-by: insumity
* Update proto/interchain_security/ccv/provider/v1/tx.proto
Co-authored-by: Marius Poke
* optimize keys
* Update x/ccv/provider/keeper/keeper.go
Co-authored-by: insumity
* address comments
* address comments
* remove unnecessary check
* Revert "remove unnecessary check"
This reverts commit 2951e9bace04f6436d6ad1e4a11efcedd0be8cb1.
* fix minor bug in StopConsumerChain
---------
Co-authored-by: insumity
Co-authored-by: Marius Poke
* fix nits in MBT model after merging #1676 from main
* Fix merging ccv model
* Remove conflict markers
* Remove more conflict markers
* EndProviderEpoch takes ConsumerAdditionMsg
* Fix using consumer addition msgs instead of chain names in boundeddrift.qnt
* lint
* chore: rebase PSS branch with main (#1689)
* Update tests/mbt/driver/mbt_test.go
* nits
* revert unwanted line deletion from linter
---------
Co-authored-by: Philip Offtermatt <57488781+p-offtermatt@users.noreply.github.com>
* feat!: complete the PSS reward distribution (#1709)
* update compute consumer total power for reward distribution
* update distribution logic to work with epochcs
* Adapt reward distribution mem test to epochs
* doc
* nits
* other nits
* nits
* Update tests/integration/distribution.go
* feat!: Add slashing logic for PSS (#1710)
* add check for consumer validators in downtime logic
* fix UT
* try to fix weird errors in gh worfklow
* fix silly merge bug
* nits
* ci: do not scan the tests for security issues (#1717)
init commit
* feat!: compute partial sets (#1702)
* init commit
* nit change
* cleaning up
* clean up
* fix distribution test
* Update x/ccv/provider/keeper/hooks.go
Co-authored-by: Simon Noetzlin
* took into Simon's comments
* took into rest of the comments
* nit change
* return an error if validator cannot opt out from a Top N chain
* removed automatic opt-in for validators that vote Yes on proposals
* tiny fix for E2E tests
* nit change to remove unecessary else
* fixed topN == 0 issue
---------
Co-authored-by: Simon Noetzlin
* feat!: update PSS cli (#1708)
finalize PSS CLI cmds
* Rename and add comission rate command to commands
* feat!: only perform consumer additions for non-empty chains (#1730)
* init commit
* Update x/ccv/provider/keeper/proposal.go
Co-authored-by: Philip Offtermatt <57488781+p-offtermatt@users.noreply.github.com>
---------
Co-authored-by: Philip Offtermatt <57488781+p-offtermatt@users.noreply.github.com>
* feat: Add queries for PSS and consumer commission rate (#1733)
* init commit
* nit change
* cleaning up
* clean up
* fix distribution test
* Update x/ccv/provider/keeper/hooks.go
Co-authored-by: Simon Noetzlin
* took into Simon's comments
* took into rest of the comments
* nit change
* return an error if validator cannot opt out from a Top N chain
* removed automatic opt-in for validators that vote Yes on proposals
* tiny fix for E2E tests
* nit change to remove unecessary else
* update consumer chains query to return topN
* update query consu chains proto
* add consumer chains per validator query
* Add PSS command to provider's cli
* nits
* add consumer commission rate query
* nits
* big renaming
* fix doc
* nits
* nits
* docs
* Update proto/interchain_security/ccv/provider/v1/query.proto
Co-authored-by: insumity
* nit
* add OptedIn in QueryConsumerChainsValidatorHasToValidate
* remove OptIn field in consumer chains query response
* include validators that opt-in during the next epochs
* update has-to-validate condition
* fix tinny bug in the tests after merging feat/partial-security
* update doc
* update cli description
* Update x/ccv/provider/keeper/grpc_query.go
Co-authored-by: insumity
* changes
---------
Co-authored-by: insumity
* fix!: Fix opt-in assignment (#1732)
* Make the same validator assigning the same key a noop instead of an error
* Adjust test
* Update tests
* Fix newline warning
* Regenerate traces
* Add key assignment change to changelog
* Add info log for same key same validator assignments
* Add changelog entry to api-breaking
* Update x/ccv/provider/handler_test.go
Co-authored-by: insumity
* Add more comments to test and return right validator
---------
Co-authored-by: insumity
* fix silly bug in PSS opted-in val query
* fix logging in ibc_module.go
* test: add partial-set-security E2E tests (#1737)
* init commit
* fix traces
* Add PSS to default tests
* Update tests/e2e/steps_partial_set_security.go
Co-authored-by: Philip Offtermatt <57488781+p-offtermatt@users.noreply.github.com>
* Update tests/e2e/steps_partial_set_security.go
Co-authored-by: Philip Offtermatt <57488781+p-offtermatt@users.noreply.github.com>
---------
Co-authored-by: Philip Offtermatt
Co-authored-by: Philip Offtermatt <57488781+p-offtermatt@users.noreply.github.com>
* Nit changes based on Simons comments. To be pushed directly because E2E PR 1737 were the comments were written was accidentally merged.
* fix!: return a SlashAck even if the validator is not a consumer validator (#1763)
* init commit
* fix test
* test: Expand PSS e2e test to include slashing (#1752)
* Expand test to include slashing
* Add back existing steps
* Add downtime to top N test
* Fix nits
* fix!: update unbonding pausing for PSS (#1728)
* draft PSS unbonding fix
* fix hook logic to retrieve validator address from ubd op
* add unbonding pausing unit-test
* remove panic in hook
* Get back 3.2.0 and 3.3.0 changelog from main
* Port epilogue from main
* Fix proto conflict
* generate proto files
* Port RELEASE_NOTES
* Fix merge for tests
* Merge declaration and assignment
* Clean up model files
* Add pss tests to MBT readme
* Restore MsgSubmitConsumerDoubleVoting handler
* Remove local driver files
* Remove Quint guidelines
* Add optin/optout to MBT readme
* Fix types in model
* Fix model
* Add migration
* Ensure SlashAcks are sent even when the valset does not change
* adding changelog entry
* Empty DowntimeSlachAcks on EndBlock
* Remove logs
* Change condition for sending slash acks
* Revert model changes
* Start fixing PSS issues in model
* Add expected errors to opt out action
* Revert PSS quint model changes
* Add parameter to ComputeNextEpochConsumerValSet
* Set top N param in setup
* Fix: do not try key assignment if there is no nonjailed validator
* Do not assign keys for jailed validators
* Only jail validators with non-zero-power
* Add unit test
* Add unit test for unset case
* Panic on not being able to unmarshal
* Move packet handling into ack.Success block
* Format
* Remove unnecessary comment
* Add parens for clarity
* Format and fix typo
* Move OptIn/OptOut events to provider events
* Remove unused function
* Improve comments for keys
* Improve comments for key getter functions
* Remove order change for existing keys
* Re-add nolint instruction
* nit comment fix
* Move ConsumerAllocationTests to correct folder
* nit comment fix
* fix!: handle consumer commission marshalling errors gracefully (#1836)
* handle consumer commission setter/getter gracefully to avoid BeginBlock panic + add msg in codec
* fix consumer commission query rest path
* fix: update queries REST path for PSS (#1839)
update queries rest path
* Clarify that GetProposedConsumerChain is test-only
* fix: Fix has-to-validate query (#1823)
* Fix has-to-validate query
* Flip comparison sign for checking minPower
* Regenerate traces
* Remove unnecessary print
* Address comments
* fix!: fix slashing in PSS (#1838)
* drop slash packet for opted-out validators before updating slash meter
* fix integration test
* fix ut
* update UT
* Update x/ccv/provider/types/msg.go
Co-authored-by: Marius Poke
* Remove BlockValidatorUpdate from expected staking keeper
* added an error response value to ComputeMinPowerToOptIn
* delete additional state when we stop a chain
* Assign keys and change voting power only for unjailed nodes with >0 power
* fix: Validate consumer commission rate against minimal rate (#1834)
* Validate consumer commission rate
* Add test for commission rates
* Remove static minimum commission rate validation from Set
* feat!: introduce power shaping (#1830)
* added power shaping
* fixes
* Add property based test for power cap
* fixed tests & added algorithm's idea
* nit changes
* Update x/ccv/provider/keeper/proposal.go
Co-authored-by: Philip Offtermatt <57488781+p-offtermatt@users.noreply.github.com>
* remove empty-validator-set check
* implicit memory aliasing issue fixed
* added keeper tests
* updated HasToValidate query
* Update x/ccv/provider/keeper/keeper.go
Co-authored-by: Philip Offtermatt <57488781+p-offtermatt@users.noreply.github.com>
* Update x/ccv/provider/keeper/keeper.go
Co-authored-by: Philip Offtermatt <57488781+p-offtermatt@users.noreply.github.com>
* took into account comments
* do not use cached ctx
* Fix E2E test. A jailed validator does not have to validate.
* fix merge issue and format
---------
Co-authored-by: Philip Offtermatt
Co-authored-by: Philip Offtermatt <57488781+p-offtermatt@users.noreply.github.com>
* Update v4 to v5 in package version
* Bump consensus version
* Add migration in correct folder
* Update version from v4 to v5 in migration
---------
Co-authored-by: mpoke
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Co-authored-by: insumity
Co-authored-by: insumity
Co-authored-by: Simon Noetzlin
---
.changelog/unreleased/.gitkeep | 0
...1732-assigning-already-assigned-key-fix.md | 2 +
.changelog/unreleased/features/1809-pss.md | 3 +
...ble-opt-in-chains-through-gov-proposals.md | 2 +
.../unreleased/state-breaking/1809-pss.md | 2 +
...ble-opt-in-chains-through-gov-proposals.md | 2 +
...1732-assigning-already-assigned-key-fix.md | 2 +
.../ante/forbidden_proposals_ante_test.go | 4 +-
app/consumer-democracy/ante_handler.go | 6 +-
app/consumer-democracy/app.go | 16 +-
.../proposals_whitelisting_test.go | 6 +-
.../ante/disabled_modules_ante_test.go | 4 +-
app/consumer/ante/msg_filter_ante_test.go | 4 +-
app/consumer/ante_handler.go | 4 +-
app/consumer/app.go | 10 +-
app/consumer/genesis.go | 4 +-
app/consumer/genesis_test.go | 6 +-
app/provider/app.go | 26 +-
app/sovereign/app.go | 5 +-
cmd/interchain-security-cd/cmd/root.go | 4 +-
cmd/interchain-security-cd/main.go | 6 +-
cmd/interchain-security-cdd/cmd/root.go | 4 +-
cmd/interchain-security-cdd/main.go | 6 +-
cmd/interchain-security-pd/cmd/root.go | 4 +-
cmd/interchain-security-pd/main.go | 6 +-
cmd/interchain-security-sd/cmd/root.go | 4 +-
cmd/interchain-security-sd/main.go | 6 +-
go.mod | 2 +-
.../ccv/consumer/v1/consumer.proto | 2 +-
.../ccv/consumer/v1/genesis.proto | 2 +-
.../ccv/consumer/v1/query.proto | 2 +-
.../ccv/provider/v1/genesis.proto | 2 +-
.../ccv/provider/v1/provider.proto | 35 +-
.../ccv/provider/v1/query.proto | 69 +-
.../ccv/provider/v1/tx.proto | 52 +-
.../ccv/v1/shared_consumer.proto | 2 +-
proto/interchain_security/ccv/v1/wire.proto | 2 +-
scripts/protocgen.sh | 2 +-
tests/e2e/actions.go | 124 +-
tests/e2e/builder.go | 1 -
tests/e2e/main.go | 14 +-
tests/e2e/state.go | 32 +
tests/e2e/steps_compatibility.go | 13 +-
tests/e2e/steps_consumer_misbehaviour.go | 1 +
tests/e2e/steps_partial_set_security.go | 1002 ++++++++++
tests/e2e/steps_sovereign_changeover.go | 1 +
tests/e2e/steps_start_chains.go | 17 +-
tests/e2e/test_driver.go | 4 +
.../e2e/tracehandler_testdata/changeover.json | 20 +-
.../consumer-double-sign.json | 43 +-
.../consumer-misbehaviour.json | 16 +-
.../e2e/tracehandler_testdata/democracy.json | 58 +-
.../democracyRewardsSteps.json | 58 +-
.../e2e/tracehandler_testdata/happyPath.json | 87 +-
.../multipleConsumers.json | 157 +-
.../e2e/tracehandler_testdata/shorthappy.json | 70 +-
.../tracehandler_testdata/slashThrottle.json | 58 +-
tests/integration/common.go | 8 +-
tests/integration/democracy.go | 6 +-
tests/integration/distribution.go | 712 ++++++-
tests/integration/double_vote.go | 4 +-
tests/integration/expired_client.go | 2 +-
tests/integration/instance_test.go | 10 +-
tests/integration/key_assignment.go | 61 +-
tests/integration/misbehaviour.go | 4 +-
tests/integration/normal_operations.go | 4 +-
tests/integration/setup.go | 79 +-
tests/integration/slashing.go | 15 +-
tests/integration/soft_opt_out.go | 4 +-
tests/integration/stop_consumer.go | 2 +-
tests/integration/throttle.go | 8 +-
tests/integration/throttle_retry.go | 2 +-
tests/integration/unbonding.go | 4 +-
tests/integration/valset_update.go | 2 +-
tests/mbt/driver/core.go | 16 +-
tests/mbt/driver/mbt_test.go | 6 +-
tests/mbt/driver/setup.go | 17 +-
tests/mbt/model/README.md | 20 +-
tests/mbt/model/ccv.qnt | 10 +-
tests/mbt/model/ccv_model.qnt | 16 +-
tests/mbt/model/ccv_pss.qnt | 157 ++
tests/mbt/model/ccv_pss_model.qnt | 113 ++
tests/mbt/model/ccv_pss_test.qnt | 61 +
tests/mbt/model/ccv_utils.qnt | 5 +
testutil/crypto/crypto.go | 2 +-
testutil/ibc_testing/generic_setup.go | 33 +-
testutil/ibc_testing/specific_setup.go | 10 +-
testutil/integration/debug_test.go | 30 +-
testutil/integration/interfaces.go | 7 +-
testutil/keeper/expectations.go | 4 +-
testutil/keeper/mocks.go | 214 ++-
testutil/keeper/unit_test_helpers.go | 20 +-
x/ccv/consumer/client/cli/query.go | 2 +-
x/ccv/consumer/ibc_module.go | 6 +-
x/ccv/consumer/ibc_module_test.go | 8 +-
x/ccv/consumer/keeper/changeover_test.go | 4 +-
x/ccv/consumer/keeper/distribution.go | 4 +-
x/ccv/consumer/keeper/distribution_test.go | 6 +-
x/ccv/consumer/keeper/genesis.go | 4 +-
x/ccv/consumer/keeper/genesis_test.go | 10 +-
x/ccv/consumer/keeper/grpc_query.go | 4 +-
x/ccv/consumer/keeper/hooks.go | 2 +-
x/ccv/consumer/keeper/keeper.go | 4 +-
x/ccv/consumer/keeper/keeper_test.go | 8 +-
x/ccv/consumer/keeper/migrations.go | 2 +-
x/ccv/consumer/keeper/params.go | 2 +-
x/ccv/consumer/keeper/params_test.go | 4 +-
x/ccv/consumer/keeper/provider_info.go | 4 +-
x/ccv/consumer/keeper/relay.go | 4 +-
x/ccv/consumer/keeper/relay_test.go | 10 +-
x/ccv/consumer/keeper/soft_opt_out.go | 2 +-
x/ccv/consumer/keeper/soft_opt_out_test.go | 6 +-
x/ccv/consumer/keeper/throttle_retry.go | 2 +-
x/ccv/consumer/keeper/throttle_retry_test.go | 6 +-
x/ccv/consumer/keeper/validators.go | 2 +-
x/ccv/consumer/keeper/validators_test.go | 8 +-
x/ccv/consumer/migrations/v2/migration.go | 4 +-
.../consumer/migrations/v2/migration_test.go | 8 +-
x/ccv/consumer/module.go | 8 +-
x/ccv/consumer/types/genesis.go | 2 +-
x/ccv/consumer/types/genesis.pb.go | 2 +-
x/ccv/consumer/types/genesis_test.go | 6 +-
x/ccv/consumer/types/keys.go | 2 +-
x/ccv/consumer/types/params_test.go | 2 +-
x/ccv/consumer/types/query.pb.go | 2 +-
x/ccv/democracy/distribution/module.go | 2 +-
x/ccv/provider/client/cli/query.go | 125 +-
x/ccv/provider/client/cli/tx.go | 134 +-
x/ccv/provider/client/proposal_handler.go | 18 +-
x/ccv/provider/handler.go | 13 +-
x/ccv/provider/handler_test.go | 43 +-
x/ccv/provider/ibc_middleware.go | 242 +++
x/ccv/provider/ibc_middleware_test.go | 77 +
x/ccv/provider/ibc_module.go | 6 +-
x/ccv/provider/ibc_module_test.go | 10 +-
.../provider/keeper/consumer_equivocation.go | 4 +-
.../keeper/consumer_equivocation_test.go | 6 +-
x/ccv/provider/keeper/distribution.go | 268 ++-
x/ccv/provider/keeper/distribution_test.go | 272 +++
x/ccv/provider/keeper/genesis.go | 4 +-
x/ccv/provider/keeper/genesis_test.go | 10 +-
x/ccv/provider/keeper/grpc_query.go | 110 +-
x/ccv/provider/keeper/grpc_query_test.go | 8 +-
x/ccv/provider/keeper/hooks.go | 63 +-
x/ccv/provider/keeper/hooks_test.go | 12 +-
x/ccv/provider/keeper/keeper.go | 409 +++-
x/ccv/provider/keeper/keeper_test.go | 225 ++-
x/ccv/provider/keeper/key_assignment.go | 74 +-
x/ccv/provider/keeper/key_assignment_test.go | 15 +-
x/ccv/provider/keeper/msg_server.go | 155 +-
x/ccv/provider/keeper/params.go | 4 +-
x/ccv/provider/keeper/params_test.go | 4 +-
x/ccv/provider/keeper/partial_set_security.go | 295 +++
.../keeper/partial_set_security_test.go | 676 +++++++
x/ccv/provider/keeper/proposal.go | 59 +-
x/ccv/provider/keeper/proposal_test.go | 106 +-
x/ccv/provider/keeper/relay.go | 26 +-
x/ccv/provider/keeper/relay_test.go | 248 ++-
x/ccv/provider/keeper/throttle.go | 2 +-
x/ccv/provider/keeper/throttle_legacy.go | 4 +-
x/ccv/provider/keeper/throttle_test.go | 4 +-
x/ccv/provider/keeper/validator_set_update.go | 121 +-
.../keeper/validator_set_update_test.go | 228 ++-
x/ccv/provider/migrations/migrator.go | 14 +-
.../provider/migrations/v3/migration_test.go | 2 +-
x/ccv/provider/migrations/v3/migrations.go | 2 +-
.../provider/migrations/v4/migration_test.go | 4 +-
x/ccv/provider/migrations/v4/migrations.go | 2 +-
.../provider/migrations/v5/migration_test.go | 30 +
x/ccv/provider/migrations/v5/migrations.go | 24 +
x/ccv/provider/module.go | 14 +-
x/ccv/provider/module_test.go | 8 +-
x/ccv/provider/proposal_handler.go | 4 +-
x/ccv/provider/proposal_handler_test.go | 11 +-
x/ccv/provider/types/codec.go | 12 +
x/ccv/provider/types/consumer.go | 2 +-
x/ccv/provider/types/errors.go | 4 +-
x/ccv/provider/types/events.go | 5 +
x/ccv/provider/types/genesis.go | 2 +-
x/ccv/provider/types/genesis.pb.go | 2 +-
x/ccv/provider/types/genesis_test.go | 6 +-
x/ccv/provider/types/key_assignment.go | 2 +-
x/ccv/provider/types/keys.go | 83 +-
x/ccv/provider/types/keys_test.go | 8 +-
x/ccv/provider/types/msg.go | 168 +-
x/ccv/provider/types/params.go | 2 +-
x/ccv/provider/types/params_test.go | 2 +-
x/ccv/provider/types/proposal.go | 22 +-
x/ccv/provider/types/proposal_test.go | 124 +-
x/ccv/provider/types/provider.pb.go | 620 +++++--
x/ccv/provider/types/query.pb.go | 1498 +++++++++++++--
x/ccv/provider/types/query.pb.gw.go | 325 ++++
x/ccv/provider/types/tx.pb.go | 1650 ++++++++++++++---
x/ccv/types/expected_keepers.go | 9 +
x/ccv/types/utils_test.go | 2 +-
x/ccv/types/wire_test.go | 4 +-
196 files changed, 11433 insertions(+), 1230 deletions(-)
create mode 100644 .changelog/unreleased/.gitkeep
create mode 100644 .changelog/unreleased/api-breaking/provider/1732-assigning-already-assigned-key-fix.md
create mode 100644 .changelog/unreleased/features/1809-pss.md
create mode 100644 .changelog/unreleased/features/provider/1587-enable-opt-in-chains-through-gov-proposals.md
create mode 100644 .changelog/unreleased/state-breaking/1809-pss.md
create mode 100644 .changelog/unreleased/state-breaking/provider/1587-enable-opt-in-chains-through-gov-proposals.md
create mode 100644 .changelog/unreleased/state-breaking/provider/1732-assigning-already-assigned-key-fix.md
create mode 100644 tests/e2e/steps_partial_set_security.go
create mode 100644 tests/mbt/model/ccv_pss.qnt
create mode 100644 tests/mbt/model/ccv_pss_model.qnt
create mode 100644 tests/mbt/model/ccv_pss_test.qnt
create mode 100644 x/ccv/provider/ibc_middleware.go
create mode 100644 x/ccv/provider/ibc_middleware_test.go
create mode 100644 x/ccv/provider/keeper/distribution_test.go
create mode 100644 x/ccv/provider/keeper/partial_set_security.go
create mode 100644 x/ccv/provider/keeper/partial_set_security_test.go
create mode 100644 x/ccv/provider/migrations/v5/migration_test.go
create mode 100644 x/ccv/provider/migrations/v5/migrations.go
diff --git a/.changelog/unreleased/.gitkeep b/.changelog/unreleased/.gitkeep
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/.changelog/unreleased/api-breaking/provider/1732-assigning-already-assigned-key-fix.md b/.changelog/unreleased/api-breaking/provider/1732-assigning-already-assigned-key-fix.md
new file mode 100644
index 0000000000..667a481d3f
--- /dev/null
+++ b/.changelog/unreleased/api-breaking/provider/1732-assigning-already-assigned-key-fix.md
@@ -0,0 +1,2 @@
+- Assigning a key that is already assigned by the same validator will now be a no-op instead of throwing an error.
+ ([\#1732](https://github.com/cosmos/interchain-security/pull/1732))
\ No newline at end of file
diff --git a/.changelog/unreleased/features/1809-pss.md b/.changelog/unreleased/features/1809-pss.md
new file mode 100644
index 0000000000..f7a235c5be
--- /dev/null
+++ b/.changelog/unreleased/features/1809-pss.md
@@ -0,0 +1,3 @@
+- Adding the Partial Set Security (PSS) feature cf. [ADR 015](https://cosmos.github.io/interchain-security/adrs/adr-015-partial-set-security).
+ PSS enables consumer chains to join ICS as _Top N_ or _Opt In_ chains and enables validators to opt to validate the consumer chains they want.
+ ([\#1809](https://github.com/cosmos/interchain-security/pull/1809))
\ No newline at end of file
diff --git a/.changelog/unreleased/features/provider/1587-enable-opt-in-chains-through-gov-proposals.md b/.changelog/unreleased/features/provider/1587-enable-opt-in-chains-through-gov-proposals.md
new file mode 100644
index 0000000000..57f16adc9b
--- /dev/null
+++ b/.changelog/unreleased/features/provider/1587-enable-opt-in-chains-through-gov-proposals.md
@@ -0,0 +1,2 @@
+- Enable Opt In and Top N chains through gov proposals.
+ ([\#1587](https://github.com/cosmos/interchain-security/pull/1587))
\ No newline at end of file
diff --git a/.changelog/unreleased/state-breaking/1809-pss.md b/.changelog/unreleased/state-breaking/1809-pss.md
new file mode 100644
index 0000000000..c0af9ae11e
--- /dev/null
+++ b/.changelog/unreleased/state-breaking/1809-pss.md
@@ -0,0 +1,2 @@
+- Adding the Partial Set Security feature cf. [ADR 015](https://cosmos.github.io/interchain-security/adrs/adr-015-partial-set-security).
+ ([\#1809](https://github.com/cosmos/interchain-security/pull/1809))
\ No newline at end of file
diff --git a/.changelog/unreleased/state-breaking/provider/1587-enable-opt-in-chains-through-gov-proposals.md b/.changelog/unreleased/state-breaking/provider/1587-enable-opt-in-chains-through-gov-proposals.md
new file mode 100644
index 0000000000..57f16adc9b
--- /dev/null
+++ b/.changelog/unreleased/state-breaking/provider/1587-enable-opt-in-chains-through-gov-proposals.md
@@ -0,0 +1,2 @@
+- Enable Opt In and Top N chains through gov proposals.
+ ([\#1587](https://github.com/cosmos/interchain-security/pull/1587))
\ No newline at end of file
diff --git a/.changelog/unreleased/state-breaking/provider/1732-assigning-already-assigned-key-fix.md b/.changelog/unreleased/state-breaking/provider/1732-assigning-already-assigned-key-fix.md
new file mode 100644
index 0000000000..667a481d3f
--- /dev/null
+++ b/.changelog/unreleased/state-breaking/provider/1732-assigning-already-assigned-key-fix.md
@@ -0,0 +1,2 @@
+- Assigning a key that is already assigned by the same validator will now be a no-op instead of throwing an error.
+ ([\#1732](https://github.com/cosmos/interchain-security/pull/1732))
\ No newline at end of file
diff --git a/app/consumer-democracy/ante/forbidden_proposals_ante_test.go b/app/consumer-democracy/ante/forbidden_proposals_ante_test.go
index 8fd7fe3824..c4c7123290 100644
--- a/app/consumer-democracy/ante/forbidden_proposals_ante_test.go
+++ b/app/consumer-democracy/ante/forbidden_proposals_ante_test.go
@@ -14,8 +14,8 @@ import (
minttypes "github.com/cosmos/cosmos-sdk/x/mint/types"
"github.com/cosmos/cosmos-sdk/x/params/types/proposal"
- app "github.com/cosmos/interchain-security/v4/app/consumer-democracy"
- "github.com/cosmos/interchain-security/v4/app/consumer-democracy/ante"
+ app "github.com/cosmos/interchain-security/v5/app/consumer-democracy"
+ "github.com/cosmos/interchain-security/v5/app/consumer-democracy/ante"
)
// in SDKv47 parameter updates full params object is required
diff --git a/app/consumer-democracy/ante_handler.go b/app/consumer-democracy/ante_handler.go
index 7e652ebb0c..b0f7432fb6 100644
--- a/app/consumer-democracy/ante_handler.go
+++ b/app/consumer-democracy/ante_handler.go
@@ -10,9 +10,9 @@ import (
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/x/auth/ante"
- democracyante "github.com/cosmos/interchain-security/v4/app/consumer-democracy/ante"
- consumerante "github.com/cosmos/interchain-security/v4/app/consumer/ante"
- ibcconsumerkeeper "github.com/cosmos/interchain-security/v4/x/ccv/consumer/keeper"
+ democracyante "github.com/cosmos/interchain-security/v5/app/consumer-democracy/ante"
+ consumerante "github.com/cosmos/interchain-security/v5/app/consumer/ante"
+ ibcconsumerkeeper "github.com/cosmos/interchain-security/v5/x/ccv/consumer/keeper"
)
// HandlerOptions extend the SDK's AnteHandler options by requiring the IBC
diff --git a/app/consumer-democracy/app.go b/app/consumer-democracy/app.go
index e90d35760e..190e6680d8 100644
--- a/app/consumer-democracy/app.go
+++ b/app/consumer-democracy/app.go
@@ -103,14 +103,14 @@ import (
"github.com/cometbft/cometbft/libs/log"
tmos "github.com/cometbft/cometbft/libs/os"
- appencoding "github.com/cosmos/interchain-security/v4/app/encoding"
- testutil "github.com/cosmos/interchain-security/v4/testutil/integration"
- consumer "github.com/cosmos/interchain-security/v4/x/ccv/consumer"
- consumerkeeper "github.com/cosmos/interchain-security/v4/x/ccv/consumer/keeper"
- consumertypes "github.com/cosmos/interchain-security/v4/x/ccv/consumer/types"
- ccvdistr "github.com/cosmos/interchain-security/v4/x/ccv/democracy/distribution"
- ccvgov "github.com/cosmos/interchain-security/v4/x/ccv/democracy/governance"
- ccvstaking "github.com/cosmos/interchain-security/v4/x/ccv/democracy/staking"
+ appencoding "github.com/cosmos/interchain-security/v5/app/encoding"
+ testutil "github.com/cosmos/interchain-security/v5/testutil/integration"
+ consumer "github.com/cosmos/interchain-security/v5/x/ccv/consumer"
+ consumerkeeper "github.com/cosmos/interchain-security/v5/x/ccv/consumer/keeper"
+ consumertypes "github.com/cosmos/interchain-security/v5/x/ccv/consumer/types"
+ ccvdistr "github.com/cosmos/interchain-security/v5/x/ccv/democracy/distribution"
+ ccvgov "github.com/cosmos/interchain-security/v5/x/ccv/democracy/governance"
+ ccvstaking "github.com/cosmos/interchain-security/v5/x/ccv/democracy/staking"
)
const (
diff --git a/app/consumer-democracy/proposals_whitelisting_test.go b/app/consumer-democracy/proposals_whitelisting_test.go
index 47dd42317a..c4209bf3b9 100644
--- a/app/consumer-democracy/proposals_whitelisting_test.go
+++ b/app/consumer-democracy/proposals_whitelisting_test.go
@@ -6,9 +6,9 @@ import (
ibctesting "github.com/cosmos/ibc-go/v7/testing"
"github.com/stretchr/testify/require"
- appConsumer "github.com/cosmos/interchain-security/v4/app/consumer-democracy"
- icstestingutils "github.com/cosmos/interchain-security/v4/testutil/ibc_testing"
- testutil "github.com/cosmos/interchain-security/v4/testutil/integration"
+ appConsumer "github.com/cosmos/interchain-security/v5/app/consumer-democracy"
+ icstestingutils "github.com/cosmos/interchain-security/v5/testutil/ibc_testing"
+ testutil "github.com/cosmos/interchain-security/v5/testutil/integration"
)
func TestDemocracyGovernanceWhitelistingKeys(t *testing.T) {
diff --git a/app/consumer/ante/disabled_modules_ante_test.go b/app/consumer/ante/disabled_modules_ante_test.go
index 7fa95f37c6..d06c3ad595 100644
--- a/app/consumer/ante/disabled_modules_ante_test.go
+++ b/app/consumer/ante/disabled_modules_ante_test.go
@@ -12,8 +12,8 @@ import (
evidencetypes "github.com/cosmos/cosmos-sdk/x/evidence/types"
slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types"
- "github.com/cosmos/interchain-security/v4/app/consumer/ante"
- appencoding "github.com/cosmos/interchain-security/v4/app/encoding"
+ "github.com/cosmos/interchain-security/v5/app/consumer/ante"
+ appencoding "github.com/cosmos/interchain-security/v5/app/encoding"
)
func TestDisabledModulesDecorator(t *testing.T) {
diff --git a/app/consumer/ante/msg_filter_ante_test.go b/app/consumer/ante/msg_filter_ante_test.go
index bfc1bb0a50..9dd5f47ef3 100644
--- a/app/consumer/ante/msg_filter_ante_test.go
+++ b/app/consumer/ante/msg_filter_ante_test.go
@@ -9,8 +9,8 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
- "github.com/cosmos/interchain-security/v4/app/consumer/ante"
- appencoding "github.com/cosmos/interchain-security/v4/app/encoding"
+ "github.com/cosmos/interchain-security/v5/app/consumer/ante"
+ appencoding "github.com/cosmos/interchain-security/v5/app/encoding"
)
type consumerKeeper struct {
diff --git a/app/consumer/ante_handler.go b/app/consumer/ante_handler.go
index fa28a52caf..f9cd986dad 100644
--- a/app/consumer/ante_handler.go
+++ b/app/consumer/ante_handler.go
@@ -10,8 +10,8 @@ import (
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/x/auth/ante"
- consumerante "github.com/cosmos/interchain-security/v4/app/consumer/ante"
- ibcconsumerkeeper "github.com/cosmos/interchain-security/v4/x/ccv/consumer/keeper"
+ consumerante "github.com/cosmos/interchain-security/v5/app/consumer/ante"
+ ibcconsumerkeeper "github.com/cosmos/interchain-security/v5/x/ccv/consumer/keeper"
)
// HandlerOptions extend the SDK's AnteHandler options by requiring the IBC
diff --git a/app/consumer/app.go b/app/consumer/app.go
index 9853145117..207939adcb 100644
--- a/app/consumer/app.go
+++ b/app/consumer/app.go
@@ -87,11 +87,11 @@ import (
"github.com/cometbft/cometbft/libs/log"
tmos "github.com/cometbft/cometbft/libs/os"
- appencoding "github.com/cosmos/interchain-security/v4/app/encoding"
- testutil "github.com/cosmos/interchain-security/v4/testutil/integration"
- ibcconsumer "github.com/cosmos/interchain-security/v4/x/ccv/consumer"
- ibcconsumerkeeper "github.com/cosmos/interchain-security/v4/x/ccv/consumer/keeper"
- ibcconsumertypes "github.com/cosmos/interchain-security/v4/x/ccv/consumer/types"
+ appencoding "github.com/cosmos/interchain-security/v5/app/encoding"
+ testutil "github.com/cosmos/interchain-security/v5/testutil/integration"
+ ibcconsumer "github.com/cosmos/interchain-security/v5/x/ccv/consumer"
+ ibcconsumerkeeper "github.com/cosmos/interchain-security/v5/x/ccv/consumer/keeper"
+ ibcconsumertypes "github.com/cosmos/interchain-security/v5/x/ccv/consumer/types"
)
const (
diff --git a/app/consumer/genesis.go b/app/consumer/genesis.go
index f6c8e47905..da55a0334e 100644
--- a/app/consumer/genesis.go
+++ b/app/consumer/genesis.go
@@ -16,8 +16,8 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/version"
- consumerTypes "github.com/cosmos/interchain-security/v4/x/ccv/consumer/types"
- "github.com/cosmos/interchain-security/v4/x/ccv/types"
+ consumerTypes "github.com/cosmos/interchain-security/v5/x/ccv/consumer/types"
+ "github.com/cosmos/interchain-security/v5/x/ccv/types"
)
// The genesis state of the blockchain is represented here as a map of raw json
diff --git a/app/consumer/genesis_test.go b/app/consumer/genesis_test.go
index 5827651959..2dd29e1b71 100644
--- a/app/consumer/genesis_test.go
+++ b/app/consumer/genesis_test.go
@@ -16,9 +16,9 @@ import (
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/x/auth/types"
- app "github.com/cosmos/interchain-security/v4/app/consumer"
- consumerTypes "github.com/cosmos/interchain-security/v4/x/ccv/consumer/types"
- ccvtypes "github.com/cosmos/interchain-security/v4/x/ccv/types"
+ app "github.com/cosmos/interchain-security/v5/app/consumer"
+ consumerTypes "github.com/cosmos/interchain-security/v5/x/ccv/consumer/types"
+ ccvtypes "github.com/cosmos/interchain-security/v5/x/ccv/types"
)
const (
diff --git a/app/provider/app.go b/app/provider/app.go
index 7527756d45..e5baa31270 100644
--- a/app/provider/app.go
+++ b/app/provider/app.go
@@ -100,12 +100,13 @@ import (
"github.com/cometbft/cometbft/libs/log"
tmos "github.com/cometbft/cometbft/libs/os"
- appencoding "github.com/cosmos/interchain-security/v4/app/encoding"
- testutil "github.com/cosmos/interchain-security/v4/testutil/integration"
- ibcprovider "github.com/cosmos/interchain-security/v4/x/ccv/provider"
- ibcproviderclient "github.com/cosmos/interchain-security/v4/x/ccv/provider/client"
- ibcproviderkeeper "github.com/cosmos/interchain-security/v4/x/ccv/provider/keeper"
- providertypes "github.com/cosmos/interchain-security/v4/x/ccv/provider/types"
+ appencoding "github.com/cosmos/interchain-security/v5/app/encoding"
+ testutil "github.com/cosmos/interchain-security/v5/testutil/integration"
+ "github.com/cosmos/interchain-security/v5/x/ccv/provider"
+ ibcprovider "github.com/cosmos/interchain-security/v5/x/ccv/provider"
+ ibcproviderclient "github.com/cosmos/interchain-security/v5/x/ccv/provider/client"
+ ibcproviderkeeper "github.com/cosmos/interchain-security/v5/x/ccv/provider/keeper"
+ providertypes "github.com/cosmos/interchain-security/v5/x/ccv/provider/types"
)
const (
@@ -470,12 +471,15 @@ func New(
app.BankKeeper,
scopedTransferKeeper,
)
- transferModule := transfer.NewAppModule(app.TransferKeeper)
- ibcmodule := transfer.NewIBCModule(app.TransferKeeper)
+
+ // Add an IBC middleware callback to track the consumer rewards
+ var transferStack porttypes.IBCModule
+ transferStack = transfer.NewIBCModule(app.TransferKeeper)
+ transferStack = provider.NewIBCMiddleware(transferStack, app.ProviderKeeper)
// create static IBC router, add transfer route, then set and seal it
ibcRouter := porttypes.NewRouter()
- ibcRouter.AddRoute(ibctransfertypes.ModuleName, ibcmodule)
+ ibcRouter.AddRoute(ibctransfertypes.ModuleName, transferStack)
ibcRouter.AddRoute(providertypes.ModuleName, providerModule)
app.IBCKeeper.SetRouter(ibcRouter)
@@ -514,7 +518,7 @@ func New(
evidence.NewAppModule(app.EvidenceKeeper),
ibc.NewAppModule(app.IBCKeeper),
params.NewAppModule(app.ParamsKeeper),
- transferModule,
+ transfer.NewAppModule(app.TransferKeeper),
providerModule,
)
@@ -610,7 +614,7 @@ func New(
params.NewAppModule(app.ParamsKeeper),
evidence.NewAppModule(app.EvidenceKeeper),
ibc.NewAppModule(app.IBCKeeper),
- transferModule,
+ transfer.NewAppModule(app.TransferKeeper),
)
app.sm.RegisterStoreDecoders()
diff --git a/app/sovereign/app.go b/app/sovereign/app.go
index 3d1a981e83..6dd9774f3b 100644
--- a/app/sovereign/app.go
+++ b/app/sovereign/app.go
@@ -79,6 +79,7 @@ import (
govkeeper "github.com/cosmos/cosmos-sdk/x/gov/keeper"
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
govv1beta1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1"
+
// add mint
mint "github.com/cosmos/cosmos-sdk/x/mint"
mintkeeper "github.com/cosmos/cosmos-sdk/x/mint/keeper"
@@ -105,8 +106,8 @@ import (
"github.com/cometbft/cometbft/libs/log"
tmos "github.com/cometbft/cometbft/libs/os"
- appencoding "github.com/cosmos/interchain-security/v4/app/encoding"
- testutil "github.com/cosmos/interchain-security/v4/testutil/integration"
+ appencoding "github.com/cosmos/interchain-security/v5/app/encoding"
+ testutil "github.com/cosmos/interchain-security/v5/testutil/integration"
)
const (
diff --git a/cmd/interchain-security-cd/cmd/root.go b/cmd/interchain-security-cd/cmd/root.go
index 215b45317a..3d844d9c7c 100644
--- a/cmd/interchain-security-cd/cmd/root.go
+++ b/cmd/interchain-security-cd/cmd/root.go
@@ -31,8 +31,8 @@ import (
tmcfg "github.com/cometbft/cometbft/config"
"github.com/cometbft/cometbft/libs/log"
- consumer "github.com/cosmos/interchain-security/v4/app/consumer"
- appencoding "github.com/cosmos/interchain-security/v4/app/encoding"
+ consumer "github.com/cosmos/interchain-security/v5/app/consumer"
+ appencoding "github.com/cosmos/interchain-security/v5/app/encoding"
)
// NewRootCmd creates a new root command for simd. It is called once in the
diff --git a/cmd/interchain-security-cd/main.go b/cmd/interchain-security-cd/main.go
index a64a2a8645..7cbe0a898a 100644
--- a/cmd/interchain-security-cd/main.go
+++ b/cmd/interchain-security-cd/main.go
@@ -6,9 +6,9 @@ import (
"github.com/cosmos/cosmos-sdk/server"
svrcmd "github.com/cosmos/cosmos-sdk/server/cmd"
- app "github.com/cosmos/interchain-security/v4/app/consumer"
- appparams "github.com/cosmos/interchain-security/v4/app/params"
- "github.com/cosmos/interchain-security/v4/cmd/interchain-security-cd/cmd"
+ app "github.com/cosmos/interchain-security/v5/app/consumer"
+ appparams "github.com/cosmos/interchain-security/v5/app/params"
+ "github.com/cosmos/interchain-security/v5/cmd/interchain-security-cd/cmd"
)
func main() {
diff --git a/cmd/interchain-security-cdd/cmd/root.go b/cmd/interchain-security-cdd/cmd/root.go
index 6b2e6cc726..cb5140ade6 100644
--- a/cmd/interchain-security-cdd/cmd/root.go
+++ b/cmd/interchain-security-cdd/cmd/root.go
@@ -31,8 +31,8 @@ import (
tmcfg "github.com/cometbft/cometbft/config"
"github.com/cometbft/cometbft/libs/log"
- cdd "github.com/cosmos/interchain-security/v4/app/consumer-democracy"
- appencoding "github.com/cosmos/interchain-security/v4/app/encoding"
+ cdd "github.com/cosmos/interchain-security/v5/app/consumer-democracy"
+ appencoding "github.com/cosmos/interchain-security/v5/app/encoding"
)
// NewRootCmd creates a new root command for simd. It is called once in the
diff --git a/cmd/interchain-security-cdd/main.go b/cmd/interchain-security-cdd/main.go
index 9b6aacd759..9fbd09df75 100644
--- a/cmd/interchain-security-cdd/main.go
+++ b/cmd/interchain-security-cdd/main.go
@@ -6,9 +6,9 @@ import (
"github.com/cosmos/cosmos-sdk/server"
svrcmd "github.com/cosmos/cosmos-sdk/server/cmd"
- app "github.com/cosmos/interchain-security/v4/app/consumer-democracy"
- appparams "github.com/cosmos/interchain-security/v4/app/params"
- "github.com/cosmos/interchain-security/v4/cmd/interchain-security-cdd/cmd"
+ app "github.com/cosmos/interchain-security/v5/app/consumer-democracy"
+ appparams "github.com/cosmos/interchain-security/v5/app/params"
+ "github.com/cosmos/interchain-security/v5/cmd/interchain-security-cdd/cmd"
)
func main() {
diff --git a/cmd/interchain-security-pd/cmd/root.go b/cmd/interchain-security-pd/cmd/root.go
index 8a8f5fec32..7f1b0a6b9a 100644
--- a/cmd/interchain-security-pd/cmd/root.go
+++ b/cmd/interchain-security-pd/cmd/root.go
@@ -31,8 +31,8 @@ import (
tmcfg "github.com/cometbft/cometbft/config"
"github.com/cometbft/cometbft/libs/log"
- appencoding "github.com/cosmos/interchain-security/v4/app/encoding"
- providerApp "github.com/cosmos/interchain-security/v4/app/provider"
+ appencoding "github.com/cosmos/interchain-security/v5/app/encoding"
+ providerApp "github.com/cosmos/interchain-security/v5/app/provider"
)
// NewRootCmd creates a new root command for simd. It is called once in the
diff --git a/cmd/interchain-security-pd/main.go b/cmd/interchain-security-pd/main.go
index 7788f06bff..dab89c91fc 100644
--- a/cmd/interchain-security-pd/main.go
+++ b/cmd/interchain-security-pd/main.go
@@ -6,9 +6,9 @@ import (
"github.com/cosmos/cosmos-sdk/server"
svrcmd "github.com/cosmos/cosmos-sdk/server/cmd"
- appparams "github.com/cosmos/interchain-security/v4/app/params"
- app "github.com/cosmos/interchain-security/v4/app/provider"
- "github.com/cosmos/interchain-security/v4/cmd/interchain-security-pd/cmd"
+ appparams "github.com/cosmos/interchain-security/v5/app/params"
+ app "github.com/cosmos/interchain-security/v5/app/provider"
+ "github.com/cosmos/interchain-security/v5/cmd/interchain-security-pd/cmd"
)
func main() {
diff --git a/cmd/interchain-security-sd/cmd/root.go b/cmd/interchain-security-sd/cmd/root.go
index 28520ef1a4..10a79a251a 100644
--- a/cmd/interchain-security-sd/cmd/root.go
+++ b/cmd/interchain-security-sd/cmd/root.go
@@ -31,8 +31,8 @@ import (
tmcfg "github.com/cometbft/cometbft/config"
"github.com/cometbft/cometbft/libs/log"
- appencoding "github.com/cosmos/interchain-security/v4/app/encoding"
- sovereignApp "github.com/cosmos/interchain-security/v4/app/sovereign"
+ appencoding "github.com/cosmos/interchain-security/v5/app/encoding"
+ sovereignApp "github.com/cosmos/interchain-security/v5/app/sovereign"
)
// NewRootCmd creates a new root command for simd. It is called once in the
diff --git a/cmd/interchain-security-sd/main.go b/cmd/interchain-security-sd/main.go
index 2265afad90..e719eb48f3 100644
--- a/cmd/interchain-security-sd/main.go
+++ b/cmd/interchain-security-sd/main.go
@@ -6,9 +6,9 @@ import (
"github.com/cosmos/cosmos-sdk/server"
svrcmd "github.com/cosmos/cosmos-sdk/server/cmd"
- appparams "github.com/cosmos/interchain-security/v4/app/params"
- app "github.com/cosmos/interchain-security/v4/app/sovereign"
- "github.com/cosmos/interchain-security/v4/cmd/interchain-security-sd/cmd"
+ appparams "github.com/cosmos/interchain-security/v5/app/params"
+ app "github.com/cosmos/interchain-security/v5/app/sovereign"
+ "github.com/cosmos/interchain-security/v5/cmd/interchain-security-sd/cmd"
)
func main() {
diff --git a/go.mod b/go.mod
index db8b94586c..4a5ddd9493 100644
--- a/go.mod
+++ b/go.mod
@@ -1,4 +1,4 @@
-module github.com/cosmos/interchain-security/v4
+module github.com/cosmos/interchain-security/v5
go 1.21.1
diff --git a/proto/interchain_security/ccv/consumer/v1/consumer.proto b/proto/interchain_security/ccv/consumer/v1/consumer.proto
index 749eedc7ac..959d06c087 100644
--- a/proto/interchain_security/ccv/consumer/v1/consumer.proto
+++ b/proto/interchain_security/ccv/consumer/v1/consumer.proto
@@ -1,7 +1,7 @@
syntax = "proto3";
package interchain_security.ccv.consumer.v1;
-option go_package = "github.com/cosmos/interchain-security/v4/x/ccv/consumer/types";
+option go_package = "github.com/cosmos/interchain-security/v5/x/ccv/consumer/types";
import "google/protobuf/any.proto";
import "gogoproto/gogo.proto";
diff --git a/proto/interchain_security/ccv/consumer/v1/genesis.proto b/proto/interchain_security/ccv/consumer/v1/genesis.proto
index a2ceb0f9f6..642b78451d 100644
--- a/proto/interchain_security/ccv/consumer/v1/genesis.proto
+++ b/proto/interchain_security/ccv/consumer/v1/genesis.proto
@@ -2,7 +2,7 @@ syntax = "proto3";
package interchain_security.ccv.consumer.v1;
-option go_package = "github.com/cosmos/interchain-security/v4/x/ccv/consumer/types";
+option go_package = "github.com/cosmos/interchain-security/v5/x/ccv/consumer/types";
import "interchain_security/ccv/v1/shared_consumer.proto";
import "ibc/lightclients/tendermint/v1/tendermint.proto";
diff --git a/proto/interchain_security/ccv/consumer/v1/query.proto b/proto/interchain_security/ccv/consumer/v1/query.proto
index eb8eb29a3d..0e9b088e1d 100644
--- a/proto/interchain_security/ccv/consumer/v1/query.proto
+++ b/proto/interchain_security/ccv/consumer/v1/query.proto
@@ -2,7 +2,7 @@ syntax = "proto3";
package interchain_security.ccv.consumer.v1;
import "interchain_security/ccv/v1/shared_consumer.proto";
-option go_package = "github.com/cosmos/interchain-security/v4/x/ccv/consumer/types";
+option go_package = "github.com/cosmos/interchain-security/v5/x/ccv/consumer/types";
import "gogoproto/gogo.proto";
import "google/api/annotations.proto";
diff --git a/proto/interchain_security/ccv/provider/v1/genesis.proto b/proto/interchain_security/ccv/provider/v1/genesis.proto
index 443ea26b32..269743721e 100644
--- a/proto/interchain_security/ccv/provider/v1/genesis.proto
+++ b/proto/interchain_security/ccv/provider/v1/genesis.proto
@@ -2,7 +2,7 @@ syntax = "proto3";
package interchain_security.ccv.provider.v1;
-option go_package = "github.com/cosmos/interchain-security/v4/x/ccv/provider/types";
+option go_package = "github.com/cosmos/interchain-security/v5/x/ccv/provider/types";
import "gogoproto/gogo.proto";
import "interchain_security/ccv/v1/shared_consumer.proto";
diff --git a/proto/interchain_security/ccv/provider/v1/provider.proto b/proto/interchain_security/ccv/provider/v1/provider.proto
index 4da89022e8..068cdc0f06 100644
--- a/proto/interchain_security/ccv/provider/v1/provider.proto
+++ b/proto/interchain_security/ccv/provider/v1/provider.proto
@@ -2,7 +2,7 @@ syntax = "proto3";
package interchain_security.ccv.provider.v1;
-option go_package = "github.com/cosmos/interchain-security/v4/x/ccv/provider/types";
+option go_package = "github.com/cosmos/interchain-security/v5/x/ccv/provider/types";
import "interchain_security/ccv/v1/wire.proto";
import "gogoproto/gogo.proto";
@@ -13,6 +13,8 @@ import "ibc/lightclients/tendermint/v1/tendermint.proto";
import "tendermint/crypto/keys.proto";
import "cosmos/evidence/v1beta1/evidence.proto";
import "cosmos/base/v1beta1/coin.proto";
+import "amino/amino.proto";
+
//
// Note any type defined in this file is ONLY used internally to the provider CCV module.
@@ -83,6 +85,25 @@ message ConsumerAdditionProposal {
// chain. it is most relevant for chains performing a sovereign to consumer
// changeover in order to maintain the existing ibc transfer channel
string distribution_transmission_channel = 14;
+ // Corresponds to the percentage of validators that have to validate the chain under the Top N case.
+ // For example, 53 corresponds to a Top 53% chain, meaning that the top 53% provider validators by voting power
+ // have to validate the proposed consumer chain. top_N can either be 0 or any value in [50, 100].
+ // A chain can join with top_N == 0 as an Opt In chain, or with top_N ∈ [50, 100] as a Top N chain.
+ uint32 top_N = 15;
+ // Corresponds to the maximum power (percentage-wise) a validator can have on the consumer chain. For instance, if
+ // `validators_power_cap` is set to 32, it means that no validator can have more than 32% of the voting power on the
+ // consumer chain. Note that this might not be feasible. For example, think of a consumer chain with only
+ // 5 validators and with `validators_power_cap` set to 10%. In such a scenario, at least one validator would need
+ // to have more than 20% of the total voting power. Therefore, `validators_power_cap` operates on a best-effort basis.
+ uint32 validators_power_cap = 16;
+ // Corresponds to the maximum number of validators that can validate a consumer chain.
+ // Only applicable to Opt In chains. Setting `validator_set_cap` on a Top N chain is a no-op.
+ uint32 validator_set_cap = 17;
+ // Corresponds to a list of provider consensus addresses of validators that are the ONLY ones that can validate
+ // the consumer chain.
+ repeated string allowlist = 18;
+ // Corresponds to a list of provider consensus addresses of validators that CANNOT validate the consumer chain.
+ repeated string denylist = 19;
}
// ConsumerRemovalProposal is a governance proposal on the provider chain to
@@ -308,4 +329,14 @@ message ConsumerValidator {
int64 power = 2;
// public key the validator uses on the consumer chain during this epoch
tendermint.crypto.PublicKey consumer_public_key = 3;
-}
\ No newline at end of file
+}
+// ConsumerRewardsAllocation stores the rewards allocated by a consumer chain
+// to the consumer rewards pool. It is used to allocate the tokens to the consumer
+// opted-in validators and the community pool during BeginBlock.
+message ConsumerRewardsAllocation {
+ repeated cosmos.base.v1beta1.DecCoin rewards = 1 [
+ (gogoproto.nullable) = false,
+ (amino.dont_omitempty) = true,
+ (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.DecCoins"
+ ];
+}
diff --git a/proto/interchain_security/ccv/provider/v1/query.proto b/proto/interchain_security/ccv/provider/v1/query.proto
index 14a5ce41f6..f6d5d5a379 100644
--- a/proto/interchain_security/ccv/provider/v1/query.proto
+++ b/proto/interchain_security/ccv/provider/v1/query.proto
@@ -1,7 +1,7 @@
syntax = "proto3";
package interchain_security.ccv.provider.v1;
-option go_package = "github.com/cosmos/interchain-security/v4/x/ccv/provider/types";
+option go_package = "github.com/cosmos/interchain-security/v5/x/ccv/provider/types";
import "google/api/annotations.proto";
import "gogoproto/gogo.proto";
@@ -10,6 +10,7 @@ import "interchain_security/ccv/provider/v1/provider.proto";
import "interchain_security/ccv/v1/shared_consumer.proto";
import "interchain_security/ccv/v1/wire.proto";
import "tendermint/crypto/keys.proto";
+import "cosmos_proto/cosmos.proto";
service Query {
// ConsumerGenesis queries the genesis state needed to start a consumer chain
@@ -100,6 +101,33 @@ service Query {
"/interchain_security/ccv/provider/params";
}
+ // QueryConsumerChainOptedInValidators returns a list of validators consensus addresses
+ // that opted-in to the given consumer chain
+ rpc QueryConsumerChainOptedInValidators(
+ QueryConsumerChainOptedInValidatorsRequest)
+ returns (QueryConsumerChainOptedInValidatorsResponse) {
+ option (google.api.http).get =
+ "/interchain_security/ccv/provider/opted_in_validators/{chain_id}";
+ }
+
+ // QueryConsumerChainsValidatorHasToValidate returns a list of consumer chains
+ // that a given validator must validate
+ rpc QueryConsumerChainsValidatorHasToValidate(
+ QueryConsumerChainsValidatorHasToValidateRequest)
+ returns (QueryConsumerChainsValidatorHasToValidateResponse) {
+ option (google.api.http).get =
+ "/interchain_security/ccv/provider/consumer_chains_per_validator/{provider_address}";
+ }
+
+ // QueryValidatorConsumerCommissionRate returns the commission rate a given
+ // validator charges on a given consumer chain
+ rpc QueryValidatorConsumerCommissionRate(
+ QueryValidatorConsumerCommissionRateRequest)
+ returns (QueryValidatorConsumerCommissionRateResponse) {
+ option (google.api.http).get =
+ "/interchain_security/ccv/provider/consumer_commission_rate/{chain_id}/{provider_address}";
+ }
+
// QueryOldestUnconfirmedVsc returns the send timestamp of the oldest unconfirmed VSCPacket for a given chainID
rpc QueryOldestUnconfirmedVsc(QueryOldestUnconfirmedVscRequest)
returns (QueryOldestUnconfirmedVscResponse) {
@@ -134,6 +162,8 @@ message QueryConsumerChainStopProposalsResponse {
message Chain {
string chain_id = 1;
string client_id = 2;
+ // If chain with `chainID` is a Top-N chain, i.e., enforces at least one validator to validate chain `chainID`
+ uint32 top_N = 3;
}
message QueryValidatorConsumerAddrRequest {
@@ -219,9 +249,44 @@ message QueryParamsResponse {
Params params = 1 [(gogoproto.nullable) = false];
}
+
+message QueryConsumerChainOptedInValidatorsRequest {
+ string chain_id = 1;
+}
+
+message QueryConsumerChainOptedInValidatorsResponse {
+ // The consensus addresses of the validators on the provider chain
+ repeated string validators_provider_addresses = 1;
+}
+
+
+message QueryConsumerChainsValidatorHasToValidateRequest {
+ // The consensus address of the validator on the provider chain
+ string provider_address = 1 [ (gogoproto.moretags) = "yaml:\"address\"" ];
+}
+
+message QueryConsumerChainsValidatorHasToValidateResponse {
+ repeated string consumer_chain_ids = 1;
+}
+
+message QueryValidatorConsumerCommissionRateRequest {
+ string chain_id = 1;
+ // The consensus address of the validator on the provider chain
+ string provider_address = 2 [ (gogoproto.moretags) = "yaml:\"address\"" ];
+}
+
+message QueryValidatorConsumerCommissionRateResponse {
+ // The rate to charge delegators on the consumer chain, as a fraction
+ string rate = 1 [
+ (cosmos_proto.scalar) = "cosmos.Dec",
+ (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec",
+ (gogoproto.nullable) = false
+ ];
+}
+
message QueryOldestUnconfirmedVscRequest { string chain_id = 1; }
message QueryOldestUnconfirmedVscResponse {
interchain_security.ccv.provider.v1.VscSendTimestamp vsc_send_timestamp = 1
[ (gogoproto.nullable) = false ];
-}
\ No newline at end of file
+}
diff --git a/proto/interchain_security/ccv/provider/v1/tx.proto b/proto/interchain_security/ccv/provider/v1/tx.proto
index 3294807015..02a69d25f9 100644
--- a/proto/interchain_security/ccv/provider/v1/tx.proto
+++ b/proto/interchain_security/ccv/provider/v1/tx.proto
@@ -1,7 +1,7 @@
syntax = "proto3";
package interchain_security.ccv.provider.v1;
-option go_package = "github.com/cosmos/interchain-security/v4/x/ccv/provider/types";
+option go_package = "github.com/cosmos/interchain-security/v5/x/ccv/provider/types";
import "gogoproto/gogo.proto";
import "cosmos_proto/cosmos.proto";
@@ -15,6 +15,9 @@ service Msg {
rpc AssignConsumerKey(MsgAssignConsumerKey) returns (MsgAssignConsumerKeyResponse);
rpc SubmitConsumerMisbehaviour(MsgSubmitConsumerMisbehaviour) returns (MsgSubmitConsumerMisbehaviourResponse);
rpc SubmitConsumerDoubleVoting(MsgSubmitConsumerDoubleVoting) returns (MsgSubmitConsumerDoubleVotingResponse);
+ rpc OptIn(MsgOptIn) returns (MsgOptInResponse);
+ rpc OptOut(MsgOptOut) returns (MsgOptOutResponse);
+ rpc SetConsumerCommissionRate(MsgSetConsumerCommissionRate) returns (MsgSetConsumerCommissionRateResponse);
}
message MsgAssignConsumerKey {
@@ -61,3 +64,50 @@ message MsgSubmitConsumerDoubleVoting {
}
message MsgSubmitConsumerDoubleVotingResponse {}
+
+message MsgOptIn {
+ option (gogoproto.equal) = false;
+ option (gogoproto.goproto_getters) = false;
+ // the chain id of the consumer chain to opt in to
+ string chain_id = 1;
+ // the validator address on the provider
+ string provider_addr = 2 [ (gogoproto.moretags) = "yaml:\"address\"" ];
+ // (optional) The consensus public key to use on the consumer in json string format corresponding to proto-any,
+ // for example `{"@type":"/cosmos.crypto.ed25519.PubKey","key":"Ui5Gf1+mtWUdH8u3xlmzdKID+F3PK0sfXZ73GZ6q6is="}`.
+ // This field is optional and can remain empty (i.e., `consumer_key = ""`). A validator can always change the
+ // consumer public key at a later stage by issuing a `MsgAssignConsumerKey` message.
+ string consumer_key = 3;
+}
+
+message MsgOptInResponse {}
+
+message MsgOptOut {
+ option (gogoproto.equal) = false;
+ option (gogoproto.goproto_getters) = false;
+ // the chain id of the consumer chain to opt out from
+ string chain_id = 1;
+ // the validator address on the provider
+ string provider_addr = 2 [ (gogoproto.moretags) = "yaml:\"address\"" ];
+}
+
+message MsgOptOutResponse {}
+
+// MsgSetConsumerCommissionRate allows validators to set
+// a per-consumer chain commission rate
+message MsgSetConsumerCommissionRate {
+ option (gogoproto.equal) = false;
+ option (gogoproto.goproto_getters) = false;
+ // The validator address on the provider
+ string provider_addr = 1 [ (gogoproto.moretags) = "yaml:\"address\"" ];
+ // The chain id of the consumer chain to set a commission rate
+ string chain_id = 2;
+ // The rate to charge delegators on the consumer chain, as a fraction
+ string rate = 3 [
+ (cosmos_proto.scalar) = "cosmos.Dec",
+ (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec",
+ (gogoproto.nullable) = false
+ ];
+}
+
+
+message MsgSetConsumerCommissionRateResponse {}
diff --git a/proto/interchain_security/ccv/v1/shared_consumer.proto b/proto/interchain_security/ccv/v1/shared_consumer.proto
index d1f0a5d5a3..ce65df04a6 100644
--- a/proto/interchain_security/ccv/v1/shared_consumer.proto
+++ b/proto/interchain_security/ccv/v1/shared_consumer.proto
@@ -2,7 +2,7 @@ syntax = "proto3";
package interchain_security.ccv.v1;
-option go_package = "github.com/cosmos/interchain-security/v4/x/ccv/types";
+option go_package = "github.com/cosmos/interchain-security/v5/x/ccv/types";
import "tendermint/abci/types.proto";
import "ibc/lightclients/tendermint/v1/tendermint.proto";
diff --git a/proto/interchain_security/ccv/v1/wire.proto b/proto/interchain_security/ccv/v1/wire.proto
index 7382b9d0da..f0ba6ab41a 100644
--- a/proto/interchain_security/ccv/v1/wire.proto
+++ b/proto/interchain_security/ccv/v1/wire.proto
@@ -2,7 +2,7 @@ syntax = "proto3";
package interchain_security.ccv.v1;
-option go_package = "github.com/cosmos/interchain-security/v4/x/ccv/types";
+option go_package = "github.com/cosmos/interchain-security/v5/x/ccv/types";
import "cosmos/staking/v1beta1/staking.proto";
diff --git a/scripts/protocgen.sh b/scripts/protocgen.sh
index 67ae158143..fdf6a894c1 100644
--- a/scripts/protocgen.sh
+++ b/scripts/protocgen.sh
@@ -16,6 +16,6 @@ done
cd ..
# move proto files to the right places
-cp -r github.com/cosmos/interchain-security/v4/* ./
+cp -r github.com/cosmos/interchain-security/v5/* ./
rm -rf github.com
diff --git a/tests/e2e/actions.go b/tests/e2e/actions.go
index 172ac70432..31813efd27 100644
--- a/tests/e2e/actions.go
+++ b/tests/e2e/actions.go
@@ -19,9 +19,9 @@ import (
"github.com/tidwall/gjson"
"golang.org/x/mod/semver"
- "github.com/cosmos/interchain-security/v4/x/ccv/provider/client"
- "github.com/cosmos/interchain-security/v4/x/ccv/provider/types"
- ccvtypes "github.com/cosmos/interchain-security/v4/x/ccv/types"
+ "github.com/cosmos/interchain-security/v5/x/ccv/provider/client"
+ "github.com/cosmos/interchain-security/v5/x/ccv/provider/types"
+ ccvtypes "github.com/cosmos/interchain-security/v5/x/ccv/types"
)
const (
@@ -260,6 +260,7 @@ type SubmitConsumerAdditionProposalAction struct {
SpawnTime uint
InitialHeight clienttypes.Height
DistributionChannel string
+ TopN uint32
}
func (tr TestConfig) submitConsumerAdditionProposal(
@@ -285,6 +286,7 @@ func (tr TestConfig) submitConsumerAdditionProposal(
UnbondingPeriod: params.UnbondingPeriod,
Deposit: fmt.Sprint(action.Deposit) + `stake`,
DistributionTransmissionChannel: action.DistributionChannel,
+ TopN: action.TopN,
}
bz, err := json.Marshal(prop)
@@ -298,9 +300,15 @@ func (tr TestConfig) submitConsumerAdditionProposal(
}
//#nosec G204 -- bypass unsafe quoting warning (no production code)
- bz, err = target.ExecCommand(
+ cmd := target.ExecCommand(
"/bin/bash", "-c", fmt.Sprintf(`echo '%s' > %s`, jsonStr, "/temp-proposal.json"),
- ).CombinedOutput()
+ )
+ bz, err = cmd.CombinedOutput()
+
+ if verbose {
+ log.Println("submitConsumerAdditionProposal cmd: ", cmd.String())
+ }
+
if err != nil {
log.Fatal(err, "\n", string(bz))
}
@@ -1498,11 +1506,9 @@ func (tr TestConfig) delegateTokens(
}
cmd := target.ExecCommand(tr.chainConfigs[action.Chain].BinaryName,
-
"tx", "staking", "delegate",
validatorAddress,
fmt.Sprint(action.Amount)+`stake`,
-
`--from`, `validator`+fmt.Sprint(action.From),
`--chain-id`, string(tr.chainConfigs[action.Chain].ChainId),
`--home`, tr.getValidatorHome(action.Chain, action.From),
@@ -1689,7 +1695,6 @@ func (tr TestConfig) redelegateTokens(action RedelegateTokensAction, target Exec
cmd := target.ExecCommand(
tr.chainConfigs[action.Chain].BinaryName,
-
"tx", "staking", "redelegate",
redelegateSrc,
redelegateDst,
@@ -2264,6 +2269,109 @@ func (tc TestConfig) startConsumerEvidenceDetector(
tc.waitBlocks("provi", 10, 2*time.Minute)
}
+type OptInAction struct {
+ Chain ChainID
+ Validator ValidatorID
+}
+
+func (tr TestConfig) optIn(action OptInAction, target ExecutionTarget, verbose bool) {
+ // Note: to get error response reported back from this command '--gas auto' needs to be set.
+ gas := "auto"
+ // Unfortunately, --gas auto does not work with CometMock. so when using CometMock, just use --gas 9000000 then
+ if tr.useCometmock {
+ gas = "9000000"
+ }
+
+ // Use: "opt-in [consumer-chain-id] [consumer-pubkey]",
+ optIn := fmt.Sprintf(
+ `%s tx provider opt-in %s --from validator%s --chain-id %s --home %s --node %s --gas %s --keyring-backend test -y -o json`,
+ tr.chainConfigs[ChainID("provi")].BinaryName,
+ string(tr.chainConfigs[action.Chain].ChainId),
+ action.Validator,
+ tr.chainConfigs[ChainID("provi")].ChainId,
+ tr.getValidatorHome(ChainID("provi"), action.Validator),
+ tr.getValidatorNode(ChainID("provi"), action.Validator),
+ gas,
+ )
+
+ cmd := target.ExecCommand(
+ "/bin/bash", "-c",
+ optIn,
+ )
+
+ if verbose {
+ fmt.Println("optIn cmd:", cmd.String())
+ }
+
+ bz, err := cmd.CombinedOutput()
+ if err != nil {
+ log.Fatal(err, "\n", string(bz))
+ }
+
+ if !tr.useCometmock { // error report only works with --gas auto, which does not work with CometMock, so ignore
+ if err != nil && verbose {
+ fmt.Printf("got error during opt in | err: %s | output: %s \n", err, string(bz))
+ }
+ }
+
+ // wait for inclusion in a block -> '--broadcast-mode block' is deprecated
+ tr.waitBlocks(ChainID("provi"), 2, 30*time.Second)
+}
+
+type OptOutAction struct {
+ Chain ChainID
+ Validator ValidatorID
+ ExpectError bool
+}
+
+func (tr TestConfig) optOut(action OptOutAction, target ExecutionTarget, verbose bool) {
+ // Note: to get error response reported back from this command '--gas auto' needs to be set.
+ gas := "auto"
+ // Unfortunately, --gas auto does not work with CometMock. so when using CometMock, just use --gas 9000000 then
+ if tr.useCometmock {
+ gas = "9000000"
+ }
+
+ // Use: "opt-out [consumer-chain-id]",
+ optIn := fmt.Sprintf(
+ `%s tx provider opt-out %s --from validator%s --chain-id %s --home %s --node %s --gas %s --keyring-backend test -y -o json`,
+ tr.chainConfigs[ChainID("provi")].BinaryName,
+ string(tr.chainConfigs[action.Chain].ChainId),
+ action.Validator,
+ tr.chainConfigs[ChainID("provi")].ChainId,
+ tr.getValidatorHome(ChainID("provi"), action.Validator),
+ tr.getValidatorNode(ChainID("provi"), action.Validator),
+ gas,
+ )
+
+ cmd := target.ExecCommand(
+ "/bin/bash", "-c",
+ optIn,
+ )
+
+ if verbose {
+ fmt.Println("optOut cmd:", cmd.String())
+ }
+
+ bz, err := cmd.CombinedOutput()
+ if action.ExpectError {
+ if err != nil {
+ if verbose {
+ fmt.Printf("got expected error during opt out | err: %s | output: %s \n", err, string(bz))
+ }
+ } else {
+ log.Fatal("expected error during opt-out but got none")
+ }
+ } else {
+ if err != nil {
+ log.Fatal(err, "\n", string(bz))
+ }
+ }
+
+ // wait for inclusion in a block -> '--broadcast-mode block' is deprecated
+ tr.waitBlocks(ChainID("provi"), 2, 30*time.Second)
+}
+
// WaitTime waits for the given duration.
// To make sure that the new timestamp is visible on-chain, it also waits until at least one block has been
// produced on each chain after waiting.
diff --git a/tests/e2e/builder.go b/tests/e2e/builder.go
index 26eb5c34f6..e9e0f00d5a 100644
--- a/tests/e2e/builder.go
+++ b/tests/e2e/builder.go
@@ -82,7 +82,6 @@ func generateImageName(version string, cfg TargetConfig) (string, error) {
tagName = "local" // this refers to build from local workspace
} else {
// use git hash of rev as docker image tag
- // cmd := exec.Command("git", "rev-parse", "--verify", "--short", version)
cmd := exec.Command("git", "log", "--pretty=format:%h", "-n", "1", version)
out, err := cmd.CombinedOutput()
if err != nil {
diff --git a/tests/e2e/main.go b/tests/e2e/main.go
index 83a41a0342..c1766ccf37 100644
--- a/tests/e2e/main.go
+++ b/tests/e2e/main.go
@@ -156,6 +156,18 @@ var stepChoices = map[string]StepChoice{
description: `Minimal set of test steps to perform compatibility tests`,
testConfig: CompatibilityTestCfg,
},
+ "partial-set-security-opt-in": {
+ name: "partial-set-security-opt-in",
+ steps: stepsOptInChain(),
+ description: "test partial set security for an Opt-In chain",
+ testConfig: DefaultTestCfg,
+ },
+ "partial-set-security-top-n": {
+ name: "partial-set-security-top-n",
+ steps: stepsTopNChain(),
+ description: "test partial set security for a Top-N chain",
+ testConfig: DefaultTestCfg,
+ },
}
func getTestCaseUsageString() string {
@@ -241,7 +253,7 @@ func getTestCases(selectedPredefinedTests, selectedTestFiles TestSet, providerVe
"changeover", "happy-path",
"democracy-reward", "democracy",
"slash-throttle", "consumer-double-sign", "consumer-misbehaviour",
- "consumer-double-downtime",
+ "consumer-double-downtime", "partial-set-security-opt-in", "partial-set-security-top-n",
}
if includeMultiConsumer != nil && *includeMultiConsumer {
selectedPredefinedTests = append(selectedPredefinedTests, "multiconsumer")
diff --git a/tests/e2e/state.go b/tests/e2e/state.go
index 91379a0705..7b674b0df8 100644
--- a/tests/e2e/state.go
+++ b/tests/e2e/state.go
@@ -31,6 +31,7 @@ type ChainState struct {
ConsumerPendingPacketQueueSize *uint // Only relevant to consumer chains
RegisteredConsumerRewardDenoms *[]string
ClientsFrozenHeights *map[string]clienttypes.Height
+ HasToValidate *map[ValidatorID][]ChainID // only relevant to provider chain
}
type Proposal interface {
@@ -180,6 +181,14 @@ func (tr TestConfig) getChainState(chain ChainID, modelState ChainState) ChainSt
chainState.ClientsFrozenHeights = &chainClientsFrozenHeights
}
+ if modelState.HasToValidate != nil {
+ hasToValidate := map[ValidatorID][]ChainID{}
+ for validatorId := range *modelState.HasToValidate {
+ hasToValidate[validatorId] = tr.getHasToValidate(validatorId)
+ }
+ chainState.HasToValidate = &hasToValidate
+ }
+
if modelState.ConsumerPendingPacketQueueSize != nil {
pendingPacketQueueSize := tr.getPendingPacketQueueSize(chain)
chainState.ConsumerPendingPacketQueueSize = &pendingPacketQueueSize
@@ -833,6 +842,29 @@ func (tc TestConfig) getClientFrozenHeight(chain ChainID, clientID string) clien
return clienttypes.Height{RevisionHeight: uint64(revHeight), RevisionNumber: uint64(revNumber)}
}
+func (tr TestConfig) getHasToValidate(
+ validatorId ValidatorID,
+) []ChainID {
+ //#nosec G204 -- Bypass linter warning for spawning subprocess with cmd arguments.
+ bz, err := exec.Command("docker", "exec", tr.containerConfig.InstanceName, tr.chainConfigs[ChainID("provi")].BinaryName,
+ "query", "provider", "has-to-validate",
+ tr.validatorConfigs[validatorId].ValconsAddress,
+ `--node`, tr.getQueryNode(ChainID("provi")),
+ `-o`, `json`,
+ ).CombinedOutput()
+ if err != nil {
+ log.Fatal(err, "\n", string(bz))
+ }
+
+ arr := gjson.Get(string(bz), "consumer_chain_ids").Array()
+ chains := []ChainID{}
+ for _, c := range arr {
+ chains = append(chains, ChainID(c.String()))
+ }
+
+ return chains
+}
+
func (tc TestConfig) getTrustedHeight(
chain ChainID,
clientID string,
diff --git a/tests/e2e/steps_compatibility.go b/tests/e2e/steps_compatibility.go
index 89e80f3600..c6bc3c88b1 100644
--- a/tests/e2e/steps_compatibility.go
+++ b/tests/e2e/steps_compatibility.go
@@ -41,6 +41,7 @@ func compstepsStartConsumerChain(consumerName string, proposalIndex, chainIndex
ConsumerChain: ChainID(consumerName),
SpawnTime: 0,
InitialHeight: clienttypes.Height{RevisionNumber: 0, RevisionHeight: 1},
+ TopN: 100,
},
State: State{
ChainID("provi"): ChainState{
@@ -85,18 +86,6 @@ func compstepsStartConsumerChain(consumerName string, proposalIndex, chainIndex
},
},
},
- {
- // op should fail - key already assigned by the same validator
- Action: AssignConsumerPubKeyAction{
- Chain: ChainID(consumerName),
- Validator: ValidatorID("carol"),
- ConsumerPubkey: getDefaultValidators()[ValidatorID("carol")].ConsumerValPubKey,
- ReconfigureNode: false,
- ExpectError: true,
- ExpectedError: "a validator has assigned the consumer key already: consumer key is already in use by a validator",
- },
- State: State{},
- },
{
// op should fail - key already assigned by another validator
Action: AssignConsumerPubKeyAction{
diff --git a/tests/e2e/steps_consumer_misbehaviour.go b/tests/e2e/steps_consumer_misbehaviour.go
index 3cb4ce0f1b..bd6e3f1d3c 100644
--- a/tests/e2e/steps_consumer_misbehaviour.go
+++ b/tests/e2e/steps_consumer_misbehaviour.go
@@ -36,6 +36,7 @@ func stepsStartChainsWithSoftOptOut(consumerName string) []Step {
ConsumerChain: ChainID(consumerName),
SpawnTime: 0,
InitialHeight: clienttypes.Height{RevisionNumber: 0, RevisionHeight: 1},
+ TopN: 100,
},
State: State{
ChainID("provi"): ChainState{
diff --git a/tests/e2e/steps_partial_set_security.go b/tests/e2e/steps_partial_set_security.go
new file mode 100644
index 0000000000..4c63e479df
--- /dev/null
+++ b/tests/e2e/steps_partial_set_security.go
@@ -0,0 +1,1002 @@
+package main
+
+import clienttypes "github.com/cosmos/ibc-go/v7/modules/core/02-client/types"
+
+// stepsOptInChain starts a provider chain and an Opt-In chain and opts in and out validators
+func stepsOptInChain() []Step {
+ s := []Step{
+ {
+ Action: StartChainAction{
+ Chain: ChainID("provi"),
+ Validators: []StartChainValidator{
+ {Id: ValidatorID("alice"), Stake: 100000000, Allocation: 10000000000},
+ {Id: ValidatorID("bob"), Stake: 200000000, Allocation: 10000000000},
+ {Id: ValidatorID("carol"), Stake: 300000000, Allocation: 10000000000},
+ },
+ },
+ State: State{
+ ChainID("provi"): ChainState{
+ ValPowers: &map[ValidatorID]uint{
+ ValidatorID("alice"): 100,
+ ValidatorID("bob"): 200,
+ ValidatorID("carol"): 300,
+ },
+ },
+ },
+ },
+ {
+ Action: SubmitConsumerAdditionProposalAction{
+ Chain: ChainID("provi"),
+ From: ValidatorID("alice"),
+ Deposit: 10000001,
+ ConsumerChain: ChainID("consu"),
+ SpawnTime: 0,
+ InitialHeight: clienttypes.Height{RevisionNumber: 0, RevisionHeight: 1},
+ TopN: 0,
+ },
+ State: State{
+ ChainID("provi"): ChainState{
+ Proposals: &map[uint]Proposal{
+ 1: ConsumerAdditionProposal{
+ Deposit: 10000001,
+ Chain: ChainID("consu"),
+ SpawnTime: 0,
+ InitialHeight: clienttypes.Height{RevisionNumber: 0, RevisionHeight: 1},
+ Status: "PROPOSAL_STATUS_VOTING_PERIOD",
+ },
+ },
+ HasToValidate: &map[ValidatorID][]ChainID{
+ ValidatorID("alice"): {},
+ ValidatorID("bob"): {},
+ ValidatorID("carol"): {},
+ },
+ },
+ },
+ },
+ // Οpt in "alice" and "bob" so the chain is not empty when it is about to start. Note, that "alice" and "bob" use
+ // the provider's public key (see `UseConsumerKey` is set to `false` in `getDefaultValidators`) and hence do not
+ // need a consumer-key assigment.
+ {
+ Action: OptInAction{
+ Chain: ChainID("consu"),
+ Validator: ValidatorID("alice"),
+ },
+ State: State{
+ ChainID("provi"): ChainState{
+ HasToValidate: &map[ValidatorID][]ChainID{
+ ValidatorID("alice"): {}, // chain is not running yet
+ ValidatorID("bob"): {},
+ ValidatorID("carol"): {},
+ },
+ },
+ },
+ },
+ {
+ Action: OptInAction{
+ Chain: ChainID("consu"),
+ Validator: ValidatorID("bob"),
+ },
+ State: State{
+ ChainID("provi"): ChainState{
+ HasToValidate: &map[ValidatorID][]ChainID{
+ ValidatorID("alice"): {},
+ ValidatorID("bob"): {},
+ ValidatorID("carol"): {},
+ },
+ },
+ },
+ },
+ {
+ Action: VoteGovProposalAction{
+ Chain: ChainID("provi"),
+ From: []ValidatorID{ValidatorID("alice"), ValidatorID("bob")},
+ Vote: []string{"yes", "yes"},
+ PropNumber: 1,
+ },
+ State: State{
+ ChainID("provi"): ChainState{
+ Proposals: &map[uint]Proposal{
+ 1: ConsumerAdditionProposal{
+ Deposit: 10000001,
+ Chain: ChainID("consu"),
+ SpawnTime: 0,
+ InitialHeight: clienttypes.Height{RevisionNumber: 0, RevisionHeight: 1},
+ Status: "PROPOSAL_STATUS_PASSED",
+ },
+ },
+ },
+ },
+ },
+ {
+ // we start all the validators but only "alice" and "bob" have opted in and hence
+ // only "alice" and "bob" are validating blocks
+ Action: StartConsumerChainAction{
+ ConsumerChain: ChainID("consu"),
+ ProviderChain: ChainID("provi"),
+ Validators: []StartChainValidator{
+ {Id: ValidatorID("alice"), Stake: 100000000, Allocation: 10000000000},
+ {Id: ValidatorID("bob"), Stake: 200000000, Allocation: 10000000000},
+ {Id: ValidatorID("carol"), Stake: 300000000, Allocation: 10000000000},
+ },
+ // For consumers that're launching with the provider being on an earlier version
+ // of ICS before the soft opt-out threshold was introduced, we need to set the
+ // soft opt-out threshold to 0.05 in the consumer genesis to ensure that the
+ // consumer binary doesn't panic. Sdk requires that all params are set to valid
+ // values from the genesis file.
+ GenesisChanges: ".app_state.ccvconsumer.params.soft_opt_out_threshold = \"0.05\"",
+ },
+ State: State{
+ ChainID("consu"): ChainState{
+ ValPowers: &map[ValidatorID]uint{
+ ValidatorID("alice"): 100,
+ ValidatorID("bob"): 200,
+ // carol has not yet opted in
+ ValidatorID("carol"): 0,
+ },
+ },
+ },
+ },
+ {
+ Action: AddIbcConnectionAction{
+ ChainA: ChainID("consu"),
+ ChainB: ChainID("provi"),
+ ClientA: 0,
+ ClientB: 0,
+ },
+ State: State{},
+ },
+ {
+ Action: AddIbcChannelAction{
+ ChainA: ChainID("consu"),
+ ChainB: ChainID("provi"),
+ ConnectionA: 0,
+ PortA: "consumer",
+ PortB: "provider",
+ Order: "ordered",
+ },
+ State: State{},
+ },
+ {
+ Action: OptInAction{
+ Chain: ChainID("consu"),
+ Validator: ValidatorID("carol"),
+ },
+ State: State{
+ ChainID("consu"): ChainState{
+ ValPowers: &map[ValidatorID]uint{
+ ValidatorID("alice"): 100,
+ ValidatorID("bob"): 200,
+ // "carol" has opted in, but the VSCPacket capturing the opt-in was not relayed yet
+ ValidatorID("carol"): 0,
+ },
+ },
+ ChainID("provi"): ChainState{
+ HasToValidate: &map[ValidatorID][]ChainID{
+ ValidatorID("alice"): {"consu"},
+ ValidatorID("bob"): {"consu"},
+ ValidatorID("carol"): {"consu"},
+ },
+ },
+ },
+ },
+ {
+ // assign the consumer key "carol" is using on the consumer chain to be the one "carol" uses when opting in
+ Action: AssignConsumerPubKeyAction{
+ Chain: ChainID("consu"),
+ Validator: ValidatorID("carol"),
+ // reconfigure the node -> validator was using provider key
+ // until this point -> key matches config.consumerValPubKey for "carol"
+ ConsumerPubkey: getDefaultValidators()[ValidatorID("carol")].ConsumerValPubKey,
+ ReconfigureNode: true,
+ },
+ State: State{},
+ },
+ {
+ Action: RelayPacketsAction{
+ ChainA: ChainID("provi"),
+ ChainB: ChainID("consu"),
+ Port: "provider",
+ Channel: 0,
+ },
+ State: State{
+ ChainID("consu"): ChainState{
+ ValPowers: &map[ValidatorID]uint{
+ ValidatorID("alice"): 100,
+ ValidatorID("bob"): 200,
+ // carol has now opted in
+ ValidatorID("carol"): 300,
+ },
+ },
+ ChainID("provi"): ChainState{
+ HasToValidate: &map[ValidatorID][]ChainID{
+ ValidatorID("alice"): {"consu"},
+ ValidatorID("bob"): {"consu"},
+ ValidatorID("carol"): {"consu"},
+ },
+ },
+ },
+ },
+ {
+ Action: OptOutAction{
+ Chain: ChainID("consu"),
+ Validator: ValidatorID("bob"),
+ },
+ State: State{
+ ChainID("consu"): ChainState{
+ ValPowers: &map[ValidatorID]uint{
+ ValidatorID("alice"): 100,
+ // "bob" has not yet opted out from the consumer chain because the VSCPacket has not yet been relayed
+ ValidatorID("bob"): 200,
+ ValidatorID("carol"): 300,
+ },
+ },
+ },
+ },
+ {
+ Action: RelayPacketsAction{
+ ChainA: ChainID("provi"),
+ ChainB: ChainID("consu"),
+ Port: "provider",
+ Channel: 0,
+ },
+ State: State{
+ ChainID("consu"): ChainState{
+ ValPowers: &map[ValidatorID]uint{
+ ValidatorID("alice"): 100,
+ // bob has now opted out
+ ValidatorID("bob"): 0,
+ ValidatorID("carol"): 300,
+ },
+ },
+ ChainID("provi"): ChainState{
+ HasToValidate: &map[ValidatorID][]ChainID{
+ ValidatorID("alice"): {"consu"},
+ ValidatorID("bob"): {},
+ ValidatorID("carol"): {"consu"},
+ },
+ },
+ },
+ },
+ {
+ // re opt-in "bob"
+ Action: OptInAction{
+ Chain: ChainID("consu"),
+ Validator: ValidatorID("bob"),
+ },
+ State: State{
+ ChainID("consu"): ChainState{
+ ValPowers: &map[ValidatorID]uint{
+ ValidatorID("alice"): 100,
+ // "bob" has not yet been opted in to the consumer chain because the VSCPacket has not yet been relayed
+ ValidatorID("bob"): 0,
+ ValidatorID("carol"): 300,
+ },
+ HasToValidate: &map[ValidatorID][]ChainID{
+ ValidatorID("alice"): {"consu"},
+ ValidatorID("bob"): {"consu"}, // but has to validate is true because bob opted in on the provider
+ ValidatorID("carol"): {"consu"},
+ },
+ },
+ },
+ },
+ {
+ Action: RelayPacketsAction{
+ ChainA: ChainID("provi"),
+ ChainB: ChainID("consu"),
+ Port: "provider",
+ Channel: 0,
+ },
+ State: State{
+ ChainID("consu"): ChainState{
+ ValPowers: &map[ValidatorID]uint{
+ ValidatorID("alice"): 100,
+ // bob is in power on the consumer
+ ValidatorID("bob"): 200,
+ ValidatorID("carol"): 300,
+ },
+ },
+ },
+ },
+ {
+ // DowntimeSlash for alice on consumer
+ Action: DowntimeSlashAction{
+ Chain: ChainID("consu"),
+ Validator: ValidatorID("alice"),
+ },
+ // powers are not affected yet on either chain
+ State: State{
+ ChainID("consu"): ChainState{
+ ValPowers: &map[ValidatorID]uint{
+ ValidatorID("alice"): 100,
+ ValidatorID("bob"): 200,
+ ValidatorID("carol"): 300,
+ },
+ },
+ ChainID("provi"): ChainState{
+ ValPowers: &map[ValidatorID]uint{
+ ValidatorID("alice"): 100,
+ ValidatorID("bob"): 200,
+ ValidatorID("carol"): 300,
+ },
+ HasToValidate: &map[ValidatorID][]ChainID{
+ ValidatorID("alice"): {"consu"},
+ ValidatorID("bob"): {"consu"},
+ ValidatorID("carol"): {"consu"},
+ },
+ },
+ },
+ },
+ {
+ // relay the slash packet
+ Action: RelayPacketsAction{
+ ChainA: ChainID("consu"),
+ ChainB: ChainID("provi"),
+ Port: "consumer",
+ Channel: 0,
+ },
+ // alice's power is reduced on the provider
+ State: State{
+ ChainID("provi"): ChainState{
+ ValPowers: &map[ValidatorID]uint{
+ ValidatorID("alice"): 0,
+ ValidatorID("bob"): 200,
+ ValidatorID("carol"): 300,
+ },
+ HasToValidate: &map[ValidatorID][]ChainID{
+ ValidatorID("alice"): {}, // alice is jailed on the provider and does not have to validate
+ ValidatorID("bob"): {"consu"},
+ ValidatorID("carol"): {"consu"},
+ },
+ },
+ },
+ },
+ {
+ // relay the VSCPacket that contains the slashed power for alice
+ Action: RelayPacketsAction{
+ ChainA: ChainID("consu"),
+ ChainB: ChainID("provi"),
+ Port: "consumer",
+ Channel: 0,
+ },
+ // alice's power is reduced on the provider
+ State: State{
+ ChainID("provi"): ChainState{
+ ValPowers: &map[ValidatorID]uint{
+ ValidatorID("alice"): 0,
+ ValidatorID("bob"): 200,
+ ValidatorID("carol"): 300,
+ },
+ HasToValidate: &map[ValidatorID][]ChainID{
+ ValidatorID("alice"): {}, // alice is jailed on the provider and does not have to validate
+ ValidatorID("bob"): {"consu"},
+ ValidatorID("carol"): {"consu"},
+ },
+ },
+ ChainID("consu"): ChainState{
+ ValPowers: &map[ValidatorID]uint{
+ // alice should definitely not be in power on the consumer
+ ValidatorID("alice"): 0,
+ ValidatorID("bob"): 200,
+ ValidatorID("carol"): 300,
+ },
+ },
+ },
+ },
+ {
+ // unjail alice
+ Action: UnjailValidatorAction{
+ Provider: ChainID("provi"),
+ Validator: ValidatorID("alice"),
+ },
+ // alices power is restored on the provider
+ State: State{
+ ChainID("provi"): ChainState{
+ ValPowers: &map[ValidatorID]uint{
+ ValidatorID("alice"): 100,
+ ValidatorID("bob"): 200,
+ ValidatorID("carol"): 300,
+ },
+ HasToValidate: &map[ValidatorID][]ChainID{
+ ValidatorID("alice"): {"consu"}, // alice is unjailed and hence has to validate again
+ ValidatorID("bob"): {"consu"},
+ ValidatorID("carol"): {"consu"},
+ },
+ },
+ // still 0 power on the consumer
+ ChainID("consu"): ChainState{
+ ValPowers: &map[ValidatorID]uint{
+ ValidatorID("alice"): 0,
+ ValidatorID("bob"): 200,
+ ValidatorID("carol"): 300,
+ },
+ },
+ },
+ },
+ {
+ // relay the VSCPacket that puts alice back into power on the consumer
+ Action: RelayPacketsAction{
+ ChainA: ChainID("provi"),
+ ChainB: ChainID("consu"),
+ Port: "provider",
+ Channel: 0,
+ },
+ // alice's power is restored on the consumer
+ State: State{
+ ChainID("consu"): ChainState{
+ ValPowers: &map[ValidatorID]uint{
+ ValidatorID("alice"): 100,
+ ValidatorID("bob"): 200,
+ ValidatorID("carol"): 300,
+ },
+ },
+ },
+ },
+ {
+ // slash alice for downtime again
+ Action: DowntimeSlashAction{
+ Chain: ChainID("consu"),
+ Validator: ValidatorID("alice"),
+ },
+ // alice's power is not yet reduced, the packet needs to be relayed
+ State: State{
+ ChainID("consu"): ChainState{
+ ValPowers: &map[ValidatorID]uint{
+ ValidatorID("alice"): 100,
+ ValidatorID("bob"): 200,
+ ValidatorID("carol"): 300,
+ },
+ },
+ ChainID("provi"): ChainState{
+ ValPowers: &map[ValidatorID]uint{
+ ValidatorID("alice"): 100,
+ ValidatorID("bob"): 200,
+ ValidatorID("carol"): 300,
+ },
+ HasToValidate: &map[ValidatorID][]ChainID{
+ ValidatorID("alice"): {"consu"},
+ ValidatorID("bob"): {"consu"},
+ ValidatorID("carol"): {"consu"},
+ },
+ },
+ },
+ },
+ {
+ // relay the slash packet
+ Action: RelayPacketsAction{
+ ChainA: ChainID("consu"),
+ ChainB: ChainID("provi"),
+ Port: "consumer",
+ Channel: 0,
+ },
+ // alice's power is reduced on the provider
+ State: State{
+ ChainID("provi"): ChainState{
+ ValPowers: &map[ValidatorID]uint{
+ ValidatorID("alice"): 0,
+ ValidatorID("bob"): 200,
+ ValidatorID("carol"): 300,
+ },
+ HasToValidate: &map[ValidatorID][]ChainID{
+ ValidatorID("alice"): {}, // alice is jailed on the provider and does not have to validate
+ ValidatorID("bob"): {"consu"},
+ ValidatorID("carol"): {"consu"},
+ },
+ },
+ },
+ },
+ {
+ // relay the VSCPacket that contains the slashed power for alice
+ Action: RelayPacketsAction{
+ ChainA: ChainID("consu"),
+ ChainB: ChainID("provi"),
+ Port: "consumer",
+ Channel: 0,
+ },
+ // alice's power is reduced on the consumer
+ State: State{
+ ChainID("consu"): ChainState{
+ ValPowers: &map[ValidatorID]uint{
+ ValidatorID("alice"): 0,
+ ValidatorID("bob"): 200,
+ ValidatorID("carol"): 300,
+ },
+ },
+ ChainID("provi"): ChainState{
+ ValPowers: &map[ValidatorID]uint{
+ ValidatorID("alice"): 0,
+ ValidatorID("bob"): 200,
+ ValidatorID("carol"): 300,
+ },
+ HasToValidate: &map[ValidatorID][]ChainID{
+ ValidatorID("alice"): {}, // alice is jailed on the provider and does not have to validate
+ ValidatorID("bob"): {"consu"},
+ ValidatorID("carol"): {"consu"},
+ },
+ },
+ },
+ },
+ }
+
+ return s
+}
+
+// stepsTopNChain starts a provider chain and a Top-N chain and opts in and out validators
+func stepsTopNChain() []Step {
+ s := []Step{
+ {
+ // start a new chain where "alice", "bob", and "carol" have 20%, 30%, and 50% of
+ // the total voting power respectively
+ Action: StartChainAction{
+ Chain: ChainID("provi"),
+ Validators: []StartChainValidator{
+ {Id: ValidatorID("alice"), Stake: 200000000, Allocation: 10000000000},
+ {Id: ValidatorID("bob"), Stake: 300000000, Allocation: 10000000000},
+ {Id: ValidatorID("carol"), Stake: 500000000, Allocation: 10000000000},
+ },
+ },
+ State: State{
+ ChainID("provi"): ChainState{
+ ValPowers: &map[ValidatorID]uint{
+ ValidatorID("alice"): 200,
+ ValidatorID("bob"): 300,
+ ValidatorID("carol"): 500,
+ },
+ },
+ },
+ },
+ {
+ // propose a Top-N chain with N = 51% and hence both "carol" and "bob" have to validate
+ Action: SubmitConsumerAdditionProposalAction{
+ Chain: ChainID("provi"),
+ From: ValidatorID("alice"),
+ Deposit: 10000001,
+ ConsumerChain: ChainID("consu"),
+ SpawnTime: 0,
+ InitialHeight: clienttypes.Height{RevisionNumber: 0, RevisionHeight: 1},
+ TopN: 51,
+ },
+ State: State{
+ ChainID("provi"): ChainState{
+ Proposals: &map[uint]Proposal{
+ 1: ConsumerAdditionProposal{
+ Deposit: 10000001,
+ Chain: ChainID("consu"),
+ SpawnTime: 0,
+ InitialHeight: clienttypes.Height{RevisionNumber: 0, RevisionHeight: 1},
+ Status: "PROPOSAL_STATUS_VOTING_PERIOD",
+ },
+ },
+ },
+ },
+ },
+ {
+ // change the consumer key "carol" is using on the consumer chain to be the one "carol" uses when opting in
+ Action: AssignConsumerPubKeyAction{
+ Chain: ChainID("consu"),
+ Validator: ValidatorID("carol"),
+ // reconfigure the node -> validator was using provider key
+ // until this point -> key matches config.consumerValPubKey for "bob"
+ ConsumerPubkey: getDefaultValidators()[ValidatorID("carol")].ConsumerValPubKey,
+ ReconfigureNode: true,
+ },
+ State: State{},
+ },
+ {
+ Action: VoteGovProposalAction{
+ Chain: ChainID("provi"),
+ From: []ValidatorID{ValidatorID("alice"), ValidatorID("bob")},
+ Vote: []string{"yes", "yes"},
+ PropNumber: 1,
+ },
+ State: State{
+ ChainID("provi"): ChainState{
+ Proposals: &map[uint]Proposal{
+ 1: ConsumerAdditionProposal{
+ Deposit: 10000001,
+ Chain: ChainID("consu"),
+ SpawnTime: 0,
+ InitialHeight: clienttypes.Height{RevisionNumber: 0, RevisionHeight: 1},
+ Status: "PROPOSAL_STATUS_PASSED",
+ },
+ },
+ },
+ },
+ },
+ {
+ // we start all the validators but only "alice" and "bob" have opted in and hence
+ // only "alice" and "bob" are validating blocks
+ Action: StartConsumerChainAction{
+ ConsumerChain: ChainID("consu"),
+ ProviderChain: ChainID("provi"),
+ Validators: []StartChainValidator{
+ {Id: ValidatorID("alice"), Stake: 200000000, Allocation: 10000000000},
+ {Id: ValidatorID("bob"), Stake: 300000000, Allocation: 10000000000},
+ {Id: ValidatorID("carol"), Stake: 500000000, Allocation: 10000000000},
+ },
+ // For consumers that're launching with the provider being on an earlier version
+ // of ICS before the soft opt-out threshold was introduced, we need to set the
+ // soft opt-out threshold to 0.05 in the consumer genesis to ensure that the
+ // consumer binary doesn't panic. Sdk requires that all params are set to valid
+ // values from the genesis file.
+ GenesisChanges: ".app_state.ccvconsumer.params.soft_opt_out_threshold = \"0.05\"",
+ },
+ State: State{
+ ChainID("consu"): ChainState{
+ ValPowers: &map[ValidatorID]uint{
+ ValidatorID("alice"): 0,
+ ValidatorID("bob"): 300,
+ ValidatorID("carol"): 500,
+ },
+ },
+ },
+ },
+ {
+ Action: AddIbcConnectionAction{
+ ChainA: ChainID("consu"),
+ ChainB: ChainID("provi"),
+ ClientA: 0,
+ ClientB: 0,
+ },
+ State: State{},
+ },
+ {
+ Action: AddIbcChannelAction{
+ ChainA: ChainID("consu"),
+ ChainB: ChainID("provi"),
+ ConnectionA: 0,
+ PortA: "consumer",
+ PortB: "provider",
+ Order: "ordered",
+ },
+ State: State{},
+ },
+ {
+ Action: OptInAction{
+ Chain: ChainID("consu"),
+ Validator: ValidatorID("alice"),
+ },
+ State: State{
+ ChainID("consu"): ChainState{
+ ValPowers: &map[ValidatorID]uint{
+ // "alice" is not yet opted in because the VSCPacket has not yet been relayed
+ ValidatorID("alice"): 0,
+ ValidatorID("bob"): 300,
+ ValidatorID("carol"): 500,
+ },
+ },
+ ChainID("provi"): ChainState{
+ HasToValidate: &map[ValidatorID][]ChainID{
+ ValidatorID("alice"): {"consu"},
+ ValidatorID("bob"): {"consu"},
+ ValidatorID("carol"): {"consu"},
+ },
+ },
+ },
+ },
+ {
+ Action: RelayPacketsAction{
+ ChainA: ChainID("provi"),
+ ChainB: ChainID("consu"),
+ Port: "provider",
+ Channel: 0,
+ },
+ State: State{
+ ChainID("consu"): ChainState{
+ ValPowers: &map[ValidatorID]uint{
+ // "alice" is now opted in
+ ValidatorID("alice"): 200,
+ ValidatorID("bob"): 300,
+ ValidatorID("carol"): 500,
+ },
+ },
+ },
+ },
+ {
+ Action: OptOutAction{
+ Chain: ChainID("consu"),
+ Validator: ValidatorID("carol"),
+ ExpectError: true,
+ },
+ State: State{},
+ },
+ {
+ Action: OptOutAction{
+ Chain: ChainID("consu"),
+ Validator: ValidatorID("bob"),
+ ExpectError: true,
+ },
+ State: State{
+ ChainID("provi"): ChainState{
+ HasToValidate: &map[ValidatorID][]ChainID{
+ ValidatorID("alice"): {"consu"},
+ ValidatorID("bob"): {"consu"},
+ ValidatorID("carol"): {"consu"},
+ },
+ },
+ },
+ },
+ {
+ // opting out "bob" or "carol" does not work because they belong to the Top N validators
+ Action: RelayPacketsAction{
+ ChainA: ChainID("provi"),
+ ChainB: ChainID("consu"),
+ Port: "provider",
+ Channel: 0,
+ },
+ State: State{
+ ChainID("consu"): ChainState{
+ ValPowers: &map[ValidatorID]uint{
+ ValidatorID("alice"): 200,
+ ValidatorID("bob"): 300,
+ ValidatorID("carol"): 500,
+ },
+ },
+ ChainID("provi"): ChainState{
+ HasToValidate: &map[ValidatorID][]ChainID{
+ ValidatorID("alice"): {"consu"},
+ ValidatorID("bob"): {"consu"},
+ ValidatorID("carol"): {"consu"},
+ },
+ },
+ },
+ },
+ {
+ Action: OptOutAction{
+ Chain: ChainID("consu"),
+ Validator: ValidatorID("alice"),
+ },
+ State: State{},
+ },
+ {
+ Action: RelayPacketsAction{
+ ChainA: ChainID("provi"),
+ ChainB: ChainID("consu"),
+ Port: "provider",
+ Channel: 0,
+ },
+ State: State{
+ ChainID("consu"): ChainState{
+ ValPowers: &map[ValidatorID]uint{
+ // "alice" has now opted out
+ ValidatorID("alice"): 0,
+ ValidatorID("bob"): 300,
+ ValidatorID("carol"): 500,
+ },
+ },
+ ChainID("provi"): ChainState{
+ HasToValidate: &map[ValidatorID][]ChainID{
+ ValidatorID("alice"): {}, // alice has opted out and the epoch is over, so definitely does not have to validate anymore
+ ValidatorID("bob"): {"consu"},
+ ValidatorID("carol"): {"consu"},
+ },
+ },
+ },
+ },
+ // opt alice back in
+ {
+ Action: OptInAction{
+ Chain: ChainID("consu"),
+ Validator: ValidatorID("alice"),
+ },
+ State: State{
+ ChainID("provi"): ChainState{
+ HasToValidate: &map[ValidatorID][]ChainID{
+ ValidatorID("alice"): {"consu"}, // alice has to validate again
+ ValidatorID("bob"): {"consu"},
+ ValidatorID("carol"): {"consu"},
+ },
+ },
+ },
+ },
+ {
+ Action: RelayPacketsAction{
+ ChainA: ChainID("provi"),
+ ChainB: ChainID("consu"),
+ Port: "provider",
+ Channel: 0,
+ },
+ State: State{
+ ChainID("consu"): ChainState{
+ ValPowers: &map[ValidatorID]uint{
+ // "alice" has now opted in
+ ValidatorID("alice"): 200,
+ ValidatorID("bob"): 300,
+ ValidatorID("carol"): 500,
+ },
+ },
+ ChainID("provi"): ChainState{
+ HasToValidate: &map[ValidatorID][]ChainID{
+ ValidatorID("alice"): {"consu"},
+ ValidatorID("bob"): {"consu"},
+ ValidatorID("carol"): {"consu"},
+ },
+ },
+ },
+ },
+ {
+ // DowntimeSlash for alice on consumer
+ Action: DowntimeSlashAction{
+ Chain: ChainID("consu"),
+ Validator: ValidatorID("alice"),
+ },
+ // powers are not affected yet on either chain
+ State: State{
+ ChainID("consu"): ChainState{
+ ValPowers: &map[ValidatorID]uint{
+ ValidatorID("alice"): 200,
+ ValidatorID("bob"): 300,
+ ValidatorID("carol"): 500,
+ },
+ },
+ ChainID("provi"): ChainState{
+ ValPowers: &map[ValidatorID]uint{
+ ValidatorID("alice"): 200,
+ ValidatorID("bob"): 300,
+ ValidatorID("carol"): 500,
+ },
+ },
+ },
+ },
+ {
+ // relay the slash packet
+ Action: RelayPacketsAction{
+ ChainA: ChainID("consu"),
+ ChainB: ChainID("provi"),
+ Port: "consumer",
+ Channel: 0,
+ },
+ // alice's power is reduced on the provider
+ State: State{
+ ChainID("provi"): ChainState{
+ ValPowers: &map[ValidatorID]uint{
+ ValidatorID("alice"): 0,
+ ValidatorID("bob"): 300,
+ ValidatorID("carol"): 500,
+ },
+ },
+ },
+ },
+ {
+ // relay the VSCPacket that contains the slashed power for alice
+ Action: RelayPacketsAction{
+ ChainA: ChainID("consu"),
+ ChainB: ChainID("provi"),
+ Port: "consumer",
+ Channel: 0,
+ },
+ // alice's power is reduced on the provider
+ State: State{
+ ChainID("provi"): ChainState{
+ ValPowers: &map[ValidatorID]uint{
+ ValidatorID("alice"): 0,
+ ValidatorID("bob"): 300,
+ ValidatorID("carol"): 500,
+ },
+ },
+ ChainID("consu"): ChainState{
+ ValPowers: &map[ValidatorID]uint{
+ // alice should definitely not be in power on the consumer
+ ValidatorID("alice"): 0,
+ ValidatorID("bob"): 300,
+ ValidatorID("carol"): 500,
+ },
+ },
+ },
+ },
+ {
+ // unjail alice
+ Action: UnjailValidatorAction{
+ Provider: ChainID("provi"),
+ Validator: ValidatorID("alice"),
+ },
+ // alices power is restored on the provider
+ State: State{
+ ChainID("provi"): ChainState{
+ ValPowers: &map[ValidatorID]uint{
+ ValidatorID("alice"): 200,
+ ValidatorID("bob"): 300,
+ ValidatorID("carol"): 500,
+ },
+ },
+ // still 0 power on the consumer
+ ChainID("consu"): ChainState{
+ ValPowers: &map[ValidatorID]uint{
+ ValidatorID("alice"): 0,
+ ValidatorID("bob"): 300,
+ ValidatorID("carol"): 500,
+ },
+ },
+ },
+ },
+ {
+ // relay the VSCPacket that puts alice back into power on the consumer
+ Action: RelayPacketsAction{
+ ChainA: ChainID("provi"),
+ ChainB: ChainID("consu"),
+ Port: "provider",
+ Channel: 0,
+ },
+ // alice's power is restored on the consumer
+ State: State{
+ ChainID("consu"): ChainState{
+ ValPowers: &map[ValidatorID]uint{
+ ValidatorID("alice"): 200,
+ ValidatorID("bob"): 300,
+ ValidatorID("carol"): 500,
+ },
+ },
+ },
+ },
+ {
+ // slash alice for downtime again
+ Action: DowntimeSlashAction{
+ Chain: ChainID("consu"),
+ Validator: ValidatorID("alice"),
+ },
+ // alice's power is not yet reduced, the packet needs to be relayed
+ State: State{
+ ChainID("consu"): ChainState{
+ ValPowers: &map[ValidatorID]uint{
+ ValidatorID("alice"): 200,
+ ValidatorID("bob"): 300,
+ ValidatorID("carol"): 500,
+ },
+ },
+ ChainID("provi"): ChainState{
+ ValPowers: &map[ValidatorID]uint{
+ ValidatorID("alice"): 200,
+ ValidatorID("bob"): 300,
+ ValidatorID("carol"): 500,
+ },
+ },
+ },
+ },
+ {
+ // relay the slash packet
+ Action: RelayPacketsAction{
+ ChainA: ChainID("consu"),
+ ChainB: ChainID("provi"),
+ Port: "consumer",
+ Channel: 0,
+ },
+ // alice's power is reduced on the provider
+ State: State{
+ ChainID("provi"): ChainState{
+ ValPowers: &map[ValidatorID]uint{
+ ValidatorID("alice"): 0,
+ ValidatorID("bob"): 300,
+ ValidatorID("carol"): 500,
+ },
+ },
+ },
+ },
+ {
+ // relay the VSCPacket that contains the slashed power for alice
+ Action: RelayPacketsAction{
+ ChainA: ChainID("consu"),
+ ChainB: ChainID("provi"),
+ Port: "consumer",
+ Channel: 0,
+ },
+ // alice's power is reduced on the consumer
+ State: State{
+ ChainID("consu"): ChainState{
+ ValPowers: &map[ValidatorID]uint{
+ ValidatorID("alice"): 0,
+ ValidatorID("bob"): 300,
+ ValidatorID("carol"): 500,
+ },
+ },
+ ChainID("provi"): ChainState{
+ ValPowers: &map[ValidatorID]uint{
+ ValidatorID("alice"): 0,
+ ValidatorID("bob"): 300,
+ ValidatorID("carol"): 500,
+ },
+ },
+ },
+ },
+ }
+
+ return s
+}
diff --git a/tests/e2e/steps_sovereign_changeover.go b/tests/e2e/steps_sovereign_changeover.go
index 69e6680677..1ddd5a2143 100644
--- a/tests/e2e/steps_sovereign_changeover.go
+++ b/tests/e2e/steps_sovereign_changeover.go
@@ -48,6 +48,7 @@ func stepsChangeoverToConsumer(consumerName string) []Step {
DistributionChannel: "channel-0",
SpawnTime: 0,
InitialHeight: clienttypes.Height{RevisionNumber: 0, RevisionHeight: 111}, // 1 block after upgrade !important
+ TopN: 100,
},
State: State{
ChainID("provi"): ChainState{
diff --git a/tests/e2e/steps_start_chains.go b/tests/e2e/steps_start_chains.go
index 08732e3f37..2ff3226dec 100644
--- a/tests/e2e/steps_start_chains.go
+++ b/tests/e2e/steps_start_chains.go
@@ -38,6 +38,7 @@ func stepsStartConsumerChain(consumerName string, proposalIndex, chainIndex uint
ConsumerChain: ChainID(consumerName),
SpawnTime: 0,
InitialHeight: clienttypes.Height{RevisionNumber: 0, RevisionHeight: 1},
+ TopN: 100,
},
State: State{
ChainID("provi"): ChainState{
@@ -82,16 +83,24 @@ func stepsStartConsumerChain(consumerName string, proposalIndex, chainIndex uint
},
},
{
- // op should fail - key already assigned by the same validator
+ // op should be a noop - key already assigned, but by the same validator
Action: AssignConsumerPubKeyAction{
Chain: ChainID(consumerName),
Validator: ValidatorID("carol"),
ConsumerPubkey: getDefaultValidators()[ValidatorID("carol")].ConsumerValPubKey,
ReconfigureNode: false,
- ExpectError: true,
- ExpectedError: "a validator has assigned the consumer key already: consumer key is already in use by a validator",
+ ExpectError: false,
+ },
+ State: State{
+ ChainID(consumerName): ChainState{
+ AssignedKeys: &map[ValidatorID]string{
+ ValidatorID("carol"): getDefaultValidators()[ValidatorID("carol")].ConsumerValconsAddressOnProvider,
+ },
+ ProviderKeys: &map[ValidatorID]string{
+ ValidatorID("carol"): getDefaultValidators()[ValidatorID("carol")].ValconsAddress,
+ },
+ },
},
- State: State{},
},
{
// op should fail - key already assigned by another validator
diff --git a/tests/e2e/test_driver.go b/tests/e2e/test_driver.go
index 052559b3ba..a12dc7862e 100644
--- a/tests/e2e/test_driver.go
+++ b/tests/e2e/test_driver.go
@@ -138,6 +138,10 @@ func (td *DefaultDriver) runAction(action interface{}) error {
td.testCfg.startConsumerEvidenceDetector(action, td.target, td.verbose)
case SubmitChangeRewardDenomsProposalAction:
td.testCfg.submitChangeRewardDenomsProposal(action, td.target, td.verbose)
+ case OptInAction:
+ td.testCfg.optIn(action, td.target, td.verbose)
+ case OptOutAction:
+ td.testCfg.optOut(action, td.target, td.verbose)
default:
log.Fatalf("unknown action in testRun %s: %#v", td.testCfg.name, action)
}
diff --git a/tests/e2e/tracehandler_testdata/changeover.json b/tests/e2e/tracehandler_testdata/changeover.json
index 47d6fc621d..1b6ae37ae1 100644
--- a/tests/e2e/tracehandler_testdata/changeover.json
+++ b/tests/e2e/tracehandler_testdata/changeover.json
@@ -28,6 +28,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -58,6 +59,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -104,6 +106,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -151,6 +154,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": {
"1": {
"RawProposal": {
@@ -193,6 +197,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": {
"1": {
"RawProposal": {
@@ -229,7 +234,8 @@
"InitialHeight": {
"revision_height": 111
},
- "DistributionChannel": "channel-0"
+ "DistributionChannel": "channel-0",
+ "TopN": 100
},
"State": {
"provi": {
@@ -248,6 +254,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": {
"1": {
"RawProposal": {
@@ -298,6 +305,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": {
"1": {
"RawProposal": {
@@ -357,6 +365,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"sover": {
@@ -376,6 +385,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -427,6 +437,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -457,6 +468,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"sover": {
@@ -476,6 +488,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -506,6 +519,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -534,6 +548,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -564,6 +579,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"sover": {
@@ -583,6 +599,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -613,6 +630,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
diff --git a/tests/e2e/tracehandler_testdata/consumer-double-sign.json b/tests/e2e/tracehandler_testdata/consumer-double-sign.json
index e93049cf8b..290f351875 100644
--- a/tests/e2e/tracehandler_testdata/consumer-double-sign.json
+++ b/tests/e2e/tracehandler_testdata/consumer-double-sign.json
@@ -41,6 +41,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -57,7 +58,8 @@
"InitialHeight": {
"revision_height": 1
},
- "DistributionChannel": ""
+ "DistributionChannel": "",
+ "TopN": 100
},
"State": {
"provi": {
@@ -78,6 +80,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": {
"1": {
"RawProposal": {
@@ -123,6 +126,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -134,10 +138,31 @@
"Validator": "carol",
"ConsumerPubkey": "{\"@type\":\"/cosmos.crypto.ed25519.PubKey\",\"key\":\"Ui5Gf1+mtWUdH8u3xlmzdKID+F3PK0sfXZ73GZ6q6is=\"}",
"ReconfigureNode": false,
- "ExpectError": true,
- "ExpectedError": "a validator has assigned the consumer key already: consumer key is already in use by a validator"
+ "ExpectError": false,
+ "ExpectedError": ""
},
- "State": {}
+ "State": {
+ "consu": {
+ "ValBalances": null,
+ "ProposedConsumerChains": null,
+ "ValPowers": null,
+ "StakedTokens": null,
+ "Params": null,
+ "Rewards": null,
+ "ConsumerChains": null,
+ "AssignedKeys": {
+ "carol": "cosmosvalcons1kswr5sq599365kcjmhgufevfps9njf43e4lwdk"
+ },
+ "ProviderKeys": {
+ "carol": "cosmosvalcons1ezyrq65s3gshhx5585w6mpusq3xsj3ayzf4uv6"
+ },
+ "ConsumerPendingPacketQueueSize": null,
+ "RegisteredConsumerRewardDenoms": null,
+ "ClientsFrozenHeights": null,
+ "HasToValidate": null,
+ "Proposals": null
+ }
+ }
},
{
"ActionType": "main.AssignConsumerPubKeyAction",
@@ -168,6 +193,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -205,6 +231,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": {
"1": {
"RawProposal": {
@@ -264,6 +291,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -283,6 +311,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -334,6 +363,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -357,6 +387,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -384,6 +415,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -407,6 +439,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -437,6 +470,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -460,6 +494,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
diff --git a/tests/e2e/tracehandler_testdata/consumer-misbehaviour.json b/tests/e2e/tracehandler_testdata/consumer-misbehaviour.json
index 43e242e7dc..b0c64232e2 100644
--- a/tests/e2e/tracehandler_testdata/consumer-misbehaviour.json
+++ b/tests/e2e/tracehandler_testdata/consumer-misbehaviour.json
@@ -35,6 +35,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -51,7 +52,8 @@
"InitialHeight": {
"revision_height": 1
},
- "DistributionChannel": ""
+ "DistributionChannel": "",
+ "TopN": 100
},
"State": {
"provi": {
@@ -70,6 +72,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": {
"1": {
"RawProposal": {
@@ -115,6 +118,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -150,6 +154,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": {
"1": {
"RawProposal": {
@@ -197,6 +202,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -215,6 +221,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -267,6 +274,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -285,6 +293,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -314,6 +323,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -355,6 +365,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -376,6 +387,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -405,6 +417,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -430,6 +443,7 @@
"revision_height": 1
}
},
+ "HasToValidate": null,
"Proposals": null
}
}
diff --git a/tests/e2e/tracehandler_testdata/democracy.json b/tests/e2e/tracehandler_testdata/democracy.json
index 10c9838122..bcfcd0bcd4 100644
--- a/tests/e2e/tracehandler_testdata/democracy.json
+++ b/tests/e2e/tracehandler_testdata/democracy.json
@@ -41,6 +41,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -57,7 +58,8 @@
"InitialHeight": {
"revision_height": 1
},
- "DistributionChannel": ""
+ "DistributionChannel": "",
+ "TopN": 100
},
"State": {
"provi": {
@@ -78,6 +80,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": {
"1": {
"RawProposal": {
@@ -123,6 +126,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -134,10 +138,31 @@
"Validator": "carol",
"ConsumerPubkey": "{\"@type\":\"/cosmos.crypto.ed25519.PubKey\",\"key\":\"Ui5Gf1+mtWUdH8u3xlmzdKID+F3PK0sfXZ73GZ6q6is=\"}",
"ReconfigureNode": false,
- "ExpectError": true,
- "ExpectedError": "a validator has assigned the consumer key already: consumer key is already in use by a validator"
+ "ExpectError": false,
+ "ExpectedError": ""
},
- "State": {}
+ "State": {
+ "democ": {
+ "ValBalances": null,
+ "ProposedConsumerChains": null,
+ "ValPowers": null,
+ "StakedTokens": null,
+ "Params": null,
+ "Rewards": null,
+ "ConsumerChains": null,
+ "AssignedKeys": {
+ "carol": "cosmosvalcons1kswr5sq599365kcjmhgufevfps9njf43e4lwdk"
+ },
+ "ProviderKeys": {
+ "carol": "cosmosvalcons1ezyrq65s3gshhx5585w6mpusq3xsj3ayzf4uv6"
+ },
+ "ConsumerPendingPacketQueueSize": null,
+ "RegisteredConsumerRewardDenoms": null,
+ "ClientsFrozenHeights": null,
+ "HasToValidate": null,
+ "Proposals": null
+ }
+ }
},
{
"ActionType": "main.AssignConsumerPubKeyAction",
@@ -168,6 +193,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -205,6 +231,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": {
"1": {
"RawProposal": {
@@ -264,6 +291,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -283,6 +311,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -350,6 +379,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -369,6 +399,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -398,6 +429,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -428,6 +460,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -457,6 +490,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -499,6 +533,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -540,6 +575,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -577,6 +613,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": {
"1": {
"RawProposal": {
@@ -629,6 +666,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": {
"1": {
"RawProposal": {
@@ -674,6 +712,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": [],
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -699,6 +738,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": [],
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -735,6 +775,7 @@
"ibc/3C3D7B3BE4ECC85A0E5B52A3AEC3B7DFC2AA9CA47C37821E57020D6807043BE9"
],
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -769,6 +810,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -797,6 +839,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -816,6 +859,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -846,6 +890,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -865,6 +910,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -895,6 +941,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -923,6 +970,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -942,6 +990,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -975,6 +1024,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
diff --git a/tests/e2e/tracehandler_testdata/democracyRewardsSteps.json b/tests/e2e/tracehandler_testdata/democracyRewardsSteps.json
index 7e6d90cace..83b1f326d9 100644
--- a/tests/e2e/tracehandler_testdata/democracyRewardsSteps.json
+++ b/tests/e2e/tracehandler_testdata/democracyRewardsSteps.json
@@ -41,6 +41,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -57,7 +58,8 @@
"InitialHeight": {
"revision_height": 1
},
- "DistributionChannel": ""
+ "DistributionChannel": "",
+ "TopN": 100
},
"State": {
"provi": {
@@ -78,6 +80,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": {
"1": {
"RawProposal": {
@@ -123,6 +126,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -134,10 +138,31 @@
"Validator": "carol",
"ConsumerPubkey": "{\"@type\":\"/cosmos.crypto.ed25519.PubKey\",\"key\":\"Ui5Gf1+mtWUdH8u3xlmzdKID+F3PK0sfXZ73GZ6q6is=\"}",
"ReconfigureNode": false,
- "ExpectError": true,
- "ExpectedError": "a validator has assigned the consumer key already: consumer key is already in use by a validator"
+ "ExpectError": false,
+ "ExpectedError": ""
},
- "State": {}
+ "State": {
+ "democ": {
+ "ValBalances": null,
+ "ProposedConsumerChains": null,
+ "ValPowers": null,
+ "StakedTokens": null,
+ "Params": null,
+ "Rewards": null,
+ "ConsumerChains": null,
+ "AssignedKeys": {
+ "carol": "cosmosvalcons1kswr5sq599365kcjmhgufevfps9njf43e4lwdk"
+ },
+ "ProviderKeys": {
+ "carol": "cosmosvalcons1ezyrq65s3gshhx5585w6mpusq3xsj3ayzf4uv6"
+ },
+ "ConsumerPendingPacketQueueSize": null,
+ "RegisteredConsumerRewardDenoms": null,
+ "ClientsFrozenHeights": null,
+ "HasToValidate": null,
+ "Proposals": null
+ }
+ }
},
{
"ActionType": "main.AssignConsumerPubKeyAction",
@@ -168,6 +193,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -205,6 +231,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": {
"1": {
"RawProposal": {
@@ -264,6 +291,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -283,6 +311,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -350,6 +379,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -369,6 +399,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -398,6 +429,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -428,6 +460,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -457,6 +490,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -499,6 +533,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -540,6 +575,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -577,6 +613,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": {
"1": {
"RawProposal": {
@@ -629,6 +666,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": {
"1": {
"RawProposal": {
@@ -674,6 +712,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": [],
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -699,6 +738,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": [],
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -735,6 +775,7 @@
"ibc/3C3D7B3BE4ECC85A0E5B52A3AEC3B7DFC2AA9CA47C37821E57020D6807043BE9"
],
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -769,6 +810,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -797,6 +839,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -816,6 +859,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -846,6 +890,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -865,6 +910,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -895,6 +941,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -923,6 +970,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -942,6 +990,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -975,6 +1024,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
diff --git a/tests/e2e/tracehandler_testdata/happyPath.json b/tests/e2e/tracehandler_testdata/happyPath.json
index 5b9505e848..0109d72501 100644
--- a/tests/e2e/tracehandler_testdata/happyPath.json
+++ b/tests/e2e/tracehandler_testdata/happyPath.json
@@ -41,6 +41,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -57,7 +58,8 @@
"InitialHeight": {
"revision_height": 1
},
- "DistributionChannel": ""
+ "DistributionChannel": "",
+ "TopN": 100
},
"State": {
"provi": {
@@ -78,6 +80,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": {
"1": {
"RawProposal": {
@@ -123,6 +126,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -134,10 +138,31 @@
"Validator": "carol",
"ConsumerPubkey": "{\"@type\":\"/cosmos.crypto.ed25519.PubKey\",\"key\":\"Ui5Gf1+mtWUdH8u3xlmzdKID+F3PK0sfXZ73GZ6q6is=\"}",
"ReconfigureNode": false,
- "ExpectError": true,
- "ExpectedError": "a validator has assigned the consumer key already: consumer key is already in use by a validator"
+ "ExpectError": false,
+ "ExpectedError": ""
},
- "State": {}
+ "State": {
+ "consu": {
+ "ValBalances": null,
+ "ProposedConsumerChains": null,
+ "ValPowers": null,
+ "StakedTokens": null,
+ "Params": null,
+ "Rewards": null,
+ "ConsumerChains": null,
+ "AssignedKeys": {
+ "carol": "cosmosvalcons1kswr5sq599365kcjmhgufevfps9njf43e4lwdk"
+ },
+ "ProviderKeys": {
+ "carol": "cosmosvalcons1ezyrq65s3gshhx5585w6mpusq3xsj3ayzf4uv6"
+ },
+ "ConsumerPendingPacketQueueSize": null,
+ "RegisteredConsumerRewardDenoms": null,
+ "ClientsFrozenHeights": null,
+ "HasToValidate": null,
+ "Proposals": null
+ }
+ }
},
{
"ActionType": "main.AssignConsumerPubKeyAction",
@@ -168,6 +193,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -205,6 +231,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": {
"1": {
"RawProposal": {
@@ -264,6 +291,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -283,6 +311,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -336,6 +365,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -355,6 +385,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -384,6 +415,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -414,6 +446,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -443,6 +476,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -481,6 +515,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -500,6 +535,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -536,6 +572,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -555,6 +592,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -585,6 +623,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -604,6 +643,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -634,6 +674,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -664,6 +705,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -683,6 +725,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -713,6 +756,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -743,6 +787,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -762,6 +807,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -792,6 +838,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -823,6 +870,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -842,6 +890,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -872,6 +921,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -900,6 +950,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -919,6 +970,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -949,6 +1001,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -968,6 +1021,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -999,6 +1053,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -1018,6 +1073,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -1048,6 +1104,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -1076,6 +1133,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -1095,6 +1153,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -1124,6 +1183,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -1143,6 +1203,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -1173,6 +1234,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -1201,6 +1263,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -1220,6 +1283,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -1250,6 +1314,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -1278,6 +1343,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -1297,6 +1363,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -1327,6 +1394,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -1355,6 +1423,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -1374,6 +1443,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -1404,6 +1474,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -1432,6 +1503,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -1451,6 +1523,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -1481,6 +1554,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -1500,6 +1574,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -1536,6 +1611,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": {
"2": {
"RawProposal": {
@@ -1584,6 +1660,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": {
"2": {
"RawProposal": {
@@ -1625,6 +1702,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": {
"3": {
"RawProposal": {
@@ -1671,6 +1749,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": {
"3": {
"RawProposal": {
diff --git a/tests/e2e/tracehandler_testdata/multipleConsumers.json b/tests/e2e/tracehandler_testdata/multipleConsumers.json
index fdb69d1e47..b8bffb9cde 100644
--- a/tests/e2e/tracehandler_testdata/multipleConsumers.json
+++ b/tests/e2e/tracehandler_testdata/multipleConsumers.json
@@ -41,6 +41,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -57,7 +58,8 @@
"InitialHeight": {
"revision_height": 1
},
- "DistributionChannel": ""
+ "DistributionChannel": "",
+ "TopN": 100
},
"State": {
"provi": {
@@ -78,6 +80,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": {
"1": {
"RawProposal": {
@@ -123,6 +126,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -134,10 +138,31 @@
"Validator": "carol",
"ConsumerPubkey": "{\"@type\":\"/cosmos.crypto.ed25519.PubKey\",\"key\":\"Ui5Gf1+mtWUdH8u3xlmzdKID+F3PK0sfXZ73GZ6q6is=\"}",
"ReconfigureNode": false,
- "ExpectError": true,
- "ExpectedError": "a validator has assigned the consumer key already: consumer key is already in use by a validator"
+ "ExpectError": false,
+ "ExpectedError": ""
},
- "State": {}
+ "State": {
+ "consu": {
+ "ValBalances": null,
+ "ProposedConsumerChains": null,
+ "ValPowers": null,
+ "StakedTokens": null,
+ "Params": null,
+ "Rewards": null,
+ "ConsumerChains": null,
+ "AssignedKeys": {
+ "carol": "cosmosvalcons1kswr5sq599365kcjmhgufevfps9njf43e4lwdk"
+ },
+ "ProviderKeys": {
+ "carol": "cosmosvalcons1ezyrq65s3gshhx5585w6mpusq3xsj3ayzf4uv6"
+ },
+ "ConsumerPendingPacketQueueSize": null,
+ "RegisteredConsumerRewardDenoms": null,
+ "ClientsFrozenHeights": null,
+ "HasToValidate": null,
+ "Proposals": null
+ }
+ }
},
{
"ActionType": "main.AssignConsumerPubKeyAction",
@@ -168,6 +193,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -205,6 +231,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": {
"1": {
"RawProposal": {
@@ -264,6 +291,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -283,6 +311,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -322,7 +351,8 @@
"InitialHeight": {
"revision_height": 1
},
- "DistributionChannel": ""
+ "DistributionChannel": "",
+ "TopN": 100
},
"State": {
"provi": {
@@ -343,6 +373,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": {
"2": {
"RawProposal": {
@@ -388,6 +419,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -399,10 +431,31 @@
"Validator": "carol",
"ConsumerPubkey": "{\"@type\":\"/cosmos.crypto.ed25519.PubKey\",\"key\":\"Ui5Gf1+mtWUdH8u3xlmzdKID+F3PK0sfXZ73GZ6q6is=\"}",
"ReconfigureNode": false,
- "ExpectError": true,
- "ExpectedError": "a validator has assigned the consumer key already: consumer key is already in use by a validator"
+ "ExpectError": false,
+ "ExpectedError": ""
},
- "State": {}
+ "State": {
+ "densu": {
+ "ValBalances": null,
+ "ProposedConsumerChains": null,
+ "ValPowers": null,
+ "StakedTokens": null,
+ "Params": null,
+ "Rewards": null,
+ "ConsumerChains": null,
+ "AssignedKeys": {
+ "carol": "cosmosvalcons1kswr5sq599365kcjmhgufevfps9njf43e4lwdk"
+ },
+ "ProviderKeys": {
+ "carol": "cosmosvalcons1ezyrq65s3gshhx5585w6mpusq3xsj3ayzf4uv6"
+ },
+ "ConsumerPendingPacketQueueSize": null,
+ "RegisteredConsumerRewardDenoms": null,
+ "ClientsFrozenHeights": null,
+ "HasToValidate": null,
+ "Proposals": null
+ }
+ }
},
{
"ActionType": "main.AssignConsumerPubKeyAction",
@@ -433,6 +486,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -470,6 +524,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": {
"2": {
"RawProposal": {
@@ -529,6 +584,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -548,6 +604,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -601,6 +658,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"densu": {
@@ -620,6 +678,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -639,6 +698,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -669,6 +729,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"densu": {
@@ -688,6 +749,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -707,6 +769,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -737,6 +800,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"densu": {
@@ -756,6 +820,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -775,6 +840,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -805,6 +871,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"densu": {
@@ -824,6 +891,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -843,6 +911,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -873,6 +942,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"densu": {
@@ -892,6 +962,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -911,6 +982,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -941,6 +1013,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"densu": {
@@ -960,6 +1033,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -979,6 +1053,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -1010,6 +1085,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"densu": {
@@ -1029,6 +1105,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -1048,6 +1125,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -1078,6 +1156,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"densu": {
@@ -1097,6 +1176,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -1116,6 +1196,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -1146,6 +1227,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"densu": {
@@ -1165,6 +1247,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -1184,6 +1267,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -1212,6 +1296,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"densu": {
@@ -1231,6 +1316,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -1250,6 +1336,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -1280,6 +1367,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"densu": {
@@ -1299,6 +1387,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -1318,6 +1407,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -1348,6 +1438,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"densu": {
@@ -1367,6 +1458,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -1397,6 +1489,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"densu": {
@@ -1416,6 +1509,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -1444,6 +1538,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"densu": {
@@ -1463,6 +1558,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -1482,6 +1578,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -1512,6 +1609,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"densu": {
@@ -1531,6 +1629,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -1550,6 +1649,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -1580,6 +1680,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"densu": {
@@ -1599,6 +1700,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -1618,6 +1720,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -1646,6 +1749,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"densu": {
@@ -1665,6 +1769,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -1684,6 +1789,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -1714,6 +1820,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"densu": {
@@ -1733,6 +1840,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -1752,6 +1860,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -1782,6 +1891,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"densu": {
@@ -1801,6 +1911,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -1820,6 +1931,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -1848,6 +1960,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"densu": {
@@ -1867,6 +1980,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -1886,6 +2000,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -1916,6 +2031,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"densu": {
@@ -1935,6 +2051,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -1954,6 +2071,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -1984,6 +2102,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"densu": {
@@ -2003,6 +2122,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -2022,6 +2142,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -2050,6 +2171,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"densu": {
@@ -2069,6 +2191,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -2088,6 +2211,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -2118,6 +2242,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"densu": {
@@ -2137,6 +2262,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -2156,6 +2282,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -2186,6 +2313,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"densu": {
@@ -2205,6 +2333,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -2224,6 +2353,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -2252,6 +2382,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"densu": {
@@ -2271,6 +2402,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -2290,6 +2422,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -2320,6 +2453,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"densu": {
@@ -2339,6 +2473,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -2358,6 +2493,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -2388,6 +2524,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"densu": {
@@ -2407,6 +2544,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -2426,6 +2564,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -2456,6 +2595,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"densu": {
@@ -2475,6 +2615,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
diff --git a/tests/e2e/tracehandler_testdata/shorthappy.json b/tests/e2e/tracehandler_testdata/shorthappy.json
index 607c1d6d7c..e029c5951b 100644
--- a/tests/e2e/tracehandler_testdata/shorthappy.json
+++ b/tests/e2e/tracehandler_testdata/shorthappy.json
@@ -41,6 +41,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -57,7 +58,8 @@
"InitialHeight": {
"revision_height": 1
},
- "DistributionChannel": ""
+ "DistributionChannel": "",
+ "TopN": 100
},
"State": {
"provi": {
@@ -78,6 +80,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": {
"1": {
"RawProposal": {
@@ -123,6 +126,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -134,10 +138,31 @@
"Validator": "carol",
"ConsumerPubkey": "{\"@type\":\"/cosmos.crypto.ed25519.PubKey\",\"key\":\"Ui5Gf1+mtWUdH8u3xlmzdKID+F3PK0sfXZ73GZ6q6is=\"}",
"ReconfigureNode": false,
- "ExpectError": true,
- "ExpectedError": "a validator has assigned the consumer key already: consumer key is already in use by a validator"
+ "ExpectError": false,
+ "ExpectedError": ""
},
- "State": {}
+ "State": {
+ "consu": {
+ "ValBalances": null,
+ "ProposedConsumerChains": null,
+ "ValPowers": null,
+ "StakedTokens": null,
+ "Params": null,
+ "Rewards": null,
+ "ConsumerChains": null,
+ "AssignedKeys": {
+ "carol": "cosmosvalcons1kswr5sq599365kcjmhgufevfps9njf43e4lwdk"
+ },
+ "ProviderKeys": {
+ "carol": "cosmosvalcons1ezyrq65s3gshhx5585w6mpusq3xsj3ayzf4uv6"
+ },
+ "ConsumerPendingPacketQueueSize": null,
+ "RegisteredConsumerRewardDenoms": null,
+ "ClientsFrozenHeights": null,
+ "HasToValidate": null,
+ "Proposals": null
+ }
+ }
},
{
"ActionType": "main.AssignConsumerPubKeyAction",
@@ -168,6 +193,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -205,6 +231,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": {
"1": {
"RawProposal": {
@@ -264,6 +291,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -283,6 +311,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -336,6 +365,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -355,6 +385,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -384,6 +415,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -414,6 +446,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -443,6 +476,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -473,6 +507,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -492,6 +527,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -522,6 +558,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -553,6 +590,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -572,6 +610,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -602,6 +641,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -630,6 +670,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -649,6 +690,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -678,6 +720,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -697,6 +740,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -727,6 +771,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -755,6 +800,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -774,6 +820,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -804,6 +851,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -832,6 +880,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -851,6 +900,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -881,6 +931,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -909,6 +960,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -928,6 +980,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -958,6 +1011,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -986,6 +1040,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -1005,6 +1060,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -1035,6 +1091,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -1054,6 +1111,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -1090,6 +1148,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": {
"2": {
"RawProposal": {
@@ -1138,6 +1197,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": {
"2": {
"RawProposal": {
@@ -1179,6 +1239,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": {
"3": {
"RawProposal": {
@@ -1225,6 +1286,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": {
"3": {
"RawProposal": {
diff --git a/tests/e2e/tracehandler_testdata/slashThrottle.json b/tests/e2e/tracehandler_testdata/slashThrottle.json
index e99e7e2973..fb701a4dc1 100644
--- a/tests/e2e/tracehandler_testdata/slashThrottle.json
+++ b/tests/e2e/tracehandler_testdata/slashThrottle.json
@@ -41,6 +41,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -57,7 +58,8 @@
"InitialHeight": {
"revision_height": 1
},
- "DistributionChannel": ""
+ "DistributionChannel": "",
+ "TopN": 100
},
"State": {
"provi": {
@@ -78,6 +80,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": {
"1": {
"RawProposal": {
@@ -123,6 +126,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -134,10 +138,31 @@
"Validator": "carol",
"ConsumerPubkey": "{\"@type\":\"/cosmos.crypto.ed25519.PubKey\",\"key\":\"Ui5Gf1+mtWUdH8u3xlmzdKID+F3PK0sfXZ73GZ6q6is=\"}",
"ReconfigureNode": false,
- "ExpectError": true,
- "ExpectedError": "a validator has assigned the consumer key already: consumer key is already in use by a validator"
+ "ExpectError": false,
+ "ExpectedError": ""
},
- "State": {}
+ "State": {
+ "consu": {
+ "ValBalances": null,
+ "ProposedConsumerChains": null,
+ "ValPowers": null,
+ "StakedTokens": null,
+ "Params": null,
+ "Rewards": null,
+ "ConsumerChains": null,
+ "AssignedKeys": {
+ "carol": "cosmosvalcons1kswr5sq599365kcjmhgufevfps9njf43e4lwdk"
+ },
+ "ProviderKeys": {
+ "carol": "cosmosvalcons1ezyrq65s3gshhx5585w6mpusq3xsj3ayzf4uv6"
+ },
+ "ConsumerPendingPacketQueueSize": null,
+ "RegisteredConsumerRewardDenoms": null,
+ "ClientsFrozenHeights": null,
+ "HasToValidate": null,
+ "Proposals": null
+ }
+ }
},
{
"ActionType": "main.AssignConsumerPubKeyAction",
@@ -168,6 +193,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -205,6 +231,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": {
"1": {
"RawProposal": {
@@ -264,6 +291,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -283,6 +311,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -336,6 +365,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -355,6 +385,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -384,6 +415,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -414,6 +446,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -443,6 +476,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -471,6 +505,7 @@
"ConsumerPendingPacketQueueSize": 1,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -490,6 +525,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -520,6 +556,7 @@
"ConsumerPendingPacketQueueSize": 0,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -539,6 +576,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -567,6 +605,7 @@
"ConsumerPendingPacketQueueSize": 1,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -586,6 +625,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -616,6 +656,7 @@
"ConsumerPendingPacketQueueSize": 1,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -635,6 +676,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -663,6 +705,7 @@
"ConsumerPendingPacketQueueSize": 1,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -682,6 +725,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -705,6 +749,7 @@
"ConsumerPendingPacketQueueSize": 1,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -724,6 +769,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -750,6 +796,7 @@
"ConsumerPendingPacketQueueSize": 0,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
},
"provi": {
@@ -769,6 +816,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": null
}
}
@@ -800,6 +848,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": {
"2": {
"RawProposal": {
@@ -846,6 +895,7 @@
"ConsumerPendingPacketQueueSize": null,
"RegisteredConsumerRewardDenoms": null,
"ClientsFrozenHeights": null,
+ "HasToValidate": null,
"Proposals": {
"2": {
"RawProposal": {
diff --git a/tests/integration/common.go b/tests/integration/common.go
index 18b657ae56..7c4e88c344 100644
--- a/tests/integration/common.go
+++ b/tests/integration/common.go
@@ -22,10 +22,10 @@ import (
abci "github.com/cometbft/cometbft/abci/types"
tmtypes "github.com/cometbft/cometbft/types"
- icstestingutils "github.com/cosmos/interchain-security/v4/testutil/ibc_testing"
- testutil "github.com/cosmos/interchain-security/v4/testutil/integration"
- providertypes "github.com/cosmos/interchain-security/v4/x/ccv/provider/types"
- ccv "github.com/cosmos/interchain-security/v4/x/ccv/types"
+ icstestingutils "github.com/cosmos/interchain-security/v5/testutil/ibc_testing"
+ testutil "github.com/cosmos/interchain-security/v5/testutil/integration"
+ providertypes "github.com/cosmos/interchain-security/v5/x/ccv/provider/types"
+ ccv "github.com/cosmos/interchain-security/v5/x/ccv/types"
)
// ChainType defines the type of chain (either provider or consumer)
diff --git a/tests/integration/democracy.go b/tests/integration/democracy.go
index bbada900a8..53333aba0e 100644
--- a/tests/integration/democracy.go
+++ b/tests/integration/democracy.go
@@ -14,9 +14,9 @@ import (
govv1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1"
minttypes "github.com/cosmos/cosmos-sdk/x/mint/types"
- icstestingutils "github.com/cosmos/interchain-security/v4/testutil/ibc_testing"
- testutil "github.com/cosmos/interchain-security/v4/testutil/integration"
- consumertypes "github.com/cosmos/interchain-security/v4/x/ccv/consumer/types"
+ icstestingutils "github.com/cosmos/interchain-security/v5/testutil/ibc_testing"
+ testutil "github.com/cosmos/interchain-security/v5/testutil/integration"
+ consumertypes "github.com/cosmos/interchain-security/v5/x/ccv/consumer/types"
)
type ConsumerDemocracyTestSuite struct {
diff --git a/tests/integration/distribution.go b/tests/integration/distribution.go
index 1ea5bfcd00..edd7e3e0e1 100644
--- a/tests/integration/distribution.go
+++ b/tests/integration/distribution.go
@@ -4,15 +4,23 @@ import (
"strings"
transfertypes "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types"
+ clienttypes "github.com/cosmos/ibc-go/v7/modules/core/02-client/types"
+ channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types"
+
+ "cosmossdk.io/math"
sdk "github.com/cosmos/cosmos-sdk/types"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
+ distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types"
+
+ abci "github.com/cometbft/cometbft/abci/types"
- icstestingutils "github.com/cosmos/interchain-security/v4/testutil/integration"
- consumerkeeper "github.com/cosmos/interchain-security/v4/x/ccv/consumer/keeper"
- consumertypes "github.com/cosmos/interchain-security/v4/x/ccv/consumer/types"
- providertypes "github.com/cosmos/interchain-security/v4/x/ccv/provider/types"
- ccv "github.com/cosmos/interchain-security/v4/x/ccv/types"
+ icstestingutils "github.com/cosmos/interchain-security/v5/testutil/integration"
+ consumerkeeper "github.com/cosmos/interchain-security/v5/x/ccv/consumer/keeper"
+ consumertypes "github.com/cosmos/interchain-security/v5/x/ccv/consumer/types"
+ providerkeeper "github.com/cosmos/interchain-security/v5/x/ccv/provider/keeper"
+ providertypes "github.com/cosmos/interchain-security/v5/x/ccv/provider/types"
+ ccv "github.com/cosmos/interchain-security/v5/x/ccv/types"
)
// This test is valid for minimal viable consumer chain
@@ -42,6 +50,8 @@ func (s *CCVTestSuite) TestRewardsDistribution() {
providerAccountKeeper := s.providerApp.GetTestAccountKeeper()
consumerBankKeeper := s.consumerApp.GetTestBankKeeper()
providerBankKeeper := s.providerApp.GetTestBankKeeper()
+ providerKeeper := s.providerApp.GetProviderKeeper()
+ providerDistributionKeeper := s.providerApp.GetTestDistributionKeeper()
// send coins to the fee pool which is used for reward distribution
consumerFeePoolAddr := consumerAccountKeeper.GetModuleAccount(s.consumerCtx(), authtypes.FeeCollectorName).GetAddress()
@@ -70,7 +80,6 @@ func (s *CCVTestSuite) TestRewardsDistribution() {
s.Require().Equal(providerExpectedRewards.AmountOf(sdk.DefaultBondDenom), providerTokens.AmountOf(sdk.DefaultBondDenom))
// send the reward to provider chain after 2 blocks
-
s.consumerChain.NextBlock()
providerTokens = consumerBankKeeper.GetAllBalances(s.consumerCtx(), providerRedistributeAddr)
s.Require().Equal(0, len(providerTokens))
@@ -82,36 +91,85 @@ func (s *CCVTestSuite) TestRewardsDistribution() {
rewardPool := providerAccountKeeper.GetModuleAccount(s.providerCtx(), providertypes.ConsumerRewardsPool).GetAddress()
rewardCoins := providerBankKeeper.GetAllBalances(s.providerCtx(), rewardPool)
- ibcCoinIndex := -1
- for i, coin := range rewardCoins {
+ // Check that the reward pool contains a coin with an IBC denom
+ rewardsIBCdenom := ""
+ for _, coin := range rewardCoins {
if strings.HasPrefix(coin.Denom, "ibc") {
- ibcCoinIndex = i
+ rewardsIBCdenom = coin.Denom
}
}
-
- // Check that we found an ibc denom in the reward pool
- s.Require().Greater(ibcCoinIndex, -1)
+ s.Require().NotZero(rewardsIBCdenom)
// Check that the coins got into the ConsumerRewardsPool
- s.Require().True(rewardCoins[ibcCoinIndex].Amount.Equal(providerExpectedRewards[0].Amount))
+ providerExpRewardsAmount := providerExpectedRewards.AmountOf(sdk.DefaultBondDenom)
+ s.Require().Equal(rewardCoins.AmountOf(rewardsIBCdenom), providerExpRewardsAmount)
// Advance a block and check that the coins are still in the ConsumerRewardsPool
s.providerChain.NextBlock()
rewardCoins = providerBankKeeper.GetAllBalances(s.providerCtx(), rewardPool)
- s.Require().True(rewardCoins[ibcCoinIndex].Amount.Equal(providerExpectedRewards[0].Amount))
-
- // Set the consumer reward denom. This would be done by a governance proposal in prod
- s.providerApp.GetProviderKeeper().SetConsumerRewardDenom(s.providerCtx(), rewardCoins[ibcCoinIndex].Denom)
+ s.Require().Equal(rewardCoins.AmountOf(rewardsIBCdenom), providerExpRewardsAmount)
+
+ // Set the consumer reward denom. This would be done by a governance proposal in prod.
+ providerKeeper.SetConsumerRewardDenom(s.providerCtx(), rewardsIBCdenom)
+
+ // Refill the consumer fee pool
+ err = consumerBankKeeper.SendCoinsFromAccountToModule(
+ s.consumerCtx(),
+ s.consumerChain.SenderAccount.GetAddress(),
+ authtypes.FeeCollectorName,
+ fees,
+ )
+ s.Require().NoError(err)
- s.providerChain.NextBlock()
+ // Pass two blocks
+ s.consumerChain.NextBlock()
+ s.consumerChain.NextBlock()
- // Check that the reward pool has no more coins because they were transferred to the fee pool
+ // Save the consumer validators total outstanding rewards on the provider
+ consumerValsOutstandingRewardsFunc := func(ctx sdk.Context) sdk.DecCoins {
+ totalRewards := sdk.DecCoins{}
+ for _, v := range providerKeeper.GetConsumerValSet(ctx, s.consumerChain.ChainID) {
+ val, ok := s.providerApp.GetTestStakingKeeper().GetValidatorByConsAddr(ctx, sdk.ConsAddress(v.ProviderConsAddr))
+ s.Require().True(ok)
+ valReward := providerDistributionKeeper.GetValidatorOutstandingRewards(ctx, val.GetOperator())
+ totalRewards = totalRewards.Add(valReward.Rewards...)
+ }
+ return totalRewards
+ }
+ consuValsRewards := consumerValsOutstandingRewardsFunc(s.providerCtx())
+
+ // Save community pool balance
+ communityPool := providerDistributionKeeper.GetFeePoolCommunityCoins(s.providerCtx())
+
+ // Transfer rewards from consumer to provider
+ relayAllCommittedPackets(
+ s,
+ s.consumerChain,
+ s.transferPath,
+ transfertypes.PortID,
+ s.transferPath.EndpointA.ChannelID,
+ 1,
+ )
+
+ // Check that the consumer rewards allocation are empty since relayAllCommittedPackets calls BeginBlockRD,
+ // which in turns calls AllocateTokens.
+ rewardsAlloc := providerKeeper.GetConsumerRewardsAllocation(s.providerCtx(), s.consumerChain.ChainID)
+ s.Require().Empty(rewardsAlloc.Rewards)
+
+ // Check that the reward pool still holds the coins from the first transfer,
+ // which were never allocated since they were not whitelisted
rewardCoins = providerBankKeeper.GetAllBalances(s.providerCtx(), rewardPool)
- s.Require().Equal(0, len(rewardCoins))
+ s.Require().Equal(rewardCoins.AmountOf(rewardsIBCdenom), providerExpRewardsAmount)
- // check that the fee pool has the expected amount of coins
- communityCoins := s.providerApp.GetTestDistributionKeeper().GetFeePoolCommunityCoins(s.providerCtx())
- s.Require().True(communityCoins[ibcCoinIndex].Amount.Equal(sdk.NewDecCoinFromCoin(providerExpectedRewards[0]).Amount))
+ // Check that summing the rewards received by the consumer validators and the community pool
+ // is equal to the expected provider rewards
+ consuValsRewardsReceived := consumerValsOutstandingRewardsFunc(s.providerCtx()).Sub(consuValsRewards)
+ communityPoolDelta := providerDistributionKeeper.GetFeePoolCommunityCoins(s.providerCtx()).Sub(communityPool)
+
+ s.Require().Equal(
+ sdk.NewDecFromInt(providerExpRewardsAmount),
+ consuValsRewardsReceived.AmountOf(rewardsIBCdenom).Add(communityPoolDelta.AmountOf(rewardsIBCdenom)),
+ )
}
// TestSendRewardsRetries tests that failed reward transmissions are retried every BlocksPerDistributionTransmission blocks
@@ -454,6 +512,396 @@ func (s *CCVTestSuite) TestSendRewardsToProvider() {
}
}
+// TestIBCTransferMiddleware tests the logic of the IBC transfer OnRecvPacket callback
+func (s *CCVTestSuite) TestIBCTransferMiddleware() {
+ var (
+ data transfertypes.FungibleTokenPacketData
+ packet channeltypes.Packet
+ getIBCDenom func(string, string) string
+ )
+
+ testCases := []struct {
+ name string
+ setup func(sdk.Context, *providerkeeper.Keeper, icstestingutils.TestBankKeeper)
+ rewardsAllocated bool
+ expErr bool
+ }{
+ {
+ "invalid IBC packet",
+ func(sdk.Context, *providerkeeper.Keeper, icstestingutils.TestBankKeeper) {
+ packet = channeltypes.Packet{}
+ },
+ false,
+ true,
+ },
+ {
+ "IBC packet sender isn't a consumer chain",
+ func(ctx sdk.Context, keeper *providerkeeper.Keeper, bankKeeper icstestingutils.TestBankKeeper) {
+ // make the sender consumer chain impossible to identify
+ packet.DestinationChannel = "CorruptedChannelId"
+ },
+ false,
+ false,
+ },
+ {
+ "IBC Transfer recipient is not the consumer rewards pool address",
+ func(ctx sdk.Context, keeper *providerkeeper.Keeper, bankKeeper icstestingutils.TestBankKeeper) {
+ data.Receiver = "cosmos149lw9fktlqfed3zt8ah48r5czmsug5s7kw77u9" // random acct address
+ packet.Data = data.GetBytes()
+ },
+ false,
+ false,
+ },
+ {
+ "IBC Transfer coin denom isn't registered",
+ func(ctx sdk.Context, keeper *providerkeeper.Keeper, bankKeeper icstestingutils.TestBankKeeper) {},
+ false,
+ false,
+ },
+ {
+ "successful token transfer to empty pool",
+ func(ctx sdk.Context, keeper *providerkeeper.Keeper, bankKeeper icstestingutils.TestBankKeeper) {
+ keeper.SetConsumerRewardDenom(
+ s.providerCtx(),
+ getIBCDenom(packet.DestinationPort, packet.DestinationChannel),
+ )
+ },
+ true,
+ false,
+ },
+ {
+ "successful token transfer to filled pool",
+ func(ctx sdk.Context, keeper *providerkeeper.Keeper, bankKeeper icstestingutils.TestBankKeeper) {
+ keeper.SetConsumerRewardDenom(
+ ctx,
+ getIBCDenom(packet.DestinationPort, packet.DestinationChannel),
+ )
+
+ // fill consumer reward pool
+ bankKeeper.SendCoinsFromAccountToModule(
+ ctx,
+ s.providerChain.SenderAccount.GetAddress(),
+ providertypes.ConsumerRewardsPool,
+ sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, math.NewInt(100_000))),
+ )
+ // update consumer allocation
+ keeper.SetConsumerRewardsAllocation(
+ ctx,
+ s.consumerChain.ChainID,
+ providertypes.ConsumerRewardsAllocation{
+ Rewards: sdk.NewDecCoins(sdk.NewDecCoin(sdk.DefaultBondDenom, math.NewInt(100_000))),
+ },
+ )
+ },
+ true,
+ false,
+ },
+ }
+
+ for _, tc := range testCases {
+ s.Run(tc.name, func() {
+ s.SetupTest()
+ s.SetupCCVChannel(s.path)
+ s.SetupTransferChannel()
+
+ providerKeeper := s.providerApp.GetProviderKeeper()
+ bankKeeper := s.providerApp.GetTestBankKeeper()
+ amount := sdk.NewInt(100)
+
+ data = transfertypes.NewFungibleTokenPacketData( // can be explicitly changed in setup
+ sdk.DefaultBondDenom,
+ amount.String(),
+ authtypes.NewModuleAddress(consumertypes.ConsumerToSendToProviderName).String(),
+ providerKeeper.GetConsumerRewardsPoolAddressStr(s.providerCtx()),
+ "",
+ )
+
+ packet = channeltypes.NewPacket( // can be explicitly changed in setup
+ data.GetBytes(),
+ uint64(1),
+ s.transferPath.EndpointA.ChannelConfig.PortID,
+ s.transferPath.EndpointA.ChannelID,
+ s.transferPath.EndpointB.ChannelConfig.PortID,
+ s.transferPath.EndpointB.ChannelID,
+ clienttypes.NewHeight(1, 100),
+ 0,
+ )
+
+ providerKeeper.SetConsumerRewardDenom(s.providerCtx(),
+ transfertypes.GetPrefixedDenom(
+ packet.DestinationPort,
+ packet.DestinationChannel,
+ sdk.DefaultBondDenom,
+ ),
+ )
+
+ getIBCDenom = func(dstPort, dstChannel string) string {
+ return transfertypes.ParseDenomTrace(
+ transfertypes.GetPrefixedDenom(
+ packet.DestinationPort,
+ packet.DestinationChannel,
+ sdk.DefaultBondDenom,
+ ),
+ ).IBCDenom()
+ }
+
+ tc.setup(s.providerCtx(), &providerKeeper, bankKeeper)
+
+ cbs, ok := s.providerChain.App.GetIBCKeeper().Router.GetRoute(transfertypes.ModuleName)
+ s.Require().True(ok)
+
+ // save the IBC transfer rewards transferred
+ rewardsPoolBalance := bankKeeper.GetAllBalances(s.providerCtx(), sdk.MustAccAddressFromBech32(data.Receiver))
+
+ // save the consumer's rewards allocated
+ consumerRewardsAllocations := providerKeeper.GetConsumerRewardsAllocation(s.providerCtx(), s.consumerChain.ChainID)
+
+ // execute middleware OnRecvPacket logic
+ ack := cbs.OnRecvPacket(s.providerCtx(), packet, sdk.AccAddress{})
+
+ // compute expected rewards with provider denom
+ expRewards := sdk.Coin{
+ Amount: amount,
+ Denom: getIBCDenom(packet.DestinationPort, packet.DestinationChannel),
+ }
+
+ // compute the balance and allocation difference
+ rewardsTransferred := bankKeeper.GetAllBalances(s.providerCtx(), sdk.MustAccAddressFromBech32(data.Receiver)).
+ Sub(rewardsPoolBalance...)
+ rewardsAllocated := providerKeeper.GetConsumerRewardsAllocation(s.providerCtx(), s.consumerChain.ChainID).
+ Rewards.Sub(consumerRewardsAllocations.Rewards)
+
+ if !tc.expErr {
+ s.Require().True(ack.Success())
+ // verify that the consumer rewards pool received the IBC coins
+ s.Require().Equal(rewardsTransferred, sdk.Coins{expRewards})
+
+ if tc.rewardsAllocated {
+ // check the data receiver address is set to the consumer rewards pool address
+ s.Require().Equal(data.GetReceiver(), providerKeeper.GetConsumerRewardsPoolAddressStr(s.providerCtx()))
+
+ // verify that consumer rewards allocation is updated
+ s.Require().Equal(rewardsAllocated, sdk.NewDecCoinsFromCoins(expRewards))
+ } else {
+ // verify that consumer rewards aren't allocated
+ s.Require().Empty(rewardsAllocated)
+ }
+ } else {
+ s.Require().False(ack.Success())
+ }
+ })
+ }
+}
+
+// TestAllocateTokens is a happy-path test of the consumer rewards pool allocation
+// to opted-in validators and the community pool
+func (s *CCVTestSuite) TestAllocateTokens() {
+ // set up channel and delegate some tokens in order for validator set update to be sent to the consumer chain
+ s.SetupAllCCVChannels()
+ providerKeeper := s.providerApp.GetProviderKeeper()
+ bankKeeper := s.providerApp.GetTestBankKeeper()
+ distributionKeeper := s.providerApp.GetTestDistributionKeeper()
+
+ totalRewards := sdk.Coins{sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100))}
+
+ // fund consumer rewards pool
+ bankKeeper.SendCoinsFromAccountToModule(
+ s.providerCtx(),
+ s.providerChain.SenderAccount.GetAddress(),
+ providertypes.ConsumerRewardsPool,
+ totalRewards,
+ )
+
+ // Allocate rewards evenly between consumers
+ rewardsPerConsumer := totalRewards.QuoInt(math.NewInt(int64(len(s.consumerBundles))))
+ for chainID := range s.consumerBundles {
+ // update consumer allocation
+ providerKeeper.SetConsumerRewardsAllocation(
+ s.providerCtx(),
+ chainID,
+ providertypes.ConsumerRewardsAllocation{
+ Rewards: sdk.NewDecCoinsFromCoins(rewardsPerConsumer...),
+ },
+ )
+ }
+
+ // Iterate over the validators and
+ // store their current voting power and outstanding rewards
+ lastValOutRewards := map[string]sdk.DecCoins{}
+ votes := []abci.VoteInfo{}
+ for _, val := range s.providerChain.Vals.Validators {
+ votes = append(votes,
+ abci.VoteInfo{
+ Validator: abci.Validator{Address: val.Address, Power: val.VotingPower},
+ SignedLastBlock: true,
+ },
+ )
+
+ valRewards := distributionKeeper.GetValidatorOutstandingRewards(s.providerCtx(), sdk.ValAddress(val.Address))
+ lastValOutRewards[sdk.ValAddress(val.Address).String()] = valRewards.Rewards
+ }
+
+ // store community pool balance
+ lastCommPool := distributionKeeper.GetFeePoolCommunityCoins(s.providerCtx())
+
+ // execute BeginBlock to trigger the token allocation
+ providerKeeper.BeginBlockRD(
+ s.providerCtx(),
+ abci.RequestBeginBlock{
+ LastCommitInfo: abci.CommitInfo{
+ Votes: votes,
+ },
+ },
+ )
+
+ valNum := len(s.providerChain.Vals.Validators)
+ consuNum := len(s.consumerBundles)
+
+ // compute the expected validators token allocation by subtracting the community tax
+ rewardsPerConsumerDec := sdk.NewDecCoinsFromCoins(rewardsPerConsumer...)
+ communityTax := distributionKeeper.GetCommunityTax(s.providerCtx())
+ validatorsExpRewards := rewardsPerConsumerDec.
+ MulDecTruncate(math.LegacyOneDec().Sub(communityTax)).
+ // multiply by the number of consumers since all the validators opted in
+ MulDec(sdk.NewDec(int64(consuNum)))
+ perValExpReward := validatorsExpRewards.QuoDec(sdk.NewDec(int64(valNum)))
+
+ // verify the validator tokens allocation
+ // note that the validators have the same voting power to keep things simple
+ for _, val := range s.providerChain.Vals.Validators {
+ valRewards := distributionKeeper.GetValidatorOutstandingRewards(s.providerCtx(), sdk.ValAddress(val.Address))
+ s.Require().Equal(
+ valRewards.Rewards,
+ lastValOutRewards[sdk.ValAddress(val.Address).String()].Add(perValExpReward...),
+ )
+ }
+
+ commPoolExpRewards := sdk.NewDecCoinsFromCoins(totalRewards...).Sub(validatorsExpRewards)
+ currCommPool := distributionKeeper.GetFeePoolCommunityCoins(s.providerCtx())
+
+ s.Require().Equal(currCommPool, (lastCommPool.Add(commPoolExpRewards...)))
+}
+
+// TestAllocateTokens is a unit-test for TransferConsumerRewardsToDistributionModule()
+// but is written as an integration test to avoid excessive mocking.
+func (s *CCVTestSuite) TransferConsumerRewardsToDistributionModule() {
+ testCases := []struct {
+ name string
+ rewardsPool sdk.Coins
+ rewardsAlloc sdk.DecCoins
+ expErr bool
+ }{
+ {
+ "empty consumer rewards pool",
+ sdk.Coins{},
+ sdk.DecCoins{},
+ false,
+ },
+ {
+ "empty consumer allocation",
+ sdk.Coins{
+ sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100)),
+ },
+ sdk.DecCoins{},
+ false,
+ },
+ {
+ "equal consumer rewards pool and allocation",
+ sdk.Coins{
+ sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100)),
+ },
+ sdk.DecCoins{
+ sdk.NewDecCoin(sdk.DefaultBondDenom, sdk.NewInt(100)),
+ },
+ false,
+ },
+ {
+ "less consumer rewards than allocation",
+ sdk.Coins{
+ sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(90)),
+ },
+ sdk.DecCoins{
+ sdk.NewDecCoin(sdk.DefaultBondDenom, sdk.NewInt(100)),
+ },
+ true,
+ },
+ {
+ "remaining consumer rewards allocation",
+ sdk.Coins{
+ sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100)),
+ },
+ sdk.DecCoins{
+ sdk.DecCoin{
+ Denom: sdk.DefaultBondDenom,
+ Amount: sdk.NewDecWithPrec(995, 1),
+ },
+ },
+ false,
+ },
+ }
+
+ providerKeeper := s.providerApp.GetProviderKeeper()
+ bankKeeper := s.providerApp.GetTestBankKeeper()
+ distributionKeeper := s.providerApp.GetTestDistributionKeeper()
+
+ chainID := s.consumerChain.ChainID
+
+ for _, tc := range testCases {
+ s.Run(tc.name, func() {
+ ctx, _ := s.providerCtx().CacheContext()
+ // fund consumer rewards pool
+ bankKeeper.SendCoinsFromAccountToModule(
+ ctx,
+ s.providerChain.SenderAccount.GetAddress(),
+ providertypes.ConsumerRewardsPool,
+ tc.rewardsPool,
+ )
+
+ // update consumer rewars allocation
+ providerKeeper.SetConsumerRewardsAllocation(
+ ctx,
+ chainID,
+ providertypes.ConsumerRewardsAllocation{
+ Rewards: tc.rewardsAlloc,
+ },
+ )
+
+ // store pool balance
+ oldPool := bankKeeper.GetAllBalances(
+ ctx,
+ distributionKeeper.GetDistributionAccount(ctx).GetAddress(),
+ )
+
+ // transfer consumer rewars to distribution module
+ coinsTransferred, err := providerKeeper.TransferConsumerRewardsToDistributionModule(
+ ctx,
+ chainID,
+ )
+ if tc.expErr {
+ s.Require().Error(err)
+ return
+ }
+
+ // check remaining consumer rewards allocation
+ expCoinTransferred, expRemaining := tc.rewardsAlloc.TruncateDecimal()
+ s.Require().Equal(expCoinTransferred, coinsTransferred)
+
+ s.Require().Equal(
+ expRemaining,
+ providerKeeper.GetConsumerRewardsAllocation(ctx, chainID).Rewards,
+ )
+
+ // check updated consuemer rewards pool balance
+ newPool := bankKeeper.GetAllBalances(
+ ctx,
+ distributionKeeper.GetDistributionAccount(ctx).GetAddress(),
+ )
+
+ s.Require().Equal(newPool.Sub(oldPool...), coinsTransferred)
+ })
+ }
+}
+
// getEscrowBalance gets the current balances in the escrow account holding the transferred tokens to the provider
func (s *CCVTestSuite) getEscrowBalance() sdk.Coins {
consumerBankKeeper := s.consumerApp.GetTestBankKeeper()
@@ -485,3 +933,221 @@ func (s *CCVTestSuite) prepareRewardDist() {
blocksToGo := bpdt - blocksSinceLastTrans
s.coordinator.CommitNBlocks(s.consumerChain, uint64(blocksToGo))
}
+
+func (s *CCVTestSuite) TestAllocateTokensToValidator() {
+ providerKeeper := s.providerApp.GetProviderKeeper()
+ distributionKeeper := s.providerApp.GetTestDistributionKeeper()
+ bankKeeper := s.providerApp.GetTestBankKeeper()
+
+ chainID := s.consumerChain.ChainID
+
+ testCases := []struct {
+ name string
+ consuValLen int
+ tokens sdk.DecCoins
+ rate sdk.Dec
+ expAllocated sdk.DecCoins
+ }{
+ {
+ name: "tokens are empty",
+ tokens: sdk.DecCoins{},
+ rate: sdk.ZeroDec(),
+ expAllocated: nil,
+ },
+ {
+ name: "consumer valset is empty - total voting power is zero",
+ tokens: sdk.DecCoins{sdk.NewDecCoin(sdk.DefaultBondDenom, math.NewInt(100_000))},
+ rate: sdk.ZeroDec(),
+ expAllocated: nil,
+ },
+ {
+ name: "expect all tokens to be allocated to a single validator",
+ consuValLen: 1,
+ tokens: sdk.DecCoins{sdk.NewDecCoin(sdk.DefaultBondDenom, math.NewInt(999))},
+ rate: sdk.NewDecWithPrec(5, 1),
+ expAllocated: sdk.DecCoins{sdk.NewDecCoin(sdk.DefaultBondDenom, math.NewInt(999))},
+ },
+ {
+ name: "expect tokens to be allocated evenly between validators",
+ consuValLen: 2,
+ tokens: sdk.DecCoins{sdk.NewDecCoinFromDec(sdk.DefaultBondDenom, math.LegacyNewDecFromIntWithPrec(math.NewInt(999), 2))},
+ rate: sdk.OneDec(),
+ expAllocated: sdk.DecCoins{sdk.NewDecCoinFromDec(sdk.DefaultBondDenom, math.LegacyNewDecFromIntWithPrec(math.NewInt(999), 2))},
+ },
+ }
+
+ for _, tc := range testCases {
+ s.Run(tc.name, func() {
+ ctx, _ := s.providerCtx().CacheContext()
+
+ // change the consumer valset
+ consuVals := providerKeeper.GetConsumerValSet(ctx, chainID)
+ providerKeeper.DeleteConsumerValSet(ctx, chainID)
+ providerKeeper.SetConsumerValSet(ctx, chainID, consuVals[0:tc.consuValLen])
+ consuVals = providerKeeper.GetConsumerValSet(ctx, chainID)
+
+ // set the same consumer commission rate for all consumer validators
+ for _, v := range consuVals {
+ provAddr := providertypes.NewProviderConsAddress(sdk.ConsAddress(v.ProviderConsAddr))
+ err := providerKeeper.SetConsumerCommissionRate(
+ ctx,
+ chainID,
+ provAddr,
+ tc.rate,
+ )
+ s.Require().NoError(err)
+ }
+
+ // allocate tokens
+ res := providerKeeper.AllocateTokensToConsumerValidators(
+ ctx,
+ chainID,
+ tc.tokens,
+ )
+
+ // check that the expected result is returned
+ s.Require().Equal(tc.expAllocated, res)
+
+ if !tc.expAllocated.Empty() {
+ // rewards are expected to be allocated evenly between validators
+ rewardsPerVal := tc.expAllocated.QuoDec(sdk.NewDec(int64(len(consuVals))))
+
+ // check that the rewards are allocated to validators
+ for _, v := range consuVals {
+ valAddr := sdk.ValAddress(v.ProviderConsAddr)
+ rewards := s.providerApp.GetTestDistributionKeeper().GetValidatorOutstandingRewards(
+ ctx,
+ valAddr,
+ )
+ s.Require().Equal(rewardsPerVal, rewards.Rewards)
+
+ // send rewards to the distribution module
+ valRewardsTrunc, _ := rewards.Rewards.TruncateDecimal()
+ err := bankKeeper.SendCoinsFromAccountToModule(
+ ctx,
+ s.providerChain.SenderAccount.GetAddress(),
+ distrtypes.ModuleName,
+ valRewardsTrunc)
+ s.Require().NoError(err)
+
+ // check that validators can withdraw their rewards
+ withdrawnCoins, err := distributionKeeper.WithdrawValidatorCommission(
+ ctx,
+ valAddr,
+ )
+ s.Require().NoError(err)
+
+ // check that the withdrawn coins is equal to the entire reward amount
+ // times the set consumer commission rate
+ commission := rewards.Rewards.MulDec(tc.rate)
+ c, _ := commission.TruncateDecimal()
+ s.Require().Equal(withdrawnCoins, c)
+
+ // check that validators get rewards in their balance
+ s.Require().Equal(withdrawnCoins, bankKeeper.GetAllBalances(ctx, sdk.AccAddress(valAddr)))
+ }
+ } else {
+ for _, v := range consuVals {
+ valAddr := sdk.ValAddress(v.ProviderConsAddr)
+ rewards := s.providerApp.GetTestDistributionKeeper().GetValidatorOutstandingRewards(
+ ctx,
+ valAddr,
+ )
+ s.Require().Zero(rewards.Rewards)
+ }
+ }
+ })
+ }
+}
+
+// TestMultiConsumerRewardsDistribution tests the rewards distribution of multiple consumers chains
+func (s *CCVTestSuite) TestMultiConsumerRewardsDistribution() {
+ s.SetupAllCCVChannels()
+ s.SetupAllTransferChannels()
+
+ providerBankKeeper := s.providerApp.GetTestBankKeeper()
+ providerAccountKeeper := s.providerApp.GetTestAccountKeeper()
+
+ // check that the reward provider pool is empty
+ rewardPool := providerAccountKeeper.GetModuleAccount(s.providerCtx(), providertypes.ConsumerRewardsPool).GetAddress()
+ rewardCoins := providerBankKeeper.GetAllBalances(s.providerCtx(), rewardPool)
+ s.Require().Empty(rewardCoins)
+
+ totalConsumerRewards := sdk.Coins{}
+
+ // Iterate over the consumers and perform the reward distribution
+ // to the provider
+ for chainID := range s.consumerBundles {
+ bundle := s.consumerBundles[chainID]
+ consumerKeeper := bundle.App.GetConsumerKeeper()
+ bankKeeper := bundle.App.GetTestBankKeeper()
+ accountKeeper := bundle.App.GetTestAccountKeeper()
+
+ // set the consumer reward denom and the block per distribution params
+ params := consumerKeeper.GetConsumerParams(bundle.GetCtx())
+ params.RewardDenoms = []string{sdk.DefaultBondDenom}
+ // set the reward distribution to be performed during the next block
+ params.BlocksPerDistributionTransmission = int64(1)
+ consumerKeeper.SetParams(bundle.GetCtx(), params)
+
+ // transfer the consumer reward pool to the provider
+ var rewardsPerConsumer sdk.Coin
+
+ // check the consumer pool balance
+ // Note that for a democracy consumer chain the pool may already be filled
+ if pool := bankKeeper.GetAllBalances(
+ bundle.GetCtx(),
+ accountKeeper.GetModuleAccount(bundle.GetCtx(), consumertypes.ConsumerToSendToProviderName).GetAddress(),
+ ); pool.Empty() {
+ // if pool is empty, fill it with some tokens
+ rewardsPerConsumer = sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100))
+ err := bankKeeper.SendCoinsFromAccountToModule(
+ bundle.GetCtx(),
+ bundle.Chain.SenderAccount.GetAddress(),
+ consumertypes.ConsumerToSendToProviderName,
+ sdk.NewCoins(rewardsPerConsumer),
+ )
+ s.Require().NoError(err)
+ } else {
+ // execute the internal rewards distribution
+ // to save the pool's balance before
+ // it gets transferred to the provider in EndBlock
+ consumerKeeper.DistributeRewardsInternally(bundle.GetCtx())
+ pool = bankKeeper.GetAllBalances(
+ bundle.GetCtx(),
+ accountKeeper.GetModuleAccount(bundle.GetCtx(), consumertypes.ConsumerToSendToProviderName).GetAddress(),
+ )
+ s.Require().Len(pool, 1, "consumer reward pool cannot have mutiple token denoms")
+ rewardsPerConsumer = pool[0]
+ }
+
+ // perform the reward transfer
+ bundle.Chain.NextBlock()
+
+ // relay IBC transfer packet from consumer to provider
+ relayAllCommittedPackets(
+ s,
+ bundle.Chain,
+ bundle.TransferPath,
+ transfertypes.PortID,
+ bundle.TransferPath.EndpointA.ChannelID,
+ 1,
+ )
+
+ // construct the denom of the reward tokens for the provider
+ prefixedDenom := transfertypes.GetPrefixedDenom(
+ transfertypes.PortID,
+ bundle.TransferPath.EndpointB.ChannelID,
+ rewardsPerConsumer.Denom,
+ )
+ provIBCDenom := transfertypes.ParseDenomTrace(prefixedDenom).IBCDenom()
+
+ // sum the total rewards transferred to the provider
+ totalConsumerRewards = totalConsumerRewards.
+ Add(sdk.NewCoin(provIBCDenom, rewardsPerConsumer.Amount))
+ }
+
+ // Check that the provider receives the rewards of each consumer
+ rewardCoins = providerBankKeeper.GetAllBalances(s.providerCtx(), rewardPool)
+ s.Require().Equal(totalConsumerRewards, rewardCoins, totalConsumerRewards.String(), rewardCoins.String())
+}
diff --git a/tests/integration/double_vote.go b/tests/integration/double_vote.go
index c22ba3b063..c23d3feb06 100644
--- a/tests/integration/double_vote.go
+++ b/tests/integration/double_vote.go
@@ -7,8 +7,8 @@ import (
tmcrypto "github.com/cometbft/cometbft/crypto"
tmtypes "github.com/cometbft/cometbft/types"
- testutil "github.com/cosmos/interchain-security/v4/testutil/crypto"
- "github.com/cosmos/interchain-security/v4/x/ccv/provider/types"
+ testutil "github.com/cosmos/interchain-security/v5/testutil/crypto"
+ "github.com/cosmos/interchain-security/v5/x/ccv/provider/types"
)
// TestHandleConsumerDoubleVoting verifies that handling a double voting evidence
diff --git a/tests/integration/expired_client.go b/tests/integration/expired_client.go
index a46df32d8e..d5405df1c2 100644
--- a/tests/integration/expired_client.go
+++ b/tests/integration/expired_client.go
@@ -14,7 +14,7 @@ import (
abci "github.com/cometbft/cometbft/abci/types"
- ccv "github.com/cosmos/interchain-security/v4/x/ccv/types"
+ ccv "github.com/cosmos/interchain-security/v5/x/ccv/types"
)
// TestVSCPacketSendWithExpiredClient tests queueing of VSCPackets when the consumer client is expired.
diff --git a/tests/integration/instance_test.go b/tests/integration/instance_test.go
index d2896ad964..424c6c85f5 100644
--- a/tests/integration/instance_test.go
+++ b/tests/integration/instance_test.go
@@ -5,11 +5,11 @@ import (
"github.com/stretchr/testify/suite"
- appConsumer "github.com/cosmos/interchain-security/v4/app/consumer"
- appConsumerDemocracy "github.com/cosmos/interchain-security/v4/app/consumer-democracy"
- appProvider "github.com/cosmos/interchain-security/v4/app/provider"
- intg "github.com/cosmos/interchain-security/v4/tests/integration"
- icstestingutils "github.com/cosmos/interchain-security/v4/testutil/ibc_testing"
+ appConsumer "github.com/cosmos/interchain-security/v5/app/consumer"
+ appConsumerDemocracy "github.com/cosmos/interchain-security/v5/app/consumer-democracy"
+ appProvider "github.com/cosmos/interchain-security/v5/app/provider"
+ intg "github.com/cosmos/interchain-security/v5/tests/integration"
+ icstestingutils "github.com/cosmos/interchain-security/v5/testutil/ibc_testing"
)
// This file can be used as an example integration testing instance for any provider/consumer applications.
diff --git a/tests/integration/key_assignment.go b/tests/integration/key_assignment.go
index ab6cb63146..ad7a1a142e 100644
--- a/tests/integration/key_assignment.go
+++ b/tests/integration/key_assignment.go
@@ -9,8 +9,8 @@ import (
tmencoding "github.com/cometbft/cometbft/crypto/encoding"
tmprotocrypto "github.com/cometbft/cometbft/proto/tendermint/crypto"
- providerkeeper "github.com/cosmos/interchain-security/v4/x/ccv/provider/keeper"
- ccv "github.com/cosmos/interchain-security/v4/x/ccv/types"
+ providerkeeper "github.com/cosmos/interchain-security/v5/x/ccv/provider/keeper"
+ ccv "github.com/cosmos/interchain-security/v5/x/ccv/types"
)
func (s *CCVTestSuite) TestKeyAssignment() {
@@ -79,7 +79,7 @@ func (s *CCVTestSuite) TestKeyAssignment() {
}, false, 2,
},
{
- "double same-key assignment in same block", func(pk *providerkeeper.Keeper) error {
+ "double same-key assignment in same block by different vals", func(pk *providerkeeper.Keeper) error {
// establish CCV channel
s.SetupCCVChannel(s.path)
@@ -90,8 +90,9 @@ func (s *CCVTestSuite) TestKeyAssignment() {
return err
}
- // same key assignment
- err = pk.AssignConsumerKey(s.providerCtx(), s.consumerChain.ChainID, validator, consumerKey)
+ // same key assignment, but different validator
+ validator2, _ := generateNewConsumerKey(s, 1)
+ err = pk.AssignConsumerKey(s.providerCtx(), s.consumerChain.ChainID, validator2, consumerKey)
if err != nil {
return err
}
@@ -100,6 +101,28 @@ func (s *CCVTestSuite) TestKeyAssignment() {
return nil
}, true, 2,
},
+ {
+ "double same-key assignment in same block by same val", func(pk *providerkeeper.Keeper) error {
+ // establish CCV channel
+ s.SetupCCVChannel(s.path)
+
+ // key assignment
+ validator, consumerKey := generateNewConsumerKey(s, 0)
+ err := pk.AssignConsumerKey(s.providerCtx(), s.consumerChain.ChainID, validator, consumerKey)
+ if err != nil {
+ return err
+ }
+
+ // same key assignment, but different validator
+ err = pk.AssignConsumerKey(s.providerCtx(), s.consumerChain.ChainID, validator, consumerKey)
+ if err != nil {
+ return err
+ }
+ s.nextEpoch()
+
+ return nil
+ }, false, 2,
+ },
{
"double key assignment in same block", func(pk *providerkeeper.Keeper) error {
// establish CCV channel
@@ -124,7 +147,7 @@ func (s *CCVTestSuite) TestKeyAssignment() {
}, false, 2,
},
{
- "double same-key assignment in different blocks", func(pk *providerkeeper.Keeper) error {
+ "double same-key assignment in different blocks by different vals", func(pk *providerkeeper.Keeper) error {
// establish CCV channel
s.SetupCCVChannel(s.path)
@@ -137,7 +160,8 @@ func (s *CCVTestSuite) TestKeyAssignment() {
s.nextEpoch()
// same key assignment
- err = pk.AssignConsumerKey(s.providerCtx(), s.consumerChain.ChainID, validator, consumerKey)
+ validator2, _ := generateNewConsumerKey(s, 1)
+ err = pk.AssignConsumerKey(s.providerCtx(), s.consumerChain.ChainID, validator2, consumerKey)
if err != nil {
return err
}
@@ -146,6 +170,29 @@ func (s *CCVTestSuite) TestKeyAssignment() {
return nil
}, true, 2,
},
+ {
+ "double same-key assignment in different blocks by same val", func(pk *providerkeeper.Keeper) error {
+ // establish CCV channel
+ s.SetupCCVChannel(s.path)
+
+ // key assignment
+ validator, consumerKey := generateNewConsumerKey(s, 0)
+ err := pk.AssignConsumerKey(s.providerCtx(), s.consumerChain.ChainID, validator, consumerKey)
+ if err != nil {
+ return err
+ }
+ s.nextEpoch()
+
+ // same key assignment
+ err = pk.AssignConsumerKey(s.providerCtx(), s.consumerChain.ChainID, validator, consumerKey)
+ if err != nil {
+ return err
+ }
+ s.nextEpoch()
+
+ return nil
+ }, false, 2,
+ },
{
"double key assignment in different blocks", func(pk *providerkeeper.Keeper) error {
// establish CCV channel
diff --git a/tests/integration/misbehaviour.go b/tests/integration/misbehaviour.go
index acdcd0071c..cea0d15e5f 100644
--- a/tests/integration/misbehaviour.go
+++ b/tests/integration/misbehaviour.go
@@ -9,8 +9,8 @@ import (
tmtypes "github.com/cometbft/cometbft/types"
- testutil "github.com/cosmos/interchain-security/v4/testutil/crypto"
- "github.com/cosmos/interchain-security/v4/x/ccv/provider/types"
+ testutil "github.com/cosmos/interchain-security/v5/testutil/crypto"
+ "github.com/cosmos/interchain-security/v5/x/ccv/provider/types"
)
// TestHandleConsumerMisbehaviour tests that handling a valid misbehaviour,
diff --git a/tests/integration/normal_operations.go b/tests/integration/normal_operations.go
index 81c742eeed..61f7507793 100644
--- a/tests/integration/normal_operations.go
+++ b/tests/integration/normal_operations.go
@@ -5,8 +5,8 @@ import (
tmproto "github.com/cometbft/cometbft/proto/tendermint/types"
- consumertypes "github.com/cosmos/interchain-security/v4/x/ccv/consumer/types"
- ccvtypes "github.com/cosmos/interchain-security/v4/x/ccv/types"
+ consumertypes "github.com/cosmos/interchain-security/v5/x/ccv/consumer/types"
+ ccvtypes "github.com/cosmos/interchain-security/v5/x/ccv/types"
)
// Tests the tracking of historical info in the context of new blocks being committed
diff --git a/tests/integration/setup.go b/tests/integration/setup.go
index e3bf2bff8e..a70dab3dec 100644
--- a/tests/integration/setup.go
+++ b/tests/integration/setup.go
@@ -20,12 +20,12 @@ import (
abci "github.com/cometbft/cometbft/abci/types"
tmencoding "github.com/cometbft/cometbft/crypto/encoding"
- icstestingutils "github.com/cosmos/interchain-security/v4/testutil/ibc_testing"
- testutil "github.com/cosmos/interchain-security/v4/testutil/integration"
- "github.com/cosmos/interchain-security/v4/testutil/simibc"
- consumertypes "github.com/cosmos/interchain-security/v4/x/ccv/consumer/types"
- "github.com/cosmos/interchain-security/v4/x/ccv/provider/types"
- ccv "github.com/cosmos/interchain-security/v4/x/ccv/types"
+ icstestingutils "github.com/cosmos/interchain-security/v5/testutil/ibc_testing"
+ testutil "github.com/cosmos/interchain-security/v5/testutil/integration"
+ "github.com/cosmos/interchain-security/v5/testutil/simibc"
+ consumertypes "github.com/cosmos/interchain-security/v5/x/ccv/consumer/types"
+ "github.com/cosmos/interchain-security/v5/x/ccv/provider/types"
+ ccv "github.com/cosmos/interchain-security/v5/x/ccv/types"
)
// Callback for instantiating a new coordinator with a provider test chains
@@ -154,12 +154,16 @@ func (suite *CCVTestSuite) SetupTest() {
preProposalKeyAssignment(suite, icstestingutils.FirstConsumerChainID)
// start consumer chains
- numConsumers := 5
suite.consumerBundles = make(map[string]*icstestingutils.ConsumerBundle)
- for i := 0; i < numConsumers; i++ {
+ for i := 0; i < icstestingutils.NumConsumers; i++ {
bundle := suite.setupConsumerCallback(&suite.Suite, suite.coordinator, i)
suite.consumerBundles[bundle.Chain.ChainID] = bundle
suite.registerPacketSniffer(bundle.Chain)
+
+ // check that TopN is correctly set for the consumer
+ topN, found := providerKeeper.GetTopN(suite.providerCtx(), bundle.Chain.ChainID)
+ suite.Require().True(found)
+ suite.Require().Equal(bundle.TopN, topN)
}
// initialize each consumer chain with it's corresponding genesis state
@@ -240,7 +244,6 @@ func initConsumerChain(
)
s.Require().True(found, "provider endpoint clientID not found")
bundle.Path.EndpointB.ClientID = providerEndpointClientID
-
// Set consumer endpoint's clientID
consumerKeeper := bundle.GetKeeper()
consumerEndpointClientID, found := consumerKeeper.GetProviderClientID(bundle.GetCtx())
@@ -320,34 +323,70 @@ func (suite *CCVTestSuite) ExecuteCCVChannelHandshake(path *ibctesting.Path) {
// TODO: Make SetupTransferChannel functional for multiple consumers by pattern matching SetupCCVChannel.
// See: https://github.com/cosmos/interchain-security/issues/506
+// SetupTransferChannel setup the transfer channel of the first consumer chain among multiple
func (suite *CCVTestSuite) SetupTransferChannel() {
- // transfer path will use the same connection as ccv path
+ suite.setupTransferChannel(
+ suite.transferPath,
+ suite.path,
+ suite.consumerApp.GetConsumerKeeper().GetDistributionTransmissionChannel(
+ suite.consumerChain.GetContext(),
+ ),
+ )
+}
- suite.transferPath.EndpointA.ClientID = suite.path.EndpointA.ClientID
- suite.transferPath.EndpointA.ConnectionID = suite.path.EndpointA.ConnectionID
- suite.transferPath.EndpointB.ClientID = suite.path.EndpointB.ClientID
- suite.transferPath.EndpointB.ConnectionID = suite.path.EndpointB.ConnectionID
+func (suite *CCVTestSuite) setupTransferChannel(
+ transferPath *ibctesting.Path,
+ ccvPath *ibctesting.Path,
+ channelID string,
+) {
+ // transfer path will use the same connection as ccv path
+ transferPath.EndpointA.ClientID = ccvPath.EndpointA.ClientID
+ transferPath.EndpointA.ConnectionID = ccvPath.EndpointA.ConnectionID
+ transferPath.EndpointB.ClientID = ccvPath.EndpointB.ClientID
+ transferPath.EndpointB.ConnectionID = ccvPath.EndpointB.ConnectionID
// CCV channel handshake will automatically initiate transfer channel handshake on ACK
// so transfer channel will be on stage INIT when CompleteSetupCCVChannel returns.
- suite.transferPath.EndpointA.ChannelID = suite.consumerApp.GetConsumerKeeper().GetDistributionTransmissionChannel(
- suite.consumerChain.GetContext())
+ transferPath.EndpointA.ChannelID = channelID
// Complete TRY, ACK, CONFIRM for transfer path
- err := suite.transferPath.EndpointB.ChanOpenTry()
+ err := transferPath.EndpointB.ChanOpenTry()
suite.Require().NoError(err)
- err = suite.transferPath.EndpointA.ChanOpenAck()
+ err = transferPath.EndpointA.ChanOpenAck()
suite.Require().NoError(err)
- err = suite.transferPath.EndpointB.ChanOpenConfirm()
+ err = transferPath.EndpointB.ChanOpenConfirm()
suite.Require().NoError(err)
// ensure counterparty is up to date
- err = suite.transferPath.EndpointA.UpdateClient()
+ err = transferPath.EndpointA.UpdateClient()
suite.Require().NoError(err)
}
+// SetupAllTransferChannel setup all consumer chains transfer channel
+func (suite *CCVTestSuite) SetupAllTransferChannels() {
+ // setup the first consumer transfer channel
+ suite.SetupTransferChannel()
+
+ // setup all the remaining consumers transfer channels
+ for chainID := range suite.consumerBundles {
+ // skip fist consumer
+ if chainID == suite.consumerChain.ChainID {
+ continue
+ }
+
+ // get the bundle for the chain ID
+ bundle := suite.consumerBundles[chainID]
+ // setup the transfer channel
+ suite.setupTransferChannel(
+ bundle.TransferPath,
+ bundle.Path,
+ bundle.App.GetConsumerKeeper().GetDistributionTransmissionChannel(bundle.GetCtx()),
+ )
+ }
+}
+
func (s CCVTestSuite) validateEndpointsClientConfig(consumerBundle icstestingutils.ConsumerBundle) { //nolint:govet // this is a test so we can copy locks
consumerKeeper := consumerBundle.GetKeeper()
providerStakingKeeper := s.providerApp.GetTestStakingKeeper()
diff --git a/tests/integration/slashing.go b/tests/integration/slashing.go
index e7f585f756..a9dcf223f2 100644
--- a/tests/integration/slashing.go
+++ b/tests/integration/slashing.go
@@ -18,9 +18,9 @@ import (
"github.com/cometbft/cometbft/crypto/ed25519"
tmtypes "github.com/cometbft/cometbft/types"
- keepertestutil "github.com/cosmos/interchain-security/v4/testutil/keeper"
- providertypes "github.com/cosmos/interchain-security/v4/x/ccv/provider/types"
- ccv "github.com/cosmos/interchain-security/v4/x/ccv/types"
+ keepertestutil "github.com/cosmos/interchain-security/v5/testutil/keeper"
+ providertypes "github.com/cosmos/interchain-security/v5/x/ccv/provider/types"
+ ccv "github.com/cosmos/interchain-security/v5/x/ccv/types"
)
// TestRelayAndApplyDowntimePacket tests that downtime slash packets can be properly relayed
@@ -406,6 +406,15 @@ func (suite *CCVTestSuite) TestOnRecvSlashPacketErrors() {
// Check expected behavior for handling SlashPackets for downtime infractions
slashPacketData.Infraction = stakingtypes.Infraction_INFRACTION_DOWNTIME
+ // Expect packet to be handled if the validator didn't opt in
+ ackResult, err = providerKeeper.OnRecvSlashPacket(ctx, packet, *slashPacketData)
+ suite.Require().NoError(err, "no error expected")
+ suite.Require().Equal(ccv.SlashPacketHandledResult, ackResult, "expected successful ack")
+
+ providerKeeper.SetConsumerValidator(ctx, firstBundle.Chain.ChainID, providertypes.ConsumerValidator{
+ ProviderConsAddr: validAddress,
+ })
+
// Expect the packet to bounce if the slash meter is negative
providerKeeper.SetSlashMeter(ctx, sdk.NewInt(-1))
ackResult, err = providerKeeper.OnRecvSlashPacket(ctx, packet, *slashPacketData)
diff --git a/tests/integration/soft_opt_out.go b/tests/integration/soft_opt_out.go
index bce2e1d77c..3799de79fc 100644
--- a/tests/integration/soft_opt_out.go
+++ b/tests/integration/soft_opt_out.go
@@ -10,8 +10,8 @@ import (
abci "github.com/cometbft/cometbft/abci/types"
- consumerKeeper "github.com/cosmos/interchain-security/v4/x/ccv/consumer/keeper"
- ccv "github.com/cosmos/interchain-security/v4/x/ccv/types"
+ consumerKeeper "github.com/cosmos/interchain-security/v5/x/ccv/consumer/keeper"
+ ccv "github.com/cosmos/interchain-security/v5/x/ccv/types"
)
// TestSoftOptOut tests the soft opt-out feature
diff --git a/tests/integration/stop_consumer.go b/tests/integration/stop_consumer.go
index 6e72679ccd..33f36fa186 100644
--- a/tests/integration/stop_consumer.go
+++ b/tests/integration/stop_consumer.go
@@ -6,7 +6,7 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
- ccv "github.com/cosmos/interchain-security/v4/x/ccv/types"
+ ccv "github.com/cosmos/interchain-security/v5/x/ccv/types"
)
// Tests the functionality of stopping a consumer chain at a higher level than unit tests
diff --git a/tests/integration/throttle.go b/tests/integration/throttle.go
index ff2d32dade..e9e013575c 100644
--- a/tests/integration/throttle.go
+++ b/tests/integration/throttle.go
@@ -10,10 +10,10 @@ import (
tmtypes "github.com/cometbft/cometbft/types"
- icstestingutils "github.com/cosmos/interchain-security/v4/testutil/ibc_testing"
- "github.com/cosmos/interchain-security/v4/x/ccv/provider"
- providertypes "github.com/cosmos/interchain-security/v4/x/ccv/provider/types"
- ccvtypes "github.com/cosmos/interchain-security/v4/x/ccv/types"
+ icstestingutils "github.com/cosmos/interchain-security/v5/testutil/ibc_testing"
+ "github.com/cosmos/interchain-security/v5/x/ccv/provider"
+ providertypes "github.com/cosmos/interchain-security/v5/x/ccv/provider/types"
+ ccvtypes "github.com/cosmos/interchain-security/v5/x/ccv/types"
)
const fullSlashMeterString = "1.0"
diff --git a/tests/integration/throttle_retry.go b/tests/integration/throttle_retry.go
index 36acad3602..3d26847136 100644
--- a/tests/integration/throttle_retry.go
+++ b/tests/integration/throttle_retry.go
@@ -7,7 +7,7 @@ import (
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
- ccvtypes "github.com/cosmos/interchain-security/v4/x/ccv/types"
+ ccvtypes "github.com/cosmos/interchain-security/v5/x/ccv/types"
)
// TestSlashRetries tests the throttling v2 retry logic at an integration level.
diff --git a/tests/integration/unbonding.go b/tests/integration/unbonding.go
index 7f87516444..ca94fd3679 100644
--- a/tests/integration/unbonding.go
+++ b/tests/integration/unbonding.go
@@ -7,8 +7,8 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
- providerkeeper "github.com/cosmos/interchain-security/v4/x/ccv/provider/keeper"
- ccv "github.com/cosmos/interchain-security/v4/x/ccv/types"
+ providerkeeper "github.com/cosmos/interchain-security/v5/x/ccv/provider/keeper"
+ ccv "github.com/cosmos/interchain-security/v5/x/ccv/types"
)
// TestUndelegationNormalOperation tests that undelegations complete after
diff --git a/tests/integration/valset_update.go b/tests/integration/valset_update.go
index eb0560a35e..113dcc01f4 100644
--- a/tests/integration/valset_update.go
+++ b/tests/integration/valset_update.go
@@ -10,7 +10,7 @@ import (
abci "github.com/cometbft/cometbft/abci/types"
- ccv "github.com/cosmos/interchain-security/v4/x/ccv/types"
+ ccv "github.com/cosmos/interchain-security/v5/x/ccv/types"
)
// TestPacketRoundtrip tests a CCV packet roundtrip when tokens are bonded on provider
diff --git a/tests/mbt/driver/core.go b/tests/mbt/driver/core.go
index 3c985cb6fa..9235071d3e 100644
--- a/tests/mbt/driver/core.go
+++ b/tests/mbt/driver/core.go
@@ -24,14 +24,14 @@ import (
"github.com/cometbft/cometbft/proto/tendermint/crypto"
cmttypes "github.com/cometbft/cometbft/types"
- appConsumer "github.com/cosmos/interchain-security/v4/app/consumer"
- appProvider "github.com/cosmos/interchain-security/v4/app/provider"
- simibc "github.com/cosmos/interchain-security/v4/testutil/simibc"
- consumerkeeper "github.com/cosmos/interchain-security/v4/x/ccv/consumer/keeper"
- consumertypes "github.com/cosmos/interchain-security/v4/x/ccv/consumer/types"
- providerkeeper "github.com/cosmos/interchain-security/v4/x/ccv/provider/keeper"
- providertypes "github.com/cosmos/interchain-security/v4/x/ccv/provider/types"
- "github.com/cosmos/interchain-security/v4/x/ccv/types"
+ appConsumer "github.com/cosmos/interchain-security/v5/app/consumer"
+ appProvider "github.com/cosmos/interchain-security/v5/app/provider"
+ simibc "github.com/cosmos/interchain-security/v5/testutil/simibc"
+ consumerkeeper "github.com/cosmos/interchain-security/v5/x/ccv/consumer/keeper"
+ consumertypes "github.com/cosmos/interchain-security/v5/x/ccv/consumer/types"
+ providerkeeper "github.com/cosmos/interchain-security/v5/x/ccv/provider/keeper"
+ providertypes "github.com/cosmos/interchain-security/v5/x/ccv/provider/types"
+ "github.com/cosmos/interchain-security/v5/x/ccv/types"
)
// Define a new type for ChainIds to be more explicit
diff --git a/tests/mbt/driver/mbt_test.go b/tests/mbt/driver/mbt_test.go
index 9a82bd7b9b..e9a50f5c52 100644
--- a/tests/mbt/driver/mbt_test.go
+++ b/tests/mbt/driver/mbt_test.go
@@ -21,9 +21,9 @@ import (
tmencoding "github.com/cometbft/cometbft/crypto/encoding"
cmttypes "github.com/cometbft/cometbft/types"
- "github.com/cosmos/interchain-security/v4/testutil/integration"
- providertypes "github.com/cosmos/interchain-security/v4/x/ccv/provider/types"
- "github.com/cosmos/interchain-security/v4/x/ccv/types"
+ "github.com/cosmos/interchain-security/v5/testutil/integration"
+ providertypes "github.com/cosmos/interchain-security/v5/x/ccv/provider/types"
+ "github.com/cosmos/interchain-security/v5/x/ccv/types"
)
const verbose = false
diff --git a/tests/mbt/driver/setup.go b/tests/mbt/driver/setup.go
index f6f68f14c5..d30b85bf30 100644
--- a/tests/mbt/driver/setup.go
+++ b/tests/mbt/driver/setup.go
@@ -30,11 +30,12 @@ import (
cmtproto "github.com/cometbft/cometbft/proto/tendermint/types"
cmttypes "github.com/cometbft/cometbft/types"
- icstestingutils "github.com/cosmos/interchain-security/v4/testutil/ibc_testing"
- "github.com/cosmos/interchain-security/v4/testutil/integration"
- simibc "github.com/cosmos/interchain-security/v4/testutil/simibc"
- consumertypes "github.com/cosmos/interchain-security/v4/x/ccv/consumer/types"
- ccvtypes "github.com/cosmos/interchain-security/v4/x/ccv/types"
+ icstestingutils "github.com/cosmos/interchain-security/v5/testutil/ibc_testing"
+ "github.com/cosmos/interchain-security/v5/testutil/integration"
+ simibc "github.com/cosmos/interchain-security/v5/testutil/simibc"
+ consumertypes "github.com/cosmos/interchain-security/v5/x/ccv/consumer/types"
+ "github.com/cosmos/interchain-security/v5/x/ccv/provider/types"
+ ccvtypes "github.com/cosmos/interchain-security/v5/x/ccv/types"
)
const (
@@ -377,7 +378,8 @@ func (s *Driver) ConfigureNewPath(consumerChain, providerChain *ibctesting.TestC
stakingValidators = append(stakingValidators, v)
}
- nextValidators := s.providerKeeper().ComputeNextEpochConsumerValSet(s.providerCtx(), string(consumerChainId), stakingValidators)
+ considerAll := func(providerAddr types.ProviderConsAddress) bool { return true }
+ nextValidators := s.providerKeeper().FilterValidators(s.providerCtx(), string(consumerChainId), stakingValidators, considerAll)
s.providerKeeper().SetConsumerValSet(s.providerCtx(), string(consumerChainId), nextValidators)
err = s.providerKeeper().SetConsumerGenesis(
@@ -386,6 +388,9 @@ func (s *Driver) ConfigureNewPath(consumerChain, providerChain *ibctesting.TestC
consumerGenesisForProvider)
require.NoError(s.t, err, "Error setting consumer genesis on provider for chain %v", consumerChain.ChainID)
+ // set the top N percentage to 100 to simulate a full consumer
+ s.providerKeeper().SetTopN(providerChain.GetContext(), consumerChain.ChainID, 100)
+
// Client ID is set in InitGenesis and we treat it as a black box. So
// must query it to use it with the endpoint.
clientID, _ := s.consumerKeeper(consumerChainId).GetProviderClientID(s.ctx(consumerChainId))
diff --git a/tests/mbt/model/README.md b/tests/mbt/model/README.md
index b8ce579440..f4add0e213 100644
--- a/tests/mbt/model/README.md
+++ b/tests/mbt/model/README.md
@@ -32,6 +32,8 @@ All the logic in EndBlock/BeginBlock happens here, like updating the validator s
* `DeliverVscPacket(receiver: Chain)`: Delivers a pending VSCPacket from the provider to the consumer `receiver`.
* `DeliverPacketToProvider(sender: Chain)`: Delivers a pending packet from the consumer `sender` to the provider.
* `KeyAssignment(chain: Chain, validator: Node, consumerAddr: ConsumerAddr)` (only when running with `--step stepKeyAssignment`): Assigns the `consumerAddr` to the `validator` on the `chain`. Note that we use "key" and "consumerAddr" pretty much interchangeably, as the model makes no differentiation between private keys, public keys, addresses, etc, as it doesn't model the cryptography.
+* `OptIn(chain: Chain, validator: Node)` (only when running with `--step stepBoundedDriftKeyAndPSS` on `ccv_boundeddrift.qnt`): The `validator` opts in on the `chain`.
+* `OptOut(chain: Chain, validator: Node)` (only when running with `--step stepBoundedDriftKeyAndPSS` on `ccv_boundeddrift.qnt`): The `validator` opts out on the `chain`.
### State machines
@@ -51,6 +53,12 @@ To run with key assignment, specify the step flag: `--step stepKeyAssignment`.
KeyAssignment also needs some different invariants, see below.
+#### Partial Set Security
+
+To run with Partial Set Security, specify the step flag `--step stepBoundedDriftKeyAndPSS`.
+This runs both PSS and Key Assignment.
+It also requires running with `ccv_boundeddrift.qnt`, see below.
+
#### ccv_boundeddrift.qnt
This state machine layer is more restricted to generate more interesting traces:
* It never allows consumer chains to drift more than `MaxDrift` time apart from each other.
@@ -75,10 +83,8 @@ traces are not very useful for testing.
To run unit tests, run
```
-quint test ccv_test.qnt
-```
-and
-```
+quint test ccv_test.qnt;
+quint test ccv_pss_test.qnt;
quint test ccv_model.qnt
```
@@ -132,4 +138,8 @@ The available sanity checks are:
- CanSendVscMaturedPackets
- CanReceiveMaturations
- CanAssignConsumerKey (only with `--step stepKeyAssignment`)
-- CanHaveConsumerAddresses (only with `--step stepKeyAssignment`)
\ No newline at end of file
+- CanHaveConsumerAddresses (only with `--step stepKeyAssignment`)
+- CanOptIn (only with `--step stepBoundedDriftKeyAndPSS` on `ccv_boundeddrift.qnt`)
+- CanOptOut (only with `--step stepBoundedDriftKeyAndPSS` on `ccv_boundeddrift.qnt`)
+- CanFailOptOut (only with `--step stepBoundedDriftKeyAndPSS` on `ccv_boundeddrift.qnt`)
+- CanHaveOptIn (only with `--step stepBoundedDriftKeyAndPSS` on `ccv_boundeddrift.qnt`)
diff --git a/tests/mbt/model/ccv.qnt b/tests/mbt/model/ccv.qnt
index 87ddc91ea2..80aed91ec2 100644
--- a/tests/mbt/model/ccv.qnt
+++ b/tests/mbt/model/ccv.qnt
@@ -908,14 +908,18 @@ module ccv {
// (in general, the validator is a consumer address and could be an assigned one)
val slashFactor = DowntimeSlashPercentage
+
+ val curValPowerIsZero = currentState.providerState.chainState.currentValidatorPowers.get(providerVal) == 0
- val newProviderState = currentState.providerState
- .jailUntil(providerVal, jailEndTime)
+ val newProviderState = if (not(curValPowerIsZero))
+ currentState.providerState
+ .jailUntil(providerVal, jailEndTime) else
+ currentState.providerState // validators with zero power are not jailed
// // slashing is currently not enabled in ICS
// .slash(packet.validator, packet.valPower, slashFactor)
// if the validator did not have voting power of 0 or was already jailed before, the validator set will change due to the slash
- val valSetChanged = currentState.providerState.chainState.currentValidatorPowers.get(providerVal) != 0
+ val valSetChanged = not(curValPowerIsZero)
// add the consumer address to the list of acknowledged slashes
// for the sender chain of this slash packet and indicate that we need to send a packet at endblock
diff --git a/tests/mbt/model/ccv_model.qnt b/tests/mbt/model/ccv_model.qnt
index e2b812e212..312f6a5bdb 100644
--- a/tests/mbt/model/ccv_model.qnt
+++ b/tests/mbt/model/ccv_model.qnt
@@ -216,11 +216,14 @@ module ccv_model {
// stepCommon is the core functionality of steps that does not have anything to do with time.
action stepCommon = any {
- nondet node = oneOf(nonJailedNodes(currentState.providerState))
- // very restricted set of voting powers. exact values are not important,
- // and this keeps the state space smaller.
- nondet newVotingPower = oneOf(Set(-50, 50))
- VotingPowerChange(node, newVotingPower),
+ all {
+ currentState.providerState.validatorsWithPower().size() > 0,
+ nondet node = oneOf(currentState.providerState.validatorsWithPower())
+ // very restricted set of voting powers. exact values are not important,
+ // and this keeps the state space smaller.
+ nondet newVotingPower = oneOf(Set(-50, 50))
+ VotingPowerChange(node, newVotingPower),
+ },
// try to send a packet. we could filter by chains that can actually send,
// but it's probably not much faster than just trying and failing.
@@ -749,7 +752,8 @@ module ccv_model {
action nondetKeyAssignment =
all {
runningConsumers.size() > 0,
- nondet node = oneOf(nodes)
+ currentState.providerState.validatorsWithPower().size() > 0,
+ nondet node = oneOf(currentState.providerState.validatorsWithPower())
nondet consumerAddr = oneOf(consumerAddresses)
nondet consumer = oneOf(runningConsumers)
KeyAssignment(consumer, node, consumerAddr),
diff --git a/tests/mbt/model/ccv_pss.qnt b/tests/mbt/model/ccv_pss.qnt
new file mode 100644
index 0000000000..26aee28d56
--- /dev/null
+++ b/tests/mbt/model/ccv_pss.qnt
@@ -0,0 +1,157 @@
+// This module contains logic for PSS (Partial Set Security).
+// PSS is a variant/extension of CCV that
+// allows for only a subset of the validator set
+// to secure a consumer chain.
+// Not all logic related to PSS is inside this module, as some logic is
+// too tightly coupled with the core CCV logic,
+// which is instead found in ccv.qnt
+module ccv_pss {
+ import ccv_types.* from "./ccv"
+ import extraSpells.* from "./libraries/extraSpells"
+ import ccv_utils.* from "./ccv_utils"
+
+ // Given a base validator set, an N for a top N chain, and a set of validators that have opted in to the chain,
+ // returns the validator set that should be sent to the chain.
+ // Assumes that the value for N is valid.
+ pure def GetPSSValidatorSet(providerState: ProviderState, origValSet: ValidatorSet, consumer: Chain): ValidatorSet = {
+ pure val optedInVals = providerState.optedInVals.getOrElse(consumer, Set())
+ GetPSSValidatorSet_helper(origValSet, optedInVals)
+ }
+
+ pure def GetPSSValidatorSet_helper(origValSet: ValidatorSet, optedInVals: Set[Node]): ValidatorSet = {
+ origValSet.mapFilter(v => optedInVals.contains(v))
+ }
+
+ // Given a validator set and N, returns the top N% of validators by power.
+ // Note that in the edge case of multiple validators having the same power,
+ // this will always include all validators with the same power as the lowest top N validator.
+ pure def GetTopNVals(origValSet: ValidatorSet, N: int): Set[Node] = {
+ // == sort validators by power ==
+ // define a comparator that compares validators by power
+ pure def powerCompare(a: Node, b: Node): Ordering = {
+ pure val powA = origValSet.get(a)
+ pure val powB = origValSet.get(b)
+ intCompare(powB, powA)
+ }
+ // get a sorted list of validators by power
+ pure val sortedVals = origValSet.keys().toSortedList(powerCompare)
+
+ // == compute the threshold of how much power the top N have ==
+ pure val totalPower = origValSet.mapValuesSum()
+ pure val topNPower = totalPower * N / 100
+
+ // == construct the validator set by going through the sorted vals ==
+ pure val res = sortedVals.foldl(
+ // accumulator carries 4 values:
+ // * set of vals in top N (starts with empty set)
+ // * total power added so far (starts with 0)
+ // * whether we should add the next validator if it has the same power as the previous one,
+ // regardless of total power (starts with false)
+ // * the power of the last validator added (starts with 0)
+ (Set(), 0, false, 0),
+ (acc, validator) =>
+ pure val curValSet = acc._1
+ pure val accPower = acc._2
+ pure val shouldAddSamePow = acc._3
+ pure val lastPow = acc._4
+
+ pure val validatorPower = origValSet.get(validator)
+ if (validatorPower == lastPow and shouldAddSamePow) {
+ // we should add the validator because it has the same power as the previous one,
+ // and we add regardless of total power because we need to include all
+ // vals with the same power if we include one of them
+ pure val newAccPower = accPower + validatorPower
+ (curValSet.union(Set(validator)), newAccPower, true, validatorPower)
+ } else if (validatorPower > 0 and accPower < topNPower) {
+ // if we don't have enough power yet, add the validator to the set
+ pure val newAccPower = accPower + validatorPower
+ (curValSet.union(Set(validator)), newAccPower, true, validatorPower)
+ } else {
+ // if we have enough power and we also are done adding
+ // all validators with the same power as the lowest top N validator,
+ // don't add them
+ (curValSet, accPower, false, 0)
+ }
+ )
+ res._1
+ }
+
+ // Opts a validator in for a consumer chain the provider.
+ // Possible before the consumer chain starts running,
+ // and will then be applied when the consumer chain starts running.
+ pure def OptIn(currentState: ProtocolState, consumer: Chain, validator: Node): Result = {
+ pure val optedInVals = currentState.providerState.optedInVals.get(consumer)
+ pure val newOptedInVals = optedInVals.union(Set(validator))
+ Ok({
+ ...currentState,
+ providerState: {
+ ...currentState.providerState,
+ optedInVals: currentState.providerState.optedInVals.put(consumer, newOptedInVals)
+ }
+ })
+ }
+
+ // Returns true if the given validator is in the top N for the given consumer chain,
+ // and false otherwise.
+ pure def IsTopN(currentState: ProtocolState, validator: Node, consumer: Chain): bool = {
+ val proviValSet = currentState.providerState.chainState.votingPowerHistory.head()
+ val N = currentState.providerState.topNByConsumer.get(consumer)
+
+ val topNValSet = GetTopNVals(proviValSet, N)
+
+ topNValSet.contains(validator)
+ }
+
+ // Returns true if the given validator has opted in to the given consumer chain,
+ pure def IsOptedIn(currentState: ProtocolState, validator: Node, consumer: Chain): bool = {
+ currentState.providerState.optedInVals.getOrElse(consumer, Set()).contains(validator)
+ }
+
+ // Opts a validator out. Safe to call before the consumer chain even runs.
+ // Will not stop the validator set from being forced to validate when in the top N.
+ // Validators that are in the top N will not be able to opt out, and
+ // an error will be returned.
+ // Similarly, if the validator is not opted in, an error will be returned.
+ pure def OptOut(currentState: ProtocolState, consumer: Chain, validator: Node): Result = {
+ if (currentState.IsTopN(validator, consumer)) {
+ Err("Cannot opt out a validator that is in the top N")
+ } else if (not(currentState.IsOptedIn(validator, consumer))) {
+ Err("Cannot opt out a validator that is not opted in")
+ } else {
+ pure val optedInVals = currentState.providerState.optedInVals.get(consumer)
+ pure val newOptedInVals = optedInVals.exclude(Set(validator))
+ Ok({
+ ...currentState,
+ providerState: {
+ ...currentState.providerState,
+ optedInVals: currentState.providerState.optedInVals.put(consumer, newOptedInVals)
+ }
+ })
+ }
+ }
+
+ // Runs the PSS logic that needs to run on endblock.
+ // Concretely, this will forcefully opt in all validators that are in the top N
+ // for each chain.
+ pure def endBlockPSS(providerState: ProviderState): ProviderState = {
+ val runningConsumers = providerState.getRunningConsumers()
+ runningConsumers.fold(
+ providerState,
+ (acc, consumer) => endBlockPSS_helper(acc, consumer)
+ )
+ }
+
+ // Runs the PSS logic for a single consumer.
+ // Should only be run for running chains.
+ pure def endBlockPSS_helper(providerState: ProviderState, consumer: Chain): ProviderState = {
+ val proviValSet = providerState.chainState.currentValidatorPowers
+ val topNVals = GetTopNVals(proviValSet, providerState.topNByConsumer.get(consumer))
+ val prevOptedInVals = providerState.optedInVals.getOrElse(consumer, Set())
+ // opt in all the top N validators, i.e. union the top N vals with the previous opted in vals
+ val newOptedInVals = providerState.optedInVals.put(consumer, prevOptedInVals.union(topNVals))
+ {
+ ...providerState,
+ optedInVals: newOptedInVals
+ }
+ }
+}
\ No newline at end of file
diff --git a/tests/mbt/model/ccv_pss_model.qnt b/tests/mbt/model/ccv_pss_model.qnt
new file mode 100644
index 0000000000..9e60e241bc
--- /dev/null
+++ b/tests/mbt/model/ccv_pss_model.qnt
@@ -0,0 +1,113 @@
+module ccv_pss_model {
+ import ccv_types.* from "./ccv"
+ import ccv_model.* from "./ccv_model"
+ import ccv_pss.* from "./ccv_pss"
+ import extraSpells.* from "./libraries/extraSpells"
+
+ action StepOptIn(): bool = {
+ all {
+ runningConsumers.size() > 0,
+ nondet consumer = oneOf(runningConsumers)
+ nondet validator = oneOf(nodes)
+ OptIn_Deterministic(consumer, validator)
+ }
+ }
+
+ action OptIn_Deterministic(consumer: Chain, validator: Node): bool = {
+ val res = OptIn(currentState, consumer, validator)
+ all {
+ currentState' = res.newState,
+ trace' = trace.append(
+ {
+ ...emptyAction,
+ kind: "OptIn",
+ consumerChain: consumer,
+ validator: validator
+ }
+ ),
+ params' = params,
+ }
+ }
+
+ action StepOptOut(): bool = {
+ all {
+ runningConsumers.size() > 0,
+ nondet consumer = oneOf(runningConsumers)
+ nondet validator = oneOf(nodes)
+ OptOut_Deterministic(consumer, validator)
+ }
+ }
+
+ action OptOut_Deterministic(consumer: Chain, validator: Node): bool = {
+ val res = OptOut(currentState, consumer, validator)
+ all {
+ // if we expect an error, this should be a noop
+ currentState' = if (res.error == "") res.newState else currentState,
+ trace' = trace.append(
+ {
+ ...emptyAction,
+ kind: "OptOut",
+ consumerChain: consumer,
+ validator: validator,
+ expectedError: res.error
+ }
+ ),
+ params' = params,
+ }
+ }
+
+ // Different sets of possible values for the topN parameter.
+ val allFullConsumers: Set[int] = Set(100)
+ val allOptIn: Set[int] = Set(0)
+ // only choose a few values for top N here to not make the "edge cases" of 0 and 100 too unlikely
+ val variousPossibleTopN: Set[int] = Set(50, 70, 80, 90, 100)
+
+ // INVARIANTS
+
+ // For a consumer chain with a given top N value,
+ // the total VP on the consumer is at least N% of the total VP of some historical val set on the provider.
+ val AtLeastTopNPower: bool =
+ runningConsumers.forall(consumer => {
+ val topN = currentState.providerState.topNByConsumer.get(consumer)
+ val totalPowerConsu = currentState.consumerStates.get(consumer).chainState.currentValidatorPowers.mapValuesSum()
+ currentState.providerState.chainState.votingPowerHistory.toSet().exists(
+ valSet => {
+ val totalPowerProvi = valSet.mapValuesSum()
+
+ totalPowerConsu >= totalPowerProvi * topN / 100
+ }
+ )
+ })
+
+ // SANITY CHECKS
+
+ val CanOptIn = {
+ not(
+ trace[length(trace)-1].kind == "OptIn"
+ and
+ trace[length(trace)-1].expectedError == ""
+ )
+ }
+
+ val CanOptOut = {
+ not(
+ trace[length(trace)-1].kind == "OptOut"
+ and
+ trace[length(trace)-1].expectedError == ""
+ )
+ }
+
+ val CanFailOptOut = {
+ not(
+ trace[length(trace)-1].kind == "OptOut"
+ and
+ trace[length(trace)-1].expectedError != ""
+ )
+ }
+
+ val CanHaveOptIn = {
+ currentState.providerState.topNByConsumer.keys().exists(consumer => {
+ currentState.providerState.topNByConsumer.get(consumer) != 100
+ })
+ }
+}
\ No newline at end of file
diff --git a/tests/mbt/model/ccv_pss_test.qnt b/tests/mbt/model/ccv_pss_test.qnt
new file mode 100644
index 0000000000..61a5420150
--- /dev/null
+++ b/tests/mbt/model/ccv_pss_test.qnt
@@ -0,0 +1,61 @@
+// This module contains logic for PSS (Partial Set Security).
+// PSS is a variant/extension of CCV that
+// allows for only a subset of the validator set
+// to secure a consumer chain.
+// Not all logic related to PSS is inside this module, as some logic is
+// too tightly coupled with the core CCV logic,
+// which is instead found in ccv.qnt
+module ccv_pss_test {
+ import ccv_types.* from "./ccv"
+ import extraSpells.* from "./libraries/extraSpells"
+ import ccv_utils.* from "./ccv_utils"
+ import ccv_pss.* from "./ccv_pss"
+ import ccv.* from "./ccv"
+
+ run TopN1Test =
+ val valSet =
+ Map("d" -> 25, "c1" -> 15, "c" -> 15, "b2" -> 10, "b1" -> 10, "b" -> 10, "a2" -> 5, "a1" -> 5, "a" -> 5)
+ // total power: 5*3 + 10*3 + 15*2 + 25 = 100
+ all
+ {
+ assert(GetTopNVals(valSet, 0) == Set()),
+ assert(GetTopNVals(valSet, 1) == Set("d")),
+ assert(GetTopNVals(valSet, 10) == Set("d")),
+ assert(GetTopNVals(valSet, 25) == Set("d")),
+ // if one validator with a power is included, all validators with that power need to be included
+ assert(GetTopNVals(valSet, 26) == Set("d", "c1", "c")),
+ assert(GetTopNVals(valSet, 45) == Set("d", "c1", "c")),
+ assert(GetTopNVals(valSet, 55) == Set("d", "c1", "c")),
+ assert(GetTopNVals(valSet, 56) == Set("d", "c1", "c", "b2", "b1", "b")),
+ assert(GetTopNVals(valSet, 85) == Set("d", "c1", "c", "b2", "b1", "b")),
+ assert(GetTopNVals(valSet, 86) == valSet.keys()),
+ assert(GetTopNVals(valSet, 95) == valSet.keys()),
+ assert(GetTopNVals(valSet, 100) == valSet.keys()),
+ }
+
+ val providerState = GetEmptyProviderState().with(
+ "chainState", GetEmptyChainState().with(
+ "currentValidatorPowers", Map(
+ "a" -> 5,
+ "a1" -> 5,
+ "a2" -> 5,
+ "b" -> 10,
+ "b1" -> 10,
+ "b2" -> 10,
+ "c" -> 15,
+ "c1" -> 15,
+ "d" -> 25
+ )
+ )
+ ).with(
+ "consumerStatus", Map(
+ "consumer1" -> "running"
+ )
+ ).with(
+ "topNByConsumer", Map(
+ "consumer1" -> 80
+ )
+ )
+ run TopN2Test =
+ true
+}
\ No newline at end of file
diff --git a/tests/mbt/model/ccv_utils.qnt b/tests/mbt/model/ccv_utils.qnt
index ffb22e0dda..6c0f18b44c 100644
--- a/tests/mbt/model/ccv_utils.qnt
+++ b/tests/mbt/model/ccv_utils.qnt
@@ -531,6 +531,11 @@ module ccv_utils {
)
}
+ // Returns the set of all nodes that are neither jailed nor have 0 power on the provider.
+ pure def validatorsWithPower(providerState: ProviderState): Set[Node] = {
+ nonJailedNodes(providerState).filter(node => providerState.chainState.currentValidatorPowers.get(node) != 0)
+ }
+
pure def IsEmptyValSet(valSet: ValidatorSet): bool = {
valSet.keys().filter(
node => valSet.get(node) > 0
diff --git a/testutil/crypto/crypto.go b/testutil/crypto/crypto.go
index a9c5341947..df37e99eb5 100644
--- a/testutil/crypto/crypto.go
+++ b/testutil/crypto/crypto.go
@@ -15,7 +15,7 @@ import (
tmprotocrypto "github.com/cometbft/cometbft/proto/tendermint/crypto"
tmtypes "github.com/cometbft/cometbft/types"
- providertypes "github.com/cosmos/interchain-security/v4/x/ccv/provider/types"
+ providertypes "github.com/cosmos/interchain-security/v5/x/ccv/provider/types"
)
// CryptoIdentity is a test helper for generating keys and addresses of
diff --git a/testutil/ibc_testing/generic_setup.go b/testutil/ibc_testing/generic_setup.go
index 704657506f..9d5ec02a71 100644
--- a/testutil/ibc_testing/generic_setup.go
+++ b/testutil/ibc_testing/generic_setup.go
@@ -16,9 +16,10 @@ import (
tmencoding "github.com/cometbft/cometbft/crypto/encoding"
tmtypes "github.com/cometbft/cometbft/types"
- testutil "github.com/cosmos/interchain-security/v4/testutil/integration"
- testkeeper "github.com/cosmos/interchain-security/v4/testutil/keeper"
- consumerkeeper "github.com/cosmos/interchain-security/v4/x/ccv/consumer/keeper"
+ testutil "github.com/cosmos/interchain-security/v5/testutil/integration"
+ testkeeper "github.com/cosmos/interchain-security/v5/testutil/keeper"
+ consumerkeeper "github.com/cosmos/interchain-security/v5/x/ccv/consumer/keeper"
+ providertypes "github.com/cosmos/interchain-security/v5/x/ccv/provider/types"
)
type (
@@ -30,10 +31,16 @@ type (
// and/or democracy consumer app.go implementation. You should not need to modify or replicate this file
// to run integration tests against your app.go implementations!
+const (
+ // Default number of consumer chains
+ NumConsumers = 5
+)
+
var (
FirstConsumerChainID string
provChainID string
democConsumerChainID string
+ consumerTopNParams [NumConsumers]uint32
)
func init() {
@@ -42,6 +49,9 @@ func init() {
FirstConsumerChainID = ibctesting.GetChainID(2)
provChainID = ibctesting.GetChainID(1)
democConsumerChainID = ibctesting.GetChainID(5000)
+ // TopN parameter values per consumer chain initiated
+ // sorted in ascending order i.e. testchain2, testchain3, ..., testchain6
+ consumerTopNParams = [NumConsumers]uint32{100, 100, 100, 100, 100}
}
// ConsumerBundle serves as a way to store useful in-mem consumer app chain state
@@ -51,6 +61,7 @@ type ConsumerBundle struct {
App testutil.ConsumerApp
Path *ibctesting.Path
TransferPath *ibctesting.Path
+ TopN uint32
}
// GetCtx returns the context for the ConsumerBundle
@@ -116,6 +127,9 @@ func AddConsumer[Tp testutil.ProviderApp, Tc testutil.ConsumerApp](
index int,
appIniter ValSetAppIniter,
) *ConsumerBundle {
+ // check index isn't bigger that the number of consumers
+ s.Require().LessOrEqual(index, NumConsumers)
+
// consumer chain ID
chainID := ibctesting.GetChainID(index + 2)
@@ -126,6 +140,14 @@ func AddConsumer[Tp testutil.ProviderApp, Tc testutil.ConsumerApp](
prop := testkeeper.GetTestConsumerAdditionProp()
prop.ChainId = chainID
+ prop.Top_N = consumerTopNParams[index] // isn't used in CreateConsumerClient
+
+ // opt-in all validators
+ for _, v := range providerApp.GetTestStakingKeeper().GetLastValidators(providerChain.GetContext()) {
+ consAddr, _ := v.GetConsAddr()
+ providerKeeper.SetOptedIn(providerChain.GetContext(), chainID, providertypes.NewProviderConsAddress(consAddr))
+ }
+
// NOTE: the initial height passed to CreateConsumerClient
// must be the height on the consumer when InitGenesis is called
prop.InitialHeight = clienttypes.Height{RevisionNumber: 0, RevisionHeight: 3}
@@ -135,6 +157,10 @@ func AddConsumer[Tp testutil.ProviderApp, Tc testutil.ConsumerApp](
)
s.Require().NoError(err)
+ // set the consumer TopN here since the test suite setup only used the consumer addition prop
+ // to create the consumer genesis, see BeginBlockInit in /x/ccv/provider/keeper/proposal.go.
+ providerKeeper.SetTopN(providerChain.GetContext(), chainID, prop.Top_N)
+
// commit the state on the provider chain
coordinator.CommitBlock(providerChain)
@@ -174,5 +200,6 @@ func AddConsumer[Tp testutil.ProviderApp, Tc testutil.ConsumerApp](
return &ConsumerBundle{
Chain: testChain,
App: consumerToReturn,
+ TopN: prop.Top_N,
}
}
diff --git a/testutil/ibc_testing/specific_setup.go b/testutil/ibc_testing/specific_setup.go
index 2571346ca6..81788e10bc 100644
--- a/testutil/ibc_testing/specific_setup.go
+++ b/testutil/ibc_testing/specific_setup.go
@@ -17,11 +17,11 @@ import (
"github.com/cometbft/cometbft/abci/types"
"github.com/cometbft/cometbft/libs/log"
- appConsumer "github.com/cosmos/interchain-security/v4/app/consumer"
- appConsumerDemocracy "github.com/cosmos/interchain-security/v4/app/consumer-democracy"
- appProvider "github.com/cosmos/interchain-security/v4/app/provider"
- consumertypes "github.com/cosmos/interchain-security/v4/x/ccv/consumer/types"
- ccvtypes "github.com/cosmos/interchain-security/v4/x/ccv/types"
+ appConsumer "github.com/cosmos/interchain-security/v5/app/consumer"
+ appConsumerDemocracy "github.com/cosmos/interchain-security/v5/app/consumer-democracy"
+ appProvider "github.com/cosmos/interchain-security/v5/app/provider"
+ consumertypes "github.com/cosmos/interchain-security/v5/x/ccv/consumer/types"
+ ccvtypes "github.com/cosmos/interchain-security/v5/x/ccv/types"
)
var (
diff --git a/testutil/integration/debug_test.go b/testutil/integration/debug_test.go
index 77d460f05f..ed0ec3d65b 100644
--- a/testutil/integration/debug_test.go
+++ b/testutil/integration/debug_test.go
@@ -6,11 +6,11 @@ import (
"reflect"
"testing"
- appConsumer "github.com/cosmos/interchain-security/v4/app/consumer"
- appConsumerDemocracy "github.com/cosmos/interchain-security/v4/app/consumer-democracy"
- appProvider "github.com/cosmos/interchain-security/v4/app/provider"
- integr "github.com/cosmos/interchain-security/v4/tests/integration"
- icstestingutils "github.com/cosmos/interchain-security/v4/testutil/ibc_testing"
+ appConsumer "github.com/cosmos/interchain-security/v5/app/consumer"
+ appConsumerDemocracy "github.com/cosmos/interchain-security/v5/app/consumer-democracy"
+ appProvider "github.com/cosmos/interchain-security/v5/app/provider"
+ integr "github.com/cosmos/interchain-security/v5/tests/integration"
+ icstestingutils "github.com/cosmos/interchain-security/v5/testutil/ibc_testing"
)
// runCCVTestByName runs a single CCV integration test by name, using a CCVTestSuite
@@ -283,3 +283,23 @@ func TestHandleConsumerDoubleVotingSlashesUndelegationsAndRelegations(t *testing
func TestSlashRetries(t *testing.T) {
runCCVTestByName(t, "TestSlashRetries")
}
+
+func TestIBCTransferMiddleware(t *testing.T) {
+ runCCVTestByName(t, "TestIBCTransferMiddleware")
+}
+
+func TestAllocateTokens(t *testing.T) {
+ runCCVTestByName(t, "TestAllocateTokens")
+}
+
+func TestTransferConsumerRewardsToDistributionModule(t *testing.T) {
+ runCCVTestByName(t, "TransferConsumerRewardsToDistributionModule")
+}
+
+func TestAllocateTokensToValidator(t *testing.T) {
+ runCCVTestByName(t, "TestAllocateTokensToValidator")
+}
+
+func TestMultiConsumerRewardsDistribution(t *testing.T) {
+ runCCVTestByName(t, "TestMultiConsumerRewardsDistribution")
+}
diff --git a/testutil/integration/interfaces.go b/testutil/integration/interfaces.go
index 89d59904df..83d071a037 100644
--- a/testutil/integration/interfaces.go
+++ b/testutil/integration/interfaces.go
@@ -20,9 +20,9 @@ import (
abci "github.com/cometbft/cometbft/abci/types"
- consumerkeeper "github.com/cosmos/interchain-security/v4/x/ccv/consumer/keeper"
- providerkeeper "github.com/cosmos/interchain-security/v4/x/ccv/provider/keeper"
- ccvtypes "github.com/cosmos/interchain-security/v4/x/ccv/types"
+ consumerkeeper "github.com/cosmos/interchain-security/v5/x/ccv/consumer/keeper"
+ providerkeeper "github.com/cosmos/interchain-security/v5/x/ccv/provider/keeper"
+ ccvtypes "github.com/cosmos/interchain-security/v5/x/ccv/types"
)
// The interface that any provider app must implement to be compatible with ccv integration tests.
@@ -142,6 +142,7 @@ type TestDistributionKeeper interface {
GetValidatorOutstandingRewards(ctx sdk.Context,
val sdk.ValAddress) (rewards distributiontypes.ValidatorOutstandingRewards)
GetCommunityTax(ctx sdk.Context) (percent sdk.Dec)
+ WithdrawValidatorCommission(ctx sdk.Context, valAddr sdk.ValAddress) (sdk.Coins, error)
}
type TestMintKeeper interface {
diff --git a/testutil/keeper/expectations.go b/testutil/keeper/expectations.go
index 5a37f3a164..c595a5c080 100644
--- a/testutil/keeper/expectations.go
+++ b/testutil/keeper/expectations.go
@@ -17,8 +17,8 @@ import (
capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
- providertypes "github.com/cosmos/interchain-security/v4/x/ccv/provider/types"
- "github.com/cosmos/interchain-security/v4/x/ccv/types"
+ providertypes "github.com/cosmos/interchain-security/v5/x/ccv/provider/types"
+ "github.com/cosmos/interchain-security/v5/x/ccv/types"
)
//
diff --git a/testutil/keeper/mocks.go b/testutil/keeper/mocks.go
index 5f9d9b2694..ffa76ad40c 100644
--- a/testutil/keeper/mocks.go
+++ b/testutil/keeper/mocks.go
@@ -14,13 +14,14 @@ import (
types0 "github.com/cosmos/cosmos-sdk/types"
types1 "github.com/cosmos/cosmos-sdk/x/auth/types"
types2 "github.com/cosmos/cosmos-sdk/x/capability/types"
+ types3 "github.com/cosmos/cosmos-sdk/x/distribution/types"
v1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1"
- types3 "github.com/cosmos/cosmos-sdk/x/slashing/types"
- types4 "github.com/cosmos/cosmos-sdk/x/staking/types"
- types5 "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types"
- types6 "github.com/cosmos/ibc-go/v7/modules/core/02-client/types"
- types7 "github.com/cosmos/ibc-go/v7/modules/core/03-connection/types"
- types8 "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types"
+ types4 "github.com/cosmos/cosmos-sdk/x/slashing/types"
+ types5 "github.com/cosmos/cosmos-sdk/x/staking/types"
+ types6 "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types"
+ types7 "github.com/cosmos/ibc-go/v7/modules/core/02-client/types"
+ types8 "github.com/cosmos/ibc-go/v7/modules/core/03-connection/types"
+ types9 "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types"
exported "github.com/cosmos/ibc-go/v7/modules/core/exported"
gomock "github.com/golang/mock/gomock"
)
@@ -63,10 +64,10 @@ func (mr *MockStakingKeeperMockRecorder) BondDenom(ctx interface{}) *gomock.Call
}
// Delegation mocks base method.
-func (m *MockStakingKeeper) Delegation(ctx types0.Context, addr types0.AccAddress, valAddr types0.ValAddress) types4.DelegationI {
+func (m *MockStakingKeeper) Delegation(ctx types0.Context, addr types0.AccAddress, valAddr types0.ValAddress) types5.DelegationI {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Delegation", ctx, addr, valAddr)
- ret0, _ := ret[0].(types4.DelegationI)
+ ret0, _ := ret[0].(types5.DelegationI)
return ret0
}
@@ -105,10 +106,10 @@ func (mr *MockStakingKeeperMockRecorder) GetLastValidatorPower(ctx, operator int
}
// GetLastValidators mocks base method.
-func (m *MockStakingKeeper) GetLastValidators(ctx types0.Context) []types4.Validator {
+func (m *MockStakingKeeper) GetLastValidators(ctx types0.Context) []types5.Validator {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetLastValidators", ctx)
- ret0, _ := ret[0].([]types4.Validator)
+ ret0, _ := ret[0].([]types5.Validator)
return ret0
}
@@ -118,11 +119,26 @@ func (mr *MockStakingKeeperMockRecorder) GetLastValidators(ctx interface{}) *gom
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetLastValidators", reflect.TypeOf((*MockStakingKeeper)(nil).GetLastValidators), ctx)
}
+// GetRedelegationByUnbondingID mocks base method.
+func (m *MockStakingKeeper) GetRedelegationByUnbondingID(ctx types0.Context, id uint64) (types5.Redelegation, bool) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "GetRedelegationByUnbondingID", ctx, id)
+ ret0, _ := ret[0].(types5.Redelegation)
+ ret1, _ := ret[1].(bool)
+ return ret0, ret1
+}
+
+// GetRedelegationByUnbondingID indicates an expected call of GetRedelegationByUnbondingID.
+func (mr *MockStakingKeeperMockRecorder) GetRedelegationByUnbondingID(ctx, id interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetRedelegationByUnbondingID", reflect.TypeOf((*MockStakingKeeper)(nil).GetRedelegationByUnbondingID), ctx, id)
+}
+
// GetRedelegationsFromSrcValidator mocks base method.
-func (m *MockStakingKeeper) GetRedelegationsFromSrcValidator(ctx types0.Context, valAddr types0.ValAddress) []types4.Redelegation {
+func (m *MockStakingKeeper) GetRedelegationsFromSrcValidator(ctx types0.Context, valAddr types0.ValAddress) []types5.Redelegation {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetRedelegationsFromSrcValidator", ctx, valAddr)
- ret0, _ := ret[0].([]types4.Redelegation)
+ ret0, _ := ret[0].([]types5.Redelegation)
return ret0
}
@@ -132,11 +148,26 @@ func (mr *MockStakingKeeperMockRecorder) GetRedelegationsFromSrcValidator(ctx, v
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetRedelegationsFromSrcValidator", reflect.TypeOf((*MockStakingKeeper)(nil).GetRedelegationsFromSrcValidator), ctx, valAddr)
}
+// GetUnbondingDelegationByUnbondingID mocks base method.
+func (m *MockStakingKeeper) GetUnbondingDelegationByUnbondingID(ctx types0.Context, id uint64) (types5.UnbondingDelegation, bool) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "GetUnbondingDelegationByUnbondingID", ctx, id)
+ ret0, _ := ret[0].(types5.UnbondingDelegation)
+ ret1, _ := ret[1].(bool)
+ return ret0, ret1
+}
+
+// GetUnbondingDelegationByUnbondingID indicates an expected call of GetUnbondingDelegationByUnbondingID.
+func (mr *MockStakingKeeperMockRecorder) GetUnbondingDelegationByUnbondingID(ctx, id interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetUnbondingDelegationByUnbondingID", reflect.TypeOf((*MockStakingKeeper)(nil).GetUnbondingDelegationByUnbondingID), ctx, id)
+}
+
// GetUnbondingDelegationsFromValidator mocks base method.
-func (m *MockStakingKeeper) GetUnbondingDelegationsFromValidator(ctx types0.Context, valAddr types0.ValAddress) []types4.UnbondingDelegation {
+func (m *MockStakingKeeper) GetUnbondingDelegationsFromValidator(ctx types0.Context, valAddr types0.ValAddress) []types5.UnbondingDelegation {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetUnbondingDelegationsFromValidator", ctx, valAddr)
- ret0, _ := ret[0].([]types4.UnbondingDelegation)
+ ret0, _ := ret[0].([]types5.UnbondingDelegation)
return ret0
}
@@ -147,10 +178,10 @@ func (mr *MockStakingKeeperMockRecorder) GetUnbondingDelegationsFromValidator(ct
}
// GetUnbondingType mocks base method.
-func (m *MockStakingKeeper) GetUnbondingType(ctx types0.Context, id uint64) (types4.UnbondingType, bool) {
+func (m *MockStakingKeeper) GetUnbondingType(ctx types0.Context, id uint64) (types5.UnbondingType, bool) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetUnbondingType", ctx, id)
- ret0, _ := ret[0].(types4.UnbondingType)
+ ret0, _ := ret[0].(types5.UnbondingType)
ret1, _ := ret[1].(bool)
return ret0, ret1
}
@@ -162,10 +193,10 @@ func (mr *MockStakingKeeperMockRecorder) GetUnbondingType(ctx, id interface{}) *
}
// GetValidator mocks base method.
-func (m *MockStakingKeeper) GetValidator(ctx types0.Context, addr types0.ValAddress) (types4.Validator, bool) {
+func (m *MockStakingKeeper) GetValidator(ctx types0.Context, addr types0.ValAddress) (types5.Validator, bool) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetValidator", ctx, addr)
- ret0, _ := ret[0].(types4.Validator)
+ ret0, _ := ret[0].(types5.Validator)
ret1, _ := ret[1].(bool)
return ret0, ret1
}
@@ -177,10 +208,10 @@ func (mr *MockStakingKeeperMockRecorder) GetValidator(ctx, addr interface{}) *go
}
// GetValidatorByConsAddr mocks base method.
-func (m *MockStakingKeeper) GetValidatorByConsAddr(ctx types0.Context, consAddr types0.ConsAddress) (types4.Validator, bool) {
+func (m *MockStakingKeeper) GetValidatorByConsAddr(ctx types0.Context, consAddr types0.ConsAddress) (types5.Validator, bool) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetValidatorByConsAddr", ctx, consAddr)
- ret0, _ := ret[0].(types4.Validator)
+ ret0, _ := ret[0].(types5.Validator)
ret1, _ := ret[1].(bool)
return ret0, ret1
}
@@ -191,6 +222,21 @@ func (mr *MockStakingKeeperMockRecorder) GetValidatorByConsAddr(ctx, consAddr in
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetValidatorByConsAddr", reflect.TypeOf((*MockStakingKeeper)(nil).GetValidatorByConsAddr), ctx, consAddr)
}
+// GetValidatorByUnbondingID mocks base method.
+func (m *MockStakingKeeper) GetValidatorByUnbondingID(ctx types0.Context, id uint64) (types5.Validator, bool) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "GetValidatorByUnbondingID", ctx, id)
+ ret0, _ := ret[0].(types5.Validator)
+ ret1, _ := ret[1].(bool)
+ return ret0, ret1
+}
+
+// GetValidatorByUnbondingID indicates an expected call of GetValidatorByUnbondingID.
+func (mr *MockStakingKeeperMockRecorder) GetValidatorByUnbondingID(ctx, id interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetValidatorByUnbondingID", reflect.TypeOf((*MockStakingKeeper)(nil).GetValidatorByUnbondingID), ctx, id)
+}
+
// GetValidatorUpdates mocks base method.
func (m *MockStakingKeeper) GetValidatorUpdates(ctx types0.Context) []types.ValidatorUpdate {
m.ctrl.T.Helper()
@@ -232,7 +278,7 @@ func (mr *MockStakingKeeperMockRecorder) IterateLastValidatorPowers(ctx, cb inte
}
// IterateValidators mocks base method.
-func (m *MockStakingKeeper) IterateValidators(ctx types0.Context, f func(int64, types4.ValidatorI) bool) {
+func (m *MockStakingKeeper) IterateValidators(ctx types0.Context, f func(int64, types5.ValidatorI) bool) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "IterateValidators", ctx, f)
}
@@ -269,6 +315,20 @@ func (mr *MockStakingKeeperMockRecorder) MaxValidators(ctx interface{}) *gomock.
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MaxValidators", reflect.TypeOf((*MockStakingKeeper)(nil).MaxValidators), ctx)
}
+// MinCommissionRate mocks base method.
+func (m *MockStakingKeeper) MinCommissionRate(ctx types0.Context) math.LegacyDec {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "MinCommissionRate", ctx)
+ ret0, _ := ret[0].(math.LegacyDec)
+ return ret0
+}
+
+// MinCommissionRate indicates an expected call of MinCommissionRate.
+func (mr *MockStakingKeeperMockRecorder) MinCommissionRate(ctx interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MinCommissionRate", reflect.TypeOf((*MockStakingKeeper)(nil).MinCommissionRate), ctx)
+}
+
// PowerReduction mocks base method.
func (m *MockStakingKeeper) PowerReduction(ctx types0.Context) math.Int {
m.ctrl.T.Helper()
@@ -312,7 +372,7 @@ func (mr *MockStakingKeeperMockRecorder) Slash(arg0, arg1, arg2, arg3, arg4 inte
}
// SlashRedelegation mocks base method.
-func (m *MockStakingKeeper) SlashRedelegation(arg0 types0.Context, arg1 types4.Validator, arg2 types4.Redelegation, arg3 int64, arg4 types0.Dec) math.Int {
+func (m *MockStakingKeeper) SlashRedelegation(arg0 types0.Context, arg1 types5.Validator, arg2 types5.Redelegation, arg3 int64, arg4 types0.Dec) math.Int {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "SlashRedelegation", arg0, arg1, arg2, arg3, arg4)
ret0, _ := ret[0].(math.Int)
@@ -326,7 +386,7 @@ func (mr *MockStakingKeeperMockRecorder) SlashRedelegation(arg0, arg1, arg2, arg
}
// SlashUnbondingDelegation mocks base method.
-func (m *MockStakingKeeper) SlashUnbondingDelegation(arg0 types0.Context, arg1 types4.UnbondingDelegation, arg2 int64, arg3 types0.Dec) math.Int {
+func (m *MockStakingKeeper) SlashUnbondingDelegation(arg0 types0.Context, arg1 types5.UnbondingDelegation, arg2 int64, arg3 types0.Dec) math.Int {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "SlashUnbondingDelegation", arg0, arg1, arg2, arg3)
ret0, _ := ret[0].(math.Int)
@@ -340,7 +400,7 @@ func (mr *MockStakingKeeperMockRecorder) SlashUnbondingDelegation(arg0, arg1, ar
}
// SlashWithInfractionReason mocks base method.
-func (m *MockStakingKeeper) SlashWithInfractionReason(arg0 types0.Context, arg1 types0.ConsAddress, arg2, arg3 int64, arg4 types0.Dec, arg5 types4.Infraction) math.Int {
+func (m *MockStakingKeeper) SlashWithInfractionReason(arg0 types0.Context, arg1 types0.ConsAddress, arg2, arg3 int64, arg4 types0.Dec, arg5 types5.Infraction) math.Int {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "SlashWithInfractionReason", arg0, arg1, arg2, arg3, arg4, arg5)
ret0, _ := ret[0].(math.Int)
@@ -394,10 +454,10 @@ func (mr *MockStakingKeeperMockRecorder) Unjail(ctx, addr interface{}) *gomock.C
}
// Validator mocks base method.
-func (m *MockStakingKeeper) Validator(ctx types0.Context, addr types0.ValAddress) types4.ValidatorI {
+func (m *MockStakingKeeper) Validator(ctx types0.Context, addr types0.ValAddress) types5.ValidatorI {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Validator", ctx, addr)
- ret0, _ := ret[0].(types4.ValidatorI)
+ ret0, _ := ret[0].(types5.ValidatorI)
return ret0
}
@@ -408,10 +468,10 @@ func (mr *MockStakingKeeperMockRecorder) Validator(ctx, addr interface{}) *gomoc
}
// ValidatorByConsAddr mocks base method.
-func (m *MockStakingKeeper) ValidatorByConsAddr(ctx types0.Context, consAddr types0.ConsAddress) types4.ValidatorI {
+func (m *MockStakingKeeper) ValidatorByConsAddr(ctx types0.Context, consAddr types0.ConsAddress) types5.ValidatorI {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "ValidatorByConsAddr", ctx, consAddr)
- ret0, _ := ret[0].(types4.ValidatorI)
+ ret0, _ := ret[0].(types5.ValidatorI)
return ret0
}
@@ -459,10 +519,10 @@ func (mr *MockSlashingKeeperMockRecorder) DowntimeJailDuration(arg0 interface{})
}
// GetValidatorSigningInfo mocks base method.
-func (m *MockSlashingKeeper) GetValidatorSigningInfo(ctx types0.Context, address types0.ConsAddress) (types3.ValidatorSigningInfo, bool) {
+func (m *MockSlashingKeeper) GetValidatorSigningInfo(ctx types0.Context, address types0.ConsAddress) (types4.ValidatorSigningInfo, bool) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetValidatorSigningInfo", ctx, address)
- ret0, _ := ret[0].(types3.ValidatorSigningInfo)
+ ret0, _ := ret[0].(types4.ValidatorSigningInfo)
ret1, _ := ret[1].(bool)
return ret0, ret1
}
@@ -473,18 +533,6 @@ func (mr *MockSlashingKeeperMockRecorder) GetValidatorSigningInfo(ctx, address i
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetValidatorSigningInfo", reflect.TypeOf((*MockSlashingKeeper)(nil).GetValidatorSigningInfo), ctx, address)
}
-// SetValidatorSigningInfo mocks base method.
-func (m *MockSlashingKeeper) SetValidatorSigningInfo(ctx types0.Context, address types0.ConsAddress, info types3.ValidatorSigningInfo) {
- m.ctrl.T.Helper()
- m.ctrl.Call(m, "SetValidatorSigningInfo", ctx, address, info)
-}
-
-// SetValidatorSigningInfo indicates an expected call of SetValidatorSigningInfo.
-func (mr *MockSlashingKeeperMockRecorder) SetValidatorSigningInfo(ctx, address interface{}, info interface{}) *gomock.Call {
- mr.mock.ctrl.T.Helper()
- return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetValidatorSigningInfo", reflect.TypeOf((*MockSlashingKeeper)(nil).SetValidatorSigningInfo), ctx, address, info)
-}
-
// IsTombstoned mocks base method.
func (m *MockSlashingKeeper) IsTombstoned(arg0 types0.Context, arg1 types0.ConsAddress) bool {
m.ctrl.T.Helper()
@@ -511,6 +559,18 @@ func (mr *MockSlashingKeeperMockRecorder) JailUntil(arg0, arg1, arg2 interface{}
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "JailUntil", reflect.TypeOf((*MockSlashingKeeper)(nil).JailUntil), arg0, arg1, arg2)
}
+// SetValidatorSigningInfo mocks base method.
+func (m *MockSlashingKeeper) SetValidatorSigningInfo(ctx types0.Context, address types0.ConsAddress, info types4.ValidatorSigningInfo) {
+ m.ctrl.T.Helper()
+ m.ctrl.Call(m, "SetValidatorSigningInfo", ctx, address, info)
+}
+
+// SetValidatorSigningInfo indicates an expected call of SetValidatorSigningInfo.
+func (mr *MockSlashingKeeperMockRecorder) SetValidatorSigningInfo(ctx, address, info interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetValidatorSigningInfo", reflect.TypeOf((*MockSlashingKeeper)(nil).SetValidatorSigningInfo), ctx, address, info)
+}
+
// SlashFractionDoubleSign mocks base method.
func (m *MockSlashingKeeper) SlashFractionDoubleSign(ctx types0.Context) types0.Dec {
m.ctrl.T.Helper()
@@ -589,10 +649,10 @@ func (mr *MockChannelKeeperMockRecorder) ChanCloseInit(ctx, portID, channelID, c
}
// GetChannel mocks base method.
-func (m *MockChannelKeeper) GetChannel(ctx types0.Context, srcPort, srcChan string) (types8.Channel, bool) {
+func (m *MockChannelKeeper) GetChannel(ctx types0.Context, srcPort, srcChan string) (types9.Channel, bool) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetChannel", ctx, srcPort, srcChan)
- ret0, _ := ret[0].(types8.Channel)
+ ret0, _ := ret[0].(types9.Channel)
ret1, _ := ret[1].(bool)
return ret0, ret1
}
@@ -635,7 +695,7 @@ func (mr *MockChannelKeeperMockRecorder) GetNextSequenceSend(ctx, portID, channe
}
// SendPacket mocks base method.
-func (m *MockChannelKeeper) SendPacket(ctx types0.Context, chanCap *types2.Capability, sourcePort, sourceChannel string, timeoutHeight types6.Height, timeoutTimestamp uint64, data []byte) (uint64, error) {
+func (m *MockChannelKeeper) SendPacket(ctx types0.Context, chanCap *types2.Capability, sourcePort, sourceChannel string, timeoutHeight types7.Height, timeoutTimestamp uint64, data []byte) (uint64, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "SendPacket", ctx, chanCap, sourcePort, sourceChannel, timeoutHeight, timeoutTimestamp, data)
ret0, _ := ret[0].(uint64)
@@ -724,10 +784,10 @@ func (m *MockConnectionKeeper) EXPECT() *MockConnectionKeeperMockRecorder {
}
// GetConnection mocks base method.
-func (m *MockConnectionKeeper) GetConnection(ctx types0.Context, connectionID string) (types7.ConnectionEnd, bool) {
+func (m *MockConnectionKeeper) GetConnection(ctx types0.Context, connectionID string) (types8.ConnectionEnd, bool) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetConnection", ctx, connectionID)
- ret0, _ := ret[0].(types7.ConnectionEnd)
+ ret0, _ := ret[0].(types8.ConnectionEnd)
ret1, _ := ret[1].(bool)
return ret0, ret1
}
@@ -885,6 +945,18 @@ func (m *MockDistributionKeeper) EXPECT() *MockDistributionKeeperMockRecorder {
return m.recorder
}
+// AllocateTokensToValidator mocks base method.
+func (m *MockDistributionKeeper) AllocateTokensToValidator(ctx types0.Context, validator types5.ValidatorI, reward types0.DecCoins) {
+ m.ctrl.T.Helper()
+ m.ctrl.Call(m, "AllocateTokensToValidator", ctx, validator, reward)
+}
+
+// AllocateTokensToValidator indicates an expected call of AllocateTokensToValidator.
+func (mr *MockDistributionKeeperMockRecorder) AllocateTokensToValidator(ctx, validator, reward interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AllocateTokensToValidator", reflect.TypeOf((*MockDistributionKeeper)(nil).AllocateTokensToValidator), ctx, validator, reward)
+}
+
// FundCommunityPool mocks base method.
func (m *MockDistributionKeeper) FundCommunityPool(ctx types0.Context, amount types0.Coins, sender types0.AccAddress) error {
m.ctrl.T.Helper()
@@ -899,6 +971,46 @@ func (mr *MockDistributionKeeperMockRecorder) FundCommunityPool(ctx, amount, sen
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FundCommunityPool", reflect.TypeOf((*MockDistributionKeeper)(nil).FundCommunityPool), ctx, amount, sender)
}
+// GetCommunityTax mocks base method.
+func (m *MockDistributionKeeper) GetCommunityTax(ctx types0.Context) math.LegacyDec {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "GetCommunityTax", ctx)
+ ret0, _ := ret[0].(math.LegacyDec)
+ return ret0
+}
+
+// GetCommunityTax indicates an expected call of GetCommunityTax.
+func (mr *MockDistributionKeeperMockRecorder) GetCommunityTax(ctx interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCommunityTax", reflect.TypeOf((*MockDistributionKeeper)(nil).GetCommunityTax), ctx)
+}
+
+// GetFeePool mocks base method.
+func (m *MockDistributionKeeper) GetFeePool(ctx types0.Context) types3.FeePool {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "GetFeePool", ctx)
+ ret0, _ := ret[0].(types3.FeePool)
+ return ret0
+}
+
+// GetFeePool indicates an expected call of GetFeePool.
+func (mr *MockDistributionKeeperMockRecorder) GetFeePool(ctx interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetFeePool", reflect.TypeOf((*MockDistributionKeeper)(nil).GetFeePool), ctx)
+}
+
+// SetFeePool mocks base method.
+func (m *MockDistributionKeeper) SetFeePool(ctx types0.Context, feePool types3.FeePool) {
+ m.ctrl.T.Helper()
+ m.ctrl.Call(m, "SetFeePool", ctx, feePool)
+}
+
+// SetFeePool indicates an expected call of SetFeePool.
+func (mr *MockDistributionKeeperMockRecorder) SetFeePool(ctx, feePool interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetFeePool", reflect.TypeOf((*MockDistributionKeeper)(nil).SetFeePool), ctx, feePool)
+}
+
// MockConsumerHooks is a mock of ConsumerHooks interface.
type MockConsumerHooks struct {
ctrl *gomock.Controller
@@ -1062,10 +1174,10 @@ func (m *MockIBCTransferKeeper) EXPECT() *MockIBCTransferKeeperMockRecorder {
}
// Transfer mocks base method.
-func (m *MockIBCTransferKeeper) Transfer(arg0 context.Context, arg1 *types5.MsgTransfer) (*types5.MsgTransferResponse, error) {
+func (m *MockIBCTransferKeeper) Transfer(arg0 context.Context, arg1 *types6.MsgTransfer) (*types6.MsgTransferResponse, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Transfer", arg0, arg1)
- ret0, _ := ret[0].(*types5.MsgTransferResponse)
+ ret0, _ := ret[0].(*types6.MsgTransferResponse)
ret1, _ := ret[1].(error)
return ret0, ret1
}
@@ -1100,10 +1212,10 @@ func (m *MockIBCCoreKeeper) EXPECT() *MockIBCCoreKeeperMockRecorder {
}
// ChannelOpenInit mocks base method.
-func (m *MockIBCCoreKeeper) ChannelOpenInit(goCtx context.Context, msg *types8.MsgChannelOpenInit) (*types8.MsgChannelOpenInitResponse, error) {
+func (m *MockIBCCoreKeeper) ChannelOpenInit(goCtx context.Context, msg *types9.MsgChannelOpenInit) (*types9.MsgChannelOpenInitResponse, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "ChannelOpenInit", goCtx, msg)
- ret0, _ := ret[0].(*types8.MsgChannelOpenInitResponse)
+ ret0, _ := ret[0].(*types9.MsgChannelOpenInitResponse)
ret1, _ := ret[1].(error)
return ret0, ret1
}
diff --git a/testutil/keeper/unit_test_helpers.go b/testutil/keeper/unit_test_helpers.go
index ff3df99763..3a80eecce8 100644
--- a/testutil/keeper/unit_test_helpers.go
+++ b/testutil/keeper/unit_test_helpers.go
@@ -27,11 +27,11 @@ import (
"github.com/cometbft/cometbft/libs/log"
tmproto "github.com/cometbft/cometbft/proto/tendermint/types"
- consumerkeeper "github.com/cosmos/interchain-security/v4/x/ccv/consumer/keeper"
- consumertypes "github.com/cosmos/interchain-security/v4/x/ccv/consumer/types"
- providerkeeper "github.com/cosmos/interchain-security/v4/x/ccv/provider/keeper"
- providertypes "github.com/cosmos/interchain-security/v4/x/ccv/provider/types"
- "github.com/cosmos/interchain-security/v4/x/ccv/types"
+ consumerkeeper "github.com/cosmos/interchain-security/v5/x/ccv/consumer/keeper"
+ consumertypes "github.com/cosmos/interchain-security/v5/x/ccv/consumer/types"
+ providerkeeper "github.com/cosmos/interchain-security/v5/x/ccv/provider/keeper"
+ providertypes "github.com/cosmos/interchain-security/v5/x/ccv/provider/types"
+ "github.com/cosmos/interchain-security/v5/x/ccv/types"
)
// Parameters needed to instantiate an in-memory keeper
@@ -249,10 +249,15 @@ func TestProviderStateIsCleanedAfterConsumerChainIsStopped(t *testing.T, ctx sdk
require.Empty(t, providerKeeper.GetAllVscSendTimestamps(ctx, expectedChainID))
+ // in case the chain was successfully stopped, it should not contain a Top N associated to it
+ _, found = providerKeeper.GetTopN(ctx, expectedChainID)
+ require.False(t, found)
+
// test key assignment state is cleaned
require.Empty(t, providerKeeper.GetAllValidatorConsumerPubKeys(ctx, &expectedChainID))
require.Empty(t, providerKeeper.GetAllValidatorsByConsumerAddr(ctx, &expectedChainID))
require.Empty(t, providerKeeper.GetAllConsumerAddrsToPrune(ctx, expectedChainID))
+ require.Empty(t, providerKeeper.GetAllCommissionRateValidators(ctx, expectedChainID))
}
func GetTestConsumerAdditionProp() *providertypes.ConsumerAdditionProposal {
@@ -271,6 +276,11 @@ func GetTestConsumerAdditionProp() *providertypes.ConsumerAdditionProposal {
types.DefaultCCVTimeoutPeriod,
types.DefaultTransferTimeoutPeriod,
types.DefaultConsumerUnbondingPeriod,
+ 0,
+ 0,
+ 0,
+ nil,
+ nil,
).(*providertypes.ConsumerAdditionProposal)
return prop
diff --git a/x/ccv/consumer/client/cli/query.go b/x/ccv/consumer/client/cli/query.go
index 806b91d2cf..3630b3ed3f 100644
--- a/x/ccv/consumer/client/cli/query.go
+++ b/x/ccv/consumer/client/cli/query.go
@@ -6,7 +6,7 @@ import (
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
- "github.com/cosmos/interchain-security/v4/x/ccv/consumer/types"
+ "github.com/cosmos/interchain-security/v5/x/ccv/consumer/types"
)
// NewQueryCmd returns a root CLI command handler for all x/ccv/provider query commands.
diff --git a/x/ccv/consumer/ibc_module.go b/x/ccv/consumer/ibc_module.go
index 71caa4a082..4780a0bc73 100644
--- a/x/ccv/consumer/ibc_module.go
+++ b/x/ccv/consumer/ibc_module.go
@@ -17,9 +17,9 @@ import (
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types"
- "github.com/cosmos/interchain-security/v4/x/ccv/consumer/keeper"
- consumertypes "github.com/cosmos/interchain-security/v4/x/ccv/consumer/types"
- "github.com/cosmos/interchain-security/v4/x/ccv/types"
+ "github.com/cosmos/interchain-security/v5/x/ccv/consumer/keeper"
+ consumertypes "github.com/cosmos/interchain-security/v5/x/ccv/consumer/types"
+ "github.com/cosmos/interchain-security/v5/x/ccv/types"
)
// OnChanOpenInit implements the IBCModule interface
diff --git a/x/ccv/consumer/ibc_module_test.go b/x/ccv/consumer/ibc_module_test.go
index 51fd910902..b8868038c9 100644
--- a/x/ccv/consumer/ibc_module_test.go
+++ b/x/ccv/consumer/ibc_module_test.go
@@ -13,10 +13,10 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types"
- testkeeper "github.com/cosmos/interchain-security/v4/testutil/keeper"
- "github.com/cosmos/interchain-security/v4/x/ccv/consumer"
- consumerkeeper "github.com/cosmos/interchain-security/v4/x/ccv/consumer/keeper"
- ccv "github.com/cosmos/interchain-security/v4/x/ccv/types"
+ testkeeper "github.com/cosmos/interchain-security/v5/testutil/keeper"
+ "github.com/cosmos/interchain-security/v5/x/ccv/consumer"
+ consumerkeeper "github.com/cosmos/interchain-security/v5/x/ccv/consumer/keeper"
+ ccv "github.com/cosmos/interchain-security/v5/x/ccv/types"
)
// TestOnChanOpenInit validates the consumer's OnChanOpenInit implementation against the spec.
diff --git a/x/ccv/consumer/keeper/changeover_test.go b/x/ccv/consumer/keeper/changeover_test.go
index c431f43477..89d45534dd 100644
--- a/x/ccv/consumer/keeper/changeover_test.go
+++ b/x/ccv/consumer/keeper/changeover_test.go
@@ -11,8 +11,8 @@ import (
abci "github.com/cometbft/cometbft/abci/types"
- "github.com/cosmos/interchain-security/v4/testutil/crypto"
- uthelpers "github.com/cosmos/interchain-security/v4/testutil/keeper"
+ "github.com/cosmos/interchain-security/v5/testutil/crypto"
+ uthelpers "github.com/cosmos/interchain-security/v5/testutil/keeper"
)
func TestChangeoverToConsumer(t *testing.T) {
diff --git a/x/ccv/consumer/keeper/distribution.go b/x/ccv/consumer/keeper/distribution.go
index 1b98638498..d6157e50b5 100644
--- a/x/ccv/consumer/keeper/distribution.go
+++ b/x/ccv/consumer/keeper/distribution.go
@@ -12,8 +12,8 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
- "github.com/cosmos/interchain-security/v4/x/ccv/consumer/types"
- ccv "github.com/cosmos/interchain-security/v4/x/ccv/types"
+ "github.com/cosmos/interchain-security/v5/x/ccv/consumer/types"
+ ccv "github.com/cosmos/interchain-security/v5/x/ccv/types"
)
// EndBlockRD executes EndBlock logic for the Reward Distribution sub-protocol.
diff --git a/x/ccv/consumer/keeper/distribution_test.go b/x/ccv/consumer/keeper/distribution_test.go
index 189842a90e..199acae5b0 100644
--- a/x/ccv/consumer/keeper/distribution_test.go
+++ b/x/ccv/consumer/keeper/distribution_test.go
@@ -10,9 +10,9 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
authTypes "github.com/cosmos/cosmos-sdk/x/auth/types"
- testkeeper "github.com/cosmos/interchain-security/v4/testutil/keeper"
- "github.com/cosmos/interchain-security/v4/x/ccv/consumer/types"
- ccvtypes "github.com/cosmos/interchain-security/v4/x/ccv/types"
+ testkeeper "github.com/cosmos/interchain-security/v5/testutil/keeper"
+ "github.com/cosmos/interchain-security/v5/x/ccv/consumer/types"
+ ccvtypes "github.com/cosmos/interchain-security/v5/x/ccv/types"
)
// TestGetEstimatedNextFeeDistribution tests next fee distribution parameters.
diff --git a/x/ccv/consumer/keeper/genesis.go b/x/ccv/consumer/keeper/genesis.go
index 1b9afb2a4e..bdb8e35418 100644
--- a/x/ccv/consumer/keeper/genesis.go
+++ b/x/ccv/consumer/keeper/genesis.go
@@ -7,8 +7,8 @@ import (
abci "github.com/cometbft/cometbft/abci/types"
- "github.com/cosmos/interchain-security/v4/x/ccv/consumer/types"
- ccv "github.com/cosmos/interchain-security/v4/x/ccv/types"
+ "github.com/cosmos/interchain-security/v5/x/ccv/consumer/types"
+ ccv "github.com/cosmos/interchain-security/v5/x/ccv/types"
)
// InitGenesis initializes the CCV consumer state and binds to PortID.
diff --git a/x/ccv/consumer/keeper/genesis_test.go b/x/ccv/consumer/keeper/genesis_test.go
index b9fc1b6f3a..77e7e639d3 100644
--- a/x/ccv/consumer/keeper/genesis_test.go
+++ b/x/ccv/consumer/keeper/genesis_test.go
@@ -18,11 +18,11 @@ import (
abci "github.com/cometbft/cometbft/abci/types"
tmtypes "github.com/cometbft/cometbft/types"
- "github.com/cosmos/interchain-security/v4/testutil/crypto"
- testkeeper "github.com/cosmos/interchain-security/v4/testutil/keeper"
- consumerkeeper "github.com/cosmos/interchain-security/v4/x/ccv/consumer/keeper"
- consumertypes "github.com/cosmos/interchain-security/v4/x/ccv/consumer/types"
- ccv "github.com/cosmos/interchain-security/v4/x/ccv/types"
+ "github.com/cosmos/interchain-security/v5/testutil/crypto"
+ testkeeper "github.com/cosmos/interchain-security/v5/testutil/keeper"
+ consumerkeeper "github.com/cosmos/interchain-security/v5/x/ccv/consumer/keeper"
+ consumertypes "github.com/cosmos/interchain-security/v5/x/ccv/consumer/types"
+ ccv "github.com/cosmos/interchain-security/v5/x/ccv/types"
)
// TestInitGenesis tests that a consumer chain is correctly initialised from genesis.
diff --git a/x/ccv/consumer/keeper/grpc_query.go b/x/ccv/consumer/keeper/grpc_query.go
index 5ac5116a28..2f1543071b 100644
--- a/x/ccv/consumer/keeper/grpc_query.go
+++ b/x/ccv/consumer/keeper/grpc_query.go
@@ -8,8 +8,8 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
- "github.com/cosmos/interchain-security/v4/x/ccv/consumer/types"
- ccvtypes "github.com/cosmos/interchain-security/v4/x/ccv/types"
+ "github.com/cosmos/interchain-security/v5/x/ccv/consumer/types"
+ ccvtypes "github.com/cosmos/interchain-security/v5/x/ccv/types"
)
var _ types.QueryServer = Keeper{} //nolint:golint
diff --git a/x/ccv/consumer/keeper/hooks.go b/x/ccv/consumer/keeper/hooks.go
index c730bf266c..715be50e08 100644
--- a/x/ccv/consumer/keeper/hooks.go
+++ b/x/ccv/consumer/keeper/hooks.go
@@ -3,7 +3,7 @@ package keeper
import (
sdk "github.com/cosmos/cosmos-sdk/types"
- ccv "github.com/cosmos/interchain-security/v4/x/ccv/types"
+ ccv "github.com/cosmos/interchain-security/v5/x/ccv/types"
)
var _ ccv.ConsumerHooks = Keeper{}
diff --git a/x/ccv/consumer/keeper/keeper.go b/x/ccv/consumer/keeper/keeper.go
index b8751344b8..e4f1830333 100644
--- a/x/ccv/consumer/keeper/keeper.go
+++ b/x/ccv/consumer/keeper/keeper.go
@@ -23,8 +23,8 @@ import (
tmtypes "github.com/cometbft/cometbft/abci/types"
"github.com/cometbft/cometbft/libs/log"
- "github.com/cosmos/interchain-security/v4/x/ccv/consumer/types"
- ccv "github.com/cosmos/interchain-security/v4/x/ccv/types"
+ "github.com/cosmos/interchain-security/v5/x/ccv/consumer/types"
+ ccv "github.com/cosmos/interchain-security/v5/x/ccv/types"
)
// Keeper defines the Cross-Chain Validation Consumer Keeper
diff --git a/x/ccv/consumer/keeper/keeper_test.go b/x/ccv/consumer/keeper/keeper_test.go
index 19856211b5..4ece86571d 100644
--- a/x/ccv/consumer/keeper/keeper_test.go
+++ b/x/ccv/consumer/keeper/keeper_test.go
@@ -17,10 +17,10 @@ import (
abci "github.com/cometbft/cometbft/abci/types"
- "github.com/cosmos/interchain-security/v4/testutil/crypto"
- testkeeper "github.com/cosmos/interchain-security/v4/testutil/keeper"
- "github.com/cosmos/interchain-security/v4/x/ccv/consumer/types"
- ccv "github.com/cosmos/interchain-security/v4/x/ccv/types"
+ "github.com/cosmos/interchain-security/v5/testutil/crypto"
+ testkeeper "github.com/cosmos/interchain-security/v5/testutil/keeper"
+ "github.com/cosmos/interchain-security/v5/x/ccv/consumer/types"
+ ccv "github.com/cosmos/interchain-security/v5/x/ccv/types"
)
// TestProviderClientID tests getter and setter functionality for the client ID stored on consumer keeper
diff --git a/x/ccv/consumer/keeper/migrations.go b/x/ccv/consumer/keeper/migrations.go
index a1e826e61e..71139fb36c 100644
--- a/x/ccv/consumer/keeper/migrations.go
+++ b/x/ccv/consumer/keeper/migrations.go
@@ -4,7 +4,7 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
paramtypes "github.com/cosmos/cosmos-sdk/x/params/types"
- v2 "github.com/cosmos/interchain-security/v4/x/ccv/consumer/migrations/v2"
+ v2 "github.com/cosmos/interchain-security/v5/x/ccv/consumer/migrations/v2"
)
// Migrator is a struct for handling in-place store migrations.
diff --git a/x/ccv/consumer/keeper/params.go b/x/ccv/consumer/keeper/params.go
index 4d96ddf604..818b2858bc 100644
--- a/x/ccv/consumer/keeper/params.go
+++ b/x/ccv/consumer/keeper/params.go
@@ -6,7 +6,7 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
- ccvtypes "github.com/cosmos/interchain-security/v4/x/ccv/types"
+ ccvtypes "github.com/cosmos/interchain-security/v5/x/ccv/types"
)
// GetParams returns the params for the consumer ccv module
diff --git a/x/ccv/consumer/keeper/params_test.go b/x/ccv/consumer/keeper/params_test.go
index e2975a0b31..18d3f5a2b2 100644
--- a/x/ccv/consumer/keeper/params_test.go
+++ b/x/ccv/consumer/keeper/params_test.go
@@ -6,8 +6,8 @@ import (
"github.com/stretchr/testify/require"
- testkeeper "github.com/cosmos/interchain-security/v4/testutil/keeper"
- ccv "github.com/cosmos/interchain-security/v4/x/ccv/types"
+ testkeeper "github.com/cosmos/interchain-security/v5/testutil/keeper"
+ ccv "github.com/cosmos/interchain-security/v5/x/ccv/types"
)
// TestParams tests getters/setters for consumer params
diff --git a/x/ccv/consumer/keeper/provider_info.go b/x/ccv/consumer/keeper/provider_info.go
index e5fbaf6540..aab84e1f85 100644
--- a/x/ccv/consumer/keeper/provider_info.go
+++ b/x/ccv/consumer/keeper/provider_info.go
@@ -5,8 +5,8 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
- "github.com/cosmos/interchain-security/v4/x/ccv/consumer/types"
- ccvtypes "github.com/cosmos/interchain-security/v4/x/ccv/types"
+ "github.com/cosmos/interchain-security/v5/x/ccv/consumer/types"
+ ccvtypes "github.com/cosmos/interchain-security/v5/x/ccv/types"
)
func (k Keeper) GetProviderInfo(ctx sdk.Context) (*types.QueryProviderInfoResponse, error) { //nolint:golint
diff --git a/x/ccv/consumer/keeper/relay.go b/x/ccv/consumer/keeper/relay.go
index 2d4e16510a..cf431fc054 100644
--- a/x/ccv/consumer/keeper/relay.go
+++ b/x/ccv/consumer/keeper/relay.go
@@ -14,8 +14,8 @@ import (
abci "github.com/cometbft/cometbft/abci/types"
- "github.com/cosmos/interchain-security/v4/x/ccv/consumer/types"
- ccv "github.com/cosmos/interchain-security/v4/x/ccv/types"
+ "github.com/cosmos/interchain-security/v5/x/ccv/consumer/types"
+ ccv "github.com/cosmos/interchain-security/v5/x/ccv/types"
)
// OnRecvVSCPacket sets the pending validator set changes that will be flushed to ABCI on Endblock
diff --git a/x/ccv/consumer/keeper/relay_test.go b/x/ccv/consumer/keeper/relay_test.go
index 46a805a85a..b1042de5d0 100644
--- a/x/ccv/consumer/keeper/relay_test.go
+++ b/x/ccv/consumer/keeper/relay_test.go
@@ -21,11 +21,11 @@ import (
abci "github.com/cometbft/cometbft/abci/types"
"github.com/cometbft/cometbft/libs/bytes"
- "github.com/cosmos/interchain-security/v4/testutil/crypto"
- testkeeper "github.com/cosmos/interchain-security/v4/testutil/keeper"
- consumerkeeper "github.com/cosmos/interchain-security/v4/x/ccv/consumer/keeper"
- consumertypes "github.com/cosmos/interchain-security/v4/x/ccv/consumer/types"
- "github.com/cosmos/interchain-security/v4/x/ccv/types"
+ "github.com/cosmos/interchain-security/v5/testutil/crypto"
+ testkeeper "github.com/cosmos/interchain-security/v5/testutil/keeper"
+ consumerkeeper "github.com/cosmos/interchain-security/v5/x/ccv/consumer/keeper"
+ consumertypes "github.com/cosmos/interchain-security/v5/x/ccv/consumer/types"
+ "github.com/cosmos/interchain-security/v5/x/ccv/types"
)
// TestOnRecvVSCPacket tests the behavior of OnRecvVSCPacket over various packet scenarios
diff --git a/x/ccv/consumer/keeper/soft_opt_out.go b/x/ccv/consumer/keeper/soft_opt_out.go
index e5990ff65d..120d3d46d1 100644
--- a/x/ccv/consumer/keeper/soft_opt_out.go
+++ b/x/ccv/consumer/keeper/soft_opt_out.go
@@ -6,7 +6,7 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
- "github.com/cosmos/interchain-security/v4/x/ccv/consumer/types"
+ "github.com/cosmos/interchain-security/v5/x/ccv/consumer/types"
)
// BeginBlockSoftOptOut executes BeginBlock logic for the Soft Opt-Out sub-protocol
diff --git a/x/ccv/consumer/keeper/soft_opt_out_test.go b/x/ccv/consumer/keeper/soft_opt_out_test.go
index 1a726d1767..5c21133832 100644
--- a/x/ccv/consumer/keeper/soft_opt_out_test.go
+++ b/x/ccv/consumer/keeper/soft_opt_out_test.go
@@ -7,9 +7,9 @@ import (
tmtypes "github.com/cometbft/cometbft/types"
- "github.com/cosmos/interchain-security/v4/testutil/crypto"
- testkeeper "github.com/cosmos/interchain-security/v4/testutil/keeper"
- ccvtypes "github.com/cosmos/interchain-security/v4/x/ccv/types"
+ "github.com/cosmos/interchain-security/v5/testutil/crypto"
+ testkeeper "github.com/cosmos/interchain-security/v5/testutil/keeper"
+ ccvtypes "github.com/cosmos/interchain-security/v5/x/ccv/types"
)
// Tests that UpdateSmallestNonOptOutPower updates the smallest validator power that cannot soft opt out.
diff --git a/x/ccv/consumer/keeper/throttle_retry.go b/x/ccv/consumer/keeper/throttle_retry.go
index 22e48f9175..4b6df3cc04 100644
--- a/x/ccv/consumer/keeper/throttle_retry.go
+++ b/x/ccv/consumer/keeper/throttle_retry.go
@@ -5,7 +5,7 @@ import (
sdktypes "github.com/cosmos/cosmos-sdk/types"
- consumertypes "github.com/cosmos/interchain-security/v4/x/ccv/consumer/types"
+ consumertypes "github.com/cosmos/interchain-security/v5/x/ccv/consumer/types"
)
//
diff --git a/x/ccv/consumer/keeper/throttle_retry_test.go b/x/ccv/consumer/keeper/throttle_retry_test.go
index 4a222fde90..b979ebb51d 100644
--- a/x/ccv/consumer/keeper/throttle_retry_test.go
+++ b/x/ccv/consumer/keeper/throttle_retry_test.go
@@ -6,9 +6,9 @@ import (
"github.com/stretchr/testify/require"
- testutil "github.com/cosmos/interchain-security/v4/testutil/keeper"
- consumertypes "github.com/cosmos/interchain-security/v4/x/ccv/consumer/types"
- ccvtypes "github.com/cosmos/interchain-security/v4/x/ccv/types"
+ testutil "github.com/cosmos/interchain-security/v5/testutil/keeper"
+ consumertypes "github.com/cosmos/interchain-security/v5/x/ccv/consumer/types"
+ ccvtypes "github.com/cosmos/interchain-security/v5/x/ccv/types"
)
func TestPacketSendingPermitted(t *testing.T) {
diff --git a/x/ccv/consumer/keeper/validators.go b/x/ccv/consumer/keeper/validators.go
index 24a1c5a57c..fa1c8991db 100644
--- a/x/ccv/consumer/keeper/validators.go
+++ b/x/ccv/consumer/keeper/validators.go
@@ -11,7 +11,7 @@ import (
abci "github.com/cometbft/cometbft/abci/types"
- "github.com/cosmos/interchain-security/v4/x/ccv/consumer/types"
+ "github.com/cosmos/interchain-security/v5/x/ccv/consumer/types"
)
//
diff --git a/x/ccv/consumer/keeper/validators_test.go b/x/ccv/consumer/keeper/validators_test.go
index 1d4dcb2c86..f1c3dbd3f3 100644
--- a/x/ccv/consumer/keeper/validators_test.go
+++ b/x/ccv/consumer/keeper/validators_test.go
@@ -15,10 +15,10 @@ import (
tmrand "github.com/cometbft/cometbft/libs/rand"
tmtypes "github.com/cometbft/cometbft/types"
- "github.com/cosmos/interchain-security/v4/testutil/crypto"
- testkeeper "github.com/cosmos/interchain-security/v4/testutil/keeper"
- "github.com/cosmos/interchain-security/v4/x/ccv/consumer/keeper"
- "github.com/cosmos/interchain-security/v4/x/ccv/consumer/types"
+ "github.com/cosmos/interchain-security/v5/testutil/crypto"
+ testkeeper "github.com/cosmos/interchain-security/v5/testutil/keeper"
+ "github.com/cosmos/interchain-security/v5/x/ccv/consumer/keeper"
+ "github.com/cosmos/interchain-security/v5/x/ccv/consumer/types"
)
// TestApplyCCValidatorChanges tests the ApplyCCValidatorChanges method for a consumer keeper
diff --git a/x/ccv/consumer/migrations/v2/migration.go b/x/ccv/consumer/migrations/v2/migration.go
index 80f06d4d71..ed54512172 100644
--- a/x/ccv/consumer/migrations/v2/migration.go
+++ b/x/ccv/consumer/migrations/v2/migration.go
@@ -6,8 +6,8 @@ import (
storetypes "github.com/cosmos/cosmos-sdk/store/types"
sdk "github.com/cosmos/cosmos-sdk/types"
- consumertypes "github.com/cosmos/interchain-security/v4/x/ccv/consumer/types"
- ccvtypes "github.com/cosmos/interchain-security/v4/x/ccv/types"
+ consumertypes "github.com/cosmos/interchain-security/v5/x/ccv/consumer/types"
+ ccvtypes "github.com/cosmos/interchain-security/v5/x/ccv/types"
)
// MigrateConsumerPacketData migrates consumer packet data according to
diff --git a/x/ccv/consumer/migrations/v2/migration_test.go b/x/ccv/consumer/migrations/v2/migration_test.go
index a99a2be0fb..8ef05bcbcf 100644
--- a/x/ccv/consumer/migrations/v2/migration_test.go
+++ b/x/ccv/consumer/migrations/v2/migration_test.go
@@ -9,10 +9,10 @@ import (
storetypes "github.com/cosmos/cosmos-sdk/store/types"
sdk "github.com/cosmos/cosmos-sdk/types"
- testutil "github.com/cosmos/interchain-security/v4/testutil/keeper"
- v2 "github.com/cosmos/interchain-security/v4/x/ccv/consumer/migrations/v2"
- consumertypes "github.com/cosmos/interchain-security/v4/x/ccv/consumer/types"
- ccvtypes "github.com/cosmos/interchain-security/v4/x/ccv/types"
+ testutil "github.com/cosmos/interchain-security/v5/testutil/keeper"
+ v2 "github.com/cosmos/interchain-security/v5/x/ccv/consumer/migrations/v2"
+ consumertypes "github.com/cosmos/interchain-security/v5/x/ccv/consumer/types"
+ ccvtypes "github.com/cosmos/interchain-security/v5/x/ccv/types"
)
func TestMigrateConsumerPacketData(t *testing.T) {
diff --git a/x/ccv/consumer/module.go b/x/ccv/consumer/module.go
index 4b5d9c053b..f522a34fb8 100644
--- a/x/ccv/consumer/module.go
+++ b/x/ccv/consumer/module.go
@@ -19,10 +19,10 @@ import (
abci "github.com/cometbft/cometbft/abci/types"
- "github.com/cosmos/interchain-security/v4/x/ccv/consumer/client/cli"
- "github.com/cosmos/interchain-security/v4/x/ccv/consumer/keeper"
- consumertypes "github.com/cosmos/interchain-security/v4/x/ccv/consumer/types"
- ccvtypes "github.com/cosmos/interchain-security/v4/x/ccv/types"
+ "github.com/cosmos/interchain-security/v5/x/ccv/consumer/client/cli"
+ "github.com/cosmos/interchain-security/v5/x/ccv/consumer/keeper"
+ consumertypes "github.com/cosmos/interchain-security/v5/x/ccv/consumer/types"
+ ccvtypes "github.com/cosmos/interchain-security/v5/x/ccv/types"
)
var (
diff --git a/x/ccv/consumer/types/genesis.go b/x/ccv/consumer/types/genesis.go
index cb9cb61f40..9c3fab9c15 100644
--- a/x/ccv/consumer/types/genesis.go
+++ b/x/ccv/consumer/types/genesis.go
@@ -7,7 +7,7 @@ import (
abci "github.com/cometbft/cometbft/abci/types"
- ccv "github.com/cosmos/interchain-security/v4/x/ccv/types"
+ ccv "github.com/cosmos/interchain-security/v5/x/ccv/types"
)
// NewRestartGenesisState returns a consumer GenesisState that has already been established.
diff --git a/x/ccv/consumer/types/genesis.pb.go b/x/ccv/consumer/types/genesis.pb.go
index dbb7c51981..b51d09efac 100644
--- a/x/ccv/consumer/types/genesis.pb.go
+++ b/x/ccv/consumer/types/genesis.pb.go
@@ -10,7 +10,7 @@ import (
proto "github.com/cosmos/gogoproto/proto"
github_com_cosmos_gogoproto_types "github.com/cosmos/gogoproto/types"
_07_tendermint "github.com/cosmos/ibc-go/v7/modules/light-clients/07-tendermint"
- types "github.com/cosmos/interchain-security/v4/x/ccv/types"
+ types "github.com/cosmos/interchain-security/v5/x/ccv/types"
_ "google.golang.org/protobuf/types/known/timestamppb"
io "io"
math "math"
diff --git a/x/ccv/consumer/types/genesis_test.go b/x/ccv/consumer/types/genesis_test.go
index dcd30b642c..befd935ba4 100644
--- a/x/ccv/consumer/types/genesis_test.go
+++ b/x/ccv/consumer/types/genesis_test.go
@@ -15,9 +15,9 @@ import (
abci "github.com/cometbft/cometbft/abci/types"
tmtypes "github.com/cometbft/cometbft/types"
- "github.com/cosmos/interchain-security/v4/testutil/crypto"
- "github.com/cosmos/interchain-security/v4/x/ccv/consumer/types"
- ccv "github.com/cosmos/interchain-security/v4/x/ccv/types"
+ "github.com/cosmos/interchain-security/v5/testutil/crypto"
+ "github.com/cosmos/interchain-security/v5/x/ccv/consumer/types"
+ ccv "github.com/cosmos/interchain-security/v5/x/ccv/types"
)
const (
diff --git a/x/ccv/consumer/types/keys.go b/x/ccv/consumer/types/keys.go
index 20163f5ed9..f6400266e8 100644
--- a/x/ccv/consumer/types/keys.go
+++ b/x/ccv/consumer/types/keys.go
@@ -6,7 +6,7 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
- ccvtypes "github.com/cosmos/interchain-security/v4/x/ccv/types"
+ ccvtypes "github.com/cosmos/interchain-security/v5/x/ccv/types"
)
const (
diff --git a/x/ccv/consumer/types/params_test.go b/x/ccv/consumer/types/params_test.go
index 5b11b52d43..caff4db0b1 100644
--- a/x/ccv/consumer/types/params_test.go
+++ b/x/ccv/consumer/types/params_test.go
@@ -6,7 +6,7 @@ import (
"github.com/stretchr/testify/require"
- ccvtypes "github.com/cosmos/interchain-security/v4/x/ccv/types"
+ ccvtypes "github.com/cosmos/interchain-security/v5/x/ccv/types"
)
// Tests the validation of consumer params that happens at genesis
diff --git a/x/ccv/consumer/types/query.pb.go b/x/ccv/consumer/types/query.pb.go
index fe62a4217f..29f7d33971 100644
--- a/x/ccv/consumer/types/query.pb.go
+++ b/x/ccv/consumer/types/query.pb.go
@@ -9,7 +9,7 @@ import (
_ "github.com/cosmos/gogoproto/gogoproto"
grpc1 "github.com/cosmos/gogoproto/grpc"
proto "github.com/cosmos/gogoproto/proto"
- types "github.com/cosmos/interchain-security/v4/x/ccv/types"
+ types "github.com/cosmos/interchain-security/v5/x/ccv/types"
_ "google.golang.org/genproto/googleapis/api/annotations"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
diff --git a/x/ccv/democracy/distribution/module.go b/x/ccv/democracy/distribution/module.go
index af35c86846..b30893402b 100644
--- a/x/ccv/democracy/distribution/module.go
+++ b/x/ccv/democracy/distribution/module.go
@@ -16,7 +16,7 @@ import (
abci "github.com/cometbft/cometbft/abci/types"
- consumertypes "github.com/cosmos/interchain-security/v4/x/ccv/consumer/types"
+ consumertypes "github.com/cosmos/interchain-security/v5/x/ccv/consumer/types"
)
var (
diff --git a/x/ccv/provider/client/cli/query.go b/x/ccv/provider/client/cli/query.go
index 90f7450355..575470c6f3 100644
--- a/x/ccv/provider/client/cli/query.go
+++ b/x/ccv/provider/client/cli/query.go
@@ -11,7 +11,7 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/version"
- "github.com/cosmos/interchain-security/v4/x/ccv/provider/types"
+ "github.com/cosmos/interchain-security/v5/x/ccv/provider/types"
)
// NewQueryCmd returns a root CLI command handler for all x/ccv/provider query commands.
@@ -35,6 +35,9 @@ func NewQueryCmd() *cobra.Command {
cmd.AddCommand(CmdProposedConsumerChains())
cmd.AddCommand(CmdAllPairsValConAddrByConsumerChainID())
cmd.AddCommand(CmdProviderParameters())
+ cmd.AddCommand(CmdConsumerChainOptedInValidators())
+ cmd.AddCommand(CmdConsumerChainsValidatorHasToValidate())
+ cmd.AddCommand(CmdValidatorConsumerCommissionRate())
cmd.AddCommand(CmdOldestUnconfirmedVsc())
return cmd
}
@@ -411,6 +414,126 @@ $ %s query provider params
return cmd
}
+// Command to query opted-in validators by consumer chain ID
+func CmdConsumerChainOptedInValidators() *cobra.Command {
+ cmd := &cobra.Command{
+ Use: "consumer-opted-in-validators [chainid]",
+ Short: "Query opted-in validators for a given consumer chain",
+ Long: strings.TrimSpace(
+ fmt.Sprintf(`Query opted-in validators for a given consumer chain.
+Example:
+$ %s consumer-opted-in-validators foochain
+ `, version.AppName),
+ ),
+ Args: cobra.ExactArgs(1),
+ RunE: func(cmd *cobra.Command, args []string) error {
+ clientCtx, err := client.GetClientQueryContext(cmd)
+ if err != nil {
+ return err
+ }
+ queryClient := types.NewQueryClient(clientCtx)
+
+ res, err := queryClient.QueryConsumerChainOptedInValidators(cmd.Context(),
+ &types.QueryConsumerChainOptedInValidatorsRequest{ChainId: args[0]})
+ if err != nil {
+ return err
+ }
+
+ return clientCtx.PrintProto(res)
+ },
+ }
+
+ flags.AddQueryFlagsToCmd(cmd)
+
+ return cmd
+}
+
+// Command to query the consumer chains list a given validator has to validate
+func CmdConsumerChainsValidatorHasToValidate() *cobra.Command {
+ bech32PrefixConsAddr := sdk.GetConfig().GetBech32ConsensusAddrPrefix()
+ cmd := &cobra.Command{
+ Use: "has-to-validate [provider-validator-address]",
+ Short: "Query the consumer chains list a given validator has to validate",
+ Long: strings.TrimSpace(
+ fmt.Sprintf(`the list of consumer chains that as a validator, you need to be running right now, is always a subset of this, so it seems like a very nice "safe bet".
+Example:
+$ %s has-to-validate %s1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj
+ `, version.AppName, bech32PrefixConsAddr),
+ ),
+ Args: cobra.ExactArgs(1),
+ RunE: func(cmd *cobra.Command, args []string) error {
+ clientCtx, err := client.GetClientQueryContext(cmd)
+ if err != nil {
+ return err
+ }
+ queryClient := types.NewQueryClient(clientCtx)
+
+ addr, err := sdk.ConsAddressFromBech32(args[0])
+ if err != nil {
+ return err
+ }
+
+ res, err := queryClient.QueryConsumerChainsValidatorHasToValidate(cmd.Context(),
+ &types.QueryConsumerChainsValidatorHasToValidateRequest{
+ ProviderAddress: addr.String(),
+ })
+ if err != nil {
+ return err
+ }
+
+ return clientCtx.PrintProto(res)
+ },
+ }
+
+ flags.AddQueryFlagsToCmd(cmd)
+
+ return cmd
+}
+
+// Command to query the consumer commission rate a validator charges
+// on a consumer chain
+func CmdValidatorConsumerCommissionRate() *cobra.Command {
+ bech32PrefixConsAddr := sdk.GetConfig().GetBech32ConsensusAddrPrefix()
+ cmd := &cobra.Command{
+ Use: "validator-consumer-commission-rate [chainid] [provider-validator-address]",
+ Short: "Query the consumer commission rate a validator charges on a consumer chain",
+ Long: strings.TrimSpace(
+ fmt.Sprintf(`Query the consumer commission rate a validator charges on a consumer chain.
+Example:
+$ %s validator-consumer-commission-rate foochain %s1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj
+ `, version.AppName, bech32PrefixConsAddr),
+ ),
+ Args: cobra.ExactArgs(2),
+ RunE: func(cmd *cobra.Command, args []string) error {
+ clientCtx, err := client.GetClientQueryContext(cmd)
+ if err != nil {
+ return err
+ }
+ queryClient := types.NewQueryClient(clientCtx)
+
+ addr, err := sdk.ConsAddressFromBech32(args[1])
+ if err != nil {
+ return err
+ }
+
+ res, err := queryClient.QueryValidatorConsumerCommissionRate(cmd.Context(),
+ &types.QueryValidatorConsumerCommissionRateRequest{
+ ChainId: args[0],
+ ProviderAddress: addr.String(),
+ })
+ if err != nil {
+ return err
+ }
+
+ return clientCtx.PrintProto(res)
+ },
+ }
+
+ flags.AddQueryFlagsToCmd(cmd)
+
+ return cmd
+}
+
func CmdOldestUnconfirmedVsc() *cobra.Command {
cmd := &cobra.Command{
Use: "oldest_unconfirmed_vsc [chainid]",
diff --git a/x/ccv/provider/client/cli/tx.go b/x/ccv/provider/client/cli/tx.go
index 379e55a792..ef65abc28e 100644
--- a/x/ccv/provider/client/cli/tx.go
+++ b/x/ccv/provider/client/cli/tx.go
@@ -18,7 +18,7 @@ import (
tmproto "github.com/cometbft/cometbft/proto/tendermint/types"
- "github.com/cosmos/interchain-security/v4/x/ccv/provider/types"
+ "github.com/cosmos/interchain-security/v5/x/ccv/provider/types"
)
// GetTxCmd returns the transaction commands for this module
@@ -34,6 +34,9 @@ func GetTxCmd() *cobra.Command {
cmd.AddCommand(NewAssignConsumerKeyCmd())
cmd.AddCommand(NewSubmitConsumerMisbehaviourCmd())
cmd.AddCommand(NewSubmitConsumerDoubleVotingCmd())
+ cmd.AddCommand(NewOptInCmd())
+ cmd.AddCommand(NewOptOutCmd())
+ cmd.AddCommand(NewSetConsumerCommissionRateCmd())
return cmd
}
@@ -202,3 +205,132 @@ Example:
return cmd
}
+
+func NewOptInCmd() *cobra.Command {
+ cmd := &cobra.Command{
+ Use: "opt-in [consumer-chain-id] [consumer-pubkey]",
+ Short: "opts in validator to the consumer chain, and if given uses the " +
+ "provided consensus public key for this consumer chain",
+ Args: cobra.RangeArgs(1, 2),
+ RunE: func(cmd *cobra.Command, args []string) error {
+ clientCtx, err := client.GetClientTxContext(cmd)
+ if err != nil {
+ return err
+ }
+
+ txf, err := tx.NewFactoryCLI(clientCtx, cmd.Flags())
+ if err != nil {
+ return err
+ }
+ txf = txf.WithTxConfig(clientCtx.TxConfig).WithAccountRetriever(clientCtx.AccountRetriever)
+
+ providerValAddr := clientCtx.GetFromAddress()
+
+ var consumerPubKey string
+ if len(args) == 2 {
+ // consumer public key was provided
+ consumerPubKey = args[1]
+ } else {
+ consumerPubKey = ""
+ }
+ msg, err := types.NewMsgOptIn(args[0], sdk.ValAddress(providerValAddr), consumerPubKey)
+ if err != nil {
+ return err
+ }
+ if err := msg.ValidateBasic(); err != nil {
+ return err
+ }
+
+ return tx.GenerateOrBroadcastTxWithFactory(clientCtx, txf, msg)
+ },
+ }
+
+ flags.AddTxFlagsToCmd(cmd)
+
+ _ = cmd.MarkFlagRequired(flags.FlagFrom)
+
+ return cmd
+}
+
+func NewOptOutCmd() *cobra.Command {
+ cmd := &cobra.Command{
+ Use: "opt-out [consumer-chain-id]",
+ Short: "opts out validator from this consumer chain",
+ Args: cobra.ExactArgs(1),
+ RunE: func(cmd *cobra.Command, args []string) error {
+ clientCtx, err := client.GetClientTxContext(cmd)
+ if err != nil {
+ return err
+ }
+
+ txf, err := tx.NewFactoryCLI(clientCtx, cmd.Flags())
+ if err != nil {
+ return err
+ }
+ txf = txf.WithTxConfig(clientCtx.TxConfig).WithAccountRetriever(clientCtx.AccountRetriever)
+
+ providerValAddr := clientCtx.GetFromAddress()
+
+ msg, err := types.NewMsgOptOut(args[0], sdk.ValAddress(providerValAddr))
+ if err != nil {
+ return err
+ }
+ if err := msg.ValidateBasic(); err != nil {
+ return err
+ }
+
+ return tx.GenerateOrBroadcastTxWithFactory(clientCtx, txf, msg)
+ },
+ }
+
+ flags.AddTxFlagsToCmd(cmd)
+
+ _ = cmd.MarkFlagRequired(flags.FlagFrom)
+
+ return cmd
+}
+
+func NewSetConsumerCommissionRateCmd() *cobra.Command {
+ cmd := &cobra.Command{
+ Use: "set-consumer-commission-rate [consumer-chain-id] [commission-rate]",
+ Short: "set a per-consumer chain commission",
+ Long: strings.TrimSpace(
+ fmt.Sprintf(`Note that the "commission-rate" argument is a fraction and should be in the range [0,1].
+ Example:
+ %s set-consumer-commission-rate consumer-1 0.5 --from node0 --home ../node0`,
+ version.AppName),
+ ),
+ Args: cobra.ExactArgs(2),
+ RunE: func(cmd *cobra.Command, args []string) error {
+ clientCtx, err := client.GetClientTxContext(cmd)
+ if err != nil {
+ return err
+ }
+
+ txf, err := tx.NewFactoryCLI(clientCtx, cmd.Flags())
+ if err != nil {
+ return err
+ }
+ txf = txf.WithTxConfig(clientCtx.TxConfig).WithAccountRetriever(clientCtx.AccountRetriever)
+
+ providerValAddr := clientCtx.GetFromAddress()
+
+ commission, err := sdk.NewDecFromStr(args[1])
+ if err != nil {
+ return err
+ }
+ msg := types.NewMsgSetConsumerCommissionRate(args[0], commission, sdk.ValAddress(providerValAddr))
+ if err := msg.ValidateBasic(); err != nil {
+ return err
+ }
+
+ return tx.GenerateOrBroadcastTxWithFactory(clientCtx, txf, msg)
+ },
+ }
+
+ flags.AddTxFlagsToCmd(cmd)
+
+ _ = cmd.MarkFlagRequired(flags.FlagFrom)
+
+ return cmd
+}
diff --git a/x/ccv/provider/client/proposal_handler.go b/x/ccv/provider/client/proposal_handler.go
index fa74bb953e..9942a6d431 100644
--- a/x/ccv/provider/client/proposal_handler.go
+++ b/x/ccv/provider/client/proposal_handler.go
@@ -20,7 +20,7 @@ import (
govv1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
- "github.com/cosmos/interchain-security/v4/x/ccv/provider/types"
+ "github.com/cosmos/interchain-security/v5/x/ccv/provider/types"
)
var (
@@ -64,7 +64,12 @@ Where proposal.json contains:
"transfer_timeout_period": 3600000000000,
"ccv_timeout_period": 2419200000000000,
"unbonding_period": 1728000000000000,
- "deposit": "10000stake"
+ "deposit": "10000stake",
+ "top_n": 0,
+ "validators_power_cap": 32,
+ "validator_set_cap": 50,
+ "allowlist": [],
+ "denylist": ["validatorAConsensusAddress", "validatorBConsensusAddress"]
}
`,
RunE: func(cmd *cobra.Command, args []string) error {
@@ -86,7 +91,8 @@ Where proposal.json contains:
proposal.GenesisHash, proposal.BinaryHash, proposal.SpawnTime,
proposal.ConsumerRedistributionFraction, proposal.BlocksPerDistributionTransmission,
proposal.DistributionTransmissionChannel, proposal.HistoricalEntries,
- proposal.CcvTimeoutPeriod, proposal.TransferTimeoutPeriod, proposal.UnbondingPeriod)
+ proposal.CcvTimeoutPeriod, proposal.TransferTimeoutPeriod, proposal.UnbondingPeriod, proposal.TopN,
+ proposal.ValidatorsPowerCap, proposal.ValidatorSetCap, proposal.Allowlist, proposal.Denylist)
from := clientCtx.GetFromAddress()
@@ -241,6 +247,12 @@ type ConsumerAdditionProposalJSON struct {
UnbondingPeriod time.Duration `json:"unbonding_period"`
Deposit string `json:"deposit"`
+
+ TopN uint32 `json:"top_N"`
+ ValidatorsPowerCap uint32 `json:"validators_power_cap"`
+ ValidatorSetCap uint32 `json:"validator_set_cap"`
+ Allowlist []string `json:"allowlist"`
+ Denylist []string `json:"denylist"`
}
type ConsumerAdditionProposalReq struct {
diff --git a/x/ccv/provider/handler.go b/x/ccv/provider/handler.go
index cf176a86c1..72abf10c1c 100644
--- a/x/ccv/provider/handler.go
+++ b/x/ccv/provider/handler.go
@@ -6,8 +6,8 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
- "github.com/cosmos/interchain-security/v4/x/ccv/provider/keeper"
- "github.com/cosmos/interchain-security/v4/x/ccv/provider/types"
+ "github.com/cosmos/interchain-security/v5/x/ccv/provider/keeper"
+ "github.com/cosmos/interchain-security/v5/x/ccv/provider/types"
)
func NewHandler(k *keeper.Keeper) sdk.Handler {
@@ -26,6 +26,15 @@ func NewHandler(k *keeper.Keeper) sdk.Handler {
case *types.MsgSubmitConsumerDoubleVoting:
res, err := msgServer.SubmitConsumerDoubleVoting(sdk.WrapSDKContext(ctx), msg)
return sdk.WrapServiceResult(ctx, res, err)
+ case *types.MsgOptIn:
+ res, err := msgServer.OptIn(sdk.WrapSDKContext(ctx), msg)
+ return sdk.WrapServiceResult(ctx, res, err)
+ case *types.MsgOptOut:
+ res, err := msgServer.OptOut(sdk.WrapSDKContext(ctx), msg)
+ return sdk.WrapServiceResult(ctx, res, err)
+ case *types.MsgSetConsumerCommissionRate:
+ res, err := msgServer.SetConsumerCommissionRate(sdk.WrapSDKContext(ctx), msg)
+ return sdk.WrapServiceResult(ctx, res, err)
default:
return nil, errorsmod.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized %s message type: %T", types.ModuleName, msg)
}
diff --git a/x/ccv/provider/handler_test.go b/x/ccv/provider/handler_test.go
index 8cefa3f949..2351b6c61c 100644
--- a/x/ccv/provider/handler_test.go
+++ b/x/ccv/provider/handler_test.go
@@ -14,11 +14,11 @@ import (
tmproto "github.com/cometbft/cometbft/proto/tendermint/types"
- testcrypto "github.com/cosmos/interchain-security/v4/testutil/crypto"
- testkeeper "github.com/cosmos/interchain-security/v4/testutil/keeper"
- "github.com/cosmos/interchain-security/v4/x/ccv/provider"
- keeper "github.com/cosmos/interchain-security/v4/x/ccv/provider/keeper"
- providertypes "github.com/cosmos/interchain-security/v4/x/ccv/provider/types"
+ testcrypto "github.com/cosmos/interchain-security/v5/testutil/crypto"
+ testkeeper "github.com/cosmos/interchain-security/v5/testutil/keeper"
+ "github.com/cosmos/interchain-security/v5/x/ccv/provider"
+ keeper "github.com/cosmos/interchain-security/v5/x/ccv/provider/keeper"
+ providertypes "github.com/cosmos/interchain-security/v5/x/ccv/provider/types"
)
func TestInvalidMsg(t *testing.T) {
@@ -34,6 +34,10 @@ func TestAssignConsensusKeyForConsumerChain(t *testing.T) {
providerCryptoId := testcrypto.NewCryptoIdentityFromIntSeed(0)
providerConsAddr := providerCryptoId.ProviderConsAddress()
+ // a different providerConsAddr, to simulate different validators having assigned keys
+ providerCryptoId2 := testcrypto.NewCryptoIdentityFromIntSeed(10)
+ providerConsAddr2 := providerCryptoId2.ProviderConsAddress()
+
consumerCryptoId := testcrypto.NewCryptoIdentityFromIntSeed(1)
consumerConsAddr := consumerCryptoId.ConsumerConsAddress()
consumerKeyBz := base64.StdEncoding.EncodeToString(consumerCryptoId.ConsensusSDKPubKey().Bytes())
@@ -101,7 +105,32 @@ func TestAssignConsensusKeyForConsumerChain(t *testing.T) {
chainID: "chainid",
},
{
- name: "fail: consumer key in use",
+ name: "fail: consumer key in use by other validator",
+ setup: func(ctx sdk.Context,
+ k keeper.Keeper, mocks testkeeper.MockedKeepers,
+ ) {
+ k.SetPendingConsumerAdditionProp(ctx, &providertypes.ConsumerAdditionProposal{
+ ChainId: "chainid",
+ })
+ // Use the consumer key already used by some other validator
+ k.SetValidatorByConsumerAddr(ctx, "chainid", consumerConsAddr, providerConsAddr2)
+
+ gomock.InOrder(
+ mocks.MockStakingKeeper.EXPECT().GetValidator(
+ ctx, providerCryptoId.SDKValOpAddress(),
+ // validator should not be missing
+ ).Return(providerCryptoId.SDKStakingValidator(), true).Times(1),
+ mocks.MockStakingKeeper.EXPECT().GetValidatorByConsAddr(ctx,
+ consumerConsAddr.ToSdkConsAddr(),
+ // return false - no other validator uses the consumer key to validate *on the provider*
+ ).Return(stakingtypes.Validator{}, false),
+ )
+ },
+ expError: true,
+ chainID: "chainid",
+ },
+ {
+ name: "success: consumer key in use, but by the same validator",
setup: func(ctx sdk.Context,
k keeper.Keeper, mocks testkeeper.MockedKeepers,
) {
@@ -121,7 +150,7 @@ func TestAssignConsensusKeyForConsumerChain(t *testing.T) {
).Return(stakingtypes.Validator{}, false),
)
},
- expError: true,
+ expError: false,
chainID: "chainid",
},
}
diff --git a/x/ccv/provider/ibc_middleware.go b/x/ccv/provider/ibc_middleware.go
new file mode 100644
index 0000000000..a1ef6e0db8
--- /dev/null
+++ b/x/ccv/provider/ibc_middleware.go
@@ -0,0 +1,242 @@
+package provider
+
+import (
+ ibctransfertypes "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types"
+ clienttypes "github.com/cosmos/ibc-go/v7/modules/core/02-client/types"
+ channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types"
+ porttypes "github.com/cosmos/ibc-go/v7/modules/core/05-port/types"
+ "github.com/cosmos/ibc-go/v7/modules/core/exported"
+
+ "cosmossdk.io/math"
+
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types"
+
+ "github.com/cosmos/interchain-security/v5/x/ccv/provider/keeper"
+ "github.com/cosmos/interchain-security/v5/x/ccv/provider/types"
+)
+
+var _ porttypes.Middleware = &IBCMiddleware{}
+
+// IBCMiddleware implements the callbacks for the IBC transfer middleware given the
+// provider keeper and the underlying application.
+type IBCMiddleware struct {
+ app porttypes.IBCModule
+ keeper keeper.Keeper
+}
+
+// NewIBCMiddleware creates a new IBCMiddlware given the keeper and underlying application
+func NewIBCMiddleware(app porttypes.IBCModule, k keeper.Keeper) IBCMiddleware {
+ return IBCMiddleware{
+ app: app,
+ keeper: k,
+ }
+}
+
+// OnChanOpenInit implements the IBCMiddleware interface
+func (im IBCMiddleware) OnChanOpenInit(
+ ctx sdk.Context,
+ order channeltypes.Order,
+ connectionHops []string,
+ portID string,
+ channelID string,
+ chanCap *capabilitytypes.Capability,
+ counterparty channeltypes.Counterparty,
+ version string,
+) (string, error) {
+ // call underlying app's OnChanOpenInit callback with the appVersion
+ return im.app.OnChanOpenInit(ctx, order, connectionHops, portID, channelID, chanCap, counterparty, version)
+}
+
+// OnChanOpenTry implements the IBCMiddleware interface
+func (im IBCMiddleware) OnChanOpenTry(
+ ctx sdk.Context,
+ order channeltypes.Order,
+ connectionHops []string,
+ portID,
+ channelID string,
+ chanCap *capabilitytypes.Capability,
+ counterparty channeltypes.Counterparty,
+ counterpartyVersion string,
+) (string, error) {
+ // call underlying app's OnChanOpenTry callback with the appVersion
+ return im.app.OnChanOpenTry(ctx, order, connectionHops, portID, channelID, chanCap, counterparty, counterpartyVersion)
+}
+
+// OnChanOpenAck implements the IBCMiddleware interface
+func (im IBCMiddleware) OnChanOpenAck(
+ ctx sdk.Context,
+ portID,
+ channelID string,
+ counterpartyChannelID string,
+ counterpartyVersion string,
+) error {
+ // call underlying app's OnChanOpenAck callback with the counterparty app version.
+ return im.app.OnChanOpenAck(ctx, portID, channelID, counterpartyChannelID, counterpartyVersion)
+}
+
+// OnChanOpenConfirm implements the IBCMiddleware interface
+func (im IBCMiddleware) OnChanOpenConfirm(
+ ctx sdk.Context,
+ portID,
+ channelID string,
+) error {
+ // call underlying app's OnChanOpenConfirm callback.
+ return im.app.OnChanOpenConfirm(ctx, portID, channelID)
+}
+
+// OnChanCloseInit implements the IBCMiddleware interface
+func (im IBCMiddleware) OnChanCloseInit(
+ ctx sdk.Context,
+ portID,
+ channelID string,
+) error {
+ // call underlying app's OnChanCloseInit callback.
+ return im.app.OnChanCloseInit(ctx, portID, channelID)
+}
+
+// OnChanCloseConfirm implements the IBCMiddleware interface
+func (im IBCMiddleware) OnChanCloseConfirm(
+ ctx sdk.Context,
+ portID,
+ channelID string,
+) error {
+ return im.app.OnChanCloseConfirm(ctx, portID, channelID)
+}
+
+// OnRecvPacket executes the IBC transfer. In case of success,
+// it verifies if the packet sender is a consumer chain
+// and if the received IBC coin is whitelisted. In such instances,
+// it appends the coin to the consumer's chain allocation record
+func (im IBCMiddleware) OnRecvPacket(
+ ctx sdk.Context,
+ packet channeltypes.Packet,
+ relayer sdk.AccAddress,
+) exported.Acknowledgement {
+ // executes the IBC transfer OnRecv logic
+ ack := im.app.OnRecvPacket(ctx, packet, relayer)
+
+ // Note that inside the below if condition statement,
+ // we know that the IBC transfer succeeded. That entails
+ // that the packet data is valid and can be safely
+ // deserialized without checking errors.
+ if ack.Success() {
+ // execute the middleware logic only if the sender is a consumer chain
+ consumerID, err := im.keeper.IdentifyConsumerChainIDFromIBCPacket(ctx, packet)
+ if err != nil {
+ return ack
+ }
+
+ // extract the coin info received from the packet data
+ var data ibctransfertypes.FungibleTokenPacketData
+ _ = types.ModuleCdc.UnmarshalJSON(packet.GetData(), &data)
+
+ // check if the recipient is the consumer reward's pool address
+ receiver, _ := sdk.AccAddressFromBech32(data.Receiver)
+ if receiver.String() != im.keeper.GetConsumerRewardsPoolAddressStr(ctx) {
+ return ack
+ }
+
+ coinAmt, _ := math.NewIntFromString(data.Amount)
+ coinDenom := GetProviderDenom(data.Denom, packet)
+
+ // verify that the coin's denom is a whitelisted consumer denom,
+ // and if so, adds it to the consumer chain rewards allocation,
+ // otherwise the prohibited coin just stays in the pool forever.
+ if im.keeper.ConsumerRewardDenomExists(ctx, coinDenom) {
+ alloc := im.keeper.GetConsumerRewardsAllocation(ctx, consumerID)
+ alloc.Rewards = alloc.Rewards.Add(
+ sdk.NewDecCoinsFromCoins(sdk.Coin{
+ Denom: coinDenom,
+ Amount: coinAmt,
+ })...)
+ im.keeper.SetConsumerRewardsAllocation(ctx, consumerID, alloc)
+ }
+ }
+
+ return ack
+}
+
+// OnAcknowledgementPacket implements the IBCMiddleware interface
+// If fees are not enabled, this callback will default to the ibc-core packet callback
+func (im IBCMiddleware) OnAcknowledgementPacket(
+ ctx sdk.Context,
+ packet channeltypes.Packet,
+ acknowledgement []byte,
+ relayer sdk.AccAddress,
+) error {
+ // call underlying app's OnAcknowledgementPacket callback.
+ return im.app.OnAcknowledgementPacket(ctx, packet, acknowledgement, relayer)
+}
+
+// OnTimeoutPacket implements the IBCMiddleware interface
+// If fees are not enabled, this callback will default to the ibc-core packet callback
+func (im IBCMiddleware) OnTimeoutPacket(
+ ctx sdk.Context,
+ packet channeltypes.Packet,
+ relayer sdk.AccAddress,
+) error {
+ // call underlying app's OnTimeoutPacket callback.
+ return im.app.OnTimeoutPacket(ctx, packet, relayer)
+}
+
+// SendPacket implements the ICS4 Wrapper interface
+func (im IBCMiddleware) SendPacket(
+ sdk.Context,
+ *capabilitytypes.Capability,
+ string,
+ string,
+ clienttypes.Height,
+ uint64,
+ []byte,
+) (uint64, error) {
+ panic("should never be called since the IBC middleware doesn't have an ICS4wrapper")
+}
+
+// WriteAcknowledgement implements the ICS4 Wrapper interface
+func (im IBCMiddleware) WriteAcknowledgement(
+ ctx sdk.Context,
+ chanCap *capabilitytypes.Capability,
+ packet exported.PacketI,
+ ack exported.Acknowledgement,
+) error {
+ panic("should never be called since the IBC middleware doesn't have an ICS4wrapper")
+}
+
+// GetAppVersion returns the application version of the underlying application
+func (im IBCMiddleware) GetAppVersion(ctx sdk.Context, portID, channelID string) (string, bool) {
+ panic("should never be called since the IBC middleware doesn't have an ICS4wrapper")
+}
+
+// GetProviderDenom returns the updated given denom according to the given IBC packet
+// It follows the same logic than the OnRecvPacket method of the IBC transfer module
+// see https://github.com/cosmos/ibc-go/blob/v7.3.2/modules/apps/transfer/keeper/relay.go#L162
+func GetProviderDenom(denom string, packet channeltypes.Packet) (providerDenom string) {
+ // If the the prefix denom corresponds to the packet's source port and channel,
+ // returns the base denom
+ if ibctransfertypes.ReceiverChainIsSource(packet.GetSourcePort(), packet.GetSourceChannel(), denom) {
+ voucherPrefix := ibctransfertypes.GetDenomPrefix(packet.GetSourcePort(), packet.GetSourceChannel())
+ unprefixedDenom := denom[len(voucherPrefix):]
+
+ // coin denomination used in sending from the escrow address
+ providerDenom = unprefixedDenom
+
+ // The denomination used to send the coins is either the native denom or the hash of the path
+ // if the denomination is not native.
+ denomTrace := ibctransfertypes.ParseDenomTrace(unprefixedDenom)
+ if denomTrace.Path != "" {
+ providerDenom = denomTrace.IBCDenom()
+ }
+ // update the prefix denom according to the packet info
+ } else {
+ prefixedDenom := ibctransfertypes.GetPrefixedDenom(
+ packet.GetDestPort(),
+ packet.GetDestChannel(),
+ denom,
+ )
+
+ providerDenom = ibctransfertypes.ParseDenomTrace(prefixedDenom).IBCDenom()
+ }
+
+ return providerDenom
+}
diff --git a/x/ccv/provider/ibc_middleware_test.go b/x/ccv/provider/ibc_middleware_test.go
new file mode 100644
index 0000000000..e2be5a649d
--- /dev/null
+++ b/x/ccv/provider/ibc_middleware_test.go
@@ -0,0 +1,77 @@
+package provider_test
+
+import (
+ "testing"
+
+ clienttypes "github.com/cosmos/ibc-go/v7/modules/core/02-client/types"
+ channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types"
+ "github.com/stretchr/testify/require"
+
+ "github.com/cosmos/interchain-security/v5/x/ccv/provider"
+)
+
+func TestGetProviderDenom(t *testing.T) {
+ testCases := []struct {
+ name string
+ denom string
+ packet channeltypes.Packet
+ expProviderDenom string
+ }{
+ {
+ name: "returns base denom with destination port and channel as prefix",
+ denom: "stake",
+ packet: channeltypes.NewPacket(
+ []byte{},
+ 0,
+ "srcPort",
+ "srcChannel",
+ "dstPort",
+ "dstChannel",
+ clienttypes.NewHeight(1, 1),
+ 0,
+ ),
+ expProviderDenom: "dstPort/dstChannel/stake",
+ },
+ {
+ name: "returns base denom if the prefix denom corresponds to the packet's port and channel source",
+ denom: "srcPort/srcChannel/stake",
+ packet: channeltypes.NewPacket(
+ []byte{},
+ 0,
+ "srcPort",
+ "srcChannel",
+ "dstPort",
+ "dstChannel",
+ clienttypes.NewHeight(1, 1),
+ 0,
+ ),
+ expProviderDenom: "stake",
+ },
+ {
+ name: "returns prefixed denom updated with packet's port and channel destination as prefix",
+ denom: "dstPort/dstChannel/stake",
+ packet: channeltypes.NewPacket(
+ []byte{},
+ 0,
+ "srcPort",
+ "srcChannel",
+ "dstPort",
+ "dstChannel",
+ clienttypes.NewHeight(1, 1),
+ 0,
+ ),
+ expProviderDenom: "dstPort/dstChannel/dstPort/dstChannel/stake",
+ },
+ }
+
+ for _, tc := range testCases {
+ t.Run(tc.name, func(t *testing.T) {
+ res := provider.GetProviderDenom(
+ tc.denom,
+ tc.packet,
+ )
+
+ require.Equal(t, tc.expProviderDenom, res)
+ })
+ }
+}
diff --git a/x/ccv/provider/ibc_module.go b/x/ccv/provider/ibc_module.go
index f6ad43d60b..f4b1eace4d 100644
--- a/x/ccv/provider/ibc_module.go
+++ b/x/ccv/provider/ibc_module.go
@@ -15,9 +15,9 @@ import (
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types"
- "github.com/cosmos/interchain-security/v4/x/ccv/provider/keeper"
- providertypes "github.com/cosmos/interchain-security/v4/x/ccv/provider/types"
- ccv "github.com/cosmos/interchain-security/v4/x/ccv/types"
+ "github.com/cosmos/interchain-security/v5/x/ccv/provider/keeper"
+ providertypes "github.com/cosmos/interchain-security/v5/x/ccv/provider/types"
+ ccv "github.com/cosmos/interchain-security/v5/x/ccv/types"
)
// OnChanOpenInit implements the IBCModule interface
diff --git a/x/ccv/provider/ibc_module_test.go b/x/ccv/provider/ibc_module_test.go
index df12ed4cb8..9d41a4d9e1 100644
--- a/x/ccv/provider/ibc_module_test.go
+++ b/x/ccv/provider/ibc_module_test.go
@@ -15,11 +15,11 @@ import (
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types"
- testkeeper "github.com/cosmos/interchain-security/v4/testutil/keeper"
- "github.com/cosmos/interchain-security/v4/x/ccv/provider"
- providerkeeper "github.com/cosmos/interchain-security/v4/x/ccv/provider/keeper"
- providertypes "github.com/cosmos/interchain-security/v4/x/ccv/provider/types"
- ccv "github.com/cosmos/interchain-security/v4/x/ccv/types"
+ testkeeper "github.com/cosmos/interchain-security/v5/testutil/keeper"
+ "github.com/cosmos/interchain-security/v5/x/ccv/provider"
+ providerkeeper "github.com/cosmos/interchain-security/v5/x/ccv/provider/keeper"
+ providertypes "github.com/cosmos/interchain-security/v5/x/ccv/provider/types"
+ ccv "github.com/cosmos/interchain-security/v5/x/ccv/types"
)
// TestOnChanOpenInit tests the provider's OnChanOpenInit method against spec.
diff --git a/x/ccv/provider/keeper/consumer_equivocation.go b/x/ccv/provider/keeper/consumer_equivocation.go
index 8fc9808304..6324dfa5c0 100644
--- a/x/ccv/provider/keeper/consumer_equivocation.go
+++ b/x/ccv/provider/keeper/consumer_equivocation.go
@@ -19,8 +19,8 @@ import (
tmtypes "github.com/cometbft/cometbft/types"
- "github.com/cosmos/interchain-security/v4/x/ccv/provider/types"
- ccvtypes "github.com/cosmos/interchain-security/v4/x/ccv/types"
+ "github.com/cosmos/interchain-security/v5/x/ccv/provider/types"
+ ccvtypes "github.com/cosmos/interchain-security/v5/x/ccv/types"
)
//
diff --git a/x/ccv/provider/keeper/consumer_equivocation_test.go b/x/ccv/provider/keeper/consumer_equivocation_test.go
index d92caf69a3..13b56fc04a 100644
--- a/x/ccv/provider/keeper/consumer_equivocation_test.go
+++ b/x/ccv/provider/keeper/consumer_equivocation_test.go
@@ -18,9 +18,9 @@ import (
tmtypes "github.com/cometbft/cometbft/types"
- cryptotestutil "github.com/cosmos/interchain-security/v4/testutil/crypto"
- testkeeper "github.com/cosmos/interchain-security/v4/testutil/keeper"
- "github.com/cosmos/interchain-security/v4/x/ccv/provider/types"
+ cryptotestutil "github.com/cosmos/interchain-security/v5/testutil/crypto"
+ testkeeper "github.com/cosmos/interchain-security/v5/testutil/keeper"
+ "github.com/cosmos/interchain-security/v5/x/ccv/provider/types"
)
func TestVerifyDoubleVotingEvidence(t *testing.T) {
diff --git a/x/ccv/provider/keeper/distribution.go b/x/ccv/provider/keeper/distribution.go
index 5b2e6025ef..49137936eb 100644
--- a/x/ccv/provider/keeper/distribution.go
+++ b/x/ccv/provider/keeper/distribution.go
@@ -1,17 +1,27 @@
package keeper
import (
+ channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types"
+
+ errorsmod "cosmossdk.io/errors"
+ "cosmossdk.io/math"
+
sdk "github.com/cosmos/cosmos-sdk/types"
+ distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types"
+ stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
+
+ abci "github.com/cometbft/cometbft/abci/types"
- "github.com/cosmos/interchain-security/v4/x/ccv/provider/types"
+ "github.com/cosmos/interchain-security/v5/x/ccv/provider/types"
)
-// EndBlockRD executes EndBlock logic for the Reward Distribution sub-protocol.
-// Reward Distribution follows a simple model: send tokens to the ConsumerRewardsPool,
-// from where they sent to the fee collector address
-func (k Keeper) EndBlockRD(ctx sdk.Context) {
- // transfers all whitelisted consumer rewards to the fee collector address
- k.TransferRewardsToFeeCollector(ctx)
+// BeginBlockRD executes BeginBlock logic for the Reward Distribution sub-protocol.
+func (k Keeper) BeginBlockRD(ctx sdk.Context, req abci.RequestBeginBlock) {
+ // TODO this is Tendermint-dependent
+ // ref https://github.com/cosmos/cosmos-sdk/issues/3095
+ if ctx.BlockHeight() > 1 {
+ k.AllocateTokens(ctx)
+ }
}
func (k Keeper) GetConsumerRewardsPoolAddressStr(ctx sdk.Context) string {
@@ -57,32 +67,232 @@ func (k Keeper) GetAllConsumerRewardDenoms(ctx sdk.Context) (consumerRewardDenom
return consumerRewardDenoms
}
-// TransferRewardsToFeeCollector transfers all consumer rewards to the fee collector address
-func (k Keeper) TransferRewardsToFeeCollector(ctx sdk.Context) {
- // 1. Get the denom whitelist from the store
- denoms := k.GetAllConsumerRewardDenoms(ctx)
+// AllocateTokens performs rewards distribution to the community pool and validators
+// based on the Partial Set Security distribution specification.
+func (k Keeper) AllocateTokens(ctx sdk.Context) {
+ // return if there is no coins in the consumer rewards pool
+ if k.GetConsumerRewardsPool(ctx).IsZero() {
+ return
+ }
+
+ // Iterate over all registered consumer chains
+ for _, consumer := range k.GetAllConsumerChains(ctx) {
+ // transfer the consumer rewards to the distribution module account
+ // note that the rewards transferred are only consumer whitelisted denoms
+ rewardsCollected, err := k.TransferConsumerRewardsToDistributionModule(ctx, consumer.ChainId)
+ if err != nil {
+ k.Logger(ctx).Error(
+ "fail to transfer rewards to distribution module for chain %s: %s",
+ consumer.ChainId,
+ err,
+ )
+ continue
+ }
+
+ // note that it's possible that no rewards are collected even though the
+ // reward pool isn't empty. This can happen if the reward pool holds some tokens
+ // of non-whitelisted denominations.
+ if rewardsCollected.IsZero() {
+ continue
+ }
+
+ rewardsCollectedDec := sdk.NewDecCoinsFromCoins(rewardsCollected...)
+
+ // temporary workaround to keep CanWithdrawInvariant happy
+ // general discussions here: https://github.com/cosmos/cosmos-sdk/issues/2906#issuecomment-441867634
+ feePool := k.distributionKeeper.GetFeePool(ctx)
+ if k.ComputeConsumerTotalVotingPower(ctx, consumer.ChainId) == 0 {
+ feePool.CommunityPool = feePool.CommunityPool.Add(rewardsCollectedDec...)
+ k.distributionKeeper.SetFeePool(ctx, feePool)
+ return
+ }
+
+ // calculate the reward allocations
+ remaining := rewardsCollectedDec
+ communityTax := k.distributionKeeper.GetCommunityTax(ctx)
+ voteMultiplier := math.LegacyOneDec().Sub(communityTax)
+ feeMultiplier := rewardsCollectedDec.MulDecTruncate(voteMultiplier)
- // 2. Iterate over the whitelist
- for _, denom := range denoms {
- // 3. For each denom, retrieve the balance from the consumer rewards pool
- balance := k.bankKeeper.GetBalance(
+ // allocate tokens to consumer validators
+ feeAllocated := k.AllocateTokensToConsumerValidators(
ctx,
- k.accountKeeper.GetModuleAccount(ctx, types.ConsumerRewardsPool).GetAddress(),
- denom,
+ consumer.ChainId,
+ feeMultiplier,
)
+ remaining = remaining.Sub(feeAllocated)
- // if the balance is not zero,
- if !balance.IsZero() {
- // 4. Transfer the balance to the fee collector address
- err := k.bankKeeper.SendCoinsFromModuleToModule(
- ctx,
- types.ConsumerRewardsPool,
- k.feeCollectorName,
- sdk.NewCoins(balance),
- )
- if err != nil {
- k.Logger(ctx).Error("cannot sent consumer rewards to fee collector:", "reward", balance.String())
- }
+ // allocate community funding
+ feePool.CommunityPool = feePool.CommunityPool.Add(remaining...)
+ k.distributionKeeper.SetFeePool(ctx, feePool)
+ }
+}
+
+// AllocateTokensToConsumerValidators allocates tokens
+// to the given consumer chain's validator set
+func (k Keeper) AllocateTokensToConsumerValidators(
+ ctx sdk.Context,
+ chainID string,
+ tokens sdk.DecCoins,
+) (allocated sdk.DecCoins) {
+ // return early if the tokens are empty
+ if tokens.Empty() {
+ return allocated
+ }
+
+ // get the total voting power of the consumer valset
+ totalPower := k.ComputeConsumerTotalVotingPower(ctx, chainID)
+ if totalPower == 0 {
+ return allocated
+ }
+
+ // Allocate tokens by iterating over the consumer validators
+ for _, consumerVal := range k.GetConsumerValSet(ctx, chainID) {
+ consAddr := sdk.ConsAddress(consumerVal.ProviderConsAddr)
+
+ // get the validator tokens fraction using its voting power
+ powerFraction := math.LegacyNewDec(consumerVal.Power).QuoTruncate(math.LegacyNewDec(totalPower))
+ tokensFraction := tokens.MulDecTruncate(powerFraction)
+
+ // get the validator type struct for the consensus address
+ val := k.stakingKeeper.ValidatorByConsAddr(ctx, consAddr).(stakingtypes.Validator)
+
+ // check if the validator set a custom commission rate for the consumer chain
+ if cr, found := k.GetConsumerCommissionRate(ctx, chainID, types.NewProviderConsAddress(consAddr)); found {
+ // set the validator commission rate
+ val.Commission.CommissionRates.Rate = cr
}
+
+ // allocate the consumer reward tokens to the validator
+ k.distributionKeeper.AllocateTokensToValidator(
+ ctx,
+ val,
+ tokensFraction,
+ )
+
+ // sum the tokens allocated
+ allocated = allocated.Add(tokensFraction...)
+ }
+
+ return allocated
+}
+
+// TransferConsumerRewardsToDistributionModule transfers the rewards allocation of the given consumer chain
+// from the consumer rewards pool to a the distribution module
+func (k Keeper) TransferConsumerRewardsToDistributionModule(
+ ctx sdk.Context,
+ chainID string,
+) (sdk.Coins, error) {
+ // Get coins of the consumer rewards allocation
+ allocation := k.GetConsumerRewardsAllocation(ctx, chainID)
+
+ if allocation.Rewards.IsZero() {
+ return sdk.Coins{}, nil
+ }
+
+ // Truncate coin rewards
+ rewardsToSend, _ := allocation.Rewards.TruncateDecimal()
+
+ // NOTE the consumer rewards allocation isn't a module account, however its coins
+ // are held in the consumer reward pool module account. Thus the consumer
+ // rewards allocation must be reduced separately from the SendCoinsFromModuleToAccount call.
+
+ // Update consumer rewards allocation with the remaining decimal coins
+ allocation.Rewards = allocation.Rewards.Sub(sdk.NewDecCoinsFromCoins(rewardsToSend...))
+
+ // Send coins to distribution module account
+ err := k.bankKeeper.SendCoinsFromModuleToModule(ctx, types.ConsumerRewardsPool, distrtypes.ModuleName, rewardsToSend)
+ if err != nil {
+ return sdk.Coins{}, err
+ }
+
+ k.SetConsumerRewardsAllocation(ctx, chainID, allocation)
+ return rewardsToSend, nil
+}
+
+// consumer reward pools getter and setter
+
+// GetConsumerRewardsAllocation returns the consumer rewards allocation for the given chain ID
+func (k Keeper) GetConsumerRewardsAllocation(ctx sdk.Context, chainID string) (pool types.ConsumerRewardsAllocation) {
+ store := ctx.KVStore(k.storeKey)
+ b := store.Get(types.ConsumerRewardsAllocationKey(chainID))
+ k.cdc.MustUnmarshal(b, &pool)
+ return
+}
+
+// SetConsumerRewardsAllocation sets the consumer rewards allocation for the given chain ID
+func (k Keeper) SetConsumerRewardsAllocation(ctx sdk.Context, chainID string, pool types.ConsumerRewardsAllocation) {
+ store := ctx.KVStore(k.storeKey)
+ b := k.cdc.MustMarshal(&pool)
+ store.Set(types.ConsumerRewardsAllocationKey(chainID), b)
+}
+
+// GetConsumerRewardsPool returns the balance
+// of the consumer rewards pool module account
+func (k Keeper) GetConsumerRewardsPool(ctx sdk.Context) sdk.Coins {
+ return k.bankKeeper.GetAllBalances(
+ ctx,
+ k.accountKeeper.GetModuleAccount(ctx, types.ConsumerRewardsPool).GetAddress(),
+ )
+}
+
+// ComputeConsumerTotalVotingPower returns the validator set total voting power
+// for the given consumer chain
+func (k Keeper) ComputeConsumerTotalVotingPower(ctx sdk.Context, chainID string) (totalPower int64) {
+ // sum the opted-in validators set voting powers
+ for _, v := range k.GetConsumerValSet(ctx, chainID) {
+ totalPower += v.Power
+ }
+
+ return
+}
+
+// IdentifyConsumerChainIDFromIBCPacket checks if the packet destination matches a registered consumer chain.
+// If so, it returns the consumer chain ID, otherwise an error.
+func (k Keeper) IdentifyConsumerChainIDFromIBCPacket(ctx sdk.Context, packet channeltypes.Packet) (string, error) {
+ channel, ok := k.channelKeeper.GetChannel(ctx, packet.DestinationPort, packet.DestinationChannel)
+ if !ok {
+ return "", errorsmod.Wrapf(channeltypes.ErrChannelNotFound, "channel not found for channel ID: %s", packet.DestinationChannel)
+ }
+ if len(channel.ConnectionHops) != 1 {
+ return "", errorsmod.Wrap(channeltypes.ErrTooManyConnectionHops, "must have direct connection to consumer chain")
+ }
+ connectionID := channel.ConnectionHops[0]
+ _, tmClient, err := k.getUnderlyingClient(ctx, connectionID)
+ if err != nil {
+ return "", err
+ }
+
+ chainID := tmClient.ChainId
+ if _, ok := k.GetChainToChannel(ctx, chainID); !ok {
+ return "", errorsmod.Wrapf(types.ErrUnknownConsumerChannelId, "no CCV channel found for chain with ID: %s", chainID)
+ }
+
+ return chainID, nil
+}
+
+// HandleSetConsumerCommissionRate sets a per-consumer chain commission rate for the given provider address
+// on the condition that the given consumer chain exists.
+func (k Keeper) HandleSetConsumerCommissionRate(ctx sdk.Context, chainID string, providerAddr types.ProviderConsAddress, commissionRate sdk.Dec) error {
+ // check that the consumer chain exists
+ if !k.IsConsumerProposedOrRegistered(ctx, chainID) {
+ return errorsmod.Wrapf(
+ types.ErrUnknownConsumerChainId,
+ "unknown consumer chain, with id: %s", chainID)
+ }
+
+ // validate against the minimum commission rate
+ minRate := k.stakingKeeper.MinCommissionRate(ctx)
+ if commissionRate.LT(minRate) {
+ return errorsmod.Wrapf(
+ stakingtypes.ErrCommissionLTMinRate,
+ "commission rate cannot be less than %s", minRate,
+ )
}
+ // set per-consumer chain commission rate for the validator address
+ return k.SetConsumerCommissionRate(
+ ctx,
+ chainID,
+ providerAddr,
+ commissionRate,
+ )
}
diff --git a/x/ccv/provider/keeper/distribution_test.go b/x/ccv/provider/keeper/distribution_test.go
new file mode 100644
index 0000000000..4a5cd750fc
--- /dev/null
+++ b/x/ccv/provider/keeper/distribution_test.go
@@ -0,0 +1,272 @@
+package keeper_test
+
+import (
+ "testing"
+
+ clienttypes "github.com/cosmos/ibc-go/v7/modules/core/02-client/types"
+ conntypes "github.com/cosmos/ibc-go/v7/modules/core/03-connection/types"
+ channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types"
+ ibctmtypes "github.com/cosmos/ibc-go/v7/modules/light-clients/07-tendermint"
+ "github.com/golang/mock/gomock"
+ "github.com/stretchr/testify/require"
+
+ sdk "github.com/cosmos/cosmos-sdk/types"
+
+ tmtypes "github.com/cometbft/cometbft/types"
+
+ testkeeper "github.com/cosmos/interchain-security/v5/testutil/keeper"
+ "github.com/cosmos/interchain-security/v5/x/ccv/provider/types"
+ providertypes "github.com/cosmos/interchain-security/v5/x/ccv/provider/types"
+)
+
+func TestComputeConsumerTotalVotingPower(t *testing.T) {
+ keeper, ctx, ctrl, _ := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t))
+ defer ctrl.Finish()
+
+ createVal := func(power int64) tmtypes.Validator {
+ signer := tmtypes.NewMockPV()
+ val := tmtypes.NewValidator(signer.PrivKey.PubKey(), power)
+ return *val
+ }
+
+ chainID := "consumer"
+ expTotalPower := int64(0)
+
+ // verify that the total power returned is equal to zero
+ // when the consumer doesn't exist or has no validators.
+ require.Zero(t, keeper.ComputeConsumerTotalVotingPower(
+ ctx,
+ chainID,
+ ))
+
+ // set 5 validators to the consumer chain
+ for i := 0; i < 5; i++ {
+ val := createVal(int64(i))
+ keeper.SetConsumerValidator(
+ ctx,
+ chainID,
+ types.ConsumerValidator{
+ ProviderConsAddr: val.Address,
+ Power: val.VotingPower,
+ },
+ )
+
+ expTotalPower += val.VotingPower
+ }
+
+ // compute the total power of opted-in validators
+ res := keeper.ComputeConsumerTotalVotingPower(
+ ctx,
+ chainID,
+ )
+
+ // check the total power returned
+ require.Equal(t, expTotalPower, res)
+}
+
+func TestIdentifyConsumerChainIDFromIBCPacket(t *testing.T) {
+ var (
+ chainID = "consumer"
+ ccvChannel = "channel-0"
+ )
+
+ testCases := []struct {
+ name string
+ packet channeltypes.Packet
+ expectedCalls func(sdk.Context, testkeeper.MockedKeepers, channeltypes.Packet) []*gomock.Call
+ expCCVChannel bool
+ expErr bool
+ }{
+ {
+ "channel not found",
+ channeltypes.NewPacket(
+ []byte{},
+ 0,
+ "srcPort",
+ "srcChannel",
+ "dstPort",
+ "dstChannel",
+ clienttypes.NewHeight(1, 1),
+ 0,
+ ),
+ func(ctx sdk.Context, mocks testkeeper.MockedKeepers, packet channeltypes.Packet) []*gomock.Call {
+ return []*gomock.Call{
+ mocks.MockChannelKeeper.EXPECT().GetChannel(
+ ctx,
+ packet.DestinationPort,
+ packet.DestinationChannel,
+ ).Return(channeltypes.Channel{}, false).Times(1),
+ }
+ },
+ false,
+ true,
+ },
+ {
+ "connection hops can't be greater than 1",
+ channeltypes.NewPacket(
+ []byte{},
+ 0,
+ "srcPort",
+ "srcChannel",
+ "dstPort",
+ "dstChannel",
+ clienttypes.NewHeight(1, 1),
+ 0,
+ ),
+ func(ctx sdk.Context, mocks testkeeper.MockedKeepers, packet channeltypes.Packet) []*gomock.Call {
+ return []*gomock.Call{
+ mocks.MockChannelKeeper.EXPECT().GetChannel(
+ ctx,
+ packet.DestinationPort,
+ packet.DestinationChannel,
+ ).Return(channeltypes.Channel{ConnectionHops: []string{"conn1", "conn2"}}, true).Times(1),
+ }
+ },
+ false,
+ true,
+ },
+ {
+ "underlying client isn't found",
+ channeltypes.NewPacket(
+ []byte{},
+ 0,
+ "srcPort",
+ "srcChannel",
+ "dstPort",
+ "dstChannel",
+ clienttypes.NewHeight(1, 1),
+ 0,
+ ),
+ func(ctx sdk.Context, mocks testkeeper.MockedKeepers, packet channeltypes.Packet) []*gomock.Call {
+ return []*gomock.Call{
+ mocks.MockChannelKeeper.EXPECT().GetChannel(
+ ctx,
+ packet.DestinationPort,
+ packet.DestinationChannel,
+ ).Return(channeltypes.Channel{ConnectionHops: []string{"connectionID"}}, true).Times(1),
+ mocks.MockConnectionKeeper.EXPECT().GetConnection(ctx, "connectionID").Return(
+ conntypes.ConnectionEnd{ClientId: "clientID"}, true,
+ ).Times(1),
+ mocks.MockClientKeeper.EXPECT().GetClientState(ctx, "clientID").Return(
+ &ibctmtypes.ClientState{ChainId: ""}, false,
+ ).Times(1),
+ }
+ },
+ false,
+ true,
+ },
+ {
+ "no CCV channel registered",
+ channeltypes.NewPacket(
+ []byte{},
+ 0,
+ "srcPort",
+ "srcChannel",
+ "dstPort",
+ "dstChannel",
+ clienttypes.NewHeight(1, 1),
+ 0,
+ ),
+ func(ctx sdk.Context, mocks testkeeper.MockedKeepers, packet channeltypes.Packet) []*gomock.Call {
+ return []*gomock.Call{
+ mocks.MockChannelKeeper.EXPECT().GetChannel(
+ ctx,
+ packet.DestinationPort,
+ packet.DestinationChannel,
+ ).Return(channeltypes.Channel{ConnectionHops: []string{"connectionID"}}, true).Times(1),
+ mocks.MockConnectionKeeper.EXPECT().GetConnection(ctx, "connectionID").Return(
+ conntypes.ConnectionEnd{ClientId: "clientID"}, true,
+ ).Times(1),
+ mocks.MockClientKeeper.EXPECT().GetClientState(ctx, "clientID").Return(
+ &ibctmtypes.ClientState{ChainId: chainID}, true,
+ ).Times(1),
+ }
+ },
+ false,
+ true,
+ },
+ {
+ "consumer chain identified",
+ channeltypes.NewPacket(
+ []byte{},
+ 0,
+ "srcPort",
+ "srcChannel",
+ "dstPort",
+ "dstChannel",
+ clienttypes.NewHeight(1, 1),
+ 0,
+ ),
+ func(ctx sdk.Context, mocks testkeeper.MockedKeepers, packet channeltypes.Packet) []*gomock.Call {
+ return []*gomock.Call{
+ mocks.MockChannelKeeper.EXPECT().GetChannel(
+ ctx,
+ packet.DestinationPort,
+ packet.DestinationChannel,
+ ),
+ }
+ },
+ false,
+ true,
+ },
+ }
+
+ for _, tc := range testCases {
+ t.Run(tc.name, func(t *testing.T) {
+ keeper, ctx, ctrl, mocks := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t))
+ defer ctrl.Finish()
+
+ tc.expectedCalls(ctx, mocks, tc.packet)
+ _, err := keeper.IdentifyConsumerChainIDFromIBCPacket(
+ ctx,
+ tc.packet,
+ )
+
+ if tc.expCCVChannel {
+ keeper.SetChainToChannel(ctx, chainID, ccvChannel)
+ }
+
+ if !tc.expErr {
+ require.NoError(t, err)
+ } else {
+ require.Error(t, err)
+ }
+ })
+ }
+}
+
+func TestSetConsumerRewardsAllocation(t *testing.T) {
+ keeperParams := testkeeper.NewInMemKeeperParams(t)
+ ctx := keeperParams.Ctx
+
+ ctrl := gomock.NewController(t)
+ defer ctrl.Finish()
+ mocks := testkeeper.NewMockedKeepers(ctrl)
+ providerKeeper := testkeeper.NewInMemProviderKeeper(keeperParams, mocks)
+
+ rewardAllocation := providertypes.ConsumerRewardsAllocation{
+ Rewards: sdk.NewDecCoins(sdk.NewDecCoin("uatom", sdk.NewInt(1000))),
+ }
+
+ providerKeeper.SetConsumerRewardsAllocation(ctx, "consumer-1", rewardAllocation)
+
+ alloc := providerKeeper.GetConsumerRewardsAllocation(ctx, "consumer-1")
+ require.Equal(t, rewardAllocation, alloc)
+}
+
+func TestGetConsumerRewardsAllocationNil(t *testing.T) {
+ keeperParams := testkeeper.NewInMemKeeperParams(t)
+ ctx := keeperParams.Ctx
+
+ ctrl := gomock.NewController(t)
+ defer ctrl.Finish()
+ mocks := testkeeper.NewMockedKeepers(ctrl)
+ providerKeeper := testkeeper.NewInMemProviderKeeper(keeperParams, mocks)
+
+ alloc := providerKeeper.GetConsumerRewardsAllocation(ctx, "consumer-1")
+
+ expectedRewardAllocation := providertypes.ConsumerRewardsAllocation{
+ Rewards: nil,
+ }
+ require.Equal(t, expectedRewardAllocation, alloc)
+}
diff --git a/x/ccv/provider/keeper/genesis.go b/x/ccv/provider/keeper/genesis.go
index 2075ff48ae..66895233a7 100644
--- a/x/ccv/provider/keeper/genesis.go
+++ b/x/ccv/provider/keeper/genesis.go
@@ -5,8 +5,8 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
- "github.com/cosmos/interchain-security/v4/x/ccv/provider/types"
- ccv "github.com/cosmos/interchain-security/v4/x/ccv/types"
+ "github.com/cosmos/interchain-security/v5/x/ccv/provider/types"
+ ccv "github.com/cosmos/interchain-security/v5/x/ccv/types"
)
// InitGenesis initializes the CCV provider state and binds to PortID.
diff --git a/x/ccv/provider/keeper/genesis_test.go b/x/ccv/provider/keeper/genesis_test.go
index 81b0a90bd8..e75241eb58 100644
--- a/x/ccv/provider/keeper/genesis_test.go
+++ b/x/ccv/provider/keeper/genesis_test.go
@@ -11,11 +11,11 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
- "github.com/cosmos/interchain-security/v4/testutil/crypto"
- testkeeper "github.com/cosmos/interchain-security/v4/testutil/keeper"
- "github.com/cosmos/interchain-security/v4/x/ccv/provider/keeper"
- providertypes "github.com/cosmos/interchain-security/v4/x/ccv/provider/types"
- ccv "github.com/cosmos/interchain-security/v4/x/ccv/types"
+ "github.com/cosmos/interchain-security/v5/testutil/crypto"
+ testkeeper "github.com/cosmos/interchain-security/v5/testutil/keeper"
+ "github.com/cosmos/interchain-security/v5/x/ccv/provider/keeper"
+ providertypes "github.com/cosmos/interchain-security/v5/x/ccv/provider/types"
+ ccv "github.com/cosmos/interchain-security/v5/x/ccv/types"
)
// TestInitAndExportGenesis tests the export and the initialisation of a provider chain genesis
diff --git a/x/ccv/provider/keeper/grpc_query.go b/x/ccv/provider/keeper/grpc_query.go
index 6803c60ddd..2baed949b7 100644
--- a/x/ccv/provider/keeper/grpc_query.go
+++ b/x/ccv/provider/keeper/grpc_query.go
@@ -2,6 +2,7 @@ package keeper
import (
"context"
+ "fmt"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
@@ -10,8 +11,8 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
- "github.com/cosmos/interchain-security/v4/x/ccv/provider/types"
- ccvtypes "github.com/cosmos/interchain-security/v4/x/ccv/types"
+ "github.com/cosmos/interchain-security/v5/x/ccv/provider/types"
+ ccvtypes "github.com/cosmos/interchain-security/v5/x/ccv/types"
)
var _ types.QueryServer = Keeper{}
@@ -45,7 +46,6 @@ func (k Keeper) QueryConsumerChains(goCtx context.Context, req *types.QueryConsu
ctx := sdk.UnwrapSDKContext(goCtx)
- // convert to array of pointers
chains := []*types.Chain{}
for _, chain := range k.GetAllConsumerChains(ctx) {
// prevent implicit memory aliasing
@@ -225,6 +225,110 @@ func (k Keeper) QueryParams(c context.Context, _ *types.QueryParamsRequest) (*ty
return &types.QueryParamsResponse{Params: params}, nil
}
+// QueryConsumerChainOptedInValidators returns all validators that opted-in to a given consumer chain
+func (k Keeper) QueryConsumerChainOptedInValidators(goCtx context.Context, req *types.QueryConsumerChainOptedInValidatorsRequest) (*types.QueryConsumerChainOptedInValidatorsResponse, error) {
+ if req == nil {
+ return nil, status.Error(codes.InvalidArgument, "empty request")
+ }
+
+ consumerChainID := req.ChainId
+ if consumerChainID == "" {
+ return nil, status.Error(codes.InvalidArgument, "empty chainId")
+ }
+
+ optedInVals := []string{}
+ ctx := sdk.UnwrapSDKContext(goCtx)
+
+ if !k.IsConsumerProposedOrRegistered(ctx, consumerChainID) {
+ return nil, status.Error(codes.InvalidArgument, fmt.Sprintf("unknown consumer chain: %s", consumerChainID))
+ }
+
+ for _, v := range k.GetAllOptedIn(ctx, consumerChainID) {
+ optedInVals = append(optedInVals, v.ToSdkConsAddr().String())
+ }
+
+ return &types.QueryConsumerChainOptedInValidatorsResponse{
+ ValidatorsProviderAddresses: optedInVals,
+ }, nil
+}
+
+// QueryConsumerChainsValidatorHasToValidate returns all consumer chains that the given validator has to validate now
+// or in the next epoch if nothing changes.
+func (k Keeper) QueryConsumerChainsValidatorHasToValidate(goCtx context.Context, req *types.QueryConsumerChainsValidatorHasToValidateRequest) (*types.QueryConsumerChainsValidatorHasToValidateResponse, error) {
+ if req == nil {
+ return nil, status.Error(codes.InvalidArgument, "empty request")
+ }
+
+ if req.ProviderAddress == "" {
+ return nil, status.Error(codes.InvalidArgument, "empty provider address")
+ }
+
+ consAddr, err := sdk.ConsAddressFromBech32(req.ProviderAddress)
+ if err != nil {
+ return nil, status.Error(codes.InvalidArgument, "invalid provider address")
+ }
+
+ ctx := sdk.UnwrapSDKContext(goCtx)
+
+ provAddr := types.NewProviderConsAddress(consAddr)
+
+ // get all the consumer chains for which the validator is either already
+ // opted-in, currently a consumer validator or if its voting power is within the TopN validators
+ consumersToValidate := []string{}
+ for _, consumer := range k.GetAllConsumerChains(ctx) {
+ chainID := consumer.ChainId
+
+ if hasToValidate, err := k.HasToValidate(ctx, provAddr, chainID); err == nil && hasToValidate {
+ consumersToValidate = append(consumersToValidate, chainID)
+ }
+ }
+
+ return &types.QueryConsumerChainsValidatorHasToValidateResponse{
+ ConsumerChainIds: consumersToValidate,
+ }, nil
+}
+
+// QueryValidatorConsumerCommissionRate returns the commission rate a given
+// validator charges on a given consumer chain
+func (k Keeper) QueryValidatorConsumerCommissionRate(goCtx context.Context, req *types.QueryValidatorConsumerCommissionRateRequest) (*types.QueryValidatorConsumerCommissionRateResponse, error) {
+ if req == nil {
+ return nil, status.Error(codes.InvalidArgument, "empty request")
+ }
+
+ consumerChainID := req.ChainId
+ if consumerChainID == "" {
+ return nil, status.Error(codes.InvalidArgument, "empty chainId")
+ }
+
+ consAddr, err := sdk.ConsAddressFromBech32(req.ProviderAddress)
+ if err != nil {
+ return nil, status.Error(codes.InvalidArgument, "invalid provider address")
+ }
+
+ ctx := sdk.UnwrapSDKContext(goCtx)
+
+ if !k.IsConsumerProposedOrRegistered(ctx, consumerChainID) {
+ return nil, status.Error(codes.InvalidArgument, fmt.Sprintf("unknown consumer chain: %s", consumerChainID))
+ }
+
+ res := &types.QueryValidatorConsumerCommissionRateResponse{}
+
+ // Check if the validator has a commission rate set for the consumer chain,
+ // otherwise use the commission rate from the validator staking module struct
+ consumerRate, found := k.GetConsumerCommissionRate(ctx, consumerChainID, types.NewProviderConsAddress(consAddr))
+ if found {
+ res.Rate = consumerRate
+ } else {
+ v, ok := k.stakingKeeper.GetValidatorByConsAddr(ctx, consAddr)
+ if !ok {
+ return nil, status.Error(codes.InvalidArgument, fmt.Sprintf("unknown validator: %s", consAddr.String()))
+ }
+ res.Rate = v.Commission.Rate
+ }
+
+ return res, nil
+}
+
func (k Keeper) QueryOldestUnconfirmedVsc(goCtx context.Context, req *types.QueryOldestUnconfirmedVscRequest) (*types.QueryOldestUnconfirmedVscResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)
diff --git a/x/ccv/provider/keeper/grpc_query_test.go b/x/ccv/provider/keeper/grpc_query_test.go
index 14e6e675e1..8283f11235 100644
--- a/x/ccv/provider/keeper/grpc_query_test.go
+++ b/x/ccv/provider/keeper/grpc_query_test.go
@@ -8,10 +8,10 @@ import (
sdktypes "github.com/cosmos/cosmos-sdk/types"
- cryptotestutil "github.com/cosmos/interchain-security/v4/testutil/crypto"
- testkeeper "github.com/cosmos/interchain-security/v4/testutil/keeper"
- "github.com/cosmos/interchain-security/v4/x/ccv/provider/types"
- ccvtypes "github.com/cosmos/interchain-security/v4/x/ccv/types"
+ cryptotestutil "github.com/cosmos/interchain-security/v5/testutil/crypto"
+ testkeeper "github.com/cosmos/interchain-security/v5/testutil/keeper"
+ "github.com/cosmos/interchain-security/v5/x/ccv/provider/types"
+ ccvtypes "github.com/cosmos/interchain-security/v5/x/ccv/types"
)
func TestQueryAllPairsValConAddrByConsumerChainID(t *testing.T) {
diff --git a/x/ccv/provider/keeper/hooks.go b/x/ccv/provider/keeper/hooks.go
index 88590a9875..763804868e 100644
--- a/x/ccv/provider/keeper/hooks.go
+++ b/x/ccv/provider/keeper/hooks.go
@@ -8,8 +8,9 @@ import (
v1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
- providertypes "github.com/cosmos/interchain-security/v4/x/ccv/provider/types"
- ccvtypes "github.com/cosmos/interchain-security/v4/x/ccv/types"
+ "github.com/cosmos/interchain-security/v5/x/ccv/provider/types"
+ providertypes "github.com/cosmos/interchain-security/v5/x/ccv/provider/types"
+ ccvtypes "github.com/cosmos/interchain-security/v5/x/ccv/types"
)
// Wrapper struct
@@ -35,8 +36,64 @@ func (k *Keeper) Hooks() Hooks {
func (h Hooks) AfterUnbondingInitiated(ctx sdk.Context, id uint64) error {
var consumerChainIDS []string
+ // get validator address from unbonding operation
+ unbondingType, found := h.k.stakingKeeper.GetUnbondingType(ctx, id)
+ vadAddrBech32 := ""
+ if !found {
+ ctx.Logger().Error("undefined type for unbonding operation id: %d", id)
+ return nil
+ }
+
+ switch unbondingType {
+ case stakingtypes.UnbondingType_UnbondingDelegation:
+ ubd, found := h.k.stakingKeeper.GetUnbondingDelegationByUnbondingID(ctx, id)
+ if !found {
+ ctx.Logger().Error("unfound ubonding delegation for unbonding id: %d", id)
+ return nil
+ }
+ vadAddrBech32 = ubd.ValidatorAddress
+ case stakingtypes.UnbondingType_Redelegation:
+ red, found := h.k.stakingKeeper.GetRedelegationByUnbondingID(ctx, id)
+ if !found {
+ ctx.Logger().Error("unfound relegation for unbonding operation id: %d", id)
+ return nil
+ }
+ vadAddrBech32 = red.ValidatorSrcAddress
+ case stakingtypes.UnbondingType_ValidatorUnbonding:
+ val, found := h.k.stakingKeeper.GetValidatorByUnbondingID(ctx, id)
+ if !found {
+ ctx.Logger().Error("unfound validator for unbonding operation id: %d", id)
+ return nil
+ }
+ vadAddrBech32 = val.OperatorAddress
+ default:
+ ctx.Logger().Error("invalid unbonding operation type: %s", unbondingType)
+ return nil
+ }
+
+ valAddr, err := sdk.ValAddressFromBech32(vadAddrBech32)
+ if err != nil {
+ ctx.Logger().Error(err.Error())
+ return nil
+ }
+
+ validator, found := h.k.stakingKeeper.GetValidator(ctx, valAddr)
+ if !found {
+ ctx.Logger().Error("unfound validator for validator address %s", vadAddrBech32)
+ return nil
+ }
+
+ consAddr, err := validator.GetConsAddr()
+ if err != nil {
+ ctx.Logger().Error(err.Error())
+ return nil
+ }
+
+ // get all consumers where the validator is in the validator set
for _, chain := range h.k.GetAllConsumerChains(ctx) {
- consumerChainIDS = append(consumerChainIDS, chain.ChainId)
+ if h.k.IsConsumerValidator(ctx, chain.ChainId, types.NewProviderConsAddress(consAddr)) {
+ consumerChainIDS = append(consumerChainIDS, chain.ChainId)
+ }
}
if len(consumerChainIDS) == 0 {
diff --git a/x/ccv/provider/keeper/hooks_test.go b/x/ccv/provider/keeper/hooks_test.go
index f4aad8d441..5372fc37cd 100644
--- a/x/ccv/provider/keeper/hooks_test.go
+++ b/x/ccv/provider/keeper/hooks_test.go
@@ -15,9 +15,9 @@ import (
v1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1"
"github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1"
- cryptotestutil "github.com/cosmos/interchain-security/v4/testutil/crypto"
- testkeeper "github.com/cosmos/interchain-security/v4/testutil/keeper"
- providerkeeper "github.com/cosmos/interchain-security/v4/x/ccv/provider/keeper"
+ cryptotestutil "github.com/cosmos/interchain-security/v5/testutil/crypto"
+ testkeeper "github.com/cosmos/interchain-security/v5/testutil/keeper"
+ providerkeeper "github.com/cosmos/interchain-security/v5/x/ccv/provider/keeper"
)
func TestValidatorConsensusKeyInUse(t *testing.T) {
@@ -123,11 +123,13 @@ func TestAfterPropSubmissionAndVotingPeriodEnded(t *testing.T) {
k.Hooks().AfterProposalSubmission(ctx, prop.Id)
// verify that the proposal ID is created
- require.NotEmpty(t, k.GetProposedConsumerChain(ctx, prop.Id))
+ _, found := k.GetProposedConsumerChain(ctx, prop.Id)
+ require.True(t, found)
k.Hooks().AfterProposalVotingPeriodEnded(ctx, prop.Id)
// verify that the proposal ID is deleted
- require.Empty(t, k.GetProposedConsumerChain(ctx, prop.Id))
+ _, found = k.GetProposedConsumerChain(ctx, prop.Id)
+ require.False(t, found)
}
func TestGetConsumerAdditionLegacyPropFromProp(t *testing.T) {
diff --git a/x/ccv/provider/keeper/keeper.go b/x/ccv/provider/keeper/keeper.go
index 510d957c5d..e602c16e5e 100644
--- a/x/ccv/provider/keeper/keeper.go
+++ b/x/ccv/provider/keeper/keeper.go
@@ -23,9 +23,9 @@ import (
"github.com/cometbft/cometbft/libs/log"
- consumertypes "github.com/cosmos/interchain-security/v4/x/ccv/consumer/types"
- "github.com/cosmos/interchain-security/v4/x/ccv/provider/types"
- ccv "github.com/cosmos/interchain-security/v4/x/ccv/types"
+ consumertypes "github.com/cosmos/interchain-security/v5/x/ccv/consumer/types"
+ "github.com/cosmos/interchain-security/v5/x/ccv/provider/types"
+ ccv "github.com/cosmos/interchain-security/v5/x/ccv/types"
)
// Keeper defines the Cross-Chain Validation Provider Keeper
@@ -186,9 +186,14 @@ func (k Keeper) SetProposedConsumerChain(ctx sdk.Context, chainID string, propos
}
// GetProposedConsumerChain returns the proposed chainID for the given consumerAddition proposal ID.
-func (k Keeper) GetProposedConsumerChain(ctx sdk.Context, proposalID uint64) string {
+// This method is only used for testing.
+func (k Keeper) GetProposedConsumerChain(ctx sdk.Context, proposalID uint64) (string, bool) {
store := ctx.KVStore(k.storeKey)
- return string(store.Get(types.ProposedConsumerChainKey(proposalID)))
+ consumerChain := store.Get(types.ProposedConsumerChainKey(proposalID))
+ if consumerChain != nil {
+ return string(consumerChain), true
+ }
+ return "", false
}
// DeleteProposedConsumerChainInStore deletes the consumer chainID from store
@@ -248,9 +253,12 @@ func (k Keeper) GetAllConsumerChains(ctx sdk.Context) (chains []types.Chain) {
chainID := string(iterator.Key()[1:])
clientID := string(iterator.Value())
+ topN, _ := k.GetTopN(ctx, chainID)
+
chains = append(chains, types.Chain{
ChainId: chainID,
ClientId: clientID,
+ Top_N: topN,
})
}
@@ -1136,3 +1144,394 @@ func (k Keeper) GetAllRegisteredAndProposedChainIDs(ctx sdk.Context) []string {
return allConsumerChains
}
+
+// SetTopN stores the N value associated to chain with `chainID`
+func (k Keeper) SetTopN(
+ ctx sdk.Context,
+ chainID string,
+ N uint32,
+) {
+ store := ctx.KVStore(k.storeKey)
+
+ buf := make([]byte, 4)
+ binary.BigEndian.PutUint32(buf, N)
+
+ store.Set(types.TopNKey(chainID), buf)
+}
+
+// DeleteTopN removes the N value associated to chain with `chainID`
+func (k Keeper) DeleteTopN(
+ ctx sdk.Context,
+ chainID string,
+) {
+ store := ctx.KVStore(k.storeKey)
+ store.Delete(types.TopNKey(chainID))
+}
+
+// GetTopN returns (N, true) if chain `chainID` has a top N associated, and (0, false) otherwise.
+func (k Keeper) GetTopN(
+ ctx sdk.Context,
+ chainID string,
+) (uint32, bool) {
+ store := ctx.KVStore(k.storeKey)
+ buf := store.Get(types.TopNKey(chainID))
+ if buf == nil {
+ return 0, false
+ }
+ return binary.BigEndian.Uint32(buf), true
+}
+
+// IsTopN returns true if chain with `chainID` is a Top-N chain (i.e., enforces at least one validator to validate chain `chainID`)
+func (k Keeper) IsTopN(ctx sdk.Context, chainID string) bool {
+ topN, found := k.GetTopN(ctx, chainID)
+ return found && topN > 0
+}
+
+// IsOptIn returns true if chain with `chainID` is an Opt-In chain (i.e., no validator is forced to validate chain `chainID`)
+func (k Keeper) IsOptIn(ctx sdk.Context, chainID string) bool {
+ topN, found := k.GetTopN(ctx, chainID)
+ return !found || topN == 0
+}
+
+func (k Keeper) SetOptedIn(
+ ctx sdk.Context,
+ chainID string,
+ providerConsAddress types.ProviderConsAddress,
+) {
+ store := ctx.KVStore(k.storeKey)
+ store.Set(types.OptedInKey(chainID, providerConsAddress), []byte{})
+}
+
+func (k Keeper) DeleteOptedIn(
+ ctx sdk.Context,
+ chainID string,
+ providerAddr types.ProviderConsAddress,
+) {
+ store := ctx.KVStore(k.storeKey)
+ store.Delete(types.OptedInKey(chainID, providerAddr))
+}
+
+func (k Keeper) IsOptedIn(
+ ctx sdk.Context,
+ chainID string,
+ providerAddr types.ProviderConsAddress,
+) bool {
+ store := ctx.KVStore(k.storeKey)
+ return store.Get(types.OptedInKey(chainID, providerAddr)) != nil
+}
+
+// GetAllOptedIn returns all the opted-in validators on chain `chainID`
+func (k Keeper) GetAllOptedIn(
+ ctx sdk.Context,
+ chainID string,
+) (providerConsAddresses []types.ProviderConsAddress) {
+ store := ctx.KVStore(k.storeKey)
+ key := types.ChainIdWithLenKey(types.OptedInBytePrefix, chainID)
+ iterator := sdk.KVStorePrefixIterator(store, key)
+ defer iterator.Close()
+
+ for ; iterator.Valid(); iterator.Next() {
+ providerConsAddresses = append(providerConsAddresses, types.NewProviderConsAddress(iterator.Key()[len(key):]))
+ }
+
+ return providerConsAddresses
+}
+
+// DeleteAllOptedIn deletes all the opted-in validators for chain with `chainID`
+func (k Keeper) DeleteAllOptedIn(
+ ctx sdk.Context,
+ chainID string,
+) {
+ store := ctx.KVStore(k.storeKey)
+ key := types.ChainIdWithLenKey(types.OptedInBytePrefix, chainID)
+ iterator := sdk.KVStorePrefixIterator(store, key)
+
+ var keysToDel [][]byte
+ defer iterator.Close()
+ for ; iterator.Valid(); iterator.Next() {
+ keysToDel = append(keysToDel, iterator.Key())
+ }
+ for _, delKey := range keysToDel {
+ store.Delete(delKey)
+ }
+}
+
+func (k Keeper) HasToValidate(
+ ctx sdk.Context,
+ provAddr types.ProviderConsAddress,
+ chainID string,
+) (bool, error) {
+ // if the validator was sent as part of the packet in the last epoch, it has to validate
+ if k.IsConsumerValidator(ctx, chainID, provAddr) {
+ return true, nil
+ }
+
+ // if the validator was not part of the last epoch, check if the validator is going to be part of te next epoch
+ bondedValidators := k.stakingKeeper.GetLastValidators(ctx)
+ if topN, found := k.GetTopN(ctx, chainID); found && topN > 0 {
+ // in a Top-N chain, we automatically opt in all validators that belong to the top N
+ minPower, err := k.ComputeMinPowerToOptIn(ctx, chainID, bondedValidators, topN)
+ if err == nil {
+ k.OptInTopNValidators(ctx, chainID, bondedValidators, minPower)
+ }
+ }
+
+ // if the validator is opted in and belongs to the validators of the next epoch, then if nothing changes
+ // the validator would have to validate in the next epoch
+ if k.IsOptedIn(ctx, chainID, provAddr) {
+ nextValidators := k.ComputeNextValidators(ctx, chainID, k.stakingKeeper.GetLastValidators(ctx))
+ for _, v := range nextValidators {
+ consAddr := sdk.ConsAddress(v.ProviderConsAddr)
+ if provAddr.ToSdkConsAddr().Equals(consAddr) {
+ return true, nil
+ }
+ }
+ }
+
+ return false, nil
+}
+
+// SetConsumerCommissionRate sets a per-consumer chain commission rate
+// for the given validator address
+func (k Keeper) SetConsumerCommissionRate(
+ ctx sdk.Context,
+ chainID string,
+ providerAddr types.ProviderConsAddress,
+ commissionRate sdk.Dec,
+) error {
+ store := ctx.KVStore(k.storeKey)
+ bz, err := commissionRate.Marshal()
+ if err != nil {
+ err = fmt.Errorf("consumer commission rate marshalling failed: %s", err)
+ k.Logger(ctx).Error(err.Error())
+ return err
+ }
+
+ store.Set(types.ConsumerCommissionRateKey(chainID, providerAddr), bz)
+ return nil
+}
+
+// GetConsumerCommissionRate returns the per-consumer commission rate set
+// for the given validator address
+func (k Keeper) GetConsumerCommissionRate(
+ ctx sdk.Context,
+ chainID string,
+ providerAddr types.ProviderConsAddress,
+) (sdk.Dec, bool) {
+ store := ctx.KVStore(k.storeKey)
+ bz := store.Get(types.ConsumerCommissionRateKey(chainID, providerAddr))
+ if bz == nil {
+ return sdk.ZeroDec(), false
+ }
+
+ cr := sdk.Dec{}
+ // handle error gracefully since it's called in BeginBlockRD
+ if err := cr.Unmarshal(bz); err != nil {
+ k.Logger(ctx).Error("consumer commission rate unmarshalling failed: %s", err)
+ return sdk.ZeroDec(), false
+ }
+
+ return cr, true
+}
+
+// GetAllCommissionRateValidators returns all the validator address
+// that set a commission rate for the given chain ID
+func (k Keeper) GetAllCommissionRateValidators(
+ ctx sdk.Context,
+ chainID string,
+) (addresses []types.ProviderConsAddress) {
+ store := ctx.KVStore(k.storeKey)
+ key := types.ChainIdWithLenKey(types.ConsumerCommissionRatePrefix, chainID)
+ iterator := sdk.KVStorePrefixIterator(store, key)
+ defer iterator.Close()
+
+ for ; iterator.Valid(); iterator.Next() {
+ providerAddr := types.NewProviderConsAddress(iterator.Key()[len(key):])
+ addresses = append(addresses, providerAddr)
+ }
+
+ return addresses
+}
+
+// DeleteConsumerCommissionRate the per-consumer chain commission rate
+// associated to the given validator address
+func (k Keeper) DeleteConsumerCommissionRate(
+ ctx sdk.Context,
+ chainID string,
+ providerAddr types.ProviderConsAddress,
+) {
+ store := ctx.KVStore(k.storeKey)
+ store.Delete(types.ConsumerCommissionRateKey(chainID, providerAddr))
+}
+
+// SetValidatorsPowerCap sets the power-cap value `p` associated to chain with `chainID`
+func (k Keeper) SetValidatorsPowerCap(
+ ctx sdk.Context,
+ chainID string,
+ p uint32,
+) {
+ store := ctx.KVStore(k.storeKey)
+
+ buf := make([]byte, 4)
+ binary.BigEndian.PutUint32(buf, p)
+
+ store.Set(types.ValidatorsPowerCapKey(chainID), buf)
+}
+
+// DeleteValidatorsPowerCap removes the power-cap value associated to chain with `chainID`
+func (k Keeper) DeleteValidatorsPowerCap(
+ ctx sdk.Context,
+ chainID string,
+) {
+ store := ctx.KVStore(k.storeKey)
+ store.Delete(types.ValidatorsPowerCapKey(chainID))
+}
+
+// GetValidatorsPowerCap returns `(p, true)` if chain `chainID` has power cap `p` associated with it, and (0, false) otherwise
+func (k Keeper) GetValidatorsPowerCap(
+ ctx sdk.Context,
+ chainID string,
+) (uint32, bool) {
+ store := ctx.KVStore(k.storeKey)
+ buf := store.Get(types.ValidatorsPowerCapKey(chainID))
+ if buf == nil {
+ return 0, false
+ }
+ return binary.BigEndian.Uint32(buf), true
+}
+
+// SetValidatorSetCap stores the validator-set cap value `c` associated to chain with `chainID`
+func (k Keeper) SetValidatorSetCap(
+ ctx sdk.Context,
+ chainID string,
+ c uint32,
+) {
+ store := ctx.KVStore(k.storeKey)
+
+ buf := make([]byte, 4)
+ binary.BigEndian.PutUint32(buf, c)
+
+ store.Set(types.ValidatorSetCapKey(chainID), buf)
+}
+
+// DeleteValidatorSetCap removes the validator-set cap value associated to chain with `chainID`
+func (k Keeper) DeleteValidatorSetCap(
+ ctx sdk.Context,
+ chainID string,
+) {
+ store := ctx.KVStore(k.storeKey)
+ store.Delete(types.ValidatorSetCapKey(chainID))
+}
+
+// GetValidatorSetCap returns `(c, true)` if chain `chainID` has validator-set cap `c` associated with it, and (0, false) otherwise
+func (k Keeper) GetValidatorSetCap(
+ ctx sdk.Context,
+ chainID string,
+) (uint32, bool) {
+ store := ctx.KVStore(k.storeKey)
+ buf := store.Get(types.ValidatorSetCapKey(chainID))
+ if buf == nil {
+ return 0, false
+ }
+ return binary.BigEndian.Uint32(buf), true
+}
+
+// SetAllowlist allowlists validator with `providerAddr` address on chain `chainID`
+func (k Keeper) SetAllowlist(
+ ctx sdk.Context,
+ chainID string,
+ providerAddr types.ProviderConsAddress,
+) {
+ store := ctx.KVStore(k.storeKey)
+ store.Set(types.AllowlistCapKey(chainID, providerAddr), []byte{})
+}
+
+// IsAllowlisted returns `true` if validator with `providerAddr` has been allowlisted on chain `chainID`
+func (k Keeper) IsAllowlisted(
+ ctx sdk.Context,
+ chainID string,
+ providerAddr types.ProviderConsAddress,
+) bool {
+ store := ctx.KVStore(k.storeKey)
+ bz := store.Get(types.AllowlistCapKey(chainID, providerAddr))
+ return bz != nil
+}
+
+// DeleteAllowlist deletes all allowlisted validators
+func (k Keeper) DeleteAllowlist(ctx sdk.Context, chainID string) {
+ store := ctx.KVStore(k.storeKey)
+ iterator := sdk.KVStorePrefixIterator(store, types.ChainIdWithLenKey(types.AllowlistPrefix, chainID))
+ defer iterator.Close()
+
+ keysToDel := [][]byte{}
+ for ; iterator.Valid(); iterator.Next() {
+ keysToDel = append(keysToDel, iterator.Key())
+ }
+
+ for _, key := range keysToDel {
+ store.Delete(key)
+ }
+}
+
+// IsAllowlistEmpty returns `true` if no validator is allowlisted on chain `chainID`
+func (k Keeper) IsAllowlistEmpty(ctx sdk.Context, chainID string) bool {
+ store := ctx.KVStore(k.storeKey)
+ iterator := sdk.KVStorePrefixIterator(store, types.ChainIdWithLenKey(types.AllowlistPrefix, chainID))
+ defer iterator.Close()
+
+ if iterator.Valid() {
+ return false
+ }
+
+ return true
+}
+
+// SetDenylist denylists validator with `providerAddr` address on chain `chainID`
+func (k Keeper) SetDenylist(
+ ctx sdk.Context,
+ chainID string,
+ providerAddr types.ProviderConsAddress,
+) {
+ store := ctx.KVStore(k.storeKey)
+ store.Set(types.DenylistCapKey(chainID, providerAddr), []byte{})
+}
+
+// IsDenylisted returns `true` if validator with `providerAddr` has been denylisted on chain `chainID`
+func (k Keeper) IsDenylisted(
+ ctx sdk.Context,
+ chainID string,
+ providerAddr types.ProviderConsAddress,
+) bool {
+ store := ctx.KVStore(k.storeKey)
+ bz := store.Get(types.DenylistCapKey(chainID, providerAddr))
+ return bz != nil
+}
+
+// DeleteDenylist deletes all denylisted validators
+func (k Keeper) DeleteDenylist(ctx sdk.Context, chainID string) {
+ store := ctx.KVStore(k.storeKey)
+ iterator := sdk.KVStorePrefixIterator(store, types.ChainIdWithLenKey(types.DenylistPrefix, chainID))
+ defer iterator.Close()
+
+ keysToDel := [][]byte{}
+ for ; iterator.Valid(); iterator.Next() {
+ keysToDel = append(keysToDel, iterator.Key())
+ }
+
+ for _, key := range keysToDel {
+ store.Delete(key)
+ }
+}
+
+// IsDenylistEmpty returns `true` if no validator is denylisted on chain `chainID`
+func (k Keeper) IsDenylistEmpty(ctx sdk.Context, chainID string) bool {
+ store := ctx.KVStore(k.storeKey)
+ iterator := sdk.KVStorePrefixIterator(store, types.ChainIdWithLenKey(types.DenylistPrefix, chainID))
+ defer iterator.Close()
+
+ if iterator.Valid() {
+ return false
+ }
+
+ return true
+}
diff --git a/x/ccv/provider/keeper/keeper_test.go b/x/ccv/provider/keeper/keeper_test.go
index 9c9d421fd9..a66b7e3826 100644
--- a/x/ccv/provider/keeper/keeper_test.go
+++ b/x/ccv/provider/keeper/keeper_test.go
@@ -1,6 +1,7 @@
package keeper_test
import (
+ "bytes"
"fmt"
"sort"
"testing"
@@ -10,14 +11,15 @@ import (
"github.com/stretchr/testify/require"
cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec"
+ sdk "github.com/cosmos/cosmos-sdk/types"
abci "github.com/cometbft/cometbft/abci/types"
tmprotocrypto "github.com/cometbft/cometbft/proto/tendermint/crypto"
- cryptotestutil "github.com/cosmos/interchain-security/v4/testutil/crypto"
- testkeeper "github.com/cosmos/interchain-security/v4/testutil/keeper"
- "github.com/cosmos/interchain-security/v4/x/ccv/provider/types"
- ccv "github.com/cosmos/interchain-security/v4/x/ccv/types"
+ cryptotestutil "github.com/cosmos/interchain-security/v5/testutil/crypto"
+ testkeeper "github.com/cosmos/interchain-security/v5/testutil/keeper"
+ "github.com/cosmos/interchain-security/v5/x/ccv/provider/types"
+ ccv "github.com/cosmos/interchain-security/v5/x/ccv/types"
)
const consumer = "consumer"
@@ -400,8 +402,10 @@ func TestGetAllConsumerChains(t *testing.T) {
expectedGetAllOrder := []types.Chain{}
for i, chainID := range chainIDs {
clientID := fmt.Sprintf("client-%d", len(chainIDs)-i)
+ topN := uint32(i)
pk.SetConsumerClientId(ctx, chainID, clientID)
- expectedGetAllOrder = append(expectedGetAllOrder, types.Chain{ChainId: chainID, ClientId: clientID})
+ pk.SetTopN(ctx, chainID, topN)
+ expectedGetAllOrder = append(expectedGetAllOrder, types.Chain{ChainId: chainID, ClientId: clientID, Top_N: topN})
}
// sorting by chainID
sort.Slice(expectedGetAllOrder, func(i, j int) bool {
@@ -550,7 +554,7 @@ func TestSetProposedConsumerChains(t *testing.T) {
for _, test := range tests {
providerKeeper.SetProposedConsumerChain(ctx, test.chainID, test.proposalID)
- cID := providerKeeper.GetProposedConsumerChain(ctx, test.proposalID)
+ cID, _ := providerKeeper.GetProposedConsumerChain(ctx, test.proposalID)
require.Equal(t, cID, test.chainID)
}
}
@@ -572,9 +576,9 @@ func TestDeleteProposedConsumerChainInStore(t *testing.T) {
for _, test := range tests {
providerKeeper.SetProposedConsumerChain(ctx, test.chainID, test.proposalID)
providerKeeper.DeleteProposedConsumerChainInStore(ctx, test.deleteProposalID)
- cID := providerKeeper.GetProposedConsumerChain(ctx, test.proposalID)
+ cID, found := providerKeeper.GetProposedConsumerChain(ctx, test.proposalID)
if test.ok {
- require.Equal(t, cID, "")
+ require.False(t, found)
} else {
require.Equal(t, cID, test.chainID)
}
@@ -628,3 +632,208 @@ func TestGetAllProposedConsumerChainIDs(t *testing.T) {
}
}
}
+
+// TestTopN tests the `SetTopN`, `GetTopN`, `IsTopN`, and `IsOptIn` methods
+func TestTopN(t *testing.T) {
+ providerKeeper, ctx, ctrl, _ := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t))
+ defer ctrl.Finish()
+
+ tests := []struct {
+ chainID string
+ N uint32
+ isOptIn bool
+ }{
+ {chainID: "TopNChain1", N: 50, isOptIn: false},
+ {chainID: "TopNChain2", N: 100, isOptIn: false},
+ {chainID: "OptInChain", N: 0, isOptIn: true},
+ }
+
+ for _, test := range tests {
+ providerKeeper.SetTopN(ctx, test.chainID, test.N)
+ topN, found := providerKeeper.GetTopN(ctx, test.chainID)
+ require.Equal(t, test.N, topN)
+ require.True(t, found)
+
+ if test.isOptIn {
+ require.True(t, providerKeeper.IsOptIn(ctx, test.chainID))
+ require.False(t, providerKeeper.IsTopN(ctx, test.chainID))
+ } else {
+ require.False(t, providerKeeper.IsOptIn(ctx, test.chainID))
+ require.True(t, providerKeeper.IsTopN(ctx, test.chainID))
+ }
+ }
+}
+
+func TestGetAllOptedIn(t *testing.T) {
+ providerKeeper, ctx, ctrl, _ := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t))
+ defer ctrl.Finish()
+
+ expectedOptedInValidators := []types.ProviderConsAddress{
+ types.NewProviderConsAddress([]byte("providerAddr1")),
+ types.NewProviderConsAddress([]byte("providerAddr2")),
+ types.NewProviderConsAddress([]byte("providerAddr3")),
+ }
+
+ for _, expectedOptedInValidator := range expectedOptedInValidators {
+ providerKeeper.SetOptedIn(ctx, "chainID", expectedOptedInValidator)
+ }
+
+ actualOptedInValidators := providerKeeper.GetAllOptedIn(ctx, "chainID")
+
+ // sort validators first to be able to compare
+ sortOptedInValidators := func(addresses []types.ProviderConsAddress) {
+ sort.Slice(addresses, func(i, j int) bool {
+ return bytes.Compare(addresses[i].ToSdkConsAddr(), addresses[j].ToSdkConsAddr()) < 0
+ })
+ }
+ sortOptedInValidators(expectedOptedInValidators)
+ sortOptedInValidators(actualOptedInValidators)
+ require.Equal(t, expectedOptedInValidators, actualOptedInValidators)
+}
+
+// TestOptedIn tests the `SetOptedIn`, `IsOptedIn`, `DeleteOptedIn` and `DeleteAllOptedIn` methods
+func TestOptedIn(t *testing.T) {
+ providerKeeper, ctx, ctrl, _ := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t))
+ defer ctrl.Finish()
+
+ optedInValidator1 := types.NewProviderConsAddress([]byte("providerAddr1"))
+ optedInValidator2 := types.NewProviderConsAddress([]byte("providerAddr2"))
+
+ require.False(t, providerKeeper.IsOptedIn(ctx, "chainID", optedInValidator1))
+ providerKeeper.SetOptedIn(ctx, "chainID", optedInValidator1)
+ require.True(t, providerKeeper.IsOptedIn(ctx, "chainID", optedInValidator1))
+ providerKeeper.DeleteOptedIn(ctx, "chainID", optedInValidator1)
+ require.False(t, providerKeeper.IsOptedIn(ctx, "chainID", optedInValidator1))
+
+ providerKeeper.SetOptedIn(ctx, "chainID", optedInValidator1)
+ providerKeeper.SetOptedIn(ctx, "chainID", optedInValidator2)
+ require.True(t, providerKeeper.IsOptedIn(ctx, "chainID", optedInValidator1))
+ require.True(t, providerKeeper.IsOptedIn(ctx, "chainID", optedInValidator2))
+ providerKeeper.DeleteAllOptedIn(ctx, "chainID")
+ require.False(t, providerKeeper.IsOptedIn(ctx, "chainID", optedInValidator1))
+ require.False(t, providerKeeper.IsOptedIn(ctx, "chainID", optedInValidator2))
+}
+
+// TestConsumerCommissionRate tests the `SetConsumerCommissionRate`, `GetConsumerCommissionRate`, and `DeleteConsumerCommissionRate` methods
+func TestConsumerCommissionRate(t *testing.T) {
+ providerKeeper, ctx, ctrl, _ := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t))
+ defer ctrl.Finish()
+
+ providerAddr1 := types.NewProviderConsAddress([]byte("providerAddr1"))
+ providerAddr2 := types.NewProviderConsAddress([]byte("providerAddr2"))
+
+ cr, found := providerKeeper.GetConsumerCommissionRate(ctx, "chainID", providerAddr1)
+ require.False(t, found)
+ require.Equal(t, sdk.ZeroDec(), cr)
+
+ providerKeeper.SetConsumerCommissionRate(ctx, "chainID", providerAddr1, sdk.OneDec())
+ cr, found = providerKeeper.GetConsumerCommissionRate(ctx, "chainID", providerAddr1)
+ require.True(t, found)
+ require.Equal(t, sdk.OneDec(), cr)
+
+ providerKeeper.SetConsumerCommissionRate(ctx, "chainID", providerAddr2, sdk.ZeroDec())
+ cr, found = providerKeeper.GetConsumerCommissionRate(ctx, "chainID", providerAddr2)
+ require.True(t, found)
+ require.Equal(t, sdk.ZeroDec(), cr)
+
+ provAddrs := providerKeeper.GetAllCommissionRateValidators(ctx, "chainID")
+ require.Len(t, provAddrs, 2)
+
+ for _, addr := range provAddrs {
+ providerKeeper.DeleteConsumerCommissionRate(ctx, "chainID", addr)
+ }
+
+ _, found = providerKeeper.GetConsumerCommissionRate(ctx, "chainID", providerAddr1)
+ require.False(t, found)
+
+ _, found = providerKeeper.GetConsumerCommissionRate(ctx, "chainID", providerAddr2)
+ require.False(t, found)
+}
+
+// TestValidatorsPowerCap tests the `SetValidatorsPowerCap`, `GetValidatorsPowerCap`, and `DeleteValidatorsPowerCap` methods
+func TestValidatorsPowerCap(t *testing.T) {
+ providerKeeper, ctx, ctrl, _ := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t))
+ defer ctrl.Finish()
+
+ expectedPowerCap := uint32(10)
+ providerKeeper.SetValidatorsPowerCap(ctx, "chainID", expectedPowerCap)
+ powerCap, found := providerKeeper.GetValidatorsPowerCap(ctx, "chainID")
+ require.Equal(t, expectedPowerCap, powerCap)
+ require.True(t, found)
+
+ providerKeeper.DeleteValidatorsPowerCap(ctx, "chainID")
+ _, found = providerKeeper.GetValidatorsPowerCap(ctx, "chainID")
+ require.False(t, found)
+}
+
+// TestValidatorSetCap tests the `SetValidatorSetCap`, `GetValidatorSetCap`, and `DeleteValidatorSetCap` methods
+func TestValidatorSetCap(t *testing.T) {
+ providerKeeper, ctx, ctrl, _ := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t))
+ defer ctrl.Finish()
+
+ expectedPowerCap := uint32(10)
+ providerKeeper.SetValidatorSetCap(ctx, "chainID", expectedPowerCap)
+ powerCap, found := providerKeeper.GetValidatorSetCap(ctx, "chainID")
+ require.Equal(t, expectedPowerCap, powerCap)
+ require.True(t, found)
+
+ providerKeeper.DeleteValidatorSetCap(ctx, "chainID")
+ _, found = providerKeeper.GetValidatorSetCap(ctx, "chainID")
+ require.False(t, found)
+}
+
+// TestAllowlist tests the `SetAllowlist`, `IsAllowlisted`, `DeleteAllowlist`, and `IsAllowlistEmpty` methods
+func TestAllowlist(t *testing.T) {
+ providerKeeper, ctx, ctrl, _ := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t))
+ defer ctrl.Finish()
+
+ chainID := "chainID"
+
+ // no validator was allowlisted and hence the allowlist is empty
+ require.True(t, providerKeeper.IsAllowlistEmpty(ctx, chainID))
+
+ providerAddr1 := types.NewProviderConsAddress([]byte("providerAddr1"))
+ providerKeeper.SetAllowlist(ctx, chainID, providerAddr1)
+ require.True(t, providerKeeper.IsAllowlisted(ctx, chainID, providerAddr1))
+
+ // allowlist is not empty anymore
+ require.False(t, providerKeeper.IsAllowlistEmpty(ctx, chainID))
+
+ providerAddr2 := types.NewProviderConsAddress([]byte("providerAddr2"))
+ providerKeeper.SetAllowlist(ctx, chainID, providerAddr2)
+ require.True(t, providerKeeper.IsAllowlisted(ctx, chainID, providerAddr2))
+ require.False(t, providerKeeper.IsAllowlistEmpty(ctx, chainID))
+
+ providerKeeper.DeleteAllowlist(ctx, chainID)
+ require.False(t, providerKeeper.IsAllowlisted(ctx, chainID, providerAddr1))
+ require.False(t, providerKeeper.IsAllowlisted(ctx, chainID, providerAddr2))
+ require.True(t, providerKeeper.IsAllowlistEmpty(ctx, chainID))
+}
+
+// TestDenylist tests the `SetDenylist`, `IsDenylisted`, `DeleteDenylist`, and `IsDenylistEmpty` methods
+func TestDenylist(t *testing.T) {
+ providerKeeper, ctx, ctrl, _ := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t))
+ defer ctrl.Finish()
+
+ chainID := "chainID"
+
+ // no validator was denylisted and hence the denylist is empty
+ require.True(t, providerKeeper.IsDenylistEmpty(ctx, chainID))
+
+ providerAddr1 := types.NewProviderConsAddress([]byte("providerAddr1"))
+ providerKeeper.SetDenylist(ctx, chainID, providerAddr1)
+ require.True(t, providerKeeper.IsDenylisted(ctx, chainID, providerAddr1))
+
+ // denylist is not empty anymore
+ require.False(t, providerKeeper.IsDenylistEmpty(ctx, chainID))
+
+ providerAddr2 := types.NewProviderConsAddress([]byte("providerAddr2"))
+ providerKeeper.SetDenylist(ctx, chainID, providerAddr2)
+ require.True(t, providerKeeper.IsDenylisted(ctx, chainID, providerAddr2))
+ require.False(t, providerKeeper.IsDenylistEmpty(ctx, chainID))
+
+ providerKeeper.DeleteDenylist(ctx, chainID)
+ require.False(t, providerKeeper.IsDenylisted(ctx, chainID, providerAddr1))
+ require.False(t, providerKeeper.IsDenylisted(ctx, chainID, providerAddr2))
+ require.True(t, providerKeeper.IsDenylistEmpty(ctx, chainID))
+}
diff --git a/x/ccv/provider/keeper/key_assignment.go b/x/ccv/provider/keeper/key_assignment.go
index 89dbcfda4e..cb359620b9 100644
--- a/x/ccv/provider/keeper/key_assignment.go
+++ b/x/ccv/provider/keeper/key_assignment.go
@@ -1,6 +1,7 @@
package keeper
import (
+ "encoding/base64"
"fmt"
errorsmod "cosmossdk.io/errors"
@@ -10,10 +11,57 @@ import (
tmprotocrypto "github.com/cometbft/cometbft/proto/tendermint/crypto"
- "github.com/cosmos/interchain-security/v4/x/ccv/provider/types"
- ccvtypes "github.com/cosmos/interchain-security/v4/x/ccv/types"
+ "github.com/cosmos/interchain-security/v5/x/ccv/provider/types"
+ ccvtypes "github.com/cosmos/interchain-security/v5/x/ccv/types"
)
+// ParseConsumerKey parses the ED25519 PubKey`consumerKey` from a JSON string
+// and constructs its corresponding `tmprotocrypto.PublicKey`
+func (k Keeper) ParseConsumerKey(consumerKey string) (tmprotocrypto.PublicKey, error) {
+ // parse consumer key as long as it's in the right format
+ pkType, keyStr, err := types.ParseConsumerKeyFromJson(consumerKey)
+ if err != nil {
+ return tmprotocrypto.PublicKey{}, err
+ }
+
+ // Note: the correct way to decide if a key type is supported is to check the
+ // consensus params. However this functionality was disabled in https://github.com/cosmos/interchain-security/pull/916
+ // as a quick way to get ed25519 working, avoiding amino/proto-any marshalling issues.
+
+ // make sure the consumer key type is supported
+ // cp := ctx.ConsensusParams()
+ // if cp != nil && cp.Validator != nil {
+ // if !tmstrings.StringInSlice(pkType, cp.Validator.PubKeyTypes) {
+ // return nil, errorsmod.Wrapf(
+ // stakingtypes.ErrValidatorPubKeyTypeNotSupported,
+ // "got: %s, expected one of: %s", pkType, cp.Validator.PubKeyTypes,
+ // )
+ // }
+ // }
+
+ // For now, only accept ed25519.
+ // TODO: decide what types should be supported.
+ if pkType != "/cosmos.crypto.ed25519.PubKey" {
+ return tmprotocrypto.PublicKey{}, errorsmod.Wrapf(
+ stakingtypes.ErrValidatorPubKeyTypeNotSupported,
+ "got: %s, expected: %s", pkType, "/cosmos.crypto.ed25519.PubKey",
+ )
+ }
+
+ pubKeyBytes, err := base64.StdEncoding.DecodeString(keyStr)
+ if err != nil {
+ return tmprotocrypto.PublicKey{}, err
+ }
+
+ consumerTMPublicKey := tmprotocrypto.PublicKey{
+ Sum: &tmprotocrypto.PublicKey_Ed25519{
+ Ed25519: pubKeyBytes,
+ },
+ }
+
+ return consumerTMPublicKey, nil
+}
+
// GetValidatorConsumerPubKey returns a validator's public key assigned for a consumer chain
func (k Keeper) GetValidatorConsumerPubKey(
ctx sdk.Context,
@@ -323,12 +371,24 @@ func (k Keeper) AssignConsumerKey(
}
}
- if _, found := k.GetValidatorByConsumerAddr(ctx, chainID, consumerAddr); found {
+ if existingProviderAddr, found := k.GetValidatorByConsumerAddr(ctx, chainID, consumerAddr); found {
// consumer key is already in use
- // prevent multiple validators from assigning the same key
- return errorsmod.Wrapf(
- types.ErrConsumerKeyInUse, "a validator has assigned the consumer key already",
- )
+ if providerAddr.Address.Equals(existingProviderAddr.Address) {
+ // the validator itself is the one already using the consumer key,
+ // just do a noop
+ k.Logger(ctx).Info("tried to assign a consumer key that is already assigned to the validator",
+ "consumer chainID", chainID,
+ "validator", providerAddr.String(),
+ "consumer consensus addr", consumerAddr.String(),
+ )
+ return nil
+ } else {
+ // the validators are different -> throw an error to
+ // prevent multiple validators from assigning the same key
+ return errorsmod.Wrapf(
+ types.ErrConsumerKeyInUse, "a validator has assigned the consumer key already",
+ )
+ }
}
// get the previous key assigned for this validator on this consumer chain
diff --git a/x/ccv/provider/keeper/key_assignment_test.go b/x/ccv/provider/keeper/key_assignment_test.go
index 46aefb1bbf..e721b39c33 100644
--- a/x/ccv/provider/keeper/key_assignment_test.go
+++ b/x/ccv/provider/keeper/key_assignment_test.go
@@ -17,11 +17,11 @@ import (
abci "github.com/cometbft/cometbft/abci/types"
tmprotocrypto "github.com/cometbft/cometbft/proto/tendermint/crypto"
- cryptotestutil "github.com/cosmos/interchain-security/v4/testutil/crypto"
- testkeeper "github.com/cosmos/interchain-security/v4/testutil/keeper"
- providerkeeper "github.com/cosmos/interchain-security/v4/x/ccv/provider/keeper"
- "github.com/cosmos/interchain-security/v4/x/ccv/provider/types"
- ccvtypes "github.com/cosmos/interchain-security/v4/x/ccv/types"
+ cryptotestutil "github.com/cosmos/interchain-security/v5/testutil/crypto"
+ testkeeper "github.com/cosmos/interchain-security/v5/testutil/keeper"
+ providerkeeper "github.com/cosmos/interchain-security/v5/x/ccv/provider/keeper"
+ "github.com/cosmos/interchain-security/v5/x/ccv/provider/types"
+ ccvtypes "github.com/cosmos/interchain-security/v5/x/ccv/types"
)
const ChainID = "chainID"
@@ -768,7 +768,10 @@ func TestSimulatedAssignmentsAndUpdateApplication(t *testing.T) {
})
}
- nextValidators := k.ComputeNextEpochConsumerValSet(ctx, CHAINID, bondedValidators)
+ nextValidators := k.FilterValidators(ctx, CHAINID, bondedValidators,
+ func(providerAddr types.ProviderConsAddress) bool {
+ return true
+ })
updates = providerkeeper.DiffValidators(k.GetConsumerValSet(ctx, CHAINID), nextValidators)
k.SetConsumerValSet(ctx, CHAINID, nextValidators)
diff --git a/x/ccv/provider/keeper/msg_server.go b/x/ccv/provider/keeper/msg_server.go
index 9a27d1d144..ee17fd8228 100644
--- a/x/ccv/provider/keeper/msg_server.go
+++ b/x/ccv/provider/keeper/msg_server.go
@@ -2,7 +2,6 @@ package keeper
import (
"context"
- "encoding/base64"
errorsmod "cosmossdk.io/errors"
@@ -10,11 +9,10 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
- tmprotocrypto "github.com/cometbft/cometbft/proto/tendermint/crypto"
tmtypes "github.com/cometbft/cometbft/types"
- "github.com/cosmos/interchain-security/v4/x/ccv/provider/types"
- ccvtypes "github.com/cosmos/interchain-security/v4/x/ccv/types"
+ "github.com/cosmos/interchain-security/v5/x/ccv/provider/types"
+ ccvtypes "github.com/cosmos/interchain-security/v5/x/ccv/types"
)
type msgServer struct {
@@ -45,47 +43,11 @@ func (k msgServer) AssignConsumerKey(goCtx context.Context, msg *types.MsgAssign
return nil, stakingtypes.ErrNoValidatorFound
}
- // parse consumer key as long as it's in the right format
- pkType, keyStr, err := types.ParseConsumerKeyFromJson(msg.ConsumerKey)
+ consumerTMPublicKey, err := k.ParseConsumerKey(msg.ConsumerKey)
if err != nil {
return nil, err
}
- // Note: the correct way to decide if a key type is supported is to check the
- // consensus params. However this functionality was disabled in https://github.com/cosmos/interchain-security/pull/916
- // as a quick way to get ed25519 working, avoiding amino/proto-any marshalling issues.
-
- // make sure the consumer key type is supported
- // cp := ctx.ConsensusParams()
- // if cp != nil && cp.Validator != nil {
- // if !tmstrings.StringInSlice(pkType, cp.Validator.PubKeyTypes) {
- // return nil, errorsmod.Wrapf(
- // stakingtypes.ErrValidatorPubKeyTypeNotSupported,
- // "got: %s, expected one of: %s", pkType, cp.Validator.PubKeyTypes,
- // )
- // }
- // }
-
- // For now, only accept ed25519.
- // TODO: decide what types should be supported.
- if pkType != "/cosmos.crypto.ed25519.PubKey" {
- return nil, errorsmod.Wrapf(
- stakingtypes.ErrValidatorPubKeyTypeNotSupported,
- "got: %s, expected: %s", pkType, "/cosmos.crypto.ed25519.PubKey",
- )
- }
-
- pubKeyBytes, err := base64.StdEncoding.DecodeString(keyStr)
- if err != nil {
- return nil, err
- }
-
- consumerTMPublicKey := tmprotocrypto.PublicKey{
- Sum: &tmprotocrypto.PublicKey_Ed25519{
- Ed25519: pubKeyBytes,
- },
- }
-
if err := k.Keeper.AssignConsumerKey(ctx, msg.ChainId, validator, consumerTMPublicKey); err != nil {
return nil, err
}
@@ -174,3 +136,114 @@ func (k msgServer) SubmitConsumerDoubleVoting(goCtx context.Context, msg *types.
return &types.MsgSubmitConsumerDoubleVotingResponse{}, nil
}
+
+func (k msgServer) OptIn(goCtx context.Context, msg *types.MsgOptIn) (*types.MsgOptInResponse, error) {
+ ctx := sdk.UnwrapSDKContext(goCtx)
+
+ valAddress, err := sdk.ValAddressFromBech32(msg.ProviderAddr)
+ if err != nil {
+ return nil, err
+ }
+
+ // validator must already be registered
+ validator, found := k.stakingKeeper.GetValidator(ctx, valAddress)
+ if !found {
+ return nil, stakingtypes.ErrNoValidatorFound
+ }
+
+ consAddrTmp, err := validator.GetConsAddr()
+ if err != nil {
+ return nil, err
+ }
+ providerConsAddr := types.NewProviderConsAddress(consAddrTmp)
+
+ if msg.ConsumerKey != "" {
+ err = k.Keeper.HandleOptIn(ctx, msg.ChainId, providerConsAddr, &msg.ConsumerKey)
+ } else {
+ err = k.Keeper.HandleOptIn(ctx, msg.ChainId, providerConsAddr, nil)
+ }
+
+ if err != nil {
+ return nil, err
+ }
+
+ ctx.EventManager().EmitEvents(sdk.Events{
+ sdk.NewEvent(
+ types.EventTypeOptIn,
+ sdk.NewAttribute(types.AttributeProviderValidatorAddress, msg.ProviderAddr),
+ sdk.NewAttribute(types.AttributeConsumerConsensusPubKey, msg.ConsumerKey),
+ ),
+ })
+
+ return &types.MsgOptInResponse{}, nil
+}
+
+func (k msgServer) OptOut(goCtx context.Context, msg *types.MsgOptOut) (*types.MsgOptOutResponse, error) {
+ ctx := sdk.UnwrapSDKContext(goCtx)
+
+ valAddress, err := sdk.ValAddressFromBech32(msg.ProviderAddr)
+ if err != nil {
+ return nil, err
+ }
+
+ // validator must already be registered
+ validator, found := k.stakingKeeper.GetValidator(ctx, valAddress)
+ if !found {
+ return nil, stakingtypes.ErrNoValidatorFound
+ }
+
+ consAddrTmp, err := validator.GetConsAddr()
+ if err != nil {
+ return nil, err
+ }
+ providerConsAddr := types.NewProviderConsAddress(consAddrTmp)
+
+ err = k.Keeper.HandleOptOut(ctx, msg.ChainId, providerConsAddr)
+ if err != nil {
+ return nil, err
+ }
+
+ ctx.EventManager().EmitEvents(sdk.Events{
+ sdk.NewEvent(
+ types.EventTypeOptOut,
+ sdk.NewAttribute(types.AttributeProviderValidatorAddress, msg.ProviderAddr),
+ ),
+ })
+
+ return &types.MsgOptOutResponse{}, nil
+}
+
+func (k msgServer) SetConsumerCommissionRate(goCtx context.Context, msg *types.MsgSetConsumerCommissionRate) (*types.MsgSetConsumerCommissionRateResponse, error) {
+ ctx := sdk.UnwrapSDKContext(goCtx)
+
+ providerValidatorAddr, err := sdk.ValAddressFromBech32(msg.ProviderAddr)
+ if err != nil {
+ return nil, err
+ }
+
+ // validator must already be registered
+ validator, found := k.stakingKeeper.GetValidator(ctx, providerValidatorAddr)
+ if !found {
+ return nil, stakingtypes.ErrNoValidatorFound
+ }
+
+ consAddr, err := validator.GetConsAddr()
+ if err != nil {
+ return nil, err
+ }
+
+ if err := k.HandleSetConsumerCommissionRate(ctx, msg.ChainId, types.NewProviderConsAddress(consAddr), msg.Rate); err != nil {
+ return nil, err
+ }
+
+ ctx.EventManager().EmitEvents(sdk.Events{
+ sdk.NewEvent(
+ types.EventTypeSetConsumerCommissionRate,
+ sdk.NewAttribute(types.AttributeConsumerChainID, msg.ChainId),
+ sdk.NewAttribute(types.AttributeProviderValidatorAddress, msg.ProviderAddr),
+ sdk.NewAttribute(types.AttributeConsumerCommissionRate, msg.Rate.String()),
+ ),
+ })
+
+ return &types.MsgSetConsumerCommissionRateResponse{}, nil
+}
diff --git a/x/ccv/provider/keeper/params.go b/x/ccv/provider/keeper/params.go
index f74baf656e..3834358b0b 100644
--- a/x/ccv/provider/keeper/params.go
+++ b/x/ccv/provider/keeper/params.go
@@ -7,8 +7,8 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
- "github.com/cosmos/interchain-security/v4/x/ccv/provider/types"
- ccvtypes "github.com/cosmos/interchain-security/v4/x/ccv/types"
+ "github.com/cosmos/interchain-security/v5/x/ccv/provider/types"
+ ccvtypes "github.com/cosmos/interchain-security/v5/x/ccv/types"
)
// GetTemplateClient returns the template client for provider proposals
diff --git a/x/ccv/provider/keeper/params_test.go b/x/ccv/provider/keeper/params_test.go
index 88175431c0..ccbd8629d6 100644
--- a/x/ccv/provider/keeper/params_test.go
+++ b/x/ccv/provider/keeper/params_test.go
@@ -11,8 +11,8 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
- testkeeper "github.com/cosmos/interchain-security/v4/testutil/keeper"
- providertypes "github.com/cosmos/interchain-security/v4/x/ccv/provider/types"
+ testkeeper "github.com/cosmos/interchain-security/v5/testutil/keeper"
+ providertypes "github.com/cosmos/interchain-security/v5/x/ccv/provider/types"
)
// TestParams tests the getting/setting of provider ccv module params.
diff --git a/x/ccv/provider/keeper/partial_set_security.go b/x/ccv/provider/keeper/partial_set_security.go
new file mode 100644
index 0000000000..9020a3db82
--- /dev/null
+++ b/x/ccv/provider/keeper/partial_set_security.go
@@ -0,0 +1,295 @@
+package keeper
+
+import (
+ "fmt"
+ "sort"
+
+ errorsmod "cosmossdk.io/errors"
+
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
+
+ "github.com/cosmos/interchain-security/v5/x/ccv/provider/types"
+)
+
+// HandleOptIn prepares validator `providerAddr` to opt in to `chainID` with an optional `consumerKey` consumer public key.
+// Note that the validator only opts in at the end of an epoch.
+func (k Keeper) HandleOptIn(ctx sdk.Context, chainID string, providerAddr types.ProviderConsAddress, consumerKey *string) error {
+ if !k.IsConsumerProposedOrRegistered(ctx, chainID) {
+ return errorsmod.Wrapf(
+ types.ErrUnknownConsumerChainId,
+ "opting in to an unknown consumer chain, with id: %s", chainID)
+ }
+
+ k.SetOptedIn(ctx, chainID, providerAddr)
+
+ if consumerKey != nil {
+ consumerTMPublicKey, err := k.ParseConsumerKey(*consumerKey)
+ if err != nil {
+ return err
+ }
+
+ validator, found := k.stakingKeeper.GetValidatorByConsAddr(ctx, providerAddr.Address)
+ if !found {
+ return stakingtypes.ErrNoValidatorFound
+ }
+
+ err = k.AssignConsumerKey(ctx, chainID, validator, consumerTMPublicKey)
+ if err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
+// HandleOptOut prepares validator `providerAddr` to opt out from running `chainID`.
+// Note that the validator only opts out at the end of an epoch.
+func (k Keeper) HandleOptOut(ctx sdk.Context, chainID string, providerAddr types.ProviderConsAddress) error {
+ if _, found := k.GetConsumerClientId(ctx, chainID); !found {
+ // A validator can only opt out from a running chain. We check this by checking the consumer client id, because
+ // `SetConsumerClientId` is set when the chain starts in `CreateConsumerClientInCachedCtx` of `BeginBlockInit`.
+ return errorsmod.Wrapf(
+ types.ErrUnknownConsumerChainId,
+ "opting out of an unknown or not running consumer chain, with id: %s", chainID)
+ }
+
+ if topN, found := k.GetTopN(ctx, chainID); found && topN > 0 {
+ // a validator cannot opt out from a Top N chain if the validator is in the Top N validators
+ validator, validatorFound := k.stakingKeeper.GetValidatorByConsAddr(ctx, providerAddr.ToSdkConsAddr())
+ if !validatorFound {
+ return errorsmod.Wrapf(
+ stakingtypes.ErrNoValidatorFound,
+ "validator with consensus address %s could not be found", providerAddr.ToSdkConsAddr())
+ }
+ power := k.stakingKeeper.GetLastValidatorPower(ctx, validator.GetOperator())
+ minPowerToOptIn, err := k.ComputeMinPowerToOptIn(ctx, chainID, k.stakingKeeper.GetLastValidators(ctx), topN)
+
+ if err != nil || power >= minPowerToOptIn {
+ return errorsmod.Wrapf(
+ types.ErrCannotOptOutFromTopN,
+ "validator with power (%d) cannot opt out from Top N chain because all validators"+
+ "with at least %d power have to validate", power, minPowerToOptIn)
+ }
+ }
+
+ k.DeleteOptedIn(ctx, chainID, providerAddr)
+ return nil
+}
+
+// OptInTopNValidators opts in to `chainID` all the `bondedValidators` that have at least `minPowerToOptIn` power
+func (k Keeper) OptInTopNValidators(ctx sdk.Context, chainID string, bondedValidators []stakingtypes.Validator, minPowerToOptIn int64) {
+ for _, val := range bondedValidators {
+ power := k.stakingKeeper.GetLastValidatorPower(ctx, val.GetOperator())
+ if power >= minPowerToOptIn {
+ consAddr, err := val.GetConsAddr()
+ if err != nil {
+ k.Logger(ctx).Error("could not retrieve validators consensus address",
+ "validator", val,
+ "error", err)
+ continue
+ }
+
+ // if validator already exists it gets overwritten
+ k.SetOptedIn(ctx, chainID, types.NewProviderConsAddress(consAddr))
+ } // else validators that do not belong to the top N validators but were opted in, remain opted in
+ }
+}
+
+// ComputeMinPowerToOptIn returns the minimum power needed for a validator (from the bonded validators)
+// to belong to the `topN` validators. `chainID` is only used for logging purposes.
+func (k Keeper) ComputeMinPowerToOptIn(ctx sdk.Context, chainID string, bondedValidators []stakingtypes.Validator, topN uint32) (int64, error) {
+ if topN == 0 || topN > 100 {
+ return 0, fmt.Errorf("trying to compute minimum power with an incorrect topN value (%d)."+
+ "topN has to be between (0, 100]", topN)
+ }
+
+ totalPower := sdk.ZeroDec()
+ var powers []int64
+
+ for _, val := range bondedValidators {
+ power := k.stakingKeeper.GetLastValidatorPower(ctx, val.GetOperator())
+ powers = append(powers, power)
+ totalPower = totalPower.Add(sdk.NewDecFromInt(sdk.NewInt(power)))
+ }
+
+ // sort by powers descending
+ sort.Slice(powers, func(i, j int) bool {
+ return powers[i] > powers[j]
+ })
+
+ topNThreshold := sdk.NewDecFromInt(sdk.NewInt(int64(topN))).QuoInt64(int64(100))
+ powerSum := sdk.ZeroDec()
+ for _, power := range powers {
+ powerSum = powerSum.Add(sdk.NewDecFromInt(sdk.NewInt(power)))
+ if powerSum.Quo(totalPower).GTE(topNThreshold) {
+ return power, nil
+ }
+ }
+
+ // We should never reach this point because the topN can be up to 1.0 (100%) and in the above `for` loop we
+ // perform an equal comparison as well (`GTE`).
+ return 0, fmt.Errorf("should never reach this point with topN (%d), totalPower (%d), and powerSum (%d)", topN, totalPower, powerSum)
+}
+
+// CapValidatorSet caps the provided `validators` if chain `chainID` is an Opt In chain with a validator-set cap. If cap
+// is `k`, `CapValidatorSet` returns the first `k` validators from `validators` with the highest power.
+func (k Keeper) CapValidatorSet(ctx sdk.Context, chainID string, validators []types.ConsumerValidator) []types.ConsumerValidator {
+ if topN, found := k.GetTopN(ctx, chainID); found && topN > 0 {
+ // is a no-op if the chain is a Top N chain
+ return validators
+ }
+
+ if validatorSetCap, found := k.GetValidatorSetCap(ctx, chainID); found && validatorSetCap != 0 {
+ sort.Slice(validators, func(i, j int) bool {
+ return validators[i].Power > validators[j].Power
+ })
+
+ minNumberOfValidators := 0
+ if len(validators) < int(validatorSetCap) {
+ minNumberOfValidators = len(validators)
+ } else {
+ minNumberOfValidators = int(validatorSetCap)
+ }
+ return validators[:minNumberOfValidators]
+ } else {
+ return validators
+ }
+}
+
+// CapValidatorsPower caps the power of the validators on chain `chainID` and returns an updated slice of validators
+// with their new powers. Works on a best-basis effort because there are cases where we cannot guarantee that all validators
+// on the consumer chain have less power than the set validators-power cap. For example, if we have 10 validators and
+// the power cap is set to 5%, we need at least one validator to have more than 10% of the voting power on the consumer chain.
+func (k Keeper) CapValidatorsPower(ctx sdk.Context, chainID string, validators []types.ConsumerValidator) []types.ConsumerValidator {
+ if p, found := k.GetValidatorsPowerCap(ctx, chainID); found && p > 0 {
+ return NoMoreThanPercentOfTheSum(validators, p)
+ } else {
+ // is a no-op if power cap is not set for `chainID`
+ return validators
+ }
+}
+
+// sum is a helper function to sum all the validators' power
+func sum(validators []types.ConsumerValidator) int64 {
+ s := int64(0)
+ for _, v := range validators {
+ s = s + v.Power
+ }
+ return s
+}
+
+// NoMoreThanPercentOfTheSum returns a set of validators with updated powers such that no validator has more than the
+// provided `percent` of the sum of all validators' powers. Operates on a best-effort basis.
+func NoMoreThanPercentOfTheSum(validators []types.ConsumerValidator, percent uint32) []types.ConsumerValidator {
+ // Algorithm's idea
+ // ----------------
+ // Consider the validators' powers to be `a_1, a_2, ... a_n` and `p` to be the percent in [1, 100]. Now, consider
+ // the sum `s = a_1 + a_2 + ... + a_n`. Then `maxPower = s * p / 100 <=> 100 * maxPower = s * p`.
+ // The problem of capping the validators' powers to be no more than `p` has no solution if `(100 / n) > p`. For example,
+ // for n = 10 and p = 5 we do not have a solution. We would need at least one validator with power greater than 10%
+ // for a solution to exist.
+ // So, if `(100 / n) > p` there's no solution. We know that `100 * maxPower = s * p` and so `(100 / n) > (100 * maxPower) / s`
+ // `100 * s > 100 * maxPower * n <=> s > maxPower * n`. Thus, we do not have a solution if `s > n * maxPower`.
+
+ // If `s <= n * maxPower` the idea of the algorithm is rather simple.
+ // - Compute the `maxPower` a validator must have so that it does not have more than `percent` of the voting power.
+ // - If a validator `v` has power `p`, then:
+ // - if `p > maxPower` we set `v`'s power to `maxPower` and distribute the `p - maxPower` to validators that
+ // have less than `maxPower` power. This way, the total sum remains the same and no validator has more than
+ // `maxPower` and so the power capping is satisfied.
+ // - Note that in order to avoid setting multiple validators to `maxPower`, we first compute all the `remainingPower`
+ // we have to distribute and then attempt to add `remainingPower / validatorsWithPowerLessThanMaxPower` to each validator.
+ // To guarantee that the sum remains the same after the distribution of powers, we sort the powers in descending
+ // order. This way, we first attempt to add `remainingPower / validatorsWithPowerLessThanMaxPower` to validators
+ // with greater power and if we cannot add the `remainingPower / validatorsWithPowerLessThanMaxPower` without
+ // exceeding `maxPower`, we just add enough to reach `maxPower` and add the remaining power to validators with smaller
+ // power.
+
+ // If `s > n * maxPower` there's no solution and the algorithm would set everything to `maxPower`.
+ // ----------------
+
+ // Computes `(sum(validators) * percent) / 100`. Because `sdk.Dec` does not provide a `Floor` function, but only
+ // a `Ceil` one, we use `Ceil` and subtract one.
+ maxPower := sdk.NewDec(sum(validators)).Mul(sdk.NewDec(int64(percent))).QuoInt64(100).Ceil().RoundInt64() - 1
+
+ if maxPower == 0 {
+ // edge case: set `maxPower` to 1 to avoid setting the power of a validator to 0
+ maxPower = 1
+ }
+
+ // Sort by `.Power` in decreasing order. Sorting in descending order is needed because otherwise we would have cases
+ // like this `powers =[60, 138, 559]` and `p = 35%` where sum is `757` and `maxValue = 264`.
+ // Because `559 - 264 = 295` we have to distribute 295 to the first 2 numbers (`295/2 = 147` to each number). However,
+ // note that `138 + 147 > 264`. If we were to add 147 to 60 first, then we cannot give the remaining 147 to 138.
+ // So, the idea is to first give `126 (= 264 - 138)` to 138, so it becomes 264, and then add `21 (=147 - 26) + 147` to 60.
+ sort.Slice(validators, func(i, j int) bool {
+ return validators[i].Power > validators[j].Power
+ })
+
+ // `remainingPower` is to be distributed to validators that have power less than `maxPower`
+ remainingPower := int64(0)
+ validatorsWithPowerLessThanMaxPower := 0
+ for _, v := range validators {
+ if v.Power >= maxPower {
+ remainingPower = remainingPower + (v.Power - maxPower)
+ } else {
+ validatorsWithPowerLessThanMaxPower++
+ }
+ }
+
+ updatedValidators := make([]types.ConsumerValidator, len(validators))
+
+ powerPerValidator := int64(0)
+ remainingValidators := int64(validatorsWithPowerLessThanMaxPower)
+ if remainingValidators != 0 {
+ // power to give to each validator in order to distribute the `remainingPower`
+ powerPerValidator = remainingPower / remainingValidators
+ }
+
+ for i, v := range validators {
+ if v.Power >= maxPower {
+ updatedValidators[i] = validators[i]
+ updatedValidators[i].Power = maxPower
+ } else if v.Power+powerPerValidator >= maxPower {
+ updatedValidators[i] = validators[i]
+ updatedValidators[i].Power = maxPower
+ remainingPower = remainingPower - (maxPower - v.Power)
+ remainingValidators--
+ } else {
+ updatedValidators[i] = validators[i]
+ updatedValidators[i].Power = v.Power + powerPerValidator
+ remainingPower = remainingPower - (updatedValidators[i].Power - validators[i].Power)
+ remainingValidators--
+ }
+ if remainingValidators == 0 {
+ continue
+ }
+ powerPerValidator = remainingPower / remainingValidators
+ }
+
+ return updatedValidators
+}
+
+// FilterOptedInAndAllowAndDenylistedPredicate filters the opted-in validators that are allowlisted and not denylisted
+func (k Keeper) FilterOptedInAndAllowAndDenylistedPredicate(ctx sdk.Context, chainID string, providerAddr types.ProviderConsAddress) bool {
+ // only consider opted-in validators
+ return k.IsOptedIn(ctx, chainID, providerAddr) &&
+ // if an allowlist is declared, only consider allowlisted validators
+ (k.IsAllowlistEmpty(ctx, chainID) ||
+ k.IsAllowlisted(ctx, chainID, providerAddr)) &&
+ // if a denylist is declared, only consider denylisted validators
+ (k.IsDenylistEmpty(ctx, chainID) ||
+ !k.IsDenylisted(ctx, chainID, providerAddr))
+}
+
+// ComputeNextValidators computes the validators for the upcoming epoch based on the currently `bondedValidators`.
+func (k Keeper) ComputeNextValidators(ctx sdk.Context, chainID string, bondedValidators []stakingtypes.Validator) []types.ConsumerValidator {
+ nextValidators := k.FilterValidators(ctx, chainID, bondedValidators,
+ func(providerAddr types.ProviderConsAddress) bool {
+ return k.FilterOptedInAndAllowAndDenylistedPredicate(ctx, chainID, providerAddr)
+ })
+
+ nextValidators = k.CapValidatorSet(ctx, chainID, nextValidators)
+ return k.CapValidatorsPower(ctx, chainID, nextValidators)
+}
diff --git a/x/ccv/provider/keeper/partial_set_security_test.go b/x/ccv/provider/keeper/partial_set_security_test.go
new file mode 100644
index 0000000000..42ff7a14ab
--- /dev/null
+++ b/x/ccv/provider/keeper/partial_set_security_test.go
@@ -0,0 +1,676 @@
+package keeper_test
+
+import (
+ "bytes"
+ "math"
+ "sort"
+ "testing"
+
+ "github.com/golang/mock/gomock"
+ "github.com/stretchr/testify/require"
+ "pgregory.net/rapid"
+
+ codectypes "github.com/cosmos/cosmos-sdk/codec/types"
+ "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
+
+ "github.com/cometbft/cometbft/proto/tendermint/crypto"
+
+ testkeeper "github.com/cosmos/interchain-security/v5/testutil/keeper"
+ "github.com/cosmos/interchain-security/v5/x/ccv/provider/keeper"
+ "github.com/cosmos/interchain-security/v5/x/ccv/provider/types"
+ ccvtypes "github.com/cosmos/interchain-security/v5/x/ccv/types"
+)
+
+func TestHandleOptIn(t *testing.T) {
+ providerKeeper, ctx, ctrl, _ := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t))
+ defer ctrl.Finish()
+
+ providerAddr := types.NewProviderConsAddress([]byte("providerAddr"))
+
+ // trying to opt in to a non-proposed and non-registered chain returns an error
+ require.Error(t, providerKeeper.HandleOptIn(ctx, "unknownChainID", providerAddr, nil))
+
+ providerKeeper.SetProposedConsumerChain(ctx, "chainID", 1)
+ require.False(t, providerKeeper.IsOptedIn(ctx, "chainID", providerAddr))
+ providerKeeper.HandleOptIn(ctx, "chainID", providerAddr, nil)
+ require.True(t, providerKeeper.IsOptedIn(ctx, "chainID", providerAddr))
+}
+
+func TestHandleOptInWithConsumerKey(t *testing.T) {
+ providerKeeper, ctx, ctrl, mocks := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t))
+ defer ctrl.Finish()
+
+ // generate a consensus public key for the provider
+ providerConsPubKey := ed25519.GenPrivKeyFromSecret([]byte{1}).PubKey()
+ consAddr := sdk.ConsAddress(providerConsPubKey.Address())
+ providerAddr := types.NewProviderConsAddress(consAddr)
+
+ calls := []*gomock.Call{
+ mocks.MockStakingKeeper.EXPECT().
+ GetValidatorByConsAddr(gomock.Any(), gomock.Any()).
+ DoAndReturn(func(ctx sdk.Context, addr sdk.ConsAddress) (stakingtypes.Validator, bool) {
+ if addr.Equals(providerAddr.Address) {
+ // Given `providerAddr`, `GetValidatorByConsAddr` returns a validator with the
+ // exact same `ConsensusPubkey`
+ pkAny, _ := codectypes.NewAnyWithValue(providerConsPubKey)
+ return stakingtypes.Validator{ConsensusPubkey: pkAny}, true
+ } else {
+ // for any other consensus address, we cannot find a validator
+ return stakingtypes.Validator{}, false
+ }
+ }).Times(2),
+ }
+
+ gomock.InOrder(calls...)
+ providerKeeper.SetProposedConsumerChain(ctx, "chainID", 1)
+
+ // create a sample consumer key to assign to the `providerAddr` validator
+ // on the consumer chain with id `chainID`
+ consumerKey := "{\"@type\":\"/cosmos.crypto.ed25519.PubKey\",\"key\":\"Ui5Gf1+mtWUdH8u3xlmzdKID+F3PK0sfXZ73GZ6q6is=\"}"
+ expectedConsumerPubKey, _ := providerKeeper.ParseConsumerKey(consumerKey)
+
+ err := providerKeeper.HandleOptIn(ctx, "chainID", providerAddr, &consumerKey)
+ require.NoError(t, err)
+
+ // assert that the consumeKey was assigned to `providerAddr` validator on chain with id `chainID`
+ actualConsumerPubKey, found := providerKeeper.GetValidatorConsumerPubKey(ctx, "chainID", providerAddr)
+ require.True(t, found)
+ require.Equal(t, expectedConsumerPubKey, actualConsumerPubKey)
+
+ // assert that the `consumerAddr` to `providerAddr` association was set as well
+ consumerAddr, _ := ccvtypes.TMCryptoPublicKeyToConsAddr(actualConsumerPubKey)
+ actualProviderConsAddr, found := providerKeeper.GetValidatorByConsumerAddr(ctx, "chainID", types.NewConsumerConsAddress(consumerAddr))
+ require.Equal(t, providerAddr, actualProviderConsAddr)
+}
+
+func TestHandleOptOut(t *testing.T) {
+ providerKeeper, ctx, ctrl, _ := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t))
+ defer ctrl.Finish()
+
+ providerAddr := types.NewProviderConsAddress([]byte("providerAddr"))
+
+ // trying to opt out from a not running chain returns an error
+ require.Error(t, providerKeeper.HandleOptOut(ctx, "unknownChainID", providerAddr))
+
+ // set a consumer client so that the chain is considered running
+ providerKeeper.SetConsumerClientId(ctx, "chainID", "clientID")
+
+ // if validator (`providerAddr`) is already opted in, then an opt-out would remove this validator
+ providerKeeper.SetOptedIn(ctx, "chainID", providerAddr)
+ require.True(t, providerKeeper.IsOptedIn(ctx, "chainID", providerAddr))
+ providerKeeper.HandleOptOut(ctx, "chainID", providerAddr)
+ require.False(t, providerKeeper.IsOptedIn(ctx, "chainID", providerAddr))
+}
+
+func TestHandleOptOutFromTopNChain(t *testing.T) {
+ providerKeeper, ctx, ctrl, mocks := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t))
+ defer ctrl.Finish()
+
+ chainID := "chainID"
+
+ // set a consumer client so that the chain is considered running
+ providerKeeper.SetConsumerClientId(ctx, chainID, "clientID")
+
+ // set the chain as Top 50 and create 4 validators with 10%, 20%, 30%, and 40% of the total voting power
+ // respectively
+ providerKeeper.SetTopN(ctx, "chainID", 50)
+ valA := createStakingValidator(ctx, mocks, 1, 1) // 10% of the total voting power (can opt out)
+ valAConsAddr, _ := valA.GetConsAddr()
+ mocks.MockStakingKeeper.EXPECT().GetValidatorByConsAddr(ctx, valAConsAddr).Return(valA, true).AnyTimes()
+ valB := createStakingValidator(ctx, mocks, 2, 2) // 20% of the total voting power (can opt out)
+ valBConsAddr, _ := valB.GetConsAddr()
+ mocks.MockStakingKeeper.EXPECT().GetValidatorByConsAddr(ctx, valBConsAddr).Return(valB, true).AnyTimes()
+ valC := createStakingValidator(ctx, mocks, 3, 3) // 30% of the total voting power (cannot opt out)
+ valCConsAddr, _ := valC.GetConsAddr()
+ mocks.MockStakingKeeper.EXPECT().GetValidatorByConsAddr(ctx, valCConsAddr).Return(valC, true).AnyTimes()
+ valD := createStakingValidator(ctx, mocks, 4, 4) // 40% of the total voting power (cannot opt out)
+ valDConsAddr, _ := valD.GetConsAddr()
+ mocks.MockStakingKeeper.EXPECT().GetValidatorByConsAddr(ctx, valDConsAddr).Return(valD, true).AnyTimes()
+
+ mocks.MockStakingKeeper.EXPECT().GetLastValidators(ctx).Return([]stakingtypes.Validator{valA, valB, valC, valD}).AnyTimes()
+
+ // opt in all validators
+ providerKeeper.SetOptedIn(ctx, chainID, types.NewProviderConsAddress(valAConsAddr))
+ providerKeeper.SetOptedIn(ctx, chainID, types.NewProviderConsAddress(valBConsAddr))
+ providerKeeper.SetOptedIn(ctx, chainID, types.NewProviderConsAddress(valCConsAddr))
+ providerKeeper.SetOptedIn(ctx, chainID, types.NewProviderConsAddress(valDConsAddr))
+
+ // validators A and B can opt out because they belong the bottom 30% of validators
+ require.NoError(t, providerKeeper.HandleOptOut(ctx, chainID, types.NewProviderConsAddress(valAConsAddr)))
+ require.NoError(t, providerKeeper.HandleOptOut(ctx, chainID, types.NewProviderConsAddress(valBConsAddr)))
+
+ // validators C and D cannot opt out because C has 30% of the voting power and D has 40% of the voting power
+ // and hence both are needed to keep validating a Top 50 chain
+ require.Error(t, providerKeeper.HandleOptOut(ctx, chainID, types.NewProviderConsAddress(valCConsAddr)))
+ require.Error(t, providerKeeper.HandleOptOut(ctx, chainID, types.NewProviderConsAddress(valDConsAddr)))
+
+ // opting out a validator that cannot be found from a Top N chain should also return an error
+ notFoundValidator := createStakingValidator(ctx, mocks, 5, 5)
+ notFoundValidatorConsAddr, _ := notFoundValidator.GetConsAddr()
+ mocks.MockStakingKeeper.EXPECT().GetValidatorByConsAddr(ctx, notFoundValidatorConsAddr).
+ Return(stakingtypes.Validator{}, false)
+ require.Error(t, providerKeeper.HandleOptOut(ctx, chainID, types.NewProviderConsAddress(notFoundValidatorConsAddr)))
+}
+
+func TestHandleSetConsumerCommissionRate(t *testing.T) {
+ providerKeeper, ctx, ctrl, mocks := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t))
+ defer ctrl.Finish()
+
+ providerAddr := types.NewProviderConsAddress([]byte("providerAddr"))
+
+ // trying to set a commission rate to a unknown consumer chain
+ require.Error(t, providerKeeper.HandleSetConsumerCommissionRate(ctx, "unknownChainID", providerAddr, sdk.ZeroDec()))
+
+ // setup a pending consumer chain
+ chainID := "pendingChainID"
+ providerKeeper.SetPendingConsumerAdditionProp(ctx, &types.ConsumerAdditionProposal{ChainId: chainID})
+
+ // check that there's no commission rate set for the validator yet
+ _, found := providerKeeper.GetConsumerCommissionRate(ctx, chainID, providerAddr)
+ require.False(t, found)
+
+ mocks.MockStakingKeeper.EXPECT().MinCommissionRate(ctx).Return(sdk.ZeroDec()).Times(1)
+ require.NoError(t, providerKeeper.HandleSetConsumerCommissionRate(ctx, chainID, providerAddr, sdk.OneDec()))
+
+ // check that the commission rate is now set
+ cr, found := providerKeeper.GetConsumerCommissionRate(ctx, chainID, providerAddr)
+ require.Equal(t, sdk.OneDec(), cr)
+ require.True(t, found)
+
+ // set minimum rate of 1/2
+ commissionRate := sdk.NewDec(1).Quo(sdk.NewDec(2))
+ mocks.MockStakingKeeper.EXPECT().MinCommissionRate(ctx).Return(commissionRate).AnyTimes()
+
+ // try to set a rate slightly below the minimum
+ require.Error(t, providerKeeper.HandleSetConsumerCommissionRate(
+ ctx,
+ chainID,
+ providerAddr,
+ commissionRate.Sub(sdk.NewDec(1).Quo(sdk.NewDec(100)))), // 0.5 - 0.01
+ "commission rate should be rejected (below min), but is not",
+ )
+
+ // set a valid commission equal to the minimum
+ require.NoError(t, providerKeeper.HandleSetConsumerCommissionRate(ctx, chainID, providerAddr, commissionRate))
+ // check that the rate was set
+ cr, found = providerKeeper.GetConsumerCommissionRate(ctx, chainID, providerAddr)
+ require.Equal(t, commissionRate, cr)
+ require.True(t, found)
+}
+
+func TestOptInTopNValidators(t *testing.T) {
+ providerKeeper, ctx, ctrl, mocks := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t))
+ defer ctrl.Finish()
+
+ // create 4 validators with powers 1, 2, 3, and 1 respectively
+ valA := createStakingValidator(ctx, mocks, 1, 1)
+ valAConsAddr, _ := valA.GetConsAddr()
+ valB := createStakingValidator(ctx, mocks, 2, 2)
+ valBConsAddr, _ := valB.GetConsAddr()
+ valC := createStakingValidator(ctx, mocks, 3, 3)
+ valCConsAddr, _ := valC.GetConsAddr()
+ valD := createStakingValidator(ctx, mocks, 4, 1)
+ valDConsAddr, _ := valD.GetConsAddr()
+
+ // Start Test 1: opt in all validators with power >= 0
+ providerKeeper.OptInTopNValidators(ctx, "chainID", []stakingtypes.Validator{valA, valB, valC, valD}, 0)
+ expectedOptedInValidators := []types.ProviderConsAddress{
+ types.NewProviderConsAddress(valAConsAddr),
+ types.NewProviderConsAddress(valBConsAddr),
+ types.NewProviderConsAddress(valCConsAddr),
+ types.NewProviderConsAddress(valDConsAddr),
+ }
+ actualOptedInValidators := providerKeeper.GetAllOptedIn(ctx, "chainID")
+
+ // sort validators first to be able to compare
+ sortUpdates := func(addresses []types.ProviderConsAddress) {
+ sort.Slice(addresses, func(i, j int) bool {
+ return bytes.Compare(addresses[i].ToSdkConsAddr(), addresses[j].ToSdkConsAddr()) < 0
+ })
+ }
+
+ sortUpdates(expectedOptedInValidators)
+ sortUpdates(actualOptedInValidators)
+ require.Equal(t, expectedOptedInValidators, actualOptedInValidators)
+
+ // reset state for the upcoming checks
+ providerKeeper.DeleteOptedIn(ctx, "chainID", types.NewProviderConsAddress(valAConsAddr))
+ providerKeeper.DeleteOptedIn(ctx, "chainID", types.NewProviderConsAddress(valBConsAddr))
+ providerKeeper.DeleteOptedIn(ctx, "chainID", types.NewProviderConsAddress(valCConsAddr))
+ providerKeeper.DeleteOptedIn(ctx, "chainID", types.NewProviderConsAddress(valDConsAddr))
+
+ // Start Test 2: opt in all validators with power >= 1
+ // We expect the same `expectedOptedInValidators` as when we opted in all validators with power >= 0 because the
+ // validators with the smallest power have power == 1
+ providerKeeper.OptInTopNValidators(ctx, "chainID", []stakingtypes.Validator{valA, valB, valC, valD}, 0)
+ actualOptedInValidators = providerKeeper.GetAllOptedIn(ctx, "chainID")
+ sortUpdates(actualOptedInValidators)
+ require.Equal(t, expectedOptedInValidators, actualOptedInValidators)
+
+ providerKeeper.DeleteOptedIn(ctx, "chainID", types.NewProviderConsAddress(valAConsAddr))
+ providerKeeper.DeleteOptedIn(ctx, "chainID", types.NewProviderConsAddress(valBConsAddr))
+ providerKeeper.DeleteOptedIn(ctx, "chainID", types.NewProviderConsAddress(valCConsAddr))
+ providerKeeper.DeleteOptedIn(ctx, "chainID", types.NewProviderConsAddress(valDConsAddr))
+
+ // Start Test 3: opt in all validators with power >= 2 and hence we do not expect to opt in validator A
+ providerKeeper.OptInTopNValidators(ctx, "chainID", []stakingtypes.Validator{valA, valB, valC, valD}, 2)
+ expectedOptedInValidators = []types.ProviderConsAddress{
+ types.NewProviderConsAddress(valBConsAddr),
+ types.NewProviderConsAddress(valCConsAddr),
+ }
+ actualOptedInValidators = providerKeeper.GetAllOptedIn(ctx, "chainID")
+
+ // sort validators first to be able to compare
+ sortUpdates(expectedOptedInValidators)
+ sortUpdates(actualOptedInValidators)
+ require.Equal(t, expectedOptedInValidators, actualOptedInValidators)
+
+ // reset state for the upcoming checks
+ providerKeeper.DeleteOptedIn(ctx, "chainID", types.NewProviderConsAddress(valAConsAddr))
+ providerKeeper.DeleteOptedIn(ctx, "chainID", types.NewProviderConsAddress(valBConsAddr))
+ providerKeeper.DeleteOptedIn(ctx, "chainID", types.NewProviderConsAddress(valCConsAddr))
+ providerKeeper.DeleteOptedIn(ctx, "chainID", types.NewProviderConsAddress(valDConsAddr))
+
+ // Start Test 4: opt in all validators with power >= 4 and hence we do not expect any opted-in validators
+ providerKeeper.OptInTopNValidators(ctx, "chainID", []stakingtypes.Validator{valA, valB, valC, valD}, 4)
+ require.Empty(t, providerKeeper.GetAllOptedIn(ctx, "chainID"))
+}
+
+func TestComputeMinPowerToOptIn(t *testing.T) {
+ providerKeeper, ctx, ctrl, mocks := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t))
+ defer ctrl.Finish()
+
+ // create 5 validators with powers 1, 3, 5, 6, 10 (not in that order) with total power of 25 (= 1 + 3 + 5 + 6 + 10)
+ // such that:
+ // validator power => cumulative share
+ // 10 => 40%
+ // 6 => 64%
+ // 5 => 84%
+ // 3 => 96%
+ // 1 => 100%
+
+ bondedValidators := []stakingtypes.Validator{
+ createStakingValidator(ctx, mocks, 1, 5),
+ createStakingValidator(ctx, mocks, 2, 10),
+ createStakingValidator(ctx, mocks, 3, 3),
+ createStakingValidator(ctx, mocks, 4, 1),
+ createStakingValidator(ctx, mocks, 5, 6),
+ }
+
+ m, err := providerKeeper.ComputeMinPowerToOptIn(ctx, "chainID", bondedValidators, 100)
+ require.NoError(t, err)
+ require.Equal(t, int64(1), m)
+
+ m, err = providerKeeper.ComputeMinPowerToOptIn(ctx, "chainID", bondedValidators, 97)
+ require.NoError(t, err)
+ require.Equal(t, int64(1), m)
+
+ m, err = providerKeeper.ComputeMinPowerToOptIn(ctx, "chainID", bondedValidators, 96)
+ require.NoError(t, err)
+ require.Equal(t, int64(3), m)
+
+ m, err = providerKeeper.ComputeMinPowerToOptIn(ctx, "chainID", bondedValidators, 85)
+ require.NoError(t, err)
+ require.Equal(t, int64(3), m)
+
+ m, err = providerKeeper.ComputeMinPowerToOptIn(ctx, "chainID", bondedValidators, 84)
+ require.NoError(t, err)
+ require.Equal(t, int64(5), m)
+
+ m, err = providerKeeper.ComputeMinPowerToOptIn(ctx, "chainID", bondedValidators, 65)
+ require.NoError(t, err)
+ require.Equal(t, int64(5), m)
+
+ m, err = providerKeeper.ComputeMinPowerToOptIn(ctx, "chainID", bondedValidators, 64)
+ require.NoError(t, err)
+ require.Equal(t, int64(6), m)
+
+ m, err = providerKeeper.ComputeMinPowerToOptIn(ctx, "chainID", bondedValidators, 41)
+ require.NoError(t, err)
+ require.Equal(t, int64(6), m)
+
+ m, err = providerKeeper.ComputeMinPowerToOptIn(ctx, "chainID", bondedValidators, 40)
+ require.NoError(t, err)
+ require.Equal(t, int64(10), m)
+
+ m, err = providerKeeper.ComputeMinPowerToOptIn(ctx, "chainID", bondedValidators, 1)
+ require.NoError(t, err)
+ require.Equal(t, int64(10), m)
+
+ // exceptional case when we erroneously call with `topN == 0` or `topN > 100`
+ _, err = providerKeeper.ComputeMinPowerToOptIn(ctx, "chainID", bondedValidators, 0)
+ require.Error(t, err)
+
+ _, err = providerKeeper.ComputeMinPowerToOptIn(ctx, "chainID", bondedValidators, 101)
+ require.Error(t, err)
+}
+
+// TestFilterOptedInAndAllowAndDenylistedPredicate returns true if `validator` is opted in, in `chainID.
+func TestFilterOptedInAndAllowAndDenylistedPredicate(t *testing.T) {
+ providerKeeper, ctx, ctrl, mocks := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t))
+ defer ctrl.Finish()
+
+ validator := createStakingValidator(ctx, mocks, 0, 1)
+ consAddr, _ := validator.GetConsAddr()
+ providerAddr := types.NewProviderConsAddress(consAddr)
+
+ // with no allowlist or denylist, the validator has to be opted in, in order to consider it
+ require.False(t, providerKeeper.FilterOptedInAndAllowAndDenylistedPredicate(ctx, "chainID", providerAddr))
+ providerKeeper.SetOptedIn(ctx, "chainID", types.NewProviderConsAddress(consAddr))
+ require.True(t, providerKeeper.FilterOptedInAndAllowAndDenylistedPredicate(ctx, "chainID", providerAddr))
+
+ // create an allow list but do not add the validator `providerAddr` to it
+ validatorA := createStakingValidator(ctx, mocks, 1, 1)
+ consAddrA, _ := validatorA.GetConsAddr()
+ providerKeeper.SetAllowlist(ctx, "chainID", types.NewProviderConsAddress(consAddrA))
+ require.False(t, providerKeeper.FilterOptedInAndAllowAndDenylistedPredicate(ctx, "chainID", providerAddr))
+ providerKeeper.SetAllowlist(ctx, "chainID", types.NewProviderConsAddress(consAddr))
+ require.True(t, providerKeeper.FilterOptedInAndAllowAndDenylistedPredicate(ctx, "chainID", providerAddr))
+
+ // create a denylist but do not add validator `providerAddr` to it
+ providerKeeper.SetDenylist(ctx, "chainID", types.NewProviderConsAddress(consAddrA))
+ require.True(t, providerKeeper.FilterOptedInAndAllowAndDenylistedPredicate(ctx, "chainID", providerAddr))
+ // add validator `providerAddr` to the denylist
+ providerKeeper.SetDenylist(ctx, "chainID", types.NewProviderConsAddress(consAddr))
+ require.False(t, providerKeeper.FilterOptedInAndAllowAndDenylistedPredicate(ctx, "chainID", providerAddr))
+}
+
+func TestCapValidatorSet(t *testing.T) {
+ providerKeeper, ctx, ctrl, _ := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t))
+ defer ctrl.Finish()
+
+ validatorA := types.ConsumerValidator{
+ ProviderConsAddr: []byte("providerConsAddrA"),
+ Power: 1,
+ ConsumerPublicKey: &crypto.PublicKey{},
+ }
+
+ validatorB := types.ConsumerValidator{
+ ProviderConsAddr: []byte("providerConsAddrB"),
+ Power: 2,
+ ConsumerPublicKey: &crypto.PublicKey{},
+ }
+
+ validatorC := types.ConsumerValidator{
+ ProviderConsAddr: []byte("providerConsAddrC"),
+ Power: 3,
+ ConsumerPublicKey: &crypto.PublicKey{},
+ }
+ validators := []types.ConsumerValidator{validatorA, validatorB, validatorC}
+
+ consumerValidators := providerKeeper.CapValidatorSet(ctx, "chainID", validators)
+ require.Equal(t, validators, consumerValidators)
+
+ providerKeeper.SetValidatorSetCap(ctx, "chainID", 0)
+ consumerValidators = providerKeeper.CapValidatorSet(ctx, "chainID", validators)
+ require.Equal(t, validators, consumerValidators)
+
+ providerKeeper.SetValidatorSetCap(ctx, "chainID", 100)
+ consumerValidators = providerKeeper.CapValidatorSet(ctx, "chainID", validators)
+ require.Equal(t, validators, consumerValidators)
+
+ providerKeeper.SetValidatorSetCap(ctx, "chainID", 1)
+ consumerValidators = providerKeeper.CapValidatorSet(ctx, "chainID", validators)
+ require.Equal(t, []types.ConsumerValidator{validatorC}, consumerValidators)
+
+ providerKeeper.SetValidatorSetCap(ctx, "chainID", 2)
+ consumerValidators = providerKeeper.CapValidatorSet(ctx, "chainID", validators)
+ require.Equal(t, []types.ConsumerValidator{validatorC, validatorB}, consumerValidators)
+
+ providerKeeper.SetValidatorSetCap(ctx, "chainID", 3)
+ consumerValidators = providerKeeper.CapValidatorSet(ctx, "chainID", validators)
+ require.Equal(t, []types.ConsumerValidator{validatorC, validatorB, validatorA}, consumerValidators)
+}
+
+func TestCapValidatorsPower(t *testing.T) {
+ providerKeeper, ctx, ctrl, _ := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t))
+ defer ctrl.Finish()
+
+ validatorA := types.ConsumerValidator{
+ ProviderConsAddr: []byte("providerConsAddrA"),
+ Power: 1,
+ ConsumerPublicKey: &crypto.PublicKey{},
+ }
+
+ validatorB := types.ConsumerValidator{
+ ProviderConsAddr: []byte("providerConsAddrB"),
+ Power: 2,
+ ConsumerPublicKey: &crypto.PublicKey{},
+ }
+
+ validatorC := types.ConsumerValidator{
+ ProviderConsAddr: []byte("providerConsAddrC"),
+ Power: 3,
+ ConsumerPublicKey: &crypto.PublicKey{},
+ }
+
+ validatorD := types.ConsumerValidator{
+ ProviderConsAddr: []byte("providerConsAddrD"),
+ Power: 4,
+ ConsumerPublicKey: &crypto.PublicKey{},
+ }
+
+ validators := []types.ConsumerValidator{validatorA, validatorB, validatorC, validatorD}
+
+ expectedValidators := make([]types.ConsumerValidator, len(validators))
+ copy(expectedValidators, validators)
+ expectedValidators[0].Power = 2
+ expectedValidators[1].Power = 2
+ expectedValidators[2].Power = 3
+ expectedValidators[3].Power = 3
+
+ sortValidators := func(validators []types.ConsumerValidator) {
+ sort.Slice(validators, func(i, j int) bool {
+ return bytes.Compare(validators[i].ProviderConsAddr, validators[j].ProviderConsAddr) < 0
+ })
+ }
+
+ // no capping takes place because validators power-cap is not set
+ cappedValidators := providerKeeper.CapValidatorsPower(ctx, "chainID", validators)
+ sortValidators(validators)
+ sortValidators(cappedValidators)
+ require.Equal(t, validators, cappedValidators)
+
+ providerKeeper.SetValidatorsPowerCap(ctx, "chainID", 33)
+ cappedValidators = providerKeeper.CapValidatorsPower(ctx, "chainID", validators)
+ sortValidators(expectedValidators)
+ sortValidators(cappedValidators)
+ require.Equal(t, expectedValidators, cappedValidators)
+}
+
+func TestNoMoreThanPercentOfTheSum(t *testing.T) {
+ // **impossible** case where we only have 9 powers, and we want that no number has more than 10% of the total sum
+ powers := []int64{1, 2, 3, 4, 5, 6, 7, 8, 9}
+ percent := uint32(10)
+ require.False(t, noMoreThanPercent(keeper.NoMoreThanPercentOfTheSum(createConsumerValidators(powers), percent), percent))
+
+ powers = []int64{1, 2, 3, 4, 5}
+ percent = 20
+ require.True(t, noMoreThanPercent(keeper.NoMoreThanPercentOfTheSum(createConsumerValidators(powers), percent), percent))
+
+ powers = []int64{1, 2, 3, 4, 5}
+ percent = 21
+ require.True(t, noMoreThanPercent(keeper.NoMoreThanPercentOfTheSum(createConsumerValidators(powers), percent), percent))
+
+ powers = []int64{1, 2, 3, 4, 5}
+ percent = 25
+ require.True(t, noMoreThanPercent(keeper.NoMoreThanPercentOfTheSum(createConsumerValidators(powers), percent), percent))
+
+ powers = []int64{1, 2, 3, 4, 5}
+ percent = 32
+ require.True(t, noMoreThanPercent(keeper.NoMoreThanPercentOfTheSum(createConsumerValidators(powers), percent), percent))
+
+ powers = []int64{1, 2, 3, 4, 5}
+ percent = 33
+ require.True(t, noMoreThanPercent(keeper.NoMoreThanPercentOfTheSum(createConsumerValidators(powers), percent), percent))
+
+ powers = []int64{1, 2, 3, 4, 5}
+ percent = 34
+ require.True(t, noMoreThanPercent(keeper.NoMoreThanPercentOfTheSum(createConsumerValidators(powers), percent), percent))
+
+ powers = []int64{1, 2, 3, 4, 5}
+ percent = 50
+ require.True(t, noMoreThanPercent(keeper.NoMoreThanPercentOfTheSum(createConsumerValidators(powers), percent), percent))
+}
+
+func createConsumerValidators(powers []int64) []types.ConsumerValidator {
+ var validators []types.ConsumerValidator
+ for _, p := range powers {
+ validators = append(validators, types.ConsumerValidator{
+ ProviderConsAddr: []byte("providerConsAddr"),
+ Power: p,
+ ConsumerPublicKey: &crypto.PublicKey{},
+ })
+ }
+ return validators
+}
+
+// returns `true` if no validator in `validators` corresponds to more than `percent` of the total sum of all
+// validators' powers
+func noMoreThanPercent(validators []types.ConsumerValidator, percent uint32) bool {
+ sum := int64(0)
+ for _, v := range validators {
+ sum = sum + v.Power
+ }
+
+ for _, v := range validators {
+ if (float64(v.Power)/float64(sum))*100.0 > float64(percent) {
+ return false
+ }
+ }
+ return true
+}
+
+func sumPowers(vals []types.ConsumerValidator) int64 {
+ sum := int64(0)
+ for _, v := range vals {
+ sum += v.Power
+ }
+ return sum
+}
+
+func CapSatisfiable(vals []types.ConsumerValidator, percent uint32) bool {
+ // 100 / len(vals) is what each validator gets if each has the same power.
+ // if this is more than the cap, it cannot be satisfied.
+ return float64(100)/float64(len(vals)) < float64(percent)
+}
+
+func TestNoMoreThanPercentOfTheSumProps(t *testing.T) {
+ // define properties to test
+
+ // capRespectedIfSatisfiable: if the cap can be respected, then it will be respected
+ capRespectedIfSatisfiable := func(valsBefore, valsAfter []types.ConsumerValidator, percent uint32) bool {
+ if CapSatisfiable(valsBefore, percent) {
+ return noMoreThanPercent(valsAfter, percent)
+ }
+ return true
+ }
+
+ evenPowersIfCapCannotBeSatisfied := func(valsBefore, valsAfter []types.ConsumerValidator, percent uint32) bool {
+ if !CapSatisfiable(valsBefore, percent) {
+ // if the cap cannot be satisfied, each validator should have the same power
+ for _, valAfter := range valsAfter {
+ if valAfter.Power != valsAfter[0].Power {
+ return false
+ }
+ }
+ }
+ return true
+ }
+
+ // fairness: if before, v1 has more power than v2, then afterwards v1 will not have less power than v2
+ // (they might get the same power if they are both capped)
+ fairness := func(valsBefore, valsAfter []types.ConsumerValidator) bool {
+ for i, v := range valsBefore {
+ // find the validator after with the same address
+ vAfter := findConsumerValidator(t, v, valsAfter)
+
+ // go through all other validators before (after this one, to avoid double checking)
+ for j := i + 1; j < len(valsBefore); j++ {
+ otherV := valsBefore[j]
+ otherVAfter := findConsumerValidator(t, otherV, valsAfter)
+
+ // v has at least as much power before
+ if v.Power >= otherV.Power {
+ // then otherV should not have more power after
+ if vAfter.Power < otherVAfter.Power {
+ return false
+ }
+ } else {
+ // v has less power before
+ // then v should not have more power after
+ if vAfter.Power > otherVAfter.Power {
+ return false
+ }
+ }
+ }
+ }
+ return true
+ }
+
+ // non-zero: v has non-zero power before IFF it has non-zero power after
+ nonZero := func(valsBefore, valsAfter []types.ConsumerValidator) bool {
+ for _, v := range valsBefore {
+ vAfter := findConsumerValidator(t, v, valsAfter)
+ if (v.Power == 0) != (vAfter.Power == 0) {
+ return false
+ }
+ }
+ return true
+ }
+
+ // equalSumIfCapSatisfiable: the sum of the powers of the validators will not change if the cap can be satisfied
+ // (except for small changes by rounding errors)
+ equalSumIfCapSatisfiable := func(valsBefore, valsAfter []types.ConsumerValidator, percent uint32) bool {
+ if CapSatisfiable(valsBefore, percent) {
+ difference := math.Abs(float64(sumPowers(valsBefore) - sumPowers(valsAfter)))
+ if difference > 1 {
+ // if the difference is more than a rounding error, they are not equal
+ return false
+ }
+ }
+ return true
+ }
+
+ // num validators: the number of validators will not change
+ equalNumVals := func(valsBefore, valsAfter []types.ConsumerValidator) bool {
+ return len(valsBefore) == len(valsAfter)
+ }
+
+ // test setup for pbt
+ rapid.Check(t, func(t *rapid.T) {
+ powers := rapid.SliceOf(rapid.Int64Range(1, 1000000000000)).Draw(t, "powers")
+ percent := uint32(rapid.Int32Range(1, 100).Draw(t, "percent"))
+
+ consumerValidators := createConsumerValidators(powers)
+ cappedValidators := keeper.NoMoreThanPercentOfTheSum(consumerValidators, percent)
+
+ t.Log("can the cap be satisfied: ", CapSatisfiable(consumerValidators, percent))
+ t.Log("before: ", consumerValidators)
+ t.Log("after: ", cappedValidators)
+
+ // check properties
+ require.True(t, capRespectedIfSatisfiable(consumerValidators, cappedValidators, percent))
+ require.True(t, evenPowersIfCapCannotBeSatisfied(consumerValidators, cappedValidators, percent))
+ require.True(t, fairness(consumerValidators, cappedValidators))
+ require.True(t, nonZero(consumerValidators, cappedValidators))
+ require.True(t, equalSumIfCapSatisfiable(consumerValidators, cappedValidators, percent), "sum before: %v, sum after: %v", sumPowers(consumerValidators), sumPowers(cappedValidators))
+ require.True(t, equalNumVals(consumerValidators, cappedValidators), "num before: %v, num after: %v", len(consumerValidators), len(cappedValidators))
+ })
+}
+
+func findConsumerValidator(t *testing.T, v types.ConsumerValidator, valsAfter []types.ConsumerValidator) *types.ConsumerValidator {
+ var vAfter *types.ConsumerValidator
+ for _, vA := range valsAfter {
+ if bytes.Equal(v.ProviderConsAddr, vA.ProviderConsAddr) {
+ vAfter = &vA
+ break
+ }
+ }
+ if vAfter == nil {
+ t.Fatalf("could not find validator with address %v in validators after \n validators after capping: %v", v.ProviderConsAddr, valsAfter)
+ }
+ return vAfter
+}
diff --git a/x/ccv/provider/keeper/proposal.go b/x/ccv/provider/keeper/proposal.go
index c7a122b497..67d3c91bca 100644
--- a/x/ccv/provider/keeper/proposal.go
+++ b/x/ccv/provider/keeper/proposal.go
@@ -18,8 +18,8 @@ import (
tmtypes "github.com/cometbft/cometbft/types"
- "github.com/cosmos/interchain-security/v4/x/ccv/provider/types"
- ccv "github.com/cosmos/interchain-security/v4/x/ccv/types"
+ "github.com/cosmos/interchain-security/v5/x/ccv/provider/types"
+ ccv "github.com/cosmos/interchain-security/v5/x/ccv/types"
)
// HandleConsumerAdditionProposal will receive the consumer chain's client state from the proposal.
@@ -189,6 +189,12 @@ func (k Keeper) StopConsumerChain(ctx sdk.Context, chainID string, closeChan boo
k.DeleteVscSendTimestampsForConsumer(ctx, chainID)
}
+ // delete consumer commission rate
+ provAddrs := k.GetAllCommissionRateValidators(ctx, chainID)
+ for _, addr := range provAddrs {
+ k.DeleteConsumerCommissionRate(ctx, chainID, addr)
+ }
+
k.DeleteInitChainHeight(ctx, chainID)
k.DeleteSlashAcks(ctx, chainID)
k.DeletePendingVSCPackets(ctx, chainID)
@@ -213,6 +219,15 @@ func (k Keeper) StopConsumerChain(ctx sdk.Context, chainID string, closeChan boo
k.DeleteUnbondingOpIndex(ctx, chainID, unbondingOpsIndex.VscId)
}
+ k.DeleteTopN(ctx, chainID)
+ k.DeleteValidatorsPowerCap(ctx, chainID)
+ k.DeleteValidatorSetCap(ctx, chainID)
+ k.DeleteAllowlist(ctx, chainID)
+ k.DeleteDenylist(ctx, chainID)
+
+ k.DeleteAllOptedIn(ctx, chainID)
+ k.DeleteConsumerValSet(ctx, chainID)
+
k.Logger(ctx).Info("consumer chain removed from provider", "chainID", chainID)
return nil
@@ -269,7 +284,16 @@ func (k Keeper) MakeConsumerGenesis(
bondedValidators = append(bondedValidators, val)
}
- nextValidators := k.ComputeNextEpochConsumerValSet(ctx, chainID, bondedValidators)
+ if topN, found := k.GetTopN(ctx, chainID); found && topN > 0 {
+ // in a Top-N chain, we automatically opt in all validators that belong to the top N
+ minPower, err := k.ComputeMinPowerToOptIn(ctx, chainID, bondedValidators, prop.Top_N)
+ if err == nil {
+ k.OptInTopNValidators(ctx, chainID, bondedValidators, minPower)
+ }
+ }
+
+ nextValidators := k.ComputeNextValidators(ctx, chainID, bondedValidators)
+
k.SetConsumerValSet(ctx, chainID, nextValidators)
// get the initial updates with the latest set consumer public keys
@@ -353,14 +377,39 @@ func (k Keeper) GetPendingConsumerAdditionProp(ctx sdk.Context, spawnTime time.T
func (k Keeper) BeginBlockInit(ctx sdk.Context) {
propsToExecute := k.GetConsumerAdditionPropsToExecute(ctx)
- for _, prop := range propsToExecute {
+ for i, prop := range propsToExecute {
// create consumer client in a cached context to handle errors
- cachedCtx, writeFn, err := k.CreateConsumerClientInCachedCtx(ctx, prop)
+ cachedCtx, writeFn := ctx.CacheContext()
+
+ k.SetTopN(cachedCtx, prop.ChainId, prop.Top_N)
+ k.SetValidatorSetCap(cachedCtx, prop.ChainId, prop.ValidatorSetCap)
+ k.SetValidatorsPowerCap(cachedCtx, prop.ChainId, prop.ValidatorsPowerCap)
+
+ for _, address := range prop.Allowlist {
+ consAddr, err := sdk.ConsAddressFromBech32(address)
+ if err != nil {
+ continue
+ }
+
+ k.SetAllowlist(cachedCtx, prop.ChainId, types.NewProviderConsAddress(consAddr))
+ }
+
+ for _, address := range prop.Denylist {
+ consAddr, err := sdk.ConsAddressFromBech32(address)
+ if err != nil {
+ continue
+ }
+
+ k.SetDenylist(cachedCtx, prop.ChainId, types.NewProviderConsAddress(consAddr))
+ }
+
+ err := k.CreateConsumerClient(cachedCtx, &propsToExecute[i])
if err != nil {
// drop the proposal
ctx.Logger().Info("consumer client could not be created: %w", err)
continue
}
+
// The cached context is created with a new EventManager so we merge the event
// into the original context
ctx.EventManager().EmitEvents(cachedCtx.EventManager().Events())
diff --git a/x/ccv/provider/keeper/proposal_test.go b/x/ccv/provider/keeper/proposal_test.go
index fc1c7a4344..67b0f93778 100644
--- a/x/ccv/provider/keeper/proposal_test.go
+++ b/x/ccv/provider/keeper/proposal_test.go
@@ -17,10 +17,11 @@ import (
abci "github.com/cometbft/cometbft/abci/types"
- testkeeper "github.com/cosmos/interchain-security/v4/testutil/keeper"
- providerkeeper "github.com/cosmos/interchain-security/v4/x/ccv/provider/keeper"
- providertypes "github.com/cosmos/interchain-security/v4/x/ccv/provider/types"
- ccvtypes "github.com/cosmos/interchain-security/v4/x/ccv/types"
+ cryptotestutil "github.com/cosmos/interchain-security/v5/testutil/crypto"
+ testkeeper "github.com/cosmos/interchain-security/v5/testutil/keeper"
+ providerkeeper "github.com/cosmos/interchain-security/v5/x/ccv/provider/keeper"
+ providertypes "github.com/cosmos/interchain-security/v5/x/ccv/provider/types"
+ ccvtypes "github.com/cosmos/interchain-security/v5/x/ccv/types"
)
//
@@ -64,6 +65,11 @@ func TestHandleConsumerAdditionProposal(t *testing.T) {
100000000000,
100000000000,
100000000000,
+ 0,
+ 0,
+ 0,
+ nil,
+ nil,
).(*providertypes.ConsumerAdditionProposal),
blockTime: now,
expAppendProp: true,
@@ -89,6 +95,11 @@ func TestHandleConsumerAdditionProposal(t *testing.T) {
100000000000,
100000000000,
100000000000,
+ 0,
+ 0,
+ 0,
+ nil,
+ nil,
).(*providertypes.ConsumerAdditionProposal),
blockTime: now,
expAppendProp: false,
@@ -924,6 +935,11 @@ func TestBeginBlockInit(t *testing.T) {
100000000000,
100000000000,
100000000000,
+ 50,
+ 0,
+ 0,
+ nil,
+ nil,
).(*providertypes.ConsumerAdditionProposal),
providertypes.NewConsumerAdditionProposal(
"title", "spawn time passed", "chain2", clienttypes.NewHeight(3, 4), []byte{}, []byte{},
@@ -935,6 +951,11 @@ func TestBeginBlockInit(t *testing.T) {
100000000000,
100000000000,
100000000000,
+ 50,
+ 0,
+ 0,
+ nil,
+ nil,
).(*providertypes.ConsumerAdditionProposal),
providertypes.NewConsumerAdditionProposal(
"title", "spawn time not passed", "chain3", clienttypes.NewHeight(3, 4), []byte{}, []byte{},
@@ -946,6 +967,11 @@ func TestBeginBlockInit(t *testing.T) {
100000000000,
100000000000,
100000000000,
+ 50,
+ 0,
+ 0,
+ nil,
+ nil,
).(*providertypes.ConsumerAdditionProposal),
providertypes.NewConsumerAdditionProposal(
"title", "invalid proposal: chain id already exists", "chain2", clienttypes.NewHeight(4, 5), []byte{}, []byte{},
@@ -957,38 +983,94 @@ func TestBeginBlockInit(t *testing.T) {
100000000000,
100000000000,
100000000000,
+ 50,
+ 0,
+ 0,
+ nil,
+ nil,
+ ).(*providertypes.ConsumerAdditionProposal),
+ providertypes.NewConsumerAdditionProposal(
+ "title", "opt-in chain with at least one validator opted in", "chain5", clienttypes.NewHeight(3, 4), []byte{}, []byte{},
+ now.Add(-time.Hour*1).UTC(),
+ "0.75",
+ 10,
+ "",
+ 10000,
+ 100000000000,
+ 100000000000,
+ 100000000000,
+ 0,
+ 0,
+ 0,
+ nil,
+ nil,
).(*providertypes.ConsumerAdditionProposal),
}
- // Expect client creation for only for the 1st and second proposals (spawn time already passed and valid)
- gomock.InOrder(
- append(testkeeper.GetMocksForCreateConsumerClient(ctx, &mocks, "chain1", clienttypes.NewHeight(3, 4)),
- testkeeper.GetMocksForCreateConsumerClient(ctx, &mocks, "chain2", clienttypes.NewHeight(3, 4))...)...,
- )
+ // Expect client creation for only the first, second, and fifth proposals (spawn time already passed and valid)
+ expectedCalls := testkeeper.GetMocksForCreateConsumerClient(ctx, &mocks, "chain1", clienttypes.NewHeight(3, 4))
+ expectedCalls = append(expectedCalls, testkeeper.GetMocksForCreateConsumerClient(ctx, &mocks, "chain2", clienttypes.NewHeight(3, 4))...)
+ expectedCalls = append(expectedCalls, testkeeper.GetMocksForCreateConsumerClient(ctx, &mocks, "chain5", clienttypes.NewHeight(3, 4))...)
+
+ gomock.InOrder(expectedCalls...)
for _, prop := range pendingProps {
providerKeeper.SetPendingConsumerAdditionProp(ctx, prop)
}
+ // opt in a sample validator so the chain's proposal can successfully execute
+ validator := cryptotestutil.NewCryptoIdentityFromIntSeed(0).SDKStakingValidator()
+ consAddr, _ := validator.GetConsAddr()
+ providerKeeper.SetOptedIn(ctx, pendingProps[4].ChainId, providertypes.NewProviderConsAddress(consAddr))
+
providerKeeper.BeginBlockInit(ctx)
- // Only the third proposal is still stored as pending
+ // first proposal is not pending anymore because its spawn time already passed and was executed
_, found := providerKeeper.GetPendingConsumerAdditionProp(
ctx, pendingProps[0].SpawnTime, pendingProps[0].ChainId)
require.False(t, found)
+ // first proposal was successfully executed and hence consumer genesis was created
+ _, found = providerKeeper.GetConsumerGenesis(ctx, pendingProps[0].ChainId)
+ require.True(t, found)
+ // second proposal is not pending anymore because its spawn time already passed and was executed
_, found = providerKeeper.GetPendingConsumerAdditionProp(
ctx, pendingProps[1].SpawnTime, pendingProps[1].ChainId)
require.False(t, found)
+ // second proposal was successfully executed and hence consumer genesis was created
+ _, found = providerKeeper.GetConsumerGenesis(ctx, pendingProps[1].ChainId)
+ require.True(t, found)
+ // third proposal is still stored as pending because its spawn time has not passed
_, found = providerKeeper.GetPendingConsumerAdditionProp(
ctx, pendingProps[2].SpawnTime, pendingProps[2].ChainId)
require.True(t, found)
+ // because the proposal is still pending, no consumer genesis was created
+ _, found = providerKeeper.GetConsumerGenesis(ctx, pendingProps[2].ChainId)
+ require.False(t, found)
- // check that the invalid proposal was dropped
+ // check that the invalid proposals were dropped
_, found = providerKeeper.GetPendingConsumerAdditionProp(
ctx, pendingProps[3].SpawnTime, pendingProps[3].ChainId)
require.False(t, found)
+ // Note that we do not check that `GetConsumerGenesis(ctx, pendingProps[3].ChainId)` returns `false` here because
+ // `pendingProps[3]` is an invalid proposal due to the chain id already existing so the consumer genesis also exists
+
+ // fifth proposal corresponds to an Opt-In chain with one opted-in validator and hence the proposal gets
+ // successfully executed
+ _, found = providerKeeper.GetPendingConsumerAdditionProp(
+ ctx, pendingProps[4].SpawnTime, pendingProps[4].ChainId)
+ require.False(t, found)
+ // sixth proposal was successfully executed and hence consumer genesis was created
+ _, found = providerKeeper.GetConsumerGenesis(ctx, pendingProps[4].ChainId)
+ require.True(t, found)
+
+ // test that Top N is set correctly
+ require.True(t, providerKeeper.IsTopN(ctx, "chain1"))
+ topN, found := providerKeeper.GetTopN(ctx, "chain1")
+ require.Equal(t, uint32(50), topN)
+
+ require.True(t, providerKeeper.IsOptIn(ctx, "chain4"))
}
// TestBeginBlockCCR tests BeginBlockCCR against the spec.
@@ -1040,6 +1122,7 @@ func TestBeginBlockCCR(t *testing.T) {
additionProp := testkeeper.GetTestConsumerAdditionProp()
additionProp.ChainId = prop.ChainId
additionProp.InitialHeight = clienttypes.NewHeight(2, 3)
+
err := providerKeeper.CreateConsumerClient(ctx, additionProp)
require.NoError(t, err)
err = providerKeeper.SetConsumerChain(ctx, "channelID")
@@ -1058,6 +1141,7 @@ func TestBeginBlockCCR(t *testing.T) {
//
// Test execution
//
+
providerKeeper.BeginBlockCCR(ctx)
// Only the 3rd (final) proposal is still stored as pending
diff --git a/x/ccv/provider/keeper/relay.go b/x/ccv/provider/keeper/relay.go
index 939f6d3995..f785d5d6b5 100644
--- a/x/ccv/provider/keeper/relay.go
+++ b/x/ccv/provider/keeper/relay.go
@@ -12,8 +12,8 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
- providertypes "github.com/cosmos/interchain-security/v4/x/ccv/provider/types"
- ccv "github.com/cosmos/interchain-security/v4/x/ccv/types"
+ providertypes "github.com/cosmos/interchain-security/v5/x/ccv/provider/types"
+ ccv "github.com/cosmos/interchain-security/v5/x/ccv/types"
)
// OnRecvVSCMaturedPacket handles a VSCMatured packet and returns a no-op result ack.
@@ -222,7 +222,17 @@ func (k Keeper) QueueVSCPackets(ctx sdk.Context) {
for _, chain := range k.GetAllConsumerChains(ctx) {
currentValidators := k.GetConsumerValSet(ctx, chain.ChainId)
- nextValidators := k.ComputeNextEpochConsumerValSet(ctx, chain.ChainId, bondedValidators)
+
+ if topN, found := k.GetTopN(ctx, chain.ChainId); found && topN > 0 {
+ // in a Top-N chain, we automatically opt in all validators that belong to the top N
+ minPower, err := k.ComputeMinPowerToOptIn(ctx, chain.ChainId, bondedValidators, topN)
+ if err == nil {
+ k.OptInTopNValidators(ctx, chain.ChainId, bondedValidators, minPower)
+ }
+ }
+
+ nextValidators := k.ComputeNextValidators(ctx, chain.ChainId, bondedValidators)
+
valUpdates := DiffValidators(currentValidators, nextValidators)
k.SetConsumerValSet(ctx, chain.ChainId, nextValidators)
@@ -328,6 +338,16 @@ func (k Keeper) OnRecvSlashPacket(
return ccv.V1Result, nil
}
+ // Check that the validator belongs to the consumer chain valset
+ if !k.IsConsumerValidator(ctx, chainID, providerConsAddr) {
+ k.Logger(ctx).Error("cannot jail validator %s that does not belong to consumer %s valset",
+ providerConsAddr.String(), chainID)
+ // drop packet but return a slash ack so that the consumer can send another slash packet
+ k.AppendSlashAck(ctx, chainID, consumerConsAddr.String())
+
+ return ccv.SlashPacketHandledResult, nil
+ }
+
meter := k.GetSlashMeter(ctx)
// Return bounce ack if meter is negative in value
if meter.IsNegative() {
diff --git a/x/ccv/provider/keeper/relay_test.go b/x/ccv/provider/keeper/relay_test.go
index 1e7347d3ce..2b50c695bc 100644
--- a/x/ccv/provider/keeper/relay_test.go
+++ b/x/ccv/provider/keeper/relay_test.go
@@ -12,17 +12,21 @@ import (
"cosmossdk.io/math"
+ codectypes "github.com/cosmos/cosmos-sdk/codec/types"
cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec"
+ cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
sdk "github.com/cosmos/cosmos-sdk/types"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
abci "github.com/cometbft/cometbft/abci/types"
- cryptotestutil "github.com/cosmos/interchain-security/v4/testutil/crypto"
- testkeeper "github.com/cosmos/interchain-security/v4/testutil/keeper"
- "github.com/cosmos/interchain-security/v4/x/ccv/provider/keeper"
- providertypes "github.com/cosmos/interchain-security/v4/x/ccv/provider/types"
- ccv "github.com/cosmos/interchain-security/v4/x/ccv/types"
+ "github.com/cosmos/interchain-security/v5/testutil/crypto"
+ cryptotestutil "github.com/cosmos/interchain-security/v5/testutil/crypto"
+ testkeeper "github.com/cosmos/interchain-security/v5/testutil/keeper"
+ "github.com/cosmos/interchain-security/v5/x/ccv/provider/keeper"
+ "github.com/cosmos/interchain-security/v5/x/ccv/provider/types"
+ providertypes "github.com/cosmos/interchain-security/v5/x/ccv/provider/types"
+ ccv "github.com/cosmos/interchain-security/v5/x/ccv/types"
)
// TestQueueVSCPackets tests queueing validator set updates.
@@ -121,12 +125,22 @@ func TestOnRecvDowntimeSlashPacket(t *testing.T) {
// Set a block height for the valset update id in the generated packet data
providerKeeper.SetValsetUpdateBlockHeight(ctx, packetData.ValsetUpdateId, uint64(15))
+ // Set consumer validator
+ providerKeeper.SetConsumerValidator(ctx, "chain-1", providertypes.ConsumerValidator{
+ ProviderConsAddr: packetData.Validator.Address,
+ })
+
// Set slash meter to negative value and assert a bounce ack is returned
providerKeeper.SetSlashMeter(ctx, math.NewInt(-5))
ackResult, err := executeOnRecvSlashPacket(t, &providerKeeper, ctx, "channel-1", 1, packetData)
require.Equal(t, ccv.SlashPacketBouncedResult, ackResult)
require.NoError(t, err)
+ // Set consumer validator
+ providerKeeper.SetConsumerValidator(ctx, "chain-2", providertypes.ConsumerValidator{
+ ProviderConsAddr: packetData.Validator.Address,
+ })
+
// Also bounced for chain-2
ackResult, err = executeOnRecvSlashPacket(t, &providerKeeper, ctx, "channel-2", 2, packetData)
require.Equal(t, ccv.SlashPacketBouncedResult, ackResult)
@@ -135,6 +149,9 @@ func TestOnRecvDowntimeSlashPacket(t *testing.T) {
// Now set slash meter to positive value and assert slash packet handled result is returned
providerKeeper.SetSlashMeter(ctx, math.NewInt(5))
+ // Set the consumer validator
+ providerKeeper.SetConsumerValidator(ctx, "chain-1", types.ConsumerValidator{ProviderConsAddr: packetData.Validator.Address})
+
// Mock call to GetEffectiveValPower, so that it returns 2.
providerAddr := providertypes.NewProviderConsAddress(packetData.Validator.Address)
calls := []*gomock.Call{
@@ -288,6 +305,7 @@ func TestValidateSlashPacket(t *testing.T) {
func TestHandleSlashPacket(t *testing.T) {
chainId := "consumer-id"
validVscID := uint64(234)
+
providerConsAddr := cryptotestutil.NewCryptoIdentityFromIntSeed(7842334).ProviderConsAddress()
consumerConsAddr := cryptotestutil.NewCryptoIdentityFromIntSeed(784987634).ConsumerConsAddress()
@@ -295,8 +313,9 @@ func TestHandleSlashPacket(t *testing.T) {
name string
packetData ccv.SlashPacketData
// The mocks that we expect to be called for the specified packet data.
- expectedCalls func(sdk.Context, testkeeper.MockedKeepers, ccv.SlashPacketData) []*gomock.Call
- expectedSlashAcksLen int
+ expectedCalls func(sdk.Context, testkeeper.MockedKeepers, ccv.SlashPacketData) []*gomock.Call
+ expectedSlashAcksLen int
+ expectedSlashAckConsumerConsAddress types.ConsumerConsAddress
}{
{
"unfound validator",
@@ -318,6 +337,7 @@ func TestHandleSlashPacket(t *testing.T) {
}
},
0,
+ consumerConsAddr,
},
{
"found, but tombstoned validator",
@@ -340,6 +360,7 @@ func TestHandleSlashPacket(t *testing.T) {
}
},
0,
+ consumerConsAddr,
},
{
"drop packet when infraction height not found",
@@ -363,6 +384,7 @@ func TestHandleSlashPacket(t *testing.T) {
}
},
0,
+ consumerConsAddr,
},
{
"full downtime packet handling, uses init chain height and non-jailed validator",
@@ -380,6 +402,7 @@ func TestHandleSlashPacket(t *testing.T) {
true) // expectJailing = true
},
1,
+ consumerConsAddr,
},
{
"full downtime packet handling, uses valid vscID and jailed validator",
@@ -397,39 +420,42 @@ func TestHandleSlashPacket(t *testing.T) {
false) // expectJailing = false, validator is already jailed.
},
1,
+ consumerConsAddr,
},
// Note: double-sign slash packet handling should not occur, see OnRecvSlashPacket.
}
for _, tc := range testCases {
+ t.Run(tc.name, func(t *testing.T) {
+ providerKeeper, ctx, ctrl, mocks := testkeeper.GetProviderKeeperAndCtx(
+ t, testkeeper.NewInMemKeeperParams(t))
- providerKeeper, ctx, ctrl, mocks := testkeeper.GetProviderKeeperAndCtx(
- t, testkeeper.NewInMemKeeperParams(t))
-
- // Setup expected mock calls
- gomock.InOrder(tc.expectedCalls(ctx, mocks, tc.packetData)...)
+ // Setup expected mock calls
+ gomock.InOrder(tc.expectedCalls(ctx, mocks, tc.packetData)...)
- // Setup init chain height and a single valid valset update ID to block height mapping.
- providerKeeper.SetInitChainHeight(ctx, chainId, 5)
- providerKeeper.SetValsetUpdateBlockHeight(ctx, validVscID, 99)
+ // Setup init chain height and a single valid valset update ID to block height mapping.
+ providerKeeper.SetInitChainHeight(ctx, chainId, 5)
+ providerKeeper.SetValsetUpdateBlockHeight(ctx, validVscID, 99)
- // Setup consumer address to provider address mapping.
- require.NotEmpty(t, tc.packetData.Validator.Address)
- providerKeeper.SetValidatorByConsumerAddr(ctx, chainId, consumerConsAddr, providerConsAddr)
+ // Setup consumer address to provider address mapping.
+ require.NotEmpty(t, tc.packetData.Validator.Address)
+ providerKeeper.SetValidatorByConsumerAddr(ctx, chainId, consumerConsAddr, providerConsAddr)
+ providerKeeper.SetConsumerValidator(ctx, chainId, types.ConsumerValidator{ProviderConsAddr: providerConsAddr.Address.Bytes()})
- // Execute method and assert expected mock calls.
- providerKeeper.HandleSlashPacket(ctx, chainId, tc.packetData)
+ // Execute method and assert expected mock calls.
+ providerKeeper.HandleSlashPacket(ctx, chainId, tc.packetData)
- require.Equal(t, tc.expectedSlashAcksLen, len(providerKeeper.GetSlashAcks(ctx, chainId)))
+ require.Equal(t, tc.expectedSlashAcksLen, len(providerKeeper.GetSlashAcks(ctx, chainId)))
- if tc.expectedSlashAcksLen == 1 {
- // must match the consumer address
- require.Equal(t, consumerConsAddr.String(), providerKeeper.GetSlashAcks(ctx, chainId)[0])
- require.NotEqual(t, providerConsAddr.String(), providerKeeper.GetSlashAcks(ctx, chainId)[0])
- require.NotEqual(t, providerConsAddr.String(), consumerConsAddr.String())
- }
+ if tc.expectedSlashAcksLen == 1 {
+ // must match the consumer address
+ require.Equal(t, tc.expectedSlashAckConsumerConsAddress.String(), providerKeeper.GetSlashAcks(ctx, chainId)[0])
+ require.NotEqual(t, providerConsAddr.String(), providerKeeper.GetSlashAcks(ctx, chainId)[0])
+ require.NotEqual(t, providerConsAddr.String(), consumerConsAddr.String())
+ }
- ctrl.Finish()
+ ctrl.Finish()
+ })
}
}
@@ -444,6 +470,10 @@ func TestHandleVSCMaturedPacket(t *testing.T) {
// Start first unbonding without any consumers registered
var unbondingOpId uint64 = 1
+ gomock.InOrder(
+ mocks.MockStakingKeeper.EXPECT().GetUnbondingType(ctx, unbondingOpId).Return(stakingtypes.UnbondingType_Undefined, false),
+ )
+
err := pk.Hooks().AfterUnbondingInitiated(ctx, unbondingOpId)
require.NoError(t, err)
// Check that no unbonding op was stored
@@ -454,12 +484,34 @@ func TestHandleVSCMaturedPacket(t *testing.T) {
pk.IncrementValidatorSetUpdateId(ctx)
require.Equal(t, uint64(2), pk.GetValidatorSetUpdateId(ctx))
- // Registered first consumer
+ // Register first consumer
pk.SetConsumerClientId(ctx, "chain-1", "client-1")
+ // Create 2 validators
+ vals := []stakingtypes.Validator{}
+ valsPk := []cryptotypes.PubKey{}
+ for i := 0; i < 2; i++ {
+ pubkey, err := cryptocodec.FromTmPubKeyInterface(cryptotestutil.NewCryptoIdentityFromIntSeed(54321 + i).TMCryptoPubKey())
+ require.NoError(t, err)
+ valsPk = append(valsPk, pubkey)
+ pkAny, err := codectypes.NewAnyWithValue(pubkey)
+ require.NoError(t, err)
+ vals = append(vals, stakingtypes.Validator{ConsensusPubkey: pkAny})
+ }
+
+ // Opt-in one validator to consumer
+ pk.SetConsumerValidator(ctx, "chain-1", types.ConsumerValidator{ProviderConsAddr: valsPk[0].Address()})
+
// Start second unbonding
unbondingOpId = 2
gomock.InOrder(
+ mocks.MockStakingKeeper.EXPECT().GetUnbondingType(ctx, unbondingOpId).Return(stakingtypes.UnbondingType_UnbondingDelegation, true),
+ mocks.MockStakingKeeper.EXPECT().GetUnbondingDelegationByUnbondingID(ctx, unbondingOpId).Return(
+ stakingtypes.UnbondingDelegation{
+ ValidatorAddress: sdk.ValAddress([]byte{1}).String(),
+ }, true),
+ mocks.MockStakingKeeper.EXPECT().GetValidator(ctx, sdk.ValAddress([]byte{1})).
+ Return(vals[0], true),
mocks.MockStakingKeeper.EXPECT().PutUnbondingOnHold(ctx, unbondingOpId).Return(nil),
)
err = pk.Hooks().AfterUnbondingInitiated(ctx, unbondingOpId)
@@ -483,10 +535,21 @@ func TestHandleVSCMaturedPacket(t *testing.T) {
// Registered second consumer
pk.SetConsumerClientId(ctx, "chain-2", "client-2")
+ // Opt-in both validators to second consumer
+ pk.SetConsumerValidator(ctx, "chain-2", types.ConsumerValidator{ProviderConsAddr: valsPk[0].Address()})
+ pk.SetConsumerValidator(ctx, "chain-2", types.ConsumerValidator{ProviderConsAddr: valsPk[1].Address()})
+
// Start third and fourth unbonding
unbondingOpIds := []uint64{3, 4}
for _, id := range unbondingOpIds {
gomock.InOrder(
+ mocks.MockStakingKeeper.EXPECT().GetUnbondingType(ctx, id).Return(stakingtypes.UnbondingType_Redelegation, true),
+ mocks.MockStakingKeeper.EXPECT().GetRedelegationByUnbondingID(ctx, id).Return(
+ stakingtypes.Redelegation{
+ ValidatorSrcAddress: sdk.ValAddress([]byte{1}).String(),
+ }, true),
+ mocks.MockStakingKeeper.EXPECT().GetValidator(ctx, sdk.ValAddress([]byte{1})).
+ Return(vals[0], true),
mocks.MockStakingKeeper.EXPECT().PutUnbondingOnHold(ctx, id).Return(nil),
)
err = pk.Hooks().AfterUnbondingInitiated(ctx, id)
@@ -507,6 +570,33 @@ func TestHandleVSCMaturedPacket(t *testing.T) {
require.Equal(t, unbondingOpIds, ids)
}
+ // Increment vscID
+ pk.IncrementValidatorSetUpdateId(ctx)
+ require.Equal(t, uint64(4), pk.GetValidatorSetUpdateId(ctx))
+
+ // Start fith unbonding
+ unbondingOpId = 5
+ gomock.InOrder(
+ mocks.MockStakingKeeper.EXPECT().GetUnbondingType(ctx, unbondingOpId).Return(stakingtypes.UnbondingType_ValidatorUnbonding, true),
+ mocks.MockStakingKeeper.EXPECT().GetValidatorByUnbondingID(ctx, unbondingOpId).Return(
+ stakingtypes.Validator{
+ OperatorAddress: sdk.ValAddress([]byte{1}).String(),
+ }, true),
+ mocks.MockStakingKeeper.EXPECT().GetValidator(ctx, sdk.ValAddress([]byte{1})).
+ Return(vals[1], true),
+ mocks.MockStakingKeeper.EXPECT().PutUnbondingOnHold(ctx, unbondingOpId).Return(nil),
+ )
+ err = pk.Hooks().AfterUnbondingInitiated(ctx, unbondingOpId)
+ require.NoError(t, err)
+
+ // Check that an unbonding op was stored for chain-2 only
+ // since it's the only consumer the unbonding validator has opted-in to
+ expectedChains = []string{"chain-2"}
+ unbondingOp, found = pk.GetUnbondingOp(ctx, unbondingOpId)
+ require.True(t, found)
+ require.Equal(t, unbondingOpId, unbondingOp.Id)
+ require.Equal(t, expectedChains, unbondingOp.UnbondingConsumerChains)
+
// Handle VSCMatured packet from chain-1 for vscID 1.
// Note that no VSCPacket was sent as the chain was not yet registered,
// but the code should still work
@@ -658,6 +748,10 @@ func TestEndBlockVSU(t *testing.T) {
providerKeeper, ctx, ctrl, mocks := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t))
defer ctrl.Finish()
+ chainID := "chainID"
+
+ providerKeeper.SetTopN(ctx, chainID, 100)
+
// 10 blocks constitute an epoch
params := providertypes.DefaultParams()
params.BlocksPerEpoch = 10
@@ -665,34 +759,116 @@ func TestEndBlockVSU(t *testing.T) {
// create 4 sample lastValidators
var lastValidators []stakingtypes.Validator
+ var valAddresses []sdk.ValAddress
for i := 0; i < 4; i++ {
- lastValidators = append(lastValidators, cryptotestutil.NewCryptoIdentityFromIntSeed(i).SDKStakingValidator())
+ validator := crypto.NewCryptoIdentityFromIntSeed(i).SDKStakingValidator()
+ lastValidators = append(lastValidators, validator)
+ valAddresses = append(valAddresses, validator.GetOperator())
+ mocks.MockStakingKeeper.EXPECT().GetLastValidatorPower(gomock.Any(), validator.GetOperator()).Return(int64(i + 1)).AnyTimes()
}
+
mocks.MockStakingKeeper.EXPECT().GetLastValidators(gomock.Any()).Return(lastValidators).AnyTimes()
- mocks.MockStakingKeeper.EXPECT().GetLastValidatorPower(gomock.Any(), gomock.Any()).Return(int64(2)).AnyTimes()
// set a sample client for a consumer chain so that `GetAllConsumerChains` in `QueueVSCPackets` iterates at least once
- providerKeeper.SetConsumerClientId(ctx, "chainID", "clientID")
+ providerKeeper.SetConsumerClientId(ctx, chainID, "clientID")
// with block height of 1 we do not expect any queueing of VSC packets
ctx = ctx.WithBlockHeight(1)
providerKeeper.EndBlockVSU(ctx)
- require.Equal(t, 0, len(providerKeeper.GetPendingVSCPackets(ctx, "chainID")))
+ require.Equal(t, 0, len(providerKeeper.GetPendingVSCPackets(ctx, chainID)))
// with block height of 5 we do not expect any queueing of VSC packets
ctx = ctx.WithBlockHeight(5)
providerKeeper.EndBlockVSU(ctx)
- require.Equal(t, 0, len(providerKeeper.GetPendingVSCPackets(ctx, "chainID")))
+ require.Equal(t, 0, len(providerKeeper.GetPendingVSCPackets(ctx, chainID)))
// with block height of 10 we expect the queueing of one VSC packet
ctx = ctx.WithBlockHeight(10)
providerKeeper.EndBlockVSU(ctx)
- require.Equal(t, 1, len(providerKeeper.GetPendingVSCPackets(ctx, "chainID")))
+ require.Equal(t, 1, len(providerKeeper.GetPendingVSCPackets(ctx, chainID)))
// With block height of 15 we expect no additional queueing of a VSC packet.
// Note that the pending VSC packet is still there because `SendVSCPackets` does not send the packet. We
// need to mock channels, etc. for this to work, and it's out of scope for this test.
ctx = ctx.WithBlockHeight(15)
providerKeeper.EndBlockVSU(ctx)
- require.Equal(t, 1, len(providerKeeper.GetPendingVSCPackets(ctx, "chainID")))
+ require.Equal(t, 1, len(providerKeeper.GetPendingVSCPackets(ctx, chainID)))
+}
+
+// TestQueueVSCPacketsWithPowerCapping tests queueing validator set updates with power capping
+func TestQueueVSCPacketsWithPowerCapping(t *testing.T) {
+ providerKeeper, ctx, ctrl, mocks := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t))
+ defer ctrl.Finish()
+
+ providerKeeper.SetValidatorSetUpdateId(ctx, 1)
+
+ valA := createStakingValidator(ctx, mocks, 1, 1) // 3.125% of the total voting power
+ valAConsAddr, _ := valA.GetConsAddr()
+ valAPubKey, _ := valA.TmConsPublicKey()
+ mocks.MockStakingKeeper.EXPECT().GetValidatorByConsAddr(ctx, valAConsAddr).Return(valA, true).AnyTimes()
+ valB := createStakingValidator(ctx, mocks, 2, 3) // 9.375% of the total voting power
+ valBConsAddr, _ := valB.GetConsAddr()
+ valBPubKey, _ := valB.TmConsPublicKey()
+ mocks.MockStakingKeeper.EXPECT().GetValidatorByConsAddr(ctx, valBConsAddr).Return(valB, true).AnyTimes()
+ valC := createStakingValidator(ctx, mocks, 3, 4) // 12.5% of the total voting power
+ valCConsAddr, _ := valC.GetConsAddr()
+ valCPubKey, _ := valC.TmConsPublicKey()
+ mocks.MockStakingKeeper.EXPECT().GetValidatorByConsAddr(ctx, valCConsAddr).Return(valC, true).AnyTimes()
+ valD := createStakingValidator(ctx, mocks, 4, 8) // 25% of the total voting power
+ valDConsAddr, _ := valD.GetConsAddr()
+ mocks.MockStakingKeeper.EXPECT().GetValidatorByConsAddr(ctx, valDConsAddr).Return(valD, true).AnyTimes()
+ valE := createStakingValidator(ctx, mocks, 5, 16) // 50% of the total voting power
+ valEConsAddr, _ := valE.GetConsAddr()
+ valEPubKey, _ := valE.TmConsPublicKey()
+ mocks.MockStakingKeeper.EXPECT().GetValidatorByConsAddr(ctx, valEConsAddr).Return(valE, true).AnyTimes()
+
+ mocks.MockStakingKeeper.EXPECT().GetLastValidators(ctx).Return([]stakingtypes.Validator{valA, valB, valC, valD, valE}).AnyTimes()
+
+ // add a consumer chain
+ providerKeeper.SetConsumerClientId(ctx, "chainID", "clientID")
+
+ providerKeeper.SetTopN(ctx, "chainID", 50) // would opt in E
+
+ // opt in all validators
+ providerKeeper.SetOptedIn(ctx, "chainID", providertypes.NewProviderConsAddress(valAConsAddr))
+ providerKeeper.SetOptedIn(ctx, "chainID", providertypes.NewProviderConsAddress(valBConsAddr))
+ providerKeeper.SetOptedIn(ctx, "chainID", providertypes.NewProviderConsAddress(valCConsAddr))
+ providerKeeper.SetOptedIn(ctx, "chainID", providertypes.NewProviderConsAddress(valDConsAddr))
+
+ // denylist validator D
+ providerKeeper.SetDenylist(ctx, "chainID", providertypes.NewProviderConsAddress(valDConsAddr))
+
+ // set a power-capping of 40%
+ providerKeeper.SetValidatorsPowerCap(ctx, "chainID", 40)
+
+ providerKeeper.QueueVSCPackets(ctx)
+
+ actualQueuedVSCPackets := providerKeeper.GetPendingVSCPackets(ctx, "chainID")
+ expectedQueuedVSCPackets := []ccv.ValidatorSetChangePacketData{
+ ccv.NewValidatorSetChangePacketData(
+ []abci.ValidatorUpdate{
+ // validator D is not here because it was denylisted
+ // powers have changed because of power capping
+ {
+ PubKey: valEPubKey,
+ Power: 9,
+ },
+ {
+ PubKey: valCPubKey,
+ Power: 6,
+ },
+ {
+ PubKey: valBPubKey,
+ Power: 5,
+ },
+ {
+ PubKey: valAPubKey,
+ Power: 4,
+ },
+ },
+ 1,
+ nil),
+ }
+
+ require.Equal(t, expectedQueuedVSCPackets, actualQueuedVSCPackets)
}
diff --git a/x/ccv/provider/keeper/throttle.go b/x/ccv/provider/keeper/throttle.go
index b7e7fd5941..b1da78db0f 100644
--- a/x/ccv/provider/keeper/throttle.go
+++ b/x/ccv/provider/keeper/throttle.go
@@ -10,7 +10,7 @@ import (
tmtypes "github.com/cometbft/cometbft/types"
- providertypes "github.com/cosmos/interchain-security/v4/x/ccv/provider/types"
+ providertypes "github.com/cosmos/interchain-security/v5/x/ccv/provider/types"
)
// Obtains the effective validator power relevant to a validator consensus address.
diff --git a/x/ccv/provider/keeper/throttle_legacy.go b/x/ccv/provider/keeper/throttle_legacy.go
index 6f347b8f60..c14c994e84 100644
--- a/x/ccv/provider/keeper/throttle_legacy.go
+++ b/x/ccv/provider/keeper/throttle_legacy.go
@@ -5,8 +5,8 @@ import (
sdktypes "github.com/cosmos/cosmos-sdk/types"
- providertypes "github.com/cosmos/interchain-security/v4/x/ccv/provider/types"
- ccvtypes "github.com/cosmos/interchain-security/v4/x/ccv/types"
+ providertypes "github.com/cosmos/interchain-security/v5/x/ccv/provider/types"
+ ccvtypes "github.com/cosmos/interchain-security/v5/x/ccv/types"
)
// Pending packet data type enum, used to encode the type of packet data stored at each entry in the mutual queue.
diff --git a/x/ccv/provider/keeper/throttle_test.go b/x/ccv/provider/keeper/throttle_test.go
index 478ec0f235..5a315e5ec9 100644
--- a/x/ccv/provider/keeper/throttle_test.go
+++ b/x/ccv/provider/keeper/throttle_test.go
@@ -13,8 +13,8 @@ import (
tmtypes "github.com/cometbft/cometbft/types"
- testkeeper "github.com/cosmos/interchain-security/v4/testutil/keeper"
- providertypes "github.com/cosmos/interchain-security/v4/x/ccv/provider/types"
+ testkeeper "github.com/cosmos/interchain-security/v5/testutil/keeper"
+ providertypes "github.com/cosmos/interchain-security/v5/x/ccv/provider/types"
)
// TestSlashMeterReplenishment tests the CheckForSlashMeterReplenishment, ReplenishSlashMeter,
diff --git a/x/ccv/provider/keeper/validator_set_update.go b/x/ccv/provider/keeper/validator_set_update.go
index adaee853e8..42016708a5 100644
--- a/x/ccv/provider/keeper/validator_set_update.go
+++ b/x/ccv/provider/keeper/validator_set_update.go
@@ -8,7 +8,7 @@ import (
abci "github.com/cometbft/cometbft/abci/types"
- "github.com/cosmos/interchain-security/v4/x/ccv/provider/types"
+ "github.com/cosmos/interchain-security/v5/x/ccv/provider/types"
)
// SetConsumerValidator sets provided consumer `validator` on the consumer chain with `chainID`
@@ -26,6 +26,15 @@ func (k Keeper) SetConsumerValidator(
store.Set(types.ConsumerValidatorKey(chainID, validator.ProviderConsAddr), bz)
}
+// SetConsumerValSet resets the current consumer validators with the `nextValidators` computed by
+// `FilterValidators` and hence this method should only be called after `FilterValidators` has completed.
+func (k Keeper) SetConsumerValSet(ctx sdk.Context, chainID string, nextValidators []types.ConsumerValidator) {
+ k.DeleteConsumerValSet(ctx, chainID)
+ for _, val := range nextValidators {
+ k.SetConsumerValidator(ctx, chainID, val)
+ }
+}
+
// DeleteConsumerValidator removes consumer validator with `providerAddr` address
func (k Keeper) DeleteConsumerValidator(
ctx sdk.Context,
@@ -57,11 +66,7 @@ func (k Keeper) DeleteConsumerValSet(
// IsConsumerValidator returns `true` if the consumer validator with `providerAddr` exists for chain `chainID`
// and `false` otherwise
-func (k Keeper) IsConsumerValidator(
- ctx sdk.Context,
- chainID string,
- providerAddr types.ProviderConsAddress,
-) bool {
+func (k Keeper) IsConsumerValidator(ctx sdk.Context, chainID string, providerAddr types.ProviderConsAddress) bool {
store := ctx.KVStore(k.storeKey)
return store.Get(types.ConsumerValidatorKey(chainID, providerAddr.ToSdkConsAddr())) != nil
}
@@ -88,51 +93,6 @@ func (k Keeper) GetConsumerValSet(
return validators
}
-// ComputeNextEpochConsumerValSet returns the next validator set that is responsible for validating consumer
-// chain `chainID`, based on the bonded validators.
-func (k Keeper) ComputeNextEpochConsumerValSet(
- ctx sdk.Context,
- chainID string,
- bondedValidators []stakingtypes.Validator,
-) []types.ConsumerValidator {
- var nextValidators []types.ConsumerValidator
- for _, val := range bondedValidators {
- // get next voting power and the next consumer public key
- nextPower := k.stakingKeeper.GetLastValidatorPower(ctx, val.GetOperator())
- consAddr, err := val.GetConsAddr()
- if err != nil {
- // this should never happen but is recoverable if we exclude this validator from the `nextValidators`
- k.Logger(ctx).Error("could not get consensus address of validator",
- "validator", val.GetOperator().String(),
- "error", err)
- continue
- }
- nextConsumerPublicKey, foundConsumerPublicKey := k.GetValidatorConsumerPubKey(ctx, chainID, types.NewProviderConsAddress(consAddr))
- if !foundConsumerPublicKey {
- // if no consumer key assigned then use the validator's key itself
- k.Logger(ctx).Info("could not retrieve public key for validator on consumer chain because"+
- " the validator did not assign a new consumer key",
- "validator", val.GetOperator().String(),
- "chainID", chainID)
- nextConsumerPublicKey, err = val.TmConsPublicKey()
- if err != nil {
- // this should never happen and might not be recoverable because without the public key
- // we cannot generate a validator update
- panic(fmt.Errorf("could not retrieve validator's (%+v) public key: %w", val, err))
- }
- }
-
- nextValidator := types.ConsumerValidator{
- ProviderConsAddr: consAddr,
- Power: nextPower,
- ConsumerPublicKey: &nextConsumerPublicKey,
- }
- nextValidators = append(nextValidators, nextValidator)
- }
-
- return nextValidators
-}
-
// DiffValidators compares the current and the next epoch's consumer validators and returns the `ValidatorUpdate` diff
// needed by CometBFT to update the validator set on a chain.
func DiffValidators(
@@ -174,11 +134,58 @@ func DiffValidators(
return updates
}
-// SetConsumerValSet resets the current consumer validators with the `nextValidators` computed by
-// `ComputeNextEpochConsumerValSet` and hence this method should only be called after `ComputeNextEpochConsumerValSet` has completed.
-func (k Keeper) SetConsumerValSet(ctx sdk.Context, chainID string, nextValidators []types.ConsumerValidator) {
- k.DeleteConsumerValSet(ctx, chainID)
- for _, val := range nextValidators {
- k.SetConsumerValidator(ctx, chainID, val)
+// CreateConsumerValidator creates a consumer validator for `chainID` from the given staking `validator`
+func (k Keeper) CreateConsumerValidator(ctx sdk.Context, chainID string, validator stakingtypes.Validator) (types.ConsumerValidator, error) {
+ power := k.stakingKeeper.GetLastValidatorPower(ctx, validator.GetOperator())
+ consAddr, err := validator.GetConsAddr()
+ if err != nil {
+ return types.ConsumerValidator{}, fmt.Errorf("could not retrieve validator's (%+v) consensus address: %w",
+ validator, err)
+ }
+
+ consumerPublicKey, foundConsumerPublicKey := k.GetValidatorConsumerPubKey(ctx, chainID, types.NewProviderConsAddress(consAddr))
+ if !foundConsumerPublicKey {
+ consumerPublicKey, err = validator.TmConsPublicKey()
+ if err != nil {
+ return types.ConsumerValidator{}, fmt.Errorf("could not retrieve validator's (%+v) public key: %w", validator, err)
+ }
+ }
+
+ return types.ConsumerValidator{
+ ProviderConsAddr: consAddr,
+ Power: power,
+ ConsumerPublicKey: &consumerPublicKey,
+ }, nil
+}
+
+// FilterValidators filters the provided `bondedValidators` according to `predicate` and returns
+// the filtered set.
+func (k Keeper) FilterValidators(
+ ctx sdk.Context,
+ chainID string,
+ bondedValidators []stakingtypes.Validator,
+ predicate func(providerAddr types.ProviderConsAddress) bool,
+) []types.ConsumerValidator {
+ var nextValidators []types.ConsumerValidator
+ for _, val := range bondedValidators {
+ consAddr, err := val.GetConsAddr()
+ if err != nil {
+ continue
+ }
+
+ if predicate(types.NewProviderConsAddress(consAddr)) {
+ nextValidator, err := k.CreateConsumerValidator(ctx, chainID, val)
+ if err != nil {
+ // this should never happen but is recoverable if we exclude this validator from the next validator set
+ k.Logger(ctx).Error("could not create consumer validator",
+ "validator", val.GetOperator().String(),
+ "error", err)
+ continue
+ }
+
+ nextValidators = append(nextValidators, nextValidator)
+ }
}
+
+ return nextValidators
}
diff --git a/x/ccv/provider/keeper/validator_set_update_test.go b/x/ccv/provider/keeper/validator_set_update_test.go
index 3c6441bbc5..9da3039b14 100644
--- a/x/ccv/provider/keeper/validator_set_update_test.go
+++ b/x/ccv/provider/keeper/validator_set_update_test.go
@@ -16,10 +16,10 @@ import (
"github.com/cometbft/cometbft/crypto/ed25519"
"github.com/cometbft/cometbft/proto/tendermint/crypto"
- cryptotestutil "github.com/cosmos/interchain-security/v4/testutil/crypto"
- testkeeper "github.com/cosmos/interchain-security/v4/testutil/keeper"
- "github.com/cosmos/interchain-security/v4/x/ccv/provider/keeper"
- "github.com/cosmos/interchain-security/v4/x/ccv/provider/types"
+ cryptotestutil "github.com/cosmos/interchain-security/v5/testutil/crypto"
+ testkeeper "github.com/cosmos/interchain-security/v5/testutil/keeper"
+ "github.com/cosmos/interchain-security/v5/x/ccv/provider/keeper"
+ "github.com/cosmos/interchain-security/v5/x/ccv/provider/types"
)
// TestConsumerValidator tests the `SetConsumerValidator`, `IsConsumerValidator`, and `DeleteConsumerValidator` methods
@@ -110,62 +110,22 @@ func createConsumerValidator(index int, power int64, seed int) (types.ConsumerVa
}, publicKey
}
-func TestComputeNextEpochConsumerValSet(t *testing.T) {
- providerKeeper, ctx, ctrl, mocks := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t))
- defer ctrl.Finish()
-
- chainID := "chainID"
-
- // helper function to generate a validator with the given power and with a provider address based on index
- createStakingValidator := func(ctx sdk.Context, mocks testkeeper.MockedKeepers, index int, power int64) stakingtypes.Validator {
- providerConsPubKey := ed25519.GenPrivKeyFromSecret([]byte{byte(index)}).PubKey()
- consAddr := sdk.ConsAddress(providerConsPubKey.Address())
- providerAddr := types.NewProviderConsAddress(consAddr)
- pk, _ := cryptocodec.FromTmPubKeyInterface(providerConsPubKey)
- pkAny, _ := codectypes.NewAnyWithValue(pk)
-
- var providerValidatorAddr sdk.ValAddress = providerAddr.Address.Bytes()
-
- mocks.MockStakingKeeper.EXPECT().
- GetLastValidatorPower(ctx, providerValidatorAddr).Return(power).AnyTimes()
-
- return stakingtypes.Validator{
- OperatorAddress: providerValidatorAddr.String(),
- ConsensusPubkey: pkAny,
- }
+// createStakingValidator helper function to generate a validator with the given power and with a provider address based on index
+func createStakingValidator(ctx sdk.Context, mocks testkeeper.MockedKeepers, index int, power int64) stakingtypes.Validator {
+ providerConsPubKey := ed25519.GenPrivKeyFromSecret([]byte{byte(index)}).PubKey()
+ consAddr := sdk.ConsAddress(providerConsPubKey.Address())
+ providerAddr := types.NewProviderConsAddress(consAddr)
+ pk, _ := cryptocodec.FromTmPubKeyInterface(providerConsPubKey)
+ pkAny, _ := codectypes.NewAnyWithValue(pk)
+ providerValidatorAddr := sdk.ValAddress(providerAddr.Address.Bytes())
+
+ mocks.MockStakingKeeper.EXPECT().
+ GetLastValidatorPower(ctx, providerValidatorAddr).Return(power).AnyTimes()
+
+ return stakingtypes.Validator{
+ OperatorAddress: providerValidatorAddr.String(),
+ ConsensusPubkey: pkAny,
}
-
- // no consumer validators returned if we have no bonded validators
- require.Empty(t, providerKeeper.ComputeNextEpochConsumerValSet(ctx, chainID, []stakingtypes.Validator{}))
-
- var expectedValidators []types.ConsumerValidator
-
- // create a staking validator A that has not set a consumer public key
- valA := createStakingValidator(ctx, mocks, 1, 1)
- // because validator A has no consumer key set, the `ConsumerPublicKey` we expect is the key on the provider chain
- valAConsAddr, _ := valA.GetConsAddr()
- valAPublicKey, _ := valA.TmConsPublicKey()
- expectedValidators = append(expectedValidators, types.ConsumerValidator{
- ProviderConsAddr: types.NewProviderConsAddress(valAConsAddr).Address.Bytes(),
- Power: 1,
- ConsumerPublicKey: &valAPublicKey,
- })
-
- // create a staking validator B that has set a consumer public key
- valB := createStakingValidator(ctx, mocks, 2, 2)
- // validator B has set a consumer key, the `ConsumerPublicKey` we expect is the key set by `SetValidatorConsumerPubKey`
- valBConsumerKey := cryptotestutil.NewCryptoIdentityFromIntSeed(1).TMProtoCryptoPublicKey()
- valBConsAddr, _ := valB.GetConsAddr()
- providerKeeper.SetValidatorConsumerPubKey(ctx, chainID, types.NewProviderConsAddress(valBConsAddr), valBConsumerKey)
- expectedValidators = append(expectedValidators, types.ConsumerValidator{
- ProviderConsAddr: types.NewProviderConsAddress(valBConsAddr).Address.Bytes(),
- Power: 2,
- ConsumerPublicKey: &valBConsumerKey,
- })
-
- bondedValidators := []stakingtypes.Validator{valA, valB}
- actualValidators := providerKeeper.ComputeNextEpochConsumerValSet(ctx, "chainID", bondedValidators)
- require.Equal(t, expectedValidators, actualValidators)
}
func TestDiff(t *testing.T) {
@@ -366,3 +326,153 @@ func TestSetConsumerValSet(t *testing.T) {
sortValidators(nextCurrentValidators)
require.Equal(t, nextValidators, nextCurrentValidators)
}
+
+func TestComputeNextEpochConsumerValSetConsiderAll(t *testing.T) {
+ providerKeeper, ctx, ctrl, mocks := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t))
+ defer ctrl.Finish()
+
+ chainID := "chainID"
+
+ // no consumer validators returned if we have no bonded validators
+ considerAll := func(providerAddr types.ProviderConsAddress) bool { return true }
+ require.Empty(t, providerKeeper.FilterValidators(ctx, chainID, []stakingtypes.Validator{}, considerAll))
+
+ var expectedValidators []types.ConsumerValidator
+
+ // create a staking validator A that has not set a consumer public key
+ valA := createStakingValidator(ctx, mocks, 1, 1)
+ // because validator A has no consumer key set, the `ConsumerPublicKey` we expect is the key on the provider chain
+ valAConsAddr, _ := valA.GetConsAddr()
+ valAPublicKey, _ := valA.TmConsPublicKey()
+ expectedValidators = append(expectedValidators, types.ConsumerValidator{
+ ProviderConsAddr: types.NewProviderConsAddress(valAConsAddr).Address.Bytes(),
+ Power: 1,
+ ConsumerPublicKey: &valAPublicKey,
+ })
+
+ // create a staking validator B that has set a consumer public key
+ valB := createStakingValidator(ctx, mocks, 2, 2)
+ // validator B has set a consumer key, the `ConsumerPublicKey` we expect is the key set by `SetValidatorConsumerPubKey`
+ valBConsumerKey := cryptotestutil.NewCryptoIdentityFromIntSeed(1).TMProtoCryptoPublicKey()
+ valBConsAddr, _ := valB.GetConsAddr()
+ providerKeeper.SetValidatorConsumerPubKey(ctx, chainID, types.NewProviderConsAddress(valBConsAddr), valBConsumerKey)
+ expectedValidators = append(expectedValidators, types.ConsumerValidator{
+ ProviderConsAddr: types.NewProviderConsAddress(valBConsAddr).Address.Bytes(),
+ Power: 2,
+ ConsumerPublicKey: &valBConsumerKey,
+ })
+
+ bondedValidators := []stakingtypes.Validator{valA, valB}
+ actualValidators := providerKeeper.FilterValidators(ctx, chainID, bondedValidators, considerAll)
+ require.Equal(t, expectedValidators, actualValidators)
+}
+
+func TestComputeNextEpochConsumerValSetConsiderOnlyOptIn(t *testing.T) {
+ providerKeeper, ctx, ctrl, mocks := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t))
+ defer ctrl.Finish()
+
+ chainID := "chainID"
+
+ // no consumer validators returned if we have no opted-in validators
+ require.Empty(t, providerKeeper.FilterValidators(ctx, chainID, []stakingtypes.Validator{},
+ func(providerAddr types.ProviderConsAddress) bool {
+ return providerKeeper.IsOptedIn(ctx, chainID, providerAddr)
+ }))
+
+ var expectedValidators []types.ConsumerValidator
+
+ // create a staking validator A that has not set a consumer public key
+ valA := createStakingValidator(ctx, mocks, 1, 1)
+ // because validator A has no consumer key set, the `ConsumerPublicKey` we expect is the key on the provider chain
+ valAConsAddr, _ := valA.GetConsAddr()
+ valAPublicKey, _ := valA.TmConsPublicKey()
+ expectedValAConsumerValidator := types.ConsumerValidator{
+ ProviderConsAddr: types.NewProviderConsAddress(valAConsAddr).Address.Bytes(),
+ Power: 1,
+ ConsumerPublicKey: &valAPublicKey,
+ }
+ expectedValidators = append(expectedValidators, expectedValAConsumerValidator)
+
+ // create a staking validator B that has set a consumer public key
+ valB := createStakingValidator(ctx, mocks, 2, 2)
+ // validator B has set a consumer key, the `ConsumerPublicKey` we expect is the key set by `SetValidatorConsumerPubKey`
+ valBConsumerKey := cryptotestutil.NewCryptoIdentityFromIntSeed(1).TMProtoCryptoPublicKey()
+ valBConsAddr, _ := valB.GetConsAddr()
+ providerKeeper.SetValidatorConsumerPubKey(ctx, chainID, types.NewProviderConsAddress(valBConsAddr), valBConsumerKey)
+ expectedValBConsumerValidator := types.ConsumerValidator{
+ ProviderConsAddr: types.NewProviderConsAddress(valBConsAddr).Address.Bytes(),
+ Power: 2,
+ ConsumerPublicKey: &valBConsumerKey,
+ }
+ expectedValidators = append(expectedValidators, expectedValBConsumerValidator)
+
+ // opt in validators A and B with 0 power and no consumer public keys
+ providerKeeper.SetOptedIn(ctx, chainID, types.NewProviderConsAddress(valAConsAddr))
+ providerKeeper.SetOptedIn(ctx, chainID, types.NewProviderConsAddress(valBConsAddr))
+
+ // the expected actual validators are the opted-in validators but with the correct power and consumer public keys set
+ bondedValidators := []stakingtypes.Validator{valA, valB}
+ actualValidators := providerKeeper.FilterValidators(ctx, "chainID", bondedValidators,
+ func(providerAddr types.ProviderConsAddress) bool {
+ return providerKeeper.IsOptedIn(ctx, chainID, providerAddr)
+ })
+
+ // sort validators first to be able to compare
+ sortValidators := func(validators []types.ConsumerValidator) {
+ sort.Slice(validators, func(i, j int) bool {
+ return bytes.Compare(validators[i].ProviderConsAddr, validators[j].ProviderConsAddr) < 0
+ })
+ }
+
+ sortValidators(actualValidators)
+ sortValidators(expectedValidators)
+ require.Equal(t, expectedValidators, actualValidators)
+
+ // create a staking validator C that is not opted in, hence `expectedValidators` remains the same
+ valC := createStakingValidator(ctx, mocks, 3, 3)
+ bondedValidators = []stakingtypes.Validator{valA, valB, valC}
+ actualValidators = providerKeeper.FilterValidators(ctx, "chainID", bondedValidators,
+ func(providerAddr types.ProviderConsAddress) bool {
+ return providerKeeper.IsOptedIn(ctx, chainID, providerAddr)
+ })
+
+ sortValidators(actualValidators)
+ sortValidators(expectedValidators)
+ require.Equal(t, expectedValidators, actualValidators)
+}
+
+func TestCreateConsumerValidator(t *testing.T) {
+ providerKeeper, ctx, ctrl, mocks := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t))
+ defer ctrl.Finish()
+
+ chainID := "chainID"
+
+ // create a validator which has set a consumer public key
+ valA := createStakingValidator(ctx, mocks, 0, 1)
+ valAConsumerKey := cryptotestutil.NewCryptoIdentityFromIntSeed(1).TMProtoCryptoPublicKey()
+ valAConsAddr, _ := valA.GetConsAddr()
+ valAProviderConsAddr := types.NewProviderConsAddress(valAConsAddr)
+ providerKeeper.SetValidatorConsumerPubKey(ctx, chainID, valAProviderConsAddr, valAConsumerKey)
+ actualConsumerValidatorA, err := providerKeeper.CreateConsumerValidator(ctx, chainID, valA)
+ expectedConsumerValidatorA := types.ConsumerValidator{
+ ProviderConsAddr: valAProviderConsAddr.ToSdkConsAddr(),
+ Power: 1,
+ ConsumerPublicKey: &valAConsumerKey,
+ }
+ require.Equal(t, expectedConsumerValidatorA, actualConsumerValidatorA)
+ require.NoError(t, err)
+
+ // create a validator which has not set a consumer public key
+ valB := createStakingValidator(ctx, mocks, 1, 2)
+ valBConsAddr, _ := valB.GetConsAddr()
+ valBProviderConsAddr := types.NewProviderConsAddress(valBConsAddr)
+ valBPublicKey, _ := valB.TmConsPublicKey()
+ actualConsumerValidatorB, err := providerKeeper.CreateConsumerValidator(ctx, chainID, valB)
+ expectedConsumerValidatorB := types.ConsumerValidator{
+ ProviderConsAddr: valBProviderConsAddr.ToSdkConsAddr(),
+ Power: 2,
+ ConsumerPublicKey: &valBPublicKey,
+ }
+ require.Equal(t, expectedConsumerValidatorB, actualConsumerValidatorB)
+ require.NoError(t, err)
+}
diff --git a/x/ccv/provider/migrations/migrator.go b/x/ccv/provider/migrations/migrator.go
index 7c52ee27ce..ea6e9e00d5 100644
--- a/x/ccv/provider/migrations/migrator.go
+++ b/x/ccv/provider/migrations/migrator.go
@@ -4,9 +4,10 @@ import (
sdktypes "github.com/cosmos/cosmos-sdk/types"
paramtypes "github.com/cosmos/cosmos-sdk/x/params/types"
- providerkeeper "github.com/cosmos/interchain-security/v4/x/ccv/provider/keeper"
- v3 "github.com/cosmos/interchain-security/v4/x/ccv/provider/migrations/v3"
- v4 "github.com/cosmos/interchain-security/v4/x/ccv/provider/migrations/v4"
+ providerkeeper "github.com/cosmos/interchain-security/v5/x/ccv/provider/keeper"
+ v3 "github.com/cosmos/interchain-security/v5/x/ccv/provider/migrations/v3"
+ v4 "github.com/cosmos/interchain-security/v5/x/ccv/provider/migrations/v4"
+ v5 "github.com/cosmos/interchain-security/v5/x/ccv/provider/migrations/v5"
)
// Migrator is a struct for handling in-place store migrations.
@@ -39,3 +40,10 @@ func (m Migrator) Migrate3to4(ctx sdktypes.Context) error {
v4.MigrateParams(ctx, m.paramSpace)
return nil
}
+
+// MigrateXtoY migrates x/ccvprovider state from consensus version X to Y.
+// The migration consists of setting a top N of 95 for all registered consumer chains.
+func (m Migrator) MigrateXtoY(ctx sdktypes.Context) error {
+ v5.MigrateTopNForRegisteredChains(ctx, m.providerKeeper)
+ return nil
+}
diff --git a/x/ccv/provider/migrations/v3/migration_test.go b/x/ccv/provider/migrations/v3/migration_test.go
index 630b8fd7dd..56d6b617d9 100644
--- a/x/ccv/provider/migrations/v3/migration_test.go
+++ b/x/ccv/provider/migrations/v3/migration_test.go
@@ -6,7 +6,7 @@ import (
"github.com/stretchr/testify/require"
- testutil "github.com/cosmos/interchain-security/v4/testutil/keeper"
+ testutil "github.com/cosmos/interchain-security/v5/testutil/keeper"
)
func TestMigrate2To3(t *testing.T) {
diff --git a/x/ccv/provider/migrations/v3/migrations.go b/x/ccv/provider/migrations/v3/migrations.go
index d308316761..2ffd1e6f25 100644
--- a/x/ccv/provider/migrations/v3/migrations.go
+++ b/x/ccv/provider/migrations/v3/migrations.go
@@ -5,7 +5,7 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
- providerkeeper "github.com/cosmos/interchain-security/v4/x/ccv/provider/keeper"
+ providerkeeper "github.com/cosmos/interchain-security/v5/x/ccv/provider/keeper"
)
// MigrateQueuedPackets processes all queued packet data for all consumer chains that were stored
diff --git a/x/ccv/provider/migrations/v4/migration_test.go b/x/ccv/provider/migrations/v4/migration_test.go
index 5ab5faf87a..4423842149 100644
--- a/x/ccv/provider/migrations/v4/migration_test.go
+++ b/x/ccv/provider/migrations/v4/migration_test.go
@@ -5,8 +5,8 @@ import (
"github.com/stretchr/testify/require"
- testutil "github.com/cosmos/interchain-security/v4/testutil/keeper"
- providertypes "github.com/cosmos/interchain-security/v4/x/ccv/provider/types"
+ testutil "github.com/cosmos/interchain-security/v5/testutil/keeper"
+ providertypes "github.com/cosmos/interchain-security/v5/x/ccv/provider/types"
)
func TestMigrateParams(t *testing.T) {
diff --git a/x/ccv/provider/migrations/v4/migrations.go b/x/ccv/provider/migrations/v4/migrations.go
index 825d01e25d..e60c98700e 100644
--- a/x/ccv/provider/migrations/v4/migrations.go
+++ b/x/ccv/provider/migrations/v4/migrations.go
@@ -4,7 +4,7 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
paramtypes "github.com/cosmos/cosmos-sdk/x/params/types"
- providertypes "github.com/cosmos/interchain-security/v4/x/ccv/provider/types"
+ providertypes "github.com/cosmos/interchain-security/v5/x/ccv/provider/types"
)
// MigrateParams adds missing provider chain params to the param store.
diff --git a/x/ccv/provider/migrations/v5/migration_test.go b/x/ccv/provider/migrations/v5/migration_test.go
new file mode 100644
index 0000000000..907aa1b019
--- /dev/null
+++ b/x/ccv/provider/migrations/v5/migration_test.go
@@ -0,0 +1,30 @@
+package v5
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/require"
+
+ testutil "github.com/cosmos/interchain-security/v5/testutil/keeper"
+)
+
+func TestMigrateParams(t *testing.T) {
+ inMemParams := testutil.NewInMemKeeperParams(t)
+ provKeeper, ctx, ctrl, _ := testutil.GetProviderKeeperAndCtx(t, inMemParams)
+ defer ctrl.Finish()
+
+ provKeeper.SetConsumerClientId(ctx, "chainID", "clientID")
+
+ // initially top N should not exist
+ topN, found := provKeeper.GetTopN(ctx, "chainID")
+ require.False(t, found)
+ require.Zero(t, topN)
+
+ // migrate
+ MigrateTopNForRegisteredChains(ctx, provKeeper)
+
+ // after migration, top N should be 95
+ topN, found = provKeeper.GetTopN(ctx, "chainID")
+ require.True(t, found)
+ require.Equal(t, uint32(95), topN)
+}
diff --git a/x/ccv/provider/migrations/v5/migrations.go b/x/ccv/provider/migrations/v5/migrations.go
new file mode 100644
index 0000000000..aa228b6a09
--- /dev/null
+++ b/x/ccv/provider/migrations/v5/migrations.go
@@ -0,0 +1,24 @@
+package v5
+
+import (
+ sdk "github.com/cosmos/cosmos-sdk/types"
+
+ providerkeeper "github.com/cosmos/interchain-security/v5/x/ccv/provider/keeper"
+)
+
+// This migration only takes already registered chains into account.
+// If a chain is in voting while the upgrade happens, this is not sufficient,
+// and a migration to rewrite the proposal is needed.
+func MigrateTopNForRegisteredChains(ctx sdk.Context, providerKeeper providerkeeper.Keeper) {
+ // get all consumer chains
+ registeredConsumerChains := providerKeeper.GetAllConsumerChains(ctx)
+
+ // Set the topN of each chain to 95
+ for _, chain := range registeredConsumerChains {
+ providerKeeper.SetTopN(ctx, chain.ChainId, 95)
+ }
+}
+
+// // If there are consumer addition proposals in the voting period at the upgrade time, they may need the topN value updated.
+// func MigrateTopNForVotingPeriodChains(ctx sdk.Context, govKeeper govkeeper.Keeper, providerKeeper providerkeeper.Keeper) {
+// }
diff --git a/x/ccv/provider/module.go b/x/ccv/provider/module.go
index 4cdeac6af7..85555af2c2 100644
--- a/x/ccv/provider/module.go
+++ b/x/ccv/provider/module.go
@@ -19,10 +19,10 @@ import (
abci "github.com/cometbft/cometbft/abci/types"
- "github.com/cosmos/interchain-security/v4/x/ccv/provider/client/cli"
- "github.com/cosmos/interchain-security/v4/x/ccv/provider/keeper"
- "github.com/cosmos/interchain-security/v4/x/ccv/provider/migrations"
- providertypes "github.com/cosmos/interchain-security/v4/x/ccv/provider/types"
+ "github.com/cosmos/interchain-security/v5/x/ccv/provider/client/cli"
+ "github.com/cosmos/interchain-security/v5/x/ccv/provider/keeper"
+ "github.com/cosmos/interchain-security/v5/x/ccv/provider/migrations"
+ providertypes "github.com/cosmos/interchain-security/v5/x/ccv/provider/types"
)
var (
@@ -137,7 +137,7 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.Raw
}
// ConsensusVersion implements AppModule/ConsensusVersion.
-func (AppModule) ConsensusVersion() uint64 { return 4 }
+func (AppModule) ConsensusVersion() uint64 { return 5 }
// BeginBlock implements the AppModule interface
func (am AppModule) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) {
@@ -147,6 +147,8 @@ func (am AppModule) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) {
am.keeper.BeginBlockCCR(ctx)
// Check for replenishing slash meter before any slash packets are processed for this block
am.keeper.BeginBlockCIS(ctx)
+ // BeginBlock logic need for the Reward Distribution sub-protocol
+ am.keeper.BeginBlockRD(ctx, req)
}
// EndBlock implements the AppModule interface
@@ -158,8 +160,6 @@ func (am AppModule) EndBlock(ctx sdk.Context, req abci.RequestEndBlock) []abci.V
am.keeper.EndBlockCCR(ctx)
// EndBlock logic needed for the Validator Set Update sub-protocol
am.keeper.EndBlockVSU(ctx)
- // EndBlock logic need for the Reward Distribution sub-protocol
- am.keeper.EndBlockRD(ctx)
return []abci.ValidatorUpdate{}
}
diff --git a/x/ccv/provider/module_test.go b/x/ccv/provider/module_test.go
index 869c24253f..2dfdfc1598 100644
--- a/x/ccv/provider/module_test.go
+++ b/x/ccv/provider/module_test.go
@@ -11,10 +11,10 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types"
- testkeeper "github.com/cosmos/interchain-security/v4/testutil/keeper"
- "github.com/cosmos/interchain-security/v4/x/ccv/provider"
- "github.com/cosmos/interchain-security/v4/x/ccv/provider/types"
- ccv "github.com/cosmos/interchain-security/v4/x/ccv/types"
+ testkeeper "github.com/cosmos/interchain-security/v5/testutil/keeper"
+ "github.com/cosmos/interchain-security/v5/x/ccv/provider"
+ "github.com/cosmos/interchain-security/v5/x/ccv/provider/types"
+ ccv "github.com/cosmos/interchain-security/v5/x/ccv/types"
)
// Tests the provider's InitGenesis implementation against the spec.
diff --git a/x/ccv/provider/proposal_handler.go b/x/ccv/provider/proposal_handler.go
index 50089a8ab5..2a4342ea20 100644
--- a/x/ccv/provider/proposal_handler.go
+++ b/x/ccv/provider/proposal_handler.go
@@ -7,8 +7,8 @@ import (
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
govv1beta1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1"
- "github.com/cosmos/interchain-security/v4/x/ccv/provider/keeper"
- "github.com/cosmos/interchain-security/v4/x/ccv/provider/types"
+ "github.com/cosmos/interchain-security/v5/x/ccv/provider/keeper"
+ "github.com/cosmos/interchain-security/v5/x/ccv/provider/types"
)
// NewProviderProposalHandler defines the handler for consumer addition,
diff --git a/x/ccv/provider/proposal_handler_test.go b/x/ccv/provider/proposal_handler_test.go
index 65e84ac661..e15036f565 100644
--- a/x/ccv/provider/proposal_handler_test.go
+++ b/x/ccv/provider/proposal_handler_test.go
@@ -12,9 +12,9 @@ import (
distributiontypes "github.com/cosmos/cosmos-sdk/x/distribution/types"
govv1beta1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1"
- testkeeper "github.com/cosmos/interchain-security/v4/testutil/keeper"
- "github.com/cosmos/interchain-security/v4/x/ccv/provider"
- providertypes "github.com/cosmos/interchain-security/v4/x/ccv/provider/types"
+ testkeeper "github.com/cosmos/interchain-security/v5/testutil/keeper"
+ "github.com/cosmos/interchain-security/v5/x/ccv/provider"
+ providertypes "github.com/cosmos/interchain-security/v5/x/ccv/provider/types"
)
// TestProviderProposalHandler tests the highest level handler for proposals
@@ -44,6 +44,11 @@ func TestProviderProposalHandler(t *testing.T) {
100000000000,
100000000000,
100000000000,
+ 0,
+ 0,
+ 0,
+ nil,
+ nil,
),
blockTime: hourFromNow, // ctx blocktime is after proposal's spawn time
expValidConsumerAddition: true,
diff --git a/x/ccv/provider/types/codec.go b/x/ccv/provider/types/codec.go
index e5900bcf04..cc842276fb 100644
--- a/x/ccv/provider/types/codec.go
+++ b/x/ccv/provider/types/codec.go
@@ -46,10 +46,22 @@ func RegisterInterfaces(registry codectypes.InterfaceRegistry) {
(*sdk.Msg)(nil),
&MsgSubmitConsumerDoubleVoting{},
)
+ registry.RegisterImplementations(
+ (*sdk.Msg)(nil),
+ &MsgOptIn{},
+ )
+ registry.RegisterImplementations(
+ (*sdk.Msg)(nil),
+ &MsgOptOut{},
+ )
registry.RegisterImplementations(
(*exported.ClientMessage)(nil),
&tendermint.Misbehaviour{},
)
+ registry.RegisterImplementations(
+ (*sdk.Msg)(nil),
+ &MsgSetConsumerCommissionRate{},
+ )
msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc)
}
diff --git a/x/ccv/provider/types/consumer.go b/x/ccv/provider/types/consumer.go
index 4c43bd58e7..02651ac03e 100644
--- a/x/ccv/provider/types/consumer.go
+++ b/x/ccv/provider/types/consumer.go
@@ -1,7 +1,7 @@
package types
import (
- ccv "github.com/cosmos/interchain-security/v4/x/ccv/types"
+ ccv "github.com/cosmos/interchain-security/v5/x/ccv/types"
)
func NewConsumerStates(
diff --git a/x/ccv/provider/types/errors.go b/x/ccv/provider/types/errors.go
index 315cda5197..32000ed65f 100644
--- a/x/ccv/provider/types/errors.go
+++ b/x/ccv/provider/types/errors.go
@@ -24,5 +24,7 @@ var (
ErrInvalidConsumerClient = errorsmod.Register(ModuleName, 16, "ccv channel is not built on correct client")
ErrDuplicateConsumerChain = errorsmod.Register(ModuleName, 17, "consumer chain already exists")
ErrConsumerChainNotFound = errorsmod.Register(ModuleName, 18, "consumer chain not found")
- ErrNoUnconfirmedVSCPacket = errorsmod.Register(ModuleName, 19, "no unconfirmed vsc packet for this chain id")
+ ErrInvalidConsumerCommissionRate = errorsmod.Register(ModuleName, 19, "consumer commission rate is invalid")
+ ErrCannotOptOutFromTopN = errorsmod.Register(ModuleName, 20, "cannot opt out from a Top N chain")
+ ErrNoUnconfirmedVSCPacket = errorsmod.Register(ModuleName, 21, "no unconfirmed vsc packet for this chain id")
)
diff --git a/x/ccv/provider/types/events.go b/x/ccv/provider/types/events.go
index 58d686020f..8701821c52 100644
--- a/x/ccv/provider/types/events.go
+++ b/x/ccv/provider/types/events.go
@@ -7,6 +7,9 @@ const (
EventTypeAddConsumerRewardDenom = "add_consumer_reward_denom"
EventTypeRemoveConsumerRewardDenom = "remove_consumer_reward_denom"
EventTypeExecuteConsumerChainSlash = "execute_consumer_chain_slash"
+ EventTypeSetConsumerCommissionRate = "set_consumer_commission_rate"
+ EventTypeOptIn = "opt_in"
+ EventTypeOptOut = "opt_out"
AttributeInfractionHeight = "infraction_height"
AttributeInitialHeight = "initial_height"
AttributeInitializationTimeout = "initialization_timeout"
@@ -15,4 +18,6 @@ const (
AttributeProviderValidatorAddress = "provider_validator_address"
AttributeConsumerConsensusPubKey = "consumer_consensus_pub_key"
AttributeConsumerRewardDenom = "consumer_reward_denom"
+ AttributeConsumerCommissionRate = "consumer_commission_rate"
+ AttributeConsumerChainID = "consumer_chain_id"
)
diff --git a/x/ccv/provider/types/genesis.go b/x/ccv/provider/types/genesis.go
index ae929ba541..00802558c5 100644
--- a/x/ccv/provider/types/genesis.go
+++ b/x/ccv/provider/types/genesis.go
@@ -9,7 +9,7 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
- ccv "github.com/cosmos/interchain-security/v4/x/ccv/types"
+ ccv "github.com/cosmos/interchain-security/v5/x/ccv/types"
)
func NewGenesisState(
diff --git a/x/ccv/provider/types/genesis.pb.go b/x/ccv/provider/types/genesis.pb.go
index d5041f1b10..d7d225b762 100644
--- a/x/ccv/provider/types/genesis.pb.go
+++ b/x/ccv/provider/types/genesis.pb.go
@@ -7,7 +7,7 @@ import (
fmt "fmt"
_ "github.com/cosmos/gogoproto/gogoproto"
proto "github.com/cosmos/gogoproto/proto"
- types "github.com/cosmos/interchain-security/v4/x/ccv/types"
+ types "github.com/cosmos/interchain-security/v5/x/ccv/types"
io "io"
math "math"
math_bits "math/bits"
diff --git a/x/ccv/provider/types/genesis_test.go b/x/ccv/provider/types/genesis_test.go
index 41a716757f..d682e93897 100644
--- a/x/ccv/provider/types/genesis_test.go
+++ b/x/ccv/provider/types/genesis_test.go
@@ -14,9 +14,9 @@ import (
abci "github.com/cometbft/cometbft/abci/types"
tmtypes "github.com/cometbft/cometbft/types"
- "github.com/cosmos/interchain-security/v4/testutil/crypto"
- "github.com/cosmos/interchain-security/v4/x/ccv/provider/types"
- ccv "github.com/cosmos/interchain-security/v4/x/ccv/types"
+ "github.com/cosmos/interchain-security/v5/testutil/crypto"
+ "github.com/cosmos/interchain-security/v5/x/ccv/provider/types"
+ ccv "github.com/cosmos/interchain-security/v5/x/ccv/types"
)
// Tests validation of consumer states and params within a provider genesis state
diff --git a/x/ccv/provider/types/key_assignment.go b/x/ccv/provider/types/key_assignment.go
index 04192ae53a..ee403e1e49 100644
--- a/x/ccv/provider/types/key_assignment.go
+++ b/x/ccv/provider/types/key_assignment.go
@@ -8,7 +8,7 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
- ccvtypes "github.com/cosmos/interchain-security/v4/x/ccv/types"
+ ccvtypes "github.com/cosmos/interchain-security/v5/x/ccv/types"
)
// A validator's consensus address on the provider chain.
diff --git a/x/ccv/provider/types/keys.go b/x/ccv/provider/types/keys.go
index e9222ade98..4126a58cb7 100644
--- a/x/ccv/provider/types/keys.go
+++ b/x/ccv/provider/types/keys.go
@@ -8,7 +8,7 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
- ccvtypes "github.com/cosmos/interchain-security/v4/x/ccv/types"
+ ccvtypes "github.com/cosmos/interchain-security/v5/x/ccv/types"
)
type Status int
@@ -147,9 +147,42 @@ const (
// ProposedConsumerChainByteKey is the byte prefix storing the consumer chainId in consumerAddition gov proposal submitted before voting finishes
ProposedConsumerChainByteKey
- // ConsumerValidatorBytePrefix is the byte prefix used when storing for each consumer chain all the consumer validators in this epoch
+ // ConsumerValidatorBytePrefix is the byte prefix used when storing for each consumer chain all the consumer
+ // validators in this epoch that are validating the consumer chain
ConsumerValidatorBytePrefix
+ // OptedInBytePrefix is the byte prefix for storing whether a validator is opted in to validate on a consumer chain
+ OptedInBytePrefix
+
+ // TopNBytePrefix is the byte prefix storing the mapping from a consumer chain to the N value of this chain,
+ // that corresponds to the N% of the top validators that have to validate this consumer chain
+ TopNBytePrefix
+
+ // ValidatorsPowerCapPrefix is the byte prefix storing the mapping from a consumer chain to the power-cap value of this chain,
+ // that corresponds to p% such that no validator can have more than p% of the voting power on the consumer chain.
+ // Operates on a best-effort basis.
+ ValidatorsPowerCapPrefix
+
+ // ValidatorSetCapPrefix is the byte prefix storing the mapping from a consumer chain to the validator-set cap value
+ // of this chain.
+ ValidatorSetCapPrefix
+
+ // AllowlistPrefix is the byte prefix storing the mapping from a consumer chain to the set of validators that are
+ // allowlisted.
+ AllowlistPrefix
+
+ // DenylistPrefix is the byte prefix storing the mapping from a consumer chain to the set of validators that are
+ // denylisted.
+ DenylistPrefix
+
+ // ConsumerRewardsAllocationBytePrefix is the byte prefix for storing for each consumer the ICS rewards
+ // allocated to the consumer rewards pool
+ ConsumerRewardsAllocationBytePrefix
+
+ // ConsumerCommissionRatePrefix is the byte prefix for storing the commission rate
+ // per validator per consumer chain
+ ConsumerCommissionRatePrefix
+
// NOTE: DO NOT ADD NEW BYTE PREFIXES HERE WITHOUT ADDING THEM TO getAllKeyPrefixes() IN keys_test.go
)
@@ -522,6 +555,52 @@ func ConsumerValidatorKey(chainID string, providerAddr []byte) []byte {
return append(prefix, providerAddr...)
}
+// TopNKey returns the key used to store the Top N value per consumer chain.
+// This value corresponds to the N% of the top validators that have to validate the consumer chain.
+func TopNKey(chainID string) []byte {
+ return ChainIdWithLenKey(TopNBytePrefix, chainID)
+}
+
+// ValidatorSetPowerKey returns the key of consumer chain `chainID`
+func ValidatorsPowerCapKey(chainID string) []byte {
+ return ChainIdWithLenKey(ValidatorsPowerCapPrefix, chainID)
+}
+
+// ValidatorSetCapKey returns the key of consumer chain `chainID`
+func ValidatorSetCapKey(chainID string) []byte {
+ return ChainIdWithLenKey(ValidatorSetCapPrefix, chainID)
+}
+
+// AllowlistCapKey returns the key to a validator's slash log
+func AllowlistCapKey(chainID string, providerAddr ProviderConsAddress) []byte {
+ return append(ChainIdWithLenKey(AllowlistPrefix, chainID), providerAddr.ToSdkConsAddr().Bytes()...)
+}
+
+// DenylistCapKey returns the key to a validator's slash log
+func DenylistCapKey(chainID string, providerAddr ProviderConsAddress) []byte {
+ return append(ChainIdWithLenKey(DenylistPrefix, chainID), providerAddr.ToSdkConsAddr().Bytes()...)
+}
+
+// OptedInKey returns the key used to store whether a validator is opted in on a consumer chain.
+func OptedInKey(chainID string, providerAddr ProviderConsAddress) []byte {
+ prefix := ChainIdWithLenKey(OptedInBytePrefix, chainID)
+ return append(prefix, providerAddr.ToSdkConsAddr().Bytes()...)
+}
+
+// ConsumerRewardsAllocationKey returns the key used to store the ICS rewards per consumer chain
+func ConsumerRewardsAllocationKey(chainID string) []byte {
+ return append([]byte{ConsumerRewardsAllocationBytePrefix}, []byte(chainID)...)
+}
+
+// ConsumerCommissionRateKey returns the key used to store the commission rate per validator per consumer chain.
+func ConsumerCommissionRateKey(chainID string, providerAddr ProviderConsAddress) []byte {
+ return ChainIdAndConsAddrKey(
+ ConsumerCommissionRatePrefix,
+ chainID,
+ providerAddr.ToSdkConsAddr(),
+ )
+}
+
//
// End of generic helpers section
//
diff --git a/x/ccv/provider/types/keys_test.go b/x/ccv/provider/types/keys_test.go
index 02faa9a640..78d8b4f806 100644
--- a/x/ccv/provider/types/keys_test.go
+++ b/x/ccv/provider/types/keys_test.go
@@ -8,8 +8,8 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
- cryptoutil "github.com/cosmos/interchain-security/v4/testutil/crypto"
- providertypes "github.com/cosmos/interchain-security/v4/x/ccv/provider/types"
+ cryptoutil "github.com/cosmos/interchain-security/v5/testutil/crypto"
+ providertypes "github.com/cosmos/interchain-security/v5/x/ccv/provider/types"
)
// Tests that all singular keys, or prefixes to fully resolves keys are non duplicate byte values.
@@ -57,6 +57,10 @@ func getAllKeyPrefixes() []byte {
providertypes.EquivocationEvidenceMinHeightBytePrefix,
providertypes.ProposedConsumerChainByteKey,
providertypes.ConsumerValidatorBytePrefix,
+ providertypes.OptedInBytePrefix,
+ providertypes.TopNBytePrefix,
+ providertypes.ConsumerRewardsAllocationBytePrefix,
+ providertypes.ConsumerCommissionRatePrefix,
}
}
diff --git a/x/ccv/provider/types/msg.go b/x/ccv/provider/types/msg.go
index 55e6b2fae4..b6546506fd 100644
--- a/x/ccv/provider/types/msg.go
+++ b/x/ccv/provider/types/msg.go
@@ -14,7 +14,7 @@ import (
tmtypes "github.com/cometbft/cometbft/proto/tendermint/types"
- ccvtypes "github.com/cosmos/interchain-security/v4/x/ccv/types"
+ ccvtypes "github.com/cosmos/interchain-security/v5/x/ccv/types"
)
// provider message types
@@ -22,12 +22,18 @@ const (
TypeMsgAssignConsumerKey = "assign_consumer_key"
TypeMsgSubmitConsumerMisbehaviour = "submit_consumer_misbehaviour"
TypeMsgSubmitConsumerDoubleVoting = "submit_consumer_double_vote"
+ TypeMsgOptIn = "opt_in"
+ TypeMsgOptOut = "opt_out"
+ TypeMsgSetConsumerCommissionRate = "set_consumer_commission_rate"
)
var (
_ sdk.Msg = &MsgAssignConsumerKey{}
_ sdk.Msg = &MsgSubmitConsumerMisbehaviour{}
_ sdk.Msg = &MsgSubmitConsumerDoubleVoting{}
+ _ sdk.Msg = &MsgOptIn{}
+ _ sdk.Msg = &MsgOptOut{}
+ _ sdk.Msg = &MsgSetConsumerCommissionRate{}
)
// NewMsgAssignConsumerKey creates a new MsgAssignConsumerKey instance.
@@ -203,3 +209,163 @@ func (msg MsgSubmitConsumerDoubleVoting) GetSigners() []sdk.AccAddress {
}
return []sdk.AccAddress{addr}
}
+
+// NewMsgOptIn creates a new NewMsgOptIn instance.
+func NewMsgOptIn(chainID string, providerValidatorAddress sdk.ValAddress, consumerConsensusPubKey string) (*MsgOptIn, error) {
+ return &MsgOptIn{
+ ChainId: chainID,
+ ProviderAddr: providerValidatorAddress.String(),
+ ConsumerKey: consumerConsensusPubKey,
+ }, nil
+}
+
+// Route implements the sdk.Msg interface.
+func (msg MsgOptIn) Route() string { return RouterKey }
+
+// GetSigners implements the sdk.Msg interface. It returns the address(es) that
+// must sign over msg.GetSignBytes().
+func (msg MsgOptIn) GetSigners() []sdk.AccAddress {
+ valAddr, err := sdk.ValAddressFromBech32(msg.ProviderAddr)
+ if err != nil {
+ // same behavior as in cosmos-sdk
+ panic(err)
+ }
+ return []sdk.AccAddress{valAddr.Bytes()}
+}
+
+// GetSignBytes returns the message bytes to sign over.
+func (msg MsgOptIn) GetSignBytes() []byte {
+ bz := ccvtypes.ModuleCdc.MustMarshalJSON(&msg)
+ return sdk.MustSortJSON(bz)
+}
+
+// ValidateBasic implements the sdk.Msg interface.
+func (msg MsgOptIn) ValidateBasic() error {
+ if strings.TrimSpace(msg.ChainId) == "" {
+ return errorsmod.Wrapf(ErrInvalidConsumerChainID, "chainId cannot be blank")
+ }
+ // It is possible to opt in to validate on consumer chains that are not yet approved.
+ // This can only be done by a signing validator, but it is still sensible
+ // to limit the chainID size to prevent abuse.
+ if 128 < len(msg.ChainId) {
+ return errorsmod.Wrapf(ErrInvalidConsumerChainID, "chainId cannot exceed 128 length")
+ }
+ _, err := sdk.ValAddressFromBech32(msg.ProviderAddr)
+ if err != nil {
+ return ErrInvalidProviderAddress
+ }
+
+ if msg.ConsumerKey != "" {
+ if _, _, err := ParseConsumerKeyFromJson(msg.ConsumerKey); err != nil {
+ return ErrInvalidConsumerConsensusPubKey
+ }
+ }
+ return nil
+}
+
+// NewMsgOptOut creates a new NewMsgOptIn instance.
+func NewMsgOptOut(chainID string, providerValidatorAddress sdk.ValAddress) (*MsgOptOut, error) {
+ return &MsgOptOut{
+ ChainId: chainID,
+ ProviderAddr: providerValidatorAddress.String(),
+ }, nil
+}
+
+// Route implements the sdk.Msg interface.
+func (msg MsgOptOut) Route() string { return RouterKey }
+
+// Type implements the sdk.Msg interface.
+func (msg MsgOptIn) Type() string {
+ return TypeMsgOptIn
+}
+
+// GetSigners implements the sdk.Msg interface. It returns the address(es) that
+// must sign over msg.GetSignBytes().
+func (msg MsgOptOut) GetSigners() []sdk.AccAddress {
+ valAddr, err := sdk.ValAddressFromBech32(msg.ProviderAddr)
+ if err != nil {
+ // same behavior as in cosmos-sdk
+ panic(err)
+ }
+ return []sdk.AccAddress{valAddr.Bytes()}
+}
+
+// GetSignBytes returns the message bytes to sign over.
+func (msg MsgOptOut) GetSignBytes() []byte {
+ bz := ccvtypes.ModuleCdc.MustMarshalJSON(&msg)
+ return sdk.MustSortJSON(bz)
+}
+
+// ValidateBasic implements the sdk.Msg interface.
+func (msg MsgOptOut) ValidateBasic() error {
+ if strings.TrimSpace(msg.ChainId) == "" {
+ return errorsmod.Wrapf(ErrInvalidConsumerChainID, "chainId cannot be blank")
+ }
+ // It is possible to assign keys for consumer chains that are not yet approved.
+ // This can only be done by a signing validator, but it is still sensible
+ // to limit the chainID size to prevent abuse.
+ if 128 < len(msg.ChainId) {
+ return errorsmod.Wrapf(ErrInvalidConsumerChainID, "chainId cannot exceed 128 length")
+ }
+ _, err := sdk.ValAddressFromBech32(msg.ProviderAddr)
+ if err != nil {
+ return ErrInvalidProviderAddress
+ }
+ return nil
+}
+
+// NewMsgSetConsumerCommissionRate creates a new MsgSetConsumerCommissionRate msg instance.
+func NewMsgSetConsumerCommissionRate(chainID string, commission sdk.Dec, providerValidatorAddress sdk.ValAddress) *MsgSetConsumerCommissionRate {
+ return &MsgSetConsumerCommissionRate{
+ ChainId: chainID,
+ Rate: commission,
+ ProviderAddr: providerValidatorAddress.String(),
+ }
+}
+
+// Type implements the sdk.Msg interface.
+func (msg MsgOptOut) Type() string {
+ return TypeMsgOptOut
+}
+
+func (msg MsgSetConsumerCommissionRate) Route() string {
+ return RouterKey
+}
+
+func (msg MsgSetConsumerCommissionRate) Type() string {
+ return TypeMsgSetConsumerCommissionRate
+}
+
+func (msg MsgSetConsumerCommissionRate) ValidateBasic() error {
+ if strings.TrimSpace(msg.ChainId) == "" {
+ return errorsmod.Wrapf(ErrInvalidConsumerChainID, "chainId cannot be blank")
+ }
+
+ if 128 < len(msg.ChainId) {
+ return errorsmod.Wrapf(ErrInvalidConsumerChainID, "chainId cannot exceed 128 length")
+ }
+ _, err := sdk.ValAddressFromBech32(msg.ProviderAddr)
+ if err != nil {
+ return ErrInvalidProviderAddress
+ }
+
+ if msg.Rate.IsNegative() || msg.Rate.GT(sdk.OneDec()) {
+ return errorsmod.Wrapf(ErrInvalidConsumerCommissionRate, "consumer commission rate should be in the range [0, 1]")
+ }
+
+ return nil
+}
+
+func (msg MsgSetConsumerCommissionRate) GetSigners() []sdk.AccAddress {
+ valAddr, err := sdk.ValAddressFromBech32(msg.ProviderAddr)
+ if err != nil {
+ // same behavior as in cosmos-sdk
+ panic(err)
+ }
+ return []sdk.AccAddress{valAddr.Bytes()}
+}
+
+func (msg MsgSetConsumerCommissionRate) GetSignBytes() []byte {
+ bz := ccvtypes.ModuleCdc.MustMarshalJSON(&msg)
+ return sdk.MustSortJSON(bz)
+}
diff --git a/x/ccv/provider/types/params.go b/x/ccv/provider/types/params.go
index a0a7a5ed7a..c398188c98 100644
--- a/x/ccv/provider/types/params.go
+++ b/x/ccv/provider/types/params.go
@@ -11,7 +11,7 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
paramtypes "github.com/cosmos/cosmos-sdk/x/params/types"
- ccvtypes "github.com/cosmos/interchain-security/v4/x/ccv/types"
+ ccvtypes "github.com/cosmos/interchain-security/v5/x/ccv/types"
)
const (
diff --git a/x/ccv/provider/types/params_test.go b/x/ccv/provider/types/params_test.go
index 4e72c233af..b86dd0cddf 100644
--- a/x/ccv/provider/types/params_test.go
+++ b/x/ccv/provider/types/params_test.go
@@ -11,7 +11,7 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
- "github.com/cosmos/interchain-security/v4/x/ccv/provider/types"
+ "github.com/cosmos/interchain-security/v5/x/ccv/provider/types"
)
func TestValidateParams(t *testing.T) {
diff --git a/x/ccv/provider/types/proposal.go b/x/ccv/provider/types/proposal.go
index 93cadfd14e..d2cfa7ed3f 100644
--- a/x/ccv/provider/types/proposal.go
+++ b/x/ccv/provider/types/proposal.go
@@ -14,7 +14,7 @@ import (
evidencetypes "github.com/cosmos/cosmos-sdk/x/evidence/types"
govv1beta1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1"
- ccvtypes "github.com/cosmos/interchain-security/v4/x/ccv/types"
+ ccvtypes "github.com/cosmos/interchain-security/v5/x/ccv/types"
)
const (
@@ -49,6 +49,11 @@ func NewConsumerAdditionProposal(title, description, chainID string,
ccvTimeoutPeriod time.Duration,
transferTimeoutPeriod time.Duration,
unbondingPeriod time.Duration,
+ topN uint32,
+ validatorsPowerCap uint32,
+ validatorSetCap uint32,
+ allowlist []string,
+ denylist []string,
) govv1beta1.Content {
return &ConsumerAdditionProposal{
Title: title,
@@ -65,6 +70,11 @@ func NewConsumerAdditionProposal(title, description, chainID string,
CcvTimeoutPeriod: ccvTimeoutPeriod,
TransferTimeoutPeriod: transferTimeoutPeriod,
UnbondingPeriod: unbondingPeriod,
+ Top_N: topN,
+ ValidatorsPowerCap: validatorsPowerCap,
+ ValidatorSetCap: validatorSetCap,
+ Allowlist: allowlist,
+ Denylist: denylist,
}
}
@@ -135,6 +145,16 @@ func (cccp *ConsumerAdditionProposal) ValidateBasic() error {
return errorsmod.Wrap(ErrInvalidConsumerAdditionProposal, "unbonding period cannot be zero")
}
+ // Top N corresponds to the top N% of validators that have to validate the consumer chain and can only be 0 (for an
+ // Opt In chain) or in the range [50, 100] (for a Top N chain).
+ if cccp.Top_N != 0 && (cccp.Top_N < 50 || cccp.Top_N > 100) {
+ return errorsmod.Wrap(ErrInvalidConsumerAdditionProposal, "Top N can either be 0 or in the range [50, 100]")
+ }
+
+ if cccp.ValidatorsPowerCap != 0 && cccp.ValidatorSetCap > 100 {
+ return errorsmod.Wrap(ErrInvalidConsumerAdditionProposal, "validators' power cap has to be in the range [1, 100]")
+ }
+
return nil
}
diff --git a/x/ccv/provider/types/proposal_test.go b/x/ccv/provider/types/proposal_test.go
index 72fcfe8436..a2f8f574ee 100644
--- a/x/ccv/provider/types/proposal_test.go
+++ b/x/ccv/provider/types/proposal_test.go
@@ -15,7 +15,7 @@ import (
govv1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1"
govv1beta1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1"
- "github.com/cosmos/interchain-security/v4/x/ccv/provider/types"
+ "github.com/cosmos/interchain-security/v5/x/ccv/provider/types"
)
func TestConsumerAdditionProposalValidateBasic(t *testing.T) {
@@ -36,6 +36,11 @@ func TestConsumerAdditionProposalValidateBasic(t *testing.T) {
100000000000,
100000000000,
100000000000,
+ 0,
+ 0,
+ 0,
+ nil,
+ nil,
),
true,
},
@@ -48,7 +53,13 @@ func TestConsumerAdditionProposalValidateBasic(t *testing.T) {
10000,
100000000000,
100000000000,
- 100000000000),
+ 100000000000,
+ 0,
+ 0,
+ 0,
+ nil,
+ nil,
+ ),
true,
},
{
@@ -60,7 +71,13 @@ func TestConsumerAdditionProposalValidateBasic(t *testing.T) {
10000,
100000000000,
100000000000,
- 100000000000),
+ 100000000000,
+ 0,
+ 0,
+ 0,
+ nil,
+ nil,
+ ),
false,
},
{
@@ -72,7 +89,13 @@ func TestConsumerAdditionProposalValidateBasic(t *testing.T) {
10000,
100000000000,
100000000000,
- 100000000000),
+ 100000000000,
+ 0,
+ 0,
+ 0,
+ nil,
+ nil,
+ ),
false,
},
{
@@ -104,7 +127,13 @@ func TestConsumerAdditionProposalValidateBasic(t *testing.T) {
10000,
100000000000,
100000000000,
- 100000000000),
+ 100000000000,
+ 0,
+ 0,
+ 0,
+ nil,
+ nil,
+ ),
false,
},
{
@@ -116,7 +145,12 @@ func TestConsumerAdditionProposalValidateBasic(t *testing.T) {
10000,
100000000000,
100000000000,
- 100000000000),
+ 100000000000,
+ 0,
+ 0,
+ 0,
+ nil,
+ nil),
false,
},
{
@@ -128,7 +162,13 @@ func TestConsumerAdditionProposalValidateBasic(t *testing.T) {
10000,
100000000000,
100000000000,
- 100000000000),
+ 100000000000,
+ 0,
+ 0,
+ 0,
+ nil,
+ nil,
+ ),
false,
},
{
@@ -140,7 +180,13 @@ func TestConsumerAdditionProposalValidateBasic(t *testing.T) {
10000,
100000000000,
100000000000,
- 100000000000),
+ 100000000000,
+ 0,
+ 0,
+ 0,
+ nil,
+ nil,
+ ),
false,
},
{
@@ -152,7 +198,13 @@ func TestConsumerAdditionProposalValidateBasic(t *testing.T) {
100000000000,
10000,
100000000000,
- 100000000000),
+ 100000000000,
+ 0,
+ 0,
+ 0,
+ nil,
+ nil,
+ ),
false,
},
{
@@ -164,7 +216,13 @@ func TestConsumerAdditionProposalValidateBasic(t *testing.T) {
10000,
100000000000,
100000000000,
- 100000000000),
+ 100000000000,
+ 0,
+ 0,
+ 0,
+ nil,
+ nil,
+ ),
false,
},
{
@@ -176,7 +234,13 @@ func TestConsumerAdditionProposalValidateBasic(t *testing.T) {
-2,
100000000000,
100000000000,
- 100000000000),
+ 100000000000,
+ 0,
+ 0,
+ 0,
+ nil,
+ nil,
+ ),
false,
},
{
@@ -188,7 +252,13 @@ func TestConsumerAdditionProposalValidateBasic(t *testing.T) {
10000,
0,
100000000000,
- 100000000000),
+ 100000000000,
+ 0,
+ 0,
+ 0,
+ nil,
+ nil,
+ ),
false,
},
{
@@ -200,7 +270,13 @@ func TestConsumerAdditionProposalValidateBasic(t *testing.T) {
10000,
100000000000,
0,
- 100000000000),
+ 100000000000,
+ 0,
+ 0,
+ 0,
+ nil,
+ nil,
+ ),
false,
},
{
@@ -212,7 +288,13 @@ func TestConsumerAdditionProposalValidateBasic(t *testing.T) {
10000,
100000000000,
100000000000,
- 0),
+ 0,
+ 0,
+ 0,
+ 0,
+ nil,
+ nil,
+ ),
false,
},
}
@@ -236,7 +318,12 @@ func TestMarshalConsumerAdditionProposal(t *testing.T) {
10000,
100000000000,
100000000000,
- 100000000000)
+ 100000000000,
+ 0,
+ 0,
+ 0,
+ nil,
+ nil)
cccp, ok := content.(*types.ConsumerAdditionProposal)
require.True(t, ok)
@@ -278,7 +365,12 @@ func TestConsumerAdditionProposalString(t *testing.T) {
500000,
100000000000,
10000000000,
- 100000000000)
+ 100000000000,
+ 0,
+ 0,
+ 0,
+ []string{},
+ []string{})
expect := fmt.Sprintf(`CreateConsumerChain Proposal
Title: title
diff --git a/x/ccv/provider/types/provider.pb.go b/x/ccv/provider/types/provider.pb.go
index 8a83879f7f..07e511669c 100644
--- a/x/ccv/provider/types/provider.pb.go
+++ b/x/ccv/provider/types/provider.pb.go
@@ -6,14 +6,16 @@ package types
import (
fmt "fmt"
crypto "github.com/cometbft/cometbft/proto/tendermint/crypto"
+ github_com_cosmos_cosmos_sdk_types "github.com/cosmos/cosmos-sdk/types"
types2 "github.com/cosmos/cosmos-sdk/types"
+ _ "github.com/cosmos/cosmos-sdk/types/tx/amino"
types1 "github.com/cosmos/cosmos-sdk/x/evidence/types"
_ "github.com/cosmos/gogoproto/gogoproto"
proto "github.com/cosmos/gogoproto/proto"
github_com_cosmos_gogoproto_types "github.com/cosmos/gogoproto/types"
types "github.com/cosmos/ibc-go/v7/modules/core/02-client/types"
_07_tendermint "github.com/cosmos/ibc-go/v7/modules/light-clients/07-tendermint"
- types3 "github.com/cosmos/interchain-security/v4/x/ccv/types"
+ types3 "github.com/cosmos/interchain-security/v5/x/ccv/types"
_ "google.golang.org/protobuf/types/known/durationpb"
_ "google.golang.org/protobuf/types/known/timestamppb"
io "io"
@@ -90,6 +92,25 @@ type ConsumerAdditionProposal struct {
// chain. it is most relevant for chains performing a sovereign to consumer
// changeover in order to maintain the existing ibc transfer channel
DistributionTransmissionChannel string `protobuf:"bytes,14,opt,name=distribution_transmission_channel,json=distributionTransmissionChannel,proto3" json:"distribution_transmission_channel,omitempty"`
+ // Corresponds to the percentage of validators that have to validate the chain under the Top N case.
+ // For example, 53 corresponds to a Top 53% chain, meaning that the top 53% provider validators by voting power
+ // have to validate the proposed consumer chain. top_N can either be 0 or any value in [50, 100].
+ // A chain can join with top_N == 0 as an Opt In chain, or with top_N ∈ [50, 100] as a Top N chain.
+ Top_N uint32 `protobuf:"varint,15,opt,name=top_N,json=topN,proto3" json:"top_N,omitempty"`
+ // Corresponds to the maximum power (percentage-wise) a validator can have on the consumer chain. For instance, if
+ // `validators_power_cap` is set to 32, it means that no validator can have more than 32% of the voting power on the
+ // consumer chain. Note that this might not be feasible. For example, think of a consumer chain with only
+ // 5 validators and with `validators_power_cap` set to 10%. In such a scenario, at least one validator would need
+ // to have more than 20% of the total voting power. Therefore, `validators_power_cap` operates on a best-effort basis.
+ ValidatorsPowerCap uint32 `protobuf:"varint,16,opt,name=validators_power_cap,json=validatorsPowerCap,proto3" json:"validators_power_cap,omitempty"`
+ // Corresponds to the maximum number of validators that can validate a consumer chain.
+ // Only applicable to Opt In chains. Setting `validator_set_cap` on a Top N chain is a no-op.
+ ValidatorSetCap uint32 `protobuf:"varint,17,opt,name=validator_set_cap,json=validatorSetCap,proto3" json:"validator_set_cap,omitempty"`
+ // Corresponds to a list of provider consensus addresses of validators that are the ONLY ones that can validate
+ // the consumer chain.
+ Allowlist []string `protobuf:"bytes,18,rep,name=allowlist,proto3" json:"allowlist,omitempty"`
+ // Corresponds to a list of provider consensus addresses of validators that CANNOT validate the consumer chain.
+ Denylist []string `protobuf:"bytes,19,rep,name=denylist,proto3" json:"denylist,omitempty"`
}
func (m *ConsumerAdditionProposal) Reset() { *m = ConsumerAdditionProposal{} }
@@ -1459,6 +1480,53 @@ func (m *ConsumerValidator) GetConsumerPublicKey() *crypto.PublicKey {
return nil
}
+// ConsumerRewardsAllocation stores the rewards allocated by a consumer chain
+// to the consumer rewards pool. It is used to allocate the tokens to the consumer
+// opted-in validators and the community pool during BeginBlock.
+type ConsumerRewardsAllocation struct {
+ Rewards github_com_cosmos_cosmos_sdk_types.DecCoins `protobuf:"bytes,1,rep,name=rewards,proto3,castrepeated=github.com/cosmos/cosmos-sdk/types.DecCoins" json:"rewards"`
+}
+
+func (m *ConsumerRewardsAllocation) Reset() { *m = ConsumerRewardsAllocation{} }
+func (m *ConsumerRewardsAllocation) String() string { return proto.CompactTextString(m) }
+func (*ConsumerRewardsAllocation) ProtoMessage() {}
+func (*ConsumerRewardsAllocation) Descriptor() ([]byte, []int) {
+ return fileDescriptor_f22ec409a72b7b72, []int{23}
+}
+func (m *ConsumerRewardsAllocation) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *ConsumerRewardsAllocation) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_ConsumerRewardsAllocation.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 *ConsumerRewardsAllocation) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_ConsumerRewardsAllocation.Merge(m, src)
+}
+func (m *ConsumerRewardsAllocation) XXX_Size() int {
+ return m.Size()
+}
+func (m *ConsumerRewardsAllocation) XXX_DiscardUnknown() {
+ xxx_messageInfo_ConsumerRewardsAllocation.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_ConsumerRewardsAllocation proto.InternalMessageInfo
+
+func (m *ConsumerRewardsAllocation) GetRewards() github_com_cosmos_cosmos_sdk_types.DecCoins {
+ if m != nil {
+ return m.Rewards
+ }
+ return nil
+}
+
func init() {
proto.RegisterType((*ConsumerAdditionProposal)(nil), "interchain_security.ccv.provider.v1.ConsumerAdditionProposal")
proto.RegisterType((*ConsumerRemovalProposal)(nil), "interchain_security.ccv.provider.v1.ConsumerRemovalProposal")
@@ -1483,6 +1551,7 @@ func init() {
proto.RegisterType((*ValidatorByConsumerAddr)(nil), "interchain_security.ccv.provider.v1.ValidatorByConsumerAddr")
proto.RegisterType((*ConsumerAddrsToPrune)(nil), "interchain_security.ccv.provider.v1.ConsumerAddrsToPrune")
proto.RegisterType((*ConsumerValidator)(nil), "interchain_security.ccv.provider.v1.ConsumerValidator")
+ proto.RegisterType((*ConsumerRewardsAllocation)(nil), "interchain_security.ccv.provider.v1.ConsumerRewardsAllocation")
}
func init() {
@@ -1490,117 +1559,127 @@ func init() {
}
var fileDescriptor_f22ec409a72b7b72 = []byte{
- // 1755 bytes of a gzipped FileDescriptorProto
+ // 1919 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x58, 0x4f, 0x6f, 0x1b, 0xc7,
- 0x15, 0xd7, 0x92, 0x94, 0x2c, 0x3e, 0x4a, 0x94, 0xb4, 0x52, 0xe2, 0x95, 0xab, 0x52, 0xf2, 0xa6,
- 0x49, 0x55, 0xa4, 0x59, 0x56, 0x4a, 0x0b, 0x04, 0x46, 0x83, 0x40, 0xa2, 0x9c, 0x58, 0x56, 0x12,
- 0x2b, 0x2b, 0x55, 0x46, 0xdb, 0xc3, 0x62, 0x38, 0x3b, 0x26, 0x07, 0x5a, 0xee, 0xac, 0x67, 0x66,
- 0xd7, 0xe1, 0xa5, 0xe7, 0x1e, 0xd3, 0x5b, 0xd0, 0x4b, 0xd3, 0x02, 0x3d, 0xf7, 0x6b, 0xe4, 0x98,
- 0x63, 0x4f, 0x49, 0x61, 0x1f, 0xfb, 0x25, 0x8a, 0x99, 0xfd, 0x4b, 0x4a, 0x72, 0x69, 0xb8, 0xbd,
- 0xcd, 0xbe, 0x79, 0xef, 0xf7, 0xfe, 0xbf, 0x37, 0x24, 0xec, 0xd3, 0x50, 0x12, 0x8e, 0x87, 0x88,
- 0x86, 0x9e, 0x20, 0x38, 0xe6, 0x54, 0x8e, 0xbb, 0x18, 0x27, 0xdd, 0x88, 0xb3, 0x84, 0xfa, 0x84,
- 0x77, 0x93, 0xbd, 0xe2, 0xec, 0x44, 0x9c, 0x49, 0x66, 0xbe, 0x75, 0x8d, 0x8c, 0x83, 0x71, 0xe2,
- 0x14, 0x7c, 0xc9, 0xde, 0x9d, 0xb7, 0x6f, 0x02, 0x4e, 0xf6, 0xba, 0xcf, 0x28, 0x27, 0x29, 0xd6,
- 0x9d, 0x8d, 0x01, 0x1b, 0x30, 0x7d, 0xec, 0xaa, 0x53, 0x46, 0xdd, 0x1e, 0x30, 0x36, 0x08, 0x48,
- 0x57, 0x7f, 0xf5, 0xe3, 0x27, 0x5d, 0x49, 0x47, 0x44, 0x48, 0x34, 0x8a, 0x32, 0x86, 0xce, 0x34,
- 0x83, 0x1f, 0x73, 0x24, 0x29, 0x0b, 0x73, 0x00, 0xda, 0xc7, 0x5d, 0xcc, 0x38, 0xe9, 0xe2, 0x80,
- 0x92, 0x50, 0x2a, 0xad, 0xe9, 0x29, 0x63, 0xe8, 0x2a, 0x86, 0x80, 0x0e, 0x86, 0x32, 0x25, 0x8b,
- 0xae, 0x24, 0xa1, 0x4f, 0xf8, 0x88, 0xa6, 0xcc, 0xe5, 0x57, 0x26, 0xb0, 0x55, 0xb9, 0xc7, 0x7c,
- 0x1c, 0x49, 0xd6, 0xbd, 0x24, 0x63, 0x91, 0xdd, 0xbe, 0x83, 0x99, 0x18, 0x31, 0xd1, 0x25, 0xca,
- 0xff, 0x10, 0x93, 0x6e, 0xb2, 0xd7, 0x27, 0x12, 0xed, 0x15, 0x84, 0xdc, 0xee, 0x8c, 0xaf, 0x8f,
- 0x44, 0xc9, 0x83, 0x19, 0xcd, 0xec, 0xb6, 0x7f, 0x58, 0x00, 0xab, 0xc7, 0x42, 0x11, 0x8f, 0x08,
- 0x3f, 0xf0, 0x7d, 0xaa, 0x5c, 0x3a, 0xe5, 0x2c, 0x62, 0x02, 0x05, 0xe6, 0x06, 0xcc, 0x4b, 0x2a,
- 0x03, 0x62, 0x19, 0x3b, 0xc6, 0x6e, 0xd3, 0x4d, 0x3f, 0xcc, 0x1d, 0x68, 0xf9, 0x44, 0x60, 0x4e,
- 0x23, 0xc5, 0x6c, 0xd5, 0xf4, 0x5d, 0x95, 0x64, 0x6e, 0xc2, 0x62, 0x9a, 0x07, 0xea, 0x5b, 0x75,
- 0x7d, 0x7d, 0x4b, 0x7f, 0x1f, 0xfb, 0xe6, 0x27, 0xd0, 0xa6, 0x21, 0x95, 0x14, 0x05, 0xde, 0x90,
- 0xa8, 0x68, 0x58, 0x8d, 0x1d, 0x63, 0xb7, 0xb5, 0x7f, 0xc7, 0xa1, 0x7d, 0xec, 0xa8, 0x00, 0x3a,
- 0x59, 0xd8, 0x92, 0x3d, 0xe7, 0x81, 0xe6, 0x38, 0x6c, 0x7c, 0xfb, 0xfd, 0xf6, 0x9c, 0xbb, 0x9c,
- 0xc9, 0xa5, 0x44, 0xf3, 0x2e, 0x2c, 0x0d, 0x48, 0x48, 0x04, 0x15, 0xde, 0x10, 0x89, 0xa1, 0x35,
- 0xbf, 0x63, 0xec, 0x2e, 0xb9, 0xad, 0x8c, 0xf6, 0x00, 0x89, 0xa1, 0xb9, 0x0d, 0xad, 0x3e, 0x0d,
- 0x11, 0x1f, 0xa7, 0x1c, 0x0b, 0x9a, 0x03, 0x52, 0x92, 0x66, 0xe8, 0x01, 0x88, 0x08, 0x3d, 0x0b,
- 0x3d, 0x95, 0x6d, 0xeb, 0x56, 0x66, 0x48, 0x9a, 0x69, 0x27, 0xcf, 0xb4, 0x73, 0x9e, 0x97, 0xc2,
- 0xe1, 0xa2, 0x32, 0xe4, 0xab, 0x1f, 0xb6, 0x0d, 0xb7, 0xa9, 0xe5, 0xd4, 0x8d, 0xf9, 0x39, 0xac,
- 0xc6, 0x61, 0x9f, 0x85, 0x3e, 0x0d, 0x07, 0x5e, 0x44, 0x38, 0x65, 0xbe, 0xb5, 0xa8, 0xa1, 0x36,
- 0xaf, 0x40, 0x1d, 0x65, 0x45, 0x93, 0x22, 0x7d, 0xad, 0x90, 0x56, 0x0a, 0xe1, 0x53, 0x2d, 0x6b,
- 0x7e, 0x01, 0x26, 0xc6, 0x89, 0x36, 0x89, 0xc5, 0x32, 0x47, 0x6c, 0xce, 0x8e, 0xb8, 0x8a, 0x71,
- 0x72, 0x9e, 0x4a, 0x67, 0x90, 0xbf, 0x87, 0xdb, 0x92, 0xa3, 0x50, 0x3c, 0x21, 0x7c, 0x1a, 0x17,
- 0x66, 0xc7, 0x7d, 0x23, 0xc7, 0x98, 0x04, 0x7f, 0x00, 0x3b, 0x38, 0x2b, 0x20, 0x8f, 0x13, 0x9f,
- 0x0a, 0xc9, 0x69, 0x3f, 0x56, 0xb2, 0xde, 0x13, 0x8e, 0xb0, 0xae, 0x91, 0x96, 0x2e, 0x82, 0x4e,
- 0xce, 0xe7, 0x4e, 0xb0, 0x7d, 0x9c, 0x71, 0x99, 0x8f, 0xe0, 0x27, 0xfd, 0x80, 0xe1, 0x4b, 0xa1,
- 0x8c, 0xf3, 0x26, 0x90, 0xb4, 0xea, 0x11, 0x15, 0x42, 0xa1, 0x2d, 0xed, 0x18, 0xbb, 0x75, 0xf7,
- 0x6e, 0xca, 0x7b, 0x4a, 0xf8, 0x51, 0x85, 0xf3, 0xbc, 0xc2, 0x68, 0xbe, 0x07, 0xe6, 0x90, 0x0a,
- 0xc9, 0x38, 0xc5, 0x28, 0xf0, 0x48, 0x28, 0x39, 0x25, 0xc2, 0x5a, 0xd6, 0xe2, 0x6b, 0xe5, 0xcd,
- 0xfd, 0xf4, 0xc2, 0x7c, 0x08, 0x77, 0x6f, 0x54, 0xea, 0xe1, 0x21, 0x0a, 0x43, 0x12, 0x58, 0x6d,
- 0xed, 0xca, 0xb6, 0x7f, 0x83, 0xce, 0x5e, 0xca, 0x76, 0x6f, 0xf1, 0x8f, 0xdf, 0x6c, 0xcf, 0x7d,
- 0xfd, 0xcd, 0xf6, 0x9c, 0xfd, 0x0f, 0x03, 0x6e, 0xf7, 0x0a, 0xc7, 0x47, 0x2c, 0x41, 0xc1, 0xff,
- 0xb3, 0xc1, 0x0e, 0xa0, 0x29, 0x24, 0x8b, 0xd2, 0x92, 0x6e, 0xbc, 0x42, 0x49, 0x2f, 0x2a, 0x31,
- 0x75, 0x61, 0xff, 0xc5, 0x80, 0x8d, 0xfb, 0x4f, 0x63, 0x9a, 0x30, 0x8c, 0xfe, 0x27, 0xf3, 0xe0,
- 0x04, 0x96, 0x49, 0x05, 0x4f, 0x58, 0xf5, 0x9d, 0xfa, 0x6e, 0x6b, 0xff, 0x6d, 0x27, 0x1d, 0x4e,
- 0x4e, 0x31, 0xb3, 0xb2, 0x01, 0xe5, 0x54, 0xb5, 0xbb, 0x93, 0xb2, 0xf7, 0x6a, 0x96, 0x61, 0xff,
- 0xcd, 0x80, 0x3b, 0x2a, 0xd2, 0x03, 0xe2, 0x92, 0x67, 0x88, 0xfb, 0x47, 0x24, 0x64, 0x23, 0xf1,
- 0xda, 0x76, 0xda, 0xb0, 0xec, 0x6b, 0x24, 0x4f, 0x32, 0x0f, 0xf9, 0xbe, 0xb6, 0x53, 0xf3, 0x28,
- 0xe2, 0x39, 0x3b, 0xf0, 0x7d, 0x73, 0x17, 0x56, 0x4b, 0x1e, 0xae, 0xf2, 0xa9, 0xc2, 0xac, 0xd8,
- 0xda, 0x39, 0x9b, 0xce, 0x32, 0xb1, 0xff, 0x6d, 0xc0, 0xea, 0x27, 0x01, 0xeb, 0xa3, 0xe0, 0x2c,
- 0x40, 0x62, 0xa8, 0xaa, 0x6c, 0xac, 0xd2, 0xc3, 0x49, 0xd6, 0xde, 0xda, 0xbc, 0x99, 0xd3, 0xa3,
- 0xc4, 0xf4, 0xc0, 0xf9, 0x08, 0xd6, 0x8a, 0x86, 0x2b, 0xaa, 0x40, 0x7b, 0x73, 0xb8, 0xfe, 0xfc,
- 0xfb, 0xed, 0x95, 0xbc, 0xd8, 0x7a, 0xba, 0x22, 0x8e, 0xdc, 0x15, 0x3c, 0x41, 0xf0, 0xcd, 0x0e,
- 0xb4, 0x68, 0x1f, 0x7b, 0x82, 0x3c, 0xf5, 0xc2, 0x78, 0xa4, 0x0b, 0xa8, 0xe1, 0x36, 0x69, 0x1f,
- 0x9f, 0x91, 0xa7, 0x9f, 0xc7, 0x23, 0xf3, 0x7d, 0x78, 0x33, 0x5f, 0xac, 0x5e, 0x82, 0x02, 0x4f,
- 0xc9, 0xab, 0x70, 0x70, 0x5d, 0x4f, 0x4b, 0xee, 0x7a, 0x7e, 0x7b, 0x81, 0x02, 0xa5, 0xec, 0xc0,
- 0xf7, 0xb9, 0xfd, 0x62, 0x1e, 0x16, 0x4e, 0x11, 0x47, 0x23, 0x61, 0x9e, 0xc3, 0x8a, 0x24, 0xa3,
- 0x28, 0x40, 0x92, 0x78, 0xe9, 0x30, 0xcf, 0x3c, 0x7d, 0x57, 0x0f, 0xf9, 0xea, 0x12, 0x74, 0x2a,
- 0x6b, 0x2f, 0xd9, 0x73, 0x7a, 0x9a, 0x7a, 0x26, 0x91, 0x24, 0x6e, 0x3b, 0xc7, 0x48, 0x89, 0xe6,
- 0x07, 0x60, 0x49, 0x1e, 0x0b, 0x59, 0x8e, 0xd9, 0x72, 0xbe, 0xa4, 0xb9, 0x7c, 0x33, 0xbf, 0x4f,
- 0x27, 0x53, 0x31, 0x57, 0xae, 0x9f, 0xa8, 0xf5, 0xd7, 0x99, 0xa8, 0x67, 0xb0, 0xae, 0xd6, 0xd1,
- 0x34, 0x66, 0x63, 0x76, 0xcc, 0x35, 0x25, 0x3f, 0x09, 0xfa, 0x05, 0x98, 0x89, 0xc0, 0xd3, 0x98,
- 0xf3, 0xaf, 0x60, 0x67, 0x22, 0xf0, 0x24, 0xa4, 0x0f, 0x5b, 0x42, 0x15, 0x9f, 0x37, 0x22, 0x52,
- 0xcf, 0xe7, 0x28, 0x20, 0x21, 0x15, 0xc3, 0x1c, 0x7c, 0x61, 0x76, 0xf0, 0x4d, 0x0d, 0xf4, 0x99,
- 0xc2, 0x71, 0x73, 0x98, 0x4c, 0x4b, 0x0f, 0x3a, 0xd7, 0x6b, 0x29, 0x12, 0x74, 0x4b, 0x27, 0xe8,
- 0x47, 0xd7, 0x40, 0x14, 0x59, 0x12, 0xf0, 0x4e, 0x65, 0x8f, 0xa8, 0xae, 0xf6, 0x74, 0x43, 0x79,
- 0x9c, 0x0c, 0xd4, 0xb0, 0x45, 0xe9, 0x4a, 0x21, 0xa4, 0xd8, 0x85, 0xd9, 0xf4, 0x50, 0x4f, 0x9b,
- 0x62, 0x72, 0xf4, 0x18, 0x0d, 0xb3, 0x07, 0x83, 0x5d, 0xae, 0x9b, 0x62, 0x46, 0xb8, 0x15, 0xac,
- 0x8f, 0x09, 0x51, 0xdd, 0x5c, 0x59, 0x39, 0x24, 0x62, 0x78, 0xa8, 0x57, 0x62, 0xdd, 0x6d, 0x17,
- 0xeb, 0xe5, 0xbe, 0xa2, 0x3e, 0x6c, 0x2c, 0x2e, 0xae, 0x36, 0xed, 0x9f, 0x41, 0x53, 0x37, 0xf3,
- 0x01, 0xbe, 0x14, 0xe6, 0x16, 0x34, 0x55, 0x57, 0x10, 0x21, 0x88, 0xb0, 0x0c, 0x3d, 0x03, 0x4a,
- 0x82, 0x2d, 0x61, 0xf3, 0xa6, 0x87, 0x95, 0x30, 0x1f, 0xc3, 0xad, 0x88, 0xe8, 0xad, 0xaf, 0x05,
- 0x5b, 0xfb, 0x1f, 0x3a, 0x33, 0xbc, 0x71, 0x9d, 0x9b, 0x00, 0xdd, 0x1c, 0xcd, 0xe6, 0xe5, 0x73,
- 0x6e, 0x6a, 0xd9, 0x08, 0xf3, 0x62, 0x5a, 0xe9, 0xaf, 0x5f, 0x49, 0xe9, 0x14, 0x5e, 0xa9, 0xf3,
- 0x5d, 0x68, 0x1d, 0xa4, 0x6e, 0x7f, 0x4a, 0x85, 0xbc, 0x1a, 0x96, 0xa5, 0x6a, 0x58, 0x1e, 0x42,
- 0x3b, 0xdb, 0x91, 0xe7, 0x4c, 0x0f, 0x24, 0xf3, 0xc7, 0x00, 0xd9, 0x72, 0x55, 0x83, 0x2c, 0x1d,
- 0xd9, 0xcd, 0x8c, 0x72, 0xec, 0x4f, 0xec, 0xba, 0xda, 0xc4, 0xae, 0xb3, 0x5d, 0x58, 0xb9, 0x10,
- 0xf8, 0x37, 0xf9, 0x03, 0xea, 0x51, 0x24, 0xcc, 0x37, 0x60, 0x41, 0xf5, 0x50, 0x06, 0xd4, 0x70,
- 0xe7, 0x13, 0x81, 0x8f, 0xf5, 0xd4, 0x2e, 0x1f, 0x69, 0x2c, 0xf2, 0xa8, 0x2f, 0xac, 0xda, 0x4e,
- 0x7d, 0xb7, 0xe1, 0xb6, 0xe3, 0x52, 0xfc, 0xd8, 0x17, 0xf6, 0x6f, 0xa1, 0x55, 0x01, 0x34, 0xdb,
- 0x50, 0x2b, 0xb0, 0x6a, 0xd4, 0x37, 0xef, 0xc1, 0x66, 0x09, 0x34, 0x39, 0x86, 0x53, 0xc4, 0xa6,
- 0x7b, 0xbb, 0x60, 0x98, 0x98, 0xc4, 0xc2, 0x7e, 0x04, 0x1b, 0xc7, 0x65, 0xd3, 0x17, 0x43, 0x7e,
- 0xc2, 0x43, 0x63, 0x72, 0x9b, 0x6f, 0x41, 0xb3, 0xf8, 0x25, 0xa2, 0xbd, 0x6f, 0xb8, 0x25, 0xc1,
- 0x1e, 0xc1, 0xea, 0x85, 0xc0, 0x67, 0x24, 0xf4, 0x4b, 0xb0, 0x1b, 0x02, 0x70, 0x38, 0x0d, 0x34,
- 0xf3, 0x4b, 0xb7, 0x54, 0xc7, 0x60, 0xf3, 0x02, 0x05, 0xd4, 0x47, 0x92, 0xf1, 0x33, 0x22, 0xd3,
- 0x05, 0x7c, 0x8a, 0xf0, 0x25, 0x91, 0xc2, 0x74, 0xa1, 0x11, 0x50, 0x21, 0xb3, 0xca, 0xfa, 0xe0,
- 0xc6, 0xca, 0x4a, 0xf6, 0x9c, 0x9b, 0x40, 0x8e, 0x90, 0x44, 0x59, 0xef, 0x6a, 0x2c, 0xfb, 0xa7,
- 0xb0, 0xfe, 0x19, 0x92, 0x31, 0x27, 0xfe, 0x44, 0x8e, 0x57, 0xa1, 0xae, 0xf2, 0x67, 0xe8, 0xfc,
- 0xa9, 0xa3, 0x7a, 0x0f, 0x58, 0xf7, 0xbf, 0x8c, 0x18, 0x97, 0xc4, 0xbf, 0x12, 0x91, 0x97, 0x84,
- 0xf7, 0x12, 0xd6, 0x55, 0xb0, 0x04, 0x09, 0x7d, 0xaf, 0xf0, 0x33, 0xcd, 0x63, 0x6b, 0xff, 0x57,
- 0x33, 0x75, 0xc7, 0xb4, 0xba, 0xcc, 0x81, 0xb5, 0x64, 0x8a, 0x2e, 0xec, 0x3f, 0x19, 0x60, 0x9d,
- 0x90, 0xf1, 0x81, 0x10, 0x74, 0x10, 0x8e, 0x48, 0x28, 0xd5, 0x0c, 0x44, 0x98, 0xa8, 0xa3, 0xf9,
- 0x16, 0x2c, 0x17, 0x3b, 0x57, 0xaf, 0x5a, 0x43, 0xaf, 0xda, 0xa5, 0x9c, 0xa8, 0x1a, 0xcc, 0xbc,
- 0x07, 0x10, 0x71, 0x92, 0x78, 0xd8, 0xbb, 0x24, 0xe3, 0x2c, 0x8b, 0x5b, 0xd5, 0x15, 0x9a, 0xfe,
- 0x4e, 0x74, 0x4e, 0xe3, 0x7e, 0x40, 0xf1, 0x09, 0x19, 0xbb, 0x8b, 0x8a, 0xbf, 0x77, 0x42, 0xc6,
- 0xea, 0x4d, 0x14, 0xb1, 0x67, 0x84, 0xeb, 0xbd, 0x57, 0x77, 0xd3, 0x0f, 0xfb, 0xcf, 0x06, 0xdc,
- 0x2e, 0xd2, 0x91, 0x97, 0xeb, 0x69, 0xdc, 0x57, 0x12, 0x2f, 0x89, 0xdb, 0x15, 0x6b, 0x6b, 0xd7,
- 0x58, 0xfb, 0x11, 0x2c, 0x15, 0x0d, 0xa2, 0xec, 0xad, 0xcf, 0x60, 0x6f, 0x2b, 0x97, 0x38, 0x21,
- 0x63, 0xfb, 0x0f, 0x15, 0xdb, 0x0e, 0xc7, 0x95, 0xd9, 0xc7, 0xff, 0x8b, 0x6d, 0x85, 0xda, 0xaa,
- 0x6d, 0xb8, 0x2a, 0x7f, 0xc5, 0x81, 0xfa, 0x55, 0x07, 0xec, 0xbf, 0x1a, 0xb0, 0x51, 0xd5, 0x2a,
- 0xce, 0xd9, 0x29, 0x8f, 0x43, 0xf2, 0x32, 0xed, 0x65, 0xfb, 0xd5, 0xaa, 0xed, 0xf7, 0x18, 0xda,
- 0x13, 0x46, 0x89, 0x2c, 0x1a, 0xbf, 0x98, 0xa9, 0xc6, 0x2a, 0xd3, 0xd5, 0x5d, 0xae, 0xfa, 0x21,
- 0xec, 0xbf, 0x1b, 0xb0, 0x96, 0xdb, 0x58, 0x04, 0xcb, 0xfc, 0x39, 0x98, 0x85, 0x7b, 0xe5, 0xeb,
- 0x2d, 0x2d, 0xa9, 0xd5, 0xfc, 0x26, 0x7f, 0xba, 0x95, 0xa5, 0x51, 0xab, 0x94, 0x86, 0xf9, 0x29,
- 0xac, 0x17, 0x26, 0x47, 0x3a, 0x41, 0x33, 0x67, 0xb1, 0x78, 0x9f, 0x16, 0xa4, 0xc3, 0xc7, 0xdf,
- 0x3e, 0xef, 0x18, 0xdf, 0x3d, 0xef, 0x18, 0xff, 0x7a, 0xde, 0x31, 0xbe, 0x7a, 0xd1, 0x99, 0xfb,
- 0xee, 0x45, 0x67, 0xee, 0x9f, 0x2f, 0x3a, 0x73, 0xbf, 0xfb, 0x70, 0x40, 0xe5, 0x30, 0xee, 0x3b,
- 0x98, 0x8d, 0xba, 0xd9, 0x9f, 0x15, 0x65, 0x4c, 0xde, 0x2b, 0xfe, 0xc9, 0x49, 0x7e, 0xd9, 0xfd,
- 0x72, 0xf2, 0x7f, 0x22, 0x39, 0x8e, 0x88, 0xe8, 0x2f, 0xe8, 0xe9, 0xf5, 0xfe, 0x7f, 0x02, 0x00,
- 0x00, 0xff, 0xff, 0x0a, 0xef, 0x81, 0x2b, 0x58, 0x12, 0x00, 0x00,
+ 0x15, 0xd7, 0x8a, 0x94, 0x45, 0x0e, 0xf5, 0x77, 0xa4, 0xc4, 0x2b, 0x55, 0xa5, 0xe8, 0x4d, 0x93,
+ 0xaa, 0x71, 0xbd, 0x1b, 0x29, 0x2d, 0x60, 0x18, 0x0d, 0x02, 0x89, 0x72, 0x62, 0x59, 0x89, 0xcd,
+ 0xac, 0x54, 0x19, 0x6d, 0x0f, 0x8b, 0xe1, 0xec, 0x98, 0x1c, 0x68, 0xb9, 0xb3, 0x9e, 0x19, 0xae,
+ 0xc2, 0x4b, 0xcf, 0x3d, 0xb4, 0x40, 0x7a, 0x0b, 0x7a, 0x69, 0x5a, 0xa0, 0x40, 0xd1, 0x4b, 0xfb,
+ 0x31, 0x72, 0xcc, 0xb1, 0xa7, 0xa4, 0xb0, 0x0f, 0x3d, 0xf4, 0x4b, 0x14, 0x33, 0xfb, 0x97, 0x94,
+ 0xe4, 0xd2, 0x48, 0x73, 0x91, 0x76, 0xdf, 0xbc, 0xf7, 0x7b, 0x6f, 0xe6, 0xbd, 0x79, 0xbf, 0xc7,
+ 0x05, 0x7b, 0x34, 0x94, 0x84, 0xe3, 0x3e, 0xa2, 0xa1, 0x27, 0x08, 0x1e, 0x72, 0x2a, 0x47, 0x0e,
+ 0xc6, 0xb1, 0x13, 0x71, 0x16, 0x53, 0x9f, 0x70, 0x27, 0xde, 0xcd, 0x9f, 0xed, 0x88, 0x33, 0xc9,
+ 0xe0, 0x1b, 0x57, 0xd8, 0xd8, 0x18, 0xc7, 0x76, 0xae, 0x17, 0xef, 0x6e, 0xbe, 0x79, 0x1d, 0x70,
+ 0xbc, 0xeb, 0x5c, 0x50, 0x4e, 0x12, 0xac, 0xcd, 0xf5, 0x1e, 0xeb, 0x31, 0xfd, 0xe8, 0xa8, 0xa7,
+ 0x54, 0xba, 0xdd, 0x63, 0xac, 0x17, 0x10, 0x47, 0xbf, 0x75, 0x87, 0x4f, 0x1d, 0x49, 0x07, 0x44,
+ 0x48, 0x34, 0x88, 0x52, 0x85, 0xe6, 0xa4, 0x82, 0x3f, 0xe4, 0x48, 0x52, 0x16, 0x66, 0x00, 0xb4,
+ 0x8b, 0x1d, 0xcc, 0x38, 0x71, 0x70, 0x40, 0x49, 0x28, 0x95, 0xd7, 0xe4, 0x29, 0x55, 0x70, 0x94,
+ 0x42, 0x40, 0x7b, 0x7d, 0x99, 0x88, 0x85, 0x23, 0x49, 0xe8, 0x13, 0x3e, 0xa0, 0x89, 0x72, 0xf1,
+ 0x96, 0x1a, 0x6c, 0x95, 0xd6, 0x31, 0x1f, 0x45, 0x92, 0x39, 0xe7, 0x64, 0x24, 0xd2, 0xd5, 0xb7,
+ 0x30, 0x13, 0x03, 0x26, 0x1c, 0xa2, 0xf6, 0x1f, 0x62, 0xe2, 0xc4, 0xbb, 0x5d, 0x22, 0xd1, 0x6e,
+ 0x2e, 0xc8, 0xe2, 0x4e, 0xf5, 0xba, 0x48, 0x14, 0x3a, 0x98, 0xd1, 0x2c, 0xee, 0x55, 0x34, 0xa0,
+ 0x21, 0x73, 0xf4, 0xdf, 0x44, 0x64, 0xfd, 0xb6, 0x06, 0xcc, 0x36, 0x0b, 0xc5, 0x70, 0x40, 0xf8,
+ 0xbe, 0xef, 0x53, 0xb5, 0xcb, 0x0e, 0x67, 0x11, 0x13, 0x28, 0x80, 0xeb, 0x60, 0x4e, 0x52, 0x19,
+ 0x10, 0xd3, 0x68, 0x19, 0x3b, 0x75, 0x37, 0x79, 0x81, 0x2d, 0xd0, 0xf0, 0x89, 0xc0, 0x9c, 0x46,
+ 0x4a, 0xd9, 0x9c, 0xd5, 0x6b, 0x65, 0x11, 0xdc, 0x00, 0xb5, 0x24, 0x35, 0xd4, 0x37, 0x2b, 0x7a,
+ 0x79, 0x5e, 0xbf, 0x1f, 0xf9, 0xf0, 0x43, 0xb0, 0x44, 0x43, 0x2a, 0x29, 0x0a, 0xbc, 0x3e, 0x51,
+ 0x07, 0x64, 0x56, 0x5b, 0xc6, 0x4e, 0x63, 0x6f, 0xd3, 0xa6, 0x5d, 0x6c, 0xab, 0x33, 0xb5, 0xd3,
+ 0x93, 0x8c, 0x77, 0xed, 0x07, 0x5a, 0xe3, 0xa0, 0xfa, 0xe5, 0xd7, 0xdb, 0x33, 0xee, 0x62, 0x6a,
+ 0x97, 0x08, 0xe1, 0x2d, 0xb0, 0xd0, 0x23, 0x21, 0x11, 0x54, 0x78, 0x7d, 0x24, 0xfa, 0xe6, 0x5c,
+ 0xcb, 0xd8, 0x59, 0x70, 0x1b, 0xa9, 0xec, 0x01, 0x12, 0x7d, 0xb8, 0x0d, 0x1a, 0x5d, 0x1a, 0x22,
+ 0x3e, 0x4a, 0x34, 0x6e, 0x68, 0x0d, 0x90, 0x88, 0xb4, 0x42, 0x1b, 0x00, 0x11, 0xa1, 0x8b, 0xd0,
+ 0x53, 0x05, 0x60, 0xce, 0xa7, 0x81, 0x24, 0xc9, 0xb7, 0xb3, 0xe4, 0xdb, 0xa7, 0x59, 0x75, 0x1c,
+ 0xd4, 0x54, 0x20, 0x9f, 0x7d, 0xb3, 0x6d, 0xb8, 0x75, 0x6d, 0xa7, 0x56, 0xe0, 0x23, 0xb0, 0x32,
+ 0x0c, 0xbb, 0x2c, 0xf4, 0x69, 0xd8, 0xf3, 0x22, 0xc2, 0x29, 0xf3, 0xcd, 0x9a, 0x86, 0xda, 0xb8,
+ 0x04, 0x75, 0x98, 0xd6, 0x51, 0x82, 0xf4, 0xb9, 0x42, 0x5a, 0xce, 0x8d, 0x3b, 0xda, 0x16, 0x7e,
+ 0x02, 0x20, 0xc6, 0xb1, 0x0e, 0x89, 0x0d, 0x65, 0x86, 0x58, 0x9f, 0x1e, 0x71, 0x05, 0xe3, 0xf8,
+ 0x34, 0xb1, 0x4e, 0x21, 0x7f, 0x05, 0x6e, 0x4a, 0x8e, 0x42, 0xf1, 0x94, 0xf0, 0x49, 0x5c, 0x30,
+ 0x3d, 0xee, 0x6b, 0x19, 0xc6, 0x38, 0xf8, 0x03, 0xd0, 0xc2, 0x69, 0x01, 0x79, 0x9c, 0xf8, 0x54,
+ 0x48, 0x4e, 0xbb, 0x43, 0x65, 0xeb, 0x3d, 0xe5, 0x08, 0xeb, 0x1a, 0x69, 0xe8, 0x22, 0x68, 0x66,
+ 0x7a, 0xee, 0x98, 0xda, 0x07, 0xa9, 0x16, 0x7c, 0x0c, 0x7e, 0xd0, 0x0d, 0x18, 0x3e, 0x17, 0x2a,
+ 0x38, 0x6f, 0x0c, 0x49, 0xbb, 0x1e, 0x50, 0x21, 0x14, 0xda, 0x42, 0xcb, 0xd8, 0xa9, 0xb8, 0xb7,
+ 0x12, 0xdd, 0x0e, 0xe1, 0x87, 0x25, 0xcd, 0xd3, 0x92, 0x22, 0xbc, 0x03, 0x60, 0x9f, 0x0a, 0xc9,
+ 0x38, 0xc5, 0x28, 0xf0, 0x48, 0x28, 0x39, 0x25, 0xc2, 0x5c, 0xd4, 0xe6, 0xab, 0xc5, 0xca, 0xfd,
+ 0x64, 0x01, 0x3e, 0x04, 0xb7, 0xae, 0x75, 0xea, 0xe1, 0x3e, 0x0a, 0x43, 0x12, 0x98, 0x4b, 0x7a,
+ 0x2b, 0xdb, 0xfe, 0x35, 0x3e, 0xdb, 0x89, 0x1a, 0x5c, 0x03, 0x73, 0x92, 0x45, 0xde, 0x23, 0x73,
+ 0xb9, 0x65, 0xec, 0x2c, 0xba, 0x55, 0xc9, 0xa2, 0x47, 0xf0, 0x1d, 0xb0, 0x1e, 0xa3, 0x80, 0xfa,
+ 0x48, 0x32, 0x2e, 0xbc, 0x88, 0x5d, 0x10, 0xee, 0x61, 0x14, 0x99, 0x2b, 0x5a, 0x07, 0x16, 0x6b,
+ 0x1d, 0xb5, 0xd4, 0x46, 0x11, 0x7c, 0x1b, 0xac, 0xe6, 0x52, 0x4f, 0x10, 0xa9, 0xd5, 0x57, 0xb5,
+ 0xfa, 0x72, 0xbe, 0x70, 0x42, 0xa4, 0xd2, 0xdd, 0x02, 0x75, 0x14, 0x04, 0xec, 0x22, 0xa0, 0x42,
+ 0x9a, 0xb0, 0x55, 0xd9, 0xa9, 0xbb, 0x85, 0x00, 0x6e, 0x82, 0x9a, 0x4f, 0xc2, 0x91, 0x5e, 0x5c,
+ 0xd3, 0x8b, 0xf9, 0xfb, 0xbd, 0xda, 0x6f, 0xbe, 0xd8, 0x9e, 0xf9, 0xfc, 0x8b, 0xed, 0x19, 0xeb,
+ 0xef, 0x06, 0xb8, 0xd9, 0xce, 0xb3, 0x34, 0x60, 0x31, 0x0a, 0xbe, 0xcb, 0x6e, 0xb0, 0x0f, 0xea,
+ 0x42, 0x1d, 0x93, 0xbe, 0x7f, 0xd5, 0x57, 0xb8, 0x7f, 0x35, 0x65, 0xa6, 0x16, 0xac, 0x3f, 0x1a,
+ 0x60, 0xfd, 0xfe, 0xb3, 0x21, 0x8d, 0x19, 0x46, 0xff, 0x97, 0xe6, 0x75, 0x0c, 0x16, 0x49, 0x09,
+ 0x4f, 0x98, 0x95, 0x56, 0x65, 0xa7, 0xb1, 0xf7, 0xa6, 0x9d, 0x34, 0x57, 0x3b, 0xef, 0xb9, 0x69,
+ 0x83, 0xb5, 0xcb, 0xde, 0xdd, 0x71, 0xdb, 0x7b, 0xb3, 0xa6, 0x61, 0xfd, 0xd9, 0x00, 0x9b, 0xaa,
+ 0x2c, 0x7a, 0xc4, 0x25, 0x17, 0x88, 0xfb, 0x87, 0x24, 0x64, 0x03, 0xf1, 0xad, 0xe3, 0xb4, 0xc0,
+ 0xa2, 0xaf, 0x91, 0x3c, 0xc9, 0x3c, 0xe4, 0xfb, 0x3a, 0x4e, 0xad, 0xa3, 0x84, 0xa7, 0x6c, 0xdf,
+ 0xf7, 0xe1, 0x0e, 0x58, 0x29, 0x74, 0xb8, 0xca, 0xa7, 0x3a, 0x66, 0xa5, 0xb6, 0x94, 0xa9, 0xe9,
+ 0x2c, 0x13, 0xeb, 0x3f, 0x06, 0x58, 0xf9, 0x30, 0x60, 0x5d, 0x14, 0x9c, 0x04, 0x48, 0xf4, 0xd5,
+ 0x95, 0x18, 0xa9, 0xf4, 0x70, 0x92, 0xf6, 0x22, 0x1d, 0xde, 0xd4, 0xe9, 0x51, 0x66, 0xba, 0x3b,
+ 0xbe, 0x0f, 0x56, 0xf3, 0xee, 0x90, 0x57, 0x81, 0xde, 0xcd, 0xc1, 0xda, 0xf3, 0xaf, 0xb7, 0x97,
+ 0xb3, 0x62, 0x6b, 0xeb, 0x8a, 0x38, 0x74, 0x97, 0xf1, 0x98, 0xc0, 0x87, 0x4d, 0xd0, 0xa0, 0x5d,
+ 0xec, 0x09, 0xf2, 0xcc, 0x0b, 0x87, 0x03, 0x5d, 0x40, 0x55, 0xb7, 0x4e, 0xbb, 0xf8, 0x84, 0x3c,
+ 0x7b, 0x34, 0x1c, 0xc0, 0x77, 0xc1, 0xeb, 0xd9, 0x60, 0xe0, 0xc5, 0x28, 0xf0, 0x94, 0xbd, 0x3a,
+ 0x0e, 0xae, 0xeb, 0x69, 0xc1, 0x5d, 0xcb, 0x56, 0xcf, 0x50, 0xa0, 0x9c, 0xed, 0xfb, 0x3e, 0xb7,
+ 0x5e, 0xcc, 0x81, 0x1b, 0x1d, 0xc4, 0xd1, 0x40, 0xc0, 0x53, 0xb0, 0x2c, 0xc9, 0x20, 0x0a, 0x90,
+ 0x24, 0x5e, 0xc2, 0x3c, 0xe9, 0x4e, 0x6f, 0x6b, 0x46, 0x2a, 0x93, 0xb8, 0x5d, 0xa2, 0xed, 0x78,
+ 0xd7, 0x6e, 0x6b, 0xe9, 0x89, 0x44, 0x92, 0xb8, 0x4b, 0x19, 0x46, 0x22, 0x84, 0x77, 0x81, 0x29,
+ 0xf9, 0x50, 0xc8, 0x82, 0x13, 0x8a, 0x66, 0x98, 0xe4, 0xf2, 0xf5, 0x6c, 0x3d, 0x69, 0xa3, 0x79,
+ 0x13, 0xbc, 0xba, 0xfd, 0x57, 0xbe, 0x4d, 0xfb, 0x3f, 0x01, 0x6b, 0x8a, 0x3b, 0x27, 0x31, 0xab,
+ 0xd3, 0x63, 0xae, 0x2a, 0xfb, 0x71, 0xd0, 0x4f, 0x00, 0x8c, 0x05, 0x9e, 0xc4, 0x9c, 0x7b, 0x85,
+ 0x38, 0x63, 0x81, 0xc7, 0x21, 0x7d, 0xb0, 0x25, 0x54, 0xf1, 0x79, 0x03, 0x22, 0x35, 0x99, 0x44,
+ 0x01, 0x09, 0xa9, 0xe8, 0x67, 0xe0, 0x37, 0xa6, 0x07, 0xdf, 0xd0, 0x40, 0x1f, 0x2b, 0x1c, 0x37,
+ 0x83, 0x49, 0xbd, 0xb4, 0x41, 0xf3, 0x6a, 0x2f, 0x79, 0x82, 0xe6, 0x75, 0x82, 0xbe, 0x77, 0x05,
+ 0x44, 0x9e, 0x25, 0x01, 0xde, 0x2a, 0x91, 0x9e, 0xba, 0xd5, 0x9e, 0xbe, 0x50, 0x1e, 0x27, 0x3d,
+ 0xc5, 0x0c, 0x28, 0xe1, 0x3f, 0x42, 0x72, 0xe2, 0x4e, 0xbb, 0x87, 0x1a, 0xcd, 0xf2, 0xce, 0xd1,
+ 0x66, 0x34, 0x4c, 0xa7, 0x1b, 0xab, 0xe0, 0xc6, 0xbc, 0x47, 0xb8, 0x25, 0xac, 0x0f, 0x08, 0x51,
+ 0xb7, 0xb9, 0xc4, 0x8f, 0x24, 0x62, 0xb8, 0xaf, 0xf9, 0xbb, 0xe2, 0x2e, 0xe5, 0x5c, 0x78, 0x5f,
+ 0x49, 0x1f, 0x56, 0x6b, 0xb5, 0x95, 0xba, 0xf5, 0x23, 0x50, 0xd7, 0x97, 0x79, 0x1f, 0x9f, 0x0b,
+ 0xcd, 0x0e, 0xbe, 0xcf, 0x89, 0x10, 0x44, 0x98, 0x46, 0xca, 0x0e, 0x99, 0xc0, 0x92, 0x60, 0xe3,
+ 0xba, 0x29, 0x50, 0xc0, 0x27, 0x60, 0x3e, 0x22, 0x7a, 0x44, 0xd1, 0x86, 0x8d, 0xbd, 0xf7, 0xec,
+ 0x29, 0x66, 0x74, 0xfb, 0x3a, 0x40, 0x37, 0x43, 0xb3, 0x78, 0x31, 0x7b, 0x4e, 0x90, 0x8d, 0x80,
+ 0x67, 0x93, 0x4e, 0x7f, 0xf6, 0x4a, 0x4e, 0x27, 0xf0, 0x0a, 0x9f, 0xb7, 0x41, 0x63, 0x3f, 0xd9,
+ 0xf6, 0x47, 0x8a, 0x16, 0x2f, 0x1d, 0xcb, 0x42, 0xf9, 0x58, 0x1e, 0x82, 0xa5, 0x94, 0xd0, 0x4f,
+ 0x99, 0x6e, 0x48, 0xf0, 0xfb, 0x00, 0xa4, 0x93, 0x80, 0x6a, 0x64, 0x49, 0xcb, 0xae, 0xa7, 0x92,
+ 0x23, 0x7f, 0x8c, 0xeb, 0x66, 0xc7, 0xb8, 0xce, 0x72, 0xc1, 0xf2, 0x99, 0xc0, 0x3f, 0xcf, 0xa6,
+ 0xbd, 0xc7, 0x91, 0x80, 0xaf, 0x81, 0x1b, 0xea, 0x0e, 0xa5, 0x40, 0x55, 0x77, 0x2e, 0x16, 0xf8,
+ 0x48, 0x77, 0xed, 0x62, 0xa2, 0x64, 0x91, 0x47, 0x7d, 0x61, 0xce, 0xb6, 0x2a, 0x3b, 0x55, 0x77,
+ 0x69, 0x58, 0x98, 0x1f, 0xf9, 0xc2, 0xfa, 0x05, 0x68, 0x94, 0x00, 0xe1, 0x12, 0x98, 0xcd, 0xb1,
+ 0x66, 0xa9, 0x0f, 0xef, 0x81, 0x8d, 0x02, 0x68, 0xbc, 0x0d, 0x27, 0x88, 0x75, 0xf7, 0x66, 0xae,
+ 0x30, 0xd6, 0x89, 0x85, 0xf5, 0x18, 0xac, 0x1f, 0x15, 0x97, 0x3e, 0x6f, 0xf2, 0x63, 0x3b, 0x34,
+ 0xc6, 0xd9, 0x7c, 0x0b, 0xd4, 0xf3, 0x5f, 0x52, 0x7a, 0xf7, 0x55, 0xb7, 0x10, 0x58, 0x03, 0xb0,
+ 0x72, 0x26, 0xf0, 0x09, 0x09, 0xfd, 0x02, 0xec, 0x9a, 0x03, 0x38, 0x98, 0x04, 0x9a, 0x7a, 0x2c,
+ 0x2f, 0xdc, 0x31, 0xb0, 0x71, 0x56, 0x1e, 0x90, 0x34, 0x01, 0x77, 0x10, 0x3e, 0x27, 0x52, 0x40,
+ 0x17, 0x54, 0xf5, 0x20, 0x94, 0x54, 0xd6, 0xdd, 0x6b, 0x2b, 0x2b, 0xde, 0xb5, 0xaf, 0x03, 0x39,
+ 0x44, 0x12, 0xa5, 0x77, 0x57, 0x63, 0x59, 0x3f, 0x04, 0x6b, 0x1f, 0x23, 0x39, 0xe4, 0xc4, 0x1f,
+ 0xcb, 0xf1, 0x0a, 0xa8, 0xa8, 0xfc, 0x19, 0x3a, 0x7f, 0xea, 0x51, 0xcd, 0x03, 0xe6, 0xfd, 0x4f,
+ 0x23, 0xc6, 0x25, 0xf1, 0x2f, 0x9d, 0xc8, 0x4b, 0x8e, 0xf7, 0x1c, 0xac, 0xa9, 0xc3, 0x12, 0x24,
+ 0xf4, 0xbd, 0x7c, 0x9f, 0x49, 0x1e, 0x1b, 0x7b, 0x3f, 0x9d, 0xea, 0x76, 0x4c, 0xba, 0x4b, 0x37,
+ 0xb0, 0x1a, 0x4f, 0xc8, 0x85, 0xf5, 0x7b, 0x03, 0x98, 0xc7, 0x64, 0xb4, 0x2f, 0x04, 0xed, 0x85,
+ 0x03, 0x12, 0x4a, 0xd5, 0x03, 0x11, 0x26, 0xea, 0x11, 0xbe, 0x01, 0x16, 0x73, 0xce, 0xd5, 0x54,
+ 0x6b, 0x68, 0xaa, 0x5d, 0xc8, 0x84, 0xea, 0x82, 0xc1, 0x7b, 0x00, 0x44, 0x9c, 0xc4, 0x1e, 0xf6,
+ 0xce, 0xc9, 0x28, 0xcd, 0xe2, 0x56, 0x99, 0x42, 0x93, 0xdf, 0xb9, 0x76, 0x67, 0xd8, 0x0d, 0x28,
+ 0x3e, 0x26, 0x23, 0xb7, 0xa6, 0xf4, 0xdb, 0xc7, 0x64, 0xa4, 0x66, 0x22, 0x3d, 0x1d, 0x6b, 0xde,
+ 0xab, 0xb8, 0xc9, 0x8b, 0xf5, 0x07, 0x03, 0xdc, 0xcc, 0xd3, 0x91, 0x95, 0x6b, 0x67, 0xd8, 0x55,
+ 0x16, 0x2f, 0x39, 0xb7, 0x4b, 0xd1, 0xce, 0x5e, 0x11, 0xed, 0xfb, 0x60, 0x21, 0xbf, 0x20, 0x2a,
+ 0xde, 0xca, 0x14, 0xf1, 0x36, 0x32, 0x8b, 0x63, 0x32, 0xb2, 0x7e, 0x5d, 0x8a, 0xed, 0x60, 0x54,
+ 0xea, 0x7d, 0xfc, 0x7f, 0xc4, 0x96, 0xbb, 0x2d, 0xc7, 0x86, 0xcb, 0xf6, 0x97, 0x36, 0x50, 0xb9,
+ 0xbc, 0x01, 0xeb, 0x4f, 0x06, 0x58, 0x2f, 0x7b, 0x15, 0xa7, 0xac, 0xc3, 0x87, 0x21, 0x79, 0x99,
+ 0xf7, 0xe2, 0xfa, 0xcd, 0x96, 0xaf, 0xdf, 0x13, 0xb0, 0x34, 0x16, 0x94, 0x48, 0x4f, 0xe3, 0x9d,
+ 0xa9, 0x6a, 0xac, 0xd4, 0x5d, 0xdd, 0xc5, 0xf2, 0x3e, 0x84, 0xf5, 0x17, 0x03, 0xac, 0x66, 0x31,
+ 0xe6, 0x87, 0x05, 0x7f, 0x0c, 0x60, 0xbe, 0xbd, 0x62, 0x7a, 0x4b, 0x4a, 0x6a, 0x25, 0x5b, 0xc9,
+ 0x46, 0xb7, 0xa2, 0x34, 0x66, 0x4b, 0xa5, 0x01, 0x3f, 0x02, 0x6b, 0x79, 0xc8, 0x91, 0x4e, 0xd0,
+ 0xd4, 0x59, 0xcc, 0xe7, 0xd3, 0x5c, 0x64, 0xfd, 0xce, 0x28, 0xe8, 0x30, 0xe1, 0x63, 0xb1, 0x1f,
+ 0x04, 0xe9, 0x50, 0x0f, 0x23, 0x30, 0x9f, 0x50, 0xbe, 0x48, 0xfb, 0xc7, 0xd6, 0x95, 0xe4, 0x7e,
+ 0x48, 0xb0, 0xe6, 0xf7, 0xbb, 0xea, 0x8a, 0xfd, 0xed, 0x9b, 0xed, 0xdb, 0x3d, 0x2a, 0xfb, 0xc3,
+ 0xae, 0x8d, 0xd9, 0xc0, 0x49, 0xbf, 0xd3, 0x24, 0xff, 0xee, 0x08, 0xff, 0xdc, 0x91, 0xa3, 0x88,
+ 0x88, 0xcc, 0x46, 0xfc, 0xf5, 0xdf, 0xff, 0x78, 0xdb, 0x70, 0x33, 0x37, 0x07, 0x4f, 0xbe, 0x7c,
+ 0xde, 0x34, 0xbe, 0x7a, 0xde, 0x34, 0xfe, 0xf5, 0xbc, 0x69, 0x7c, 0xf6, 0xa2, 0x39, 0xf3, 0xd5,
+ 0x8b, 0xe6, 0xcc, 0x3f, 0x5f, 0x34, 0x67, 0x7e, 0xf9, 0xde, 0x65, 0xd0, 0x22, 0x47, 0x77, 0xf2,
+ 0x2f, 0x63, 0xf1, 0x4f, 0x9c, 0x4f, 0xc7, 0xbf, 0xbb, 0x69, 0x7f, 0xdd, 0x1b, 0xba, 0x9b, 0xbe,
+ 0xfb, 0xdf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x6d, 0xb7, 0x45, 0x0f, 0xa8, 0x13, 0x00, 0x00,
}
func (m *ConsumerAdditionProposal) Marshal() (dAtA []byte, err error) {
@@ -1623,6 +1702,47 @@ func (m *ConsumerAdditionProposal) MarshalToSizedBuffer(dAtA []byte) (int, error
_ = i
var l int
_ = l
+ if len(m.Denylist) > 0 {
+ for iNdEx := len(m.Denylist) - 1; iNdEx >= 0; iNdEx-- {
+ i -= len(m.Denylist[iNdEx])
+ copy(dAtA[i:], m.Denylist[iNdEx])
+ i = encodeVarintProvider(dAtA, i, uint64(len(m.Denylist[iNdEx])))
+ i--
+ dAtA[i] = 0x1
+ i--
+ dAtA[i] = 0x9a
+ }
+ }
+ if len(m.Allowlist) > 0 {
+ for iNdEx := len(m.Allowlist) - 1; iNdEx >= 0; iNdEx-- {
+ i -= len(m.Allowlist[iNdEx])
+ copy(dAtA[i:], m.Allowlist[iNdEx])
+ i = encodeVarintProvider(dAtA, i, uint64(len(m.Allowlist[iNdEx])))
+ i--
+ dAtA[i] = 0x1
+ i--
+ dAtA[i] = 0x92
+ }
+ }
+ if m.ValidatorSetCap != 0 {
+ i = encodeVarintProvider(dAtA, i, uint64(m.ValidatorSetCap))
+ i--
+ dAtA[i] = 0x1
+ i--
+ dAtA[i] = 0x88
+ }
+ if m.ValidatorsPowerCap != 0 {
+ i = encodeVarintProvider(dAtA, i, uint64(m.ValidatorsPowerCap))
+ i--
+ dAtA[i] = 0x1
+ i--
+ dAtA[i] = 0x80
+ }
+ if m.Top_N != 0 {
+ i = encodeVarintProvider(dAtA, i, uint64(m.Top_N))
+ i--
+ dAtA[i] = 0x78
+ }
if len(m.DistributionTransmissionChannel) > 0 {
i -= len(m.DistributionTransmissionChannel)
copy(dAtA[i:], m.DistributionTransmissionChannel)
@@ -2716,6 +2836,43 @@ func (m *ConsumerValidator) MarshalToSizedBuffer(dAtA []byte) (int, error) {
return len(dAtA) - i, nil
}
+func (m *ConsumerRewardsAllocation) 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 *ConsumerRewardsAllocation) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *ConsumerRewardsAllocation) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if len(m.Rewards) > 0 {
+ for iNdEx := len(m.Rewards) - 1; iNdEx >= 0; iNdEx-- {
+ {
+ size, err := m.Rewards[iNdEx].MarshalToSizedBuffer(dAtA[:i])
+ if err != nil {
+ return 0, err
+ }
+ i -= size
+ i = encodeVarintProvider(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0xa
+ }
+ }
+ return len(dAtA) - i, nil
+}
+
func encodeVarintProvider(dAtA []byte, offset int, v uint64) int {
offset -= sovProvider(v)
base := offset
@@ -2777,6 +2934,27 @@ func (m *ConsumerAdditionProposal) Size() (n int) {
if l > 0 {
n += 1 + l + sovProvider(uint64(l))
}
+ if m.Top_N != 0 {
+ n += 1 + sovProvider(uint64(m.Top_N))
+ }
+ if m.ValidatorsPowerCap != 0 {
+ n += 2 + sovProvider(uint64(m.ValidatorsPowerCap))
+ }
+ if m.ValidatorSetCap != 0 {
+ n += 2 + sovProvider(uint64(m.ValidatorSetCap))
+ }
+ if len(m.Allowlist) > 0 {
+ for _, s := range m.Allowlist {
+ l = len(s)
+ n += 2 + l + sovProvider(uint64(l))
+ }
+ }
+ if len(m.Denylist) > 0 {
+ for _, s := range m.Denylist {
+ l = len(s)
+ n += 2 + l + sovProvider(uint64(l))
+ }
+ }
return n
}
@@ -3207,6 +3385,21 @@ func (m *ConsumerValidator) Size() (n int) {
return n
}
+func (m *ConsumerRewardsAllocation) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ if len(m.Rewards) > 0 {
+ for _, e := range m.Rewards {
+ l = e.Size()
+ n += 1 + l + sovProvider(uint64(l))
+ }
+ }
+ return n
+}
+
func sovProvider(x uint64) (n int) {
return (math_bits.Len64(x|1) + 6) / 7
}
@@ -3673,6 +3866,127 @@ func (m *ConsumerAdditionProposal) Unmarshal(dAtA []byte) error {
}
m.DistributionTransmissionChannel = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
+ case 15:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Top_N", wireType)
+ }
+ m.Top_N = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowProvider
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.Top_N |= uint32(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 16:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field ValidatorsPowerCap", wireType)
+ }
+ m.ValidatorsPowerCap = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowProvider
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.ValidatorsPowerCap |= uint32(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 17:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field ValidatorSetCap", wireType)
+ }
+ m.ValidatorSetCap = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowProvider
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.ValidatorSetCap |= uint32(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 18:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Allowlist", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowProvider
+ }
+ 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 ErrInvalidLengthProvider
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthProvider
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Allowlist = append(m.Allowlist, string(dAtA[iNdEx:postIndex]))
+ iNdEx = postIndex
+ case 19:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Denylist", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowProvider
+ }
+ 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 ErrInvalidLengthProvider
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthProvider
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Denylist = append(m.Denylist, string(dAtA[iNdEx:postIndex]))
+ iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipProvider(dAtA[iNdEx:])
@@ -6639,6 +6953,90 @@ func (m *ConsumerValidator) Unmarshal(dAtA []byte) error {
}
return nil
}
+func (m *ConsumerRewardsAllocation) 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 ErrIntOverflowProvider
+ }
+ 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: ConsumerRewardsAllocation: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: ConsumerRewardsAllocation: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Rewards", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowProvider
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthProvider
+ }
+ postIndex := iNdEx + msglen
+ if postIndex < 0 {
+ return ErrInvalidLengthProvider
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Rewards = append(m.Rewards, types2.DecCoin{})
+ if err := m.Rewards[len(m.Rewards)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipProvider(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthProvider
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
func skipProvider(dAtA []byte) (n int, err error) {
l := len(dAtA)
iNdEx := 0
diff --git a/x/ccv/provider/types/query.pb.go b/x/ccv/provider/types/query.pb.go
index 84d4ff8e34..099c2be2db 100644
--- a/x/ccv/provider/types/query.pb.go
+++ b/x/ccv/provider/types/query.pb.go
@@ -7,11 +7,13 @@ import (
context "context"
fmt "fmt"
crypto "github.com/cometbft/cometbft/proto/tendermint/crypto"
+ _ "github.com/cosmos/cosmos-proto"
+ github_com_cosmos_cosmos_sdk_types "github.com/cosmos/cosmos-sdk/types"
_ "github.com/cosmos/gogoproto/gogoproto"
grpc1 "github.com/cosmos/gogoproto/grpc"
proto "github.com/cosmos/gogoproto/proto"
github_com_cosmos_gogoproto_types "github.com/cosmos/gogoproto/types"
- types "github.com/cosmos/interchain-security/v4/x/ccv/types"
+ types "github.com/cosmos/interchain-security/v5/x/ccv/types"
_ "google.golang.org/genproto/googleapis/api/annotations"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
@@ -374,6 +376,8 @@ func (m *QueryConsumerChainStopProposalsResponse) GetProposals() *ConsumerRemova
type Chain struct {
ChainId string `protobuf:"bytes,1,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"`
ClientId string `protobuf:"bytes,2,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty"`
+ // If chain with `chainID` is a Top-N chain, i.e., enforces at least one validator to validate chain `chainID`
+ Top_N uint32 `protobuf:"varint,3,opt,name=top_N,json=topN,proto3" json:"top_N,omitempty"`
}
func (m *Chain) Reset() { *m = Chain{} }
@@ -423,6 +427,13 @@ func (m *Chain) GetClientId() string {
return ""
}
+func (m *Chain) GetTop_N() uint32 {
+ if m != nil {
+ return m.Top_N
+ }
+ return 0
+}
+
type QueryValidatorConsumerAddrRequest struct {
// The id of the consumer chain
ChainId string `protobuf:"bytes,1,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"`
@@ -1013,9 +1024,9 @@ func (m *QueryAllPairsValConAddrByConsumerChainIDResponse) GetPairValConAddr() [
type PairValConAddrProviderAndConsumer struct {
// The consensus address of the validator on the provider chain
- ProviderAddress string `protobuf:"bytes,1,opt,name=provider_address,json=providerAddress,proto3" json:"provider_address,omitempty" yaml:"address"`
+ ProviderAddress string `protobuf:"bytes,1,opt,name=provider_address,json=providerAddress,proto3" json:"provider_address,omitempty" yaml:"provider_address"`
// The consensus address of the validator on the consumer chain
- ConsumerAddress string `protobuf:"bytes,2,opt,name=consumer_address,json=consumerAddress,proto3" json:"consumer_address,omitempty" yaml:"address"`
+ ConsumerAddress string `protobuf:"bytes,2,opt,name=consumer_address,json=consumerAddress,proto3" json:"consumer_address,omitempty" yaml:"consumer_address"`
ConsumerKey *crypto.PublicKey `protobuf:"bytes,3,opt,name=consumer_key,json=consumerKey,proto3" json:"consumer_key,omitempty"`
}
@@ -1153,6 +1164,299 @@ func (m *QueryParamsResponse) GetParams() Params {
return Params{}
}
+type QueryConsumerChainOptedInValidatorsRequest struct {
+ ChainId string `protobuf:"bytes,1,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"`
+}
+
+func (m *QueryConsumerChainOptedInValidatorsRequest) Reset() {
+ *m = QueryConsumerChainOptedInValidatorsRequest{}
+}
+func (m *QueryConsumerChainOptedInValidatorsRequest) String() string {
+ return proto.CompactTextString(m)
+}
+func (*QueryConsumerChainOptedInValidatorsRequest) ProtoMessage() {}
+func (*QueryConsumerChainOptedInValidatorsRequest) Descriptor() ([]byte, []int) {
+ return fileDescriptor_422512d7b7586cd7, []int{25}
+}
+func (m *QueryConsumerChainOptedInValidatorsRequest) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *QueryConsumerChainOptedInValidatorsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_QueryConsumerChainOptedInValidatorsRequest.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 *QueryConsumerChainOptedInValidatorsRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_QueryConsumerChainOptedInValidatorsRequest.Merge(m, src)
+}
+func (m *QueryConsumerChainOptedInValidatorsRequest) XXX_Size() int {
+ return m.Size()
+}
+func (m *QueryConsumerChainOptedInValidatorsRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_QueryConsumerChainOptedInValidatorsRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_QueryConsumerChainOptedInValidatorsRequest proto.InternalMessageInfo
+
+func (m *QueryConsumerChainOptedInValidatorsRequest) GetChainId() string {
+ if m != nil {
+ return m.ChainId
+ }
+ return ""
+}
+
+type QueryConsumerChainOptedInValidatorsResponse struct {
+ // The consensus addresses of the validators on the provider chain
+ ValidatorsProviderAddresses []string `protobuf:"bytes,1,rep,name=validators_provider_addresses,json=validatorsProviderAddresses,proto3" json:"validators_provider_addresses,omitempty"`
+}
+
+func (m *QueryConsumerChainOptedInValidatorsResponse) Reset() {
+ *m = QueryConsumerChainOptedInValidatorsResponse{}
+}
+func (m *QueryConsumerChainOptedInValidatorsResponse) String() string {
+ return proto.CompactTextString(m)
+}
+func (*QueryConsumerChainOptedInValidatorsResponse) ProtoMessage() {}
+func (*QueryConsumerChainOptedInValidatorsResponse) Descriptor() ([]byte, []int) {
+ return fileDescriptor_422512d7b7586cd7, []int{26}
+}
+func (m *QueryConsumerChainOptedInValidatorsResponse) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *QueryConsumerChainOptedInValidatorsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_QueryConsumerChainOptedInValidatorsResponse.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 *QueryConsumerChainOptedInValidatorsResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_QueryConsumerChainOptedInValidatorsResponse.Merge(m, src)
+}
+func (m *QueryConsumerChainOptedInValidatorsResponse) XXX_Size() int {
+ return m.Size()
+}
+func (m *QueryConsumerChainOptedInValidatorsResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_QueryConsumerChainOptedInValidatorsResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_QueryConsumerChainOptedInValidatorsResponse proto.InternalMessageInfo
+
+func (m *QueryConsumerChainOptedInValidatorsResponse) GetValidatorsProviderAddresses() []string {
+ if m != nil {
+ return m.ValidatorsProviderAddresses
+ }
+ return nil
+}
+
+type QueryConsumerChainsValidatorHasToValidateRequest struct {
+ // The consensus address of the validator on the provider chain
+ ProviderAddress string `protobuf:"bytes,1,opt,name=provider_address,json=providerAddress,proto3" json:"provider_address,omitempty" yaml:"address"`
+}
+
+func (m *QueryConsumerChainsValidatorHasToValidateRequest) Reset() {
+ *m = QueryConsumerChainsValidatorHasToValidateRequest{}
+}
+func (m *QueryConsumerChainsValidatorHasToValidateRequest) String() string {
+ return proto.CompactTextString(m)
+}
+func (*QueryConsumerChainsValidatorHasToValidateRequest) ProtoMessage() {}
+func (*QueryConsumerChainsValidatorHasToValidateRequest) Descriptor() ([]byte, []int) {
+ return fileDescriptor_422512d7b7586cd7, []int{27}
+}
+func (m *QueryConsumerChainsValidatorHasToValidateRequest) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *QueryConsumerChainsValidatorHasToValidateRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_QueryConsumerChainsValidatorHasToValidateRequest.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 *QueryConsumerChainsValidatorHasToValidateRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_QueryConsumerChainsValidatorHasToValidateRequest.Merge(m, src)
+}
+func (m *QueryConsumerChainsValidatorHasToValidateRequest) XXX_Size() int {
+ return m.Size()
+}
+func (m *QueryConsumerChainsValidatorHasToValidateRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_QueryConsumerChainsValidatorHasToValidateRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_QueryConsumerChainsValidatorHasToValidateRequest proto.InternalMessageInfo
+
+func (m *QueryConsumerChainsValidatorHasToValidateRequest) GetProviderAddress() string {
+ if m != nil {
+ return m.ProviderAddress
+ }
+ return ""
+}
+
+type QueryConsumerChainsValidatorHasToValidateResponse struct {
+ ConsumerChainIds []string `protobuf:"bytes,1,rep,name=consumer_chain_ids,json=consumerChainIds,proto3" json:"consumer_chain_ids,omitempty"`
+}
+
+func (m *QueryConsumerChainsValidatorHasToValidateResponse) Reset() {
+ *m = QueryConsumerChainsValidatorHasToValidateResponse{}
+}
+func (m *QueryConsumerChainsValidatorHasToValidateResponse) String() string {
+ return proto.CompactTextString(m)
+}
+func (*QueryConsumerChainsValidatorHasToValidateResponse) ProtoMessage() {}
+func (*QueryConsumerChainsValidatorHasToValidateResponse) Descriptor() ([]byte, []int) {
+ return fileDescriptor_422512d7b7586cd7, []int{28}
+}
+func (m *QueryConsumerChainsValidatorHasToValidateResponse) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *QueryConsumerChainsValidatorHasToValidateResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_QueryConsumerChainsValidatorHasToValidateResponse.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 *QueryConsumerChainsValidatorHasToValidateResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_QueryConsumerChainsValidatorHasToValidateResponse.Merge(m, src)
+}
+func (m *QueryConsumerChainsValidatorHasToValidateResponse) XXX_Size() int {
+ return m.Size()
+}
+func (m *QueryConsumerChainsValidatorHasToValidateResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_QueryConsumerChainsValidatorHasToValidateResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_QueryConsumerChainsValidatorHasToValidateResponse proto.InternalMessageInfo
+
+func (m *QueryConsumerChainsValidatorHasToValidateResponse) GetConsumerChainIds() []string {
+ if m != nil {
+ return m.ConsumerChainIds
+ }
+ return nil
+}
+
+type QueryValidatorConsumerCommissionRateRequest struct {
+ ChainId string `protobuf:"bytes,1,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"`
+ // The consensus address of the validator on the provider chain
+ ProviderAddress string `protobuf:"bytes,2,opt,name=provider_address,json=providerAddress,proto3" json:"provider_address,omitempty" yaml:"address"`
+}
+
+func (m *QueryValidatorConsumerCommissionRateRequest) Reset() {
+ *m = QueryValidatorConsumerCommissionRateRequest{}
+}
+func (m *QueryValidatorConsumerCommissionRateRequest) String() string {
+ return proto.CompactTextString(m)
+}
+func (*QueryValidatorConsumerCommissionRateRequest) ProtoMessage() {}
+func (*QueryValidatorConsumerCommissionRateRequest) Descriptor() ([]byte, []int) {
+ return fileDescriptor_422512d7b7586cd7, []int{29}
+}
+func (m *QueryValidatorConsumerCommissionRateRequest) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *QueryValidatorConsumerCommissionRateRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_QueryValidatorConsumerCommissionRateRequest.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 *QueryValidatorConsumerCommissionRateRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_QueryValidatorConsumerCommissionRateRequest.Merge(m, src)
+}
+func (m *QueryValidatorConsumerCommissionRateRequest) XXX_Size() int {
+ return m.Size()
+}
+func (m *QueryValidatorConsumerCommissionRateRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_QueryValidatorConsumerCommissionRateRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_QueryValidatorConsumerCommissionRateRequest proto.InternalMessageInfo
+
+func (m *QueryValidatorConsumerCommissionRateRequest) GetChainId() string {
+ if m != nil {
+ return m.ChainId
+ }
+ return ""
+}
+
+func (m *QueryValidatorConsumerCommissionRateRequest) GetProviderAddress() string {
+ if m != nil {
+ return m.ProviderAddress
+ }
+ return ""
+}
+
+type QueryValidatorConsumerCommissionRateResponse struct {
+ // The rate to charge delegators on the consumer chain, as a fraction
+ Rate github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,1,opt,name=rate,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"rate"`
+}
+
+func (m *QueryValidatorConsumerCommissionRateResponse) Reset() {
+ *m = QueryValidatorConsumerCommissionRateResponse{}
+}
+func (m *QueryValidatorConsumerCommissionRateResponse) String() string {
+ return proto.CompactTextString(m)
+}
+func (*QueryValidatorConsumerCommissionRateResponse) ProtoMessage() {}
+func (*QueryValidatorConsumerCommissionRateResponse) Descriptor() ([]byte, []int) {
+ return fileDescriptor_422512d7b7586cd7, []int{30}
+}
+func (m *QueryValidatorConsumerCommissionRateResponse) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *QueryValidatorConsumerCommissionRateResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_QueryValidatorConsumerCommissionRateResponse.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 *QueryValidatorConsumerCommissionRateResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_QueryValidatorConsumerCommissionRateResponse.Merge(m, src)
+}
+func (m *QueryValidatorConsumerCommissionRateResponse) XXX_Size() int {
+ return m.Size()
+}
+func (m *QueryValidatorConsumerCommissionRateResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_QueryValidatorConsumerCommissionRateResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_QueryValidatorConsumerCommissionRateResponse proto.InternalMessageInfo
+
type QueryOldestUnconfirmedVscRequest struct {
ChainId string `protobuf:"bytes,1,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"`
}
@@ -1161,7 +1465,7 @@ func (m *QueryOldestUnconfirmedVscRequest) Reset() { *m = QueryOldestUnc
func (m *QueryOldestUnconfirmedVscRequest) String() string { return proto.CompactTextString(m) }
func (*QueryOldestUnconfirmedVscRequest) ProtoMessage() {}
func (*QueryOldestUnconfirmedVscRequest) Descriptor() ([]byte, []int) {
- return fileDescriptor_422512d7b7586cd7, []int{25}
+ return fileDescriptor_422512d7b7586cd7, []int{31}
}
func (m *QueryOldestUnconfirmedVscRequest) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -1205,7 +1509,7 @@ func (m *QueryOldestUnconfirmedVscResponse) Reset() { *m = QueryOldestUn
func (m *QueryOldestUnconfirmedVscResponse) String() string { return proto.CompactTextString(m) }
func (*QueryOldestUnconfirmedVscResponse) ProtoMessage() {}
func (*QueryOldestUnconfirmedVscResponse) Descriptor() ([]byte, []int) {
- return fileDescriptor_422512d7b7586cd7, []int{26}
+ return fileDescriptor_422512d7b7586cd7, []int{32}
}
func (m *QueryOldestUnconfirmedVscResponse) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -1267,6 +1571,12 @@ func init() {
proto.RegisterType((*PairValConAddrProviderAndConsumer)(nil), "interchain_security.ccv.provider.v1.PairValConAddrProviderAndConsumer")
proto.RegisterType((*QueryParamsRequest)(nil), "interchain_security.ccv.provider.v1.QueryParamsRequest")
proto.RegisterType((*QueryParamsResponse)(nil), "interchain_security.ccv.provider.v1.QueryParamsResponse")
+ proto.RegisterType((*QueryConsumerChainOptedInValidatorsRequest)(nil), "interchain_security.ccv.provider.v1.QueryConsumerChainOptedInValidatorsRequest")
+ proto.RegisterType((*QueryConsumerChainOptedInValidatorsResponse)(nil), "interchain_security.ccv.provider.v1.QueryConsumerChainOptedInValidatorsResponse")
+ proto.RegisterType((*QueryConsumerChainsValidatorHasToValidateRequest)(nil), "interchain_security.ccv.provider.v1.QueryConsumerChainsValidatorHasToValidateRequest")
+ proto.RegisterType((*QueryConsumerChainsValidatorHasToValidateResponse)(nil), "interchain_security.ccv.provider.v1.QueryConsumerChainsValidatorHasToValidateResponse")
+ proto.RegisterType((*QueryValidatorConsumerCommissionRateRequest)(nil), "interchain_security.ccv.provider.v1.QueryValidatorConsumerCommissionRateRequest")
+ proto.RegisterType((*QueryValidatorConsumerCommissionRateResponse)(nil), "interchain_security.ccv.provider.v1.QueryValidatorConsumerCommissionRateResponse")
proto.RegisterType((*QueryOldestUnconfirmedVscRequest)(nil), "interchain_security.ccv.provider.v1.QueryOldestUnconfirmedVscRequest")
proto.RegisterType((*QueryOldestUnconfirmedVscResponse)(nil), "interchain_security.ccv.provider.v1.QueryOldestUnconfirmedVscResponse")
}
@@ -1276,101 +1586,122 @@ func init() {
}
var fileDescriptor_422512d7b7586cd7 = []byte{
- // 1501 bytes of a gzipped FileDescriptorProto
- 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x58, 0xcf, 0x73, 0xdb, 0x44,
- 0x14, 0x8e, 0x92, 0x36, 0x24, 0x9b, 0xfe, 0x62, 0x5b, 0x4a, 0xaa, 0x06, 0xbb, 0x55, 0x07, 0x48,
- 0x5b, 0x90, 0x12, 0x97, 0x0e, 0xfd, 0x41, 0x9a, 0xda, 0x49, 0x5a, 0x3c, 0x69, 0xa7, 0x41, 0x6d,
- 0xc3, 0x0c, 0x30, 0xa8, 0x1b, 0x69, 0xeb, 0x68, 0x2a, 0x6b, 0xd5, 0x5d, 0xd9, 0xad, 0xa7, 0xc3,
- 0xa1, 0x1c, 0xa0, 0x27, 0xa6, 0x33, 0xc0, 0xbd, 0x17, 0xfe, 0x01, 0xfe, 0x8a, 0x72, 0xa2, 0x4c,
- 0x2f, 0x9c, 0x0a, 0x93, 0x72, 0x60, 0x38, 0x31, 0x5c, 0x38, 0x31, 0xc3, 0x68, 0xb5, 0x92, 0x2d,
- 0x5b, 0xb1, 0x65, 0x27, 0x37, 0x7b, 0xb5, 0xef, 0x7b, 0xdf, 0xf7, 0xf4, 0xf6, 0xed, 0x67, 0x03,
- 0xcd, 0x76, 0x7d, 0x4c, 0xcd, 0x75, 0x64, 0xbb, 0x06, 0xc3, 0x66, 0x8d, 0xda, 0x7e, 0x43, 0x33,
- 0xcd, 0xba, 0xe6, 0x51, 0x52, 0xb7, 0x2d, 0x4c, 0xb5, 0xfa, 0xac, 0x76, 0xb7, 0x86, 0x69, 0x43,
- 0xf5, 0x28, 0xf1, 0x09, 0x3c, 0x96, 0x12, 0xa0, 0x9a, 0x66, 0x5d, 0x8d, 0x02, 0xd4, 0xfa, 0xac,
- 0x3c, 0x55, 0x21, 0xa4, 0xe2, 0x60, 0x0d, 0x79, 0xb6, 0x86, 0x5c, 0x97, 0xf8, 0xc8, 0xb7, 0x89,
- 0xcb, 0x42, 0x08, 0xf9, 0x40, 0x85, 0x54, 0x08, 0xff, 0xa8, 0x05, 0x9f, 0xc4, 0x6a, 0x5e, 0xc4,
- 0xf0, 0x6f, 0x6b, 0xb5, 0xdb, 0x9a, 0x6f, 0x57, 0x31, 0xf3, 0x51, 0xd5, 0x13, 0x1b, 0x0a, 0x59,
- 0xa8, 0xc6, 0x2c, 0xc2, 0x98, 0x99, 0xcd, 0x62, 0xea, 0xb3, 0x1a, 0x5b, 0x47, 0x14, 0x5b, 0x86,
- 0x49, 0x5c, 0x56, 0xab, 0xc6, 0x11, 0x6f, 0x76, 0x89, 0xb8, 0x67, 0x53, 0x2c, 0xb6, 0x4d, 0xf9,
- 0xd8, 0xb5, 0x30, 0xad, 0xda, 0xae, 0xaf, 0x99, 0xb4, 0xe1, 0xf9, 0x44, 0xbb, 0x83, 0x1b, 0x42,
- 0xa1, 0x72, 0x06, 0x1c, 0xfe, 0x28, 0xa8, 0xd9, 0x82, 0xc0, 0xbe, 0x8c, 0x5d, 0xcc, 0x6c, 0xa6,
- 0xe3, 0xbb, 0x35, 0xcc, 0x7c, 0x78, 0x08, 0x8c, 0x85, 0x09, 0x6c, 0x6b, 0x52, 0x3a, 0x22, 0x4d,
- 0x8f, 0xeb, 0xaf, 0xf0, 0xef, 0x65, 0x4b, 0x79, 0x00, 0xa6, 0xd2, 0x23, 0x99, 0x47, 0x5c, 0x86,
- 0xe1, 0xa7, 0x60, 0x77, 0x25, 0x5c, 0x32, 0x98, 0x8f, 0x7c, 0xcc, 0xe3, 0x27, 0x0a, 0x33, 0xea,
- 0x66, 0xaf, 0xa5, 0x3e, 0xab, 0xb6, 0x61, 0x5d, 0x0f, 0xe2, 0x4a, 0x3b, 0x9e, 0xbe, 0xc8, 0x0f,
- 0xe9, 0xbb, 0x2a, 0x2d, 0x6b, 0xca, 0x14, 0x90, 0x13, 0xc9, 0x17, 0x02, 0xb8, 0x88, 0xb5, 0x82,
- 0xda, 0x44, 0x45, 0x4f, 0x05, 0xb3, 0x12, 0x18, 0xe5, 0xe9, 0xd9, 0xa4, 0x74, 0x64, 0x64, 0x7a,
- 0xa2, 0x70, 0x42, 0xcd, 0xd0, 0x29, 0x2a, 0x07, 0xd1, 0x45, 0xa4, 0x72, 0x1c, 0xbc, 0xdd, 0x99,
- 0xe2, 0xba, 0x8f, 0xa8, 0xbf, 0x42, 0x89, 0x47, 0x18, 0x72, 0x62, 0x36, 0x8f, 0x24, 0x30, 0xdd,
- 0x7b, 0xaf, 0xe0, 0xf6, 0x19, 0x18, 0xf7, 0xa2, 0x45, 0x51, 0xb1, 0x0b, 0xd9, 0xe8, 0x09, 0xf0,
- 0xa2, 0x65, 0xd9, 0x41, 0x0b, 0x37, 0xa1, 0x9b, 0x80, 0xca, 0x34, 0x78, 0x2b, 0x8d, 0x09, 0xf1,
- 0x3a, 0x48, 0x7f, 0x25, 0xa5, 0x0b, 0x4c, 0x6c, 0x8d, 0xdf, 0x74, 0x07, 0xe7, 0xb9, 0xbe, 0x38,
- 0xeb, 0xb8, 0x4a, 0xea, 0xc8, 0x49, 0xa5, 0x3c, 0x0f, 0x76, 0xf2, 0xd4, 0x5d, 0x5a, 0x11, 0x1e,
- 0x06, 0xe3, 0xa6, 0x63, 0x63, 0xd7, 0x0f, 0x9e, 0x0d, 0xf3, 0x67, 0x63, 0xe1, 0x42, 0xd9, 0x52,
- 0xbe, 0x96, 0xc0, 0x51, 0xae, 0x64, 0x15, 0x39, 0xb6, 0x85, 0x7c, 0x42, 0x5b, 0x4a, 0x45, 0x7b,
- 0x37, 0x3a, 0x9c, 0x03, 0xfb, 0x22, 0xd2, 0x06, 0xb2, 0x2c, 0x8a, 0x19, 0x0b, 0x93, 0x94, 0xe0,
- 0x3f, 0x2f, 0xf2, 0x7b, 0x1a, 0xa8, 0xea, 0x9c, 0x53, 0xc4, 0x03, 0x45, 0xdf, 0x1b, 0xed, 0x2d,
- 0x86, 0x2b, 0xe7, 0xc6, 0x1e, 0x3d, 0xc9, 0x0f, 0xfd, 0xf9, 0x24, 0x3f, 0xa4, 0x5c, 0x03, 0x4a,
- 0x37, 0x22, 0xa2, 0x9a, 0xc7, 0xc1, 0xbe, 0xe8, 0xa0, 0xc7, 0xe9, 0x42, 0x46, 0x7b, 0xcd, 0x96,
- 0xfd, 0x41, 0xb2, 0x4e, 0x69, 0x2b, 0x2d, 0xc9, 0xb3, 0x49, 0xeb, 0xc8, 0xd5, 0x45, 0x5a, 0x5b,
- 0xfe, 0x6e, 0xd2, 0x92, 0x44, 0x9a, 0xd2, 0x3a, 0x2a, 0x29, 0xa4, 0xb5, 0x55, 0x4d, 0x39, 0x0c,
- 0x0e, 0x71, 0xc0, 0x1b, 0xeb, 0x94, 0xf8, 0xbe, 0x83, 0xf9, 0xb1, 0x8f, 0x9a, 0xf3, 0x17, 0x49,
- 0x1c, 0xff, 0xb6, 0xa7, 0x22, 0x4d, 0x1e, 0x4c, 0x30, 0x07, 0xb1, 0x75, 0xa3, 0x8a, 0x7d, 0x4c,
- 0x79, 0x86, 0x11, 0x1d, 0xf0, 0xa5, 0xab, 0xc1, 0x0a, 0x2c, 0x80, 0xd7, 0x5a, 0x36, 0x18, 0xc8,
- 0x71, 0xc8, 0x3d, 0xe4, 0x9a, 0x98, 0x6b, 0x1f, 0xd1, 0xf7, 0x37, 0xb7, 0x16, 0xa3, 0x47, 0xf0,
- 0x73, 0x30, 0xe9, 0xe2, 0xfb, 0xbe, 0x41, 0xb1, 0xe7, 0x60, 0xd7, 0x66, 0xeb, 0x86, 0x89, 0x5c,
- 0x2b, 0x10, 0x8b, 0x27, 0x47, 0x78, 0xcf, 0xcb, 0x6a, 0x78, 0x2f, 0xa8, 0xd1, 0xbd, 0xa0, 0xde,
- 0x88, 0xee, 0x85, 0xd2, 0x58, 0x30, 0xc3, 0x1e, 0xff, 0x96, 0x97, 0xf4, 0x83, 0x01, 0x8a, 0x1e,
- 0x81, 0x2c, 0x44, 0x18, 0xca, 0x3b, 0xe0, 0x04, 0x97, 0xa4, 0xe3, 0x8a, 0xcd, 0x7c, 0x4c, 0xb1,
- 0xd5, 0x3c, 0x1d, 0xf7, 0x10, 0xb5, 0x16, 0xb1, 0x4b, 0xaa, 0xf1, 0xf1, 0x5c, 0x02, 0x27, 0x33,
- 0xed, 0x16, 0x15, 0x39, 0x08, 0x46, 0x2d, 0xbe, 0xc2, 0x27, 0xde, 0xb8, 0x2e, 0xbe, 0x29, 0x39,
- 0x31, 0xc3, 0xc3, 0x93, 0x87, 0x2d, 0x7e, 0xd2, 0xca, 0x8b, 0x71, 0x9a, 0x87, 0x12, 0x78, 0x63,
- 0x93, 0x0d, 0x02, 0xf9, 0x16, 0xd8, 0xe3, 0xb5, 0x3e, 0x8b, 0x66, 0x6a, 0x21, 0xd3, 0x00, 0x48,
- 0xc0, 0x8a, 0x41, 0xdf, 0x86, 0xa7, 0x94, 0xc1, 0xee, 0xc4, 0x36, 0x38, 0x09, 0x44, 0xff, 0x2e,
- 0x26, 0xdb, 0x79, 0x11, 0xe6, 0x00, 0x88, 0x06, 0x47, 0x79, 0x91, 0xbf, 0xcc, 0x1d, 0x7a, 0xcb,
- 0x8a, 0x72, 0x05, 0x68, 0x5c, 0x4d, 0xd1, 0x71, 0x56, 0x90, 0x4d, 0xd9, 0x2a, 0x72, 0x16, 0x88,
- 0x1b, 0xb4, 0x5c, 0x29, 0x39, 0xe7, 0xca, 0x8b, 0x19, 0x2e, 0xc0, 0x1f, 0x24, 0x30, 0x93, 0x1d,
- 0x4e, 0xd4, 0xeb, 0x2e, 0x78, 0xd5, 0x43, 0x36, 0x35, 0xea, 0xc8, 0x09, 0xee, 0x73, 0x7e, 0x0c,
- 0x44, 0xc9, 0x2e, 0x65, 0x2b, 0x19, 0xb2, 0x69, 0x33, 0x51, 0x7c, 0xcc, 0xdc, 0x66, 0x03, 0xec,
- 0xf1, 0x12, 0x5b, 0x94, 0x0d, 0x09, 0x1c, 0xed, 0x19, 0x95, 0x3a, 0xe5, 0xa4, 0xcc, 0x53, 0x6e,
- 0x8b, 0x93, 0x04, 0xce, 0x83, 0x5d, 0x71, 0xf8, 0x1d, 0xdc, 0x10, 0x27, 0x6a, 0x4a, 0x6d, 0x7a,
- 0x17, 0x35, 0xf4, 0x2e, 0xea, 0x4a, 0x6d, 0xcd, 0xb1, 0xcd, 0x65, 0xdc, 0xd0, 0x27, 0xa2, 0x88,
- 0x65, 0xdc, 0x50, 0x0e, 0x00, 0x18, 0x36, 0x2a, 0xa2, 0xa8, 0x79, 0x4c, 0x6e, 0x81, 0xfd, 0x89,
- 0x55, 0xf1, 0x12, 0xca, 0x60, 0xd4, 0xe3, 0x2b, 0xe2, 0xb6, 0x3a, 0x99, 0xb1, 0xf2, 0x41, 0x88,
- 0xe8, 0x52, 0x01, 0xa0, 0xcc, 0x81, 0x23, 0x3c, 0xc3, 0x35, 0xc7, 0xc2, 0xcc, 0xbf, 0xe9, 0x9a,
- 0xc4, 0xbd, 0x6d, 0xd3, 0x2a, 0xb6, 0x56, 0x99, 0x99, 0xa1, 0x87, 0xbe, 0x89, 0x26, 0x78, 0x7a,
- 0xbc, 0xe0, 0x6b, 0x03, 0x58, 0x67, 0xa6, 0xc1, 0xb0, 0x6b, 0x19, 0xb1, 0xd7, 0x14, 0xdc, 0x4f,
- 0x67, 0xe2, 0xbe, 0xca, 0xcc, 0xeb, 0xd8, 0xb5, 0x9a, 0x03, 0x29, 0x54, 0xb1, 0xaf, 0xde, 0xb6,
- 0x5e, 0xf8, 0xe9, 0x20, 0xd8, 0xc9, 0x09, 0xc1, 0x0d, 0x09, 0x1c, 0x48, 0x33, 0x78, 0xf0, 0x62,
- 0xa6, 0x8c, 0x5d, 0x5c, 0xa5, 0x5c, 0xdc, 0x02, 0x42, 0x58, 0x12, 0x65, 0xe9, 0xcb, 0xe7, 0x7f,
- 0x7c, 0x3b, 0x3c, 0x0f, 0xe7, 0x7a, 0xff, 0x2c, 0x88, 0x1b, 0x4b, 0x38, 0x48, 0xed, 0x41, 0xf4,
- 0x36, 0xbe, 0x80, 0xcf, 0x25, 0xd1, 0x21, 0x49, 0xab, 0x08, 0xe7, 0xfb, 0x67, 0x98, 0xb0, 0xa0,
- 0xf2, 0xc5, 0xc1, 0x01, 0x84, 0xc2, 0xb3, 0x5c, 0xe1, 0x29, 0x38, 0xdb, 0x87, 0xc2, 0xd0, 0x9c,
- 0xc2, 0x87, 0xc3, 0x60, 0x72, 0x13, 0xc7, 0xc9, 0xe0, 0x95, 0x01, 0x99, 0xa5, 0x9a, 0x5b, 0xf9,
- 0xea, 0x36, 0xa1, 0x09, 0xd1, 0x1f, 0x72, 0xd1, 0x25, 0x78, 0xb1, 0x5f, 0xd1, 0xc1, 0x6f, 0x0c,
- 0xea, 0x1b, 0xb1, 0x6f, 0x84, 0xff, 0x49, 0xe0, 0xf5, 0x74, 0x03, 0xcb, 0xe0, 0xf2, 0xc0, 0xa4,
- 0x3b, 0x9d, 0xb2, 0x7c, 0x65, 0x7b, 0xc0, 0x44, 0x01, 0x2e, 0xf3, 0x02, 0x14, 0xe1, 0xfc, 0x00,
- 0x05, 0x20, 0x5e, 0x8b, 0xfe, 0xbf, 0x23, 0x8f, 0x94, 0xea, 0x36, 0xe1, 0xa5, 0xec, 0xac, 0xbb,
- 0xf9, 0x66, 0xf9, 0xf2, 0x96, 0x71, 0x84, 0xf0, 0x22, 0x17, 0x7e, 0x1e, 0x9e, 0xcd, 0xf0, 0x3b,
- 0x3f, 0x02, 0x32, 0x12, 0x57, 0x4e, 0x8a, 0xe4, 0x56, 0x17, 0x3a, 0x90, 0xe4, 0x14, 0x3f, 0x3d,
- 0x90, 0xe4, 0x34, 0x3b, 0x3c, 0x98, 0xe4, 0xc4, 0x25, 0x0d, 0x7f, 0x96, 0xc4, 0xbd, 0x97, 0x70,
- 0xc2, 0xf0, 0x42, 0x76, 0x8a, 0x69, 0x06, 0x5b, 0x9e, 0x1f, 0x38, 0x5e, 0x48, 0x3b, 0xc3, 0xa5,
- 0x15, 0xe0, 0x4c, 0x6f, 0x69, 0xbe, 0x00, 0x08, 0xff, 0x25, 0x80, 0xdf, 0x0f, 0x83, 0x63, 0x19,
- 0xac, 0x2d, 0xbc, 0x96, 0x9d, 0x62, 0x26, 0x4b, 0x2d, 0xaf, 0x6c, 0x1f, 0xa0, 0x28, 0xc2, 0x32,
- 0x2f, 0xc2, 0x12, 0x5c, 0xe8, 0x5d, 0x04, 0x1a, 0x23, 0x36, 0x7b, 0x9a, 0x72, 0x4c, 0x23, 0xb4,
- 0xea, 0xf0, 0xaf, 0x0e, 0x2b, 0x9e, 0x74, 0x98, 0x0c, 0xf6, 0x71, 0xab, 0x6e, 0xe2, 0xf7, 0xe5,
- 0xd2, 0x56, 0x20, 0x84, 0xea, 0x12, 0x57, 0xfd, 0x01, 0x3c, 0xd7, 0x5b, 0x75, 0xe4, 0xf4, 0x8d,
- 0xf6, 0x0b, 0xec, 0xbb, 0x61, 0xf1, 0x97, 0x49, 0x06, 0x6b, 0x0d, 0x6f, 0x64, 0x27, 0x9d, 0xdd,
- 0xf8, 0xcb, 0x37, 0xb7, 0x19, 0x55, 0x54, 0xe7, 0x3c, 0xaf, 0xce, 0x69, 0x78, 0xaa, 0xef, 0xf9,
- 0x6e, 0x5b, 0xf0, 0x47, 0x09, 0x4c, 0xb4, 0xf8, 0x59, 0xf8, 0x7e, 0x1f, 0xaf, 0xab, 0xd5, 0x17,
- 0xcb, 0x67, 0xfa, 0x0f, 0x14, 0xfc, 0x67, 0x38, 0xff, 0x13, 0x70, 0x3a, 0xc3, 0xdb, 0x0d, 0x49,
- 0xfe, 0x2b, 0x89, 0x9f, 0xf2, 0x69, 0x16, 0x17, 0x2e, 0x65, 0x67, 0xd2, 0xc5, 0x62, 0xcb, 0x97,
- 0xb6, 0x0a, 0xd3, 0xff, 0x91, 0x25, 0x1c, 0xc7, 0xa8, 0x35, 0x81, 0x8c, 0x3a, 0x33, 0x5b, 0xcc,
- 0x65, 0xe9, 0xe3, 0xa7, 0x1b, 0x39, 0xe9, 0xd9, 0x46, 0x4e, 0xfa, 0x7d, 0x23, 0x27, 0x3d, 0x7e,
- 0x99, 0x1b, 0x7a, 0xf6, 0x32, 0x37, 0xf4, 0xeb, 0xcb, 0xdc, 0xd0, 0x27, 0x73, 0x15, 0xdb, 0x5f,
- 0xaf, 0xad, 0xa9, 0x26, 0xa9, 0x6a, 0x26, 0x61, 0x55, 0xc2, 0x5a, 0xf2, 0xbd, 0x1b, 0xe7, 0xab,
- 0xbf, 0xa7, 0xdd, 0x6f, 0x1b, 0x96, 0x0d, 0x0f, 0xb3, 0xb5, 0x51, 0xfe, 0x0f, 0xc3, 0xa9, 0xff,
- 0x03, 0x00, 0x00, 0xff, 0xff, 0xe2, 0x62, 0xc2, 0x43, 0x13, 0x17, 0x00, 0x00,
+ // 1834 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x58, 0xcd, 0x6f, 0xdc, 0x5a,
+ 0x15, 0x8f, 0x93, 0x34, 0x24, 0x37, 0xaf, 0x7d, 0xe5, 0xb6, 0xbc, 0x97, 0x3a, 0xe9, 0x4c, 0x9e,
+ 0x1f, 0x3c, 0xd2, 0x2f, 0x3b, 0x99, 0xf2, 0x44, 0xbf, 0xd2, 0x34, 0x93, 0x49, 0xd2, 0x51, 0xda,
+ 0x66, 0xea, 0xa6, 0x01, 0x15, 0x84, 0xeb, 0xd8, 0xb7, 0x13, 0xab, 0x1e, 0x5f, 0xc7, 0xd7, 0x33,
+ 0xed, 0xa8, 0xaa, 0x44, 0x59, 0x40, 0x57, 0xa8, 0xe2, 0x63, 0xdf, 0x0d, 0x4b, 0x36, 0x08, 0xf1,
+ 0x2f, 0xd0, 0x1d, 0x85, 0x6e, 0x10, 0x8b, 0x80, 0x52, 0x16, 0x88, 0x15, 0xaa, 0x90, 0x58, 0x21,
+ 0x21, 0x5f, 0x5f, 0x7f, 0xcd, 0x38, 0x33, 0x9e, 0x49, 0x58, 0x25, 0x73, 0x7d, 0xef, 0xef, 0x9c,
+ 0xdf, 0xf1, 0x39, 0xe7, 0x9e, 0x9f, 0x81, 0x64, 0x58, 0x2e, 0x72, 0xb4, 0x6d, 0xd5, 0xb0, 0x14,
+ 0x82, 0xb4, 0xba, 0x63, 0xb8, 0x4d, 0x49, 0xd3, 0x1a, 0x92, 0xed, 0xe0, 0x86, 0xa1, 0x23, 0x47,
+ 0x6a, 0xcc, 0x49, 0x3b, 0x75, 0xe4, 0x34, 0x45, 0xdb, 0xc1, 0x2e, 0x86, 0x9f, 0xa7, 0x1c, 0x10,
+ 0x35, 0xad, 0x21, 0x06, 0x07, 0xc4, 0xc6, 0x1c, 0x3f, 0x55, 0xc5, 0xb8, 0x6a, 0x22, 0x49, 0xb5,
+ 0x0d, 0x49, 0xb5, 0x2c, 0xec, 0xaa, 0xae, 0x81, 0x2d, 0xe2, 0x43, 0xf0, 0x27, 0xab, 0xb8, 0x8a,
+ 0xe9, 0xbf, 0x92, 0xf7, 0x1f, 0x5b, 0xcd, 0xb3, 0x33, 0xf4, 0xd7, 0x56, 0xfd, 0x91, 0xe4, 0x1a,
+ 0x35, 0x44, 0x5c, 0xb5, 0x66, 0xb3, 0x0d, 0x85, 0x2c, 0xae, 0x86, 0x5e, 0xf8, 0x67, 0x66, 0xf7,
+ 0x3b, 0xd3, 0x98, 0x93, 0xc8, 0xb6, 0xea, 0x20, 0x5d, 0xd1, 0xb0, 0x45, 0xea, 0xb5, 0xf0, 0xc4,
+ 0x37, 0x3a, 0x9c, 0x78, 0x62, 0x38, 0x88, 0x6d, 0x9b, 0x72, 0x91, 0xa5, 0x23, 0xa7, 0x66, 0x58,
+ 0xae, 0xa4, 0x39, 0x4d, 0xdb, 0xc5, 0xd2, 0x63, 0xd4, 0x0c, 0x18, 0x9e, 0xd2, 0x30, 0xa9, 0x61,
+ 0xa2, 0xf8, 0x24, 0xfd, 0x1f, 0xfe, 0x23, 0xe1, 0x12, 0x98, 0xbc, 0xeb, 0x85, 0x73, 0x89, 0x99,
+ 0x5d, 0x45, 0x16, 0x22, 0x06, 0x91, 0xd1, 0x4e, 0x1d, 0x11, 0x17, 0x9e, 0x02, 0xa3, 0xbe, 0x6d,
+ 0x43, 0x9f, 0xe0, 0xa6, 0xb9, 0x99, 0x31, 0xf9, 0x2b, 0xf4, 0x77, 0x59, 0x17, 0x9e, 0x81, 0xa9,
+ 0xf4, 0x93, 0xc4, 0xc6, 0x16, 0x41, 0xf0, 0x7b, 0xe0, 0x68, 0xd5, 0x5f, 0x52, 0x88, 0xab, 0xba,
+ 0x88, 0x9e, 0x1f, 0x2f, 0xcc, 0x8a, 0xfb, 0xbd, 0xb1, 0xc6, 0x9c, 0xd8, 0x82, 0x75, 0xcf, 0x3b,
+ 0x57, 0x1c, 0x7e, 0xb3, 0x9b, 0x1f, 0x90, 0x3f, 0xaa, 0xc6, 0xd6, 0x84, 0x29, 0xc0, 0x27, 0x8c,
+ 0x2f, 0x79, 0x70, 0x81, 0xd7, 0x82, 0xda, 0x42, 0x2a, 0x78, 0xca, 0x3c, 0x2b, 0x82, 0x11, 0x6a,
+ 0x9e, 0x4c, 0x70, 0xd3, 0x43, 0x33, 0xe3, 0x85, 0xb3, 0x62, 0x86, 0x24, 0x12, 0x29, 0x88, 0xcc,
+ 0x4e, 0x0a, 0x67, 0xc0, 0x37, 0xdb, 0x4d, 0xdc, 0x73, 0x55, 0xc7, 0xad, 0x38, 0xd8, 0xc6, 0x44,
+ 0x35, 0x43, 0x6f, 0x5e, 0x72, 0x60, 0xa6, 0xfb, 0x5e, 0xe6, 0xdb, 0xf7, 0xc1, 0x98, 0x1d, 0x2c,
+ 0xb2, 0x88, 0x5d, 0xcf, 0xe6, 0x1e, 0x03, 0x5f, 0xd4, 0x75, 0xc3, 0xcb, 0xee, 0x08, 0x3a, 0x02,
+ 0x14, 0x66, 0xc0, 0x17, 0x69, 0x9e, 0x60, 0xbb, 0xcd, 0xe9, 0x1f, 0x73, 0xe9, 0x04, 0x13, 0x5b,
+ 0xc3, 0x37, 0xdd, 0xe6, 0xf3, 0x7c, 0x4f, 0x3e, 0xcb, 0xa8, 0x86, 0x1b, 0xaa, 0x99, 0xea, 0xf2,
+ 0x06, 0x38, 0x42, 0x4d, 0x77, 0x48, 0x45, 0x38, 0x09, 0xc6, 0x34, 0xd3, 0x40, 0x96, 0xeb, 0x3d,
+ 0x1b, 0xa4, 0xcf, 0x46, 0xfd, 0x85, 0xb2, 0x0e, 0x4f, 0x80, 0x23, 0x2e, 0xb6, 0x95, 0x3b, 0x13,
+ 0x43, 0xd3, 0xdc, 0xcc, 0x51, 0x79, 0xd8, 0xc5, 0xf6, 0x1d, 0xe1, 0x27, 0x1c, 0xf8, 0x8c, 0xd2,
+ 0xdb, 0x54, 0x4d, 0x43, 0x57, 0x5d, 0xec, 0xc4, 0xe2, 0xe7, 0x74, 0xcf, 0x7e, 0x38, 0x0f, 0x8e,
+ 0x07, 0x4c, 0x14, 0x55, 0xd7, 0x1d, 0x44, 0x88, 0x6f, 0xb9, 0x08, 0x3f, 0xec, 0xe6, 0x8f, 0x35,
+ 0xd5, 0x9a, 0x79, 0x45, 0x60, 0x0f, 0x04, 0xf9, 0xe3, 0x60, 0xef, 0xa2, 0xbf, 0x72, 0x65, 0xf4,
+ 0xe5, 0xeb, 0xfc, 0xc0, 0x3f, 0x5e, 0xe7, 0x07, 0x84, 0x75, 0x20, 0x74, 0x72, 0x84, 0x85, 0xf8,
+ 0x0c, 0x38, 0x1e, 0x34, 0x86, 0xd0, 0x9c, 0xef, 0xd1, 0xc7, 0x5a, 0x6c, 0xbf, 0x67, 0xac, 0x9d,
+ 0x5a, 0x25, 0x66, 0x3c, 0x1b, 0xb5, 0x36, 0x5b, 0x1d, 0xa8, 0xb5, 0xd8, 0xef, 0x44, 0x2d, 0xe9,
+ 0x48, 0x44, 0xad, 0x2d, 0x92, 0x8c, 0x5a, 0x4b, 0xd4, 0x84, 0x49, 0x70, 0x8a, 0x02, 0x6e, 0x6c,
+ 0x3b, 0xd8, 0x75, 0x4d, 0x44, 0x7b, 0x41, 0x90, 0xb1, 0x7f, 0xe4, 0x58, 0x4f, 0x68, 0x79, 0xca,
+ 0xcc, 0xe4, 0xc1, 0x38, 0x31, 0x55, 0xb2, 0xad, 0xd4, 0x90, 0x8b, 0x1c, 0x6a, 0x61, 0x48, 0x06,
+ 0x74, 0xe9, 0xb6, 0xb7, 0x02, 0x0b, 0xe0, 0x6b, 0xb1, 0x0d, 0x8a, 0x6a, 0x9a, 0xf8, 0x89, 0x6a,
+ 0x69, 0x88, 0x72, 0x1f, 0x92, 0x4f, 0x44, 0x5b, 0x17, 0x83, 0x47, 0xf0, 0x07, 0x60, 0xc2, 0x42,
+ 0x4f, 0x5d, 0xc5, 0x41, 0xb6, 0x89, 0x2c, 0x83, 0x6c, 0x2b, 0x9a, 0x6a, 0xe9, 0x1e, 0x59, 0x44,
+ 0xd3, 0x6d, 0xbc, 0xc0, 0x8b, 0xfe, 0x3d, 0x22, 0x06, 0xf7, 0x88, 0xb8, 0x11, 0xdc, 0x23, 0xc5,
+ 0x51, 0xaf, 0xb1, 0xbd, 0xfa, 0x6b, 0x9e, 0x93, 0x3f, 0xf1, 0x50, 0xe4, 0x00, 0x64, 0x29, 0xc0,
+ 0x10, 0xce, 0x83, 0xb3, 0x94, 0x92, 0x8c, 0xaa, 0x06, 0x71, 0x91, 0x83, 0xf4, 0xa8, 0x64, 0x9e,
+ 0xa8, 0x8e, 0x5e, 0x42, 0x16, 0xae, 0x85, 0x35, 0xbb, 0x0c, 0xce, 0x65, 0xda, 0xcd, 0x22, 0xf2,
+ 0x09, 0x18, 0xd1, 0xe9, 0x0a, 0x6d, 0x83, 0x63, 0x32, 0xfb, 0x25, 0xe4, 0x58, 0x63, 0xf7, 0xcb,
+ 0x11, 0xe9, 0xb4, 0xfc, 0xca, 0xa5, 0xd0, 0xcc, 0x0b, 0x0e, 0x9c, 0xde, 0x67, 0x03, 0x43, 0x7e,
+ 0x08, 0x8e, 0xd9, 0xf1, 0x67, 0x41, 0xa3, 0x2d, 0x64, 0xea, 0x0a, 0x09, 0x58, 0xd6, 0xfd, 0x5b,
+ 0xf0, 0x84, 0x32, 0x38, 0x9a, 0xd8, 0x06, 0x27, 0x00, 0xcb, 0xdf, 0x52, 0x32, 0x9d, 0x4b, 0x30,
+ 0x07, 0x40, 0xd0, 0x4d, 0xca, 0x25, 0xfa, 0x32, 0x87, 0xe5, 0xd8, 0x8a, 0x70, 0x0b, 0x48, 0x94,
+ 0xcd, 0xa2, 0x69, 0x56, 0x54, 0xc3, 0x21, 0x9b, 0xaa, 0xb9, 0x84, 0x2d, 0x2f, 0xe5, 0x8a, 0xc9,
+ 0xe6, 0x57, 0x2e, 0x65, 0xb8, 0x15, 0x7f, 0xc5, 0x81, 0xd9, 0xec, 0x70, 0x2c, 0x5e, 0x3b, 0xe0,
+ 0xab, 0xb6, 0x6a, 0x38, 0x4a, 0x43, 0x35, 0xbd, 0xfb, 0x9f, 0x96, 0x01, 0x0b, 0xd9, 0x4a, 0xb6,
+ 0x90, 0xa9, 0x86, 0x13, 0x19, 0x0a, 0xcb, 0xcc, 0x8a, 0x12, 0xe0, 0x98, 0x9d, 0xd8, 0x22, 0xfc,
+ 0x9b, 0x03, 0x9f, 0x75, 0x3d, 0x05, 0x57, 0xf6, 0xab, 0xcd, 0xe2, 0xe4, 0x87, 0xdd, 0xfc, 0xa7,
+ 0x7e, 0x2b, 0x68, 0xdd, 0xd1, 0xde, 0xee, 0x3c, 0x9c, 0x7d, 0x5a, 0x4a, 0x0c, 0xa7, 0x75, 0x47,
+ 0x7b, 0x6f, 0x81, 0x0b, 0xe0, 0xa3, 0x70, 0xd7, 0x63, 0xd4, 0x64, 0x35, 0x36, 0x25, 0x46, 0xd3,
+ 0x8f, 0xe8, 0x4f, 0x3f, 0x62, 0xa5, 0xbe, 0x65, 0x1a, 0xda, 0x1a, 0x6a, 0xca, 0xe3, 0xc1, 0x89,
+ 0x35, 0xd4, 0x14, 0x4e, 0x02, 0xe8, 0xa7, 0xae, 0xea, 0xa8, 0x51, 0xe1, 0x3c, 0x04, 0x27, 0x12,
+ 0xab, 0xec, 0xb5, 0x94, 0xc1, 0x88, 0x4d, 0x57, 0xd8, 0xa5, 0x76, 0x2e, 0xe3, 0xbb, 0xf0, 0x8e,
+ 0xb0, 0xbc, 0x65, 0x00, 0xc2, 0x2a, 0x2b, 0xe4, 0x44, 0x06, 0xac, 0xdb, 0x2e, 0xd2, 0xcb, 0x56,
+ 0xd8, 0x1e, 0xb3, 0x4c, 0x5d, 0x3b, 0xac, 0xc6, 0xbb, 0x01, 0x85, 0xa3, 0xce, 0xe9, 0x46, 0xb8,
+ 0xaa, 0xb4, 0xbe, 0x29, 0x14, 0x94, 0xfe, 0x64, 0xb4, 0xa9, 0x92, 0x7c, 0x75, 0x88, 0x08, 0x3b,
+ 0x2c, 0xa3, 0x93, 0xd3, 0x54, 0x68, 0xec, 0xa6, 0x4a, 0x36, 0x30, 0xfb, 0x15, 0x34, 0xe3, 0xd4,
+ 0xeb, 0x91, 0xcb, 0x7c, 0x3d, 0x0a, 0x2a, 0x98, 0xeb, 0xc1, 0x24, 0xe3, 0x7a, 0x1e, 0xc0, 0x30,
+ 0x39, 0x82, 0xf0, 0x05, 0x04, 0xc3, 0xf4, 0xf3, 0x4b, 0x4f, 0xa7, 0xd7, 0xe4, 0xb9, 0xf4, 0x8b,
+ 0x77, 0x09, 0xd7, 0x6a, 0x06, 0x21, 0x06, 0xb6, 0xe4, 0x18, 0xa3, 0xff, 0xdb, 0x2c, 0x20, 0xfc,
+ 0x90, 0x03, 0xe7, 0xb3, 0x79, 0xc2, 0x88, 0x56, 0xc0, 0xb0, 0x13, 0x0c, 0xd4, 0x63, 0xc5, 0x6b,
+ 0x5e, 0xa2, 0xfd, 0x65, 0x37, 0xff, 0x45, 0xd5, 0x70, 0xb7, 0xeb, 0x5b, 0xa2, 0x86, 0x6b, 0x6c,
+ 0xc4, 0x67, 0x7f, 0x2e, 0x10, 0xfd, 0xb1, 0xe4, 0x36, 0x6d, 0x44, 0xc4, 0x12, 0xd2, 0xfe, 0xf4,
+ 0xdb, 0x0b, 0x80, 0x29, 0x80, 0x12, 0xd2, 0x64, 0x8a, 0x24, 0xcc, 0x83, 0x69, 0xea, 0xc1, 0xba,
+ 0xa9, 0x23, 0xe2, 0xde, 0xb7, 0x34, 0x6c, 0x3d, 0x32, 0x9c, 0x1a, 0xd2, 0x37, 0x89, 0x96, 0x21,
+ 0x29, 0x7f, 0x1a, 0x8c, 0x1c, 0xe9, 0xe7, 0x99, 0xdb, 0x06, 0x80, 0x0d, 0xa2, 0x29, 0x04, 0x59,
+ 0xba, 0x12, 0x8a, 0x29, 0x56, 0x5a, 0x5f, 0x66, 0x2a, 0xad, 0x4d, 0xa2, 0xdd, 0x43, 0x96, 0x1e,
+ 0xdd, 0xa0, 0x7e, 0x91, 0x1d, 0x6f, 0xb4, 0xac, 0x17, 0x7e, 0x7f, 0x1a, 0x1c, 0xa1, 0x0e, 0xc1,
+ 0x3d, 0x0e, 0x9c, 0x4c, 0x93, 0x29, 0xf0, 0x46, 0x26, 0x8b, 0x1d, 0xb4, 0x11, 0xbf, 0x78, 0x00,
+ 0x04, 0x3f, 0x24, 0xc2, 0xf2, 0x8f, 0xde, 0xfd, 0xfd, 0xe7, 0x83, 0x0b, 0x70, 0xbe, 0xbb, 0xee,
+ 0x0d, 0x53, 0x9b, 0xe9, 0x20, 0xe9, 0x59, 0xf0, 0x36, 0x9e, 0xc3, 0x77, 0x1c, 0x6b, 0x60, 0xc9,
+ 0x7a, 0x81, 0x0b, 0xbd, 0x7b, 0x98, 0x10, 0x52, 0xfc, 0x8d, 0xfe, 0x01, 0x18, 0xc3, 0xcb, 0x94,
+ 0xe1, 0x45, 0x38, 0xd7, 0x03, 0x43, 0x5f, 0x62, 0xc1, 0x17, 0x83, 0x60, 0x62, 0x1f, 0xdd, 0x44,
+ 0xe0, 0xad, 0x3e, 0x3d, 0x4b, 0x95, 0x68, 0xfc, 0xed, 0x43, 0x42, 0x63, 0xa4, 0x6f, 0x52, 0xd2,
+ 0x45, 0x78, 0xa3, 0x57, 0xd2, 0x9e, 0x52, 0x76, 0x5c, 0x25, 0x54, 0x3f, 0xf0, 0xbf, 0x1c, 0xf8,
+ 0x34, 0x5d, 0x86, 0x11, 0xb8, 0xd6, 0xb7, 0xd3, 0xed, 0x7a, 0x8f, 0xbf, 0x75, 0x38, 0x60, 0x2c,
+ 0x00, 0xab, 0x34, 0x00, 0x8b, 0x70, 0xa1, 0x8f, 0x00, 0x60, 0x3b, 0xc6, 0xff, 0x5f, 0xc1, 0x50,
+ 0x9f, 0x2a, 0x8f, 0xe0, 0x4a, 0x76, 0xaf, 0x3b, 0x09, 0x3d, 0x7e, 0xf5, 0xc0, 0x38, 0x8c, 0xf8,
+ 0x22, 0x25, 0x7e, 0x15, 0x5e, 0xce, 0xf0, 0x21, 0x2b, 0x00, 0x52, 0x12, 0x83, 0x4f, 0x0a, 0xe5,
+ 0xf8, 0x95, 0xdc, 0x17, 0xe5, 0x14, 0x01, 0xd8, 0x17, 0xe5, 0x34, 0xfd, 0xd6, 0x1f, 0xe5, 0xc4,
+ 0x7d, 0x09, 0xff, 0xc0, 0xb1, 0xb1, 0x2c, 0x21, 0xdd, 0xe0, 0xf5, 0xec, 0x2e, 0xa6, 0x29, 0x42,
+ 0x7e, 0xa1, 0xef, 0xf3, 0x8c, 0xda, 0x25, 0x4a, 0xad, 0x00, 0x67, 0xbb, 0x53, 0x73, 0x19, 0x80,
+ 0xff, 0xad, 0x0b, 0xfe, 0x72, 0x10, 0x7c, 0x9e, 0x41, 0x8b, 0xc1, 0xf5, 0xec, 0x2e, 0x66, 0xd2,
+ 0x80, 0x7c, 0xe5, 0xf0, 0x00, 0x59, 0x10, 0xd6, 0x68, 0x10, 0x96, 0xe1, 0x52, 0xf7, 0x20, 0x38,
+ 0x21, 0x62, 0x94, 0xd3, 0x0e, 0xc5, 0x54, 0x7c, 0x6d, 0x09, 0xff, 0xd9, 0xa6, 0x1d, 0x93, 0x92,
+ 0x88, 0xc0, 0x1e, 0x6e, 0xd5, 0x7d, 0x04, 0x2a, 0x5f, 0x3c, 0x08, 0x04, 0x63, 0x5d, 0xa4, 0xac,
+ 0xaf, 0xc1, 0x2b, 0xdd, 0x59, 0x07, 0xd2, 0x54, 0x69, 0xbd, 0xc0, 0x7e, 0x31, 0xc8, 0x3e, 0xfc,
+ 0x65, 0xd0, 0x82, 0x70, 0x23, 0xbb, 0xd3, 0xd9, 0x95, 0x2a, 0x7f, 0xff, 0x90, 0x51, 0x59, 0x74,
+ 0xae, 0xd2, 0xe8, 0x7c, 0x09, 0x2f, 0xf6, 0xdc, 0xdf, 0x0d, 0x1d, 0xfe, 0x86, 0x03, 0xe3, 0x31,
+ 0xb9, 0x05, 0xbf, 0xdd, 0xc3, 0xeb, 0x8a, 0xcb, 0x36, 0xfe, 0x52, 0xef, 0x07, 0x99, 0xff, 0xb3,
+ 0xd4, 0xff, 0xb3, 0x70, 0x26, 0xc3, 0xdb, 0xf5, 0x9d, 0xfc, 0x59, 0x50, 0xd0, 0x9d, 0x85, 0x57,
+ 0x2f, 0x05, 0x9d, 0x49, 0x0b, 0xf6, 0x52, 0xd0, 0xd9, 0x34, 0x61, 0x2f, 0xd3, 0x09, 0xf6, 0x40,
+ 0x14, 0xc3, 0x52, 0x22, 0x7d, 0x18, 0x9f, 0x3b, 0x7f, 0x37, 0x08, 0xce, 0x64, 0xd6, 0x69, 0xf0,
+ 0x7e, 0xbf, 0xc3, 0x64, 0x47, 0xa9, 0xc9, 0x6f, 0x1e, 0x36, 0x2c, 0x0b, 0xd3, 0x03, 0x1a, 0xa6,
+ 0x0d, 0x28, 0xf7, 0x3c, 0xb9, 0x2a, 0x36, 0x72, 0xa2, 0x88, 0x49, 0xcf, 0x5a, 0xc5, 0xe1, 0x73,
+ 0xf8, 0xeb, 0x41, 0xf0, 0xf5, 0x2c, 0x92, 0x0f, 0x56, 0x0e, 0x30, 0x98, 0xa4, 0xea, 0x58, 0xfe,
+ 0xee, 0x21, 0x22, 0xb2, 0x48, 0x3d, 0xa4, 0x91, 0x7a, 0x00, 0xbf, 0xdb, 0x4b, 0xa4, 0x42, 0x28,
+ 0xc5, 0x53, 0xa0, 0xb1, 0xac, 0x4a, 0x8b, 0xd7, 0x7f, 0x38, 0xf6, 0xe5, 0x37, 0x4d, 0x60, 0xc2,
+ 0xe5, 0xec, 0x94, 0x3a, 0x08, 0x5c, 0x7e, 0xe5, 0xa0, 0x30, 0xbd, 0x5f, 0x98, 0x98, 0xe2, 0x28,
+ 0xf5, 0x08, 0x48, 0x69, 0x10, 0x2d, 0x16, 0x8c, 0xe2, 0x77, 0xde, 0xec, 0xe5, 0xb8, 0xb7, 0x7b,
+ 0x39, 0xee, 0x6f, 0x7b, 0x39, 0xee, 0xd5, 0xfb, 0xdc, 0xc0, 0xdb, 0xf7, 0xb9, 0x81, 0x3f, 0xbf,
+ 0xcf, 0x0d, 0x3c, 0x98, 0x6f, 0xd7, 0xfb, 0x91, 0xbd, 0x0b, 0xa1, 0xbd, 0xc6, 0xb7, 0xa4, 0xa7,
+ 0x2d, 0xa3, 0x4a, 0xd3, 0x46, 0x64, 0x6b, 0x84, 0x7e, 0x90, 0xbe, 0xf8, 0xbf, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0x21, 0x1e, 0x15, 0x5a, 0x72, 0x1d, 0x00, 0x00,
}
// Reference imports to suppress errors if they are not otherwise used.
@@ -1415,6 +1746,15 @@ type QueryClient interface {
QueryAllPairsValConAddrByConsumerChainID(ctx context.Context, in *QueryAllPairsValConAddrByConsumerChainIDRequest, opts ...grpc.CallOption) (*QueryAllPairsValConAddrByConsumerChainIDResponse, error)
// QueryParams returns all current values of provider parameters
QueryParams(ctx context.Context, in *QueryParamsRequest, opts ...grpc.CallOption) (*QueryParamsResponse, error)
+ // QueryConsumerChainOptedInValidators returns a list of validators consensus addresses
+ // that opted-in to the given consumer chain
+ QueryConsumerChainOptedInValidators(ctx context.Context, in *QueryConsumerChainOptedInValidatorsRequest, opts ...grpc.CallOption) (*QueryConsumerChainOptedInValidatorsResponse, error)
+ // QueryConsumerChainsValidatorHasToValidate returns a list of consumer chains
+ // that a given validator must validate
+ QueryConsumerChainsValidatorHasToValidate(ctx context.Context, in *QueryConsumerChainsValidatorHasToValidateRequest, opts ...grpc.CallOption) (*QueryConsumerChainsValidatorHasToValidateResponse, error)
+ // QueryValidatorConsumerCommissionRate returns the commission rate a given
+ // validator charges on a given consumer chain
+ QueryValidatorConsumerCommissionRate(ctx context.Context, in *QueryValidatorConsumerCommissionRateRequest, opts ...grpc.CallOption) (*QueryValidatorConsumerCommissionRateResponse, error)
// QueryOldestUnconfirmedVsc returns the send timestamp of the oldest unconfirmed VSCPacket for a given chainID
QueryOldestUnconfirmedVsc(ctx context.Context, in *QueryOldestUnconfirmedVscRequest, opts ...grpc.CallOption) (*QueryOldestUnconfirmedVscResponse, error)
}
@@ -1526,6 +1866,33 @@ func (c *queryClient) QueryParams(ctx context.Context, in *QueryParamsRequest, o
return out, nil
}
+func (c *queryClient) QueryConsumerChainOptedInValidators(ctx context.Context, in *QueryConsumerChainOptedInValidatorsRequest, opts ...grpc.CallOption) (*QueryConsumerChainOptedInValidatorsResponse, error) {
+ out := new(QueryConsumerChainOptedInValidatorsResponse)
+ err := c.cc.Invoke(ctx, "/interchain_security.ccv.provider.v1.Query/QueryConsumerChainOptedInValidators", in, out, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *queryClient) QueryConsumerChainsValidatorHasToValidate(ctx context.Context, in *QueryConsumerChainsValidatorHasToValidateRequest, opts ...grpc.CallOption) (*QueryConsumerChainsValidatorHasToValidateResponse, error) {
+ out := new(QueryConsumerChainsValidatorHasToValidateResponse)
+ err := c.cc.Invoke(ctx, "/interchain_security.ccv.provider.v1.Query/QueryConsumerChainsValidatorHasToValidate", in, out, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *queryClient) QueryValidatorConsumerCommissionRate(ctx context.Context, in *QueryValidatorConsumerCommissionRateRequest, opts ...grpc.CallOption) (*QueryValidatorConsumerCommissionRateResponse, error) {
+ out := new(QueryValidatorConsumerCommissionRateResponse)
+ err := c.cc.Invoke(ctx, "/interchain_security.ccv.provider.v1.Query/QueryValidatorConsumerCommissionRate", in, out, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
func (c *queryClient) QueryOldestUnconfirmedVsc(ctx context.Context, in *QueryOldestUnconfirmedVscRequest, opts ...grpc.CallOption) (*QueryOldestUnconfirmedVscResponse, error) {
out := new(QueryOldestUnconfirmedVscResponse)
err := c.cc.Invoke(ctx, "/interchain_security.ccv.provider.v1.Query/QueryOldestUnconfirmedVsc", in, out, opts...)
@@ -1567,6 +1934,15 @@ type QueryServer interface {
QueryAllPairsValConAddrByConsumerChainID(context.Context, *QueryAllPairsValConAddrByConsumerChainIDRequest) (*QueryAllPairsValConAddrByConsumerChainIDResponse, error)
// QueryParams returns all current values of provider parameters
QueryParams(context.Context, *QueryParamsRequest) (*QueryParamsResponse, error)
+ // QueryConsumerChainOptedInValidators returns a list of validators consensus addresses
+ // that opted-in to the given consumer chain
+ QueryConsumerChainOptedInValidators(context.Context, *QueryConsumerChainOptedInValidatorsRequest) (*QueryConsumerChainOptedInValidatorsResponse, error)
+ // QueryConsumerChainsValidatorHasToValidate returns a list of consumer chains
+ // that a given validator must validate
+ QueryConsumerChainsValidatorHasToValidate(context.Context, *QueryConsumerChainsValidatorHasToValidateRequest) (*QueryConsumerChainsValidatorHasToValidateResponse, error)
+ // QueryValidatorConsumerCommissionRate returns the commission rate a given
+ // validator charges on a given consumer chain
+ QueryValidatorConsumerCommissionRate(context.Context, *QueryValidatorConsumerCommissionRateRequest) (*QueryValidatorConsumerCommissionRateResponse, error)
// QueryOldestUnconfirmedVsc returns the send timestamp of the oldest unconfirmed VSCPacket for a given chainID
QueryOldestUnconfirmedVsc(context.Context, *QueryOldestUnconfirmedVscRequest) (*QueryOldestUnconfirmedVscResponse, error)
}
@@ -1608,6 +1984,15 @@ func (*UnimplementedQueryServer) QueryAllPairsValConAddrByConsumerChainID(ctx co
func (*UnimplementedQueryServer) QueryParams(ctx context.Context, req *QueryParamsRequest) (*QueryParamsResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method QueryParams not implemented")
}
+func (*UnimplementedQueryServer) QueryConsumerChainOptedInValidators(ctx context.Context, req *QueryConsumerChainOptedInValidatorsRequest) (*QueryConsumerChainOptedInValidatorsResponse, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method QueryConsumerChainOptedInValidators not implemented")
+}
+func (*UnimplementedQueryServer) QueryConsumerChainsValidatorHasToValidate(ctx context.Context, req *QueryConsumerChainsValidatorHasToValidateRequest) (*QueryConsumerChainsValidatorHasToValidateResponse, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method QueryConsumerChainsValidatorHasToValidate not implemented")
+}
+func (*UnimplementedQueryServer) QueryValidatorConsumerCommissionRate(ctx context.Context, req *QueryValidatorConsumerCommissionRateRequest) (*QueryValidatorConsumerCommissionRateResponse, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method QueryValidatorConsumerCommissionRate not implemented")
+}
func (*UnimplementedQueryServer) QueryOldestUnconfirmedVsc(ctx context.Context, req *QueryOldestUnconfirmedVscRequest) (*QueryOldestUnconfirmedVscResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method QueryOldestUnconfirmedVsc not implemented")
}
@@ -1814,6 +2199,60 @@ func _Query_QueryParams_Handler(srv interface{}, ctx context.Context, dec func(i
return interceptor(ctx, in, info, handler)
}
+func _Query_QueryConsumerChainOptedInValidators_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(QueryConsumerChainOptedInValidatorsRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(QueryServer).QueryConsumerChainOptedInValidators(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/interchain_security.ccv.provider.v1.Query/QueryConsumerChainOptedInValidators",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(QueryServer).QueryConsumerChainOptedInValidators(ctx, req.(*QueryConsumerChainOptedInValidatorsRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _Query_QueryConsumerChainsValidatorHasToValidate_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(QueryConsumerChainsValidatorHasToValidateRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(QueryServer).QueryConsumerChainsValidatorHasToValidate(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/interchain_security.ccv.provider.v1.Query/QueryConsumerChainsValidatorHasToValidate",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(QueryServer).QueryConsumerChainsValidatorHasToValidate(ctx, req.(*QueryConsumerChainsValidatorHasToValidateRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _Query_QueryValidatorConsumerCommissionRate_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(QueryValidatorConsumerCommissionRateRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(QueryServer).QueryValidatorConsumerCommissionRate(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/interchain_security.ccv.provider.v1.Query/QueryValidatorConsumerCommissionRate",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(QueryServer).QueryValidatorConsumerCommissionRate(ctx, req.(*QueryValidatorConsumerCommissionRateRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
func _Query_QueryOldestUnconfirmedVsc_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(QueryOldestUnconfirmedVscRequest)
if err := dec(in); err != nil {
@@ -1881,8 +2320,20 @@ var _Query_serviceDesc = grpc.ServiceDesc{
Handler: _Query_QueryParams_Handler,
},
{
- MethodName: "QueryOldestUnconfirmedVsc",
- Handler: _Query_QueryOldestUnconfirmedVsc_Handler,
+ MethodName: "QueryConsumerChainOptedInValidators",
+ Handler: _Query_QueryConsumerChainOptedInValidators_Handler,
+ },
+ {
+ MethodName: "QueryConsumerChainsValidatorHasToValidate",
+ Handler: _Query_QueryConsumerChainsValidatorHasToValidate_Handler,
+ },
+ {
+ MethodName: "QueryValidatorConsumerCommissionRate",
+ Handler: _Query_QueryValidatorConsumerCommissionRate_Handler,
+ },
+ {
+ MethodName: "QueryOldestUnconfirmedVsc",
+ Handler: _Query_QueryOldestUnconfirmedVsc_Handler,
},
},
Streams: []grpc.StreamDesc{},
@@ -2148,6 +2599,11 @@ func (m *Chain) MarshalToSizedBuffer(dAtA []byte) (int, error) {
_ = i
var l int
_ = l
+ if m.Top_N != 0 {
+ i = encodeVarintQuery(dAtA, i, uint64(m.Top_N))
+ i--
+ dAtA[i] = 0x18
+ }
if len(m.ClientId) > 0 {
i -= len(m.ClientId)
copy(dAtA[i:], m.ClientId)
@@ -2685,6 +3141,200 @@ func (m *QueryParamsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
return len(dAtA) - i, nil
}
+func (m *QueryConsumerChainOptedInValidatorsRequest) 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 *QueryConsumerChainOptedInValidatorsRequest) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *QueryConsumerChainOptedInValidatorsRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if len(m.ChainId) > 0 {
+ i -= len(m.ChainId)
+ copy(dAtA[i:], m.ChainId)
+ i = encodeVarintQuery(dAtA, i, uint64(len(m.ChainId)))
+ i--
+ dAtA[i] = 0xa
+ }
+ return len(dAtA) - i, nil
+}
+
+func (m *QueryConsumerChainOptedInValidatorsResponse) 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 *QueryConsumerChainOptedInValidatorsResponse) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *QueryConsumerChainOptedInValidatorsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if len(m.ValidatorsProviderAddresses) > 0 {
+ for iNdEx := len(m.ValidatorsProviderAddresses) - 1; iNdEx >= 0; iNdEx-- {
+ i -= len(m.ValidatorsProviderAddresses[iNdEx])
+ copy(dAtA[i:], m.ValidatorsProviderAddresses[iNdEx])
+ i = encodeVarintQuery(dAtA, i, uint64(len(m.ValidatorsProviderAddresses[iNdEx])))
+ i--
+ dAtA[i] = 0xa
+ }
+ }
+ return len(dAtA) - i, nil
+}
+
+func (m *QueryConsumerChainsValidatorHasToValidateRequest) 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 *QueryConsumerChainsValidatorHasToValidateRequest) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *QueryConsumerChainsValidatorHasToValidateRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if len(m.ProviderAddress) > 0 {
+ i -= len(m.ProviderAddress)
+ copy(dAtA[i:], m.ProviderAddress)
+ i = encodeVarintQuery(dAtA, i, uint64(len(m.ProviderAddress)))
+ i--
+ dAtA[i] = 0xa
+ }
+ return len(dAtA) - i, nil
+}
+
+func (m *QueryConsumerChainsValidatorHasToValidateResponse) 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 *QueryConsumerChainsValidatorHasToValidateResponse) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *QueryConsumerChainsValidatorHasToValidateResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if len(m.ConsumerChainIds) > 0 {
+ for iNdEx := len(m.ConsumerChainIds) - 1; iNdEx >= 0; iNdEx-- {
+ i -= len(m.ConsumerChainIds[iNdEx])
+ copy(dAtA[i:], m.ConsumerChainIds[iNdEx])
+ i = encodeVarintQuery(dAtA, i, uint64(len(m.ConsumerChainIds[iNdEx])))
+ i--
+ dAtA[i] = 0xa
+ }
+ }
+ return len(dAtA) - i, nil
+}
+
+func (m *QueryValidatorConsumerCommissionRateRequest) 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 *QueryValidatorConsumerCommissionRateRequest) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *QueryValidatorConsumerCommissionRateRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if len(m.ProviderAddress) > 0 {
+ i -= len(m.ProviderAddress)
+ copy(dAtA[i:], m.ProviderAddress)
+ i = encodeVarintQuery(dAtA, i, uint64(len(m.ProviderAddress)))
+ i--
+ dAtA[i] = 0x12
+ }
+ if len(m.ChainId) > 0 {
+ i -= len(m.ChainId)
+ copy(dAtA[i:], m.ChainId)
+ i = encodeVarintQuery(dAtA, i, uint64(len(m.ChainId)))
+ i--
+ dAtA[i] = 0xa
+ }
+ return len(dAtA) - i, nil
+}
+
+func (m *QueryValidatorConsumerCommissionRateResponse) 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 *QueryValidatorConsumerCommissionRateResponse) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *QueryValidatorConsumerCommissionRateResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ {
+ size := m.Rate.Size()
+ i -= size
+ if _, err := m.Rate.MarshalTo(dAtA[i:]); err != nil {
+ return 0, err
+ }
+ i = encodeVarintQuery(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0xa
+ return len(dAtA) - i, nil
+}
+
func (m *QueryOldestUnconfirmedVscRequest) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
@@ -2865,6 +3515,9 @@ func (m *Chain) Size() (n int) {
if l > 0 {
n += 1 + l + sovQuery(uint64(l))
}
+ if m.Top_N != 0 {
+ n += 1 + sovQuery(uint64(m.Top_N))
+ }
return n
}
@@ -3087,6 +3740,90 @@ func (m *QueryParamsResponse) Size() (n int) {
return n
}
+func (m *QueryConsumerChainOptedInValidatorsRequest) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ l = len(m.ChainId)
+ if l > 0 {
+ n += 1 + l + sovQuery(uint64(l))
+ }
+ return n
+}
+
+func (m *QueryConsumerChainOptedInValidatorsResponse) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ if len(m.ValidatorsProviderAddresses) > 0 {
+ for _, s := range m.ValidatorsProviderAddresses {
+ l = len(s)
+ n += 1 + l + sovQuery(uint64(l))
+ }
+ }
+ return n
+}
+
+func (m *QueryConsumerChainsValidatorHasToValidateRequest) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ l = len(m.ProviderAddress)
+ if l > 0 {
+ n += 1 + l + sovQuery(uint64(l))
+ }
+ return n
+}
+
+func (m *QueryConsumerChainsValidatorHasToValidateResponse) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ if len(m.ConsumerChainIds) > 0 {
+ for _, s := range m.ConsumerChainIds {
+ l = len(s)
+ n += 1 + l + sovQuery(uint64(l))
+ }
+ }
+ return n
+}
+
+func (m *QueryValidatorConsumerCommissionRateRequest) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ l = len(m.ChainId)
+ if l > 0 {
+ n += 1 + l + sovQuery(uint64(l))
+ }
+ l = len(m.ProviderAddress)
+ if l > 0 {
+ n += 1 + l + sovQuery(uint64(l))
+ }
+ return n
+}
+
+func (m *QueryValidatorConsumerCommissionRateResponse) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ l = m.Rate.Size()
+ n += 1 + l + sovQuery(uint64(l))
+ return n
+}
+
func (m *QueryOldestUnconfirmedVscRequest) Size() (n int) {
if m == nil {
return 0
@@ -3781,13 +4518,32 @@ func (m *Chain) Unmarshal(dAtA []byte) error {
}
m.ClientId = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
- default:
- iNdEx = preIndex
- skippy, err := skipQuery(dAtA[iNdEx:])
- if err != nil {
- return err
+ case 3:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Top_N", wireType)
}
- if (skippy < 0) || (iNdEx+skippy) < 0 {
+ m.Top_N = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.Top_N |= uint32(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ default:
+ iNdEx = preIndex
+ skippy, err := skipQuery(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthQuery
}
if (iNdEx + skippy) > l {
@@ -5181,6 +5937,532 @@ func (m *QueryParamsResponse) Unmarshal(dAtA []byte) error {
}
return nil
}
+func (m *QueryConsumerChainOptedInValidatorsRequest) 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 ErrIntOverflowQuery
+ }
+ 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: QueryConsumerChainOptedInValidatorsRequest: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: QueryConsumerChainOptedInValidatorsRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field ChainId", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ 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 ErrInvalidLengthQuery
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthQuery
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.ChainId = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipQuery(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthQuery
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *QueryConsumerChainOptedInValidatorsResponse) 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 ErrIntOverflowQuery
+ }
+ 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: QueryConsumerChainOptedInValidatorsResponse: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: QueryConsumerChainOptedInValidatorsResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field ValidatorsProviderAddresses", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ 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 ErrInvalidLengthQuery
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthQuery
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.ValidatorsProviderAddresses = append(m.ValidatorsProviderAddresses, string(dAtA[iNdEx:postIndex]))
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipQuery(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthQuery
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *QueryConsumerChainsValidatorHasToValidateRequest) 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 ErrIntOverflowQuery
+ }
+ 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: QueryConsumerChainsValidatorHasToValidateRequest: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: QueryConsumerChainsValidatorHasToValidateRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field ProviderAddress", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ 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 ErrInvalidLengthQuery
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthQuery
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.ProviderAddress = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipQuery(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthQuery
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *QueryConsumerChainsValidatorHasToValidateResponse) 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 ErrIntOverflowQuery
+ }
+ 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: QueryConsumerChainsValidatorHasToValidateResponse: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: QueryConsumerChainsValidatorHasToValidateResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field ConsumerChainIds", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ 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 ErrInvalidLengthQuery
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthQuery
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.ConsumerChainIds = append(m.ConsumerChainIds, string(dAtA[iNdEx:postIndex]))
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipQuery(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthQuery
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *QueryValidatorConsumerCommissionRateRequest) 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 ErrIntOverflowQuery
+ }
+ 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: QueryValidatorConsumerCommissionRateRequest: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: QueryValidatorConsumerCommissionRateRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field ChainId", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ 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 ErrInvalidLengthQuery
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthQuery
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.ChainId = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field ProviderAddress", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ 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 ErrInvalidLengthQuery
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthQuery
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.ProviderAddress = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipQuery(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthQuery
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *QueryValidatorConsumerCommissionRateResponse) 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 ErrIntOverflowQuery
+ }
+ 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: QueryValidatorConsumerCommissionRateResponse: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: QueryValidatorConsumerCommissionRateResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Rate", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowQuery
+ }
+ 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 ErrInvalidLengthQuery
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthQuery
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if err := m.Rate.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipQuery(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthQuery
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
func (m *QueryOldestUnconfirmedVscRequest) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
diff --git a/x/ccv/provider/types/query.pb.gw.go b/x/ccv/provider/types/query.pb.gw.go
index 0ebfbfa6fd..2be0974fbf 100644
--- a/x/ccv/provider/types/query.pb.gw.go
+++ b/x/ccv/provider/types/query.pb.gw.go
@@ -321,6 +321,190 @@ func local_request_Query_QueryParams_0(ctx context.Context, marshaler runtime.Ma
}
+func request_Query_QueryConsumerChainOptedInValidators_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq QueryConsumerChainOptedInValidatorsRequest
+ var metadata runtime.ServerMetadata
+
+ var (
+ val string
+ ok bool
+ err error
+ _ = err
+ )
+
+ val, ok = pathParams["chain_id"]
+ if !ok {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "chain_id")
+ }
+
+ protoReq.ChainId, err = runtime.String(val)
+
+ if err != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "chain_id", err)
+ }
+
+ msg, err := client.QueryConsumerChainOptedInValidators(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+ return msg, metadata, err
+
+}
+
+func local_request_Query_QueryConsumerChainOptedInValidators_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq QueryConsumerChainOptedInValidatorsRequest
+ var metadata runtime.ServerMetadata
+
+ var (
+ val string
+ ok bool
+ err error
+ _ = err
+ )
+
+ val, ok = pathParams["chain_id"]
+ if !ok {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "chain_id")
+ }
+
+ protoReq.ChainId, err = runtime.String(val)
+
+ if err != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "chain_id", err)
+ }
+
+ msg, err := server.QueryConsumerChainOptedInValidators(ctx, &protoReq)
+ return msg, metadata, err
+
+}
+
+func request_Query_QueryConsumerChainsValidatorHasToValidate_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq QueryConsumerChainsValidatorHasToValidateRequest
+ var metadata runtime.ServerMetadata
+
+ var (
+ val string
+ ok bool
+ err error
+ _ = err
+ )
+
+ val, ok = pathParams["provider_address"]
+ if !ok {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "provider_address")
+ }
+
+ protoReq.ProviderAddress, err = runtime.String(val)
+
+ if err != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "provider_address", err)
+ }
+
+ msg, err := client.QueryConsumerChainsValidatorHasToValidate(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+ return msg, metadata, err
+
+}
+
+func local_request_Query_QueryConsumerChainsValidatorHasToValidate_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq QueryConsumerChainsValidatorHasToValidateRequest
+ var metadata runtime.ServerMetadata
+
+ var (
+ val string
+ ok bool
+ err error
+ _ = err
+ )
+
+ val, ok = pathParams["provider_address"]
+ if !ok {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "provider_address")
+ }
+
+ protoReq.ProviderAddress, err = runtime.String(val)
+
+ if err != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "provider_address", err)
+ }
+
+ msg, err := server.QueryConsumerChainsValidatorHasToValidate(ctx, &protoReq)
+ return msg, metadata, err
+
+}
+
+func request_Query_QueryValidatorConsumerCommissionRate_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq QueryValidatorConsumerCommissionRateRequest
+ var metadata runtime.ServerMetadata
+
+ var (
+ val string
+ ok bool
+ err error
+ _ = err
+ )
+
+ val, ok = pathParams["chain_id"]
+ if !ok {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "chain_id")
+ }
+
+ protoReq.ChainId, err = runtime.String(val)
+
+ if err != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "chain_id", err)
+ }
+
+ val, ok = pathParams["provider_address"]
+ if !ok {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "provider_address")
+ }
+
+ protoReq.ProviderAddress, err = runtime.String(val)
+
+ if err != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "provider_address", err)
+ }
+
+ msg, err := client.QueryValidatorConsumerCommissionRate(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+ return msg, metadata, err
+
+}
+
+func local_request_Query_QueryValidatorConsumerCommissionRate_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq QueryValidatorConsumerCommissionRateRequest
+ var metadata runtime.ServerMetadata
+
+ var (
+ val string
+ ok bool
+ err error
+ _ = err
+ )
+
+ val, ok = pathParams["chain_id"]
+ if !ok {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "chain_id")
+ }
+
+ protoReq.ChainId, err = runtime.String(val)
+
+ if err != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "chain_id", err)
+ }
+
+ val, ok = pathParams["provider_address"]
+ if !ok {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "provider_address")
+ }
+
+ protoReq.ProviderAddress, err = runtime.String(val)
+
+ if err != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "provider_address", err)
+ }
+
+ msg, err := server.QueryValidatorConsumerCommissionRate(ctx, &protoReq)
+ return msg, metadata, err
+
+}
+
func request_Query_QueryOldestUnconfirmedVsc_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq QueryOldestUnconfirmedVscRequest
var metadata runtime.ServerMetadata
@@ -634,6 +818,75 @@ func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv
})
+ mux.Handle("GET", pattern_Query_QueryConsumerChainOptedInValidators_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ var stream runtime.ServerTransportStream
+ ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := local_request_Query_QueryConsumerChainOptedInValidators_0(rctx, inboundMarshaler, server, req, pathParams)
+ md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Query_QueryConsumerChainOptedInValidators_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("GET", pattern_Query_QueryConsumerChainsValidatorHasToValidate_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ var stream runtime.ServerTransportStream
+ ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := local_request_Query_QueryConsumerChainsValidatorHasToValidate_0(rctx, inboundMarshaler, server, req, pathParams)
+ md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Query_QueryConsumerChainsValidatorHasToValidate_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("GET", pattern_Query_QueryValidatorConsumerCommissionRate_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ var stream runtime.ServerTransportStream
+ ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := local_request_Query_QueryValidatorConsumerCommissionRate_0(rctx, inboundMarshaler, server, req, pathParams)
+ md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Query_QueryValidatorConsumerCommissionRate_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
mux.Handle("GET", pattern_Query_QueryOldestUnconfirmedVsc_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
@@ -918,6 +1171,66 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie
})
+ mux.Handle("GET", pattern_Query_QueryConsumerChainOptedInValidators_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := request_Query_QueryConsumerChainOptedInValidators_0(rctx, inboundMarshaler, client, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Query_QueryConsumerChainOptedInValidators_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("GET", pattern_Query_QueryConsumerChainsValidatorHasToValidate_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := request_Query_QueryConsumerChainsValidatorHasToValidate_0(rctx, inboundMarshaler, client, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Query_QueryConsumerChainsValidatorHasToValidate_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("GET", pattern_Query_QueryValidatorConsumerCommissionRate_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := request_Query_QueryValidatorConsumerCommissionRate_0(rctx, inboundMarshaler, client, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Query_QueryValidatorConsumerCommissionRate_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
mux.Handle("GET", pattern_Query_QueryOldestUnconfirmedVsc_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
@@ -964,6 +1277,12 @@ var (
pattern_Query_QueryParams_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"interchain_security", "ccv", "provider", "params"}, "", runtime.AssumeColonVerbOpt(false)))
+ pattern_Query_QueryConsumerChainOptedInValidators_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"interchain_security", "ccv", "provider", "opted_in_validators", "chain_id"}, "", runtime.AssumeColonVerbOpt(false)))
+
+ pattern_Query_QueryConsumerChainsValidatorHasToValidate_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"interchain_security", "ccv", "provider", "consumer_chains_per_validator", "provider_address"}, "", runtime.AssumeColonVerbOpt(false)))
+
+ pattern_Query_QueryValidatorConsumerCommissionRate_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4, 1, 0, 4, 1, 5, 5}, []string{"interchain_security", "ccv", "provider", "consumer_commission_rate", "chain_id", "provider_address"}, "", runtime.AssumeColonVerbOpt(false)))
+
pattern_Query_QueryOldestUnconfirmedVsc_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"interchain_security", "ccv", "provider", "oldest_unconfirmed_vsc", "chain_id"}, "", runtime.AssumeColonVerbOpt(false)))
)
@@ -990,5 +1309,11 @@ var (
forward_Query_QueryParams_0 = runtime.ForwardResponseMessage
+ forward_Query_QueryConsumerChainOptedInValidators_0 = runtime.ForwardResponseMessage
+
+ forward_Query_QueryConsumerChainsValidatorHasToValidate_0 = runtime.ForwardResponseMessage
+
+ forward_Query_QueryValidatorConsumerCommissionRate_0 = runtime.ForwardResponseMessage
+
forward_Query_QueryOldestUnconfirmedVsc_0 = runtime.ForwardResponseMessage
)
diff --git a/x/ccv/provider/types/tx.pb.go b/x/ccv/provider/types/tx.pb.go
index f72e95acb2..1fd4869548 100644
--- a/x/ccv/provider/types/tx.pb.go
+++ b/x/ccv/provider/types/tx.pb.go
@@ -9,6 +9,7 @@ import (
types "github.com/cometbft/cometbft/proto/tendermint/types"
_ "github.com/cosmos/cosmos-proto"
_ "github.com/cosmos/cosmos-sdk/codec/types"
+ github_com_cosmos_cosmos_sdk_types "github.com/cosmos/cosmos-sdk/types"
_ "github.com/cosmos/gogoproto/gogoproto"
grpc1 "github.com/cosmos/gogoproto/grpc"
proto "github.com/cosmos/gogoproto/proto"
@@ -270,6 +271,243 @@ func (m *MsgSubmitConsumerDoubleVotingResponse) XXX_DiscardUnknown() {
var xxx_messageInfo_MsgSubmitConsumerDoubleVotingResponse proto.InternalMessageInfo
+type MsgOptIn struct {
+ // the chain id of the consumer chain to opt in to
+ ChainId string `protobuf:"bytes,1,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"`
+ // the validator address on the provider
+ ProviderAddr string `protobuf:"bytes,2,opt,name=provider_addr,json=providerAddr,proto3" json:"provider_addr,omitempty" yaml:"address"`
+ // (optional) The consensus public key to use on the consumer in json string format corresponding to proto-any,
+ // for example `{"@type":"/cosmos.crypto.ed25519.PubKey","key":"Ui5Gf1+mtWUdH8u3xlmzdKID+F3PK0sfXZ73GZ6q6is="}`.
+ // This field is optional and can remain empty (i.e., `consumer_key = ""`). A validator can always change the
+ // consumer public key at a later stage by issuing a `MsgAssignConsumerKey` message.
+ ConsumerKey string `protobuf:"bytes,3,opt,name=consumer_key,json=consumerKey,proto3" json:"consumer_key,omitempty"`
+}
+
+func (m *MsgOptIn) Reset() { *m = MsgOptIn{} }
+func (m *MsgOptIn) String() string { return proto.CompactTextString(m) }
+func (*MsgOptIn) ProtoMessage() {}
+func (*MsgOptIn) Descriptor() ([]byte, []int) {
+ return fileDescriptor_43221a4391e9fbf4, []int{6}
+}
+func (m *MsgOptIn) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *MsgOptIn) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_MsgOptIn.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 *MsgOptIn) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_MsgOptIn.Merge(m, src)
+}
+func (m *MsgOptIn) XXX_Size() int {
+ return m.Size()
+}
+func (m *MsgOptIn) XXX_DiscardUnknown() {
+ xxx_messageInfo_MsgOptIn.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_MsgOptIn proto.InternalMessageInfo
+
+type MsgOptInResponse struct {
+}
+
+func (m *MsgOptInResponse) Reset() { *m = MsgOptInResponse{} }
+func (m *MsgOptInResponse) String() string { return proto.CompactTextString(m) }
+func (*MsgOptInResponse) ProtoMessage() {}
+func (*MsgOptInResponse) Descriptor() ([]byte, []int) {
+ return fileDescriptor_43221a4391e9fbf4, []int{7}
+}
+func (m *MsgOptInResponse) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *MsgOptInResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_MsgOptInResponse.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 *MsgOptInResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_MsgOptInResponse.Merge(m, src)
+}
+func (m *MsgOptInResponse) XXX_Size() int {
+ return m.Size()
+}
+func (m *MsgOptInResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_MsgOptInResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_MsgOptInResponse proto.InternalMessageInfo
+
+type MsgOptOut struct {
+ // the chain id of the consumer chain to opt out from
+ ChainId string `protobuf:"bytes,1,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"`
+ // the validator address on the provider
+ ProviderAddr string `protobuf:"bytes,2,opt,name=provider_addr,json=providerAddr,proto3" json:"provider_addr,omitempty" yaml:"address"`
+}
+
+func (m *MsgOptOut) Reset() { *m = MsgOptOut{} }
+func (m *MsgOptOut) String() string { return proto.CompactTextString(m) }
+func (*MsgOptOut) ProtoMessage() {}
+func (*MsgOptOut) Descriptor() ([]byte, []int) {
+ return fileDescriptor_43221a4391e9fbf4, []int{8}
+}
+func (m *MsgOptOut) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *MsgOptOut) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_MsgOptOut.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 *MsgOptOut) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_MsgOptOut.Merge(m, src)
+}
+func (m *MsgOptOut) XXX_Size() int {
+ return m.Size()
+}
+func (m *MsgOptOut) XXX_DiscardUnknown() {
+ xxx_messageInfo_MsgOptOut.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_MsgOptOut proto.InternalMessageInfo
+
+type MsgOptOutResponse struct {
+}
+
+func (m *MsgOptOutResponse) Reset() { *m = MsgOptOutResponse{} }
+func (m *MsgOptOutResponse) String() string { return proto.CompactTextString(m) }
+func (*MsgOptOutResponse) ProtoMessage() {}
+func (*MsgOptOutResponse) Descriptor() ([]byte, []int) {
+ return fileDescriptor_43221a4391e9fbf4, []int{9}
+}
+func (m *MsgOptOutResponse) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *MsgOptOutResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_MsgOptOutResponse.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 *MsgOptOutResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_MsgOptOutResponse.Merge(m, src)
+}
+func (m *MsgOptOutResponse) XXX_Size() int {
+ return m.Size()
+}
+func (m *MsgOptOutResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_MsgOptOutResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_MsgOptOutResponse proto.InternalMessageInfo
+
+// MsgSetConsumerCommissionRate allows validators to set
+// a per-consumer chain commission rate
+type MsgSetConsumerCommissionRate struct {
+ // The validator address on the provider
+ ProviderAddr string `protobuf:"bytes,1,opt,name=provider_addr,json=providerAddr,proto3" json:"provider_addr,omitempty" yaml:"address"`
+ // The chain id of the consumer chain to set a commission rate
+ ChainId string `protobuf:"bytes,2,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"`
+ // The rate to charge delegators on the consumer chain, as a fraction
+ Rate github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,3,opt,name=rate,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"rate"`
+}
+
+func (m *MsgSetConsumerCommissionRate) Reset() { *m = MsgSetConsumerCommissionRate{} }
+func (m *MsgSetConsumerCommissionRate) String() string { return proto.CompactTextString(m) }
+func (*MsgSetConsumerCommissionRate) ProtoMessage() {}
+func (*MsgSetConsumerCommissionRate) Descriptor() ([]byte, []int) {
+ return fileDescriptor_43221a4391e9fbf4, []int{10}
+}
+func (m *MsgSetConsumerCommissionRate) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *MsgSetConsumerCommissionRate) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_MsgSetConsumerCommissionRate.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 *MsgSetConsumerCommissionRate) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_MsgSetConsumerCommissionRate.Merge(m, src)
+}
+func (m *MsgSetConsumerCommissionRate) XXX_Size() int {
+ return m.Size()
+}
+func (m *MsgSetConsumerCommissionRate) XXX_DiscardUnknown() {
+ xxx_messageInfo_MsgSetConsumerCommissionRate.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_MsgSetConsumerCommissionRate proto.InternalMessageInfo
+
+type MsgSetConsumerCommissionRateResponse struct {
+}
+
+func (m *MsgSetConsumerCommissionRateResponse) Reset() { *m = MsgSetConsumerCommissionRateResponse{} }
+func (m *MsgSetConsumerCommissionRateResponse) String() string { return proto.CompactTextString(m) }
+func (*MsgSetConsumerCommissionRateResponse) ProtoMessage() {}
+func (*MsgSetConsumerCommissionRateResponse) Descriptor() ([]byte, []int) {
+ return fileDescriptor_43221a4391e9fbf4, []int{11}
+}
+func (m *MsgSetConsumerCommissionRateResponse) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *MsgSetConsumerCommissionRateResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_MsgSetConsumerCommissionRateResponse.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 *MsgSetConsumerCommissionRateResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_MsgSetConsumerCommissionRateResponse.Merge(m, src)
+}
+func (m *MsgSetConsumerCommissionRateResponse) XXX_Size() int {
+ return m.Size()
+}
+func (m *MsgSetConsumerCommissionRateResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_MsgSetConsumerCommissionRateResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_MsgSetConsumerCommissionRateResponse proto.InternalMessageInfo
+
func init() {
proto.RegisterType((*MsgAssignConsumerKey)(nil), "interchain_security.ccv.provider.v1.MsgAssignConsumerKey")
proto.RegisterType((*MsgAssignConsumerKeyResponse)(nil), "interchain_security.ccv.provider.v1.MsgAssignConsumerKeyResponse")
@@ -277,6 +515,12 @@ func init() {
proto.RegisterType((*MsgSubmitConsumerMisbehaviourResponse)(nil), "interchain_security.ccv.provider.v1.MsgSubmitConsumerMisbehaviourResponse")
proto.RegisterType((*MsgSubmitConsumerDoubleVoting)(nil), "interchain_security.ccv.provider.v1.MsgSubmitConsumerDoubleVoting")
proto.RegisterType((*MsgSubmitConsumerDoubleVotingResponse)(nil), "interchain_security.ccv.provider.v1.MsgSubmitConsumerDoubleVotingResponse")
+ proto.RegisterType((*MsgOptIn)(nil), "interchain_security.ccv.provider.v1.MsgOptIn")
+ proto.RegisterType((*MsgOptInResponse)(nil), "interchain_security.ccv.provider.v1.MsgOptInResponse")
+ proto.RegisterType((*MsgOptOut)(nil), "interchain_security.ccv.provider.v1.MsgOptOut")
+ proto.RegisterType((*MsgOptOutResponse)(nil), "interchain_security.ccv.provider.v1.MsgOptOutResponse")
+ proto.RegisterType((*MsgSetConsumerCommissionRate)(nil), "interchain_security.ccv.provider.v1.MsgSetConsumerCommissionRate")
+ proto.RegisterType((*MsgSetConsumerCommissionRateResponse)(nil), "interchain_security.ccv.provider.v1.MsgSetConsumerCommissionRateResponse")
}
func init() {
@@ -284,46 +528,57 @@ func init() {
}
var fileDescriptor_43221a4391e9fbf4 = []byte{
- // 610 bytes of a gzipped FileDescriptorProto
- 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x54, 0xcf, 0x4f, 0xd4, 0x4e,
- 0x14, 0xdf, 0x42, 0xf2, 0xfd, 0xc2, 0x80, 0x26, 0x36, 0x10, 0x60, 0x83, 0x5d, 0x5d, 0xa3, 0x78,
- 0xc0, 0x99, 0x80, 0x26, 0x46, 0x12, 0x0f, 0xac, 0x98, 0xf8, 0x23, 0x9b, 0x98, 0x9a, 0x60, 0xe2,
- 0xc1, 0xa6, 0x9d, 0x3e, 0xba, 0x13, 0xda, 0x99, 0xcd, 0xcc, 0xb4, 0xa1, 0xff, 0x01, 0x47, 0x3d,
- 0x19, 0x6f, 0xfc, 0x01, 0xfe, 0x21, 0x1e, 0x39, 0x7a, 0x32, 0x06, 0x2e, 0x9e, 0xbd, 0x78, 0x35,
- 0x3b, 0x6d, 0xd9, 0x12, 0x2b, 0x10, 0xbc, 0xf5, 0xbd, 0xf7, 0x79, 0xef, 0x7d, 0x3e, 0x6f, 0x5e,
- 0x1f, 0x5a, 0x65, 0x5c, 0x83, 0xa4, 0x03, 0x9f, 0x71, 0x4f, 0x01, 0x4d, 0x25, 0xd3, 0x39, 0xa1,
- 0x34, 0x23, 0x43, 0x29, 0x32, 0x16, 0x82, 0x24, 0xd9, 0x1a, 0xd1, 0x7b, 0x78, 0x28, 0x85, 0x16,
- 0xf6, 0xad, 0x06, 0x34, 0xa6, 0x34, 0xc3, 0x15, 0x1a, 0x67, 0x6b, 0xed, 0xb9, 0x48, 0x44, 0xc2,
- 0xe0, 0xc9, 0xe8, 0xab, 0x48, 0x6d, 0x2f, 0x51, 0xa1, 0x12, 0xa1, 0xbc, 0x22, 0x50, 0x18, 0x55,
- 0x28, 0x12, 0x22, 0x8a, 0x81, 0x18, 0x2b, 0x48, 0x77, 0x88, 0xcf, 0xf3, 0x32, 0x44, 0x58, 0x40,
- 0x49, 0xcc, 0xa2, 0x81, 0xa6, 0x31, 0x03, 0xae, 0x15, 0xd1, 0xc0, 0x43, 0x90, 0x09, 0xe3, 0xda,
- 0x30, 0x3b, 0xb1, 0xca, 0x84, 0x4e, 0x2d, 0xae, 0xf3, 0x21, 0x28, 0x02, 0x23, 0x62, 0x9c, 0x42,
- 0x01, 0xe8, 0x7e, 0xb4, 0xd0, 0x5c, 0x5f, 0x45, 0x9b, 0x4a, 0xb1, 0x88, 0x3f, 0x11, 0x5c, 0xa5,
- 0x09, 0xc8, 0x97, 0x90, 0xdb, 0x4b, 0x68, 0xaa, 0x10, 0xc6, 0xc2, 0x45, 0xeb, 0x86, 0x75, 0x77,
- 0xda, 0xfd, 0xdf, 0xd8, 0xcf, 0x43, 0xfb, 0x21, 0xba, 0x52, 0x09, 0xf4, 0xfc, 0x30, 0x94, 0x8b,
- 0x13, 0xa3, 0x78, 0xcf, 0xfe, 0xf9, 0xad, 0x73, 0x35, 0xf7, 0x93, 0x78, 0xa3, 0x3b, 0xf2, 0x82,
- 0x52, 0x5d, 0x77, 0xb6, 0x02, 0x6e, 0x86, 0xa1, 0xb4, 0x6f, 0xa2, 0x59, 0x5a, 0xb6, 0xf0, 0x76,
- 0x21, 0x5f, 0x9c, 0x34, 0x75, 0x67, 0xe8, 0xb8, 0xed, 0xc6, 0xd4, 0xfe, 0x41, 0xa7, 0xf5, 0xe3,
- 0xa0, 0xd3, 0xea, 0x3a, 0x68, 0xb9, 0x89, 0x98, 0x0b, 0x6a, 0x28, 0xb8, 0x82, 0xee, 0x27, 0x0b,
- 0x5d, 0xef, 0xab, 0xe8, 0x75, 0x1a, 0x24, 0x4c, 0x57, 0x80, 0x3e, 0x53, 0x01, 0x0c, 0xfc, 0x8c,
- 0x89, 0x54, 0xda, 0xcb, 0x68, 0x5a, 0x99, 0xa8, 0x06, 0x59, 0x6a, 0x18, 0x3b, 0xec, 0x57, 0x68,
- 0x36, 0xa9, 0xa1, 0x8d, 0x88, 0x99, 0xf5, 0x55, 0xcc, 0x02, 0x8a, 0xeb, 0x23, 0xc6, 0xb5, 0xa1,
- 0x66, 0x6b, 0xb8, 0xde, 0xc1, 0x3d, 0x55, 0xa1, 0xc6, 0x7d, 0x05, 0xdd, 0x3e, 0x93, 0xda, 0x89,
- 0x88, 0xfd, 0x89, 0x06, 0x11, 0x5b, 0x22, 0x0d, 0x62, 0xd8, 0x16, 0x9a, 0xf1, 0xe8, 0x1c, 0x11,
- 0x1e, 0x5a, 0x08, 0xd3, 0x61, 0xcc, 0xa8, 0xaf, 0xc1, 0xcb, 0x84, 0x06, 0xaf, 0x7a, 0xdf, 0x52,
- 0xcf, 0x4a, 0x9d, 0xbe, 0xd9, 0x00, 0xbc, 0x55, 0x25, 0x6c, 0x0b, 0x0d, 0x4f, 0x4b, 0xb8, 0x3b,
- 0x1f, 0x36, 0xb9, 0xed, 0x77, 0x68, 0x81, 0xf1, 0x1d, 0xe9, 0x53, 0xcd, 0x04, 0xf7, 0x82, 0x58,
- 0xd0, 0x5d, 0x6f, 0x00, 0x7e, 0x08, 0xd2, 0xbc, 0xde, 0xcc, 0xfa, 0x9d, 0xf3, 0x06, 0xf6, 0xcc,
- 0xa0, 0xdd, 0xf9, 0x71, 0x99, 0xde, 0xa8, 0x4a, 0xe1, 0x3e, 0x67, 0x66, 0xf5, 0x49, 0x54, 0x33,
- 0x5b, 0xff, 0x35, 0x89, 0x26, 0xfb, 0x2a, 0xb2, 0x3f, 0x58, 0xe8, 0xda, 0x9f, 0x7b, 0xfb, 0x08,
- 0x5f, 0xe0, 0xa7, 0xc4, 0x4d, 0x9b, 0xd5, 0xde, 0xbc, 0x74, 0x6a, 0xc5, 0xcd, 0xfe, 0x6c, 0xa1,
- 0xf6, 0x19, 0x1b, 0xd9, 0xbb, 0x68, 0x87, 0xbf, 0xd7, 0x68, 0xbf, 0xf8, 0xf7, 0x1a, 0x67, 0xd0,
- 0x3d, 0xb5, 0x7b, 0x97, 0xa4, 0x5b, 0xaf, 0x71, 0x59, 0xba, 0x4d, 0x2f, 0xdf, 0x7b, 0xf3, 0xe5,
- 0xc8, 0xb1, 0x0e, 0x8f, 0x1c, 0xeb, 0xfb, 0x91, 0x63, 0xbd, 0x3f, 0x76, 0x5a, 0x87, 0xc7, 0x4e,
- 0xeb, 0xeb, 0xb1, 0xd3, 0x7a, 0xfb, 0x38, 0x62, 0x7a, 0x90, 0x06, 0x98, 0x8a, 0xa4, 0x3c, 0xa6,
- 0x64, 0xdc, 0xf6, 0xde, 0xc9, 0x25, 0xcf, 0x1e, 0x90, 0xbd, 0xd3, 0xe7, 0xdc, 0xfc, 0x12, 0xc1,
- 0x7f, 0xe6, 0x18, 0xde, 0xff, 0x1d, 0x00, 0x00, 0xff, 0xff, 0x74, 0xf3, 0x13, 0x1f, 0xff, 0x05,
- 0x00, 0x00,
+ // 787 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x56, 0xcd, 0x4f, 0xd4, 0x4e,
+ 0x18, 0xde, 0xc2, 0xef, 0xc7, 0xc7, 0x80, 0x46, 0x2a, 0x04, 0x68, 0x70, 0x57, 0x57, 0x05, 0x0f,
+ 0x6c, 0x1b, 0xf0, 0x2b, 0x12, 0x3d, 0xb0, 0x60, 0x22, 0x9a, 0x0d, 0xa4, 0x24, 0x98, 0x78, 0xb0,
+ 0x69, 0xa7, 0x43, 0x77, 0xc2, 0x76, 0xa6, 0xe9, 0x4c, 0x1b, 0xf6, 0xee, 0x81, 0xc4, 0x8b, 0x9e,
+ 0x8c, 0x37, 0xae, 0x26, 0x1e, 0xfd, 0x23, 0x38, 0x19, 0xe2, 0xc9, 0x78, 0x20, 0x06, 0x2e, 0x9e,
+ 0xfd, 0x0b, 0xcc, 0x4e, 0x3f, 0xb6, 0x1b, 0x96, 0x65, 0x81, 0x18, 0x4f, 0xbb, 0x33, 0xef, 0x33,
+ 0xcf, 0xfb, 0x3c, 0x6f, 0xa7, 0x4f, 0x0a, 0x66, 0x31, 0xe1, 0xc8, 0x87, 0x55, 0x13, 0x13, 0x83,
+ 0x21, 0x18, 0xf8, 0x98, 0xd7, 0x35, 0x08, 0x43, 0xcd, 0xf3, 0x69, 0x88, 0x6d, 0xe4, 0x6b, 0xe1,
+ 0x9c, 0xc6, 0xb7, 0x55, 0xcf, 0xa7, 0x9c, 0xca, 0x37, 0xdb, 0xa0, 0x55, 0x08, 0x43, 0x35, 0x41,
+ 0xab, 0xe1, 0x9c, 0x32, 0xea, 0x50, 0x87, 0x0a, 0xbc, 0xd6, 0xf8, 0x17, 0x1d, 0x55, 0x26, 0x21,
+ 0x65, 0x2e, 0x65, 0x46, 0x54, 0x88, 0x16, 0x49, 0xc9, 0xa1, 0xd4, 0xa9, 0x21, 0x4d, 0xac, 0xac,
+ 0x60, 0x53, 0x33, 0x49, 0x3d, 0x2e, 0x69, 0xd8, 0x82, 0x5a, 0x0d, 0x3b, 0x55, 0x0e, 0x6b, 0x18,
+ 0x11, 0xce, 0x34, 0x8e, 0x88, 0x8d, 0x7c, 0x17, 0x13, 0x2e, 0x94, 0xa5, 0xab, 0xf8, 0x40, 0x21,
+ 0x53, 0xe7, 0x75, 0x0f, 0x31, 0x0d, 0x35, 0x84, 0x11, 0x88, 0x22, 0x40, 0xf1, 0x83, 0x04, 0x46,
+ 0x2b, 0xcc, 0x59, 0x64, 0x0c, 0x3b, 0x64, 0x89, 0x12, 0x16, 0xb8, 0xc8, 0x7f, 0x81, 0xea, 0xf2,
+ 0x24, 0x18, 0x88, 0x8c, 0x61, 0x7b, 0x42, 0xba, 0x2e, 0xdd, 0x19, 0xd4, 0xfb, 0xc5, 0x7a, 0xc5,
+ 0x96, 0x1f, 0x82, 0x4b, 0x89, 0x41, 0xc3, 0xb4, 0x6d, 0x7f, 0xa2, 0xa7, 0x51, 0x2f, 0xcb, 0xbf,
+ 0x0f, 0x0a, 0x97, 0xeb, 0xa6, 0x5b, 0x5b, 0x28, 0x36, 0x76, 0x11, 0x63, 0x45, 0x7d, 0x38, 0x01,
+ 0x2e, 0xda, 0xb6, 0x2f, 0xdf, 0x00, 0xc3, 0x30, 0x6e, 0x61, 0x6c, 0xa1, 0xfa, 0x44, 0xaf, 0xe0,
+ 0x1d, 0x82, 0xcd, 0xb6, 0x0b, 0x03, 0x3b, 0xbb, 0x85, 0xdc, 0xaf, 0xdd, 0x42, 0xae, 0x98, 0x07,
+ 0x53, 0xed, 0x84, 0xe9, 0x88, 0x79, 0x94, 0x30, 0x54, 0xfc, 0x28, 0x81, 0x6b, 0x15, 0xe6, 0xac,
+ 0x07, 0x96, 0x8b, 0x79, 0x02, 0xa8, 0x60, 0x66, 0xa1, 0xaa, 0x19, 0x62, 0x1a, 0xf8, 0xf2, 0x14,
+ 0x18, 0x64, 0xa2, 0xca, 0x91, 0x1f, 0x7b, 0x68, 0x6e, 0xc8, 0x6b, 0x60, 0xd8, 0xcd, 0xa0, 0x85,
+ 0x89, 0xa1, 0xf9, 0x59, 0x15, 0x5b, 0x50, 0xcd, 0x8e, 0x58, 0xcd, 0x0c, 0x35, 0x9c, 0x53, 0xb3,
+ 0x1d, 0xf4, 0x16, 0x86, 0x8c, 0xf6, 0x19, 0x70, 0xbb, 0xa3, 0xb4, 0xd4, 0xc4, 0x4e, 0x4f, 0x1b,
+ 0x13, 0xcb, 0x34, 0xb0, 0x6a, 0x68, 0x83, 0x72, 0x4c, 0x9c, 0x53, 0x4c, 0x18, 0x60, 0xdc, 0x0e,
+ 0xbc, 0x1a, 0x86, 0x26, 0x47, 0x46, 0x48, 0x39, 0x32, 0x92, 0xe7, 0x1b, 0xfb, 0x99, 0xc9, 0xca,
+ 0x17, 0x37, 0x40, 0x5d, 0x4e, 0x0e, 0x6c, 0x50, 0x8e, 0x9e, 0xc6, 0x70, 0x7d, 0xcc, 0x6e, 0xb7,
+ 0x2d, 0xbf, 0x06, 0xe3, 0x98, 0x6c, 0xfa, 0x26, 0xe4, 0x98, 0x12, 0xc3, 0xaa, 0x51, 0xb8, 0x65,
+ 0x54, 0x91, 0x69, 0x23, 0x5f, 0x3c, 0xbd, 0xa1, 0xf9, 0xe9, 0xd3, 0x06, 0xf6, 0x4c, 0xa0, 0xf5,
+ 0xb1, 0x26, 0x4d, 0xb9, 0xc1, 0x12, 0x6d, 0x9f, 0x32, 0xb3, 0xec, 0x24, 0xd2, 0x99, 0xbd, 0x95,
+ 0xc0, 0x40, 0x85, 0x39, 0xab, 0x1e, 0x5f, 0x21, 0xff, 0xfe, 0x9a, 0xca, 0xe0, 0x4a, 0x22, 0x26,
+ 0x55, 0x88, 0xc1, 0x60, 0xb4, 0xb7, 0x1a, 0xf0, 0xbf, 0xa1, 0x30, 0xd3, 0xfe, 0x2a, 0x18, 0x49,
+ 0x5b, 0xa5, 0xfd, 0xbf, 0x4a, 0xe2, 0xdd, 0x59, 0x47, 0xe9, 0x20, 0x97, 0xa8, 0xeb, 0x62, 0xc6,
+ 0x30, 0x25, 0xba, 0xc9, 0xd1, 0xf1, 0xc6, 0x52, 0x97, 0xa3, 0xc9, 0x9a, 0xe9, 0x69, 0x35, 0xb3,
+ 0x06, 0xfe, 0xf3, 0x4d, 0x8e, 0xa2, 0x69, 0x95, 0x1f, 0xef, 0x1d, 0x14, 0x72, 0x3f, 0x0e, 0x0a,
+ 0xd3, 0x0e, 0xe6, 0xd5, 0xc0, 0x52, 0x21, 0x75, 0xe3, 0x94, 0x8b, 0x7f, 0x4a, 0xcc, 0xde, 0xd2,
+ 0xe2, 0x0b, 0x89, 0xe0, 0xb7, 0x2f, 0x25, 0x10, 0x87, 0xe0, 0x32, 0x82, 0xba, 0x60, 0xca, 0xb8,
+ 0x9c, 0x06, 0xb7, 0x3a, 0xf9, 0x49, 0x8c, 0xcf, 0xbf, 0xe9, 0x07, 0xbd, 0x15, 0xe6, 0xc8, 0xef,
+ 0x25, 0x30, 0x72, 0x3c, 0xd2, 0x1e, 0xa9, 0x5d, 0xe4, 0xb5, 0xda, 0x2e, 0x74, 0x94, 0xc5, 0x73,
+ 0x1f, 0x4d, 0xb4, 0xc9, 0x9f, 0x25, 0xa0, 0x74, 0x08, 0xab, 0x72, 0xb7, 0x1d, 0x4e, 0xe6, 0x50,
+ 0x9e, 0x5f, 0x9c, 0xa3, 0x83, 0xdc, 0x96, 0x58, 0x3a, 0xa7, 0xdc, 0x2c, 0xc7, 0x79, 0xe5, 0xb6,
+ 0x0b, 0x05, 0xd9, 0x05, 0xff, 0x47, 0x81, 0x50, 0xea, 0x96, 0x54, 0xc0, 0x95, 0xfb, 0x67, 0x82,
+ 0xa7, 0xed, 0x3c, 0xd0, 0x17, 0xbf, 0xde, 0xea, 0x19, 0x08, 0x56, 0x03, 0xae, 0x3c, 0x38, 0x1b,
+ 0x3e, 0xed, 0xf8, 0x49, 0x02, 0x93, 0x27, 0xbf, 0xd0, 0x5d, 0xdf, 0xcf, 0x13, 0x29, 0x94, 0x95,
+ 0x0b, 0x53, 0x24, 0x5a, 0xcb, 0x2f, 0xf7, 0x0e, 0xf3, 0xd2, 0xfe, 0x61, 0x5e, 0xfa, 0x79, 0x98,
+ 0x97, 0xde, 0x1d, 0xe5, 0x73, 0xfb, 0x47, 0xf9, 0xdc, 0xf7, 0xa3, 0x7c, 0xee, 0xd5, 0x93, 0xe3,
+ 0x71, 0xd0, 0xec, 0x5a, 0x4a, 0xbf, 0xb8, 0xc2, 0x7b, 0xda, 0x76, 0xeb, 0x67, 0x97, 0x48, 0x0a,
+ 0xab, 0x4f, 0x7c, 0xb4, 0xdc, 0xfd, 0x13, 0x00, 0x00, 0xff, 0xff, 0x76, 0xb7, 0xbf, 0x16, 0xa7,
+ 0x09, 0x00, 0x00,
}
// Reference imports to suppress errors if they are not otherwise used.
@@ -341,6 +596,9 @@ type MsgClient interface {
AssignConsumerKey(ctx context.Context, in *MsgAssignConsumerKey, opts ...grpc.CallOption) (*MsgAssignConsumerKeyResponse, error)
SubmitConsumerMisbehaviour(ctx context.Context, in *MsgSubmitConsumerMisbehaviour, opts ...grpc.CallOption) (*MsgSubmitConsumerMisbehaviourResponse, error)
SubmitConsumerDoubleVoting(ctx context.Context, in *MsgSubmitConsumerDoubleVoting, opts ...grpc.CallOption) (*MsgSubmitConsumerDoubleVotingResponse, error)
+ OptIn(ctx context.Context, in *MsgOptIn, opts ...grpc.CallOption) (*MsgOptInResponse, error)
+ OptOut(ctx context.Context, in *MsgOptOut, opts ...grpc.CallOption) (*MsgOptOutResponse, error)
+ SetConsumerCommissionRate(ctx context.Context, in *MsgSetConsumerCommissionRate, opts ...grpc.CallOption) (*MsgSetConsumerCommissionRateResponse, error)
}
type msgClient struct {
@@ -378,11 +636,41 @@ func (c *msgClient) SubmitConsumerDoubleVoting(ctx context.Context, in *MsgSubmi
return out, nil
}
+func (c *msgClient) OptIn(ctx context.Context, in *MsgOptIn, opts ...grpc.CallOption) (*MsgOptInResponse, error) {
+ out := new(MsgOptInResponse)
+ err := c.cc.Invoke(ctx, "/interchain_security.ccv.provider.v1.Msg/OptIn", in, out, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *msgClient) OptOut(ctx context.Context, in *MsgOptOut, opts ...grpc.CallOption) (*MsgOptOutResponse, error) {
+ out := new(MsgOptOutResponse)
+ err := c.cc.Invoke(ctx, "/interchain_security.ccv.provider.v1.Msg/OptOut", in, out, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *msgClient) SetConsumerCommissionRate(ctx context.Context, in *MsgSetConsumerCommissionRate, opts ...grpc.CallOption) (*MsgSetConsumerCommissionRateResponse, error) {
+ out := new(MsgSetConsumerCommissionRateResponse)
+ err := c.cc.Invoke(ctx, "/interchain_security.ccv.provider.v1.Msg/SetConsumerCommissionRate", in, out, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
// MsgServer is the server API for Msg service.
type MsgServer interface {
AssignConsumerKey(context.Context, *MsgAssignConsumerKey) (*MsgAssignConsumerKeyResponse, error)
SubmitConsumerMisbehaviour(context.Context, *MsgSubmitConsumerMisbehaviour) (*MsgSubmitConsumerMisbehaviourResponse, error)
SubmitConsumerDoubleVoting(context.Context, *MsgSubmitConsumerDoubleVoting) (*MsgSubmitConsumerDoubleVotingResponse, error)
+ OptIn(context.Context, *MsgOptIn) (*MsgOptInResponse, error)
+ OptOut(context.Context, *MsgOptOut) (*MsgOptOutResponse, error)
+ SetConsumerCommissionRate(context.Context, *MsgSetConsumerCommissionRate) (*MsgSetConsumerCommissionRateResponse, error)
}
// UnimplementedMsgServer can be embedded to have forward compatible implementations.
@@ -398,6 +686,15 @@ func (*UnimplementedMsgServer) SubmitConsumerMisbehaviour(ctx context.Context, r
func (*UnimplementedMsgServer) SubmitConsumerDoubleVoting(ctx context.Context, req *MsgSubmitConsumerDoubleVoting) (*MsgSubmitConsumerDoubleVotingResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method SubmitConsumerDoubleVoting not implemented")
}
+func (*UnimplementedMsgServer) OptIn(ctx context.Context, req *MsgOptIn) (*MsgOptInResponse, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method OptIn not implemented")
+}
+func (*UnimplementedMsgServer) OptOut(ctx context.Context, req *MsgOptOut) (*MsgOptOutResponse, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method OptOut not implemented")
+}
+func (*UnimplementedMsgServer) SetConsumerCommissionRate(ctx context.Context, req *MsgSetConsumerCommissionRate) (*MsgSetConsumerCommissionRateResponse, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method SetConsumerCommissionRate not implemented")
+}
func RegisterMsgServer(s grpc1.Server, srv MsgServer) {
s.RegisterService(&_Msg_serviceDesc, srv)
@@ -457,6 +754,60 @@ func _Msg_SubmitConsumerDoubleVoting_Handler(srv interface{}, ctx context.Contex
return interceptor(ctx, in, info, handler)
}
+func _Msg_OptIn_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(MsgOptIn)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(MsgServer).OptIn(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/interchain_security.ccv.provider.v1.Msg/OptIn",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(MsgServer).OptIn(ctx, req.(*MsgOptIn))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _Msg_OptOut_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(MsgOptOut)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(MsgServer).OptOut(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/interchain_security.ccv.provider.v1.Msg/OptOut",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(MsgServer).OptOut(ctx, req.(*MsgOptOut))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _Msg_SetConsumerCommissionRate_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(MsgSetConsumerCommissionRate)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(MsgServer).SetConsumerCommissionRate(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/interchain_security.ccv.provider.v1.Msg/SetConsumerCommissionRate",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(MsgServer).SetConsumerCommissionRate(ctx, req.(*MsgSetConsumerCommissionRate))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
var _Msg_serviceDesc = grpc.ServiceDesc{
ServiceName: "interchain_security.ccv.provider.v1.Msg",
HandlerType: (*MsgServer)(nil),
@@ -473,6 +824,18 @@ var _Msg_serviceDesc = grpc.ServiceDesc{
MethodName: "SubmitConsumerDoubleVoting",
Handler: _Msg_SubmitConsumerDoubleVoting_Handler,
},
+ {
+ MethodName: "OptIn",
+ Handler: _Msg_OptIn_Handler,
+ },
+ {
+ MethodName: "OptOut",
+ Handler: _Msg_OptOut_Handler,
+ },
+ {
+ MethodName: "SetConsumerCommissionRate",
+ Handler: _Msg_SetConsumerCommissionRate_Handler,
+ },
},
Streams: []grpc.StreamDesc{},
Metadata: "interchain_security/ccv/provider/v1/tx.proto",
@@ -651,146 +1014,995 @@ func (m *MsgSubmitConsumerDoubleVoting) MarshalToSizedBuffer(dAtA []byte) (int,
i -= size
i = encodeVarintTx(dAtA, i, uint64(size))
}
- i--
- dAtA[i] = 0x12
- }
- if len(m.Submitter) > 0 {
- i -= len(m.Submitter)
- copy(dAtA[i:], m.Submitter)
- i = encodeVarintTx(dAtA, i, uint64(len(m.Submitter)))
- i--
- dAtA[i] = 0xa
- }
- return len(dAtA) - i, nil
-}
-
-func (m *MsgSubmitConsumerDoubleVotingResponse) 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 *MsgSubmitConsumerDoubleVotingResponse) MarshalTo(dAtA []byte) (int, error) {
- size := m.Size()
- return m.MarshalToSizedBuffer(dAtA[:size])
-}
-
-func (m *MsgSubmitConsumerDoubleVotingResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
- i := len(dAtA)
- _ = i
- var l int
- _ = l
- return len(dAtA) - i, nil
-}
-
-func encodeVarintTx(dAtA []byte, offset int, v uint64) int {
- offset -= sovTx(v)
- base := offset
- for v >= 1<<7 {
- dAtA[offset] = uint8(v&0x7f | 0x80)
- v >>= 7
- offset++
- }
- dAtA[offset] = uint8(v)
- return base
-}
-func (m *MsgAssignConsumerKey) Size() (n int) {
- if m == nil {
- return 0
- }
- var l int
- _ = l
- l = len(m.ChainId)
- if l > 0 {
- n += 1 + l + sovTx(uint64(l))
- }
- l = len(m.ProviderAddr)
- if l > 0 {
- n += 1 + l + sovTx(uint64(l))
- }
- l = len(m.ConsumerKey)
- if l > 0 {
- n += 1 + l + sovTx(uint64(l))
+ i--
+ dAtA[i] = 0x12
+ }
+ if len(m.Submitter) > 0 {
+ i -= len(m.Submitter)
+ copy(dAtA[i:], m.Submitter)
+ i = encodeVarintTx(dAtA, i, uint64(len(m.Submitter)))
+ i--
+ dAtA[i] = 0xa
+ }
+ return len(dAtA) - i, nil
+}
+
+func (m *MsgSubmitConsumerDoubleVotingResponse) 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 *MsgSubmitConsumerDoubleVotingResponse) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *MsgSubmitConsumerDoubleVotingResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ return len(dAtA) - i, nil
+}
+
+func (m *MsgOptIn) 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 *MsgOptIn) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *MsgOptIn) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if len(m.ConsumerKey) > 0 {
+ i -= len(m.ConsumerKey)
+ copy(dAtA[i:], m.ConsumerKey)
+ i = encodeVarintTx(dAtA, i, uint64(len(m.ConsumerKey)))
+ i--
+ dAtA[i] = 0x1a
+ }
+ if len(m.ProviderAddr) > 0 {
+ i -= len(m.ProviderAddr)
+ copy(dAtA[i:], m.ProviderAddr)
+ i = encodeVarintTx(dAtA, i, uint64(len(m.ProviderAddr)))
+ i--
+ dAtA[i] = 0x12
+ }
+ if len(m.ChainId) > 0 {
+ i -= len(m.ChainId)
+ copy(dAtA[i:], m.ChainId)
+ i = encodeVarintTx(dAtA, i, uint64(len(m.ChainId)))
+ i--
+ dAtA[i] = 0xa
+ }
+ return len(dAtA) - i, nil
+}
+
+func (m *MsgOptInResponse) 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 *MsgOptInResponse) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *MsgOptInResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ return len(dAtA) - i, nil
+}
+
+func (m *MsgOptOut) 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 *MsgOptOut) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *MsgOptOut) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if len(m.ProviderAddr) > 0 {
+ i -= len(m.ProviderAddr)
+ copy(dAtA[i:], m.ProviderAddr)
+ i = encodeVarintTx(dAtA, i, uint64(len(m.ProviderAddr)))
+ i--
+ dAtA[i] = 0x12
+ }
+ if len(m.ChainId) > 0 {
+ i -= len(m.ChainId)
+ copy(dAtA[i:], m.ChainId)
+ i = encodeVarintTx(dAtA, i, uint64(len(m.ChainId)))
+ i--
+ dAtA[i] = 0xa
+ }
+ return len(dAtA) - i, nil
+}
+
+func (m *MsgOptOutResponse) 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 *MsgOptOutResponse) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *MsgOptOutResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ return len(dAtA) - i, nil
+}
+
+func (m *MsgSetConsumerCommissionRate) 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 *MsgSetConsumerCommissionRate) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *MsgSetConsumerCommissionRate) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ {
+ size := m.Rate.Size()
+ i -= size
+ if _, err := m.Rate.MarshalTo(dAtA[i:]); err != nil {
+ return 0, err
+ }
+ i = encodeVarintTx(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0x1a
+ if len(m.ChainId) > 0 {
+ i -= len(m.ChainId)
+ copy(dAtA[i:], m.ChainId)
+ i = encodeVarintTx(dAtA, i, uint64(len(m.ChainId)))
+ i--
+ dAtA[i] = 0x12
+ }
+ if len(m.ProviderAddr) > 0 {
+ i -= len(m.ProviderAddr)
+ copy(dAtA[i:], m.ProviderAddr)
+ i = encodeVarintTx(dAtA, i, uint64(len(m.ProviderAddr)))
+ i--
+ dAtA[i] = 0xa
+ }
+ return len(dAtA) - i, nil
+}
+
+func (m *MsgSetConsumerCommissionRateResponse) 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 *MsgSetConsumerCommissionRateResponse) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *MsgSetConsumerCommissionRateResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ return len(dAtA) - i, nil
+}
+
+func encodeVarintTx(dAtA []byte, offset int, v uint64) int {
+ offset -= sovTx(v)
+ base := offset
+ for v >= 1<<7 {
+ dAtA[offset] = uint8(v&0x7f | 0x80)
+ v >>= 7
+ offset++
+ }
+ dAtA[offset] = uint8(v)
+ return base
+}
+func (m *MsgAssignConsumerKey) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ l = len(m.ChainId)
+ if l > 0 {
+ n += 1 + l + sovTx(uint64(l))
+ }
+ l = len(m.ProviderAddr)
+ if l > 0 {
+ n += 1 + l + sovTx(uint64(l))
+ }
+ l = len(m.ConsumerKey)
+ if l > 0 {
+ n += 1 + l + sovTx(uint64(l))
+ }
+ return n
+}
+
+func (m *MsgAssignConsumerKeyResponse) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ return n
+}
+
+func (m *MsgSubmitConsumerMisbehaviour) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ l = len(m.Submitter)
+ if l > 0 {
+ n += 1 + l + sovTx(uint64(l))
+ }
+ if m.Misbehaviour != nil {
+ l = m.Misbehaviour.Size()
+ n += 1 + l + sovTx(uint64(l))
+ }
+ return n
+}
+
+func (m *MsgSubmitConsumerMisbehaviourResponse) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ return n
+}
+
+func (m *MsgSubmitConsumerDoubleVoting) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ l = len(m.Submitter)
+ if l > 0 {
+ n += 1 + l + sovTx(uint64(l))
+ }
+ if m.DuplicateVoteEvidence != nil {
+ l = m.DuplicateVoteEvidence.Size()
+ n += 1 + l + sovTx(uint64(l))
+ }
+ if m.InfractionBlockHeader != nil {
+ l = m.InfractionBlockHeader.Size()
+ n += 1 + l + sovTx(uint64(l))
+ }
+ return n
+}
+
+func (m *MsgSubmitConsumerDoubleVotingResponse) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ return n
+}
+
+func (m *MsgOptIn) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ l = len(m.ChainId)
+ if l > 0 {
+ n += 1 + l + sovTx(uint64(l))
+ }
+ l = len(m.ProviderAddr)
+ if l > 0 {
+ n += 1 + l + sovTx(uint64(l))
+ }
+ l = len(m.ConsumerKey)
+ if l > 0 {
+ n += 1 + l + sovTx(uint64(l))
+ }
+ return n
+}
+
+func (m *MsgOptInResponse) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ return n
+}
+
+func (m *MsgOptOut) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ l = len(m.ChainId)
+ if l > 0 {
+ n += 1 + l + sovTx(uint64(l))
+ }
+ l = len(m.ProviderAddr)
+ if l > 0 {
+ n += 1 + l + sovTx(uint64(l))
+ }
+ return n
+}
+
+func (m *MsgOptOutResponse) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ return n
+}
+
+func (m *MsgSetConsumerCommissionRate) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ l = len(m.ProviderAddr)
+ if l > 0 {
+ n += 1 + l + sovTx(uint64(l))
+ }
+ l = len(m.ChainId)
+ if l > 0 {
+ n += 1 + l + sovTx(uint64(l))
+ }
+ l = m.Rate.Size()
+ n += 1 + l + sovTx(uint64(l))
+ return n
+}
+
+func (m *MsgSetConsumerCommissionRateResponse) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ return n
+}
+
+func sovTx(x uint64) (n int) {
+ return (math_bits.Len64(x|1) + 6) / 7
+}
+func sozTx(x uint64) (n int) {
+ return sovTx(uint64((x << 1) ^ uint64((int64(x) >> 63))))
+}
+func (m *MsgAssignConsumerKey) 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 ErrIntOverflowTx
+ }
+ 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: MsgAssignConsumerKey: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: MsgAssignConsumerKey: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field ChainId", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowTx
+ }
+ 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 ErrInvalidLengthTx
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthTx
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.ChainId = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field ProviderAddr", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowTx
+ }
+ 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 ErrInvalidLengthTx
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthTx
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.ProviderAddr = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 3:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field ConsumerKey", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowTx
+ }
+ 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 ErrInvalidLengthTx
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthTx
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.ConsumerKey = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipTx(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthTx
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *MsgAssignConsumerKeyResponse) 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 ErrIntOverflowTx
+ }
+ 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: MsgAssignConsumerKeyResponse: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: MsgAssignConsumerKeyResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ default:
+ iNdEx = preIndex
+ skippy, err := skipTx(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthTx
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *MsgSubmitConsumerMisbehaviour) 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 ErrIntOverflowTx
+ }
+ 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: MsgSubmitConsumerMisbehaviour: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: MsgSubmitConsumerMisbehaviour: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Submitter", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowTx
+ }
+ 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 ErrInvalidLengthTx
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthTx
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Submitter = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Misbehaviour", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowTx
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthTx
+ }
+ postIndex := iNdEx + msglen
+ if postIndex < 0 {
+ return ErrInvalidLengthTx
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.Misbehaviour == nil {
+ m.Misbehaviour = &_07_tendermint.Misbehaviour{}
+ }
+ if err := m.Misbehaviour.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipTx(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthTx
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *MsgSubmitConsumerMisbehaviourResponse) 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 ErrIntOverflowTx
+ }
+ 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: MsgSubmitConsumerMisbehaviourResponse: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: MsgSubmitConsumerMisbehaviourResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ default:
+ iNdEx = preIndex
+ skippy, err := skipTx(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthTx
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *MsgSubmitConsumerDoubleVoting) 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 ErrIntOverflowTx
+ }
+ 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: MsgSubmitConsumerDoubleVoting: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: MsgSubmitConsumerDoubleVoting: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Submitter", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowTx
+ }
+ 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 ErrInvalidLengthTx
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthTx
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Submitter = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field DuplicateVoteEvidence", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowTx
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthTx
+ }
+ postIndex := iNdEx + msglen
+ if postIndex < 0 {
+ return ErrInvalidLengthTx
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.DuplicateVoteEvidence == nil {
+ m.DuplicateVoteEvidence = &types.DuplicateVoteEvidence{}
+ }
+ if err := m.DuplicateVoteEvidence.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 3:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field InfractionBlockHeader", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowTx
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthTx
+ }
+ postIndex := iNdEx + msglen
+ if postIndex < 0 {
+ return ErrInvalidLengthTx
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.InfractionBlockHeader == nil {
+ m.InfractionBlockHeader = &_07_tendermint.Header{}
+ }
+ if err := m.InfractionBlockHeader.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipTx(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthTx
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
}
- return n
-}
-
-func (m *MsgAssignConsumerKeyResponse) Size() (n int) {
- if m == nil {
- return 0
- }
- var l int
- _ = l
- return n
-}
-
-func (m *MsgSubmitConsumerMisbehaviour) Size() (n int) {
- if m == nil {
- return 0
- }
- var l int
- _ = l
- l = len(m.Submitter)
- if l > 0 {
- n += 1 + l + sovTx(uint64(l))
- }
- if m.Misbehaviour != nil {
- l = m.Misbehaviour.Size()
- n += 1 + l + sovTx(uint64(l))
- }
- return n
-}
-func (m *MsgSubmitConsumerMisbehaviourResponse) Size() (n int) {
- if m == nil {
- return 0
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
}
- var l int
- _ = l
- return n
+ return nil
}
-
-func (m *MsgSubmitConsumerDoubleVoting) Size() (n int) {
- if m == nil {
- return 0
- }
- var l int
- _ = l
- l = len(m.Submitter)
- if l > 0 {
- n += 1 + l + sovTx(uint64(l))
- }
- if m.DuplicateVoteEvidence != nil {
- l = m.DuplicateVoteEvidence.Size()
- n += 1 + l + sovTx(uint64(l))
- }
- if m.InfractionBlockHeader != nil {
- l = m.InfractionBlockHeader.Size()
- n += 1 + l + sovTx(uint64(l))
+func (m *MsgSubmitConsumerDoubleVotingResponse) 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 ErrIntOverflowTx
+ }
+ 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: MsgSubmitConsumerDoubleVotingResponse: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: MsgSubmitConsumerDoubleVotingResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ default:
+ iNdEx = preIndex
+ skippy, err := skipTx(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthTx
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
}
- return n
-}
-func (m *MsgSubmitConsumerDoubleVotingResponse) Size() (n int) {
- if m == nil {
- return 0
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
}
- var l int
- _ = l
- return n
-}
-
-func sovTx(x uint64) (n int) {
- return (math_bits.Len64(x|1) + 6) / 7
-}
-func sozTx(x uint64) (n int) {
- return sovTx(uint64((x << 1) ^ uint64((int64(x) >> 63))))
+ return nil
}
-func (m *MsgAssignConsumerKey) Unmarshal(dAtA []byte) error {
+func (m *MsgOptIn) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
@@ -813,10 +2025,10 @@ func (m *MsgAssignConsumerKey) Unmarshal(dAtA []byte) error {
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
- return fmt.Errorf("proto: MsgAssignConsumerKey: wiretype end group for non-group")
+ return fmt.Errorf("proto: MsgOptIn: wiretype end group for non-group")
}
if fieldNum <= 0 {
- return fmt.Errorf("proto: MsgAssignConsumerKey: illegal tag %d (wire type %d)", fieldNum, wire)
+ return fmt.Errorf("proto: MsgOptIn: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
@@ -936,7 +2148,7 @@ func (m *MsgAssignConsumerKey) Unmarshal(dAtA []byte) error {
}
return nil
}
-func (m *MsgAssignConsumerKeyResponse) Unmarshal(dAtA []byte) error {
+func (m *MsgOptInResponse) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
@@ -959,10 +2171,10 @@ func (m *MsgAssignConsumerKeyResponse) Unmarshal(dAtA []byte) error {
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
- return fmt.Errorf("proto: MsgAssignConsumerKeyResponse: wiretype end group for non-group")
+ return fmt.Errorf("proto: MsgOptInResponse: wiretype end group for non-group")
}
if fieldNum <= 0 {
- return fmt.Errorf("proto: MsgAssignConsumerKeyResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+ return fmt.Errorf("proto: MsgOptInResponse: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
default:
@@ -986,7 +2198,7 @@ func (m *MsgAssignConsumerKeyResponse) Unmarshal(dAtA []byte) error {
}
return nil
}
-func (m *MsgSubmitConsumerMisbehaviour) Unmarshal(dAtA []byte) error {
+func (m *MsgOptOut) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
@@ -1009,15 +2221,15 @@ func (m *MsgSubmitConsumerMisbehaviour) Unmarshal(dAtA []byte) error {
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
- return fmt.Errorf("proto: MsgSubmitConsumerMisbehaviour: wiretype end group for non-group")
+ return fmt.Errorf("proto: MsgOptOut: wiretype end group for non-group")
}
if fieldNum <= 0 {
- return fmt.Errorf("proto: MsgSubmitConsumerMisbehaviour: illegal tag %d (wire type %d)", fieldNum, wire)
+ return fmt.Errorf("proto: MsgOptOut: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
- return fmt.Errorf("proto: wrong wireType = %d for field Submitter", wireType)
+ return fmt.Errorf("proto: wrong wireType = %d for field ChainId", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
@@ -1045,13 +2257,13 @@ func (m *MsgSubmitConsumerMisbehaviour) Unmarshal(dAtA []byte) error {
if postIndex > l {
return io.ErrUnexpectedEOF
}
- m.Submitter = string(dAtA[iNdEx:postIndex])
+ m.ChainId = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 2:
if wireType != 2 {
- return fmt.Errorf("proto: wrong wireType = %d for field Misbehaviour", wireType)
+ return fmt.Errorf("proto: wrong wireType = %d for field ProviderAddr", wireType)
}
- var msglen int
+ var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowTx
@@ -1061,27 +2273,23 @@ func (m *MsgSubmitConsumerMisbehaviour) Unmarshal(dAtA []byte) error {
}
b := dAtA[iNdEx]
iNdEx++
- msglen |= int(b&0x7F) << shift
+ stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
- if msglen < 0 {
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
return ErrInvalidLengthTx
}
- postIndex := iNdEx + msglen
+ postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthTx
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
- if m.Misbehaviour == nil {
- m.Misbehaviour = &_07_tendermint.Misbehaviour{}
- }
- if err := m.Misbehaviour.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
- return err
- }
+ m.ProviderAddr = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
default:
iNdEx = preIndex
@@ -1104,7 +2312,7 @@ func (m *MsgSubmitConsumerMisbehaviour) Unmarshal(dAtA []byte) error {
}
return nil
}
-func (m *MsgSubmitConsumerMisbehaviourResponse) Unmarshal(dAtA []byte) error {
+func (m *MsgOptOutResponse) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
@@ -1127,10 +2335,10 @@ func (m *MsgSubmitConsumerMisbehaviourResponse) Unmarshal(dAtA []byte) error {
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
- return fmt.Errorf("proto: MsgSubmitConsumerMisbehaviourResponse: wiretype end group for non-group")
+ return fmt.Errorf("proto: MsgOptOutResponse: wiretype end group for non-group")
}
if fieldNum <= 0 {
- return fmt.Errorf("proto: MsgSubmitConsumerMisbehaviourResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+ return fmt.Errorf("proto: MsgOptOutResponse: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
default:
@@ -1154,7 +2362,7 @@ func (m *MsgSubmitConsumerMisbehaviourResponse) Unmarshal(dAtA []byte) error {
}
return nil
}
-func (m *MsgSubmitConsumerDoubleVoting) Unmarshal(dAtA []byte) error {
+func (m *MsgSetConsumerCommissionRate) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
@@ -1177,15 +2385,15 @@ func (m *MsgSubmitConsumerDoubleVoting) Unmarshal(dAtA []byte) error {
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
- return fmt.Errorf("proto: MsgSubmitConsumerDoubleVoting: wiretype end group for non-group")
+ return fmt.Errorf("proto: MsgSetConsumerCommissionRate: wiretype end group for non-group")
}
if fieldNum <= 0 {
- return fmt.Errorf("proto: MsgSubmitConsumerDoubleVoting: illegal tag %d (wire type %d)", fieldNum, wire)
+ return fmt.Errorf("proto: MsgSetConsumerCommissionRate: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
- return fmt.Errorf("proto: wrong wireType = %d for field Submitter", wireType)
+ return fmt.Errorf("proto: wrong wireType = %d for field ProviderAddr", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
@@ -1213,13 +2421,13 @@ func (m *MsgSubmitConsumerDoubleVoting) Unmarshal(dAtA []byte) error {
if postIndex > l {
return io.ErrUnexpectedEOF
}
- m.Submitter = string(dAtA[iNdEx:postIndex])
+ m.ProviderAddr = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 2:
if wireType != 2 {
- return fmt.Errorf("proto: wrong wireType = %d for field DuplicateVoteEvidence", wireType)
+ return fmt.Errorf("proto: wrong wireType = %d for field ChainId", wireType)
}
- var msglen int
+ var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowTx
@@ -1229,33 +2437,29 @@ func (m *MsgSubmitConsumerDoubleVoting) Unmarshal(dAtA []byte) error {
}
b := dAtA[iNdEx]
iNdEx++
- msglen |= int(b&0x7F) << shift
+ stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
- if msglen < 0 {
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
return ErrInvalidLengthTx
}
- postIndex := iNdEx + msglen
+ postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthTx
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
- if m.DuplicateVoteEvidence == nil {
- m.DuplicateVoteEvidence = &types.DuplicateVoteEvidence{}
- }
- if err := m.DuplicateVoteEvidence.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
- return err
- }
+ m.ChainId = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 3:
if wireType != 2 {
- return fmt.Errorf("proto: wrong wireType = %d for field InfractionBlockHeader", wireType)
+ return fmt.Errorf("proto: wrong wireType = %d for field Rate", wireType)
}
- var msglen int
+ var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowTx
@@ -1265,25 +2469,23 @@ func (m *MsgSubmitConsumerDoubleVoting) Unmarshal(dAtA []byte) error {
}
b := dAtA[iNdEx]
iNdEx++
- msglen |= int(b&0x7F) << shift
+ stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
- if msglen < 0 {
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
return ErrInvalidLengthTx
}
- postIndex := iNdEx + msglen
+ postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthTx
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
- if m.InfractionBlockHeader == nil {
- m.InfractionBlockHeader = &_07_tendermint.Header{}
- }
- if err := m.InfractionBlockHeader.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ if err := m.Rate.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
@@ -1308,7 +2510,7 @@ func (m *MsgSubmitConsumerDoubleVoting) Unmarshal(dAtA []byte) error {
}
return nil
}
-func (m *MsgSubmitConsumerDoubleVotingResponse) Unmarshal(dAtA []byte) error {
+func (m *MsgSetConsumerCommissionRateResponse) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
@@ -1331,10 +2533,10 @@ func (m *MsgSubmitConsumerDoubleVotingResponse) Unmarshal(dAtA []byte) error {
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
- return fmt.Errorf("proto: MsgSubmitConsumerDoubleVotingResponse: wiretype end group for non-group")
+ return fmt.Errorf("proto: MsgSetConsumerCommissionRateResponse: wiretype end group for non-group")
}
if fieldNum <= 0 {
- return fmt.Errorf("proto: MsgSubmitConsumerDoubleVotingResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+ return fmt.Errorf("proto: MsgSetConsumerCommissionRateResponse: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
default:
diff --git a/x/ccv/types/expected_keepers.go b/x/ccv/types/expected_keepers.go
index a2ef7ab465..b3815b6d65 100644
--- a/x/ccv/types/expected_keepers.go
+++ b/x/ccv/types/expected_keepers.go
@@ -15,6 +15,7 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
auth "github.com/cosmos/cosmos-sdk/x/auth/types"
capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types"
+ distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types"
v1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1"
slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
@@ -41,6 +42,9 @@ type StakingKeeper interface {
IterateLastValidatorPowers(ctx sdk.Context, cb func(addr sdk.ValAddress, power int64) (stop bool))
PowerReduction(ctx sdk.Context) math.Int
PutUnbondingOnHold(ctx sdk.Context, id uint64) error
+ GetUnbondingDelegationByUnbondingID(ctx sdk.Context, id uint64) (ubd stakingtypes.UnbondingDelegation, found bool)
+ GetRedelegationByUnbondingID(ctx sdk.Context, id uint64) (red stakingtypes.Redelegation, found bool)
+ GetValidatorByUnbondingID(ctx sdk.Context, id uint64) (val stakingtypes.Validator, found bool)
IterateValidators(ctx sdk.Context, f func(index int64, validator stakingtypes.ValidatorI) (stop bool))
Validator(ctx sdk.Context, addr sdk.ValAddress) stakingtypes.ValidatorI
IsValidatorJailed(ctx sdk.Context, addr sdk.ConsAddress) bool
@@ -53,6 +57,7 @@ type StakingKeeper interface {
GetUnbondingDelegationsFromValidator(ctx sdk.Context, valAddr sdk.ValAddress) (ubds []stakingtypes.UnbondingDelegation)
GetRedelegationsFromSrcValidator(ctx sdk.Context, valAddr sdk.ValAddress) (reds []stakingtypes.Redelegation)
GetUnbondingType(ctx sdk.Context, id uint64) (unbondingType stakingtypes.UnbondingType, found bool)
+ MinCommissionRate(ctx sdk.Context) math.LegacyDec
}
// SlashingKeeper defines the contract expected to perform ccv slashing
@@ -109,6 +114,10 @@ type ClientKeeper interface {
// DistributionKeeper defines the expected interface of the distribution keeper
type DistributionKeeper interface {
FundCommunityPool(ctx sdk.Context, amount sdk.Coins, sender sdk.AccAddress) error
+ GetFeePool(ctx sdk.Context) distrtypes.FeePool
+ SetFeePool(ctx sdk.Context, feePool distrtypes.FeePool)
+ GetCommunityTax(ctx sdk.Context) math.LegacyDec
+ AllocateTokensToValidator(ctx sdk.Context, validator stakingtypes.ValidatorI, reward sdk.DecCoins)
}
// ConsumerHooks event hooks for newly bonded cross-chain validators
diff --git a/x/ccv/types/utils_test.go b/x/ccv/types/utils_test.go
index f7ecd83197..44f4ff6d27 100644
--- a/x/ccv/types/utils_test.go
+++ b/x/ccv/types/utils_test.go
@@ -10,7 +10,7 @@ import (
abci "github.com/cometbft/cometbft/abci/types"
- "github.com/cosmos/interchain-security/v4/x/ccv/types"
+ "github.com/cosmos/interchain-security/v5/x/ccv/types"
)
func TestAccumulateChanges(t *testing.T) {
diff --git a/x/ccv/types/wire_test.go b/x/ccv/types/wire_test.go
index ab6692912e..93512a5218 100644
--- a/x/ccv/types/wire_test.go
+++ b/x/ccv/types/wire_test.go
@@ -12,8 +12,8 @@ import (
abci "github.com/cometbft/cometbft/abci/types"
- "github.com/cosmos/interchain-security/v4/testutil/crypto"
- "github.com/cosmos/interchain-security/v4/x/ccv/types"
+ "github.com/cosmos/interchain-security/v5/testutil/crypto"
+ "github.com/cosmos/interchain-security/v5/x/ccv/types"
)
func TestPacketDataValidateBasic(t *testing.T) {