From 80b751c1d3afb5d2f8684868548faf8d3995ae3f Mon Sep 17 00:00:00 2001 From: Marius Poke Date: Tue, 1 Nov 2022 20:39:30 +0100 Subject: [PATCH] Channel initialization timeout (#406) * add provider-based timeout params * add InitTimeoutTimestamp to store * add init timeout logic * params boilerplate code & making tests pass * add TestInitTimeout* e2e tests * improve e2e tests; add test case to TestUndelegationDuringInit * remove VSC timeout * remove VSC timeout param * add testcase to TestValidateParams * handle StopConsumerChain error & gofmt * Fix init timeout conflicts (#409) * Importable e2e tests (#401) * fixes * add comment to GetInitTimeoutTimestamp * Update proto/interchain_security/ccv/provider/v1/provider.proto Co-authored-by: Aditya * fix formatting in proto file * add comment to SetConsumerChain * fix typo * add comment re. EndBlock order * change name of testcase in TestUndelegationDuringInit Co-authored-by: Shawn Marshall-Spitzbart <44221603+smarshall-spitzbart@users.noreply.github.com> Co-authored-by: Aditya --- app/consumer-democracy/export.go | 3 +- app/provider/export.go | 3 +- docs/quality_assurance.md | 2 +- go.mod | 1 - go.sum | 1 - .../ccv/provider/v1/provider.proto | 9 +- tests/e2e/channel_init.go | 97 +++++++++ tests/e2e/common.go | 50 +++-- tests/e2e/distribution.go | 2 +- tests/e2e/stop_consumer.go | 10 +- tests/e2e/unbonding.go | 165 +++++++++------ x/ccv/provider/ibc_module.go | 1 - x/ccv/provider/keeper/keeper.go | 60 +++++- x/ccv/provider/keeper/keeper_test.go | 40 ++++ x/ccv/provider/keeper/params.go | 22 +- x/ccv/provider/keeper/params_test.go | 2 +- x/ccv/provider/keeper/proposal.go | 4 + x/ccv/provider/keeper/proposal_test.go | 3 +- x/ccv/provider/keeper/relay.go | 49 ++++- x/ccv/provider/module.go | 11 +- x/ccv/provider/types/genesis_test.go | 33 ++- x/ccv/provider/types/keys.go | 11 +- x/ccv/provider/types/keys_test.go | 9 +- x/ccv/provider/types/params.go | 35 +++- x/ccv/provider/types/params_test.go | 17 +- x/ccv/provider/types/provider.pb.go | 189 +++++++++++------- 26 files changed, 625 insertions(+), 204 deletions(-) diff --git a/app/consumer-democracy/export.go b/app/consumer-democracy/export.go index c146ab7ad2..6f7f565239 100644 --- a/app/consumer-democracy/export.go +++ b/app/consumer-democracy/export.go @@ -49,7 +49,8 @@ func (app *App) ExportAppStateAndValidators( // prepare for fresh start at zero height // NOTE zero height genesis is a temporary feature which will be deprecated -// in favour of export at a block height +// +// in favour of export at a block height func (app *App) prepForZeroHeightGenesis(ctx sdk.Context, jailAllowedAddrs []string) { // applyAllowedAddrs := false diff --git a/app/provider/export.go b/app/provider/export.go index f5e4ffc4b2..5ea9b63755 100644 --- a/app/provider/export.go +++ b/app/provider/export.go @@ -50,7 +50,8 @@ func (app *App) ExportAppStateAndValidators( // prepare for fresh start at zero height // NOTE zero height genesis is a temporary feature which will be deprecated -// in favour of export at a block height +// +// in favour of export at a block height func (app *App) prepForZeroHeightGenesis(ctx sdk.Context, jailAllowedAddrs []string) { applyAllowedAddrs := false diff --git a/docs/quality_assurance.md b/docs/quality_assurance.md index 82aa137475..6ccc39d4d2 100644 --- a/docs/quality_assurance.md +++ b/docs/quality_assurance.md @@ -80,7 +80,7 @@ The main concern addressed in this section is the correctness of the provider ch | 4.01 | Liveness of undelegations
- unbonding delegation entries are eventually removed from `UnbondingDelegation` | `Scheduled` | `NA` | `Done`
[unbonding_test.go](../tests/e2e/unbonding_test.go) | `Done` | `Scheduled` | `NA` | | 4.02 | Liveness of redelegations
- redelegations entries are eventually removed from `Redelegations` | `Scheduled` | `NA` | `Scheduled` | `Scheduled` | `Scheduled` | `NA` | | 4.03 | Liveness of validator unbondings
- unbonding validators with no delegations are eventually removed from `Validators` | `Scheduled` | `NA` | `NA` | `Done` | `Scheduled` | `NA` | -| 4.04 | Unbonding operations (undelegations, redelegations, validator unbondings) should eventually complete even if the CCV channel is never established (due to error)
- expected outcome: the channel initialization sub-protocol eventually times out, which leads to the consumer chain removal
- requires https://github.com/cosmos/interchain-security/issues/278 | `Scheduled` | `NA` | `Scheduled` | `Future work` | `Scheduled` | `Done` | +| 4.04 | Unbonding operations (undelegations, redelegations, validator unbondings) should eventually complete even if the CCV channel is never established (due to error)
- expected outcome: the channel initialization sub-protocol eventually times out, which leads to the consumer chain removal | `Scheduled` | `NA` | `Done` [TestUndelegationDuringInit](../tests/e2e/unbonding_test.go#145) | `Future work` | `Scheduled` | `Done` | | 4.05 | Unbonding operations (undelegations, redelegations, validator unbondings) should eventually complete even if one of the clients expire
- expected outcome: the pending VSC packets eventually timeout, which leads to the consumer chain removal
- requires https://github.com/cosmos/interchain-security/issues/283 | `Scheduled` | `NA` | `Scheduled` | `Future work` | `Scheduled` | `NA` | | 4.06 | A validator cannot get slashed more than once for double signing, regardless of how many times it double signs on different chains (consumers or provider) | `Scheduled` | `NA` |`Done`
[TestHandleSlashPacketErrors](../tests/e2e/slashing_test.go#L317) | `Done` | `Scheduled` | `NA` | | 4.07 | A validator cannot get slashed multiple times for downtime on the same consumer chain without requesting to `Unjail` itself on the provider chain in between | `Scheduled` | `NA` | `Partial coverage`
[TestSendSlashPacket](../tests/e2e/slashing_test.go#L648) | `Partial coverage` | `Scheduled` | `NA` | diff --git a/go.mod b/go.mod index 2ff5be48a5..223beac5ff 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,6 @@ go 1.18 require ( github.com/cosmos/cosmos-sdk v0.45.2-0.20220901181011-06d4a64bf808 - github.com/cosmos/ibc-go v1.2.2 github.com/cosmos/ibc-go/v3 v3.0.0-alpha1.0.20220210141024-fb2f0416254b github.com/gogo/protobuf v1.3.3 github.com/golang/protobuf v1.5.2 diff --git a/go.sum b/go.sum index 6c55c682da..b91d177a27 100644 --- a/go.sum +++ b/go.sum @@ -243,7 +243,6 @@ github.com/cosmos/iavl v0.15.3/go.mod h1:OLjQiAQ4fGD2KDZooyJG9yz+p2ao2IAYSbke8mV github.com/cosmos/iavl v0.17.1/go.mod h1:7aisPZK8yCpQdy3PMvKeO+bhq1NwDjUwjzxwwROUxFk= github.com/cosmos/iavl v0.17.3 h1:s2N819a2olOmiauVa0WAhoIJq9EhSXE9HDBAoR9k+8Y= github.com/cosmos/iavl v0.17.3/go.mod h1:prJoErZFABYZGDHka1R6Oay4z9PrNeFFiMKHDAMOi4w= -github.com/cosmos/ibc-go v1.2.2 h1:bs6TZ8Es1kycIu2AHlRZ9dzJ+mveqlLN/0sjWtRH88o= github.com/cosmos/ibc-go v1.2.2/go.mod h1:XmYjsRFOs6Q9Cz+CSsX21icNoH27vQKb3squgnCOCbs= github.com/cosmos/keyring v1.1.7-0.20210622111912-ef00f8ac3d76 h1:DdzS1m6o/pCqeZ8VOAit/gyATedRgjvkVI+UCrLpyuU= github.com/cosmos/keyring v1.1.7-0.20210622111912-ef00f8ac3d76/go.mod h1:0mkLWIoZuQ7uBoospo5Q9zIpqq6rYCPJDSUdeCJvPM8= diff --git a/proto/interchain_security/ccv/provider/v1/provider.proto b/proto/interchain_security/ccv/provider/v1/provider.proto index 85b527af60..decc5e95d0 100644 --- a/proto/interchain_security/ccv/provider/v1/provider.proto +++ b/proto/interchain_security/ccv/provider/v1/provider.proto @@ -58,11 +58,14 @@ message ConsumerAdditionProposal { // Params defines the parameters for CCV Provider module message Params { ibc.lightclients.tendermint.v1.ClientState template_client = 1; + // TrustingPeriodFraction is used to compute the consumer and provider IBC client's TrustingPeriod from the chain defined UnbondingPeriod + int64 trusting_period_fraction = 2; // Sent IBC packets will timeout after this duration - google.protobuf.Duration ccv_timeout_period = 2 + google.protobuf.Duration ccv_timeout_period = 3 [(gogoproto.nullable) = false, (gogoproto.stdduration) = true]; - // TrustingPeriodFraction is used to compute the consumer and provider IBC client's TrustingPeriod - int64 trusting_period_fraction = 3; + // The channel initialization (IBC channel opening handshake) will timeout after this duration + google.protobuf.Duration init_timeout_period = 4 + [(gogoproto.nullable) = false, (gogoproto.stdduration) = true]; } message HandshakeMetadata { diff --git a/tests/e2e/channel_init.go b/tests/e2e/channel_init.go index f6f73549cf..7459f803d1 100644 --- a/tests/e2e/channel_init.go +++ b/tests/e2e/channel_init.go @@ -93,3 +93,100 @@ func (suite *CCVTestSuite) TestProviderClientMatches() { clientState, _ := suite.consumerApp.GetIBCKeeper().ClientKeeper.GetClientState(suite.consumerCtx(), providerClientID) suite.Require().Equal(suite.providerClient, clientState, "stored client state does not match genesis provider client") } + +// TestInitTimeout tests the init timeout +func (suite *CCVTestSuite) TestInitTimeout() { + testCases := []struct { + name string + handshake func() + removed bool + }{ + { + "init times out before INIT", func() {}, true, + }, + { + "init times out before TRY", func() { + // send ChanOpenInit + err := suite.path.EndpointA.ChanOpenInit() + suite.Require().NoError(err) + }, true, + }, + { + "init times out before ACK", func() { + // send ChanOpenInit + err := suite.path.EndpointA.ChanOpenInit() + suite.Require().NoError(err) + // send ChanOpenTry + err = suite.path.EndpointB.ChanOpenTry() + suite.Require().NoError(err) + }, true, + }, + { + "init times out before CONFIRM", func() { + // send ChanOpenInit + err := suite.path.EndpointA.ChanOpenInit() + suite.Require().NoError(err) + // send ChanOpenTry + err = suite.path.EndpointB.ChanOpenTry() + suite.Require().NoError(err) + // send ChanOpenAck + err = suite.path.EndpointA.ChanOpenAck() + suite.Require().NoError(err) + }, true, + }, + { + "init completes before timeout", func() { + // send ChanOpenInit + err := suite.path.EndpointA.ChanOpenInit() + suite.Require().NoError(err) + // send ChanOpenTry + err = suite.path.EndpointB.ChanOpenTry() + suite.Require().NoError(err) + // send ChanOpenAck + err = suite.path.EndpointA.ChanOpenAck() + suite.Require().NoError(err) + // send ChanOpenConfirm + err = suite.path.EndpointB.ChanOpenConfirm() + suite.Require().NoError(err) + }, false, + }, + } + + for i, tc := range testCases { + providerKeeper := suite.providerApp.GetProviderKeeper() + initTimeout := providerKeeper.GetParams(suite.providerCtx()).InitTimeoutPeriod + chainID := suite.consumerChain.ChainID + + // get init timeout timestamp + ts, found := providerKeeper.GetInitTimeoutTimestamp(suite.providerCtx(), chainID) + suite.Require().True(found, "cannot find init timeout timestamp; test: %s", tc.name) + expectedTs := suite.providerCtx().BlockTime().Add(initTimeout) + suite.Require().Equal(uint64(expectedTs.UnixNano()), ts, "unexpected init timeout timestamp; test: %s", tc.name) + + // create connection + suite.coordinator.CreateConnections(suite.path) + + // channel opening handshake + tc.handshake() + + // call NextBlock + suite.providerChain.NextBlock() + + // increment time + incrementTimeBy(suite, initTimeout) + + // check whether the chain was removed + _, found = providerKeeper.GetConsumerClientId(suite.providerCtx(), chainID) + suite.Require().Equal(!tc.removed, found, "unexpected outcome; test: %s", tc.name) + + if tc.removed { + // check if the chain was properly removed + suite.checkConsumerChainIsRemoved(chainID, false, false) + } + + if i+1 < len(testCases) { + // reset suite to reset provider client + suite.SetupTest() + } + } +} diff --git a/tests/e2e/common.go b/tests/e2e/common.go index b206137fe6..9e8bd1f803 100644 --- a/tests/e2e/common.go +++ b/tests/e2e/common.go @@ -1,12 +1,11 @@ package e2e import ( - "strings" + "fmt" "time" sdk "github.com/cosmos/cosmos-sdk/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" - "github.com/cosmos/interchain-security/testutil/e2e" consumertypes "github.com/cosmos/interchain-security/x/ccv/consumer/types" providertypes "github.com/cosmos/interchain-security/x/ccv/provider/types" @@ -14,10 +13,10 @@ import ( "github.com/stretchr/testify/require" abci "github.com/tendermint/tendermint/abci/types" - "github.com/cosmos/ibc-go/modules/core/exported" clienttypes "github.com/cosmos/ibc-go/v3/modules/core/02-client/types" channeltypes "github.com/cosmos/ibc-go/v3/modules/core/04-channel/types" commitmenttypes "github.com/cosmos/ibc-go/v3/modules/core/23-commitment/types" + "github.com/cosmos/ibc-go/v3/modules/core/exported" ibctmtypes "github.com/cosmos/ibc-go/v3/modules/light-clients/07-tendermint/types" ibctesting "github.com/cosmos/ibc-go/v3/testing" ) @@ -207,8 +206,8 @@ func relayAllCommittedPackets( } // incrementTimeByUnbondingPeriod increments the overall time by -// - if chainType == Provider, the unbonding period on the provider. -// - otherwise, the unbonding period on the consumer. +// - if chainType == Provider, the unbonding period on the provider. +// - otherwise, the unbonding period on the consumer. // // Note that it is expected for the provider unbonding period // to be one day larger than the consumer unbonding period. @@ -238,19 +237,44 @@ func incrementTimeByUnbondingPeriod(s *CCVTestSuite, chainType ChainType) { } } -func checkStakingUnbondingOps(s *CCVTestSuite, id uint64, found bool, onHold bool) { +func checkStakingUnbondingOps(s *CCVTestSuite, id uint64, found bool, onHold bool, msgAndArgs ...interface{}) { stakingUnbondingOp, wasFound := getStakingUnbondingDelegationEntry(s.providerCtx(), s.providerApp.GetE2eStakingKeeper(), id) - s.Require().True(found == wasFound) - s.Require().True(onHold == (0 < stakingUnbondingOp.UnbondingOnHoldRefCount)) + s.Require().Equal( + found, + wasFound, + fmt.Sprintf("checkStakingUnbondingOps failed - getStakingUnbondingDelegationEntry; %s", msgAndArgs...), + ) + if wasFound { + s.Require().True( + onHold == (0 < stakingUnbondingOp.UnbondingOnHoldRefCount), + fmt.Sprintf("checkStakingUnbondingOps failed - onHold; %s", msgAndArgs...), + ) + } } -func checkCCVUnbondingOp(s *CCVTestSuite, providerCtx sdk.Context, chainID string, valUpdateID uint64, found bool) { +func checkCCVUnbondingOp(s *CCVTestSuite, providerCtx sdk.Context, chainID string, valUpdateID uint64, found bool, msgAndArgs ...interface{}) { entries, wasFound := s.providerApp.GetProviderKeeper().GetUnbondingOpsFromIndex(providerCtx, chainID, valUpdateID) - s.Require().True(found == wasFound) + s.Require().Equal( + found, + wasFound, + fmt.Sprintf("checkCCVUnbondingOp failed - GetUnbondingOpsFromIndex; %s", msgAndArgs...), + ) if found { - s.Require().True(len(entries) > 0, "No unbonding ops found") - s.Require().True(len(entries[0].UnbondingConsumerChains) > 0, "Unbonding op with no consumer chains") - s.Require().True(strings.Compare(entries[0].UnbondingConsumerChains[0], "testchain2") == 0, "Unbonding op with unexpected consumer chain") + s.Require().Greater( + len(entries), + 0, + fmt.Sprintf("checkCCVUnbondingOp failed - no unbonding ops found; %s", msgAndArgs...), + ) + s.Require().Greater( + len(entries[0].UnbondingConsumerChains), + 0, + fmt.Sprintf("checkCCVUnbondingOp failed - unbonding op with no consumer chains; %s", msgAndArgs...), + ) + s.Require().Equal( + "testchain2", + entries[0].UnbondingConsumerChains[0], + fmt.Sprintf("checkCCVUnbondingOp failed - unbonding op with unexpected consumer chain; %s", msgAndArgs...), + ) } } diff --git a/tests/e2e/distribution.go b/tests/e2e/distribution.go index 403268cee5..cffae78e54 100644 --- a/tests/e2e/distribution.go +++ b/tests/e2e/distribution.go @@ -10,7 +10,7 @@ import ( ccv "github.com/cosmos/interchain-security/x/ccv/types" ) -//This test is valid for minimal viable consumer chain +// This test is valid for minimal viable consumer chain func (s *CCVTestSuite) TestRewardsDistribution() { //set up channel and delegate some tokens in order for validator set update to be sent to the consumer chain diff --git a/tests/e2e/stop_consumer.go b/tests/e2e/stop_consumer.go index aceab09f31..a14c6e413d 100644 --- a/tests/e2e/stop_consumer.go +++ b/tests/e2e/stop_consumer.go @@ -93,7 +93,7 @@ func (s *CCVTestSuite) TestStopConsumerChain() { s.Require().NoError(err) // check all states are removed and the unbonding operation released - s.checkConsumerChainIsRemoved(consumerChainID, false) + s.checkConsumerChainIsRemoved(consumerChainID, false, true) } // TODO Simon: implement OnChanCloseConfirm in IBC-GO testing to close the consumer chain's channel end @@ -127,13 +127,15 @@ func (s *CCVTestSuite) TestStopConsumerOnChannelClosed() { // s.Require().False(found) } -func (s *CCVTestSuite) checkConsumerChainIsRemoved(chainID string, lockUbd bool) { +func (s *CCVTestSuite) checkConsumerChainIsRemoved(chainID string, lockUbd bool, checkChannel bool) { channelID := s.path.EndpointB.ChannelID providerKeeper := s.providerApp.GetProviderKeeper() providerStakingKeeper := s.providerApp.GetE2eStakingKeeper() - // check channel's state is closed - s.Require().Equal(channeltypes.CLOSED, s.path.EndpointB.GetChannel().State) + if checkChannel { + // check channel's state is closed + s.Require().Equal(channeltypes.CLOSED, s.path.EndpointB.GetChannel().State) + } // check UnbondingOps were deleted and undelegation entries aren't onHold if !lockUbd { diff --git a/tests/e2e/unbonding.go b/tests/e2e/unbonding.go index 7dbb672d90..d8df431c27 100644 --- a/tests/e2e/unbonding.go +++ b/tests/e2e/unbonding.go @@ -5,6 +5,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" + providerkeeper "github.com/cosmos/interchain-security/x/ccv/provider/keeper" ccv "github.com/cosmos/interchain-security/x/ccv/types" ) @@ -139,68 +140,114 @@ func (s *CCVTestSuite) TestUndelegationNoValsetChange() { // TestUndelegationDuringInit checks that before the CCV channel is established // - no undelegations can complete, even if the provider unbonding period elapses // - all the VSC packets are stored in state as pending +// - if the channel handshake times out, then the undelegation completes func (s *CCVTestSuite) TestUndelegationDuringInit() { - - providerKeeper := s.providerApp.GetProviderKeeper() - - // delegate bondAmt and undelegate 1/2 of it - bondAmt := sdk.NewInt(10000000) - delAddr := s.providerChain.SenderAccount.GetAddress() - initBalance, valsetUpdateID := delegateAndUndelegate(s, delAddr, bondAmt, 2) - // - check that staking unbonding op was created and onHold is true - checkStakingUnbondingOps(s, 1, true, true) - // - check that CCV unbonding op was created - checkCCVUnbondingOp(s, s.providerCtx(), s.consumerChain.ChainID, valsetUpdateID, true) - - // call NextBlock on the provider (which increments the height) - s.providerChain.NextBlock() - - // check that the VSC packet is stored in state as pending - pendingVSCs, _ := providerKeeper.GetPendingVSCs(s.providerCtx(), s.consumerChain.ChainID) - s.Require().True(len(pendingVSCs) == 1, "no pending VSC packet found") - - // delegate again to create another VSC packet - delegate(s, delAddr, bondAmt) - - // call NextBlock on the provider (which increments the height) - s.providerChain.NextBlock() - - // check that the VSC packet is stored in state as pending - pendingVSCs, _ = providerKeeper.GetPendingVSCs(s.providerCtx(), s.consumerChain.ChainID) - s.Require().True(len(pendingVSCs) == 2, "only one pending VSC packet found") - - // increment time so that the unbonding period ends on the provider - incrementTimeByUnbondingPeriod(s, Provider) - // - check that the unbonding op is still there and onHold is true - checkStakingUnbondingOps(s, 1, true, true) - // - check that unbonding has not yet completed, i.e., the initBalance - // is still lower by the bond amount, because it has been taken out of - // the delegator's account - s.Require().True(getBalance(s, s.providerCtx(), delAddr).Equal(initBalance.Sub(bondAmt).Sub(bondAmt))) - - // complete CCV channel setup - s.SetupCCVChannel() - s.SetupTransferChannel() - - // relay VSC packets from provider to consumer - relayAllCommittedPackets(s, s.providerChain, s.path, ccv.ProviderPortID, s.path.EndpointB.ChannelID, 2) - - // increment time so that the unbonding period ends on the consumer - incrementTimeByUnbondingPeriod(s, Consumer) - - // relay VSCMatured packets from consumer to provider - relayAllCommittedPackets(s, s.consumerChain, s.path, ccv.ConsumerPortID, s.path.EndpointA.ChannelID, 2) - - // check that the unbonding operation completed - // - check that ccv unbonding op has been deleted - checkCCVUnbondingOp(s, s.providerCtx(), s.consumerChain.ChainID, valsetUpdateID, false) - // - check that staking unbonding op has been deleted - checkStakingUnbondingOps(s, valsetUpdateID, false, false) - // - check that one quarter the delegated coins have been returned - s.Require().True(getBalance(s, s.providerCtx(), delAddr).Equal(initBalance.Sub(bondAmt).Sub(bondAmt.Quo(sdk.NewInt(2))))) + testCases := []struct { + name string + updateInitTimeoutTimestamp func(*providerkeeper.Keeper, time.Duration) + removed bool + }{ + { + "channel handshake completes after unbonding period", func(pk *providerkeeper.Keeper, pUnbondingPeriod time.Duration) { + // change the init timeout timestamp for this consumer chain + // to make sure the chain is not removed before the unbonding period elapses + ts := s.providerCtx().BlockTime().Add(pUnbondingPeriod + 24*time.Hour) + pk.SetInitTimeoutTimestamp(s.providerCtx(), s.consumerChain.ChainID, uint64(ts.UnixNano())) + }, false, + }, + { + "channel handshake times out before unbonding period", func(pk *providerkeeper.Keeper, pUnbondingPeriod time.Duration) { + // change the init timeout timestamp for this consumer chain + // to make sure the chain is removed before the unbonding period elapses + ts := s.providerCtx().BlockTime().Add(pUnbondingPeriod - 24*time.Hour) + pk.SetInitTimeoutTimestamp(s.providerCtx(), s.consumerChain.ChainID, uint64(ts.UnixNano())) + }, true, + }, + } + + for i, tc := range testCases { + providerKeeper := s.providerApp.GetProviderKeeper() + stakingKeeper := s.providerApp.GetE2eStakingKeeper() + + // delegate bondAmt and undelegate 1/2 of it + bondAmt := sdk.NewInt(10000000) + delAddr := s.providerChain.SenderAccount.GetAddress() + initBalance, valsetUpdateID := delegateAndUndelegate(s, delAddr, bondAmt, 2) + // - check that staking unbonding op was created and onHold is true + checkStakingUnbondingOps(s, 1, true, true, "test: "+tc.name) + // - check that CCV unbonding op was created + checkCCVUnbondingOp(s, s.providerCtx(), s.consumerChain.ChainID, valsetUpdateID, true, "test: "+tc.name) + + // get provider unbonding period + providerUnbondingPeriod := stakingKeeper.UnbondingTime(s.providerCtx()) + // update init timeout timestamp + tc.updateInitTimeoutTimestamp(&providerKeeper, providerUnbondingPeriod) + + // call NextBlock on the provider (which increments the height) + s.providerChain.NextBlock() + + // check that the VSC packet is stored in state as pending + pendingVSCs, _ := providerKeeper.GetPendingVSCs(s.providerCtx(), s.consumerChain.ChainID) + s.Require().True(len(pendingVSCs) == 1, "no pending VSC packet found; test: %s", tc.name) + + // delegate again to create another VSC packet + delegate(s, delAddr, bondAmt) + + // call NextBlock on the provider (which increments the height) + s.providerChain.NextBlock() + + // check that the VSC packet is stored in state as pending + pendingVSCs, _ = providerKeeper.GetPendingVSCs(s.providerCtx(), s.consumerChain.ChainID) + s.Require().True(len(pendingVSCs) == 2, "only one pending VSC packet found; test: %s", tc.name) + + // increment time so that the unbonding period ends on the provider + incrementTimeByUnbondingPeriod(s, Provider) + + // check whether the unbonding op is still there and onHold is true + checkStakingUnbondingOps(s, 1, !tc.removed, true, "test: "+tc.name) + + if !tc.removed { + // check that unbonding has not yet completed, i.e., the initBalance + // is still lower by the bond amount, because it has been taken out of + // the delegator's account + s.Require().Equal( + initBalance.Sub(bondAmt).Sub(bondAmt), + getBalance(s, s.providerCtx(), delAddr), + "unexpected initial balance before unbonding; test: %s", tc.name, + ) + + // complete CCV channel setup + s.SetupCCVChannel() + + // relay VSC packets from provider to consumer + relayAllCommittedPackets(s, s.providerChain, s.path, ccv.ProviderPortID, s.path.EndpointB.ChannelID, 2) + + // increment time so that the unbonding period ends on the consumer + incrementTimeByUnbondingPeriod(s, Consumer) + + // relay VSCMatured packets from consumer to provider + relayAllCommittedPackets(s, s.consumerChain, s.path, ccv.ConsumerPortID, s.path.EndpointA.ChannelID, 2) + + // check that the unbonding operation completed + // - check that ccv unbonding op has been deleted + checkCCVUnbondingOp(s, s.providerCtx(), s.consumerChain.ChainID, valsetUpdateID, false, "test: "+tc.name) + // - check that staking unbonding op has been deleted + checkStakingUnbondingOps(s, valsetUpdateID, false, false, "test: "+tc.name) + // - check that one quarter the delegated coins have been returned + s.Require().Equal( + initBalance.Sub(bondAmt).Sub(bondAmt.Quo(sdk.NewInt(2))), + getBalance(s, s.providerCtx(), delAddr), + "unexpected initial balance after unbonding; test: %s", tc.name, + ) + } + + if i+1 < len(testCases) { + // reset suite to reset provider client + s.SetupTest() + } + } } -// TODO FIX, the consumer is added during SetupTest() // Bond some tokens on provider // Unbond them to create unbonding op // Check unbonding ops on both sides diff --git a/x/ccv/provider/ibc_module.go b/x/ccv/provider/ibc_module.go index 8792236d14..911cc66272 100644 --- a/x/ccv/provider/ibc_module.go +++ b/x/ccv/provider/ibc_module.go @@ -34,7 +34,6 @@ func (am AppModule) OnChanOpenInit( // OnChanOpenTry implements the IBCModule interface // -// // See: https://github.com/cosmos/ibc/blob/main/spec/app/ics-028-cross-chain-validation/methods.md#ccv-pcf-cotry1 // Spec tag: [CCV-PCF-COTRY.1] func (am AppModule) OnChanOpenTry( diff --git a/x/ccv/provider/keeper/keeper.go b/x/ccv/provider/keeper/keeper.go index 6663477446..6115f6c2b9 100644 --- a/x/ccv/provider/keeper/keeper.go +++ b/x/ccv/provider/keeper/keeper.go @@ -258,9 +258,13 @@ func (k Keeper) VerifyConsumerChain(ctx sdk.Context, channelID string, connectio return nil } -// SetConsumerChain ensures that the consumer chain has not already been set by a different channel, and then sets the consumer chain mappings in keeper, -// and set the channel status to validating. -// If there is already a ccv channel between the provider and consumer chain then close the channel, so that another channel can be made. +// SetConsumerChain ensures that the consumer chain has not already been +// set by a different channel, and then sets the consumer chain mappings +// in keeper, and set the channel status to validating. +// If there is already a CCV channel between the provider and consumer +// chain then close the channel, so that another channel can be made. +// +// SetConsumerChain is called by OnChanOpenConfirm. func (k Keeper) SetConsumerChain(ctx sdk.Context, channelID string) error { channel, ok := k.channelKeeper.GetChannel(ctx, ccv.ProviderPortID, channelID) if !ok { @@ -282,10 +286,12 @@ func (k Keeper) SetConsumerChain(ctx sdk.Context, channelID string) error { // the CCV channel is established: // - set channel mappings - k.SetChainToChannel(ctx, tmClient.ChainId, channelID) - k.SetChannelToChain(ctx, channelID, tmClient.ChainId) + k.SetChainToChannel(ctx, chainID, channelID) + k.SetChannelToChain(ctx, channelID, chainID) // - set current block height for the consumer chain initialization - k.SetInitChainHeight(ctx, tmClient.ChainId, uint64(ctx.BlockHeight())) + k.SetInitChainHeight(ctx, chainID, uint64(ctx.BlockHeight())) + // - remove init timeout timestamp + k.DeleteInitTimeoutTimestamp(ctx, chainID) return nil } @@ -777,3 +783,45 @@ func (k Keeper) DeleteConsumerClientId(ctx sdk.Context, chainID string) { store := ctx.KVStore(k.storeKey) store.Delete(types.ChainToClientKey(chainID)) } + +// ------ + +// SetInitTimeoutTimestamp sets the init timeout timestamp for the given chain ID +func (k Keeper) SetInitTimeoutTimestamp(ctx sdk.Context, chainID string, ts uint64) { + store := ctx.KVStore(k.storeKey) + tsBytes := make([]byte, 8) + binary.BigEndian.PutUint64(tsBytes, ts) + store.Set(types.InitTimeoutTimestampKey(chainID), tsBytes) +} + +// GetInitTimeoutTimestamp returns the init timeout timestamp for the given chain ID. +// This method is used only in testing. +func (k Keeper) GetInitTimeoutTimestamp(ctx sdk.Context, chainID string) (uint64, bool) { + store := ctx.KVStore(k.storeKey) + bz := store.Get(types.InitTimeoutTimestampKey(chainID)) + if bz == nil { + return 0, false + } + return binary.BigEndian.Uint64(bz), true +} + +// DeleteInitTimeoutTimestamp removes from the store the init timeout timestamp for the given chainID. +func (k Keeper) DeleteInitTimeoutTimestamp(ctx sdk.Context, chainID string) { + store := ctx.KVStore(k.storeKey) + store.Delete(types.InitTimeoutTimestampKey(chainID)) +} + +// IterateInitTimeoutTimestamp iterates through the init timeout timestamps in the store +func (k Keeper) IterateInitTimeoutTimestamp(ctx sdk.Context, cb func(chainID string, ts uint64) bool) { + store := ctx.KVStore(k.storeKey) + iterator := sdk.KVStorePrefixIterator(store, []byte{types.InitTimeoutTimestampBytePrefix}) + + defer iterator.Close() + for ; iterator.Valid(); iterator.Next() { + chainID := string(iterator.Key()[1:]) + ts := binary.BigEndian.Uint64(iterator.Value()) + if !cb(chainID, ts) { + return + } + } +} diff --git a/x/ccv/provider/keeper/keeper_test.go b/x/ccv/provider/keeper/keeper_test.go index a0630016ea..dd5e94a615 100644 --- a/x/ccv/provider/keeper/keeper_test.go +++ b/x/ccv/provider/keeper/keeper_test.go @@ -296,3 +296,43 @@ func TestMaturedUnbondingOps(t *testing.T) { require.Equal(t, unbondingOpIds[i], ids[i]) } } + +func TestInitTimeoutTimestamp(t *testing.T) { + providerKeeper, ctx, ctrl, _ := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t)) + defer ctrl.Finish() + + tc := []struct { + chainID string + expected uint64 + }{ + {expected: 5, chainID: "chain"}, + {expected: 10, chainID: "chain1"}, + {expected: 12, chainID: "chain2"}, + } + + _, found := providerKeeper.GetInitTimeoutTimestamp(ctx, tc[0].chainID) + require.False(t, found) + + providerKeeper.SetInitTimeoutTimestamp(ctx, tc[0].chainID, tc[0].expected) + providerKeeper.SetInitTimeoutTimestamp(ctx, tc[1].chainID, tc[1].expected) + providerKeeper.SetInitTimeoutTimestamp(ctx, tc[2].chainID, tc[2].expected) + + i := 0 + providerKeeper.IterateInitTimeoutTimestamp(ctx, func(chainID string, ts uint64) bool { + require.Equal(t, chainID, tc[i].chainID) + require.Equal(t, ts, tc[i].expected) + i++ + return true + }) + require.Equal(t, len(tc), i) + + for _, tc := range tc { + ts, found := providerKeeper.GetInitTimeoutTimestamp(ctx, tc.chainID) + require.True(t, found) + require.Equal(t, tc.expected, ts) + } + + providerKeeper.DeleteInitTimeoutTimestamp(ctx, tc[1].chainID) + _, found = providerKeeper.GetInitTimeoutTimestamp(ctx, tc[1].chainID) + require.False(t, found) +} diff --git a/x/ccv/provider/keeper/params.go b/x/ccv/provider/keeper/params.go index f3d04cb7e4..323f860258 100644 --- a/x/ccv/provider/keeper/params.go +++ b/x/ccv/provider/keeper/params.go @@ -18,6 +18,14 @@ func (k Keeper) GetTemplateClient(ctx sdk.Context) *ibctmtypes.ClientState { return &cs } +// GetTrustingPeriodFraction returns a TrustingPeriodFraction +// used to compute the provider IBC client's TrustingPeriod as UnbondingPeriod / TrustingPeriodFraction +func (k Keeper) GetTrustingPeriodFraction(ctx sdk.Context) int64 { + var i int64 + k.paramSpace.Get(ctx, types.KeyTrustingPeriodFraction, &i) + return i +} + // GetCCVTimeoutPeriod returns the timeout period for sent ibc packets func (k Keeper) GetCCVTimeoutPeriod(ctx sdk.Context) time.Duration { var p time.Duration @@ -25,20 +33,20 @@ func (k Keeper) GetCCVTimeoutPeriod(ctx sdk.Context) time.Duration { return p } -// GetTrustingPeriodFraction returns a TrustingPeriodFraction -// used to compute the provider IBC client's TrustingPeriod as UnbondingPeriod / TrustingPeriodFraction -func (k Keeper) GetTrustingPeriodFraction(ctx sdk.Context) int64 { - var i int64 - k.paramSpace.Get(ctx, types.KeyTrustingPeriodFraction, &i) - return i +// GetInitTimeoutPeriod returns the init timeout period +func (k Keeper) GetInitTimeoutPeriod(ctx sdk.Context) time.Duration { + var p time.Duration + k.paramSpace.Get(ctx, types.KeyInitTimeoutPeriod, &p) + return p } // GetParams returns the paramset for the provider module func (k Keeper) GetParams(ctx sdk.Context) types.Params { return types.NewParams( k.GetTemplateClient(ctx), - k.GetCCVTimeoutPeriod(ctx), k.GetTrustingPeriodFraction(ctx), + k.GetCCVTimeoutPeriod(ctx), + k.GetInitTimeoutPeriod(ctx), ) } diff --git a/x/ccv/provider/keeper/params_test.go b/x/ccv/provider/keeper/params_test.go index a16d1c1366..62623d4b1f 100644 --- a/x/ccv/provider/keeper/params_test.go +++ b/x/ccv/provider/keeper/params_test.go @@ -28,7 +28,7 @@ func TestParams(t *testing.T) { newParams := types.NewParams(ibctmtypes.NewClientState("", ibctmtypes.DefaultTrustLevel, 0, 0, time.Second*40, clienttypes.Height{}, commitmenttypes.GetSDKSpecs(), []string{"ibc", "upgradedIBCState"}, true, false), - ccvtypes.DefaultCCVTimeoutPeriod, types.DefaultTrustingPeriodFraction) + types.DefaultTrustingPeriodFraction, ccvtypes.DefaultCCVTimeoutPeriod, types.DefaultInitTimeoutPeriod) providerKeeper.SetParams(ctx, newParams) params = providerKeeper.GetParams(ctx) require.Equal(t, newParams, params) diff --git a/x/ccv/provider/keeper/proposal.go b/x/ccv/provider/keeper/proposal.go index 3c68368dec..bd4961817e 100644 --- a/x/ccv/provider/keeper/proposal.go +++ b/x/ccv/provider/keeper/proposal.go @@ -86,6 +86,10 @@ func (k Keeper) CreateConsumerClient(ctx sdk.Context, chainID string, return err } + // add the init timeout timestamp for this consumer chain + ts := ctx.BlockTime().Add(k.GetParams(ctx).InitTimeoutPeriod) + k.SetInitTimeoutTimestamp(ctx, chainID, uint64(ts.UnixNano())) + // store LockUnbondingOnTimeout flag if lockUbdOnTimeout { k.SetLockUnbondingOnTimeout(ctx, chainID) diff --git a/x/ccv/provider/keeper/proposal_test.go b/x/ccv/provider/keeper/proposal_test.go index 2abd362d35..8f164d2cfb 100644 --- a/x/ccv/provider/keeper/proposal_test.go +++ b/x/ccv/provider/keeper/proposal_test.go @@ -625,8 +625,9 @@ func TestMakeConsumerGenesis(t *testing.T) { }, // Note these are unused provider parameters for this test, and not actually asserted against // They must be populated with reasonable values to satisfy SetParams though. - CcvTimeoutPeriod: ccvtypes.DefaultCCVTimeoutPeriod, TrustingPeriodFraction: providertypes.DefaultTrustingPeriodFraction, + CcvTimeoutPeriod: ccvtypes.DefaultCCVTimeoutPeriod, + InitTimeoutPeriod: types.DefaultInitTimeoutPeriod, } providerKeeper.SetParams(ctx, moduleParams) defer ctrl.Finish() diff --git a/x/ccv/provider/keeper/relay.go b/x/ccv/provider/keeper/relay.go index c40603bbc9..7c6166e2a3 100644 --- a/x/ccv/provider/keeper/relay.go +++ b/x/ccv/provider/keeper/relay.go @@ -71,7 +71,7 @@ func (k Keeper) OnRecvVSCMaturedPacket( } // CompleteMaturedUnbondingOps attempts to complete all matured unbonding operations -func (k Keeper) CompleteMaturedUnbondingOps(ctx sdk.Context) { +func (k Keeper) completeMaturedUnbondingOps(ctx sdk.Context) { ids, err := k.ConsumeMaturedUnbondingOps(ctx) if err != nil { panic(fmt.Sprintf("could not get the list of matured unbonding ops: %s", err.Error())) @@ -116,8 +116,18 @@ func (k Keeper) OnTimeoutPacket(ctx sdk.Context, packet channeltypes.Packet) err return k.StopConsumerChain(ctx, chainID, k.GetLockUnbondingOnTimeout(ctx, chainID), false) } +// EndBlockVSU contains the EndBlock logic needed for +// the Validator Set Update sub-protocol +func (k Keeper) EndBlockVSU(ctx sdk.Context) { + // notify the staking module to complete all matured unbonding ops + k.completeMaturedUnbondingOps(ctx) + + // send latest validator updates to every registered consumer chain + k.sendValidatorUpdates(ctx) +} + // SendValidatorUpdates sends latest validator updates to every registered consumer chain -func (k Keeper) SendValidatorUpdates(ctx sdk.Context) { +func (k Keeper) sendValidatorUpdates(ctx sdk.Context) { // get current ValidatorSetUpdateId valUpdateID := k.GetValidatorSetUpdateId(ctx) // get the validator updates from the staking module @@ -159,7 +169,6 @@ func (k Keeper) SendValidatorUpdates(ctx sdk.Context) { } return false // do not stop the iteration }) - k.SetValsetUpdateBlockHeight(ctx, valUpdateID, uint64(ctx.BlockHeight()+1)) k.IncrementValidatorSetUpdateId(ctx) } @@ -183,6 +192,15 @@ func (k Keeper) SendPendingVSCPackets(ctx sdk.Context, chainID, channelID string } } +// EndBlockCIS contains the EndBlock logic needed for +// the Consumer Initiated Slashing sub-protocol +func (k Keeper) EndBlockCIS(ctx sdk.Context) { + // get current ValidatorSetUpdateId + valUpdateID := k.GetValidatorSetUpdateId(ctx) + // set the ValsetUpdateBlockHeight + k.SetValsetUpdateBlockHeight(ctx, valUpdateID, uint64(ctx.BlockHeight()+1)) +} + // OnRecvSlashPacket slashes and jails the given validator in the packet data func (k Keeper) OnRecvSlashPacket(ctx sdk.Context, packet channeltypes.Packet, data ccv.SlashPacketData) exported.Acknowledgement { // check that the channel is established @@ -278,3 +296,28 @@ func (k Keeper) HandleSlashPacket(ctx sdk.Context, chainID string, data ccv.Slas return true, nil } + +// EndBlockCIS contains the EndBlock logic needed for +// the Consumer Chain Removal sub-protocol +func (k Keeper) EndBlockCCR(ctx sdk.Context) { + currentTime := uint64(ctx.BlockTime().UnixNano()) + + // iterate over initTimeoutTimestamps + var removedChainIds []string + k.IterateInitTimeoutTimestamp(ctx, func(chainID string, ts uint64) bool { + if currentTime > ts { + // initTimeout expired: + // stop the consumer chain and unlock the unbonding + err := k.StopConsumerChain(ctx, chainID, false, true) + if err != nil { + panic(fmt.Errorf("consumer chain failed to stop: %w", err)) + } + removedChainIds = append(removedChainIds, chainID) + } + return true + }) + // remove the init timeout timestamps for the stopped consumers + for _, chainID := range removedChainIds { + k.DeleteInitTimeoutTimestamp(ctx, chainID) + } +} diff --git a/x/ccv/provider/module.go b/x/ccv/provider/module.go index 8b6721f3d4..c3914f4f5d 100644 --- a/x/ccv/provider/module.go +++ b/x/ccv/provider/module.go @@ -163,11 +163,14 @@ func (am AppModule) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) { // EndBlock implements the AppModule interface func (am AppModule) EndBlock(ctx sdk.Context, req abci.RequestEndBlock) []abci.ValidatorUpdate { - // notify the staking module to complete all matured unbonding ops - am.keeper.CompleteMaturedUnbondingOps(ctx) + // EndBlock logic needed for the Consumer Initiated Slashing sub-protocol. + // Important: EndBlockCIS must be called before EndBlockVSU + am.keeper.EndBlockCIS(ctx) + // EndBlock logic needed for the Consumer Chain Removal sub-protocol + am.keeper.EndBlockCCR(ctx) + // EndBlock logic needed for the Validator Set Update sub-protocol + am.keeper.EndBlockVSU(ctx) - // send validator updates to consumer chains - am.keeper.SendValidatorUpdates(ctx) return []abci.ValidatorUpdate{} } diff --git a/x/ccv/provider/types/genesis_test.go b/x/ccv/provider/types/genesis_test.go index ddc1218d7a..5c4fe8bf25 100644 --- a/x/ccv/provider/types/genesis_test.go +++ b/x/ccv/provider/types/genesis_test.go @@ -8,7 +8,6 @@ import ( commitmenttypes "github.com/cosmos/ibc-go/v3/modules/core/23-commitment/types" ibctmtypes "github.com/cosmos/ibc-go/v3/modules/light-clients/07-tendermint/types" "github.com/cosmos/interchain-security/x/ccv/provider/types" - providertypes "github.com/cosmos/interchain-security/x/ccv/provider/types" ccv "github.com/cosmos/interchain-security/x/ccv/types" "github.com/stretchr/testify/require" @@ -80,7 +79,7 @@ func TestValidateGenesisState(t *testing.T) { nil, types.NewParams(ibctmtypes.NewClientState("", ibctmtypes.DefaultTrustLevel, 0, 0, time.Second*40, clienttypes.Height{}, commitmenttypes.GetSDKSpecs(), []string{"ibc", "upgradedIBCState"}, true, false), - 2*7*24*time.Hour, 3), + 3, time.Hour, time.Hour), ), true, }, @@ -96,7 +95,25 @@ func TestValidateGenesisState(t *testing.T) { nil, types.NewParams(ibctmtypes.NewClientState("", ibctmtypes.DefaultTrustLevel, 0, 0, 0, clienttypes.Height{}, nil, []string{"ibc", "upgradedIBCState"}, true, false), - ccv.DefaultCCVTimeoutPeriod, providertypes.DefaultTrustingPeriodFraction), + types.DefaultTrustingPeriodFraction, ccv.DefaultCCVTimeoutPeriod, types.DefaultInitTimeoutPeriod), + ), + false, + }, + { + "invalid params, zero trusting period fraction", + types.NewGenesisState( + 0, + nil, + []types.ConsumerState{{ChainId: "chainid-1", ChannelId: "channelid"}}, + nil, + nil, + nil, + nil, + types.NewParams(ibctmtypes.NewClientState("", ibctmtypes.DefaultTrustLevel, 0, 0, + time.Second*40, clienttypes.Height{}, commitmenttypes.GetSDKSpecs(), []string{"ibc", "upgradedIBCState"}, true, false), + 0, // 0 trusting period fraction here + ccv.DefaultCCVTimeoutPeriod, + types.DefaultInitTimeoutPeriod), ), false, }, @@ -112,13 +129,14 @@ func TestValidateGenesisState(t *testing.T) { nil, types.NewParams(ibctmtypes.NewClientState("", ibctmtypes.DefaultTrustLevel, 0, 0, time.Second*40, clienttypes.Height{}, commitmenttypes.GetSDKSpecs(), []string{"ibc", "upgradedIBCState"}, true, false), + types.DefaultTrustingPeriodFraction, 0, // 0 ccv timeout here - providertypes.DefaultTrustingPeriodFraction), + types.DefaultInitTimeoutPeriod), ), false, }, { - "invalid params, zero trusting period fraction", + "invalid params, zero init timeout", types.NewGenesisState( 0, nil, @@ -129,8 +147,9 @@ func TestValidateGenesisState(t *testing.T) { nil, types.NewParams(ibctmtypes.NewClientState("", ibctmtypes.DefaultTrustLevel, 0, 0, time.Second*40, clienttypes.Height{}, commitmenttypes.GetSDKSpecs(), []string{"ibc", "upgradedIBCState"}, true, false), - 2*7*24*time.Hour, - 0), // 0 trusting period fraction here + types.DefaultTrustingPeriodFraction, + ccv.DefaultCCVTimeoutPeriod, + 0), // 0 init timeout here ), false, }, diff --git a/x/ccv/provider/types/keys.go b/x/ccv/provider/types/keys.go index 338921f33c..fb86846a39 100644 --- a/x/ccv/provider/types/keys.go +++ b/x/ccv/provider/types/keys.go @@ -49,9 +49,13 @@ const ( // from the CCV channel ID to the consumer chain ID. ChannelToChainBytePrefix - // ChainToClientBytePrefix is the byte prefix for storing the consumer chainID for a given consumer clientid. + // ChainToClientBytePrefix is the byte prefix for storing the client ID for a given consumer chainID. ChainToClientBytePrefix + // InitTimeoutTimestampBytePrefix is the byte prefix for storing + // the init timeout timestamp for a given consumer chainID. + InitTimeoutTimestampBytePrefix + // PendingCAPBytePrefix is the byte prefix for storing pending consumer addition proposals before the spawn time occurs. // The key includes the BigEndian timestamp to allow for efficient chronological iteration PendingCAPBytePrefix @@ -123,6 +127,11 @@ func ChainToClientKey(chainID string) []byte { return append([]byte{ChainToClientBytePrefix}, []byte(chainID)...) } +// InitTimeoutTimestampKey returns the key under which the init timeout timestamp for the given chainID is stored. +func InitTimeoutTimestampKey(chainID string) []byte { + return append([]byte{InitTimeoutTimestampBytePrefix}, []byte(chainID)...) +} + // PendingCAPKey returns the key under which a pending consumer addition proposal is stored func PendingCAPKey(timestamp time.Time, chainID string) []byte { timeBz := sdk.FormatTimeBytes(timestamp) diff --git a/x/ccv/provider/types/keys_test.go b/x/ccv/provider/types/keys_test.go index 9faca25676..d1b6525ca3 100644 --- a/x/ccv/provider/types/keys_test.go +++ b/x/ccv/provider/types/keys_test.go @@ -34,7 +34,7 @@ func TestNoDuplicates(t *testing.T) { // any of which should be a single, unique byte. func getSingleByteKeys() [][]byte { - keys := make([][]byte, 16) + keys := make([][]byte, 32) i := 0 keys[i], i = PortKey(), i+1 @@ -43,6 +43,7 @@ func getSingleByteKeys() [][]byte { keys[i], i = []byte{ChainToChannelBytePrefix}, i+1 keys[i], i = []byte{ChannelToChainBytePrefix}, i+1 keys[i], i = []byte{ChainToClientBytePrefix}, i+1 + keys[i], i = []byte{InitTimeoutTimestampBytePrefix}, i+1 keys[i], i = []byte{PendingCAPBytePrefix}, i+1 keys[i], i = []byte{PendingCRPBytePrefix}, i+1 keys[i], i = []byte{UnbondingOpBytePrefix}, i+1 @@ -52,9 +53,9 @@ func getSingleByteKeys() [][]byte { keys[i], i = []byte{SlashAcksBytePrefix}, i+1 keys[i], i = []byte{InitChainHeightBytePrefix}, i+1 keys[i], i = []byte{PendingVSCsBytePrefix}, i+1 - keys[i] = []byte{LockUnbondingOnTimeoutBytePrefix} + keys[i], i = []byte{LockUnbondingOnTimeoutBytePrefix}, i+1 - return keys + return keys[:i] } // Tests the construction and parsing of keys for storing pending consumer addition proposals @@ -138,6 +139,7 @@ func TestKeysWithPrefixAndId(t *testing.T) { ChainToChannelKey, ChannelToChainKey, ChainToClientKey, + InitTimeoutTimestampKey, ConsumerGenesisKey, SlashAcksKey, InitChainHeightKey, @@ -149,6 +151,7 @@ func TestKeysWithPrefixAndId(t *testing.T) { ChainToChannelBytePrefix, ChannelToChainBytePrefix, ChainToClientBytePrefix, + InitTimeoutTimestampBytePrefix, ConsumerGenesisBytePrefix, SlashAcksBytePrefix, InitChainHeightBytePrefix, diff --git a/x/ccv/provider/types/params.go b/x/ccv/provider/types/params.go index 5f09ead6bf..9590b46dda 100644 --- a/x/ccv/provider/types/params.go +++ b/x/ccv/provider/types/params.go @@ -20,12 +20,16 @@ const ( // DefaultTrustingPeriodFraction is the default fraction used to compute TrustingPeriod // as UnbondingPeriod / TrustingPeriodFraction DefaultTrustingPeriodFraction = 2 + + // DafaultInitTimeoutPeriod defines the init timeout period + DefaultInitTimeoutPeriod = 7 * 24 * time.Hour ) // Reflection based keys for params subspace var ( KeyTemplateClient = []byte("TemplateClient") KeyTrustingPeriodFraction = []byte("TrustingPeriodFraction") + KeyInitTimeoutPeriod = []byte("InitTimeoutPeriod") ) // ParamKeyTable returns a key table with the necessary registered provider params @@ -34,12 +38,17 @@ func ParamKeyTable() paramtypes.KeyTable { } // NewParams creates new provider parameters with provided arguments -func NewParams(templateClient *ibctmtypes.ClientState, ccvTimeoutPeriod time.Duration, - trustingPeriodFraction int64) Params { +func NewParams( + cs *ibctmtypes.ClientState, + trustingPeriodFraction int64, + ccvTimeoutPeriod time.Duration, + initTimeoutPeriod time.Duration, +) Params { return Params{ - TemplateClient: templateClient, - CcvTimeoutPeriod: ccvTimeoutPeriod, + TemplateClient: cs, TrustingPeriodFraction: trustingPeriodFraction, + CcvTimeoutPeriod: ccvTimeoutPeriod, + InitTimeoutPeriod: initTimeoutPeriod, } } @@ -58,9 +67,11 @@ func DefaultParams() Params { commitmenttypes.GetSDKSpecs(), []string{"upgrade", "upgradedIBCState"}, true, - true), - ccvtypes.DefaultCCVTimeoutPeriod, + true, + ), DefaultTrustingPeriodFraction, + ccvtypes.DefaultCCVTimeoutPeriod, + DefaultInitTimeoutPeriod, ) } @@ -72,11 +83,14 @@ func (p Params) Validate() error { if err := validateTemplateClient(*p.TemplateClient); err != nil { return err } + if err := ccvtypes.ValidatePositiveInt64(p.TrustingPeriodFraction); err != nil { + return fmt.Errorf("trusting period fraction is invalid: %s", err) + } if err := ccvtypes.ValidateDuration(p.CcvTimeoutPeriod); err != nil { - return err + return fmt.Errorf("ccv timeout period is invalid: %s", err) } - if err := ccvtypes.ValidatePositiveInt64(p.TrustingPeriodFraction); err != nil { - return err + if err := ccvtypes.ValidateDuration(p.InitTimeoutPeriod); err != nil { + return fmt.Errorf("init timeout period is invalid: %s", err) } return nil } @@ -85,8 +99,9 @@ func (p Params) Validate() error { func (p *Params) ParamSetPairs() paramtypes.ParamSetPairs { return paramtypes.ParamSetPairs{ paramtypes.NewParamSetPair(KeyTemplateClient, p.TemplateClient, validateTemplateClient), - paramtypes.NewParamSetPair(ccvtypes.KeyCCVTimeoutPeriod, p.CcvTimeoutPeriod, ccvtypes.ValidateDuration), paramtypes.NewParamSetPair(KeyTrustingPeriodFraction, p.TrustingPeriodFraction, ccvtypes.ValidatePositiveInt64), + paramtypes.NewParamSetPair(ccvtypes.KeyCCVTimeoutPeriod, p.CcvTimeoutPeriod, ccvtypes.ValidateDuration), + paramtypes.NewParamSetPair(KeyInitTimeoutPeriod, p.InitTimeoutPeriod, ccvtypes.ValidateDuration), } } diff --git a/x/ccv/provider/types/params_test.go b/x/ccv/provider/types/params_test.go index d1366e2c33..81ee001c0c 100644 --- a/x/ccv/provider/types/params_test.go +++ b/x/ccv/provider/types/params_test.go @@ -22,19 +22,22 @@ func TestValidateParams(t *testing.T) { {"default params", types.DefaultParams(), true}, {"custom valid params", types.NewParams(ibctmtypes.NewClientState("", ibctmtypes.DefaultTrustLevel, 0, 0, time.Second*40, clienttypes.Height{}, commitmenttypes.GetSDKSpecs(), []string{"ibc", "upgradedIBCState"}, true, false), - 2*7*24*time.Hour, 2), true}, + 3, time.Hour, time.Hour), true}, {"custom invalid params", types.NewParams(ibctmtypes.NewClientState("", ibctmtypes.DefaultTrustLevel, 0, 0, 0, clienttypes.Height{}, nil, []string{"ibc", "upgradedIBCState"}, true, false), - 2*7*24*time.Hour, 2), false}, + 3, time.Hour, time.Hour), false}, {"blank client", types.NewParams(&ibctmtypes.ClientState{}, - 2*7*24*time.Hour, 2), false}, - {"nil client", types.NewParams(nil, 2*7*24*time.Hour, 2), false}, + 3, time.Hour, time.Hour), false}, + {"nil client", types.NewParams(nil, 3, time.Hour, time.Hour), false}, + {"0 trusting period fraction (denominator)", types.NewParams(ibctmtypes.NewClientState("", ibctmtypes.DefaultTrustLevel, 0, 0, + time.Second*40, clienttypes.Height{}, commitmenttypes.GetSDKSpecs(), []string{"ibc", "upgradedIBCState"}, true, false), + 0, time.Hour, time.Hour), false}, {"0 ccv timeout period", types.NewParams(ibctmtypes.NewClientState("", ibctmtypes.DefaultTrustLevel, 0, 0, time.Second*40, clienttypes.Height{}, commitmenttypes.GetSDKSpecs(), []string{"ibc", "upgradedIBCState"}, true, false), - 0, 2), false}, - {"0 trusting period fraction (denominator)", types.NewParams(ibctmtypes.NewClientState("", ibctmtypes.DefaultTrustLevel, 0, 0, + 3, 0, time.Hour), false}, + {"0 init timeout period", types.NewParams(ibctmtypes.NewClientState("", ibctmtypes.DefaultTrustLevel, 0, 0, time.Second*40, clienttypes.Height{}, commitmenttypes.GetSDKSpecs(), []string{"ibc", "upgradedIBCState"}, true, false), - 10000, 0), false}, + 3, time.Hour, 0), false}, } for _, tc := range testCases { diff --git a/x/ccv/provider/types/provider.pb.go b/x/ccv/provider/types/provider.pb.go index fcd90469eb..f5f7575be5 100644 --- a/x/ccv/provider/types/provider.pb.go +++ b/x/ccv/provider/types/provider.pb.go @@ -167,10 +167,12 @@ func (m *ConsumerRemovalProposal) GetStopTime() time.Time { // Params defines the parameters for CCV Provider module type Params struct { TemplateClient *types1.ClientState `protobuf:"bytes,1,opt,name=template_client,json=templateClient,proto3" json:"template_client,omitempty"` + // TrustingPeriodFraction is used to compute the consumer and provider IBC client's TrustingPeriod from the chain defined UnbondingPeriod + TrustingPeriodFraction int64 `protobuf:"varint,2,opt,name=trusting_period_fraction,json=trustingPeriodFraction,proto3" json:"trusting_period_fraction,omitempty"` // Sent IBC packets will timeout after this duration - CcvTimeoutPeriod time.Duration `protobuf:"bytes,2,opt,name=ccv_timeout_period,json=ccvTimeoutPeriod,proto3,stdduration" json:"ccv_timeout_period"` - // TrustingPeriodFraction is used to compute the consumer and provider IBC client's TrustingPeriod - TrustingPeriodFraction int64 `protobuf:"varint,3,opt,name=trusting_period_fraction,json=trustingPeriodFraction,proto3" json:"trusting_period_fraction,omitempty"` + CcvTimeoutPeriod time.Duration `protobuf:"bytes,3,opt,name=ccv_timeout_period,json=ccvTimeoutPeriod,proto3,stdduration" json:"ccv_timeout_period"` + // The channel initialization (IBC channel opening handshake) will timeout after this duration + InitTimeoutPeriod time.Duration `protobuf:"bytes,4,opt,name=init_timeout_period,json=initTimeoutPeriod,proto3,stdduration" json:"init_timeout_period"` } func (m *Params) Reset() { *m = Params{} } @@ -213,6 +215,13 @@ func (m *Params) GetTemplateClient() *types1.ClientState { return nil } +func (m *Params) GetTrustingPeriodFraction() int64 { + if m != nil { + return m.TrustingPeriodFraction + } + return 0 +} + func (m *Params) GetCcvTimeoutPeriod() time.Duration { if m != nil { return m.CcvTimeoutPeriod @@ -220,9 +229,9 @@ func (m *Params) GetCcvTimeoutPeriod() time.Duration { return 0 } -func (m *Params) GetTrustingPeriodFraction() int64 { +func (m *Params) GetInitTimeoutPeriod() time.Duration { if m != nil { - return m.TrustingPeriodFraction + return m.InitTimeoutPeriod } return 0 } @@ -432,55 +441,56 @@ func init() { } var fileDescriptor_f22ec409a72b7b72 = []byte{ - // 765 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x54, 0x4f, 0x6f, 0xf3, 0x34, - 0x18, 0x6f, 0xe8, 0xde, 0xb5, 0x75, 0x5f, 0x5e, 0xc0, 0xbc, 0x1a, 0xe9, 0x84, 0xda, 0x52, 0x2e, - 0x45, 0x88, 0x44, 0xed, 0x2e, 0x30, 0xc1, 0xa1, 0x1b, 0x1a, 0xe3, 0x80, 0x28, 0xd9, 0x00, 0x89, - 0x4b, 0xe4, 0xd8, 0x5e, 0x62, 0x2d, 0x89, 0x23, 0xdb, 0x09, 0xec, 0xce, 0x81, 0xe3, 0x8e, 0x3b, - 0xee, 0x1b, 0xf0, 0x35, 0x76, 0xdc, 0x91, 0x13, 0xa0, 0xed, 0xc8, 0x97, 0x40, 0xb6, 0x93, 0x76, - 0x14, 0x26, 0xb1, 0xc3, 0x7b, 0xb3, 0x9f, 0xe7, 0xf7, 0x7b, 0xfe, 0xfd, 0x1e, 0x1b, 0xcc, 0x59, - 0xae, 0xa8, 0xc0, 0x09, 0x62, 0x79, 0x28, 0x29, 0x2e, 0x05, 0x53, 0x17, 0x3e, 0xc6, 0x95, 0x5f, - 0x08, 0x5e, 0x31, 0x42, 0x85, 0x5f, 0xcd, 0x56, 0x67, 0xaf, 0x10, 0x5c, 0x71, 0xf8, 0xfe, 0x7f, - 0x70, 0x3c, 0x8c, 0x2b, 0x6f, 0x85, 0xab, 0x66, 0xbb, 0x2f, 0x63, 0x1e, 0x73, 0x83, 0xf7, 0xf5, - 0xc9, 0x52, 0x77, 0x47, 0x31, 0xe7, 0x71, 0x4a, 0x7d, 0x73, 0x8b, 0xca, 0x33, 0x5f, 0xb1, 0x8c, - 0x4a, 0x85, 0xb2, 0xa2, 0x06, 0x0c, 0x37, 0x01, 0xa4, 0x14, 0x48, 0x31, 0x9e, 0x37, 0x01, 0x58, - 0x84, 0x7d, 0xcc, 0x05, 0xf5, 0x71, 0xca, 0x68, 0xae, 0x74, 0x79, 0xf6, 0x54, 0x03, 0x7c, 0x0d, - 0x48, 0x59, 0x9c, 0x28, 0x6b, 0x96, 0xbe, 0xa2, 0x39, 0xa1, 0x22, 0x63, 0x16, 0xbc, 0xbe, 0x59, - 0xc2, 0xe4, 0xe7, 0x36, 0x70, 0x0f, 0x79, 0x2e, 0xcb, 0x8c, 0x8a, 0x05, 0x21, 0x4c, 0x27, 0x5b, - 0x0a, 0x5e, 0x70, 0x89, 0x52, 0xf8, 0x12, 0x3c, 0x53, 0x4c, 0xa5, 0xd4, 0x75, 0xc6, 0xce, 0xb4, - 0x17, 0xd8, 0x0b, 0x1c, 0x83, 0x3e, 0xa1, 0x12, 0x0b, 0x56, 0x68, 0xb0, 0xfb, 0x9a, 0xf1, 0x3d, - 0x34, 0xc1, 0x01, 0xe8, 0xda, 0xf9, 0x30, 0xe2, 0xb6, 0x8d, 0xbb, 0x63, 0xee, 0x5f, 0x12, 0xf8, - 0x05, 0x78, 0xc1, 0x72, 0xa6, 0x18, 0x4a, 0xc3, 0x84, 0xea, 0x3a, 0xdd, 0xad, 0xb1, 0x33, 0xed, - 0xcf, 0x77, 0x3d, 0x16, 0x61, 0x4f, 0xb7, 0xe6, 0xd5, 0x0d, 0x55, 0x33, 0xef, 0xd8, 0x20, 0x0e, - 0xb6, 0x6e, 0x7e, 0x1f, 0xb5, 0x82, 0xd7, 0x6b, 0x9e, 0x35, 0xc2, 0xf7, 0xc0, 0xf3, 0x98, 0xe6, - 0x54, 0x32, 0x19, 0x26, 0x48, 0x26, 0xee, 0xb3, 0xb1, 0x33, 0x7d, 0x1e, 0xf4, 0x6b, 0xdb, 0x31, - 0x92, 0x09, 0x1c, 0x81, 0x7e, 0xc4, 0x72, 0x24, 0x2e, 0x2c, 0x62, 0xdb, 0x20, 0x80, 0x35, 0x19, - 0xc0, 0x21, 0x00, 0xb2, 0x40, 0x3f, 0xe6, 0xa1, 0xd6, 0xc1, 0xed, 0xd4, 0x85, 0x58, 0x0d, 0xbc, - 0x46, 0x03, 0xef, 0xb4, 0x11, 0xe9, 0xa0, 0xab, 0x0b, 0xb9, 0xfc, 0x63, 0xe4, 0x04, 0x3d, 0xc3, - 0xd3, 0x1e, 0xf8, 0x09, 0x18, 0xa4, 0x1c, 0x9f, 0x87, 0x65, 0x1e, 0xf1, 0x9c, 0xb0, 0x3c, 0x0e, - 0xb9, 0x0d, 0xc8, 0x4b, 0xe5, 0x76, 0xc7, 0xce, 0xb4, 0x1b, 0xec, 0x68, 0xc0, 0xb7, 0x8d, 0xff, - 0x6b, 0xc3, 0xe3, 0xa5, 0xda, 0xef, 0xfe, 0x72, 0x3d, 0x6a, 0x5d, 0x5d, 0x8f, 0x5a, 0x93, 0x5f, - 0x1d, 0xf0, 0x4e, 0x23, 0x43, 0x40, 0x33, 0x5e, 0xa1, 0xf4, 0x55, 0xaa, 0xb0, 0x00, 0x3d, 0xa9, - 0x78, 0x61, 0xfb, 0xde, 0x7a, 0x42, 0xdf, 0x5d, 0x4d, 0xd3, 0x8e, 0xc9, 0x5f, 0x0e, 0xd8, 0x5e, - 0x22, 0x81, 0x32, 0x09, 0x4f, 0xc1, 0x1b, 0x8a, 0x66, 0x45, 0x8a, 0x14, 0x0d, 0xad, 0x78, 0xa6, - 0xd4, 0xfe, 0xfc, 0x43, 0x23, 0xea, 0xc3, 0x75, 0xf4, 0x1e, 0x2c, 0x60, 0x35, 0xf3, 0x0e, 0x8d, - 0xf5, 0x44, 0x21, 0x45, 0x83, 0x17, 0x4d, 0x0c, 0x6b, 0x84, 0xdf, 0x00, 0x88, 0x71, 0xd5, 0x4c, - 0x32, 0x2c, 0xa8, 0x60, 0x9c, 0x98, 0x3e, 0xfb, 0xf3, 0xc1, 0xbf, 0x8a, 0xfd, 0xbc, 0x7e, 0x28, - 0xb6, 0xd6, 0x2b, 0x5d, 0xeb, 0x9b, 0x18, 0x57, 0xf5, 0xa4, 0x97, 0x86, 0x0c, 0x3f, 0x06, 0xae, - 0x12, 0xa5, 0x54, 0x5a, 0x24, 0x1b, 0x2f, 0x3c, 0x13, 0x08, 0x9b, 0x01, 0xea, 0x09, 0xb5, 0x83, - 0x9d, 0xc6, 0x6f, 0x19, 0x47, 0xb5, 0x77, 0x12, 0x81, 0xb7, 0x8e, 0x51, 0x4e, 0x64, 0x82, 0xce, - 0xe9, 0x57, 0x54, 0x21, 0x82, 0x14, 0x82, 0x7b, 0x60, 0xa7, 0x79, 0xf3, 0xe1, 0x19, 0xa5, 0x61, - 0xc1, 0x79, 0x1a, 0x22, 0x42, 0x44, 0xad, 0xd4, 0xdb, 0x8d, 0xf7, 0x88, 0xd2, 0x25, 0xe7, 0xe9, - 0x82, 0x10, 0x01, 0x5d, 0xd0, 0xa9, 0xa8, 0x90, 0x6b, 0xcd, 0x9a, 0xeb, 0xe4, 0x03, 0xd0, 0x3b, - 0x49, 0x91, 0x4c, 0x16, 0xf8, 0x5c, 0xc2, 0x77, 0x41, 0x4f, 0x47, 0xa2, 0x52, 0x52, 0xe9, 0x3a, - 0xe3, 0xf6, 0xb4, 0x17, 0xac, 0x0d, 0x13, 0x05, 0x06, 0x8f, 0x3d, 0x5a, 0x09, 0xbf, 0x07, 0x9d, - 0x82, 0x9a, 0x4d, 0x33, 0xc4, 0xfe, 0xfc, 0x33, 0xef, 0x7f, 0x7c, 0x59, 0xde, 0x63, 0x01, 0x83, - 0x26, 0xda, 0x44, 0xac, 0xbf, 0x8a, 0x8d, 0x1d, 0x95, 0xf0, 0xbb, 0xcd, 0xa4, 0x9f, 0x3e, 0x29, - 0xe9, 0x46, 0xbc, 0x55, 0xce, 0x83, 0xd3, 0x9b, 0xbb, 0xa1, 0x73, 0x7b, 0x37, 0x74, 0xfe, 0xbc, - 0x1b, 0x3a, 0x97, 0xf7, 0xc3, 0xd6, 0xed, 0xfd, 0xb0, 0xf5, 0xdb, 0xfd, 0xb0, 0xf5, 0xc3, 0x7e, - 0xcc, 0x54, 0x52, 0x46, 0x1e, 0xe6, 0x99, 0x8f, 0xb9, 0xcc, 0xb8, 0xf4, 0xd7, 0x19, 0x3f, 0x5a, - 0xfd, 0xe6, 0x3f, 0xfd, 0xf3, 0x3f, 0x57, 0x17, 0x05, 0x95, 0xd1, 0xb6, 0xd9, 0x9b, 0xbd, 0xbf, - 0x03, 0x00, 0x00, 0xff, 0xff, 0x6c, 0xf4, 0x66, 0x8b, 0x00, 0x06, 0x00, 0x00, + // 782 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x55, 0x41, 0x73, 0xe3, 0x34, + 0x14, 0x8e, 0x37, 0xd9, 0x26, 0x51, 0x96, 0x85, 0xd5, 0xee, 0x14, 0xa7, 0xc3, 0x24, 0x21, 0x5c, + 0xc2, 0x30, 0xd8, 0x93, 0xec, 0x05, 0x76, 0xe0, 0x90, 0x96, 0x59, 0xca, 0x81, 0x21, 0xb8, 0x05, + 0x66, 0xb8, 0x78, 0x64, 0x49, 0xb5, 0x35, 0xb5, 0x2d, 0x8f, 0x24, 0x1b, 0x7a, 0xe7, 0xc0, 0x71, + 0x8f, 0x7b, 0xdc, 0x7f, 0xc0, 0x5f, 0xe0, 0xd8, 0x63, 0x8f, 0x9c, 0x80, 0x69, 0xff, 0x08, 0x23, + 0xc9, 0x4e, 0xda, 0x40, 0x67, 0xda, 0x03, 0x37, 0xe9, 0xbd, 0xef, 0xfb, 0xf4, 0x9e, 0xbe, 0x67, + 0x19, 0x2c, 0x58, 0xae, 0xa8, 0xc0, 0x09, 0x62, 0x79, 0x28, 0x29, 0x2e, 0x05, 0x53, 0x67, 0x3e, + 0xc6, 0x95, 0x5f, 0x08, 0x5e, 0x31, 0x42, 0x85, 0x5f, 0xcd, 0xd7, 0x6b, 0xaf, 0x10, 0x5c, 0x71, + 0xf8, 0xc1, 0x7f, 0x70, 0x3c, 0x8c, 0x2b, 0x6f, 0x8d, 0xab, 0xe6, 0x7b, 0xcf, 0x62, 0x1e, 0x73, + 0x83, 0xf7, 0xf5, 0xca, 0x52, 0xf7, 0xc6, 0x31, 0xe7, 0x71, 0x4a, 0x7d, 0xb3, 0x8b, 0xca, 0x13, + 0x5f, 0xb1, 0x8c, 0x4a, 0x85, 0xb2, 0xa2, 0x06, 0x8c, 0xb6, 0x01, 0xa4, 0x14, 0x48, 0x31, 0x9e, + 0x37, 0x02, 0x2c, 0xc2, 0x3e, 0xe6, 0x82, 0xfa, 0x38, 0x65, 0x34, 0x57, 0xba, 0x3c, 0xbb, 0xaa, + 0x01, 0xbe, 0x06, 0xa4, 0x2c, 0x4e, 0x94, 0x0d, 0x4b, 0x5f, 0xd1, 0x9c, 0x50, 0x91, 0x31, 0x0b, + 0xde, 0xec, 0x2c, 0x61, 0xfa, 0x4b, 0x1b, 0xb8, 0x07, 0x3c, 0x97, 0x65, 0x46, 0xc5, 0x92, 0x10, + 0xa6, 0x0f, 0x5b, 0x09, 0x5e, 0x70, 0x89, 0x52, 0xf8, 0x0c, 0x3c, 0x54, 0x4c, 0xa5, 0xd4, 0x75, + 0x26, 0xce, 0xac, 0x1f, 0xd8, 0x0d, 0x9c, 0x80, 0x01, 0xa1, 0x12, 0x0b, 0x56, 0x68, 0xb0, 0xfb, + 0xc0, 0xe4, 0xae, 0x87, 0xe0, 0x10, 0xf4, 0xec, 0xfd, 0x30, 0xe2, 0xb6, 0x4d, 0xba, 0x6b, 0xf6, + 0x5f, 0x11, 0xf8, 0x25, 0x78, 0xcc, 0x72, 0xa6, 0x18, 0x4a, 0xc3, 0x84, 0xea, 0x3a, 0xdd, 0xce, + 0xc4, 0x99, 0x0d, 0x16, 0x7b, 0x1e, 0x8b, 0xb0, 0xa7, 0x5b, 0xf3, 0xea, 0x86, 0xaa, 0xb9, 0x77, + 0x68, 0x10, 0xfb, 0x9d, 0xf3, 0x3f, 0xc7, 0xad, 0xe0, 0xad, 0x9a, 0x67, 0x83, 0xf0, 0x7d, 0xf0, + 0x28, 0xa6, 0x39, 0x95, 0x4c, 0x86, 0x09, 0x92, 0x89, 0xfb, 0x70, 0xe2, 0xcc, 0x1e, 0x05, 0x83, + 0x3a, 0x76, 0x88, 0x64, 0x02, 0xc7, 0x60, 0x10, 0xb1, 0x1c, 0x89, 0x33, 0x8b, 0xd8, 0x31, 0x08, + 0x60, 0x43, 0x06, 0x70, 0x00, 0x80, 0x2c, 0xd0, 0x4f, 0x79, 0xa8, 0x7d, 0x70, 0xbb, 0x75, 0x21, + 0xd6, 0x03, 0xaf, 0xf1, 0xc0, 0x3b, 0x6e, 0x4c, 0xda, 0xef, 0xe9, 0x42, 0x5e, 0xfd, 0x35, 0x76, + 0x82, 0xbe, 0xe1, 0xe9, 0x0c, 0xfc, 0x14, 0x0c, 0x53, 0x8e, 0x4f, 0xc3, 0x32, 0x8f, 0x78, 0x4e, + 0x58, 0x1e, 0x87, 0xdc, 0x0a, 0xf2, 0x52, 0xb9, 0xbd, 0x89, 0x33, 0xeb, 0x05, 0xbb, 0x1a, 0xf0, + 0x5d, 0x93, 0xff, 0xc6, 0xf0, 0x78, 0xa9, 0x5e, 0xf4, 0x7e, 0x7d, 0x33, 0x6e, 0xbd, 0x7e, 0x33, + 0x6e, 0x4d, 0x7f, 0x73, 0xc0, 0xbb, 0x8d, 0x0d, 0x01, 0xcd, 0x78, 0x85, 0xd2, 0xff, 0xd3, 0x85, + 0x25, 0xe8, 0x4b, 0xc5, 0x0b, 0xdb, 0x77, 0xe7, 0x1e, 0x7d, 0xf7, 0x34, 0x4d, 0x27, 0xa6, 0xbf, + 0x3f, 0x00, 0x3b, 0x2b, 0x24, 0x50, 0x26, 0xe1, 0x31, 0x78, 0x5b, 0xd1, 0xac, 0x48, 0x91, 0xa2, + 0xa1, 0x35, 0xcf, 0x94, 0x3a, 0x58, 0x7c, 0x64, 0x4c, 0xbd, 0x3e, 0x8e, 0xde, 0xb5, 0x01, 0xac, + 0xe6, 0xde, 0x81, 0x89, 0x1e, 0x29, 0xa4, 0x68, 0xf0, 0xb8, 0xd1, 0xb0, 0x41, 0xf8, 0x09, 0x70, + 0x95, 0x28, 0xa5, 0xd2, 0x37, 0x5a, 0x50, 0xc1, 0x38, 0x09, 0x4f, 0x04, 0xc2, 0xeb, 0x6e, 0xdb, + 0xc1, 0x6e, 0x93, 0x5f, 0x99, 0xf4, 0xcb, 0x3a, 0x0b, 0xbf, 0x05, 0x10, 0xe3, 0xaa, 0xf1, 0xa0, + 0x26, 0x9b, 0x2b, 0x18, 0x2c, 0x86, 0xff, 0x6a, 0xf3, 0x8b, 0xfa, 0x13, 0xb3, 0x5d, 0xbe, 0xd6, + 0x5d, 0xbe, 0x83, 0x71, 0x55, 0x7b, 0x64, 0xa5, 0xe1, 0x11, 0x78, 0xaa, 0xc7, 0x6f, 0x5b, 0xb3, + 0x73, 0x77, 0xcd, 0x27, 0x9a, 0x7f, 0x43, 0x74, 0x1a, 0x81, 0x27, 0x87, 0x28, 0x27, 0x32, 0x41, + 0xa7, 0xf4, 0x6b, 0xaa, 0x10, 0x41, 0x0a, 0xc1, 0xe7, 0x60, 0xb7, 0x79, 0x48, 0xc2, 0x13, 0x4a, + 0xc3, 0x82, 0xf3, 0x34, 0x44, 0x84, 0x88, 0xda, 0xfe, 0xa7, 0x4d, 0xf6, 0x25, 0xa5, 0x2b, 0xce, + 0xd3, 0x25, 0x21, 0x02, 0xba, 0xa0, 0x5b, 0x51, 0x21, 0x37, 0x83, 0xd0, 0x6c, 0xa7, 0x1f, 0x82, + 0xfe, 0x51, 0x8a, 0x64, 0xb2, 0xc4, 0xa7, 0x12, 0xbe, 0x07, 0xfa, 0x5a, 0x89, 0x4a, 0x49, 0xa5, + 0xeb, 0x4c, 0xda, 0xb3, 0x7e, 0xb0, 0x09, 0x4c, 0x15, 0x18, 0xde, 0xf6, 0x12, 0x48, 0xf8, 0x03, + 0xe8, 0x16, 0xd4, 0x8c, 0xaf, 0x21, 0x0e, 0x16, 0x9f, 0x7b, 0x77, 0x78, 0x07, 0xbd, 0xdb, 0x04, + 0x83, 0x46, 0x6d, 0x2a, 0x36, 0xef, 0xcf, 0xd6, 0xe0, 0x4b, 0xf8, 0xfd, 0xf6, 0xa1, 0x9f, 0xdd, + 0xeb, 0xd0, 0x2d, 0xbd, 0xf5, 0x99, 0xfb, 0xc7, 0xe7, 0x97, 0x23, 0xe7, 0xe2, 0x72, 0xe4, 0xfc, + 0x7d, 0x39, 0x72, 0x5e, 0x5d, 0x8d, 0x5a, 0x17, 0x57, 0xa3, 0xd6, 0x1f, 0x57, 0xa3, 0xd6, 0x8f, + 0x2f, 0x62, 0xa6, 0x92, 0x32, 0xf2, 0x30, 0xcf, 0x7c, 0xcc, 0x65, 0xc6, 0xa5, 0xbf, 0x39, 0xf1, + 0xe3, 0xf5, 0x2f, 0xe2, 0xe7, 0x9b, 0x3f, 0x09, 0x75, 0x56, 0x50, 0x19, 0xed, 0x18, 0xfb, 0x9f, + 0xff, 0x13, 0x00, 0x00, 0xff, 0xff, 0xc2, 0x4e, 0xda, 0x4e, 0x55, 0x06, 0x00, 0x00, } func (m *ConsumerAdditionProposal) Marshal() (dAtA []byte, err error) { @@ -641,19 +651,27 @@ func (m *Params) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l - if m.TrustingPeriodFraction != 0 { - i = encodeVarintProvider(dAtA, i, uint64(m.TrustingPeriodFraction)) - i-- - dAtA[i] = 0x18 - } - n4, err4 := github_com_gogo_protobuf_types.StdDurationMarshalTo(m.CcvTimeoutPeriod, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdDuration(m.CcvTimeoutPeriod):]) + n4, err4 := github_com_gogo_protobuf_types.StdDurationMarshalTo(m.InitTimeoutPeriod, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdDuration(m.InitTimeoutPeriod):]) if err4 != nil { return 0, err4 } i -= n4 i = encodeVarintProvider(dAtA, i, uint64(n4)) i-- - dAtA[i] = 0x12 + dAtA[i] = 0x22 + n5, err5 := github_com_gogo_protobuf_types.StdDurationMarshalTo(m.CcvTimeoutPeriod, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdDuration(m.CcvTimeoutPeriod):]) + if err5 != nil { + return 0, err5 + } + i -= n5 + i = encodeVarintProvider(dAtA, i, uint64(n5)) + i-- + dAtA[i] = 0x1a + if m.TrustingPeriodFraction != 0 { + i = encodeVarintProvider(dAtA, i, uint64(m.TrustingPeriodFraction)) + i-- + dAtA[i] = 0x10 + } if m.TemplateClient != nil { { size, err := m.TemplateClient.MarshalToSizedBuffer(dAtA[:i]) @@ -892,11 +910,13 @@ func (m *Params) Size() (n int) { l = m.TemplateClient.Size() n += 1 + l + sovProvider(uint64(l)) } - l = github_com_gogo_protobuf_types.SizeOfStdDuration(m.CcvTimeoutPeriod) - n += 1 + l + sovProvider(uint64(l)) if m.TrustingPeriodFraction != 0 { n += 1 + sovProvider(uint64(m.TrustingPeriodFraction)) } + l = github_com_gogo_protobuf_types.SizeOfStdDuration(m.CcvTimeoutPeriod) + n += 1 + l + sovProvider(uint64(l)) + l = github_com_gogo_protobuf_types.SizeOfStdDuration(m.InitTimeoutPeriod) + n += 1 + l + sovProvider(uint64(l)) return n } @@ -1513,6 +1533,25 @@ func (m *Params) Unmarshal(dAtA []byte) error { } iNdEx = postIndex case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field TrustingPeriodFraction", wireType) + } + m.TrustingPeriodFraction = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowProvider + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.TrustingPeriodFraction |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field CcvTimeoutPeriod", wireType) } @@ -1545,11 +1584,11 @@ func (m *Params) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex - case 3: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field TrustingPeriodFraction", wireType) + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field InitTimeoutPeriod", wireType) } - m.TrustingPeriodFraction = 0 + var msglen int for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowProvider @@ -1559,11 +1598,25 @@ func (m *Params) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - m.TrustingPeriodFraction |= int64(b&0x7F) << shift + 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 + } + if err := github_com_gogo_protobuf_types.StdDurationUnmarshal(&m.InitTimeoutPeriod, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipProvider(dAtA[iNdEx:])