From 9fa5ec3ad568c63bc38a440134e4c5fa86bdc2cb Mon Sep 17 00:00:00 2001 From: stana-ethernal Date: Fri, 15 Nov 2024 17:33:26 +0100 Subject: [PATCH 01/14] Customizable Slashing and Jailing --- .../ccv/provider/v1/provider.proto | 19 + .../ccv/provider/v1/query.proto | 3 + .../ccv/provider/v1/tx.proto | 6 + x/ccv/provider/client/cli/tx.go | 24 +- .../provider/keeper/consumer_equivocation.go | 33 +- .../keeper/consumer_equivocation_test.go | 31 +- x/ccv/provider/keeper/consumer_lifecycle.go | 2 + x/ccv/provider/keeper/grpc_query.go | 29 +- x/ccv/provider/keeper/grpc_query_test.go | 29 +- .../provider/keeper/infraction_parameters.go | 258 ++++++ x/ccv/provider/keeper/msg_server.go | 55 ++ x/ccv/provider/keeper/relay.go | 20 +- x/ccv/provider/module.go | 4 + x/ccv/provider/types/errors.go | 1 + x/ccv/provider/types/keys.go | 50 ++ x/ccv/provider/types/keys_test.go | 9 + x/ccv/provider/types/msg.go | 41 +- x/ccv/provider/types/msg_test.go | 61 +- x/ccv/provider/types/provider.go | 25 + x/ccv/provider/types/provider.pb.go | 753 ++++++++++++++---- x/ccv/provider/types/query.pb.go | 479 +++++++---- x/ccv/provider/types/tx.pb.go | 386 ++++++--- x/ccv/types/shared_params.go | 10 + 23 files changed, 1825 insertions(+), 503 deletions(-) create mode 100644 x/ccv/provider/keeper/infraction_parameters.go diff --git a/proto/interchain_security/ccv/provider/v1/provider.proto b/proto/interchain_security/ccv/provider/v1/provider.proto index 138e5fa23b..4cec258646 100644 --- a/proto/interchain_security/ccv/provider/v1/provider.proto +++ b/proto/interchain_security/ccv/provider/v1/provider.proto @@ -556,3 +556,22 @@ enum ConsumerPhase { message AllowlistedRewardDenoms { repeated string denoms = 1; } + +// +message InfractionParameters { + SlashJailParameters double_sign = 1; + SlashJailParameters downtime = 2; +} + +// +message SlashJailParameters { + bytes slash_fraction = 1 [ + (cosmos_proto.scalar) = "cosmos.Dec", + (gogoproto.customtype) = "cosmossdk.io/math.LegacyDec", + (gogoproto.nullable) = false, + (amino.dont_omitempty) = true + ]; + // for permanent jailing use 9223372036854775807 which is the largest value a time.Duration can hold (approximately 292 years) + google.protobuf.Duration jail_duration = 8 + [ (gogoproto.nullable) = false, (gogoproto.stdduration) = true ]; +} \ No newline at end of file diff --git a/proto/interchain_security/ccv/provider/v1/query.proto b/proto/interchain_security/ccv/provider/v1/query.proto index e659b3cda6..20f85ec637 100644 --- a/proto/interchain_security/ccv/provider/v1/query.proto +++ b/proto/interchain_security/ccv/provider/v1/query.proto @@ -209,6 +209,8 @@ message Chain { // filled with these validators first, and other validators will be added to the validator set only if there are // not enough eligible priority validators. repeated string prioritylist = 15; + // Infraction parameters for slashing and jailing + InfractionParameters infraction_parameters = 16; } message QueryValidatorConsumerAddrRequest { @@ -397,6 +399,7 @@ message QueryConsumerChainResponse { ConsumerMetadata metadata = 5 [ (gogoproto.nullable) = false ]; ConsumerInitializationParameters init_params = 6; PowerShapingParameters power_shaping_params = 7; + InfractionParameters infraction_parameters = 8; } message QueryConsumerGenesisTimeRequest { diff --git a/proto/interchain_security/ccv/provider/v1/tx.proto b/proto/interchain_security/ccv/provider/v1/tx.proto index ea86835759..2fe5542e1a 100644 --- a/proto/interchain_security/ccv/provider/v1/tx.proto +++ b/proto/interchain_security/ccv/provider/v1/tx.proto @@ -363,6 +363,9 @@ message MsgCreateConsumer { // allowlisted reward denoms of the consumer AllowlistedRewardDenoms allowlisted_reward_denoms = 6; + + // infraction parameters for slashing and jailing + InfractionParameters infraction_parameters = 7; } // MsgCreateConsumerResponse defines response type for MsgCreateConsumer @@ -399,6 +402,9 @@ message MsgUpdateConsumer { // the chain id CANNOT be updated. // This field is optional and can remain empty (i.e., `new_chain_id = ""`) or correspond to the chain id the chain already has. string new_chain_id = 8; + + // infraction parameters for slashing and jailing + InfractionParameters infraction_parameters = 9; } // MsgUpdateConsumerResponse defines response type for MsgUpdateConsumer messages diff --git a/x/ccv/provider/client/cli/tx.go b/x/ccv/provider/client/cli/tx.go index 1894ad7b36..754b9ebc12 100644 --- a/x/ccv/provider/client/cli/tx.go +++ b/x/ccv/provider/client/cli/tx.go @@ -257,6 +257,16 @@ where create_consumer.json has the following structure: "allow_inactive_vals": false, "prioritylist": ["cosmosvalcons..."] }, + "infraction_parameters": { + "double_sign": { + "slash_fraction": "0.05", + "jail_duration": "9223372036854775807" + }, + "downtime": { + "slash_fraction": "0.0001", + "jail_duration": "600000000000" + } + }, "allowlisted_reward_denoms": { "denoms": ["ibc/...", "ibc/..."] } @@ -291,7 +301,7 @@ The parameters not provided are set to their zero value. } msg, err := types.NewMsgCreateConsumer(submitter, consCreate.ChainId, consCreate.Metadata, consCreate.InitializationParameters, - consCreate.PowerShapingParameters, consCreate.AllowlistedRewardDenoms) + consCreate.PowerShapingParameters, consCreate.AllowlistedRewardDenoms, consCreate.InfractionParameters) if err != nil { return err } @@ -356,6 +366,16 @@ where update_consumer.json has the following structure: "allow_inactive_vals": false, "prioritylist": ["cosmosvalcons..."] }, + "infraction_parameters": { + "double_sign": { + "slash_fraction": "0.05", + "jail_duration": "9223372036854775807" + }, + "downtime": { + "slash_fraction": "0.0001", + "jail_duration": "600000000000" + } + }, "allowlisted_reward_denoms": { "denoms": ["ibc/...", "ibc/..."] } @@ -398,7 +418,7 @@ If one of the fields is missing, it will be set to its zero value. } msg, err := types.NewMsgUpdateConsumer(owner, consUpdate.ConsumerId, consUpdate.NewOwnerAddress, consUpdate.Metadata, - consUpdate.InitializationParameters, consUpdate.PowerShapingParameters, consUpdate.AllowlistedRewardDenoms, consUpdate.NewChainId) + consUpdate.InitializationParameters, consUpdate.PowerShapingParameters, consUpdate.AllowlistedRewardDenoms, consUpdate.NewChainId, consUpdate.InfractionParameters) if err != nil { return err } diff --git a/x/ccv/provider/keeper/consumer_equivocation.go b/x/ccv/provider/keeper/consumer_equivocation.go index a7c3d2025e..db20e6e538 100644 --- a/x/ccv/provider/keeper/consumer_equivocation.go +++ b/x/ccv/provider/keeper/consumer_equivocation.go @@ -11,7 +11,6 @@ import ( errorsmod "cosmossdk.io/errors" "cosmossdk.io/math" - evidencetypes "cosmossdk.io/x/evidence/types" cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" sdk "github.com/cosmos/cosmos-sdk/types" @@ -75,10 +74,16 @@ func (k Keeper) HandleConsumerDoubleVoting( types.NewConsumerConsAddress(sdk.ConsAddress(evidence.VoteA.ValidatorAddress.Bytes())), ) - if err = k.SlashValidator(ctx, providerAddr); err != nil { + // get the consumer's infraction parameters + infractionParams, err := k.GetInfractionParameters(ctx, consumerId) + if err != nil { + return err + } + + if err = k.SlashValidator(ctx, providerAddr, infractionParams.DoubleSign, stakingtypes.Infraction_INFRACTION_DOUBLE_SIGN); err != nil { return err } - if err = k.JailAndTombstoneValidator(ctx, providerAddr); err != nil { + if err = k.JailAndTombstoneValidator(ctx, providerAddr, infractionParams.DoubleSign); err != nil { return err } @@ -186,6 +191,11 @@ func (k Keeper) HandleConsumerMisbehaviour(ctx sdk.Context, consumerId string, m provAddrs := make([]types.ProviderConsAddress, 0, len(byzantineValidators)) + infractionParams, err := k.GetInfractionParameters(ctx, consumerId) + if err != nil { + return err + } + // slash, jail, and tombstone the Byzantine validators for _, v := range byzantineValidators { providerAddr := k.GetProviderAddrFromConsumerAddr( @@ -193,12 +203,12 @@ func (k Keeper) HandleConsumerMisbehaviour(ctx sdk.Context, consumerId string, m consumerId, types.NewConsumerConsAddress(sdk.ConsAddress(v.Address.Bytes())), ) - err := k.SlashValidator(ctx, providerAddr) + err := k.SlashValidator(ctx, providerAddr, infractionParams.DoubleSign, stakingtypes.Infraction_INFRACTION_DOUBLE_SIGN) if err != nil { logger.Error("failed to slash validator: %s", err) continue } - err = k.JailAndTombstoneValidator(ctx, providerAddr) + err = k.JailAndTombstoneValidator(ctx, providerAddr, infractionParams.DoubleSign) // JailAndTombstoneValidator should never return an error if // SlashValidator succeeded because both methods fail if the malicious // validator is either or both !found, unbonded and tombstoned. @@ -411,7 +421,7 @@ func verifyLightBlockCommitSig(lightBlock tmtypes.LightBlock, sigIdx int) error // // JailAndTombstoneValidator jails and tombstones the validator with the given provider consensus address -func (k Keeper) JailAndTombstoneValidator(ctx sdk.Context, providerAddr types.ProviderConsAddress) error { +func (k Keeper) JailAndTombstoneValidator(ctx sdk.Context, providerAddr types.ProviderConsAddress, jailingParams *types.SlashJailParameters) error { validator, err := k.stakingKeeper.GetValidatorByConsAddr(ctx, providerAddr.ToSdkConsAddr()) if err != nil && errors.Is(err, stakingtypes.ErrNoValidatorFound) { return errorsmod.Wrapf(slashingtypes.ErrNoValidatorForAddress, "provider consensus address: %s", providerAddr.String()) @@ -435,7 +445,8 @@ func (k Keeper) JailAndTombstoneValidator(ctx sdk.Context, providerAddr types.Pr } } - err = k.slashingKeeper.JailUntil(ctx, providerAddr.ToSdkConsAddr(), evidencetypes.DoubleSignJailEndTime) + jailEndTime := ctx.BlockTime().Add(jailingParams.JailDuration) + err = k.slashingKeeper.JailUntil(ctx, providerAddr.ToSdkConsAddr(), jailEndTime) if err != nil { return fmt.Errorf("fail to set jail duration for validator: %s: %s", providerAddr.String(), err) } @@ -481,7 +492,7 @@ func (k Keeper) ComputePowerToSlash(ctx sdk.Context, validator stakingtypes.Vali } // SlashValidator slashes validator with given provider Address -func (k Keeper) SlashValidator(ctx sdk.Context, providerAddr types.ProviderConsAddress) error { +func (k Keeper) SlashValidator(ctx sdk.Context, providerAddr types.ProviderConsAddress, slashingParams *types.SlashJailParameters, slashingReason stakingtypes.Infraction) error { validator, err := k.stakingKeeper.GetValidatorByConsAddr(ctx, providerAddr.ToSdkConsAddr()) if err != nil && errors.Is(err, stakingtypes.ErrNoValidatorFound) { return errorsmod.Wrapf(slashingtypes.ErrNoValidatorForAddress, "provider consensus address: %s", providerAddr.String()) @@ -518,16 +529,12 @@ func (k Keeper) SlashValidator(ctx sdk.Context, providerAddr types.ProviderConsA powerReduction := k.stakingKeeper.PowerReduction(ctx) totalPower := k.ComputePowerToSlash(ctx, validator, undelegations, redelegations, lastPower, powerReduction) - slashFraction, err := k.slashingKeeper.SlashFractionDoubleSign(ctx) - if err != nil { - return err - } consAdrr, err := validator.GetConsAddr() if err != nil { return err } - _, err = k.stakingKeeper.SlashWithInfractionReason(ctx, consAdrr, 0, totalPower, slashFraction, stakingtypes.Infraction_INFRACTION_DOUBLE_SIGN) + _, err = k.stakingKeeper.SlashWithInfractionReason(ctx, consAdrr, 0, totalPower, slashingParams.SlashFraction, slashingReason) return err } diff --git a/x/ccv/provider/keeper/consumer_equivocation_test.go b/x/ccv/provider/keeper/consumer_equivocation_test.go index d85b963127..d16bf5a7c7 100644 --- a/x/ccv/provider/keeper/consumer_equivocation_test.go +++ b/x/ccv/provider/keeper/consumer_equivocation_test.go @@ -9,7 +9,6 @@ import ( "github.com/stretchr/testify/require" "cosmossdk.io/math" - evidencetypes "cosmossdk.io/x/evidence/types" cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" @@ -383,6 +382,7 @@ func TestJailAndTombstoneValidator(t *testing.T) { func(ctx sdk.Context, mocks testkeeper.MockedKeepers, provAddr types.ProviderConsAddress, ) []*gomock.Call { + jailEndTime := ctx.BlockTime().Add(getTestInfractionParameters().DoubleSign.JailDuration) return []*gomock.Call{ mocks.MockStakingKeeper.EXPECT().GetValidatorByConsAddr( ctx, providerConsAddr.ToSdkConsAddr()).Return( @@ -393,7 +393,7 @@ func TestJailAndTombstoneValidator(t *testing.T) { false, ).Times(1), mocks.MockSlashingKeeper.EXPECT().JailUntil( - ctx, providerConsAddr.ToSdkConsAddr(), evidencetypes.DoubleSignJailEndTime). + ctx, providerConsAddr.ToSdkConsAddr(), jailEndTime). Times(1), mocks.MockSlashingKeeper.EXPECT().Tombstone( ctx, providerConsAddr.ToSdkConsAddr()). @@ -407,6 +407,7 @@ func TestJailAndTombstoneValidator(t *testing.T) { func(ctx sdk.Context, mocks testkeeper.MockedKeepers, provAddr types.ProviderConsAddress, ) []*gomock.Call { + jailEndTime := ctx.BlockTime().Add(getTestInfractionParameters().DoubleSign.JailDuration) return []*gomock.Call{ mocks.MockStakingKeeper.EXPECT().GetValidatorByConsAddr( ctx, providerConsAddr.ToSdkConsAddr()).Return( @@ -420,7 +421,7 @@ func TestJailAndTombstoneValidator(t *testing.T) { ctx, providerConsAddr.ToSdkConsAddr()). Times(1), mocks.MockSlashingKeeper.EXPECT().JailUntil( - ctx, providerConsAddr.ToSdkConsAddr(), evidencetypes.DoubleSignJailEndTime). + ctx, providerConsAddr.ToSdkConsAddr(), jailEndTime). Times(1), mocks.MockSlashingKeeper.EXPECT().Tombstone( ctx, providerConsAddr.ToSdkConsAddr()). @@ -438,7 +439,7 @@ func TestJailAndTombstoneValidator(t *testing.T) { gomock.InOrder(tc.expectedCalls(ctx, mocks, tc.provAddr)...) // Execute method and assert expected mock calls - providerKeeper.JailAndTombstoneValidator(ctx, tc.provAddr) + providerKeeper.JailAndTombstoneValidator(ctx, tc.provAddr, getTestInfractionParameters().DoubleSign) ctrl.Finish() } @@ -677,7 +678,7 @@ func TestSlashValidator(t *testing.T) { currentPower := int64(3000) powerReduction := math.NewInt(2) - slashFraction, _ := math.LegacyNewDecFromStr("0.5") + slashFraction := getTestInfractionParameters().DoubleSign.SlashFraction // the call to `Slash` should provide an `infractionHeight` of 0 and an expected power of // (750 (undelegations) + 750 (redelegations)) / 2 (= powerReduction) + 3000 (currentPower) = 3750 @@ -732,16 +733,13 @@ func TestSlashValidator(t *testing.T) { } return sum, nil }).AnyTimes(), - mocks.MockSlashingKeeper.EXPECT(). - SlashFractionDoubleSign(ctx). - Return(slashFraction, nil), mocks.MockStakingKeeper.EXPECT(). SlashWithInfractionReason(ctx, consAddr, expectedInfractionHeight, expectedSlashPower, slashFraction, stakingtypes.Infraction_INFRACTION_DOUBLE_SIGN).Return(math.NewInt(expectedSlashPower), nil). Times(1), } gomock.InOrder(expectedCalls...) - keeper.SlashValidator(ctx, providerAddr) + keeper.SlashValidator(ctx, providerAddr, getTestInfractionParameters().DoubleSign, stakingtypes.Infraction_INFRACTION_DOUBLE_SIGN) } // TestSlashValidatorDoesNotSlashIfValidatorIsUnbonded asserts that `SlashValidator` does not call @@ -768,7 +766,7 @@ func TestSlashValidatorDoesNotSlashIfValidatorIsUnbonded(t *testing.T) { } gomock.InOrder(expectedCalls...) - keeper.SlashValidator(ctx, providerAddr) + keeper.SlashValidator(ctx, providerAddr, getTestInfractionParameters().DoubleSign, stakingtypes.Infraction_INFRACTION_DOUBLE_SIGN) } func TestEquivocationEvidenceMinHeightCRUD(t *testing.T) { @@ -788,3 +786,16 @@ func TestEquivocationEvidenceMinHeightCRUD(t *testing.T) { height = keeper.GetEquivocationEvidenceMinHeight(ctx, chainID) require.Zero(t, height, "equivocation evidence min height should be 0") } + +func getTestInfractionParameters() *types.InfractionParameters { + return &types.InfractionParameters{ + DoubleSign: &types.SlashJailParameters{ + JailDuration: 1200 * time.Second, + SlashFraction: math.LegacyNewDecWithPrec(5, 1), // 0.5 + }, + Downtime: &types.SlashJailParameters{ + JailDuration: 600 * time.Second, + SlashFraction: math.LegacyNewDec(0), + }, + } +} diff --git a/x/ccv/provider/keeper/consumer_lifecycle.go b/x/ccv/provider/keeper/consumer_lifecycle.go index 51d2120f89..1ee74d94e8 100644 --- a/x/ccv/provider/keeper/consumer_lifecycle.go +++ b/x/ccv/provider/keeper/consumer_lifecycle.go @@ -490,6 +490,8 @@ func (k Keeper) DeleteConsumerChain(ctx sdk.Context, consumerId string) (err err k.DeleteConsumerRemovalTime(ctx, consumerId) + k.RemoveConsumerInfractionQueuedData(ctx, consumerId) + // TODO (PERMISSIONLESS) add newly-added state to be deleted // Note that we do not delete ConsumerIdToChainIdKey and ConsumerIdToPhase, as well diff --git a/x/ccv/provider/keeper/grpc_query.go b/x/ccv/provider/keeper/grpc_query.go index d98f7e9b3e..976d27f842 100644 --- a/x/ccv/provider/keeper/grpc_query.go +++ b/x/ccv/provider/keeper/grpc_query.go @@ -100,6 +100,11 @@ func (k Keeper) GetConsumerChain(ctx sdk.Context, consumerId string) (types.Chai return types.Chain{}, fmt.Errorf("cannot find power shaping parameters for consumer (%s): %s", consumerId, err.Error()) } + infractionParameters, err := k.GetInfractionParameters(ctx, consumerId) + if err != nil { + return types.Chain{}, fmt.Errorf("cannot find infraction parameters for consumer (%s): %s", consumerId, err.Error()) + } + // Get the minimal power in the top N for the consumer chain minPowerInTopN, found := k.GetMinimumPowerInTopN(ctx, consumerId) if !found { @@ -150,6 +155,7 @@ func (k Keeper) GetConsumerChain(ctx sdk.Context, consumerId string) (types.Chai ConsumerId: consumerId, AllowlistedRewardDenoms: &types.AllowlistedRewardDenoms{Denoms: allowlistedRewardDenoms}, Prioritylist: strPrioritylist, + InfractionParameters: &infractionParameters, }, nil } @@ -618,18 +624,25 @@ func (k Keeper) QueryConsumerChain(goCtx context.Context, req *types.QueryConsum initParams, _ := k.GetConsumerInitializationParameters(ctx, consumerId) powerParams, _ := k.GetConsumerPowerShapingParameters(ctx, consumerId) + infractionParams, err := k.GetInfractionParameters(ctx, consumerId) + if err != nil { + return nil, status.Errorf(codes.InvalidArgument, "cannot retrieve infraction parameters for consumer id: %s", consumerId) + } + return &types.QueryConsumerChainResponse{ - ChainId: chainId, - ConsumerId: consumerId, - OwnerAddress: ownerAddress, - Phase: phase.String(), - Metadata: metadata, - InitParams: &initParams, - PowerShapingParams: &powerParams, + ChainId: chainId, + ConsumerId: consumerId, + OwnerAddress: ownerAddress, + Phase: phase.String(), + Metadata: metadata, + InitParams: &initParams, + PowerShapingParams: &powerParams, + InfractionParameters: &infractionParams, }, nil } -// QueryConsumerGenesisTime returns the genesis time +// QueryConsumerGenesisTime returns the genesis time +// // of the consumer chain associated with the provided consumer id func (k Keeper) QueryConsumerGenesisTime(goCtx context.Context, req *types.QueryConsumerGenesisTimeRequest) (*types.QueryConsumerGenesisTimeResponse, error) { if req == nil { diff --git a/x/ccv/provider/keeper/grpc_query_test.go b/x/ccv/provider/keeper/grpc_query_test.go index 73f1f94ffb..1f8fc4531f 100644 --- a/x/ccv/provider/keeper/grpc_query_test.go +++ b/x/ccv/provider/keeper/grpc_query_test.go @@ -303,6 +303,8 @@ func TestQueryConsumerChainsValidatorHasToValidate(t *testing.T) { providerAddr := types.NewProviderConsAddress(valConsAddr) mocks.MockStakingKeeper.EXPECT().GetValidatorByConsAddr(ctx, valConsAddr).Return(val, nil).AnyTimes() testkeeper.SetupMocksForLastBondedValidatorsExpectation(mocks.MockStakingKeeper, 1, []stakingtypes.Validator{val}, -1) // -1 to allow the calls "AnyTimes" + mocks.MockSlashingKeeper.EXPECT().DowntimeJailDuration(ctx).Return(time.Second*600, nil).AnyTimes() + mocks.MockSlashingKeeper.EXPECT().SlashFractionDoubleSign(ctx).Return(math.LegacyNewDec(0), nil).AnyTimes() req := types.QueryConsumerChainsValidatorHasToValidateRequest{ ProviderAddress: providerAddr.String(), @@ -491,6 +493,8 @@ func TestGetConsumerChain(t *testing.T) { AllowInactiveVals: allowInactiveVals[i], }) require.NoError(t, err) + err = pk.SetInfractionParameters(ctx, consumerID, *getTestInfractionParameters()) + require.NoError(t, err) pk.SetMinimumPowerInTopN(ctx, consumerID, expectedMinPowerInTopNs[i]) for _, addr := range allowlists[i] { pk.SetAllowlist(ctx, consumerID, addr) @@ -541,6 +545,7 @@ func TestGetConsumerChain(t *testing.T) { ConsumerId: consumerIDs[i], AllowlistedRewardDenoms: allowlistedRewardDenoms[i], Prioritylist: strPrioritylist, + InfractionParameters: getTestInfractionParameters(), }) } @@ -587,14 +592,18 @@ func TestQueryConsumerChain(t *testing.T) { err = providerKeeper.SetConsumerMetadata(ctx, consumerId, types.ConsumerMetadata{Name: chainId}) require.NoError(t, err) + err = providerKeeper.SetInfractionParameters(ctx, consumerId, *getTestInfractionParameters()) + require.NoError(t, err) + expRes := types.QueryConsumerChainResponse{ - ChainId: chainId, - ConsumerId: consumerId, - OwnerAddress: providerKeeper.GetAuthority(), - Metadata: types.ConsumerMetadata{Name: chainId}, - Phase: types.CONSUMER_PHASE_REGISTERED.String(), - InitParams: &types.ConsumerInitializationParameters{}, - PowerShapingParams: &types.PowerShapingParameters{}, + ChainId: chainId, + ConsumerId: consumerId, + OwnerAddress: providerKeeper.GetAuthority(), + Metadata: types.ConsumerMetadata{Name: chainId}, + Phase: types.CONSUMER_PHASE_REGISTERED.String(), + InitParams: &types.ConsumerInitializationParameters{}, + PowerShapingParams: &types.PowerShapingParameters{}, + InfractionParameters: getTestInfractionParameters(), } // expect no error when neither the consumer init and power shaping params are set @@ -642,8 +651,10 @@ func TestQueryConsumerIdFromClientId(t *testing.T) { } func TestQueryConsumerChains(t *testing.T) { - pk, ctx, ctrl, _ := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t)) + pk, ctx, ctrl, mocks := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t)) defer ctrl.Finish() + mocks.MockSlashingKeeper.EXPECT().DowntimeJailDuration(ctx).Return(time.Second*600, nil).AnyTimes() + mocks.MockSlashingKeeper.EXPECT().SlashFractionDoubleSign(ctx).Return(math.LegacyNewDec(0), nil).AnyTimes() consumerNum := 4 consumerIds := make([]string, consumerNum) @@ -674,6 +685,7 @@ func TestQueryConsumerChains(t *testing.T) { ChainId: chainID, Metadata: metadata, InitializationParameters: &initializationParameters, + InfractionParameters: getTestInfractionParameters(), } resp, err := msgServer.CreateConsumer(ctx, &msg) require.NoError(t, err) @@ -692,6 +704,7 @@ func TestQueryConsumerChains(t *testing.T) { ConsumerId: consumerId, AllowlistedRewardDenoms: &types.AllowlistedRewardDenoms{Denoms: []string{}}, Prioritylist: []string{}, + InfractionParameters: getTestInfractionParameters(), } consumerIds[i] = consumerId consumers[i] = &c diff --git a/x/ccv/provider/keeper/infraction_parameters.go b/x/ccv/provider/keeper/infraction_parameters.go new file mode 100644 index 0000000000..5dd63f3849 --- /dev/null +++ b/x/ccv/provider/keeper/infraction_parameters.go @@ -0,0 +1,258 @@ +package keeper + +import ( + "fmt" + "time" + + storetypes "cosmossdk.io/store/types" + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/cosmos/interchain-security/v6/x/ccv/provider/types" +) + +// GetInfractionParameters returns the slashing and jailing infraction parameters associated with this consumer id +func (k Keeper) GetInfractionParameters(ctx sdk.Context, consumerId string) (types.InfractionParameters, error) { + store := ctx.KVStore(k.storeKey) + bz := store.Get(types.ConsumerIdToInfractionParametersKey(consumerId)) + if bz == nil { + return types.InfractionParameters{}, fmt.Errorf("failed to retrieve infraction parameters for consumer id (%s)", consumerId) + } + var infractionParameters types.InfractionParameters + if err := infractionParameters.Unmarshal(bz); err != nil { + return types.InfractionParameters{}, fmt.Errorf("failed to unmarshal infraction parameters for consumer id (%s): %w", consumerId, err) + } + + return infractionParameters, nil +} + +// SetInfractionParameters sets the slashing and jailing infraction parameters associated with this consumer id +func (k Keeper) SetInfractionParameters(ctx sdk.Context, consumerId string, parameters types.InfractionParameters) error { + store := ctx.KVStore(k.storeKey) + bz, err := parameters.Marshal() + if err != nil { + return fmt.Errorf("failed to marshal infraction parameters (%+v) for consumer id (%s): %w", parameters, consumerId, err) + } + + store.Set(types.ConsumerIdToInfractionParametersKey(consumerId), bz) + + return nil +} + +// DeleteInfractionParameters deletes the slashing and jailing infraction parameters associated with this consumer id +func (k Keeper) DeleteInfractionParameters(ctx sdk.Context, consumerId string) { + store := ctx.KVStore(k.storeKey) + store.Delete(types.ConsumerIdToInfractionParametersKey(consumerId)) +} + +// GetQueuedInfractionParameters returns the infraction parameters associated with this consumer id that are queued for future application +func (k Keeper) GetQueuedInfractionParameters(ctx sdk.Context, consumerId string) (types.InfractionParameters, error) { + store := ctx.KVStore(k.storeKey) + bz := store.Get(types.ConsumerIdToQueuedInfractionParametersKey(consumerId)) + if bz == nil { + return types.InfractionParameters{}, fmt.Errorf("failed to retrieve queued infraction parameters for consumer id (%s)", consumerId) + } + + var infractionParameters types.InfractionParameters + if err := infractionParameters.Unmarshal(bz); err != nil { + return types.InfractionParameters{}, fmt.Errorf("failed to unmarshal queued infraction parameters for consumer id (%s): %w", consumerId, err) + } + + return infractionParameters, nil +} + +// SetQueuedInfractionParameters sets the queued infraction parameters associated with this consumer id +func (k Keeper) SetQueuedInfractionParameters(ctx sdk.Context, consumerId string, parameters types.InfractionParameters) error { + store := ctx.KVStore(k.storeKey) + bz, err := parameters.Marshal() + if err != nil { + return fmt.Errorf("failed to marshal new infraction parameters (%+v) for consumer id (%s): %w", parameters, consumerId, err) + } + + store.Set(types.ConsumerIdToQueuedInfractionParametersKey(consumerId), bz) + + return nil +} + +// DeleteQueuedInfractionParameters deletes the queued infraction parameters associated with this consumer id +func (k Keeper) DeleteQueuedInfractionParameters(ctx sdk.Context, consumerId string) { + store := ctx.KVStore(k.storeKey) + store.Delete(types.ConsumerIdToQueuedInfractionParametersKey(consumerId)) +} + +// HasQueuedInfractionParameters checks if there is the queued infraction parameters associated with this consumer id +func (k Keeper) HasQueuedInfractionParameters(ctx sdk.Context, consumerId string) bool { + store := ctx.KVStore(k.storeKey) + return store.Has(types.ConsumerIdToQueuedInfractionParametersKey(consumerId)) +} + +// GetFromInfractionUpdateSchedule returns all the consumer ids of chains stored under this update time +func (k Keeper) GetFromInfractionUpdateSchedule(ctx sdk.Context, updateTime time.Time) (types.ConsumerIds, error) { + return k.getConsumerIdsBasedOnTime(ctx, types.InfractionScheduledTimeToConsumerIdsKey, updateTime) +} + +// AddToInfractionUpdateSchedule appends a consumer id to the timestamp-scheduled update list +func (k Keeper) AddToInfractionUpdateSchedule(ctx sdk.Context, consumerId string, updateTime time.Time) error { + return k.appendConsumerIdOnTime(ctx, consumerId, types.InfractionScheduledTimeToConsumerIdsKey, updateTime) +} + +// RemoveFromInfractionUpdateSchedule removes a consumer id from the timestamp-scheduled update list using specific timestamp +func (k Keeper) RemoveFromInfractionUpdateSchedule(ctx sdk.Context, consumerId string, updateTime time.Time) error { + return k.removeConsumerIdFromTime(ctx, consumerId, types.InfractionScheduledTimeToConsumerIdsKey, updateTime) +} + +// GetConsumerInfractionUpdateTime gets the time when the consumer's infraction parameters are scheduled for update +func (k Keeper) GetConsumerInfractionUpdateTime(ctx sdk.Context, consumerId string) (time.Time, error) { + store := ctx.KVStore(k.storeKey) + + iterator := storetypes.KVStorePrefixIterator(store, []byte{types.InfractionScheduledTimeToConsumerIdsKeyPrefix()}) + defer iterator.Close() + + for ; iterator.Valid(); iterator.Next() { + // parse the scheduled time from the key + ts, err := types.ParseTime(types.InfractionScheduledTimeToConsumerIdsKeyPrefix(), iterator.Key()) + if err != nil { + return time.Time{}, fmt.Errorf("failed to parse scheduled time: %w", err) + } + + // get consumer ids associated with the scheduled time + consumerIds, err := k.GetFromInfractionUpdateSchedule(ctx, ts) + if err != nil { + return time.Time{}, fmt.Errorf("failed to get record from time queue: %w", err) + } + + // check if the target consumer id is in the list + for _, id := range consumerIds.Ids { + if id == consumerId { + // remove the consumer id from the schedule and return + if err := k.RemoveFromInfractionUpdateSchedule(ctx, consumerId, ts); err != nil { + return time.Time{}, fmt.Errorf("failed to remove consumer id from time queue: %w", err) + } + return ts, nil + } + } + } + + // consumer id was not found + return time.Time{}, fmt.Errorf("consumer id %s not found in scheduled time queue", consumerId) +} + +// DeleteAllConsumersFromInfractionUpdateSchedule deletes all consumer ids that should update infraction parameter at this specific update time +func (k Keeper) DeleteAllConsumersFromInfractionUpdateSchedule(ctx sdk.Context, updateTime time.Time) { + store := ctx.KVStore(k.storeKey) + store.Delete(types.InfractionScheduledTimeToConsumerIdsKey(updateTime)) +} + +// RemoveConsumerInfractionQueuedData consumer intraction data from both queued parameters and time queue stores +func (k Keeper) RemoveConsumerInfractionQueuedData(ctx sdk.Context, consumerId string) { + if k.HasQueuedInfractionParameters(ctx, consumerId) { + // delete queued parameters + k.DeleteQueuedInfractionParameters(ctx, consumerId) + + scheduledTime, err := k.GetConsumerInfractionUpdateTime(ctx, consumerId) + if err != nil { + return + } + // delete consumer id from time queue + err = k.RemoveFromInfractionUpdateSchedule(ctx, consumerId, scheduledTime) + if err != nil { + return + } + } +} + +// UpdateQueuedInfractionParams updates the infraction parameters in the time queue. +// Parameters for the specific consumer already exist in the queue: +// - If the new parameters are the same as the current queued parameters, the existing entry is removed to cancel the update. +// - If the new parameters are different, the existing entry is removed and new entry is added to the queue to schedule the update. +// +// Parameters for the specific consumer do not exist in the update queue and the new parameters differ from the consumer current infraction parameters, +// a new entry is added to the queue to schedule the update. +func (k Keeper) UpdateQueuedInfractionParams(ctx sdk.Context, consumerId string, newInfractionParams types.InfractionParameters) error { + // remove the queued entry for this consumer ID if it exists + k.RemoveConsumerInfractionQueuedData(ctx, consumerId) + + // get the current infraction parameters that must exist for the given consumer id + currentInfractionParams, err := k.GetInfractionParameters(ctx, consumerId) + if err != nil { + return fmt.Errorf("failed to get current infraction parameters for consumer id (%s): %w", consumerId, err) + } + + // if the new parameters are identical to the current parameters, cancel the update. + // no action since any existing entry has already been removed above + if compareInfractionParameters(currentInfractionParams, newInfractionParams) { + return nil + } + + // if the new parameters are different from the current queued parameters, queue the new infraction parameters to be applied after unbonding period + err = k.SetQueuedInfractionParameters(ctx, consumerId, newInfractionParams) + if err != nil { + return err + } + + // infraction parameters for this consumer will be updated once unbonding period elapses + unbondingPeriod, err := k.stakingKeeper.UnbondingTime(ctx) + if err != nil { + return err + } + + updateTime := ctx.BlockTime().Add(unbondingPeriod) + err = k.AddToInfractionUpdateSchedule(ctx, consumerId, updateTime) + if err != nil { + return err + } + + return nil +} + +// BeginBlockUpdateInfractionParameters updates infraction parameters for consumer chain for which the update time has passed +func (k Keeper) BeginBlockUpdateInfractionParameters(ctx sdk.Context) error { + consumerIds, err := k.ConsumeIdsFromTimeQueue( + ctx, + types.InfractionScheduledTimeToConsumerIdsKeyPrefix(), + k.GetFromInfractionUpdateSchedule, + k.DeleteAllConsumersFromInfractionUpdateSchedule, + k.AddToInfractionUpdateSchedule, + 200, + ) + if err != nil { + return err + } + + for _, consumerId := range consumerIds { + // get queued consumer infraction parameters that needs to be applied + queuedInfractionParams, err := k.GetQueuedInfractionParameters(ctx, consumerId) + if err != nil { + return err + } + + // update consumer infraction parameters + err = k.SetInfractionParameters(ctx, consumerId, queuedInfractionParams) + if err != nil { + return err + } + + k.DeleteQueuedInfractionParameters(ctx, consumerId) + } + + return nil +} + +func compareInfractionParameters(param1, param2 types.InfractionParameters) bool { + // Compare both DoubleSign and Downtime parameters + return compareSlashJailParameters(param1.DoubleSign, param2.DoubleSign) && + compareSlashJailParameters(param1.Downtime, param2.Downtime) +} + +func compareSlashJailParameters(param1, param2 *types.SlashJailParameters) bool { + if param1 == nil && param2 == nil { + return true + } + if param1 == nil || param2 == nil { + return false + } + if !param1.SlashFraction.Equal(param2.SlashFraction) { + return false + } + + return param1.JailDuration == param2.JailDuration +} diff --git a/x/ccv/provider/keeper/msg_server.go b/x/ccv/provider/keeper/msg_server.go index d55a8a1201..c82f901154 100644 --- a/x/ccv/provider/keeper/msg_server.go +++ b/x/ccv/provider/keeper/msg_server.go @@ -403,6 +403,28 @@ func (k msgServer) CreateConsumer(goCtx context.Context, msg *types.MsgCreateCon "cannot set power shaping parameters") } + // infraction parameters are optional and hence could be nil; + // in that case, all slashing and jailing parameters are the same as on the provider + infractionParameters, err := types.DefaultConsumerInfractionParameters(ctx, k.slashingKeeper) + if err != nil { + return &resp, errorsmod.Wrapf(types.ErrInvalidConsumerInfractionParameters, + "cannot get default consumer infraction parameters: %s", err.Error()) + } + + if msg.InfractionParameters != nil { + if msg.InfractionParameters.DoubleSign != nil { + infractionParameters.DoubleSign = msg.InfractionParameters.DoubleSign + } + if msg.InfractionParameters.Downtime != nil { + infractionParameters.Downtime = msg.InfractionParameters.Downtime + } + } + + if err := k.Keeper.SetInfractionParameters(ctx, consumerId, infractionParameters); err != nil { + return &resp, errorsmod.Wrapf(types.ErrInvalidConsumerInfractionParameters, + "cannot set consumer infraction parameters: %s", err.Error()) + } + if spawnTime, initialized := k.Keeper.InitializeConsumer(ctx, consumerId); initialized { if err := k.Keeper.PrepareConsumerForLaunch(ctx, consumerId, time.Time{}, spawnTime); err != nil { return &resp, errorsmod.Wrapf(ccvtypes.ErrInvalidConsumerState, @@ -587,6 +609,39 @@ func (k msgServer) UpdateConsumer(goCtx context.Context, msg *types.MsgUpdateCon sdk.NewAttribute(types.AttributeConsumerTopN, fmt.Sprintf("%v", msg.PowerShapingParameters.Top_N))) } + if msg.InfractionParameters != nil { + // get the current infraction parameters for the given consumer id + currentInfractionParams, err := k.GetInfractionParameters(ctx, consumerId) + if err != nil { + return &resp, errorsmod.Wrapf(ccvtypes.ErrInvalidConsumerState, + "cannot get consumer previous infraction parameters") + } + + // if the double sign or downtime slashing parameters are not set in the MsgUpdateConsumer, + // retain the current values by assigning them to the new infraction parameters + newInfractionParams := *msg.InfractionParameters + if msg.InfractionParameters.DoubleSign == nil { + newInfractionParams.DoubleSign = currentInfractionParams.DoubleSign + } + if msg.InfractionParameters.Downtime == nil { + newInfractionParams.Downtime = currentInfractionParams.Downtime + } + + // depending on the consumer phase, set the new infraction parameters either immediately + // or add them to the time queue to be updated after the unbonding period + if k.IsConsumerPrelaunched(ctx, consumerId) { + if err = k.Keeper.SetInfractionParameters(ctx, consumerId, newInfractionParams); err != nil { + return &resp, errorsmod.Wrapf(types.ErrInvalidConsumerInfractionParameters, + "cannot set infraction parameters") + } + } + if err = k.Keeper.UpdateQueuedInfractionParams(ctx, consumerId, newInfractionParams); err != nil { + return &resp, errorsmod.Wrapf(types.ErrInvalidConsumerInfractionParameters, + "cannot update consumer infraction time queue") + } + + } + // A Top N cannot change its owner address to something different from the gov module if the chain // remains a Top N chain. currentOwnerAddress, err := k.Keeper.GetConsumerOwnerAddress(ctx, consumerId) diff --git a/x/ccv/provider/keeper/relay.go b/x/ccv/provider/keeper/relay.go index f0fcb0f75a..fb40638900 100644 --- a/x/ccv/provider/keeper/relay.go +++ b/x/ccv/provider/keeper/relay.go @@ -478,6 +478,18 @@ func (k Keeper) HandleSlashPacket(ctx sdk.Context, consumerId string, data ccv.S // TODO: consumer cons address should be accepted here k.AppendSlashAck(ctx, consumerId, consumerConsAddr.String()) + infractionParams, err := k.GetInfractionParameters(ctx, consumerId) + if err != nil { + k.Logger(ctx).Error("failed to get infraction parameters", "err", err.Error()) + return + } + + // slash validator + if err = k.SlashValidator(ctx, providerConsAddr, infractionParams.Downtime, stakingtypes.Infraction_INFRACTION_DOWNTIME); err != nil { + k.Logger(ctx).Error("failed to slash vaidator", providerConsAddr.ToSdkConsAddr().String(), "err", err.Error()) + return + } + // jail validator if !validator.IsJailed() { err := k.stakingKeeper.Jail(ctx, providerConsAddr.ToSdkConsAddr()) @@ -486,12 +498,8 @@ func (k Keeper) HandleSlashPacket(ctx sdk.Context, consumerId string, data ccv.S return } k.Logger(ctx).Info("HandleSlashPacket - validator jailed", "provider cons addr", providerConsAddr.String()) - jailDuration, err := k.slashingKeeper.DowntimeJailDuration(ctx) - if err != nil { - k.Logger(ctx).Error("failed to get jail duration", "err", err.Error()) - return - } - jailEndTime := ctx.BlockTime().Add(jailDuration) + + jailEndTime := ctx.BlockTime().Add(infractionParams.Downtime.JailDuration) err = k.slashingKeeper.JailUntil(ctx, providerConsAddr.ToSdkConsAddr(), jailEndTime) if err != nil { k.Logger(ctx).Error("failed to set jail duration", "err", err.Error()) diff --git a/x/ccv/provider/module.go b/x/ccv/provider/module.go index 027fd2ac72..233d0b36c9 100644 --- a/x/ccv/provider/module.go +++ b/x/ccv/provider/module.go @@ -182,6 +182,10 @@ func (am AppModule) BeginBlock(ctx context.Context) error { if err := am.keeper.BeginBlockRemoveConsumers(sdkCtx); err != nil { return err } + // Update the infraction parameters for consumer chains that are scheduled for an update + if err := am.keeper.BeginBlockUpdateInfractionParameters(sdkCtx); err != nil { + return err + } // Check for replenishing slash meter before any slash packets are processed for this block am.keeper.BeginBlockCIS(sdkCtx) // BeginBlock logic needed for the Reward Distribution sub-protocol diff --git a/x/ccv/provider/types/errors.go b/x/ccv/provider/types/errors.go index 44ef35df15..cd1c0770f3 100644 --- a/x/ccv/provider/types/errors.go +++ b/x/ccv/provider/types/errors.go @@ -40,4 +40,5 @@ var ( ErrInvalidMsgSetConsumerCommissionRate = errorsmod.Register(ModuleName, 51, "invalid set consumer commission rate message") ErrInvalidMsgChangeRewardDenoms = errorsmod.Register(ModuleName, 52, "invalid change reward denoms message") ErrInvalidAllowlistedRewardDenoms = errorsmod.Register(ModuleName, 53, "invalid allowlisted reward denoms") + ErrInvalidConsumerInfractionParameters = errorsmod.Register(ModuleName, 54, "invalid consumer infraction parameters") ) diff --git a/x/ccv/provider/types/keys.go b/x/ccv/provider/types/keys.go index 2e712b3e6e..a2798da0af 100644 --- a/x/ccv/provider/types/keys.go +++ b/x/ccv/provider/types/keys.go @@ -156,6 +156,12 @@ const ( ConsumerRewardsAllocationByDenomKeyName = "ConsumerRewardsAllocationByDenomKey" PrioritylistKeyName = "PrioritylistKey" + + ConsumerIdToInfractionParametersKeyName = "ConsumerIdToInfractionParametersKey" + + ConsumerIdToQueuedInfractionParametersKeyName = "ConsumerIdToQueuedInfractionParametersKeyName" + + InfractionScheduledTimeToConsumerIdsKeyName = "InfractionScheduledTimeToConsumerIdsKeyName" ) // getKeyPrefixes returns a constant map of all the byte prefixes for existing keys @@ -397,6 +403,15 @@ func getKeyPrefixes() map[string]byte { // prioritylisted. PrioritylistKeyName: 56, + // ConsumerIdToInfractionParametersKeyName is the key for storing slashing and jailing infraction parameters for a specific consumer chain + ConsumerIdToInfractionParametersKeyName: 57, + + // ConsumerIdToQueuedInfractionParametersKeyName is the key for storing queued infraction parameters that will be used to update consumer infraction parameters + ConsumerIdToQueuedInfractionParametersKeyName: 58, + + // InfractionScheduledTimeToConsumerIdsKeyName is the key for storing time when the infraction parameters will be updated for the specific consumer + InfractionScheduledTimeToConsumerIdsKeyName: 59, + // NOTE: DO NOT ADD NEW BYTE PREFIXES HERE WITHOUT ADDING THEM TO TestPreserveBytePrefix() IN keys_test.go } } @@ -800,6 +815,41 @@ func ConsumerRewardsAllocationByDenomKey(consumerId string, denom string) []byte return append(StringIdWithLenKey(ConsumerRewardsAllocationByDenomKeyPrefix(), consumerId), []byte(denom)...) } +// ConsumerIdToInfractionParametersKeyPrefix returns the key prefix for storing consumer infraction parameters +func ConsumerIdToInfractionParametersKeyPrefix() byte { + return mustGetKeyPrefix(ConsumerIdToInfractionParametersKeyName) +} + +// ConsumerIdToInfractionParametersKey returns the key used to store the infraction parameters that corresponds to this consumer id +func ConsumerIdToInfractionParametersKey(consumerId string) []byte { + return StringIdWithLenKey(ConsumerIdToInfractionParametersKeyPrefix(), consumerId) +} + +// ConsumerIdToQueuedInfractionParametersKeyPrefix returns the key prefix for storing queued consumer infraction parameters that will be applied after due time +func ConsumerIdToQueuedInfractionParametersKeyPrefix() byte { + return mustGetKeyPrefix(ConsumerIdToQueuedInfractionParametersKeyName) +} + +// ConsumerIdToQueuedInfractionParametersKey returns the key used to store the queued consumer infraction parameters that will be applied after due time +func ConsumerIdToQueuedInfractionParametersKey(consumerId string) []byte { + return StringIdWithLenKey(ConsumerIdToQueuedInfractionParametersKeyPrefix(), consumerId) +} + +// InfractionScheduledTimeToConsumerIdsKeyPrefix returns the key prefix for storing pending consumers ids that needs to update their infraction parameters at the specific time +func InfractionScheduledTimeToConsumerIdsKeyPrefix() byte { + return mustGetKeyPrefix(InfractionScheduledTimeToConsumerIdsKeyName) +} + +// InfractionScheduledTimeToConsumerIdsKey returns the key prefix for storing pending consumers ids that needs to update their infraction parameters at the specific time +func InfractionScheduledTimeToConsumerIdsKey(updateTime time.Time) []byte { + return ccvtypes.AppendMany( + // append the prefix + []byte{InfractionScheduledTimeToConsumerIdsKeyPrefix()}, + // append the time + sdk.FormatTimeBytes(updateTime), + ) +} + // NOTE: DO NOT ADD FULLY DEFINED KEY FUNCTIONS WITHOUT ADDING THEM TO getAllFullyDefinedKeys() IN keys_test.go // diff --git a/x/ccv/provider/types/keys_test.go b/x/ccv/provider/types/keys_test.go index de8156c8ec..e931f6a63a 100644 --- a/x/ccv/provider/types/keys_test.go +++ b/x/ccv/provider/types/keys_test.go @@ -149,6 +149,12 @@ func TestPreserveBytePrefix(t *testing.T) { i++ require.Equal(t, byte(56), providertypes.PrioritylistKeyPrefix()) i++ + require.Equal(t, byte(57), providertypes.ConsumerIdToInfractionParametersKeyPrefix()) + i++ + require.Equal(t, byte(58), providertypes.ConsumerIdToQueuedInfractionParametersKeyPrefix()) + i++ + require.Equal(t, byte(59), providertypes.InfractionScheduledTimeToConsumerIdsKeyPrefix()) + i++ prefixes := providertypes.GetAllKeyPrefixes() require.Equal(t, len(prefixes), i) @@ -219,6 +225,9 @@ func getAllFullyDefinedKeys() [][]byte { providertypes.ConsumerIdToAllowlistedRewardDenomKey("13"), providertypes.ConsumerRewardsAllocationByDenomKey("13", "denom"), providertypes.PrioritylistKey("13", providertypes.NewProviderConsAddress([]byte{0x05})), + providertypes.ConsumerIdToInfractionParametersKey("13"), + providertypes.ConsumerIdToQueuedInfractionParametersKey("13"), + providertypes.InfractionScheduledTimeToConsumerIdsKey(time.Time{}), } } diff --git a/x/ccv/provider/types/msg.go b/x/ccv/provider/types/msg.go index bfc433126a..ae6b16e477 100644 --- a/x/ccv/provider/types/msg.go +++ b/x/ccv/provider/types/msg.go @@ -283,7 +283,7 @@ func (msg MsgSetConsumerCommissionRate) ValidateBasic() error { // NewMsgCreateConsumer creates a new MsgCreateConsumer instance func NewMsgCreateConsumer(submitter, chainId string, metadata ConsumerMetadata, initializationParameters *ConsumerInitializationParameters, powerShapingParameters *PowerShapingParameters, - allowlistedRewardDenoms *AllowlistedRewardDenoms, + allowlistedRewardDenoms *AllowlistedRewardDenoms, infractionParameters *InfractionParameters, ) (*MsgCreateConsumer, error) { return &MsgCreateConsumer{ Submitter: submitter, @@ -292,6 +292,7 @@ func NewMsgCreateConsumer(submitter, chainId string, metadata ConsumerMetadata, InitializationParameters: initializationParameters, PowerShapingParameters: powerShapingParameters, AllowlistedRewardDenoms: allowlistedRewardDenoms, + InfractionParameters: infractionParameters, }, nil } @@ -346,6 +347,12 @@ func (msg MsgCreateConsumer) ValidateBasic() error { } } + if msg.InfractionParameters != nil { + if err := ValidateInfractionParameters(*msg.InfractionParameters); err != nil { + return errorsmod.Wrapf(ErrInvalidMsgCreateConsumer, "InfractionParameters: %s", err.Error()) + } + } + if msg.AllowlistedRewardDenoms != nil { if err := ValidateAllowlistedRewardDenoms(*msg.AllowlistedRewardDenoms); err != nil { return errorsmod.Wrapf(ErrInvalidMsgCreateConsumer, "AllowlistedRewardDenoms: %s", err.Error()) @@ -358,7 +365,7 @@ func (msg MsgCreateConsumer) ValidateBasic() error { // NewMsgUpdateConsumer creates a new MsgUpdateConsumer instance func NewMsgUpdateConsumer(owner, consumerId, ownerAddress string, metadata *ConsumerMetadata, initializationParameters *ConsumerInitializationParameters, powerShapingParameters *PowerShapingParameters, - allowlistedRewardDenoms *AllowlistedRewardDenoms, newChainId string, + allowlistedRewardDenoms *AllowlistedRewardDenoms, newChainId string, infractionParameters *InfractionParameters, ) (*MsgUpdateConsumer, error) { return &MsgUpdateConsumer{ Owner: owner, @@ -369,6 +376,7 @@ func NewMsgUpdateConsumer(owner, consumerId, ownerAddress string, metadata *Cons PowerShapingParameters: powerShapingParameters, AllowlistedRewardDenoms: allowlistedRewardDenoms, NewChainId: newChainId, + InfractionParameters: infractionParameters, }, nil } @@ -398,6 +406,12 @@ func (msg MsgUpdateConsumer) ValidateBasic() error { } } + if msg.InfractionParameters != nil { + if err := ValidateInfractionParameters(*msg.InfractionParameters); err != nil { + return errorsmod.Wrapf(ErrInvalidMsgUpdateConsumer, "InfractionParameters: %s", err.Error()) + } + } + if msg.AllowlistedRewardDenoms != nil { if err := ValidateAllowlistedRewardDenoms(*msg.AllowlistedRewardDenoms); err != nil { return errorsmod.Wrapf(ErrInvalidMsgUpdateConsumer, "AllowlistedRewardDenoms: %s", err.Error()) @@ -611,6 +625,29 @@ func ValidateInitializationParameters(initializationParameters ConsumerInitializ return nil } +// ValidateInfractionParameters validates that all the provided infraction parameters are in the expected range +func ValidateInfractionParameters(initializationParameters InfractionParameters) error { + if initializationParameters.DoubleSign != nil { + if initializationParameters.DoubleSign.JailDuration < 0 { + return errorsmod.Wrap(ErrInvalidConsumerInfractionParameters, "DoubleSign.JailDuration cannot be negative") + } + if err := ccvtypes.ValidateFraction(initializationParameters.DoubleSign.SlashFraction); err != nil { + return errorsmod.Wrapf(ErrInvalidConsumerInfractionParameters, "DoubleSign.SlashFraction: %s", err.Error()) + } + } + + if initializationParameters.Downtime != nil { + if initializationParameters.Downtime.JailDuration < 0 { + return errorsmod.Wrap(ErrInvalidConsumerInfractionParameters, "Downtime.JailDuration cannot be negative") + } + if err := ccvtypes.ValidateFraction(initializationParameters.Downtime.SlashFraction); err != nil { + return errorsmod.Wrapf(ErrInvalidConsumerInfractionParameters, "Downtime.SlashFraction: %s", err.Error()) + } + } + + return nil +} + func ValidateByteSlice(hash []byte, maxLength int) error { if len(hash) > maxLength { return fmt.Errorf("hash is too long; got: %d, max: %d", len(hash), maxLength) diff --git a/x/ccv/provider/types/msg_test.go b/x/ccv/provider/types/msg_test.go index 1c826d350d..9f13d8d257 100644 --- a/x/ccv/provider/types/msg_test.go +++ b/x/ccv/provider/types/msg_test.go @@ -5,6 +5,7 @@ import ( "testing" "time" + "cosmossdk.io/math" clienttypes "github.com/cosmos/ibc-go/v8/modules/core/02-client/types" "github.com/stretchr/testify/require" @@ -430,49 +431,105 @@ func TestMsgCreateConsumerValidateBasic(t *testing.T) { name string chainId string powerShapingParameters *types.PowerShapingParameters + infractionParameters *types.InfractionParameters expPass bool }{ { "empty chain id", "", nil, // no power-shaping parameters + nil, false, }, { "empty chain id after trimming", " ", nil, // no power-shaping parameters + nil, false, }, { "neutron chain id that cannot be reused", "neutron-1", nil, // no power-shaping parameters + nil, false, }, { "stride chain id that cannot be reused", "stride-1", nil, // no power-shaping parameters + nil, false, }, { "valid chain id", "somechain-1", nil, // no power-shaping parameters + &types.InfractionParameters{ + DoubleSign: &types.SlashJailParameters{ + JailDuration: time.Duration(1<<63 - 1), // max duration + SlashFraction: math.LegacyNewDecWithPrec(5, 2), // 0.05 + }, + Downtime: &types.SlashJailParameters{ + JailDuration: 600 * time.Second, + SlashFraction: math.LegacyNewDec(0), + }, + }, // valid infraction params true, }, { "valid chain id and invalid power-shaping parameters", "somechain-1", &types.PowerShapingParameters{Top_N: 51}, // TopN cannot be > 0 in MsgCreateConsumer + nil, + false, + }, + { + "invalid infraction downtime jailing parameters", + "somechain-1", + nil, + &types.InfractionParameters{Downtime: &types.SlashJailParameters{ + JailDuration: -1, + SlashFraction: math.LegacyNewDec(0), + }}, + false, + }, + { + "invalid infraction downtime slashing parameters", + "somechain-1", + nil, + &types.InfractionParameters{Downtime: &types.SlashJailParameters{ + JailDuration: 600 * time.Second, + SlashFraction: math.LegacyNewDec(2), + }}, + false, + }, + { + "invalid infraction double sign jailing parameters", + "somechain-1", + nil, + &types.InfractionParameters{Downtime: &types.SlashJailParameters{ + JailDuration: -1, + SlashFraction: math.LegacyNewDec(0), + }}, + false, + }, + { + "invalid infraction double sign slashing parameters", + "somechain-1", + nil, + &types.InfractionParameters{Downtime: &types.SlashJailParameters{ + JailDuration: 600 * time.Second, + SlashFraction: math.LegacyNewDec(2), + }}, false, }, } for _, tc := range testCases { validConsumerMetadata := types.ConsumerMetadata{Name: "name", Description: "description", Metadata: "metadata"} - msg, err := types.NewMsgCreateConsumer("submitter", tc.chainId, validConsumerMetadata, nil, tc.powerShapingParameters, nil) + msg, err := types.NewMsgCreateConsumer("submitter", tc.chainId, validConsumerMetadata, nil, tc.powerShapingParameters, nil, tc.infractionParameters) require.NoError(t, err) err = msg.ValidateBasic() if tc.expPass { @@ -556,7 +613,7 @@ func TestMsgUpdateConsumerValidateBasic(t *testing.T) { for _, tc := range testCases { // TODO (PERMISSIONLESS) add more tests - msg, _ := types.NewMsgUpdateConsumer("", "0", "cosmos1p3ucd3ptpw902fluyjzhq3ffgq4ntddac9sa3s", nil, nil, &tc.powerShapingParameters, nil, tc.newChainId) + msg, _ := types.NewMsgUpdateConsumer("", "0", "cosmos1p3ucd3ptpw902fluyjzhq3ffgq4ntddac9sa3s", nil, nil, &tc.powerShapingParameters, nil, tc.newChainId, nil) err := msg.ValidateBasic() if tc.expPass { require.NoError(t, err, "valid case: %s should not return error. got %w", tc.name, err) diff --git a/x/ccv/provider/types/provider.go b/x/ccv/provider/types/provider.go index 9fd3e32718..90f1173ffd 100644 --- a/x/ccv/provider/types/provider.go +++ b/x/ccv/provider/types/provider.go @@ -1,8 +1,10 @@ package types import ( + "context" "time" + "cosmossdk.io/math" clienttypes "github.com/cosmos/ibc-go/v8/modules/core/02-client/types" ccv "github.com/cosmos/interchain-security/v6/x/ccv/types" @@ -26,3 +28,26 @@ func DefaultConsumerInitializationParameters() ConsumerInitializationParameters DistributionTransmissionChannel: "", } } + +func DefaultConsumerInfractionParameters(ctx context.Context, slashingKeeper ccv.SlashingKeeper) (InfractionParameters, error) { + jailDuration, err := slashingKeeper.DowntimeJailDuration(ctx) + if err != nil { + return InfractionParameters{}, err + } + + doubleSignSlashingFraction, err := slashingKeeper.SlashFractionDoubleSign(ctx) + if err != nil { + return InfractionParameters{}, err + } + + return InfractionParameters{ + DoubleSign: &SlashJailParameters{ + JailDuration: time.Duration(1<<63 - 1), // the largest value a time.Duration can hold 9223372036854775807 (approximately 292 years) + SlashFraction: doubleSignSlashingFraction, + }, + Downtime: &SlashJailParameters{ + JailDuration: jailDuration, + SlashFraction: math.LegacyNewDec(0), + }, + }, nil +} diff --git a/x/ccv/provider/types/provider.pb.go b/x/ccv/provider/types/provider.pb.go index ae7402200e..eb9b7a61ec 100644 --- a/x/ccv/provider/types/provider.pb.go +++ b/x/ccv/provider/types/provider.pb.go @@ -4,6 +4,7 @@ package types import ( + cosmossdk_io_math "cosmossdk.io/math" types1 "cosmossdk.io/x/evidence/types" fmt "fmt" crypto "github.com/cometbft/cometbft/proto/tendermint/crypto" @@ -1886,6 +1887,104 @@ func (m *AllowlistedRewardDenoms) GetDenoms() []string { return nil } +type InfractionParameters struct { + DoubleSign *SlashJailParameters `protobuf:"bytes,1,opt,name=double_sign,json=doubleSign,proto3" json:"double_sign,omitempty"` + Downtime *SlashJailParameters `protobuf:"bytes,2,opt,name=downtime,proto3" json:"downtime,omitempty"` +} + +func (m *InfractionParameters) Reset() { *m = InfractionParameters{} } +func (m *InfractionParameters) String() string { return proto.CompactTextString(m) } +func (*InfractionParameters) ProtoMessage() {} +func (*InfractionParameters) Descriptor() ([]byte, []int) { + return fileDescriptor_f22ec409a72b7b72, []int{24} +} +func (m *InfractionParameters) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *InfractionParameters) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_InfractionParameters.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 *InfractionParameters) XXX_Merge(src proto.Message) { + xxx_messageInfo_InfractionParameters.Merge(m, src) +} +func (m *InfractionParameters) XXX_Size() int { + return m.Size() +} +func (m *InfractionParameters) XXX_DiscardUnknown() { + xxx_messageInfo_InfractionParameters.DiscardUnknown(m) +} + +var xxx_messageInfo_InfractionParameters proto.InternalMessageInfo + +func (m *InfractionParameters) GetDoubleSign() *SlashJailParameters { + if m != nil { + return m.DoubleSign + } + return nil +} + +func (m *InfractionParameters) GetDowntime() *SlashJailParameters { + if m != nil { + return m.Downtime + } + return nil +} + +type SlashJailParameters struct { + SlashFraction cosmossdk_io_math.LegacyDec `protobuf:"bytes,1,opt,name=slash_fraction,json=slashFraction,proto3,customtype=cosmossdk.io/math.LegacyDec" json:"slash_fraction"` + // for permanent jailing use 9223372036854775807 which is the largest value a time.Duration can hold (approximately 292 years) + JailDuration time.Duration `protobuf:"bytes,8,opt,name=jail_duration,json=jailDuration,proto3,stdduration" json:"jail_duration"` +} + +func (m *SlashJailParameters) Reset() { *m = SlashJailParameters{} } +func (m *SlashJailParameters) String() string { return proto.CompactTextString(m) } +func (*SlashJailParameters) ProtoMessage() {} +func (*SlashJailParameters) Descriptor() ([]byte, []int) { + return fileDescriptor_f22ec409a72b7b72, []int{25} +} +func (m *SlashJailParameters) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *SlashJailParameters) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_SlashJailParameters.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 *SlashJailParameters) XXX_Merge(src proto.Message) { + xxx_messageInfo_SlashJailParameters.Merge(m, src) +} +func (m *SlashJailParameters) XXX_Size() int { + return m.Size() +} +func (m *SlashJailParameters) XXX_DiscardUnknown() { + xxx_messageInfo_SlashJailParameters.DiscardUnknown(m) +} + +var xxx_messageInfo_SlashJailParameters proto.InternalMessageInfo + +func (m *SlashJailParameters) GetJailDuration() time.Duration { + if m != nil { + return m.JailDuration + } + return 0 +} + func init() { proto.RegisterEnum("interchain_security.ccv.provider.v1.ConsumerPhase", ConsumerPhase_name, ConsumerPhase_value) proto.RegisterType((*ConsumerAdditionProposal)(nil), "interchain_security.ccv.provider.v1.ConsumerAdditionProposal") @@ -1912,6 +2011,8 @@ func init() { proto.RegisterType((*PowerShapingParameters)(nil), "interchain_security.ccv.provider.v1.PowerShapingParameters") proto.RegisterType((*ConsumerIds)(nil), "interchain_security.ccv.provider.v1.ConsumerIds") proto.RegisterType((*AllowlistedRewardDenoms)(nil), "interchain_security.ccv.provider.v1.AllowlistedRewardDenoms") + proto.RegisterType((*InfractionParameters)(nil), "interchain_security.ccv.provider.v1.InfractionParameters") + proto.RegisterType((*SlashJailParameters)(nil), "interchain_security.ccv.provider.v1.SlashJailParameters") } func init() { @@ -1919,150 +2020,158 @@ func init() { } var fileDescriptor_f22ec409a72b7b72 = []byte{ - // 2280 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x59, 0xcd, 0x6f, 0x1b, 0xc7, - 0xd9, 0xd7, 0x8a, 0x94, 0x44, 0x0e, 0xf5, 0x41, 0x8d, 0x1d, 0x99, 0x92, 0x15, 0x92, 0xde, 0xbc, - 0x0e, 0xf8, 0xda, 0x35, 0x19, 0x29, 0x40, 0x61, 0xb8, 0x0d, 0x0c, 0x9a, 0xa4, 0x6d, 0xfa, 0x43, - 0x66, 0x97, 0xb4, 0x02, 0xb8, 0x87, 0xc5, 0x70, 0x77, 0x44, 0x4e, 0xb5, 0xbb, 0xb3, 0xde, 0x19, - 0xae, 0xcd, 0x1e, 0x7a, 0x0e, 0x0a, 0x14, 0x48, 0x6f, 0x41, 0x2f, 0x0d, 0xd0, 0x4b, 0xd1, 0x53, - 0x0f, 0x45, 0xfe, 0x80, 0x9e, 0xd2, 0x02, 0x05, 0xd2, 0x5b, 0x4f, 0x49, 0x61, 0x1f, 0x7a, 0x28, - 0xd0, 0x9e, 0x7b, 0x2b, 0x66, 0xf6, 0x83, 0x4b, 0x7d, 0x99, 0x86, 0xed, 0x5e, 0xa4, 0x9d, 0x79, - 0x7e, 0xcf, 0x33, 0xcf, 0x33, 0xf3, 0x7c, 0xcd, 0x10, 0xec, 0x12, 0x87, 0x63, 0xcf, 0x18, 0x22, - 0xe2, 0xe8, 0x0c, 0x1b, 0x23, 0x8f, 0xf0, 0x71, 0xcd, 0x30, 0xfc, 0x9a, 0xeb, 0x51, 0x9f, 0x98, - 0xd8, 0xab, 0xf9, 0x3b, 0xf1, 0x77, 0xd5, 0xf5, 0x28, 0xa7, 0xf0, 0x83, 0x13, 0x78, 0xaa, 0x86, - 0xe1, 0x57, 0x63, 0x9c, 0xbf, 0xb3, 0xb5, 0x8e, 0x6c, 0xe2, 0xd0, 0x9a, 0xfc, 0x1b, 0xf0, 0x6d, - 0x15, 0x0d, 0xca, 0x6c, 0xca, 0x6a, 0x7d, 0xc4, 0x70, 0xcd, 0xdf, 0xe9, 0x63, 0x8e, 0x76, 0x6a, - 0x06, 0x25, 0x4e, 0x48, 0xff, 0x30, 0xa4, 0x63, 0x21, 0xc4, 0x31, 0x26, 0x98, 0x68, 0x22, 0xc4, - 0x6d, 0x06, 0x38, 0x5d, 0x8e, 0x6a, 0xc1, 0x20, 0x24, 0x9d, 0x1f, 0xd0, 0x01, 0x0d, 0xe6, 0xc5, - 0x57, 0xb4, 0xf0, 0x80, 0xd2, 0x81, 0x85, 0x6b, 0x72, 0xd4, 0x1f, 0x1d, 0xd4, 0xcc, 0x91, 0x87, - 0x38, 0xa1, 0xd1, 0xc2, 0xa5, 0xa3, 0x74, 0x4e, 0x6c, 0xcc, 0x38, 0xb2, 0xdd, 0x08, 0x40, 0xfa, - 0x46, 0xcd, 0xa0, 0x1e, 0xae, 0x19, 0x16, 0xc1, 0x0e, 0x17, 0x9b, 0x12, 0x7c, 0x85, 0x80, 0x9a, - 0x00, 0x58, 0x64, 0x30, 0xe4, 0xc1, 0x34, 0xab, 0x71, 0xec, 0x98, 0xd8, 0xb3, 0x49, 0x00, 0x9e, - 0x8c, 0x42, 0x86, 0xcb, 0xa7, 0xed, 0xbb, 0xbf, 0x53, 0x7b, 0x46, 0xbc, 0xc8, 0xd4, 0xed, 0x84, - 0x18, 0xc3, 0x1b, 0xbb, 0x9c, 0xd6, 0x0e, 0xf1, 0x38, 0xb4, 0x56, 0xfd, 0x4f, 0x06, 0x14, 0x1a, - 0xd4, 0x61, 0x23, 0x1b, 0x7b, 0x75, 0xd3, 0x24, 0xc2, 0xa4, 0x8e, 0x47, 0x5d, 0xca, 0x90, 0x05, - 0xcf, 0x83, 0x05, 0x4e, 0xb8, 0x85, 0x0b, 0x4a, 0x59, 0xa9, 0x64, 0xb5, 0x60, 0x00, 0xcb, 0x20, - 0x67, 0x62, 0x66, 0x78, 0xc4, 0x15, 0xe0, 0xc2, 0xbc, 0xa4, 0x25, 0xa7, 0xe0, 0x26, 0xc8, 0x04, - 0x6a, 0x11, 0xb3, 0x90, 0x92, 0xe4, 0x25, 0x39, 0x6e, 0x9b, 0xf0, 0x0e, 0x58, 0x25, 0x0e, 0xe1, - 0x04, 0x59, 0xfa, 0x10, 0x0b, 0x63, 0x0b, 0xe9, 0xb2, 0x52, 0xc9, 0xed, 0x6e, 0x55, 0x49, 0xdf, - 0xa8, 0x8a, 0xfd, 0xa9, 0x86, 0xbb, 0xe2, 0xef, 0x54, 0xef, 0x4a, 0xc4, 0xad, 0xf4, 0xd7, 0xdf, - 0x96, 0xe6, 0xb4, 0x95, 0x90, 0x2f, 0x98, 0x84, 0x97, 0xc0, 0xf2, 0x00, 0x3b, 0x98, 0x11, 0xa6, - 0x0f, 0x11, 0x1b, 0x16, 0x16, 0xca, 0x4a, 0x65, 0x59, 0xcb, 0x85, 0x73, 0x77, 0x11, 0x1b, 0xc2, - 0x12, 0xc8, 0xf5, 0x89, 0x83, 0xbc, 0x71, 0x80, 0x58, 0x94, 0x08, 0x10, 0x4c, 0x49, 0x40, 0x03, - 0x00, 0xe6, 0xa2, 0x67, 0x8e, 0x2e, 0x0e, 0xab, 0xb0, 0x14, 0x2a, 0x12, 0x9c, 0x64, 0x35, 0x3a, - 0xc9, 0x6a, 0x2f, 0x3a, 0xc9, 0x5b, 0x19, 0xa1, 0xc8, 0xe7, 0xdf, 0x95, 0x14, 0x2d, 0x2b, 0xf9, - 0x04, 0x05, 0xee, 0x81, 0xfc, 0xc8, 0xe9, 0x53, 0xc7, 0x24, 0xce, 0x40, 0x77, 0xb1, 0x47, 0xa8, - 0x59, 0xc8, 0x48, 0x51, 0x9b, 0xc7, 0x44, 0x35, 0x43, 0xa7, 0x09, 0x24, 0x7d, 0x21, 0x24, 0xad, - 0xc5, 0xcc, 0x1d, 0xc9, 0x0b, 0x7f, 0x04, 0xa0, 0x61, 0xf8, 0x52, 0x25, 0x3a, 0xe2, 0x91, 0xc4, - 0xec, 0xec, 0x12, 0xf3, 0x86, 0xe1, 0xf7, 0x02, 0xee, 0x50, 0xe4, 0x8f, 0xc1, 0x05, 0xee, 0x21, - 0x87, 0x1d, 0x60, 0xef, 0xa8, 0x5c, 0x30, 0xbb, 0xdc, 0xf7, 0x22, 0x19, 0xd3, 0xc2, 0xef, 0x82, - 0xb2, 0x11, 0x3a, 0x90, 0xee, 0x61, 0x93, 0x30, 0xee, 0x91, 0xfe, 0x48, 0xf0, 0xea, 0x07, 0x1e, - 0x32, 0xa4, 0x8f, 0xe4, 0xa4, 0x13, 0x14, 0x23, 0x9c, 0x36, 0x05, 0xbb, 0x1d, 0xa2, 0xe0, 0x23, - 0xf0, 0x7f, 0x7d, 0x8b, 0x1a, 0x87, 0x4c, 0x28, 0xa7, 0x4f, 0x49, 0x92, 0x4b, 0xdb, 0x84, 0x31, - 0x21, 0x6d, 0xb9, 0xac, 0x54, 0x52, 0xda, 0xa5, 0x00, 0xdb, 0xc1, 0x5e, 0x33, 0x81, 0xec, 0x25, - 0x80, 0xf0, 0x1a, 0x80, 0x43, 0xc2, 0x38, 0xf5, 0x88, 0x81, 0x2c, 0x1d, 0x3b, 0xdc, 0x23, 0x98, - 0x15, 0x56, 0x24, 0xfb, 0xfa, 0x84, 0xd2, 0x0a, 0x08, 0xf0, 0x1e, 0xb8, 0x74, 0xea, 0xa2, 0xba, - 0x31, 0x44, 0x8e, 0x83, 0xad, 0xc2, 0xaa, 0x34, 0xa5, 0x64, 0x9e, 0xb2, 0x66, 0x23, 0x80, 0xc1, - 0x73, 0x60, 0x81, 0x53, 0x57, 0xdf, 0x2b, 0xac, 0x95, 0x95, 0xca, 0x8a, 0x96, 0xe6, 0xd4, 0xdd, - 0x83, 0x1f, 0x81, 0xf3, 0x3e, 0xb2, 0x88, 0x89, 0x38, 0xf5, 0x98, 0xee, 0xd2, 0x67, 0xd8, 0xd3, - 0x0d, 0xe4, 0x16, 0xf2, 0x12, 0x03, 0x27, 0xb4, 0x8e, 0x20, 0x35, 0x90, 0x0b, 0xaf, 0x80, 0xf5, - 0x78, 0x56, 0x67, 0x98, 0x4b, 0xf8, 0xba, 0x84, 0xaf, 0xc5, 0x84, 0x2e, 0xe6, 0x02, 0xbb, 0x0d, - 0xb2, 0xc8, 0xb2, 0xe8, 0x33, 0x8b, 0x30, 0x5e, 0x80, 0xe5, 0x54, 0x25, 0xab, 0x4d, 0x26, 0xe0, - 0x16, 0xc8, 0x98, 0xd8, 0x19, 0x4b, 0xe2, 0x39, 0x49, 0x8c, 0xc7, 0xf0, 0x22, 0xc8, 0xda, 0x22, - 0x89, 0x70, 0x74, 0x88, 0x0b, 0xe7, 0xcb, 0x4a, 0x25, 0xad, 0x65, 0x6c, 0xe2, 0x74, 0xc5, 0x18, - 0x56, 0xc1, 0x39, 0x29, 0x45, 0x27, 0x8e, 0x38, 0x27, 0x1f, 0xeb, 0x3e, 0xb2, 0x58, 0xe1, 0xbd, - 0xb2, 0x52, 0xc9, 0x68, 0xeb, 0x92, 0xd4, 0x0e, 0x29, 0xfb, 0xc8, 0x62, 0x37, 0x2a, 0x9f, 0x7d, - 0x59, 0x9a, 0xfb, 0xe2, 0xcb, 0xd2, 0xdc, 0x9f, 0xff, 0x70, 0x6d, 0x2b, 0xcc, 0xac, 0x03, 0xea, - 0x57, 0xc3, 0x4c, 0x5c, 0x6d, 0x50, 0x87, 0x63, 0x87, 0x17, 0x14, 0xf5, 0xaf, 0x0a, 0xb8, 0xd0, - 0x88, 0x5d, 0xc2, 0xa6, 0x3e, 0xb2, 0xde, 0x65, 0xea, 0xa9, 0x83, 0x2c, 0x13, 0x67, 0x22, 0x83, - 0x3d, 0xfd, 0x1a, 0xc1, 0x9e, 0x11, 0x6c, 0x82, 0x70, 0xa3, 0xfc, 0x4a, 0x9b, 0xfe, 0x3d, 0x0f, - 0xb6, 0x23, 0x9b, 0x1e, 0x52, 0x93, 0x1c, 0x10, 0x03, 0xbd, 0xeb, 0x9c, 0x1a, 0xfb, 0x5a, 0x7a, - 0x06, 0x5f, 0x5b, 0x78, 0x3d, 0x5f, 0x5b, 0x9c, 0xc1, 0xd7, 0x96, 0xce, 0xf2, 0xb5, 0xcc, 0x59, - 0xbe, 0x96, 0x9d, 0xcd, 0xd7, 0xc0, 0x69, 0xbe, 0x36, 0x5f, 0x50, 0xd4, 0x5f, 0x2b, 0xe0, 0x7c, - 0xeb, 0xe9, 0x88, 0xf8, 0xf4, 0x2d, 0xed, 0xf4, 0x7d, 0xb0, 0x82, 0x13, 0xf2, 0x58, 0x21, 0x55, - 0x4e, 0x55, 0x72, 0xbb, 0x97, 0xab, 0xe1, 0xc1, 0xc7, 0xad, 0x44, 0x74, 0xfa, 0xc9, 0xd5, 0xb5, - 0x69, 0x5e, 0xa9, 0xe1, 0x1f, 0x15, 0xb0, 0x25, 0xf2, 0xc2, 0x00, 0x6b, 0xf8, 0x19, 0xf2, 0xcc, - 0x26, 0x76, 0xa8, 0xcd, 0xde, 0x58, 0x4f, 0x15, 0xac, 0x98, 0x52, 0x92, 0xce, 0xa9, 0x8e, 0x4c, - 0x53, 0xea, 0x29, 0x31, 0x62, 0xb2, 0x47, 0xeb, 0xa6, 0x09, 0x2b, 0x20, 0x3f, 0xc1, 0x78, 0x22, - 0xc6, 0x84, 0xeb, 0x0b, 0xd8, 0x6a, 0x04, 0x93, 0x91, 0x87, 0x6f, 0x14, 0xcf, 0x76, 0x6d, 0xf5, - 0x9f, 0x0a, 0xc8, 0xdf, 0xb1, 0x68, 0x1f, 0x59, 0x5d, 0x0b, 0xb1, 0xa1, 0xc8, 0x99, 0x63, 0x11, - 0x52, 0x1e, 0x0e, 0x8b, 0x95, 0x54, 0x7f, 0xe6, 0x90, 0x12, 0x6c, 0xb2, 0x7c, 0xde, 0x04, 0xeb, - 0x71, 0xf9, 0x88, 0x1d, 0x5c, 0x5a, 0x7b, 0xeb, 0xdc, 0x8b, 0x6f, 0x4b, 0x6b, 0x51, 0x30, 0x35, - 0xa4, 0xb3, 0x37, 0xb5, 0x35, 0x63, 0x6a, 0xc2, 0x84, 0x45, 0x90, 0x23, 0x7d, 0x43, 0x67, 0xf8, - 0xa9, 0xee, 0x8c, 0x6c, 0x19, 0x1b, 0x69, 0x2d, 0x4b, 0xfa, 0x46, 0x17, 0x3f, 0xdd, 0x1b, 0xd9, - 0xf0, 0x63, 0xb0, 0x11, 0x35, 0x95, 0xc2, 0x9b, 0x74, 0xc1, 0x2f, 0xb6, 0xcb, 0x93, 0xe1, 0xb2, - 0xac, 0x9d, 0x8b, 0xa8, 0xfb, 0xc8, 0x12, 0x8b, 0xd5, 0x4d, 0xd3, 0x53, 0xff, 0xb5, 0x00, 0x16, - 0x3b, 0xc8, 0x43, 0x36, 0x83, 0x3d, 0xb0, 0xc6, 0xb1, 0xed, 0x5a, 0x88, 0x63, 0x3d, 0x68, 0x4d, - 0x42, 0x4b, 0xaf, 0xca, 0x96, 0x25, 0xd9, 0xb1, 0x55, 0x13, 0x3d, 0x9a, 0xbf, 0x53, 0x6d, 0xc8, - 0xd9, 0x2e, 0x47, 0x1c, 0x6b, 0xab, 0x91, 0x8c, 0x60, 0x12, 0x5e, 0x07, 0x05, 0xee, 0x8d, 0x18, - 0x9f, 0x34, 0x0d, 0x93, 0x6a, 0x19, 0x9c, 0xf5, 0x46, 0x44, 0x0f, 0xea, 0x6c, 0x5c, 0x25, 0x4f, - 0xee, 0x0f, 0x52, 0x6f, 0xd2, 0x1f, 0x98, 0x60, 0x9b, 0x89, 0x43, 0xd5, 0x6d, 0xcc, 0x65, 0x15, - 0x77, 0x2d, 0xec, 0x10, 0x36, 0x8c, 0x84, 0x2f, 0xce, 0x2e, 0x7c, 0x53, 0x0a, 0x7a, 0x28, 0xe4, - 0x68, 0x91, 0x98, 0x70, 0x95, 0x06, 0x28, 0x9e, 0xbc, 0x4a, 0x6c, 0xf8, 0x92, 0x34, 0xfc, 0xe2, - 0x09, 0x22, 0x62, 0xeb, 0x19, 0xf8, 0x30, 0xd1, 0x6d, 0x88, 0x68, 0xd2, 0xa5, 0x23, 0xeb, 0x1e, - 0x1e, 0x88, 0x92, 0x8c, 0x82, 0xc6, 0x03, 0xe3, 0xb8, 0x63, 0x0a, 0x7d, 0x5a, 0xdc, 0x18, 0x12, - 0x4e, 0x4d, 0x9c, 0xb0, 0xad, 0x54, 0x27, 0x4d, 0x49, 0x1c, 0x9b, 0x5a, 0x42, 0xd6, 0x6d, 0x8c, - 0x45, 0x14, 0x25, 0x1a, 0x13, 0xec, 0x52, 0x63, 0x28, 0x73, 0x52, 0x4a, 0x5b, 0x8d, 0x9b, 0x90, - 0x96, 0x98, 0x85, 0x4f, 0xc0, 0x55, 0x67, 0x64, 0xf7, 0xb1, 0xa7, 0xd3, 0x83, 0x00, 0x28, 0x23, - 0x8f, 0x71, 0xe4, 0x71, 0xdd, 0xc3, 0x06, 0x26, 0xbe, 0x38, 0xf1, 0x40, 0x73, 0x26, 0xfb, 0xa2, - 0x94, 0x76, 0x39, 0x60, 0x79, 0x74, 0x20, 0x65, 0xb0, 0x1e, 0xed, 0x0a, 0xb8, 0x16, 0xa1, 0x03, - 0xc5, 0x18, 0x6c, 0x83, 0x4b, 0x36, 0x7a, 0xae, 0xc7, 0xce, 0x2c, 0x14, 0xc7, 0x0e, 0x1b, 0x31, - 0x7d, 0x92, 0xcc, 0xc3, 0xde, 0xa8, 0x68, 0xa3, 0xe7, 0x9d, 0x10, 0xd7, 0x88, 0x60, 0xfb, 0x31, - 0xea, 0x5e, 0x3a, 0x93, 0xce, 0x2f, 0xdc, 0x4b, 0x67, 0x16, 0xf2, 0x8b, 0xf7, 0xd2, 0x99, 0x4c, - 0x3e, 0xab, 0xfe, 0x3f, 0xc8, 0xca, 0xb8, 0xae, 0x1b, 0x87, 0x4c, 0x66, 0x77, 0xd3, 0xf4, 0x30, - 0x63, 0x98, 0x15, 0x94, 0x30, 0xbb, 0x47, 0x13, 0x2a, 0x07, 0x9b, 0xa7, 0xdd, 0x18, 0x18, 0xfc, - 0x14, 0x2c, 0xb9, 0x58, 0xb6, 0xb3, 0x92, 0x31, 0xb7, 0xfb, 0x49, 0x75, 0x86, 0xab, 0x5e, 0xf5, - 0x34, 0x81, 0x5a, 0x24, 0x4d, 0xf5, 0x26, 0xf7, 0x94, 0x23, 0xbd, 0x02, 0x83, 0xfb, 0x47, 0x17, - 0xfd, 0xe1, 0x6b, 0x2d, 0x7a, 0x44, 0xde, 0x64, 0xcd, 0xab, 0x20, 0x57, 0x0f, 0xcc, 0x7e, 0x20, - 0x4a, 0xd7, 0xb1, 0x6d, 0x59, 0x4e, 0x6e, 0xcb, 0x1e, 0x58, 0x0d, 0x9b, 0xbf, 0x1e, 0x95, 0xb9, - 0x09, 0xbe, 0x0f, 0x40, 0xd8, 0x35, 0x8a, 0x9c, 0x16, 0x64, 0xf7, 0x6c, 0x38, 0xd3, 0x36, 0xa7, - 0x2a, 0xfa, 0xfc, 0x54, 0x45, 0x97, 0x55, 0x83, 0x82, 0xcd, 0xfd, 0x64, 0xd5, 0x95, 0x05, 0xa4, - 0x83, 0x8c, 0x43, 0xcc, 0x19, 0xd4, 0x40, 0x5a, 0x56, 0xd7, 0xc0, 0xdc, 0xeb, 0xa7, 0x9a, 0xeb, - 0xef, 0x54, 0x4f, 0x13, 0xd2, 0x44, 0x1c, 0x85, 0x31, 0x20, 0x65, 0xa9, 0xbf, 0x54, 0x40, 0xe1, - 0x3e, 0x1e, 0xd7, 0x19, 0x23, 0x03, 0xc7, 0xc6, 0x0e, 0x17, 0xd1, 0x87, 0x0c, 0x2c, 0x3e, 0xe1, - 0x07, 0x60, 0x25, 0x76, 0x3c, 0x99, 0x3c, 0x15, 0x99, 0x3c, 0x97, 0xa3, 0x49, 0xb1, 0x4f, 0xf0, - 0x06, 0x00, 0xae, 0x87, 0x7d, 0xdd, 0xd0, 0x0f, 0xf1, 0x58, 0xda, 0x94, 0xdb, 0xdd, 0x4e, 0x26, - 0xc5, 0xe0, 0xfe, 0x59, 0xed, 0x8c, 0xfa, 0x16, 0x31, 0xee, 0xe3, 0xb1, 0x96, 0x11, 0xf8, 0xc6, - 0x7d, 0x3c, 0x16, 0x55, 0x50, 0x36, 0x29, 0x32, 0x93, 0xa5, 0xb4, 0x60, 0xa0, 0xfe, 0x4a, 0x01, - 0x17, 0x62, 0x03, 0xa2, 0xf3, 0xea, 0x8c, 0xfa, 0x82, 0x23, 0xb9, 0x7f, 0xca, 0x74, 0x47, 0x74, - 0x4c, 0xdb, 0xf9, 0x13, 0xb4, 0xbd, 0x09, 0x96, 0xe3, 0x54, 0x22, 0xf4, 0x4d, 0xcd, 0xa0, 0x6f, - 0x2e, 0xe2, 0xb8, 0x8f, 0xc7, 0xea, 0xcf, 0x12, 0xba, 0xdd, 0x1a, 0x27, 0x5c, 0xd8, 0x7b, 0x85, - 0x6e, 0xf1, 0xb2, 0x49, 0xdd, 0x8c, 0x24, 0xff, 0x31, 0x03, 0x52, 0xc7, 0x0d, 0x50, 0xff, 0xa2, - 0x80, 0x8d, 0xe4, 0xaa, 0xac, 0x47, 0x3b, 0xde, 0xc8, 0xc1, 0xfb, 0xbb, 0x67, 0xad, 0x7f, 0x13, - 0x64, 0x5c, 0x81, 0xd2, 0x39, 0x0b, 0x8f, 0x68, 0xb6, 0x92, 0xbd, 0x24, 0xb9, 0x7a, 0x22, 0xc4, - 0x57, 0xa7, 0x0c, 0x60, 0xe1, 0xce, 0x7d, 0x34, 0x53, 0xd0, 0x25, 0x02, 0x4a, 0x5b, 0x49, 0xda, - 0xcc, 0xd4, 0xaf, 0x14, 0x00, 0x8f, 0x67, 0x2b, 0xf8, 0x3d, 0x00, 0xa7, 0x72, 0x5e, 0xd2, 0xff, - 0xf2, 0x6e, 0x22, 0xcb, 0xc9, 0x9d, 0x8b, 0xfd, 0x68, 0x3e, 0xe1, 0x47, 0xf0, 0x07, 0x00, 0xb8, - 0xf2, 0x10, 0x67, 0x3e, 0xe9, 0xac, 0x1b, 0x7d, 0xc2, 0x12, 0xc8, 0xfd, 0x84, 0x12, 0x27, 0xf9, - 0x60, 0x91, 0xd2, 0x80, 0x98, 0x0a, 0xde, 0x22, 0xd4, 0x5f, 0x28, 0x93, 0x94, 0x18, 0x66, 0xeb, - 0xba, 0x65, 0x85, 0x3d, 0x20, 0x74, 0xc1, 0x52, 0x94, 0xef, 0x83, 0x70, 0xdd, 0x3e, 0xb1, 0x26, - 0x35, 0xb1, 0x21, 0xcb, 0xd2, 0x75, 0xb1, 0xe3, 0xbf, 0xfb, 0xae, 0x74, 0x75, 0x40, 0xf8, 0x70, - 0xd4, 0xaf, 0x1a, 0xd4, 0x0e, 0x1f, 0xa8, 0xc2, 0x7f, 0xd7, 0x98, 0x79, 0x58, 0xe3, 0x63, 0x17, - 0xb3, 0x88, 0x87, 0xfd, 0xf6, 0x1f, 0xbf, 0xbf, 0xa2, 0x68, 0xd1, 0x32, 0xaa, 0x09, 0xf2, 0xf1, - 0x1d, 0x04, 0x73, 0x64, 0x22, 0x8e, 0x20, 0x04, 0x69, 0x07, 0xd9, 0x51, 0x93, 0x29, 0xbf, 0x67, - 0xe8, 0x31, 0xb7, 0x40, 0xc6, 0x0e, 0x25, 0x84, 0xb7, 0x8e, 0x78, 0xac, 0xfe, 0x7c, 0x11, 0x94, - 0xa3, 0x65, 0xda, 0xc1, 0xdb, 0x0c, 0xf9, 0x69, 0xd0, 0x82, 0x8b, 0xce, 0x49, 0xd4, 0x6f, 0x76, - 0xc2, 0x7b, 0x8f, 0xf2, 0x76, 0xde, 0x7b, 0xe6, 0x5f, 0xf9, 0xde, 0x93, 0x7a, 0xc5, 0x7b, 0x4f, - 0xfa, 0xed, 0xbd, 0xf7, 0x2c, 0xbc, 0xf5, 0xf7, 0x9e, 0xc5, 0x77, 0xf4, 0xde, 0xb3, 0xf4, 0x3f, - 0x79, 0xef, 0xc9, 0xbc, 0xd5, 0xf7, 0x9e, 0xec, 0x9b, 0xbd, 0xf7, 0x80, 0x37, 0x7a, 0xef, 0xc9, - 0xcd, 0xf4, 0xde, 0xa3, 0x7e, 0x35, 0x0f, 0x36, 0xe4, 0x4d, 0xba, 0x3b, 0x44, 0xae, 0x38, 0xdc, - 0x49, 0x08, 0xc4, 0xd7, 0x73, 0x65, 0x86, 0xeb, 0xf9, 0xfc, 0xeb, 0x5d, 0xcf, 0x53, 0x33, 0x5c, - 0xcf, 0xd3, 0x67, 0x5d, 0xcf, 0x17, 0xce, 0xba, 0x9e, 0x2f, 0xce, 0x76, 0x3d, 0x5f, 0x3a, 0xe5, - 0x7a, 0x0e, 0x55, 0xb0, 0xec, 0x7a, 0x84, 0x8a, 0x3a, 0x90, 0x78, 0x0b, 0x98, 0x9a, 0x53, 0x4b, - 0x20, 0x17, 0x27, 0x11, 0x93, 0xc1, 0x3c, 0x48, 0x11, 0x33, 0x6a, 0x3a, 0xc5, 0xa7, 0xba, 0x03, - 0x2e, 0xd4, 0x23, 0xd5, 0xb1, 0x99, 0xbc, 0x41, 0xc3, 0x0d, 0xb0, 0x18, 0xdc, 0x62, 0x43, 0x7c, - 0x38, 0xba, 0xf2, 0x27, 0x05, 0xac, 0xc4, 0xcd, 0xc2, 0x10, 0x31, 0x0c, 0x8b, 0x60, 0xab, 0xf1, - 0x68, 0xaf, 0xfb, 0xf8, 0x61, 0x4b, 0xd3, 0x3b, 0x77, 0xeb, 0xdd, 0x96, 0xfe, 0x78, 0xaf, 0xdb, - 0x69, 0x35, 0xda, 0xb7, 0xdb, 0xad, 0x66, 0x7e, 0x0e, 0xbe, 0x0f, 0x36, 0x8f, 0xd0, 0xb5, 0xd6, - 0x9d, 0x76, 0xb7, 0xd7, 0xd2, 0x5a, 0xcd, 0xbc, 0x72, 0x02, 0x7b, 0x7b, 0xaf, 0xdd, 0x6b, 0xd7, - 0x1f, 0xb4, 0x9f, 0xb4, 0x9a, 0xf9, 0x79, 0x78, 0x11, 0x5c, 0x38, 0x42, 0x7f, 0x50, 0x7f, 0xbc, - 0xd7, 0xb8, 0xdb, 0x6a, 0xe6, 0x53, 0x70, 0x0b, 0x6c, 0x1c, 0x21, 0x76, 0x7b, 0x8f, 0x3a, 0x9d, - 0x56, 0x33, 0x9f, 0x3e, 0x81, 0xd6, 0x6c, 0x3d, 0x68, 0xf5, 0x5a, 0xcd, 0xfc, 0xc2, 0x56, 0xfa, - 0xb3, 0xdf, 0x14, 0xe7, 0x6e, 0x7d, 0xfa, 0xf5, 0x8b, 0xa2, 0xf2, 0xcd, 0x8b, 0xa2, 0xf2, 0xf7, - 0x17, 0x45, 0xe5, 0xf3, 0x97, 0xc5, 0xb9, 0x6f, 0x5e, 0x16, 0xe7, 0xfe, 0xf6, 0xb2, 0x38, 0xf7, - 0xe4, 0x93, 0xe3, 0x05, 0x62, 0x52, 0x80, 0xaf, 0xc5, 0xbf, 0x08, 0xf8, 0xdf, 0xaf, 0x3d, 0x9f, - 0xfe, 0x39, 0x46, 0xd6, 0x8e, 0xfe, 0xa2, 0x8c, 0xfd, 0x8f, 0xff, 0x1b, 0x00, 0x00, 0xff, 0xff, - 0x15, 0xc3, 0x5a, 0xbf, 0xbf, 0x19, 0x00, 0x00, + // 2413 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x19, 0x4b, 0x6c, 0x1b, 0xc7, + 0x55, 0x2b, 0x52, 0x12, 0x39, 0xd4, 0x87, 0x1a, 0x29, 0x32, 0x25, 0x2b, 0x24, 0xbd, 0x69, 0x02, + 0x35, 0xae, 0xc9, 0x48, 0x01, 0x02, 0xc3, 0x6d, 0x10, 0x50, 0x24, 0x63, 0xd1, 0x1f, 0x99, 0x5d, + 0xd2, 0x0a, 0xea, 0xa2, 0x58, 0x0c, 0x77, 0x47, 0xe4, 0x44, 0xbb, 0x3b, 0xeb, 0x9d, 0x21, 0x65, + 0xf6, 0xd0, 0x73, 0x50, 0xa0, 0x40, 0x7a, 0x0b, 0x7a, 0x69, 0x80, 0x5e, 0x8a, 0x9e, 0x7a, 0x08, + 0x72, 0xec, 0xa1, 0x97, 0xa6, 0x05, 0x0a, 0xa4, 0x3d, 0x15, 0x3d, 0x38, 0x85, 0x7d, 0xe8, 0xa1, + 0x40, 0x7b, 0xee, 0xad, 0x98, 0xd9, 0x0f, 0x97, 0xfa, 0x99, 0x86, 0xed, 0x5e, 0xa4, 0x9d, 0xf7, + 0x9b, 0xf7, 0x66, 0xde, 0x77, 0x08, 0x76, 0x88, 0xc3, 0xb1, 0x67, 0xf4, 0x10, 0x71, 0x74, 0x86, + 0x8d, 0xbe, 0x47, 0xf8, 0xb0, 0x6c, 0x18, 0x83, 0xb2, 0xeb, 0xd1, 0x01, 0x31, 0xb1, 0x57, 0x1e, + 0x6c, 0x47, 0xdf, 0x25, 0xd7, 0xa3, 0x9c, 0xc2, 0x37, 0xce, 0xe0, 0x29, 0x19, 0xc6, 0xa0, 0x14, + 0xd1, 0x0d, 0xb6, 0x37, 0x96, 0x91, 0x4d, 0x1c, 0x5a, 0x96, 0x7f, 0x7d, 0xbe, 0x8d, 0xbc, 0x41, + 0x99, 0x4d, 0x59, 0xb9, 0x83, 0x18, 0x2e, 0x0f, 0xb6, 0x3b, 0x98, 0xa3, 0xed, 0xb2, 0x41, 0x89, + 0x13, 0xe0, 0xdf, 0x0a, 0xf0, 0x58, 0x08, 0x71, 0x8c, 0x11, 0x4d, 0x08, 0x08, 0xe8, 0xd6, 0x7d, + 0x3a, 0x5d, 0xae, 0xca, 0xfe, 0x22, 0x40, 0xad, 0x76, 0x69, 0x97, 0xfa, 0x70, 0xf1, 0x15, 0x6e, + 0xdc, 0xa5, 0xb4, 0x6b, 0xe1, 0xb2, 0x5c, 0x75, 0xfa, 0x87, 0x65, 0xb3, 0xef, 0x21, 0x4e, 0x68, + 0xb8, 0x71, 0xe1, 0x24, 0x9e, 0x13, 0x1b, 0x33, 0x8e, 0x6c, 0x37, 0x24, 0x20, 0x1d, 0xa3, 0x6c, + 0x50, 0x0f, 0x97, 0x0d, 0x8b, 0x60, 0x87, 0x8b, 0x43, 0xf1, 0xbf, 0x02, 0x82, 0xb2, 0x20, 0xb0, + 0x48, 0xb7, 0xc7, 0x7d, 0x30, 0x2b, 0x73, 0xec, 0x98, 0xd8, 0xb3, 0x89, 0x4f, 0x3c, 0x5a, 0x05, + 0x0c, 0x6f, 0x9e, 0x77, 0xee, 0x83, 0xed, 0xf2, 0x31, 0xf1, 0x42, 0x53, 0x37, 0x63, 0x62, 0x0c, + 0x6f, 0xe8, 0x72, 0x5a, 0x3e, 0xc2, 0xc3, 0xc0, 0x5a, 0xf5, 0xbf, 0x29, 0x90, 0xab, 0x52, 0x87, + 0xf5, 0x6d, 0xec, 0x55, 0x4c, 0x93, 0x08, 0x93, 0x9a, 0x1e, 0x75, 0x29, 0x43, 0x16, 0x5c, 0x05, + 0x33, 0x9c, 0x70, 0x0b, 0xe7, 0x94, 0xa2, 0xb2, 0x95, 0xd6, 0xfc, 0x05, 0x2c, 0x82, 0x8c, 0x89, + 0x99, 0xe1, 0x11, 0x57, 0x10, 0xe7, 0xa6, 0x25, 0x2e, 0x0e, 0x82, 0xeb, 0x20, 0xe5, 0xab, 0x45, + 0xcc, 0x5c, 0x42, 0xa2, 0xe7, 0xe4, 0xba, 0x61, 0xc2, 0x9b, 0x60, 0x91, 0x38, 0x84, 0x13, 0x64, + 0xe9, 0x3d, 0x2c, 0x8c, 0xcd, 0x25, 0x8b, 0xca, 0x56, 0x66, 0x67, 0xa3, 0x44, 0x3a, 0x46, 0x49, + 0x9c, 0x4f, 0x29, 0x38, 0x95, 0xc1, 0x76, 0x69, 0x4f, 0x52, 0xec, 0x26, 0xbf, 0x7a, 0x5c, 0x98, + 0xd2, 0x16, 0x02, 0x3e, 0x1f, 0x08, 0xaf, 0x80, 0xf9, 0x2e, 0x76, 0x30, 0x23, 0x4c, 0xef, 0x21, + 0xd6, 0xcb, 0xcd, 0x14, 0x95, 0xad, 0x79, 0x2d, 0x13, 0xc0, 0xf6, 0x10, 0xeb, 0xc1, 0x02, 0xc8, + 0x74, 0x88, 0x83, 0xbc, 0xa1, 0x4f, 0x31, 0x2b, 0x29, 0x80, 0x0f, 0x92, 0x04, 0x55, 0x00, 0x98, + 0x8b, 0x8e, 0x1d, 0x5d, 0x5c, 0x56, 0x6e, 0x2e, 0x50, 0xc4, 0xbf, 0xc9, 0x52, 0x78, 0x93, 0xa5, + 0x76, 0x78, 0x93, 0xbb, 0x29, 0xa1, 0xc8, 0xa7, 0xdf, 0x14, 0x14, 0x2d, 0x2d, 0xf9, 0x04, 0x06, + 0xee, 0x83, 0x6c, 0xdf, 0xe9, 0x50, 0xc7, 0x24, 0x4e, 0x57, 0x77, 0xb1, 0x47, 0xa8, 0x99, 0x4b, + 0x49, 0x51, 0xeb, 0xa7, 0x44, 0xd5, 0x02, 0xa7, 0xf1, 0x25, 0x7d, 0x26, 0x24, 0x2d, 0x45, 0xcc, + 0x4d, 0xc9, 0x0b, 0xbf, 0x0f, 0xa0, 0x61, 0x0c, 0xa4, 0x4a, 0xb4, 0xcf, 0x43, 0x89, 0xe9, 0xc9, + 0x25, 0x66, 0x0d, 0x63, 0xd0, 0xf6, 0xb9, 0x03, 0x91, 0x3f, 0x04, 0x97, 0xb8, 0x87, 0x1c, 0x76, + 0x88, 0xbd, 0x93, 0x72, 0xc1, 0xe4, 0x72, 0x5f, 0x0b, 0x65, 0x8c, 0x0b, 0xdf, 0x03, 0x45, 0x23, + 0x70, 0x20, 0xdd, 0xc3, 0x26, 0x61, 0xdc, 0x23, 0x9d, 0xbe, 0xe0, 0xd5, 0x0f, 0x3d, 0x64, 0x48, + 0x1f, 0xc9, 0x48, 0x27, 0xc8, 0x87, 0x74, 0xda, 0x18, 0xd9, 0x87, 0x01, 0x15, 0xbc, 0x07, 0xbe, + 0xd5, 0xb1, 0xa8, 0x71, 0xc4, 0x84, 0x72, 0xfa, 0x98, 0x24, 0xb9, 0xb5, 0x4d, 0x18, 0x13, 0xd2, + 0xe6, 0x8b, 0xca, 0x56, 0x42, 0xbb, 0xe2, 0xd3, 0x36, 0xb1, 0x57, 0x8b, 0x51, 0xb6, 0x63, 0x84, + 0xf0, 0x1a, 0x80, 0x3d, 0xc2, 0x38, 0xf5, 0x88, 0x81, 0x2c, 0x1d, 0x3b, 0xdc, 0x23, 0x98, 0xe5, + 0x16, 0x24, 0xfb, 0xf2, 0x08, 0x53, 0xf7, 0x11, 0xf0, 0x16, 0xb8, 0x72, 0xee, 0xa6, 0xba, 0xd1, + 0x43, 0x8e, 0x83, 0xad, 0xdc, 0xa2, 0x34, 0xa5, 0x60, 0x9e, 0xb3, 0x67, 0xd5, 0x27, 0x83, 0x2b, + 0x60, 0x86, 0x53, 0x57, 0xdf, 0xcf, 0x2d, 0x15, 0x95, 0xad, 0x05, 0x2d, 0xc9, 0xa9, 0xbb, 0x0f, + 0xdf, 0x01, 0xab, 0x03, 0x64, 0x11, 0x13, 0x71, 0xea, 0x31, 0xdd, 0xa5, 0xc7, 0xd8, 0xd3, 0x0d, + 0xe4, 0xe6, 0xb2, 0x92, 0x06, 0x8e, 0x70, 0x4d, 0x81, 0xaa, 0x22, 0x17, 0xbe, 0x0d, 0x96, 0x23, + 0xa8, 0xce, 0x30, 0x97, 0xe4, 0xcb, 0x92, 0x7c, 0x29, 0x42, 0xb4, 0x30, 0x17, 0xb4, 0x9b, 0x20, + 0x8d, 0x2c, 0x8b, 0x1e, 0x5b, 0x84, 0xf1, 0x1c, 0x2c, 0x26, 0xb6, 0xd2, 0xda, 0x08, 0x00, 0x37, + 0x40, 0xca, 0xc4, 0xce, 0x50, 0x22, 0x57, 0x24, 0x32, 0x5a, 0xc3, 0xcb, 0x20, 0x6d, 0x8b, 0x24, + 0xc2, 0xd1, 0x11, 0xce, 0xad, 0x16, 0x95, 0xad, 0xa4, 0x96, 0xb2, 0x89, 0xd3, 0x12, 0x6b, 0x58, + 0x02, 0x2b, 0x52, 0x8a, 0x4e, 0x1c, 0x71, 0x4f, 0x03, 0xac, 0x0f, 0x90, 0xc5, 0x72, 0xaf, 0x15, + 0x95, 0xad, 0x94, 0xb6, 0x2c, 0x51, 0x8d, 0x00, 0x73, 0x80, 0x2c, 0x76, 0x63, 0xeb, 0x93, 0xcf, + 0x0b, 0x53, 0x9f, 0x7d, 0x5e, 0x98, 0xfa, 0xd3, 0x17, 0xd7, 0x36, 0x82, 0xcc, 0xda, 0xa5, 0x83, + 0x52, 0x90, 0x89, 0x4b, 0x55, 0xea, 0x70, 0xec, 0xf0, 0x9c, 0xa2, 0xfe, 0x45, 0x01, 0x97, 0xaa, + 0x91, 0x4b, 0xd8, 0x74, 0x80, 0xac, 0x57, 0x99, 0x7a, 0x2a, 0x20, 0xcd, 0xc4, 0x9d, 0xc8, 0x60, + 0x4f, 0x3e, 0x47, 0xb0, 0xa7, 0x04, 0x9b, 0x40, 0xdc, 0x28, 0x3e, 0xd3, 0xa6, 0xff, 0x4c, 0x83, + 0xcd, 0xd0, 0xa6, 0xbb, 0xd4, 0x24, 0x87, 0xc4, 0x40, 0xaf, 0x3a, 0xa7, 0x46, 0xbe, 0x96, 0x9c, + 0xc0, 0xd7, 0x66, 0x9e, 0xcf, 0xd7, 0x66, 0x27, 0xf0, 0xb5, 0xb9, 0x8b, 0x7c, 0x2d, 0x75, 0x91, + 0xaf, 0xa5, 0x27, 0xf3, 0x35, 0x70, 0x9e, 0xaf, 0x4d, 0xe7, 0x14, 0xf5, 0x97, 0x0a, 0x58, 0xad, + 0x3f, 0xec, 0x93, 0x01, 0x7d, 0x49, 0x27, 0x7d, 0x1b, 0x2c, 0xe0, 0x98, 0x3c, 0x96, 0x4b, 0x14, + 0x13, 0x5b, 0x99, 0x9d, 0x37, 0x4b, 0xc1, 0xc5, 0x47, 0xad, 0x44, 0x78, 0xfb, 0xf1, 0xdd, 0xb5, + 0x71, 0x5e, 0xa9, 0xe1, 0xef, 0x15, 0xb0, 0x21, 0xf2, 0x42, 0x17, 0x6b, 0xf8, 0x18, 0x79, 0x66, + 0x0d, 0x3b, 0xd4, 0x66, 0x2f, 0xac, 0xa7, 0x0a, 0x16, 0x4c, 0x29, 0x49, 0xe7, 0x54, 0x47, 0xa6, + 0x29, 0xf5, 0x94, 0x34, 0x02, 0xd8, 0xa6, 0x15, 0xd3, 0x84, 0x5b, 0x20, 0x3b, 0xa2, 0xf1, 0x44, + 0x8c, 0x09, 0xd7, 0x17, 0x64, 0x8b, 0x21, 0x99, 0x8c, 0x3c, 0x7c, 0x23, 0x7f, 0xb1, 0x6b, 0xab, + 0xff, 0x52, 0x40, 0xf6, 0xa6, 0x45, 0x3b, 0xc8, 0x6a, 0x59, 0x88, 0xf5, 0x44, 0xce, 0x1c, 0x8a, + 0x90, 0xf2, 0x70, 0x50, 0xac, 0xa4, 0xfa, 0x13, 0x87, 0x94, 0x60, 0x93, 0xe5, 0xf3, 0x03, 0xb0, + 0x1c, 0x95, 0x8f, 0xc8, 0xc1, 0xa5, 0xb5, 0xbb, 0x2b, 0x4f, 0x1e, 0x17, 0x96, 0xc2, 0x60, 0xaa, + 0x4a, 0x67, 0xaf, 0x69, 0x4b, 0xc6, 0x18, 0xc0, 0x84, 0x79, 0x90, 0x21, 0x1d, 0x43, 0x67, 0xf8, + 0xa1, 0xee, 0xf4, 0x6d, 0x19, 0x1b, 0x49, 0x2d, 0x4d, 0x3a, 0x46, 0x0b, 0x3f, 0xdc, 0xef, 0xdb, + 0xf0, 0x5d, 0xb0, 0x16, 0x36, 0x95, 0xc2, 0x9b, 0x74, 0xc1, 0x2f, 0x8e, 0xcb, 0x93, 0xe1, 0x32, + 0xaf, 0xad, 0x84, 0xd8, 0x03, 0x64, 0x89, 0xcd, 0x2a, 0xa6, 0xe9, 0xa9, 0xff, 0x9e, 0x01, 0xb3, + 0x4d, 0xe4, 0x21, 0x9b, 0xc1, 0x36, 0x58, 0xe2, 0xd8, 0x76, 0x2d, 0xc4, 0xb1, 0xee, 0xb7, 0x26, + 0x81, 0xa5, 0x57, 0x65, 0xcb, 0x12, 0xef, 0xd8, 0x4a, 0xb1, 0x1e, 0x6d, 0xb0, 0x5d, 0xaa, 0x4a, + 0x68, 0x8b, 0x23, 0x8e, 0xb5, 0xc5, 0x50, 0x86, 0x0f, 0x84, 0xd7, 0x41, 0x8e, 0x7b, 0x7d, 0xc6, + 0x47, 0x4d, 0xc3, 0xa8, 0x5a, 0xfa, 0x77, 0xbd, 0x16, 0xe2, 0xfd, 0x3a, 0x1b, 0x55, 0xc9, 0xb3, + 0xfb, 0x83, 0xc4, 0x8b, 0xf4, 0x07, 0x26, 0xd8, 0x64, 0xe2, 0x52, 0x75, 0x1b, 0x73, 0x59, 0xc5, + 0x5d, 0x0b, 0x3b, 0x84, 0xf5, 0x42, 0xe1, 0xb3, 0x93, 0x0b, 0x5f, 0x97, 0x82, 0xee, 0x0a, 0x39, + 0x5a, 0x28, 0x26, 0xd8, 0xa5, 0x0a, 0xf2, 0x67, 0xef, 0x12, 0x19, 0x3e, 0x27, 0x0d, 0xbf, 0x7c, + 0x86, 0x88, 0xc8, 0x7a, 0x06, 0xde, 0x8a, 0x75, 0x1b, 0x22, 0x9a, 0x74, 0xe9, 0xc8, 0xba, 0x87, + 0xbb, 0xa2, 0x24, 0x23, 0xbf, 0xf1, 0xc0, 0x38, 0xea, 0x98, 0x02, 0x9f, 0x16, 0x13, 0x43, 0xcc, + 0xa9, 0x89, 0x13, 0xb4, 0x95, 0xea, 0xa8, 0x29, 0x89, 0x62, 0x53, 0x8b, 0xc9, 0xfa, 0x10, 0x63, + 0x11, 0x45, 0xb1, 0xc6, 0x04, 0xbb, 0xd4, 0xe8, 0xc9, 0x9c, 0x94, 0xd0, 0x16, 0xa3, 0x26, 0xa4, + 0x2e, 0xa0, 0xf0, 0x01, 0xb8, 0xea, 0xf4, 0xed, 0x0e, 0xf6, 0x74, 0x7a, 0xe8, 0x13, 0xca, 0xc8, + 0x63, 0x1c, 0x79, 0x5c, 0xf7, 0xb0, 0x81, 0xc9, 0x40, 0xdc, 0xb8, 0xaf, 0x39, 0x93, 0x7d, 0x51, + 0x42, 0x7b, 0xd3, 0x67, 0xb9, 0x77, 0x28, 0x65, 0xb0, 0x36, 0x6d, 0x09, 0x72, 0x2d, 0xa4, 0xf6, + 0x15, 0x63, 0xb0, 0x01, 0xae, 0xd8, 0xe8, 0x91, 0x1e, 0x39, 0xb3, 0x50, 0x1c, 0x3b, 0xac, 0xcf, + 0xf4, 0x51, 0x32, 0x0f, 0x7a, 0xa3, 0xbc, 0x8d, 0x1e, 0x35, 0x03, 0xba, 0x6a, 0x48, 0x76, 0x10, + 0x51, 0xdd, 0x4a, 0xa6, 0x92, 0xd9, 0x99, 0x5b, 0xc9, 0xd4, 0x4c, 0x76, 0xf6, 0x56, 0x32, 0x95, + 0xca, 0xa6, 0xd5, 0x6f, 0x83, 0xb4, 0x8c, 0xeb, 0x8a, 0x71, 0xc4, 0x64, 0x76, 0x37, 0x4d, 0x0f, + 0x33, 0x86, 0x59, 0x4e, 0x09, 0xb2, 0x7b, 0x08, 0x50, 0x39, 0x58, 0x3f, 0x6f, 0x62, 0x60, 0xf0, + 0x23, 0x30, 0xe7, 0x62, 0xd9, 0xce, 0x4a, 0xc6, 0xcc, 0xce, 0xfb, 0xa5, 0x09, 0x46, 0xbd, 0xd2, + 0x79, 0x02, 0xb5, 0x50, 0x9a, 0xea, 0x8d, 0xe6, 0x94, 0x13, 0xbd, 0x02, 0x83, 0x07, 0x27, 0x37, + 0xfd, 0xde, 0x73, 0x6d, 0x7a, 0x42, 0xde, 0x68, 0xcf, 0xab, 0x20, 0x53, 0xf1, 0xcd, 0xbe, 0x23, + 0x4a, 0xd7, 0xa9, 0x63, 0x99, 0x8f, 0x1f, 0xcb, 0x3e, 0x58, 0x0c, 0x9a, 0xbf, 0x36, 0x95, 0xb9, + 0x09, 0xbe, 0x0e, 0x40, 0xd0, 0x35, 0x8a, 0x9c, 0xe6, 0x67, 0xf7, 0x74, 0x00, 0x69, 0x98, 0x63, + 0x15, 0x7d, 0x7a, 0xac, 0xa2, 0xcb, 0xaa, 0x41, 0xc1, 0xfa, 0x41, 0xbc, 0xea, 0xca, 0x02, 0xd2, + 0x44, 0xc6, 0x11, 0xe6, 0x0c, 0x6a, 0x20, 0x29, 0xab, 0xab, 0x6f, 0xee, 0xf5, 0x73, 0xcd, 0x1d, + 0x6c, 0x97, 0xce, 0x13, 0x52, 0x43, 0x1c, 0x05, 0x31, 0x20, 0x65, 0xa9, 0x3f, 0x57, 0x40, 0xee, + 0x36, 0x1e, 0x56, 0x18, 0x23, 0x5d, 0xc7, 0xc6, 0x0e, 0x17, 0xd1, 0x87, 0x0c, 0x2c, 0x3e, 0xe1, + 0x1b, 0x60, 0x21, 0x72, 0x3c, 0x99, 0x3c, 0x15, 0x99, 0x3c, 0xe7, 0x43, 0xa0, 0x38, 0x27, 0x78, + 0x03, 0x00, 0xd7, 0xc3, 0x03, 0xdd, 0xd0, 0x8f, 0xf0, 0x50, 0xda, 0x94, 0xd9, 0xd9, 0x8c, 0x27, + 0x45, 0x7f, 0xfe, 0x2c, 0x35, 0xfb, 0x1d, 0x8b, 0x18, 0xb7, 0xf1, 0x50, 0x4b, 0x09, 0xfa, 0xea, + 0x6d, 0x3c, 0x14, 0x55, 0x50, 0x36, 0x29, 0x32, 0x93, 0x25, 0x34, 0x7f, 0xa1, 0xfe, 0x42, 0x01, + 0x97, 0x22, 0x03, 0xc2, 0xfb, 0x6a, 0xf6, 0x3b, 0x82, 0x23, 0x7e, 0x7e, 0xca, 0x78, 0x47, 0x74, + 0x4a, 0xdb, 0xe9, 0x33, 0xb4, 0xfd, 0x00, 0xcc, 0x47, 0xa9, 0x44, 0xe8, 0x9b, 0x98, 0x40, 0xdf, + 0x4c, 0xc8, 0x71, 0x1b, 0x0f, 0xd5, 0x9f, 0xc4, 0x74, 0xdb, 0x1d, 0xc6, 0x5c, 0xd8, 0x7b, 0x86, + 0x6e, 0xd1, 0xb6, 0x71, 0xdd, 0x8c, 0x38, 0xff, 0x29, 0x03, 0x12, 0xa7, 0x0d, 0x50, 0xff, 0xac, + 0x80, 0xb5, 0xf8, 0xae, 0xac, 0x4d, 0x9b, 0x5e, 0xdf, 0xc1, 0x07, 0x3b, 0x17, 0xed, 0xff, 0x01, + 0x48, 0xb9, 0x82, 0x4a, 0xe7, 0x2c, 0xb8, 0xa2, 0xc9, 0x4a, 0xf6, 0x9c, 0xe4, 0x6a, 0x8b, 0x10, + 0x5f, 0x1c, 0x33, 0x80, 0x05, 0x27, 0xf7, 0xce, 0x44, 0x41, 0x17, 0x0b, 0x28, 0x6d, 0x21, 0x6e, + 0x33, 0x53, 0xbf, 0x54, 0x00, 0x3c, 0x9d, 0xad, 0xe0, 0x77, 0x00, 0x1c, 0xcb, 0x79, 0x71, 0xff, + 0xcb, 0xba, 0xb1, 0x2c, 0x27, 0x4f, 0x2e, 0xf2, 0xa3, 0xe9, 0x98, 0x1f, 0xc1, 0xef, 0x02, 0xe0, + 0xca, 0x4b, 0x9c, 0xf8, 0xa6, 0xd3, 0x6e, 0xf8, 0x09, 0x0b, 0x20, 0xf3, 0x31, 0x25, 0x4e, 0xfc, + 0xc1, 0x22, 0xa1, 0x01, 0x01, 0xf2, 0xdf, 0x22, 0xd4, 0x9f, 0x29, 0xa3, 0x94, 0x18, 0x64, 0xeb, + 0x8a, 0x65, 0x05, 0x3d, 0x20, 0x74, 0xc1, 0x5c, 0x98, 0xef, 0xfd, 0x70, 0xdd, 0x3c, 0xb3, 0x26, + 0xd5, 0xb0, 0x21, 0xcb, 0xd2, 0x75, 0x71, 0xe2, 0xbf, 0xf9, 0xa6, 0x70, 0xb5, 0x4b, 0x78, 0xaf, + 0xdf, 0x29, 0x19, 0xd4, 0x0e, 0x1e, 0xa8, 0x82, 0x7f, 0xd7, 0x98, 0x79, 0x54, 0xe6, 0x43, 0x17, + 0xb3, 0x90, 0x87, 0xfd, 0xfa, 0x9f, 0xbf, 0x7d, 0x5b, 0xd1, 0xc2, 0x6d, 0x54, 0x13, 0x64, 0xa3, + 0x19, 0x04, 0x73, 0x64, 0x22, 0x8e, 0x20, 0x04, 0x49, 0x07, 0xd9, 0x61, 0x93, 0x29, 0xbf, 0x27, + 0xe8, 0x31, 0x37, 0x40, 0xca, 0x0e, 0x24, 0x04, 0x53, 0x47, 0xb4, 0x56, 0x7f, 0x3a, 0x0b, 0x8a, + 0xe1, 0x36, 0x0d, 0xff, 0x6d, 0x86, 0xfc, 0xd8, 0x6f, 0xc1, 0x45, 0xe7, 0x24, 0xea, 0x37, 0x3b, + 0xe3, 0xbd, 0x47, 0x79, 0x39, 0xef, 0x3d, 0xd3, 0xcf, 0x7c, 0xef, 0x49, 0x3c, 0xe3, 0xbd, 0x27, + 0xf9, 0xf2, 0xde, 0x7b, 0x66, 0x5e, 0xfa, 0x7b, 0xcf, 0xec, 0x2b, 0x7a, 0xef, 0x99, 0xfb, 0xbf, + 0xbc, 0xf7, 0xa4, 0x5e, 0xea, 0x7b, 0x4f, 0xfa, 0xc5, 0xde, 0x7b, 0xc0, 0x0b, 0xbd, 0xf7, 0x64, + 0x26, 0x7a, 0xef, 0x51, 0xbf, 0x9c, 0x06, 0x6b, 0x72, 0x92, 0x6e, 0xf5, 0x90, 0x2b, 0x2e, 0x77, + 0x14, 0x02, 0xd1, 0x78, 0xae, 0x4c, 0x30, 0x9e, 0x4f, 0x3f, 0xdf, 0x78, 0x9e, 0x98, 0x60, 0x3c, + 0x4f, 0x5e, 0x34, 0x9e, 0xcf, 0x5c, 0x34, 0x9e, 0xcf, 0x4e, 0x36, 0x9e, 0xcf, 0x9d, 0x33, 0x9e, + 0x43, 0x15, 0xcc, 0xbb, 0x1e, 0xa1, 0xa2, 0x0e, 0xc4, 0xde, 0x02, 0xc6, 0x60, 0x6a, 0x01, 0x64, + 0xa2, 0x24, 0x62, 0x32, 0x98, 0x05, 0x09, 0x62, 0x86, 0x4d, 0xa7, 0xf8, 0x54, 0xb7, 0xc1, 0xa5, + 0x4a, 0xa8, 0x3a, 0x36, 0xe3, 0x13, 0x34, 0x5c, 0x03, 0xb3, 0xfe, 0x14, 0x1b, 0xd0, 0x07, 0x2b, + 0xf5, 0x0f, 0x0a, 0x58, 0x6d, 0x38, 0xa1, 0x37, 0xc6, 0xae, 0xe2, 0x07, 0x20, 0x63, 0xd2, 0x7e, + 0xc7, 0xc2, 0xba, 0xe8, 0x71, 0x82, 0x54, 0x74, 0x7d, 0xa2, 0xba, 0x25, 0xbb, 0xe3, 0x5b, 0x88, + 0x58, 0x23, 0x71, 0x1a, 0xf0, 0x85, 0xb5, 0x48, 0xd7, 0x81, 0x6d, 0x90, 0x32, 0xe9, 0xb1, 0x23, + 0x33, 0xcb, 0xf4, 0x0b, 0xca, 0x8d, 0x24, 0xa9, 0xbf, 0x53, 0xc0, 0xca, 0x19, 0x14, 0xf0, 0x47, + 0x60, 0xd1, 0x9f, 0xa5, 0xa2, 0x90, 0x93, 0xf5, 0x70, 0xf7, 0x3d, 0x11, 0xbd, 0x7f, 0x7f, 0x5c, + 0xb8, 0xec, 0x97, 0x0a, 0x66, 0x1e, 0x95, 0x08, 0x2d, 0xdb, 0x88, 0xf7, 0x4a, 0x77, 0x70, 0x17, + 0x19, 0xc3, 0x1a, 0x36, 0xfe, 0xfa, 0xc5, 0x35, 0x10, 0x14, 0xa0, 0x1a, 0x36, 0xfc, 0xd2, 0xb1, + 0x20, 0xa5, 0x45, 0x91, 0xb9, 0x07, 0x16, 0x3e, 0x46, 0xc4, 0xd2, 0xc3, 0x1f, 0x39, 0x9e, 0xe7, + 0x41, 0x7b, 0x5e, 0x70, 0x86, 0xf0, 0xb7, 0xff, 0xa8, 0x80, 0x85, 0xa8, 0x6f, 0xeb, 0x21, 0x86, + 0x61, 0x1e, 0x6c, 0x54, 0xef, 0xed, 0xb7, 0xee, 0xdf, 0xad, 0x6b, 0x7a, 0x73, 0xaf, 0xd2, 0xaa, + 0xeb, 0xf7, 0xf7, 0x5b, 0xcd, 0x7a, 0xb5, 0xf1, 0x61, 0xa3, 0x5e, 0xcb, 0x4e, 0xc1, 0xd7, 0xc1, + 0xfa, 0x09, 0xbc, 0x56, 0xbf, 0xd9, 0x68, 0xb5, 0xeb, 0x5a, 0xbd, 0x96, 0x55, 0xce, 0x60, 0x6f, + 0xec, 0x37, 0xda, 0x8d, 0xca, 0x9d, 0xc6, 0x83, 0x7a, 0x2d, 0x3b, 0x0d, 0x2f, 0x83, 0x4b, 0x27, + 0xf0, 0x77, 0x2a, 0xf7, 0xf7, 0xab, 0x7b, 0xf5, 0x5a, 0x36, 0x01, 0x37, 0xc0, 0xda, 0x09, 0x64, + 0xab, 0x7d, 0xaf, 0xd9, 0xac, 0xd7, 0xb2, 0xc9, 0x33, 0x70, 0xb5, 0xfa, 0x9d, 0x7a, 0xbb, 0x5e, + 0xcb, 0xce, 0x6c, 0x24, 0x3f, 0xf9, 0x55, 0x7e, 0x6a, 0xf7, 0xa3, 0xaf, 0x9e, 0xe4, 0x95, 0xaf, + 0x9f, 0xe4, 0x95, 0x7f, 0x3c, 0xc9, 0x2b, 0x9f, 0x3e, 0xcd, 0x4f, 0x7d, 0xfd, 0x34, 0x3f, 0xf5, + 0xb7, 0xa7, 0xf9, 0xa9, 0x07, 0xef, 0x9f, 0xae, 0xd5, 0xa3, 0xbb, 0xbf, 0x16, 0xfd, 0x38, 0x33, + 0x78, 0xaf, 0xfc, 0x68, 0xfc, 0x97, 0x31, 0x59, 0xc6, 0x3b, 0xb3, 0xf2, 0x3c, 0xdf, 0xfd, 0x5f, + 0x00, 0x00, 0x00, 0xff, 0xff, 0x35, 0xc8, 0xcf, 0x24, 0x4a, 0x1b, 0x00, 0x00, } func (m *ConsumerAdditionProposal) Marshal() (dAtA []byte, err error) { @@ -3421,6 +3530,94 @@ func (m *AllowlistedRewardDenoms) MarshalToSizedBuffer(dAtA []byte) (int, error) return len(dAtA) - i, nil } +func (m *InfractionParameters) 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 *InfractionParameters) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *InfractionParameters) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Downtime != nil { + { + size, err := m.Downtime.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintProvider(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if m.DoubleSign != nil { + { + size, err := m.DoubleSign.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 (m *SlashJailParameters) 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 *SlashJailParameters) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *SlashJailParameters) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + n24, err24 := github_com_cosmos_gogoproto_types.StdDurationMarshalTo(m.JailDuration, dAtA[i-github_com_cosmos_gogoproto_types.SizeOfStdDuration(m.JailDuration):]) + if err24 != nil { + return 0, err24 + } + i -= n24 + i = encodeVarintProvider(dAtA, i, uint64(n24)) + i-- + dAtA[i] = 0x42 + { + size := m.SlashFraction.Size() + i -= size + if _, err := m.SlashFraction.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + 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 @@ -4038,6 +4235,36 @@ func (m *AllowlistedRewardDenoms) Size() (n int) { return n } +func (m *InfractionParameters) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.DoubleSign != nil { + l = m.DoubleSign.Size() + n += 1 + l + sovProvider(uint64(l)) + } + if m.Downtime != nil { + l = m.Downtime.Size() + n += 1 + l + sovProvider(uint64(l)) + } + return n +} + +func (m *SlashJailParameters) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.SlashFraction.Size() + n += 1 + l + sovProvider(uint64(l)) + l = github_com_cosmos_gogoproto_types.SizeOfStdDuration(m.JailDuration) + n += 1 + l + sovProvider(uint64(l)) + return n +} + func sovProvider(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -8271,6 +8498,244 @@ func (m *AllowlistedRewardDenoms) Unmarshal(dAtA []byte) error { } return nil } +func (m *InfractionParameters) 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: InfractionParameters: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: InfractionParameters: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field DoubleSign", 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 + } + if m.DoubleSign == nil { + m.DoubleSign = &SlashJailParameters{} + } + if err := m.DoubleSign.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Downtime", 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 + } + if m.Downtime == nil { + m.Downtime = &SlashJailParameters{} + } + if err := m.Downtime.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 (m *SlashJailParameters) 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: SlashJailParameters: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: SlashJailParameters: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SlashFraction", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowProvider + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthProvider + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthProvider + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.SlashFraction.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field JailDuration", 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 + } + if err := github_com_cosmos_gogoproto_types.StdDurationUnmarshal(&m.JailDuration, 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 1fd93e436c..0c6f04a4ab 100644 --- a/x/ccv/provider/types/query.pb.go +++ b/x/ccv/provider/types/query.pb.go @@ -266,6 +266,8 @@ type Chain struct { // filled with these validators first, and other validators will be added to the validator set only if there are // not enough eligible priority validators. Prioritylist []string `protobuf:"bytes,15,rep,name=prioritylist,proto3" json:"prioritylist,omitempty"` + // Infraction parameters for slashing and jailing + InfractionParameters *InfractionParameters `protobuf:"bytes,16,opt,name=infraction_parameters,json=infractionParameters,proto3" json:"infraction_parameters,omitempty"` } func (m *Chain) Reset() { *m = Chain{} } @@ -406,6 +408,13 @@ func (m *Chain) GetPrioritylist() []string { return nil } +func (m *Chain) GetInfractionParameters() *InfractionParameters { + if m != nil { + return m.InfractionParameters + } + return nil +} + type QueryValidatorConsumerAddrRequest 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"` @@ -1737,13 +1746,14 @@ func (m *QueryConsumerChainRequest) GetConsumerId() string { } type QueryConsumerChainResponse struct { - ConsumerId string `protobuf:"bytes,1,opt,name=consumer_id,json=consumerId,proto3" json:"consumer_id,omitempty"` - ChainId string `protobuf:"bytes,2,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` - OwnerAddress string `protobuf:"bytes,3,opt,name=owner_address,json=ownerAddress,proto3" json:"owner_address,omitempty"` - Phase string `protobuf:"bytes,4,opt,name=phase,proto3" json:"phase,omitempty"` - Metadata ConsumerMetadata `protobuf:"bytes,5,opt,name=metadata,proto3" json:"metadata"` - InitParams *ConsumerInitializationParameters `protobuf:"bytes,6,opt,name=init_params,json=initParams,proto3" json:"init_params,omitempty"` - PowerShapingParams *PowerShapingParameters `protobuf:"bytes,7,opt,name=power_shaping_params,json=powerShapingParams,proto3" json:"power_shaping_params,omitempty"` + ConsumerId string `protobuf:"bytes,1,opt,name=consumer_id,json=consumerId,proto3" json:"consumer_id,omitempty"` + ChainId string `protobuf:"bytes,2,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` + OwnerAddress string `protobuf:"bytes,3,opt,name=owner_address,json=ownerAddress,proto3" json:"owner_address,omitempty"` + Phase string `protobuf:"bytes,4,opt,name=phase,proto3" json:"phase,omitempty"` + Metadata ConsumerMetadata `protobuf:"bytes,5,opt,name=metadata,proto3" json:"metadata"` + InitParams *ConsumerInitializationParameters `protobuf:"bytes,6,opt,name=init_params,json=initParams,proto3" json:"init_params,omitempty"` + PowerShapingParams *PowerShapingParameters `protobuf:"bytes,7,opt,name=power_shaping_params,json=powerShapingParams,proto3" json:"power_shaping_params,omitempty"` + InfractionParameters *InfractionParameters `protobuf:"bytes,8,opt,name=infraction_parameters,json=infractionParameters,proto3" json:"infraction_parameters,omitempty"` } func (m *QueryConsumerChainResponse) Reset() { *m = QueryConsumerChainResponse{} } @@ -1828,6 +1838,13 @@ func (m *QueryConsumerChainResponse) GetPowerShapingParams() *PowerShapingParame return nil } +func (m *QueryConsumerChainResponse) GetInfractionParameters() *InfractionParameters { + if m != nil { + return m.InfractionParameters + } + return nil +} + type QueryConsumerGenesisTimeRequest struct { ConsumerId string `protobuf:"bytes,1,opt,name=consumer_id,json=consumerId,proto3" json:"consumer_id,omitempty"` } @@ -1959,166 +1976,168 @@ func init() { } var fileDescriptor_422512d7b7586cd7 = []byte{ - // 2532 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x5a, 0xcd, 0x6f, 0xdc, 0xc6, - 0x15, 0x17, 0x57, 0x1f, 0x5e, 0xcd, 0x5a, 0x72, 0x32, 0x96, 0xad, 0xf5, 0xca, 0xd1, 0xca, 0x74, - 0xdc, 0x2a, 0x72, 0xbc, 0x2b, 0xa9, 0xc8, 0x97, 0x13, 0x7f, 0x68, 0x65, 0x49, 0x16, 0x1c, 0xdb, - 0x0a, 0xa5, 0x38, 0x80, 0x53, 0x97, 0x1d, 0x91, 0x93, 0xd5, 0x54, 0x5c, 0x92, 0xe6, 0x8c, 0xd6, - 0xde, 0x1a, 0xbe, 0xf4, 0x94, 0x43, 0x0b, 0x24, 0x08, 0x7a, 0x6e, 0xce, 0x3d, 0x14, 0x45, 0x11, - 0xf4, 0x1f, 0xe8, 0x25, 0xb7, 0xa6, 0xe9, 0xa5, 0x48, 0x51, 0xb7, 0xb0, 0x5b, 0xa0, 0x97, 0x1e, - 0x9a, 0x16, 0x3d, 0x17, 0x33, 0x1c, 0x72, 0x97, 0x34, 0x57, 0x4b, 0x6a, 0x75, 0x5b, 0xce, 0xbc, - 0xf7, 0x9b, 0xf7, 0xde, 0xbc, 0xf7, 0xe6, 0xbd, 0x27, 0x81, 0x2a, 0xb1, 0x19, 0xf6, 0x8c, 0x1d, - 0x44, 0x6c, 0x9d, 0x62, 0x63, 0xcf, 0x23, 0xac, 0x55, 0x35, 0x8c, 0x66, 0xd5, 0xf5, 0x9c, 0x26, - 0x31, 0xb1, 0x57, 0x6d, 0x2e, 0x54, 0xef, 0xef, 0x61, 0xaf, 0x55, 0x71, 0x3d, 0x87, 0x39, 0xf0, - 0x6c, 0x02, 0x43, 0xc5, 0x30, 0x9a, 0x95, 0x80, 0xa1, 0xd2, 0x5c, 0x28, 0x9d, 0xae, 0x3b, 0x4e, - 0xdd, 0xc2, 0x55, 0xe4, 0x92, 0x2a, 0xb2, 0x6d, 0x87, 0x21, 0x46, 0x1c, 0x9b, 0xfa, 0x10, 0xa5, - 0x89, 0xba, 0x53, 0x77, 0xc4, 0xcf, 0x2a, 0xff, 0x25, 0x57, 0xcb, 0x92, 0x47, 0x7c, 0x6d, 0xef, - 0x7d, 0x54, 0x65, 0xa4, 0x81, 0x29, 0x43, 0x0d, 0x57, 0x12, 0x2c, 0xa6, 0x11, 0x35, 0x94, 0xc2, - 0xe7, 0x99, 0xef, 0xc6, 0xd3, 0x5c, 0xa8, 0xd2, 0x1d, 0xe4, 0x61, 0x53, 0x37, 0x1c, 0x9b, 0xee, - 0x35, 0x42, 0x8e, 0x73, 0xfb, 0x70, 0x3c, 0x20, 0x1e, 0x96, 0x64, 0xa7, 0x19, 0xb6, 0x4d, 0xec, - 0x35, 0x88, 0xcd, 0xaa, 0x86, 0xd7, 0x72, 0x99, 0x53, 0xdd, 0xc5, 0xad, 0x40, 0xc3, 0x53, 0x86, - 0x43, 0x1b, 0x0e, 0xd5, 0x7d, 0x25, 0xfd, 0x0f, 0xb9, 0xf5, 0xb2, 0xff, 0x55, 0xa5, 0x0c, 0xed, - 0x12, 0xbb, 0x5e, 0x6d, 0x2e, 0x6c, 0x63, 0x86, 0x16, 0x82, 0x6f, 0x49, 0x35, 0x27, 0xa9, 0xb6, - 0x11, 0xc5, 0xbe, 0xf9, 0x43, 0x42, 0x17, 0xd5, 0x89, 0x2d, 0xec, 0xe9, 0xd3, 0xaa, 0x97, 0xc1, - 0xd4, 0x7b, 0x9c, 0x62, 0x59, 0x2a, 0xb2, 0x86, 0x6d, 0x4c, 0x09, 0xd5, 0xf0, 0xfd, 0x3d, 0x4c, - 0x19, 0x2c, 0x83, 0x42, 0xa0, 0xa2, 0x4e, 0xcc, 0xa2, 0x32, 0xa3, 0xcc, 0x8e, 0x6a, 0x20, 0x58, - 0x5a, 0x37, 0xd5, 0x47, 0xe0, 0x74, 0x32, 0x3f, 0x75, 0x1d, 0x9b, 0x62, 0xf8, 0x21, 0x18, 0xab, - 0xfb, 0x4b, 0x3a, 0x65, 0x88, 0x61, 0x01, 0x51, 0x58, 0x9c, 0xaf, 0x74, 0xf3, 0x84, 0xe6, 0x42, - 0x25, 0x86, 0xb5, 0xc9, 0xf9, 0x6a, 0x43, 0x5f, 0x3e, 0x29, 0x0f, 0x68, 0x47, 0xeb, 0x1d, 0x6b, - 0xea, 0xaf, 0x14, 0x50, 0x8a, 0x9c, 0xbe, 0xcc, 0xf1, 0x42, 0xe1, 0xaf, 0x83, 0x61, 0x77, 0x07, - 0x51, 0xff, 0xcc, 0xf1, 0xc5, 0xc5, 0x4a, 0x0a, 0xef, 0x0b, 0x0f, 0xdf, 0xe0, 0x9c, 0x9a, 0x0f, - 0x00, 0x57, 0x01, 0x68, 0x5b, 0xae, 0x98, 0x13, 0x2a, 0x7c, 0xa7, 0x22, 0xaf, 0x86, 0x9b, 0xb9, - 0xe2, 0x7b, 0xb9, 0x34, 0x73, 0x65, 0x03, 0xd5, 0xb1, 0x94, 0x42, 0xeb, 0xe0, 0x54, 0x7f, 0xa9, - 0xc4, 0xcc, 0x1d, 0x08, 0x2c, 0xad, 0x55, 0x03, 0x23, 0x42, 0x3c, 0x5a, 0x54, 0x66, 0x06, 0x67, - 0x0b, 0x8b, 0x73, 0xe9, 0x44, 0xe6, 0xdb, 0x9a, 0xe4, 0x84, 0x6b, 0x09, 0xb2, 0x7e, 0xb7, 0xa7, - 0xac, 0xbe, 0x00, 0x11, 0x61, 0x3f, 0x1b, 0x06, 0xc3, 0x02, 0x1a, 0x9e, 0x02, 0x79, 0x5f, 0x84, - 0xd0, 0x05, 0x8e, 0x88, 0xef, 0x75, 0x13, 0x4e, 0x81, 0x51, 0xc3, 0x22, 0xd8, 0x66, 0x7c, 0x2f, - 0x27, 0xf6, 0xf2, 0xfe, 0xc2, 0xba, 0x09, 0x8f, 0x83, 0x61, 0xe6, 0xb8, 0xfa, 0xad, 0xe2, 0xe0, - 0x8c, 0x32, 0x3b, 0xa6, 0x0d, 0x31, 0xc7, 0xbd, 0x05, 0xe7, 0x00, 0x6c, 0x10, 0x5b, 0x77, 0x9d, - 0x07, 0xdc, 0xa7, 0x6c, 0xdd, 0xa7, 0x18, 0x9a, 0x51, 0x66, 0x07, 0xb5, 0xf1, 0x06, 0xb1, 0x37, - 0xf8, 0xc6, 0xba, 0xbd, 0xc5, 0x69, 0xe7, 0xc1, 0x44, 0x13, 0x59, 0xc4, 0x44, 0xcc, 0xf1, 0xa8, - 0x64, 0x31, 0x90, 0x5b, 0x1c, 0x16, 0x78, 0xb0, 0xbd, 0x27, 0x98, 0x96, 0x91, 0x0b, 0xe7, 0xc0, - 0x8b, 0xe1, 0xaa, 0x4e, 0x31, 0x13, 0xe4, 0x23, 0x82, 0xfc, 0x58, 0xb8, 0xb1, 0x89, 0x19, 0xa7, - 0x3d, 0x0d, 0x46, 0x91, 0x65, 0x39, 0x0f, 0x2c, 0x42, 0x59, 0xf1, 0xc8, 0xcc, 0xe0, 0xec, 0xa8, - 0xd6, 0x5e, 0x80, 0x25, 0x90, 0x37, 0xb1, 0xdd, 0x12, 0x9b, 0x79, 0xb1, 0x19, 0x7e, 0xc3, 0x89, - 0xc0, 0xb3, 0x46, 0x85, 0xc6, 0xd2, 0x4b, 0x3e, 0x00, 0xf9, 0x06, 0x66, 0xc8, 0x44, 0x0c, 0x15, - 0x81, 0xb0, 0xfb, 0x6b, 0x99, 0x5c, 0xee, 0xa6, 0x64, 0x96, 0xbe, 0x1e, 0x82, 0x71, 0x23, 0x73, - 0x93, 0xf1, 0x28, 0xc7, 0xc5, 0xc2, 0x8c, 0x32, 0x3b, 0xa4, 0xe5, 0x1b, 0xc4, 0xde, 0xe4, 0xdf, - 0xb0, 0x02, 0x8e, 0x0b, 0xa1, 0x75, 0x62, 0x23, 0x83, 0x91, 0x26, 0xd6, 0x9b, 0xc8, 0xa2, 0xc5, - 0xa3, 0x33, 0xca, 0x6c, 0x5e, 0x7b, 0x51, 0x6c, 0xad, 0xcb, 0x9d, 0x3b, 0xc8, 0xa2, 0xf1, 0x90, - 0x1e, 0x8b, 0x87, 0x34, 0x7c, 0x08, 0x4e, 0x85, 0x56, 0xc0, 0xa6, 0xee, 0xe1, 0x07, 0xc8, 0x33, - 0x75, 0x13, 0xdb, 0x4e, 0x83, 0x16, 0xc7, 0x85, 0x5e, 0xef, 0xa4, 0xd2, 0x6b, 0xa9, 0x8d, 0xa2, - 0x09, 0x90, 0x6b, 0x02, 0x43, 0x9b, 0x44, 0xc9, 0x1b, 0x50, 0x05, 0x47, 0x5d, 0x8f, 0x38, 0x1c, - 0x4c, 0x98, 0xfd, 0x98, 0x30, 0x7b, 0x64, 0x4d, 0xfd, 0x99, 0x02, 0xce, 0x88, 0x10, 0xba, 0x13, - 0xdc, 0x66, 0x60, 0xbe, 0x25, 0xd3, 0xf4, 0x82, 0xd0, 0xbf, 0x04, 0x5e, 0x08, 0x24, 0xd1, 0x91, - 0x69, 0x7a, 0x98, 0x52, 0xdf, 0x73, 0x6b, 0xf0, 0xdb, 0x27, 0xe5, 0xf1, 0x16, 0x6a, 0x58, 0x17, - 0x55, 0xb9, 0xa1, 0x6a, 0xc7, 0x02, 0xda, 0x25, 0x7f, 0x25, 0x6e, 0xa3, 0x5c, 0xdc, 0x46, 0x17, - 0xf3, 0x1f, 0x7f, 0x5e, 0x1e, 0xf8, 0xe7, 0xe7, 0xe5, 0x01, 0xf5, 0x36, 0x50, 0xf7, 0x13, 0x47, - 0x06, 0xf6, 0x2b, 0xe0, 0x85, 0x10, 0x30, 0x22, 0x8f, 0x76, 0xcc, 0xe8, 0xa0, 0xe7, 0xd2, 0x3c, - 0xaf, 0xe0, 0x46, 0x87, 0x74, 0x1d, 0x0a, 0x26, 0x03, 0x26, 0x2b, 0x18, 0x3b, 0xa4, 0x2f, 0x05, - 0xa3, 0xe2, 0xb4, 0x15, 0x4c, 0x36, 0xf8, 0x73, 0xc6, 0x55, 0xa7, 0xc0, 0x29, 0x01, 0xb8, 0xb5, - 0xe3, 0x39, 0x8c, 0x59, 0x58, 0xe4, 0x72, 0xa9, 0x97, 0xfa, 0x87, 0x20, 0xa5, 0xc7, 0x76, 0xe5, - 0x31, 0x65, 0x50, 0xa0, 0x16, 0xa2, 0x3b, 0x7a, 0x03, 0x33, 0xec, 0x89, 0x13, 0x06, 0x35, 0x20, - 0x96, 0x6e, 0xf2, 0x15, 0xb8, 0x08, 0x4e, 0x74, 0x10, 0xe8, 0xc2, 0xd3, 0x90, 0x6d, 0x60, 0xa1, - 0xe2, 0xa0, 0x76, 0xbc, 0x4d, 0xba, 0x14, 0x6c, 0xc1, 0x1f, 0x80, 0xa2, 0x8d, 0x1f, 0x32, 0xdd, - 0xc3, 0xae, 0x85, 0x6d, 0x42, 0x77, 0x74, 0x03, 0xd9, 0x26, 0x57, 0x16, 0x8b, 0xcc, 0x55, 0x58, - 0x2c, 0x55, 0xfc, 0xfa, 0xa2, 0x12, 0xd4, 0x17, 0x95, 0xad, 0xa0, 0xbe, 0xa8, 0xe5, 0x79, 0xb0, - 0x7e, 0xf2, 0xd7, 0xb2, 0xa2, 0x9d, 0xe4, 0x28, 0x5a, 0x00, 0xb2, 0x1c, 0x60, 0xa8, 0xaf, 0x82, - 0x39, 0xa1, 0x92, 0x86, 0xeb, 0xdc, 0xe7, 0x3d, 0x6c, 0x06, 0x3e, 0x12, 0x09, 0x0b, 0x69, 0x81, - 0x15, 0x70, 0x3e, 0x15, 0xb5, 0xb4, 0xc8, 0x49, 0x30, 0x22, 0x43, 0x53, 0x11, 0xd1, 0x22, 0xbf, - 0xd4, 0x77, 0xc1, 0x2b, 0x02, 0x66, 0xc9, 0xb2, 0x36, 0x10, 0xf1, 0xe8, 0x1d, 0x64, 0x71, 0x1c, - 0x7e, 0x09, 0xb5, 0x56, 0x1b, 0x31, 0xe5, 0x33, 0xff, 0x0b, 0x45, 0xea, 0xd0, 0x03, 0x4e, 0x0a, - 0x75, 0x1f, 0xbc, 0xe8, 0x22, 0xe2, 0xf1, 0x4c, 0xc4, 0x4b, 0x24, 0xe1, 0x11, 0xf2, 0x49, 0x5b, - 0x4d, 0x95, 0x3a, 0xf8, 0x19, 0xfe, 0x11, 0xfc, 0x84, 0xd0, 0xe3, 0xec, 0xb6, 0x2d, 0xc6, 0xdd, - 0x08, 0x89, 0xfa, 0x5f, 0x05, 0x9c, 0xe9, 0xc9, 0x05, 0x57, 0xbb, 0xe6, 0x85, 0xa9, 0x6f, 0x9f, - 0x94, 0x27, 0xfd, 0xb0, 0x89, 0x53, 0x24, 0x24, 0x88, 0xd5, 0x84, 0xf0, 0xcb, 0xc5, 0x71, 0xe2, - 0x14, 0x09, 0x71, 0x78, 0x05, 0x1c, 0x0d, 0xa9, 0x76, 0x71, 0x4b, 0xba, 0xdb, 0xe9, 0x4a, 0xbb, - 0x40, 0xac, 0xf8, 0x05, 0x62, 0x65, 0x63, 0x6f, 0xdb, 0x22, 0xc6, 0x0d, 0xdc, 0xd2, 0xc2, 0xab, - 0xba, 0x81, 0x5b, 0xea, 0x04, 0x80, 0xe2, 0x5e, 0x36, 0x90, 0x87, 0xda, 0x3e, 0xf4, 0x43, 0x70, - 0x3c, 0xb2, 0x2a, 0xaf, 0x65, 0x1d, 0x8c, 0xb8, 0x62, 0x45, 0x56, 0x61, 0xe7, 0x53, 0xde, 0x05, - 0x67, 0x91, 0x8f, 0x92, 0x04, 0x50, 0x6f, 0x4a, 0x7f, 0x88, 0x14, 0x32, 0xb7, 0x5d, 0x86, 0xcd, - 0x75, 0x3b, 0xcc, 0x14, 0xe9, 0xcb, 0xc8, 0xfb, 0xd2, 0xe9, 0x7b, 0xc1, 0x85, 0x75, 0xd2, 0x4b, - 0x9d, 0x75, 0x41, 0xec, 0xbe, 0x70, 0x10, 0x0b, 0x53, 0x1d, 0x05, 0x42, 0xf4, 0x02, 0x31, 0x55, - 0x97, 0xc0, 0x74, 0xe4, 0xc8, 0x03, 0x48, 0xfd, 0xe9, 0x11, 0x30, 0xd3, 0x05, 0x23, 0xfc, 0xd5, - 0xef, 0x53, 0x14, 0xf7, 0x90, 0x5c, 0x46, 0x0f, 0x81, 0x45, 0x30, 0x2c, 0x0a, 0x27, 0xe1, 0x5b, - 0x83, 0xb5, 0x5c, 0x51, 0xd1, 0xfc, 0x05, 0xf8, 0x16, 0x18, 0xf2, 0x78, 0x8e, 0x1b, 0x12, 0xd2, - 0x9c, 0xe3, 0xf7, 0xfb, 0xcd, 0x93, 0xf2, 0x94, 0x5f, 0x2a, 0x52, 0x73, 0xb7, 0x42, 0x9c, 0x6a, - 0x03, 0xb1, 0x9d, 0xca, 0xbb, 0xb8, 0x8e, 0x8c, 0xd6, 0x35, 0x6c, 0x14, 0x15, 0x4d, 0xb0, 0xc0, - 0x73, 0x60, 0x3c, 0x94, 0xca, 0x47, 0x1f, 0x16, 0xf9, 0x75, 0x2c, 0x58, 0x15, 0x05, 0x19, 0xbc, - 0x07, 0x8a, 0x21, 0x99, 0xe1, 0x34, 0x1a, 0x84, 0x52, 0xe2, 0xd8, 0xba, 0x38, 0x75, 0x44, 0x9c, - 0x7a, 0x36, 0xc5, 0xa9, 0xda, 0xc9, 0x00, 0x64, 0x39, 0xc4, 0xd0, 0xb8, 0x14, 0xf7, 0x40, 0x31, - 0x34, 0x6d, 0x1c, 0xfe, 0x48, 0x06, 0xf8, 0x00, 0x24, 0x06, 0x7f, 0x03, 0x14, 0x4c, 0x4c, 0x0d, - 0x8f, 0xb8, 0xa2, 0x94, 0xce, 0x0b, 0xcb, 0x9f, 0x0d, 0x4a, 0xe9, 0xa0, 0xe7, 0x0a, 0xea, 0xe8, - 0x6b, 0x6d, 0x52, 0x19, 0x2b, 0x9d, 0xdc, 0xf0, 0x1e, 0x38, 0x15, 0xca, 0xea, 0xb8, 0xd8, 0x13, - 0x05, 0x6a, 0xe0, 0x0f, 0xa2, 0x8c, 0xac, 0x9d, 0xf9, 0xfa, 0x8b, 0x0b, 0x2f, 0x49, 0xf4, 0xd0, - 0x7f, 0xa4, 0x1f, 0x6c, 0x32, 0x8f, 0xd8, 0x75, 0x6d, 0x32, 0xc0, 0xb8, 0x2d, 0x21, 0x02, 0x37, - 0x39, 0x09, 0x46, 0x7e, 0x84, 0x88, 0x85, 0x4d, 0x51, 0x79, 0xe6, 0x35, 0xf9, 0x05, 0x2f, 0x82, - 0x11, 0xde, 0x77, 0xed, 0x51, 0x51, 0x37, 0x8e, 0x2f, 0xaa, 0xdd, 0xc4, 0xaf, 0x39, 0xb6, 0xb9, - 0x29, 0x28, 0x35, 0xc9, 0x01, 0xb7, 0x40, 0xe8, 0x8d, 0x3a, 0x73, 0x76, 0xb1, 0xed, 0x57, 0x95, - 0xa3, 0xb5, 0xf3, 0xd2, 0xaa, 0x27, 0x9e, 0xb7, 0xea, 0xba, 0xcd, 0xbe, 0xfe, 0xe2, 0x02, 0x90, - 0x87, 0xac, 0xdb, 0x4c, 0x1b, 0x0f, 0x30, 0xb6, 0x04, 0x04, 0x77, 0x9d, 0x10, 0xd5, 0x77, 0x9d, - 0x31, 0xdf, 0x75, 0x82, 0x55, 0xdf, 0x75, 0x5e, 0x07, 0x93, 0x32, 0x7a, 0x31, 0xd5, 0x8d, 0x3d, - 0xcf, 0xe3, 0x3d, 0x06, 0x76, 0x1d, 0x63, 0x47, 0xd4, 0xa0, 0x79, 0xed, 0x44, 0xb8, 0xbd, 0xec, - 0xef, 0xae, 0xf0, 0x4d, 0xf5, 0x63, 0x05, 0x94, 0xbb, 0xc6, 0xb5, 0x4c, 0x1f, 0x18, 0x80, 0x76, - 0x66, 0x90, 0xef, 0xd2, 0x4a, 0xaa, 0x5c, 0xd8, 0x2b, 0xda, 0xb5, 0x0e, 0x60, 0xf5, 0x3e, 0x98, - 0x4f, 0x68, 0xf6, 0x42, 0xda, 0xeb, 0x88, 0x6e, 0x39, 0xf2, 0x0b, 0x1f, 0x4e, 0xe1, 0xaa, 0xde, - 0x01, 0x0b, 0x19, 0x8e, 0x94, 0xe6, 0x38, 0xd3, 0x91, 0x62, 0x88, 0x19, 0x24, 0xcf, 0x42, 0x3b, - 0xd1, 0x89, 0xa2, 0xf4, 0x7c, 0x72, 0x99, 0x1b, 0x8d, 0x99, 0xb4, 0xa9, 0x33, 0x51, 0xcf, 0x5c, - 0x7a, 0x3d, 0xeb, 0xe0, 0xd5, 0x74, 0xe2, 0x48, 0x15, 0xdf, 0x90, 0xa9, 0x4e, 0x49, 0x9f, 0x15, - 0x04, 0x83, 0xaa, 0xca, 0x0c, 0x5f, 0xb3, 0x1c, 0x63, 0x97, 0xbe, 0x6f, 0x33, 0x62, 0xdd, 0xc2, - 0x0f, 0x7d, 0x5f, 0x0b, 0x5e, 0xdb, 0xbb, 0xb2, 0x60, 0x4f, 0xa6, 0x91, 0x12, 0xbc, 0x06, 0x26, - 0xb7, 0xc5, 0xbe, 0xbe, 0xc7, 0x09, 0x74, 0x51, 0x71, 0xfa, 0xfe, 0xac, 0x88, 0x8e, 0x6e, 0x62, - 0x3b, 0x81, 0x5d, 0x5d, 0x92, 0xd5, 0xf7, 0x72, 0x68, 0xba, 0x55, 0xcf, 0x69, 0x2c, 0xcb, 0x0e, - 0x3b, 0x30, 0x77, 0xa4, 0x0b, 0x57, 0xa2, 0x5d, 0xb8, 0xba, 0x0a, 0xce, 0xee, 0x0b, 0xd1, 0x2e, - 0xad, 0xf7, 0x7f, 0xed, 0xde, 0x91, 0x75, 0x7b, 0xc4, 0xb7, 0x52, 0xbf, 0x95, 0xbf, 0x1b, 0x4c, - 0x9a, 0xd5, 0xa4, 0x3e, 0x3d, 0x32, 0x83, 0xc8, 0x45, 0x67, 0x10, 0x67, 0xc1, 0x98, 0xf3, 0xc0, - 0xee, 0x70, 0xa4, 0x41, 0xb1, 0x7f, 0x54, 0x2c, 0x06, 0x09, 0x32, 0x6c, 0xd9, 0x87, 0xba, 0xb5, - 0xec, 0xc3, 0x87, 0xd9, 0xb2, 0x7f, 0x04, 0x0a, 0xc4, 0x26, 0x4c, 0x97, 0xf5, 0xd6, 0x88, 0xc0, - 0x5e, 0xc9, 0x84, 0xbd, 0x6e, 0x13, 0x46, 0x90, 0x45, 0x7e, 0x2c, 0xc6, 0x31, 0xa2, 0x0a, 0xe3, - 0x7d, 0x0b, 0xd5, 0x00, 0x47, 0xf6, 0xab, 0x32, 0xd8, 0x00, 0x13, 0xfe, 0x58, 0x84, 0xee, 0x20, - 0x97, 0xd8, 0xf5, 0xe0, 0xc0, 0x23, 0xe2, 0xc0, 0xb7, 0xd3, 0x15, 0x78, 0x1c, 0x60, 0xd3, 0xe7, - 0xef, 0x38, 0x06, 0xba, 0xf1, 0x75, 0xaa, 0xd6, 0x62, 0xc9, 0x55, 0x8e, 0xe8, 0x78, 0x37, 0x94, - 0xda, 0x13, 0x76, 0x63, 0x45, 0x53, 0x04, 0x43, 0xba, 0xc3, 0x1a, 0x08, 0x26, 0x7d, 0x3a, 0x23, - 0x8d, 0x60, 0x6a, 0x98, 0xae, 0x0d, 0x2b, 0xd4, 0xdb, 0x80, 0x8b, 0xdf, 0x94, 0xc1, 0xb0, 0x38, - 0x0d, 0xfe, 0x43, 0x01, 0x13, 0x49, 0xe7, 0xc2, 0xab, 0xd9, 0x33, 0x7f, 0x74, 0x4a, 0x5a, 0x5a, - 0xea, 0x03, 0xc1, 0x57, 0x58, 0xbd, 0xfe, 0x93, 0x3f, 0xfe, 0xfd, 0xb3, 0x5c, 0x0d, 0x5e, 0xed, - 0x3d, 0x53, 0x0f, 0xad, 0x2b, 0xf5, 0xac, 0x3e, 0xea, 0xb0, 0xf7, 0x63, 0xf8, 0x67, 0x45, 0x16, - 0xff, 0xd1, 0x37, 0x00, 0x5e, 0xc9, 0x2e, 0x64, 0x64, 0x9c, 0x5a, 0xba, 0x7a, 0x70, 0x00, 0xa9, - 0xe4, 0x92, 0x50, 0xf2, 0x6d, 0xf8, 0x56, 0x06, 0x25, 0xfd, 0xa9, 0x66, 0xf5, 0x91, 0x88, 0xd7, - 0xc7, 0xf0, 0xd3, 0x9c, 0x4c, 0x23, 0x89, 0xf3, 0x16, 0xb8, 0x9a, 0x5e, 0xc6, 0xfd, 0xe6, 0x47, - 0xa5, 0xb5, 0xbe, 0x71, 0xa4, 0xca, 0xdb, 0x42, 0xe5, 0xef, 0xc3, 0xbb, 0x29, 0xfe, 0x56, 0x12, - 0xce, 0x2d, 0x23, 0x8d, 0x63, 0xf4, 0x7a, 0xab, 0x8f, 0xe2, 0xcf, 0x66, 0x92, 0x4d, 0x3a, 0xbb, - 0x9d, 0x03, 0xd9, 0x24, 0x61, 0xe4, 0x74, 0x20, 0x9b, 0x24, 0xcd, 0x8a, 0x0e, 0x66, 0x93, 0x88, - 0xda, 0x71, 0x9b, 0xc4, 0x3b, 0xed, 0xc7, 0xf0, 0xf7, 0x8a, 0x6c, 0x8c, 0x23, 0x73, 0x24, 0x78, - 0x39, 0xbd, 0x0e, 0x49, 0xe3, 0xa9, 0xd2, 0x95, 0x03, 0xf3, 0x4b, 0xdd, 0xdf, 0x14, 0xba, 0x2f, - 0xc2, 0xf9, 0xde, 0xba, 0x33, 0x09, 0xe0, 0xff, 0xe1, 0x04, 0xfe, 0x3c, 0x27, 0xdf, 0xf1, 0xfd, - 0x07, 0x43, 0xf0, 0x76, 0x7a, 0x11, 0x53, 0x0d, 0xa4, 0x4a, 0x1b, 0x87, 0x07, 0x28, 0x8d, 0x70, - 0x43, 0x18, 0x61, 0x05, 0x2e, 0xf7, 0x36, 0x82, 0x17, 0x22, 0xb6, 0xa3, 0x22, 0x32, 0x91, 0x86, - 0x3f, 0xcd, 0xc9, 0x12, 0x69, 0xdf, 0xd1, 0x14, 0xbc, 0x95, 0x5e, 0x8b, 0x34, 0x23, 0xb3, 0xd2, - 0xed, 0x43, 0xc3, 0x93, 0x46, 0x59, 0x11, 0x46, 0xb9, 0x02, 0x2f, 0xf5, 0x36, 0x8a, 0xf4, 0x72, - 0xdd, 0xe5, 0xa8, 0xb1, 0xf4, 0xff, 0x1b, 0x05, 0x14, 0x3a, 0x66, 0x3f, 0xf0, 0x8d, 0xf4, 0x72, - 0x46, 0x66, 0x48, 0xa5, 0x37, 0xb3, 0x33, 0x4a, 0x4d, 0xe6, 0x85, 0x26, 0x73, 0x70, 0xb6, 0xb7, - 0x26, 0x7e, 0xb5, 0xd2, 0xf6, 0xed, 0xfd, 0xe7, 0x3f, 0x59, 0x7c, 0x3b, 0xd5, 0x60, 0x2a, 0x8b, - 0x6f, 0xa7, 0x1b, 0x4d, 0x65, 0xf1, 0x6d, 0x87, 0x83, 0xe8, 0xc4, 0xd6, 0xdb, 0x3d, 0x63, 0xec, - 0x32, 0x7f, 0x9b, 0x93, 0x53, 0xdc, 0x34, 0xfd, 0x1c, 0x7c, 0xff, 0xa0, 0x0f, 0xf4, 0xbe, 0x2d, - 0x69, 0xe9, 0xce, 0x61, 0xc3, 0x4a, 0x4b, 0xdd, 0x15, 0x96, 0xda, 0x82, 0x5a, 0xe6, 0x6a, 0x40, - 0x77, 0xb1, 0xd7, 0x36, 0x5a, 0xd2, 0x93, 0xf8, 0xeb, 0x1c, 0x78, 0x39, 0x4d, 0x83, 0x08, 0x37, - 0xfa, 0x78, 0xe8, 0x13, 0x5b, 0xdf, 0xd2, 0x7b, 0x87, 0x88, 0x28, 0x2d, 0x65, 0x08, 0x4b, 0xdd, - 0x83, 0x1f, 0x66, 0xb1, 0x54, 0x74, 0x1e, 0xd6, 0xbb, 0x8a, 0xf8, 0xb7, 0x02, 0x26, 0xbb, 0x8c, - 0x37, 0xe0, 0x72, 0x3f, 0xc3, 0x91, 0xc0, 0x30, 0xd7, 0xfa, 0x03, 0xc9, 0x1e, 0x5f, 0xa1, 0xc6, - 0x5d, 0xe3, 0xeb, 0x5f, 0x8a, 0xec, 0x69, 0x93, 0x5a, 0x77, 0x98, 0x61, 0x24, 0xb4, 0xcf, 0x78, - 0xa0, 0xb4, 0xda, 0x2f, 0x4c, 0xf6, 0xea, 0xb9, 0xcb, 0xa4, 0x01, 0xfe, 0x27, 0xfe, 0xff, 0x07, - 0xd1, 0x59, 0x00, 0x5c, 0xcb, 0x7e, 0x45, 0x89, 0x03, 0x89, 0xd2, 0xf5, 0xfe, 0x81, 0xfa, 0xe8, - 0x19, 0x88, 0x59, 0x7d, 0x14, 0xce, 0x43, 0x1e, 0xc3, 0xbf, 0x04, 0xb5, 0x60, 0x24, 0x3d, 0x65, - 0xa9, 0x05, 0x93, 0x46, 0x1e, 0xa5, 0x2b, 0x07, 0xe6, 0x97, 0xaa, 0xad, 0x0a, 0xd5, 0xae, 0xc2, - 0xcb, 0x59, 0x13, 0x60, 0xcc, 0x8b, 0xff, 0xa7, 0x80, 0x62, 0xb7, 0x8e, 0x1a, 0x5e, 0x3b, 0x70, - 0x6f, 0xda, 0xd1, 0xd4, 0x97, 0x56, 0xfa, 0x44, 0x91, 0x1a, 0xdf, 0x14, 0x1a, 0xaf, 0xc1, 0x95, - 0xec, 0x5d, 0xae, 0x98, 0x03, 0x44, 0x15, 0xaf, 0x7d, 0xf0, 0xe5, 0xd3, 0x69, 0xe5, 0xab, 0xa7, - 0xd3, 0xca, 0xdf, 0x9e, 0x4e, 0x2b, 0x9f, 0x3c, 0x9b, 0x1e, 0xf8, 0xea, 0xd9, 0xf4, 0xc0, 0x9f, - 0x9e, 0x4d, 0x0f, 0xdc, 0xbd, 0x54, 0x27, 0x6c, 0x67, 0x6f, 0xbb, 0x62, 0x38, 0x0d, 0xf9, 0x1f, - 0x54, 0x1d, 0x27, 0x5e, 0x08, 0x4f, 0x6c, 0xbe, 0x5e, 0x7d, 0x18, 0x2b, 0xba, 0x5b, 0x2e, 0xa6, - 0xdb, 0x23, 0x62, 0xc0, 0xf0, 0xbd, 0xff, 0x07, 0x00, 0x00, 0xff, 0xff, 0x93, 0x7a, 0xb2, 0x53, - 0xe1, 0x26, 0x00, 0x00, + // 2568 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x5a, 0xcf, 0x73, 0xdb, 0xc6, + 0xf5, 0x17, 0xa8, 0x1f, 0xa6, 0x96, 0x96, 0x6c, 0xaf, 0x65, 0x8b, 0xa6, 0x1c, 0x51, 0x86, 0xe3, + 0xef, 0x57, 0x91, 0x63, 0x52, 0x52, 0x27, 0x3f, 0xec, 0xc4, 0x3f, 0x44, 0x59, 0x92, 0x39, 0x8e, + 0x6d, 0x05, 0x52, 0x9c, 0x19, 0xa7, 0x2e, 0xba, 0x02, 0xd6, 0xd4, 0x56, 0x24, 0x00, 0x63, 0x57, + 0xb4, 0x59, 0x8f, 0x2f, 0xed, 0x25, 0x87, 0x76, 0x26, 0x99, 0x4e, 0xcf, 0xcd, 0xb9, 0x87, 0x4e, + 0xa7, 0xcd, 0xf4, 0x6f, 0xc8, 0xad, 0x69, 0x7a, 0xe9, 0xa4, 0x53, 0xb7, 0x63, 0xb7, 0x33, 0xbd, + 0xf4, 0xd0, 0xb4, 0xd3, 0x73, 0x67, 0x17, 0x0b, 0x90, 0x80, 0x41, 0x11, 0x10, 0xd5, 0x9b, 0xb0, + 0xfb, 0xde, 0xe7, 0xfd, 0xd8, 0xb7, 0x6f, 0xdf, 0x7b, 0x14, 0x28, 0x13, 0x8b, 0x61, 0xd7, 0xd8, + 0x46, 0xc4, 0xd2, 0x29, 0x36, 0x76, 0x5d, 0xc2, 0x5a, 0x65, 0xc3, 0x68, 0x96, 0x1d, 0xd7, 0x6e, + 0x12, 0x13, 0xbb, 0xe5, 0xe6, 0x42, 0xf9, 0xe1, 0x2e, 0x76, 0x5b, 0x25, 0xc7, 0xb5, 0x99, 0x0d, + 0xcf, 0xc6, 0x30, 0x94, 0x0c, 0xa3, 0x59, 0xf2, 0x19, 0x4a, 0xcd, 0x85, 0xc2, 0xe9, 0x9a, 0x6d, + 0xd7, 0xea, 0xb8, 0x8c, 0x1c, 0x52, 0x46, 0x96, 0x65, 0x33, 0xc4, 0x88, 0x6d, 0x51, 0x0f, 0xa2, + 0x30, 0x51, 0xb3, 0x6b, 0xb6, 0xf8, 0xb3, 0xcc, 0xff, 0x92, 0xab, 0x45, 0xc9, 0x23, 0xbe, 0xb6, + 0x76, 0x1f, 0x94, 0x19, 0x69, 0x60, 0xca, 0x50, 0xc3, 0x91, 0x04, 0x8b, 0x49, 0x54, 0x0d, 0xb4, + 0xf0, 0x78, 0xe6, 0xbb, 0xf1, 0x34, 0x17, 0xca, 0x74, 0x1b, 0xb9, 0xd8, 0xd4, 0x0d, 0xdb, 0xa2, + 0xbb, 0x8d, 0x80, 0xe3, 0xdc, 0x1e, 0x1c, 0x8f, 0x88, 0x8b, 0x25, 0xd9, 0x69, 0x86, 0x2d, 0x13, + 0xbb, 0x0d, 0x62, 0xb1, 0xb2, 0xe1, 0xb6, 0x1c, 0x66, 0x97, 0x77, 0x70, 0xcb, 0xb7, 0xf0, 0x94, + 0x61, 0xd3, 0x86, 0x4d, 0x75, 0xcf, 0x48, 0xef, 0x43, 0x6e, 0xbd, 0xea, 0x7d, 0x95, 0x29, 0x43, + 0x3b, 0xc4, 0xaa, 0x95, 0x9b, 0x0b, 0x5b, 0x98, 0xa1, 0x05, 0xff, 0x5b, 0x52, 0xcd, 0x49, 0xaa, + 0x2d, 0x44, 0xb1, 0xe7, 0xfe, 0x80, 0xd0, 0x41, 0x35, 0x62, 0x09, 0x7f, 0x7a, 0xb4, 0xea, 0x15, + 0x30, 0xf5, 0x3e, 0xa7, 0x58, 0x96, 0x86, 0xac, 0x61, 0x0b, 0x53, 0x42, 0x35, 0xfc, 0x70, 0x17, + 0x53, 0x06, 0x8b, 0x20, 0xe7, 0x9b, 0xa8, 0x13, 0x33, 0xaf, 0xcc, 0x28, 0xb3, 0xa3, 0x1a, 0xf0, + 0x97, 0xaa, 0xa6, 0xfa, 0x04, 0x9c, 0x8e, 0xe7, 0xa7, 0x8e, 0x6d, 0x51, 0x0c, 0x3f, 0x02, 0x63, + 0x35, 0x6f, 0x49, 0xa7, 0x0c, 0x31, 0x2c, 0x20, 0x72, 0x8b, 0xf3, 0xa5, 0x6e, 0x91, 0xd0, 0x5c, + 0x28, 0x45, 0xb0, 0x36, 0x38, 0x5f, 0x65, 0xe8, 0x8b, 0x67, 0xc5, 0x01, 0xed, 0x70, 0xad, 0x63, + 0x4d, 0xfd, 0x85, 0x02, 0x0a, 0x21, 0xe9, 0xcb, 0x1c, 0x2f, 0x50, 0xfe, 0x06, 0x18, 0x76, 0xb6, + 0x11, 0xf5, 0x64, 0x8e, 0x2f, 0x2e, 0x96, 0x12, 0x44, 0x5f, 0x20, 0x7c, 0x9d, 0x73, 0x6a, 0x1e, + 0x00, 0x5c, 0x05, 0xa0, 0xed, 0xb9, 0x7c, 0x46, 0x98, 0xf0, 0x7f, 0x25, 0x79, 0x34, 0xdc, 0xcd, + 0x25, 0x2f, 0xca, 0xa5, 0x9b, 0x4b, 0xeb, 0xa8, 0x86, 0xa5, 0x16, 0x5a, 0x07, 0xa7, 0xfa, 0x73, + 0x25, 0xe2, 0x6e, 0x5f, 0x61, 0xe9, 0xad, 0x0a, 0x18, 0x11, 0xea, 0xd1, 0xbc, 0x32, 0x33, 0x38, + 0x9b, 0x5b, 0x9c, 0x4b, 0xa6, 0x32, 0xdf, 0xd6, 0x24, 0x27, 0x5c, 0x8b, 0xd1, 0xf5, 0xff, 0x7b, + 0xea, 0xea, 0x29, 0x10, 0x52, 0xf6, 0x87, 0x23, 0x60, 0x58, 0x40, 0xc3, 0x53, 0x20, 0xeb, 0xa9, + 0x10, 0x84, 0xc0, 0x21, 0xf1, 0x5d, 0x35, 0xe1, 0x14, 0x18, 0x35, 0xea, 0x04, 0x5b, 0x8c, 0xef, + 0x65, 0xc4, 0x5e, 0xd6, 0x5b, 0xa8, 0x9a, 0xf0, 0x38, 0x18, 0x66, 0xb6, 0xa3, 0xdf, 0xce, 0x0f, + 0xce, 0x28, 0xb3, 0x63, 0xda, 0x10, 0xb3, 0x9d, 0xdb, 0x70, 0x0e, 0xc0, 0x06, 0xb1, 0x74, 0xc7, + 0x7e, 0xc4, 0x63, 0xca, 0xd2, 0x3d, 0x8a, 0xa1, 0x19, 0x65, 0x76, 0x50, 0x1b, 0x6f, 0x10, 0x6b, + 0x9d, 0x6f, 0x54, 0xad, 0x4d, 0x4e, 0x3b, 0x0f, 0x26, 0x9a, 0xa8, 0x4e, 0x4c, 0xc4, 0x6c, 0x97, + 0x4a, 0x16, 0x03, 0x39, 0xf9, 0x61, 0x81, 0x07, 0xdb, 0x7b, 0x82, 0x69, 0x19, 0x39, 0x70, 0x0e, + 0x1c, 0x0b, 0x56, 0x75, 0x8a, 0x99, 0x20, 0x1f, 0x11, 0xe4, 0x47, 0x82, 0x8d, 0x0d, 0xcc, 0x38, + 0xed, 0x69, 0x30, 0x8a, 0xea, 0x75, 0xfb, 0x51, 0x9d, 0x50, 0x96, 0x3f, 0x34, 0x33, 0x38, 0x3b, + 0xaa, 0xb5, 0x17, 0x60, 0x01, 0x64, 0x4d, 0x6c, 0xb5, 0xc4, 0x66, 0x56, 0x6c, 0x06, 0xdf, 0x70, + 0xc2, 0x8f, 0xac, 0x51, 0x61, 0xb1, 0x8c, 0x92, 0x0f, 0x41, 0xb6, 0x81, 0x19, 0x32, 0x11, 0x43, + 0x79, 0x20, 0xfc, 0xfe, 0x46, 0xaa, 0x90, 0xbb, 0x25, 0x99, 0x65, 0xac, 0x07, 0x60, 0xdc, 0xc9, + 0xdc, 0x65, 0xfc, 0x96, 0xe3, 0x7c, 0x6e, 0x46, 0x99, 0x1d, 0xd2, 0xb2, 0x0d, 0x62, 0x6d, 0xf0, + 0x6f, 0x58, 0x02, 0xc7, 0x85, 0xd2, 0x3a, 0xb1, 0x90, 0xc1, 0x48, 0x13, 0xeb, 0x4d, 0x54, 0xa7, + 0xf9, 0xc3, 0x33, 0xca, 0x6c, 0x56, 0x3b, 0x26, 0xb6, 0xaa, 0x72, 0xe7, 0x2e, 0xaa, 0xd3, 0xe8, + 0x95, 0x1e, 0x8b, 0x5e, 0x69, 0xf8, 0x18, 0x9c, 0x0a, 0xbc, 0x80, 0x4d, 0xdd, 0xc5, 0x8f, 0x90, + 0x6b, 0xea, 0x26, 0xb6, 0xec, 0x06, 0xcd, 0x8f, 0x0b, 0xbb, 0xde, 0x4d, 0x64, 0xd7, 0x52, 0x1b, + 0x45, 0x13, 0x20, 0xd7, 0x05, 0x86, 0x36, 0x89, 0xe2, 0x37, 0xa0, 0x0a, 0x0e, 0x3b, 0x2e, 0xb1, + 0x39, 0x98, 0x70, 0xfb, 0x11, 0xe1, 0xf6, 0xd0, 0x1a, 0xb4, 0xc0, 0x09, 0x62, 0x3d, 0x70, 0xb9, + 0x41, 0xb6, 0xa5, 0x3b, 0xc8, 0x45, 0x0d, 0xcc, 0xb0, 0x4b, 0xf3, 0x47, 0x85, 0x66, 0x17, 0x13, + 0x69, 0x56, 0x0d, 0x10, 0xd6, 0x03, 0x00, 0x6d, 0x82, 0xc4, 0xac, 0xaa, 0x3f, 0x56, 0xc0, 0x19, + 0x71, 0x65, 0xef, 0xfa, 0xd1, 0xe3, 0x1f, 0xd7, 0x92, 0x69, 0xba, 0x7e, 0xaa, 0xb9, 0x0c, 0x8e, + 0xfa, 0xf8, 0x3a, 0x32, 0x4d, 0x17, 0x53, 0xea, 0xdd, 0x94, 0x0a, 0xfc, 0xe6, 0x59, 0x71, 0xbc, + 0x85, 0x1a, 0xf5, 0x4b, 0xaa, 0xdc, 0x50, 0xb5, 0x23, 0x3e, 0xed, 0x92, 0xb7, 0x12, 0x3d, 0x93, + 0x4c, 0xf4, 0x4c, 0x2e, 0x65, 0x3f, 0xfe, 0xac, 0x38, 0xf0, 0xf7, 0xcf, 0x8a, 0x03, 0xea, 0x1d, + 0xa0, 0xee, 0xa5, 0x8e, 0x4c, 0x24, 0xaf, 0x81, 0xa3, 0x01, 0x60, 0x48, 0x1f, 0xed, 0x88, 0xd1, + 0x41, 0xcf, 0xb5, 0x79, 0xd9, 0xc0, 0xf5, 0x0e, 0xed, 0x3a, 0x0c, 0x8c, 0x07, 0x8c, 0x37, 0x30, + 0x22, 0xa4, 0x2f, 0x03, 0xc3, 0xea, 0xb4, 0x0d, 0x8c, 0x77, 0xf8, 0x4b, 0xce, 0x55, 0xa7, 0xc0, + 0x29, 0x01, 0xb8, 0xb9, 0xed, 0xda, 0x8c, 0xd5, 0xb1, 0x78, 0x3b, 0xa4, 0x5d, 0xea, 0xef, 0xfc, + 0x27, 0x24, 0xb2, 0x2b, 0xc5, 0x14, 0x41, 0x8e, 0xd6, 0x11, 0xdd, 0xd6, 0x45, 0x34, 0x08, 0x09, + 0x83, 0x1a, 0x10, 0x4b, 0xb7, 0xf8, 0x0a, 0x5c, 0x04, 0x27, 0x3a, 0x08, 0x74, 0x11, 0xd9, 0xc8, + 0x32, 0xb0, 0x30, 0x71, 0x50, 0x3b, 0xde, 0x26, 0x5d, 0xf2, 0xb7, 0xe0, 0x77, 0x40, 0xde, 0xc2, + 0x8f, 0x99, 0xee, 0x62, 0xa7, 0x8e, 0x2d, 0x42, 0xb7, 0x75, 0x03, 0x59, 0x26, 0x37, 0x16, 0x8b, + 0x4c, 0x99, 0x5b, 0x2c, 0x94, 0xbc, 0x7a, 0xa6, 0xe4, 0xd7, 0x33, 0xa5, 0x4d, 0xbf, 0x9e, 0xa9, + 0x64, 0x79, 0x72, 0xf8, 0xe4, 0xcf, 0x45, 0x45, 0x3b, 0xc9, 0x51, 0x34, 0x1f, 0x64, 0xd9, 0xc7, + 0x50, 0x5f, 0x07, 0x73, 0xc2, 0x24, 0x0d, 0xd7, 0xf8, 0x1d, 0x73, 0xb1, 0xe9, 0xc7, 0x48, 0xe8, + 0x1a, 0x4a, 0x0f, 0xac, 0x80, 0xf3, 0x89, 0xa8, 0xa5, 0x47, 0x4e, 0x82, 0x11, 0x99, 0x0a, 0x14, + 0x71, 0x3b, 0xe5, 0x97, 0xfa, 0x1e, 0x78, 0x4d, 0xc0, 0x2c, 0xd5, 0xeb, 0xeb, 0x88, 0xb8, 0xf4, + 0x2e, 0xaa, 0x73, 0x1c, 0x7e, 0x08, 0x95, 0x56, 0x1b, 0x31, 0x61, 0x59, 0xf1, 0x33, 0x45, 0xda, + 0xd0, 0x03, 0x4e, 0x2a, 0xf5, 0x10, 0x1c, 0x73, 0x10, 0x71, 0x79, 0xe6, 0xe3, 0x25, 0x99, 0x88, + 0x08, 0xf9, 0x84, 0xae, 0x26, 0x4a, 0x08, 0x5c, 0x86, 0x27, 0x82, 0x4b, 0x08, 0x22, 0xce, 0x6a, + 0xfb, 0x62, 0xdc, 0x09, 0x91, 0xa8, 0xff, 0x56, 0xc0, 0x99, 0x9e, 0x5c, 0x70, 0xb5, 0x6b, 0x5e, + 0x98, 0xfa, 0xe6, 0x59, 0x71, 0xd2, 0xbb, 0x36, 0x51, 0x8a, 0x98, 0x04, 0xb1, 0x1a, 0x73, 0xfd, + 0x32, 0x51, 0x9c, 0x28, 0x45, 0xcc, 0x3d, 0xbc, 0x0a, 0x0e, 0x07, 0x54, 0x3b, 0xb8, 0x25, 0xc3, + 0xed, 0x74, 0xa9, 0x5d, 0x90, 0x96, 0xbc, 0x82, 0xb4, 0xb4, 0xbe, 0xbb, 0x55, 0x27, 0xc6, 0x4d, + 0xdc, 0xd2, 0x82, 0xa3, 0xba, 0x89, 0x5b, 0xea, 0x04, 0x80, 0xe2, 0x5c, 0x44, 0x86, 0x0c, 0x62, + 0xe8, 0xbb, 0xe0, 0x78, 0x68, 0x55, 0x1e, 0x4b, 0x15, 0x8c, 0x88, 0x04, 0x4d, 0x65, 0xd5, 0x77, + 0x3e, 0xe1, 0x59, 0x70, 0x16, 0xf9, 0x08, 0x4a, 0x00, 0xf5, 0x96, 0x8c, 0x87, 0x50, 0xe1, 0x74, + 0xc7, 0x61, 0xd8, 0xac, 0x5a, 0x41, 0xa6, 0x48, 0x5e, 0xb6, 0x3e, 0x94, 0x41, 0xdf, 0x0b, 0x2e, + 0xa8, 0xcb, 0x5e, 0xe9, 0xac, 0x43, 0x22, 0xe7, 0x85, 0xfd, 0xbb, 0x30, 0xd5, 0x51, 0x90, 0x84, + 0x0f, 0x10, 0x53, 0x75, 0x09, 0x4c, 0x87, 0x44, 0xee, 0x43, 0xeb, 0x4f, 0x0f, 0x81, 0x99, 0x2e, + 0x18, 0xc1, 0x5f, 0xfd, 0x3e, 0x45, 0xd1, 0x08, 0xc9, 0xa4, 0x8c, 0x10, 0x98, 0x07, 0xc3, 0xa2, + 0x50, 0x13, 0xb1, 0x35, 0x58, 0xc9, 0xe4, 0x15, 0xcd, 0x5b, 0x80, 0x17, 0xc1, 0x90, 0xcb, 0x73, + 0xdc, 0x90, 0xd0, 0xe6, 0x1c, 0x3f, 0xdf, 0xaf, 0x9f, 0x15, 0xa7, 0xbc, 0xd2, 0x94, 0x9a, 0x3b, + 0x25, 0x62, 0x97, 0x1b, 0x88, 0x6d, 0x97, 0xde, 0xc3, 0x35, 0x64, 0xb4, 0xae, 0x63, 0x23, 0xaf, + 0x68, 0x82, 0x05, 0x9e, 0x03, 0xe3, 0x81, 0x56, 0x1e, 0xfa, 0xb0, 0xc8, 0xaf, 0x63, 0xfe, 0xaa, + 0x28, 0x00, 0xe1, 0x7d, 0x90, 0x0f, 0xc8, 0x0c, 0xbb, 0xd1, 0x20, 0x94, 0xf2, 0x2a, 0x41, 0x48, + 0x1d, 0x11, 0x52, 0xcf, 0x26, 0x90, 0xaa, 0x9d, 0xf4, 0x41, 0x96, 0x03, 0x0c, 0x8d, 0x6b, 0x71, + 0x1f, 0xe4, 0x03, 0xd7, 0x46, 0xe1, 0x0f, 0xa5, 0x80, 0xf7, 0x41, 0x22, 0xf0, 0x37, 0x41, 0xce, + 0xc4, 0xd4, 0x70, 0x89, 0x23, 0x4a, 0xf7, 0xac, 0xf0, 0xfc, 0x59, 0xbf, 0x74, 0xf7, 0x7b, 0x3c, + 0xbf, 0x6e, 0xbf, 0xde, 0x26, 0x95, 0x77, 0xa5, 0x93, 0x1b, 0xde, 0x07, 0xa7, 0x02, 0x5d, 0x6d, + 0x07, 0xbb, 0xa2, 0x20, 0xf6, 0xe3, 0x41, 0x94, 0xad, 0x95, 0x33, 0x5f, 0x7d, 0x7e, 0xe1, 0x15, + 0x89, 0x1e, 0xc4, 0x8f, 0x8c, 0x83, 0x0d, 0xe6, 0x12, 0xab, 0xa6, 0x4d, 0xfa, 0x18, 0x77, 0x24, + 0x84, 0x1f, 0x26, 0x27, 0xc1, 0xc8, 0xf7, 0x10, 0xa9, 0x63, 0x53, 0x54, 0xba, 0x59, 0x4d, 0x7e, + 0xc1, 0x4b, 0x60, 0x84, 0xf7, 0x79, 0xbb, 0x54, 0xd4, 0xa9, 0xe3, 0x8b, 0x6a, 0x37, 0xf5, 0x2b, + 0xb6, 0x65, 0x6e, 0x08, 0x4a, 0x4d, 0x72, 0xc0, 0x4d, 0x10, 0x44, 0xa3, 0xce, 0xec, 0x1d, 0x6c, + 0x79, 0x55, 0xec, 0x68, 0xe5, 0xbc, 0xf4, 0xea, 0x89, 0x97, 0xbd, 0x5a, 0xb5, 0xd8, 0x57, 0x9f, + 0x5f, 0x00, 0x52, 0x48, 0xd5, 0x62, 0xda, 0xb8, 0x8f, 0xb1, 0x29, 0x20, 0x78, 0xe8, 0x04, 0xa8, + 0x5e, 0xe8, 0x8c, 0x79, 0xa1, 0xe3, 0xaf, 0x7a, 0xa1, 0xf3, 0x26, 0x98, 0x94, 0xb7, 0x17, 0x53, + 0xdd, 0xd8, 0x75, 0x5d, 0xde, 0xd3, 0x60, 0xc7, 0x36, 0xb6, 0x45, 0xcd, 0x9b, 0xd5, 0x4e, 0x04, + 0xdb, 0xcb, 0xde, 0xee, 0x0a, 0xdf, 0x54, 0x3f, 0x56, 0x40, 0xb1, 0xeb, 0xbd, 0x96, 0xe9, 0x03, + 0x03, 0xd0, 0xce, 0x0c, 0xf2, 0x5d, 0x5a, 0x49, 0x94, 0x0b, 0x7b, 0xdd, 0x76, 0xad, 0x03, 0x58, + 0x7d, 0x08, 0xe6, 0x63, 0x9a, 0xcb, 0x80, 0xf6, 0x06, 0xa2, 0x9b, 0xb6, 0xfc, 0xc2, 0x07, 0x53, + 0xb8, 0xaa, 0x77, 0xc1, 0x42, 0x0a, 0x91, 0xd2, 0x1d, 0x67, 0x3a, 0x52, 0x0c, 0x31, 0xfd, 0xe4, + 0x99, 0x6b, 0x27, 0x3a, 0x51, 0x94, 0x9e, 0x8f, 0x2f, 0x73, 0xc3, 0x77, 0x26, 0x69, 0xea, 0x8c, + 0xb5, 0x33, 0x93, 0xdc, 0xce, 0x1a, 0x78, 0x3d, 0x99, 0x3a, 0xd2, 0xc4, 0xb7, 0x64, 0xaa, 0x53, + 0x92, 0x67, 0x05, 0xc1, 0xa0, 0xaa, 0x32, 0xc3, 0x57, 0xea, 0xb6, 0xb1, 0x43, 0x3f, 0xb0, 0x18, + 0xa9, 0xdf, 0xc6, 0x8f, 0xbd, 0x58, 0xf3, 0x5f, 0xdb, 0x7b, 0xb2, 0x60, 0x8f, 0xa7, 0x91, 0x1a, + 0xbc, 0x01, 0x26, 0xb7, 0xc4, 0xbe, 0xbe, 0xcb, 0x09, 0x74, 0x51, 0x71, 0x7a, 0xf1, 0xac, 0x88, + 0x0e, 0x72, 0x62, 0x2b, 0x86, 0x5d, 0x5d, 0x92, 0xd5, 0xf7, 0x72, 0xe0, 0xba, 0x55, 0xd7, 0x6e, + 0x2c, 0xcb, 0x8e, 0xde, 0x77, 0x77, 0xa8, 0xeb, 0x57, 0xc2, 0x5d, 0xbf, 0xba, 0x0a, 0xce, 0xee, + 0x09, 0xd1, 0x2e, 0xad, 0xf7, 0x7e, 0xed, 0xde, 0x95, 0x75, 0x7b, 0x28, 0xb6, 0x12, 0xbf, 0x95, + 0xbf, 0x1e, 0x8a, 0x9b, 0x0d, 0x25, 0x96, 0x1e, 0x9a, 0x79, 0x64, 0xc2, 0x33, 0x8f, 0xb3, 0x60, + 0xcc, 0x7e, 0x64, 0x75, 0x04, 0xd2, 0xa0, 0xd8, 0x3f, 0x2c, 0x16, 0xfd, 0x04, 0x19, 0x8c, 0x08, + 0x86, 0xba, 0x8d, 0x08, 0x86, 0x0f, 0x72, 0x44, 0xf0, 0x00, 0xe4, 0x88, 0x45, 0x98, 0x2e, 0xeb, + 0xad, 0x11, 0x81, 0xbd, 0x92, 0x0a, 0xbb, 0x6a, 0x11, 0x46, 0x50, 0x9d, 0x7c, 0x1f, 0x45, 0x1a, + 0x63, 0xc0, 0x91, 0xbd, 0xaa, 0x0c, 0x36, 0xc0, 0x84, 0x37, 0x86, 0xa1, 0xdb, 0xc8, 0x21, 0x56, + 0xcd, 0x17, 0x78, 0x48, 0x08, 0x7c, 0x27, 0x59, 0x81, 0xc7, 0x01, 0x36, 0x3c, 0xfe, 0x0e, 0x31, + 0xd0, 0x89, 0xae, 0xd3, 0xee, 0xdd, 0x7e, 0xf6, 0x7f, 0xd3, 0xed, 0x57, 0x22, 0xc9, 0x5c, 0x8e, + 0x20, 0x79, 0xf7, 0x95, 0x38, 0xf2, 0x76, 0x22, 0x45, 0x5a, 0x08, 0x43, 0x86, 0xdf, 0x1a, 0xf0, + 0x27, 0x99, 0x3a, 0x23, 0x0d, 0x7f, 0x2a, 0x9a, 0xac, 0xed, 0xcb, 0xd5, 0xda, 0x80, 0x8b, 0x5f, + 0x17, 0xc1, 0xb0, 0x90, 0x06, 0xff, 0xa6, 0x80, 0x89, 0x38, 0xb9, 0xf0, 0x5a, 0xfa, 0x97, 0x26, + 0x3c, 0x05, 0x2e, 0x2c, 0xf5, 0x81, 0xe0, 0x19, 0xac, 0xde, 0xf8, 0xc1, 0xef, 0xff, 0xfa, 0x93, + 0x4c, 0x05, 0x5e, 0xeb, 0xfd, 0x9b, 0x41, 0xe0, 0x5d, 0x69, 0x67, 0xf9, 0x49, 0x87, 0xbf, 0x9f, + 0xc2, 0x3f, 0x2a, 0xb2, 0xd9, 0x08, 0xbf, 0x39, 0xf0, 0x6a, 0x7a, 0x25, 0x43, 0xe3, 0xe2, 0xc2, + 0xb5, 0xfd, 0x03, 0x48, 0x23, 0x97, 0x84, 0x91, 0xef, 0xc0, 0x8b, 0x29, 0x8c, 0xf4, 0xa6, 0xb6, + 0xe5, 0x27, 0x22, 0x3f, 0x3c, 0x85, 0x9f, 0x66, 0x64, 0xda, 0x8a, 0x9d, 0xef, 0xc0, 0xd5, 0xe4, + 0x3a, 0xee, 0x35, 0xaf, 0x2a, 0xac, 0xf5, 0x8d, 0x23, 0x4d, 0xde, 0x12, 0x26, 0x7f, 0x1b, 0xde, + 0x4b, 0xf0, 0x5b, 0x50, 0x30, 0x97, 0x0d, 0x35, 0xaa, 0xe1, 0xe3, 0x2d, 0x3f, 0x89, 0x3e, 0xd3, + 0x71, 0x3e, 0xe9, 0xec, 0xae, 0xf6, 0xe5, 0x93, 0x98, 0x11, 0xd7, 0xbe, 0x7c, 0x12, 0x37, 0x9b, + 0xda, 0x9f, 0x4f, 0x42, 0x66, 0x47, 0x7d, 0x12, 0xed, 0xec, 0x9f, 0xc2, 0xdf, 0x2a, 0xb2, 0x11, + 0x0f, 0xcd, 0xad, 0xe0, 0x95, 0xe4, 0x36, 0xc4, 0x8d, 0xc3, 0x0a, 0x57, 0xf7, 0xcd, 0x2f, 0x6d, + 0x7f, 0x5b, 0xd8, 0xbe, 0x08, 0xe7, 0x7b, 0xdb, 0xce, 0x24, 0x80, 0xf7, 0xc3, 0x10, 0xfc, 0x69, + 0x46, 0xd6, 0x0d, 0x7b, 0x0f, 0xa2, 0xe0, 0x9d, 0xe4, 0x2a, 0x26, 0x1a, 0x80, 0x15, 0xd6, 0x0f, + 0x0e, 0x50, 0x3a, 0xe1, 0xa6, 0x70, 0xc2, 0x0a, 0x5c, 0xee, 0xed, 0x04, 0x37, 0x40, 0x6c, 0xdf, + 0x8a, 0xd0, 0xc4, 0x1d, 0xfe, 0x28, 0x23, 0x4b, 0xb2, 0x3d, 0x47, 0x61, 0xf0, 0x76, 0x72, 0x2b, + 0x92, 0x8c, 0xe8, 0x0a, 0x77, 0x0e, 0x0c, 0x4f, 0x3a, 0x65, 0x45, 0x38, 0xe5, 0x2a, 0xbc, 0xdc, + 0xdb, 0x29, 0x32, 0xca, 0x75, 0x87, 0xa3, 0x46, 0xd2, 0xff, 0xaf, 0x14, 0x90, 0xeb, 0x98, 0x35, + 0xc1, 0xb7, 0x92, 0xeb, 0x19, 0x9a, 0x59, 0x15, 0xde, 0x4e, 0xcf, 0x28, 0x2d, 0x99, 0x17, 0x96, + 0xcc, 0xc1, 0xd9, 0xde, 0x96, 0x78, 0xd5, 0x51, 0x3b, 0xb6, 0xf7, 0x9e, 0x37, 0xa5, 0x89, 0xed, + 0x44, 0x83, 0xb0, 0x34, 0xb1, 0x9d, 0x6c, 0x14, 0x96, 0x26, 0xb6, 0x6d, 0x0e, 0xa2, 0x13, 0x4b, + 0x6f, 0xf7, 0xa8, 0x91, 0xc3, 0xfc, 0x4d, 0x46, 0x4e, 0x8d, 0x93, 0xf4, 0x8f, 0xf0, 0x83, 0xfd, + 0x3e, 0xd0, 0x7b, 0xb6, 0xc0, 0x85, 0xbb, 0x07, 0x0d, 0x2b, 0x3d, 0x75, 0x4f, 0x78, 0x6a, 0x13, + 0x6a, 0xa9, 0xab, 0x01, 0xdd, 0xc1, 0x6e, 0xdb, 0x69, 0x71, 0x4f, 0xe2, 0x2f, 0x33, 0xe0, 0xd5, + 0x24, 0x0d, 0x29, 0x5c, 0xef, 0xe3, 0xa1, 0x8f, 0x6d, 0xb5, 0x0b, 0xef, 0x1f, 0x20, 0xa2, 0xf4, + 0x94, 0x21, 0x3c, 0x75, 0x1f, 0x7e, 0x94, 0xc6, 0x53, 0xe1, 0xf9, 0x5b, 0xef, 0x2a, 0xe2, 0x9f, + 0x0a, 0x98, 0xec, 0x32, 0x4e, 0x81, 0xcb, 0xfd, 0x0c, 0x63, 0x7c, 0xc7, 0x5c, 0xef, 0x0f, 0x24, + 0xfd, 0xfd, 0x0a, 0x2c, 0xee, 0x7a, 0xbf, 0xfe, 0xa1, 0xc8, 0x1e, 0x3a, 0x6e, 0x54, 0x00, 0x53, + 0x8c, 0xa0, 0xf6, 0x18, 0x47, 0x14, 0x56, 0xfb, 0x85, 0x49, 0x5f, 0x3d, 0x77, 0x99, 0x6c, 0xc0, + 0x7f, 0x45, 0xff, 0xbf, 0x22, 0x3c, 0x7b, 0x80, 0x6b, 0xe9, 0x8f, 0x28, 0x76, 0x00, 0x52, 0xb8, + 0xd1, 0x3f, 0x50, 0x1f, 0x3d, 0x03, 0x31, 0xcb, 0x4f, 0x82, 0xf9, 0xcb, 0x53, 0xf8, 0x27, 0xbf, + 0x16, 0x0c, 0xa5, 0xa7, 0x34, 0xb5, 0x60, 0xdc, 0x88, 0xa5, 0x70, 0x75, 0xdf, 0xfc, 0xd2, 0xb4, + 0x55, 0x61, 0xda, 0x35, 0x78, 0x25, 0x6d, 0x02, 0x8c, 0x44, 0xf1, 0x7f, 0x14, 0x90, 0xef, 0xd6, + 0x51, 0xc3, 0xeb, 0xfb, 0xee, 0x4d, 0x3b, 0x9a, 0xfa, 0xc2, 0x4a, 0x9f, 0x28, 0xd2, 0xe2, 0x5b, + 0xc2, 0xe2, 0x35, 0xb8, 0x92, 0xbe, 0xcb, 0x15, 0x73, 0x80, 0xb0, 0xe1, 0x95, 0x0f, 0xbf, 0x78, + 0x3e, 0xad, 0x7c, 0xf9, 0x7c, 0x5a, 0xf9, 0xcb, 0xf3, 0x69, 0xe5, 0x93, 0x17, 0xd3, 0x03, 0x5f, + 0xbe, 0x98, 0x1e, 0xf8, 0xc3, 0x8b, 0xe9, 0x81, 0x7b, 0x97, 0x6b, 0x84, 0x6d, 0xef, 0x6e, 0x95, + 0x0c, 0xbb, 0x21, 0xff, 0x43, 0xac, 0x43, 0xe2, 0x85, 0x40, 0x62, 0xf3, 0xcd, 0xf2, 0xe3, 0x48, + 0xd1, 0xdd, 0x72, 0x30, 0xdd, 0x1a, 0x11, 0x03, 0x86, 0x6f, 0xfd, 0x37, 0x00, 0x00, 0xff, 0xff, + 0x3e, 0x9b, 0x1b, 0x77, 0xc1, 0x27, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -2977,6 +2996,20 @@ func (m *Chain) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if m.InfractionParameters != nil { + { + size, err := m.InfractionParameters.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0x82 + } if len(m.Prioritylist) > 0 { for iNdEx := len(m.Prioritylist) - 1; iNdEx >= 0; iNdEx-- { i -= len(m.Prioritylist[iNdEx]) @@ -3269,12 +3302,12 @@ func (m *QueryThrottleStateResponse) MarshalToSizedBuffer(dAtA []byte) (int, err _ = i var l int _ = l - n6, err6 := github_com_cosmos_gogoproto_types.StdTimeMarshalTo(m.NextReplenishCandidate, dAtA[i-github_com_cosmos_gogoproto_types.SizeOfStdTime(m.NextReplenishCandidate):]) - if err6 != nil { - return 0, err6 + n7, err7 := github_com_cosmos_gogoproto_types.StdTimeMarshalTo(m.NextReplenishCandidate, dAtA[i-github_com_cosmos_gogoproto_types.SizeOfStdTime(m.NextReplenishCandidate):]) + if err7 != nil { + return 0, err7 } - i -= n6 - i = encodeVarintQuery(dAtA, i, uint64(n6)) + i -= n7 + i = encodeVarintQuery(dAtA, i, uint64(n7)) i-- dAtA[i] = 0x1a if m.SlashMeterAllowance != 0 { @@ -4078,6 +4111,18 @@ func (m *QueryConsumerChainResponse) MarshalToSizedBuffer(dAtA []byte) (int, err _ = i var l int _ = l + if m.InfractionParameters != nil { + { + size, err := m.InfractionParameters.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x42 + } if m.PowerShapingParams != nil { { size, err := m.PowerShapingParams.MarshalToSizedBuffer(dAtA[:i]) @@ -4193,12 +4238,12 @@ func (m *QueryConsumerGenesisTimeResponse) MarshalToSizedBuffer(dAtA []byte) (in _ = i var l int _ = l - n14, err14 := github_com_cosmos_gogoproto_types.StdTimeMarshalTo(m.GenesisTime, dAtA[i-github_com_cosmos_gogoproto_types.SizeOfStdTime(m.GenesisTime):]) - if err14 != nil { - return 0, err14 + n16, err16 := github_com_cosmos_gogoproto_types.StdTimeMarshalTo(m.GenesisTime, dAtA[i-github_com_cosmos_gogoproto_types.SizeOfStdTime(m.GenesisTime):]) + if err16 != nil { + return 0, err16 } - i -= n14 - i = encodeVarintQuery(dAtA, i, uint64(n14)) + i -= n16 + i = encodeVarintQuery(dAtA, i, uint64(n16)) i-- dAtA[i] = 0xa return len(dAtA) - i, nil @@ -4338,6 +4383,10 @@ func (m *Chain) Size() (n int) { n += 1 + l + sovQuery(uint64(l)) } } + if m.InfractionParameters != nil { + l = m.InfractionParameters.Size() + n += 2 + l + sovQuery(uint64(l)) + } return n } @@ -4773,6 +4822,10 @@ func (m *QueryConsumerChainResponse) Size() (n int) { l = m.PowerShapingParams.Size() n += 1 + l + sovQuery(uint64(l)) } + if m.InfractionParameters != nil { + l = m.InfractionParameters.Size() + n += 1 + l + sovQuery(uint64(l)) + } return n } @@ -5633,6 +5686,42 @@ func (m *Chain) Unmarshal(dAtA []byte) error { } m.Prioritylist = append(m.Prioritylist, string(dAtA[iNdEx:postIndex])) iNdEx = postIndex + case 16: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field InfractionParameters", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.InfractionParameters == nil { + m.InfractionParameters = &InfractionParameters{} + } + if err := m.InfractionParameters.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipQuery(dAtA[iNdEx:]) @@ -8552,6 +8641,42 @@ func (m *QueryConsumerChainResponse) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field InfractionParameters", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.InfractionParameters == nil { + m.InfractionParameters = &InfractionParameters{} + } + if err := m.InfractionParameters.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipQuery(dAtA[iNdEx:]) diff --git a/x/ccv/provider/types/tx.pb.go b/x/ccv/provider/types/tx.pb.go index f2a5989b6a..b23a9939e3 100644 --- a/x/ccv/provider/types/tx.pb.go +++ b/x/ccv/provider/types/tx.pb.go @@ -1337,6 +1337,8 @@ type MsgCreateConsumer struct { PowerShapingParameters *PowerShapingParameters `protobuf:"bytes,5,opt,name=power_shaping_parameters,json=powerShapingParameters,proto3" json:"power_shaping_parameters,omitempty"` // allowlisted reward denoms of the consumer AllowlistedRewardDenoms *AllowlistedRewardDenoms `protobuf:"bytes,6,opt,name=allowlisted_reward_denoms,json=allowlistedRewardDenoms,proto3" json:"allowlisted_reward_denoms,omitempty"` + // infraction parameters for slashing and jailing + InfractionParameters *InfractionParameters `protobuf:"bytes,7,opt,name=infraction_parameters,json=infractionParameters,proto3" json:"infraction_parameters,omitempty"` } func (m *MsgCreateConsumer) Reset() { *m = MsgCreateConsumer{} } @@ -1414,6 +1416,13 @@ func (m *MsgCreateConsumer) GetAllowlistedRewardDenoms() *AllowlistedRewardDenom return nil } +func (m *MsgCreateConsumer) GetInfractionParameters() *InfractionParameters { + if m != nil { + return m.InfractionParameters + } + return nil +} + // MsgCreateConsumerResponse defines response type for MsgCreateConsumer type MsgCreateConsumerResponse struct { ConsumerId string `protobuf:"bytes,1,opt,name=consumer_id,json=consumerId,proto3" json:"consumer_id,omitempty"` @@ -1479,6 +1488,8 @@ type MsgUpdateConsumer struct { // the chain id CANNOT be updated. // This field is optional and can remain empty (i.e., `new_chain_id = ""`) or correspond to the chain id the chain already has. NewChainId string `protobuf:"bytes,8,opt,name=new_chain_id,json=newChainId,proto3" json:"new_chain_id,omitempty"` + // infraction parameters for slashing and jailing + InfractionParameters *InfractionParameters `protobuf:"bytes,9,opt,name=infraction_parameters,json=infractionParameters,proto3" json:"infraction_parameters,omitempty"` } func (m *MsgUpdateConsumer) Reset() { *m = MsgUpdateConsumer{} } @@ -1570,6 +1581,13 @@ func (m *MsgUpdateConsumer) GetNewChainId() string { return "" } +func (m *MsgUpdateConsumer) GetInfractionParameters() *InfractionParameters { + if m != nil { + return m.InfractionParameters + } + return nil +} + // MsgUpdateConsumerResponse defines response type for MsgUpdateConsumer messages type MsgUpdateConsumerResponse struct { } @@ -1641,137 +1659,139 @@ func init() { } var fileDescriptor_43221a4391e9fbf4 = []byte{ - // 2071 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe4, 0x59, 0x4d, 0x6c, 0x1c, 0x49, - 0x15, 0x76, 0x8f, 0xc7, 0xce, 0x4c, 0xd9, 0xf1, 0x4f, 0xd9, 0x59, 0xb7, 0x27, 0x59, 0x8f, 0x33, - 0x2c, 0xbb, 0x56, 0x58, 0xf7, 0x6c, 0x0c, 0x1b, 0x84, 0x09, 0x48, 0xfe, 0x09, 0xc4, 0x0b, 0x8e, - 0xbd, 0xed, 0x90, 0x95, 0x40, 0xa2, 0x55, 0xd3, 0x5d, 0xe9, 0x29, 0x65, 0xba, 0xab, 0xd5, 0x55, - 0x33, 0x8e, 0x39, 0xa1, 0x3d, 0xed, 0x71, 0x91, 0x38, 0x70, 0x5c, 0x24, 0x38, 0x20, 0x81, 0x94, - 0xc3, 0x1e, 0xb9, 0x22, 0x45, 0xe2, 0xb2, 0xec, 0x09, 0x21, 0x14, 0x50, 0x72, 0x58, 0x2e, 0x5c, - 0xb8, 0x71, 0x43, 0xf5, 0xd3, 0x3d, 0xd3, 0x33, 0x63, 0xbb, 0x3d, 0xd1, 0xb2, 0x87, 0xbd, 0x58, - 0xd3, 0xf5, 0xbe, 0xf7, 0xbd, 0x9f, 0x7e, 0xf5, 0x5e, 0x55, 0x1b, 0xbc, 0x49, 0x42, 0x8e, 0x63, - 0xb7, 0x89, 0x48, 0xe8, 0x30, 0xec, 0xb6, 0x63, 0xc2, 0x4f, 0xea, 0xae, 0xdb, 0xa9, 0x47, 0x31, - 0xed, 0x10, 0x0f, 0xc7, 0xf5, 0xce, 0xcd, 0x3a, 0x7f, 0x6c, 0x45, 0x31, 0xe5, 0x14, 0x7e, 0x65, - 0x08, 0xda, 0x72, 0xdd, 0x8e, 0x95, 0xa0, 0xad, 0xce, 0xcd, 0xca, 0x3c, 0x0a, 0x48, 0x48, 0xeb, - 0xf2, 0xaf, 0xd2, 0xab, 0x5c, 0xf3, 0x29, 0xf5, 0x5b, 0xb8, 0x8e, 0x22, 0x52, 0x47, 0x61, 0x48, - 0x39, 0xe2, 0x84, 0x86, 0x4c, 0x4b, 0xab, 0x5a, 0x2a, 0x9f, 0x1a, 0xed, 0x87, 0x75, 0x4e, 0x02, - 0xcc, 0x38, 0x0a, 0x22, 0x0d, 0x58, 0xe9, 0x07, 0x78, 0xed, 0x58, 0x32, 0x68, 0xf9, 0x72, 0xbf, - 0x1c, 0x85, 0x27, 0x5a, 0xb4, 0xe8, 0x53, 0x9f, 0xca, 0x9f, 0x75, 0xf1, 0x2b, 0x51, 0x70, 0x29, - 0x0b, 0x28, 0x73, 0x94, 0x40, 0x3d, 0x68, 0xd1, 0x92, 0x7a, 0xaa, 0x07, 0xcc, 0x17, 0xa1, 0x07, - 0xcc, 0x4f, 0xbc, 0x24, 0x0d, 0xb7, 0xee, 0xd2, 0x18, 0xd7, 0xdd, 0x16, 0xc1, 0x21, 0x17, 0x52, - 0xf5, 0x4b, 0x03, 0x36, 0xf2, 0xa4, 0x32, 0x4d, 0x94, 0xd2, 0xa9, 0x0b, 0xd2, 0x16, 0xf1, 0x9b, - 0x5c, 0x51, 0xb1, 0x3a, 0xc7, 0xa1, 0x87, 0xe3, 0x80, 0x28, 0x03, 0xdd, 0xa7, 0xc4, 0x8b, 0x1e, - 0x39, 0x3f, 0x89, 0x30, 0xab, 0x63, 0xc1, 0x17, 0xba, 0x58, 0x01, 0x6a, 0xff, 0x35, 0xc0, 0xe2, - 0x3e, 0xf3, 0xb7, 0x18, 0x23, 0x7e, 0xb8, 0x43, 0x43, 0xd6, 0x0e, 0x70, 0xfc, 0x03, 0x7c, 0x02, - 0x5f, 0x05, 0x25, 0xe5, 0x1b, 0xf1, 0x4c, 0x63, 0xd5, 0x58, 0x2b, 0x6f, 0x17, 0x4c, 0xc3, 0xbe, - 0x24, 0xd7, 0xf6, 0x3c, 0xf8, 0x4d, 0x70, 0x39, 0xf1, 0xcd, 0x41, 0x9e, 0x17, 0x9b, 0x05, 0x89, - 0x81, 0xff, 0x79, 0x56, 0x9d, 0x39, 0x41, 0x41, 0x6b, 0xb3, 0x26, 0x56, 0x31, 0x63, 0x35, 0x7b, - 0x3a, 0x01, 0x6e, 0x79, 0x5e, 0x0c, 0xaf, 0x83, 0x69, 0x57, 0x9b, 0x71, 0x1e, 0xe1, 0x13, 0x73, - 0x5c, 0xe8, 0xd9, 0x53, 0x6e, 0x8f, 0xe9, 0xb7, 0xc0, 0xa4, 0xf0, 0x06, 0xc7, 0x66, 0x51, 0x92, - 0x9a, 0x9f, 0x7e, 0xbc, 0xbe, 0xa8, 0xb3, 0xbe, 0xa5, 0x58, 0x8f, 0x78, 0x4c, 0x42, 0xdf, 0xd6, - 0x38, 0x58, 0x05, 0x29, 0x81, 0xf0, 0x77, 0x42, 0x72, 0x82, 0x64, 0x69, 0xcf, 0xdb, 0x5c, 0xf8, - 0xe0, 0xa3, 0xea, 0xd8, 0xbf, 0x3e, 0xaa, 0x8e, 0xbd, 0xff, 0xd9, 0x93, 0x1b, 0x5a, 0xab, 0xb6, - 0x02, 0xae, 0x0d, 0x0b, 0xdd, 0xc6, 0x2c, 0xa2, 0x21, 0xc3, 0xb5, 0xe7, 0x06, 0x78, 0x75, 0x9f, - 0xf9, 0x47, 0xed, 0x46, 0x40, 0x78, 0x02, 0xd8, 0x27, 0xac, 0x81, 0x9b, 0xa8, 0x43, 0x68, 0x3b, - 0x86, 0xb7, 0x40, 0x99, 0x49, 0x29, 0xc7, 0xb1, 0xce, 0xd2, 0xe9, 0xce, 0x76, 0xa1, 0xf0, 0x10, - 0x4c, 0x07, 0x3d, 0x3c, 0x32, 0x79, 0x53, 0x1b, 0x6f, 0x5a, 0xa4, 0xe1, 0x5a, 0xbd, 0xaf, 0xd7, - 0xea, 0x79, 0xa1, 0x9d, 0x9b, 0x56, 0xaf, 0x6d, 0x3b, 0xc3, 0xd0, 0x9f, 0x81, 0xf1, 0x81, 0x0c, - 0xbc, 0xd2, 0x9b, 0x81, 0xae, 0x2b, 0xb5, 0x37, 0xc0, 0x57, 0xcf, 0x8c, 0x31, 0xcd, 0xc6, 0x5f, - 0x0a, 0x43, 0xb2, 0xb1, 0x4b, 0xdb, 0x8d, 0x16, 0x7e, 0x40, 0x39, 0x09, 0xfd, 0x91, 0xb3, 0xe1, - 0x80, 0x25, 0xaf, 0x1d, 0xb5, 0x88, 0x8b, 0x38, 0x76, 0x3a, 0x94, 0x63, 0x27, 0x29, 0x52, 0x9d, - 0x98, 0x37, 0x7a, 0xf3, 0x20, 0xcb, 0xd8, 0xda, 0x4d, 0x14, 0x1e, 0x50, 0x8e, 0xef, 0x68, 0xb8, - 0x7d, 0xc5, 0x1b, 0xb6, 0x0c, 0x7f, 0x0a, 0x96, 0x48, 0xf8, 0x30, 0x46, 0xae, 0x68, 0x02, 0x4e, - 0xa3, 0x45, 0xdd, 0x47, 0x4e, 0x13, 0x23, 0x0f, 0xc7, 0x32, 0x51, 0x53, 0x1b, 0xaf, 0x9f, 0x97, - 0xf9, 0xbb, 0x12, 0x6d, 0x5f, 0xe9, 0xd2, 0x6c, 0x0b, 0x16, 0xb5, 0xdc, 0x9f, 0xfc, 0xe2, 0x4b, - 0x25, 0xbf, 0x37, 0xa5, 0x69, 0xf2, 0x7f, 0x63, 0x80, 0xd9, 0x7d, 0xe6, 0xff, 0x28, 0xf2, 0x10, - 0xc7, 0x87, 0x28, 0x46, 0x01, 0x13, 0xe9, 0x46, 0x6d, 0xde, 0xa4, 0xa2, 0x71, 0x9c, 0x9f, 0xee, - 0x14, 0x0a, 0xf7, 0xc0, 0x64, 0x24, 0x19, 0x74, 0x76, 0xbf, 0x66, 0xe5, 0x68, 0xd3, 0x96, 0x32, - 0xba, 0x5d, 0x7c, 0xfa, 0xac, 0x3a, 0x66, 0x6b, 0x82, 0xcd, 0x19, 0x19, 0x4f, 0x4a, 0x5d, 0x5b, - 0x06, 0x4b, 0x7d, 0x5e, 0xa6, 0x11, 0xfc, 0xbd, 0x04, 0x16, 0xf6, 0x99, 0x9f, 0x44, 0xb9, 0xe5, - 0x79, 0x44, 0xa4, 0x11, 0x2e, 0xf7, 0xf7, 0x99, 0x6e, 0x8f, 0xf9, 0x3e, 0x98, 0x21, 0x21, 0xe1, - 0x04, 0xb5, 0x9c, 0x26, 0x16, 0xef, 0x46, 0x3b, 0x5c, 0x91, 0x6f, 0x4b, 0xf4, 0x56, 0x4b, 0x77, - 0x54, 0xf9, 0x86, 0x04, 0x42, 0xfb, 0x77, 0x59, 0xeb, 0xa9, 0x45, 0xd1, 0x73, 0x7c, 0x1c, 0x62, - 0x46, 0x98, 0xd3, 0x44, 0xac, 0x29, 0x5f, 0xfa, 0xb4, 0x3d, 0xa5, 0xd7, 0xee, 0x22, 0xd6, 0x14, - 0xaf, 0xb0, 0x41, 0x42, 0x14, 0x9f, 0x28, 0x44, 0x51, 0x22, 0x80, 0x5a, 0x92, 0x80, 0x1d, 0x00, - 0x58, 0x84, 0x8e, 0x43, 0x47, 0x4c, 0x1b, 0xd9, 0x61, 0x84, 0x23, 0x6a, 0x92, 0x58, 0xc9, 0x24, - 0xb1, 0xee, 0x27, 0xa3, 0x68, 0xbb, 0x24, 0x1c, 0xf9, 0xf0, 0x1f, 0x55, 0xc3, 0x2e, 0x4b, 0x3d, - 0x21, 0x81, 0xf7, 0xc0, 0x5c, 0x3b, 0x6c, 0xd0, 0xd0, 0x23, 0xa1, 0xef, 0x44, 0x38, 0x26, 0xd4, - 0x33, 0x27, 0x25, 0xd5, 0xf2, 0x00, 0xd5, 0xae, 0x1e, 0x5a, 0x8a, 0xe9, 0x57, 0x82, 0x69, 0x36, - 0x55, 0x3e, 0x94, 0xba, 0xf0, 0x5d, 0x00, 0x5d, 0xb7, 0x23, 0x5d, 0xa2, 0x6d, 0x9e, 0x30, 0x5e, - 0xca, 0xcf, 0x38, 0xe7, 0xba, 0x9d, 0xfb, 0x4a, 0x5b, 0x53, 0xfe, 0x04, 0x2c, 0xf1, 0x18, 0x85, - 0xec, 0x21, 0x8e, 0xfb, 0x79, 0x4b, 0xf9, 0x79, 0xaf, 0x24, 0x1c, 0x59, 0xf2, 0xbb, 0x60, 0x35, - 0xdd, 0x28, 0x31, 0xf6, 0x08, 0xe3, 0x31, 0x69, 0xb4, 0xe5, 0xae, 0x4c, 0xf6, 0x95, 0x59, 0x96, - 0x45, 0xb0, 0x92, 0xe0, 0xec, 0x0c, 0xec, 0x7b, 0x1a, 0x05, 0x0f, 0xc0, 0x6b, 0x72, 0x1f, 0x33, - 0xe1, 0x9c, 0x93, 0x61, 0x92, 0xa6, 0x03, 0xc2, 0x98, 0x60, 0x03, 0xab, 0xc6, 0xda, 0xb8, 0x7d, - 0x5d, 0x61, 0x0f, 0x71, 0xbc, 0xdb, 0x83, 0xbc, 0xdf, 0x03, 0x84, 0xeb, 0x00, 0x36, 0x09, 0xe3, - 0x34, 0x26, 0x2e, 0x6a, 0x39, 0x38, 0xe4, 0x31, 0xc1, 0xcc, 0x9c, 0x92, 0xea, 0xf3, 0x5d, 0xc9, - 0x1d, 0x25, 0x80, 0xef, 0x80, 0xeb, 0xa7, 0x1a, 0x75, 0xdc, 0x26, 0x0a, 0x43, 0xdc, 0x32, 0xa7, - 0x65, 0x28, 0x55, 0xef, 0x14, 0x9b, 0x3b, 0x0a, 0x06, 0x17, 0xc0, 0x04, 0xa7, 0x91, 0x73, 0xcf, - 0xbc, 0xbc, 0x6a, 0xac, 0x5d, 0xb6, 0x8b, 0x9c, 0x46, 0xf7, 0xe0, 0x5b, 0x60, 0xb1, 0x83, 0x5a, - 0xc4, 0x43, 0x9c, 0xc6, 0xcc, 0x89, 0xe8, 0x31, 0x8e, 0x1d, 0x17, 0x45, 0xe6, 0x8c, 0xc4, 0xc0, - 0xae, 0xec, 0x50, 0x88, 0x76, 0x50, 0x04, 0x6f, 0x80, 0xf9, 0x74, 0xd5, 0x61, 0x98, 0x4b, 0xf8, - 0xac, 0x84, 0xcf, 0xa6, 0x82, 0x23, 0xcc, 0x05, 0xf6, 0x1a, 0x28, 0xa3, 0x56, 0x8b, 0x1e, 0xb7, - 0x08, 0xe3, 0xe6, 0xdc, 0xea, 0xf8, 0x5a, 0xd9, 0xee, 0x2e, 0xc0, 0x0a, 0x28, 0x79, 0x38, 0x3c, - 0x91, 0xc2, 0x79, 0x29, 0x4c, 0x9f, 0xb3, 0x5d, 0x07, 0xe6, 0xef, 0x3a, 0x57, 0x41, 0x39, 0x10, - 0xfd, 0x85, 0xa3, 0x47, 0xd8, 0x5c, 0x58, 0x35, 0xd6, 0x8a, 0x76, 0x29, 0x20, 0xe1, 0x91, 0x78, - 0x86, 0x16, 0x58, 0x90, 0xd6, 0x1d, 0x12, 0x8a, 0xf7, 0xdb, 0xc1, 0x4e, 0x07, 0xb5, 0x98, 0xb9, - 0xb8, 0x6a, 0xac, 0x95, 0xec, 0x79, 0x29, 0xda, 0xd3, 0x92, 0x07, 0xa8, 0xc5, 0x36, 0xe7, 0xb2, - 0x7d, 0xc7, 0x34, 0x6a, 0x7f, 0x34, 0x00, 0xec, 0x69, 0x2f, 0x36, 0x0e, 0x68, 0x07, 0xb5, 0xce, - 0xea, 0x2e, 0x5b, 0xa0, 0xcc, 0x44, 0xda, 0xe5, 0x7e, 0x2e, 0x5c, 0x60, 0x3f, 0x97, 0x84, 0x9a, - 0xdc, 0xce, 0x99, 0x5c, 0x8c, 0xe7, 0xce, 0xc5, 0x10, 0xf7, 0x23, 0x30, 0xbf, 0xcf, 0x7c, 0xe9, - 0x35, 0x4e, 0x62, 0xe8, 0x1f, 0x2b, 0x46, 0xff, 0x58, 0x81, 0x16, 0x98, 0xa0, 0xc7, 0xe2, 0x9c, - 0x54, 0x38, 0xc7, 0xb6, 0x82, 0x6d, 0x02, 0x61, 0x57, 0xfd, 0xae, 0x5d, 0x05, 0xcb, 0x03, 0x16, - 0xd3, 0x66, 0xfd, 0x07, 0x03, 0x5c, 0x11, 0xd9, 0x6c, 0xa2, 0xd0, 0xc7, 0x36, 0x3e, 0x46, 0xb1, - 0xb7, 0x8b, 0x43, 0x1a, 0x30, 0x58, 0x03, 0x97, 0x3d, 0xf9, 0xcb, 0xe1, 0x54, 0x1c, 0xfc, 0x4c, - 0x43, 0xd6, 0xc7, 0x94, 0x5a, 0xbc, 0x4f, 0xb7, 0x3c, 0x0f, 0xae, 0x81, 0xb9, 0x2e, 0x26, 0x96, - 0x16, 0xcc, 0x82, 0x84, 0xcd, 0x24, 0x30, 0x65, 0x77, 0xe4, 0x04, 0xf6, 0xcf, 0x9d, 0xaa, 0x3c, - 0x9a, 0x0c, 0xba, 0x9b, 0x06, 0xf4, 0x6f, 0x03, 0x94, 0xf6, 0x99, 0x7f, 0x10, 0xf1, 0xbd, 0xf0, - 0xcb, 0x70, 0xb4, 0x85, 0x60, 0x2e, 0x09, 0x37, 0xcd, 0xc1, 0x9f, 0x0d, 0x50, 0x56, 0x8b, 0x07, - 0x6d, 0xfe, 0xb9, 0x25, 0xa1, 0x1b, 0xe1, 0xf8, 0x68, 0x11, 0x16, 0xf3, 0x45, 0xb8, 0x20, 0x77, - 0x8c, 0x0a, 0x26, 0x0d, 0xf1, 0xb7, 0x05, 0x79, 0xa4, 0x17, 0x4d, 0x4e, 0xab, 0xef, 0xd0, 0x40, - 0x77, 0x5b, 0x1b, 0x71, 0x3c, 0x18, 0x96, 0x91, 0x33, 0xac, 0xde, 0x74, 0x15, 0x06, 0xd3, 0x75, - 0x07, 0x14, 0x63, 0xc4, 0xb1, 0x8e, 0xf9, 0xa6, 0xe8, 0x15, 0x7f, 0x7b, 0x56, 0xbd, 0xaa, 0xe2, - 0x66, 0xde, 0x23, 0x8b, 0xd0, 0x7a, 0x80, 0x78, 0xd3, 0xfa, 0x21, 0xf6, 0x91, 0x7b, 0xb2, 0x8b, - 0xdd, 0x4f, 0x3f, 0x5e, 0x07, 0x3a, 0x2d, 0xbb, 0xd8, 0xb5, 0xa5, 0xfa, 0xff, 0xad, 0x3c, 0x5e, - 0x07, 0xaf, 0x9d, 0x95, 0xa6, 0x34, 0x9f, 0x4f, 0xc6, 0xe5, 0x81, 0x2e, 0xbd, 0x17, 0x50, 0x8f, - 0x3c, 0x14, 0xc7, 0x6b, 0x31, 0x30, 0x17, 0xc1, 0x04, 0x27, 0xbc, 0x85, 0x75, 0x5f, 0x52, 0x0f, - 0x70, 0x15, 0x4c, 0x79, 0x98, 0xb9, 0x31, 0x89, 0xe4, 0x30, 0x2f, 0xa8, 0x2d, 0xd0, 0xb3, 0x94, - 0x69, 0xc9, 0xe3, 0xd9, 0x96, 0x9c, 0x0e, 0xc2, 0x62, 0x8e, 0x41, 0x38, 0x71, 0xb1, 0x41, 0x38, - 0x99, 0x63, 0x10, 0x5e, 0x3a, 0x6b, 0x10, 0x96, 0xce, 0x1a, 0x84, 0xe5, 0x11, 0x07, 0x21, 0xc8, - 0x37, 0x08, 0xa7, 0xf2, 0x0f, 0xc2, 0xeb, 0xa0, 0x7a, 0xca, 0x1b, 0x4b, 0xdf, 0xea, 0x9f, 0x8a, - 0x72, 0xef, 0xec, 0xc4, 0x18, 0xf1, 0xee, 0xb4, 0x19, 0xf5, 0xf6, 0xb6, 0xdc, 0xbf, 0x33, 0xba, - 0xef, 0xf3, 0x3d, 0x50, 0x0a, 0x30, 0x47, 0x1e, 0xe2, 0x48, 0x5f, 0xb4, 0xde, 0xce, 0x75, 0xd7, - 0x48, 0xbd, 0xd7, 0xca, 0xfa, 0x54, 0x9f, 0x92, 0xc1, 0xf7, 0x0d, 0xb0, 0xac, 0x8f, 0xf8, 0xe4, - 0x67, 0x32, 0x38, 0x47, 0xde, 0x48, 0x30, 0xc7, 0x31, 0x93, 0xd5, 0x33, 0xb5, 0x71, 0xe7, 0x42, - 0xa6, 0xf6, 0x32, 0x6c, 0x87, 0x29, 0x99, 0x6d, 0x92, 0x53, 0x24, 0xb0, 0x0d, 0x4c, 0x55, 0x8d, - 0xac, 0x89, 0x22, 0x79, 0xa0, 0xef, 0xba, 0xa0, 0xee, 0x07, 0xdf, 0xce, 0x77, 0xb3, 0x12, 0x24, - 0x47, 0x8a, 0xa3, 0xc7, 0xf0, 0x2b, 0xd1, 0xd0, 0x75, 0xf8, 0x18, 0x2c, 0xa7, 0x05, 0x8a, 0x3d, - 0x27, 0x96, 0xe3, 0xce, 0x51, 0x83, 0x55, 0x5f, 0x26, 0x6e, 0xe7, 0xb2, 0xbb, 0xd5, 0x65, 0xc9, - 0xcc, 0xcc, 0x25, 0x34, 0x5c, 0xa0, 0xa7, 0x6e, 0xf7, 0xf6, 0x7a, 0x5b, 0x1e, 0x21, 0xb2, 0x65, - 0x94, 0x14, 0xd9, 0xb9, 0x87, 0x97, 0xda, 0xaf, 0x27, 0x64, 0x15, 0xaa, 0xcb, 0x62, 0x5a, 0x85, - 0xe9, 0x91, 0xc6, 0xc8, 0x75, 0xa4, 0xe9, 0x37, 0x53, 0x18, 0x38, 0x23, 0xed, 0x82, 0xf9, 0x10, - 0x1f, 0x3b, 0x12, 0xed, 0xe8, 0xe6, 0x7e, 0xee, 0x68, 0x9a, 0x0d, 0xf1, 0xf1, 0x81, 0xd0, 0xd0, - 0xcb, 0xf0, 0xdd, 0x9e, 0x4a, 0x2e, 0xbe, 0x44, 0x25, 0xe7, 0xae, 0xe1, 0x89, 0x2f, 0xbe, 0x86, - 0x27, 0xbf, 0xa0, 0x1a, 0xbe, 0xf4, 0x39, 0xd6, 0x30, 0x5c, 0x05, 0xd3, 0xa2, 0x1c, 0xd2, 0x8e, - 0x55, 0x52, 0x05, 0x13, 0xe2, 0xe3, 0x1d, 0xd5, 0xb4, 0x86, 0x1c, 0x92, 0xb3, 0x25, 0x9a, 0x54, - 0xf8, 0xc6, 0xd3, 0x69, 0x30, 0xbe, 0xcf, 0x7c, 0xf8, 0x0b, 0x03, 0xcc, 0x0f, 0x7e, 0x3f, 0xfd, - 0x56, 0x2e, 0xff, 0x87, 0x7d, 0x7f, 0xac, 0x6c, 0x8d, 0xac, 0x9a, 0xee, 0xbe, 0xdf, 0x1b, 0xa0, - 0x72, 0xc6, 0x77, 0xcb, 0xed, 0xbc, 0x16, 0x4e, 0xe7, 0xa8, 0xbc, 0xf3, 0xf2, 0x1c, 0x67, 0xb8, - 0x9b, 0xf9, 0xb0, 0x38, 0xa2, 0xbb, 0xbd, 0x1c, 0xa3, 0xba, 0x3b, 0xec, 0x6b, 0x1c, 0xfc, 0xc0, - 0x00, 0x33, 0xfd, 0xd3, 0x33, 0x2f, 0x7d, 0x56, 0xaf, 0xf2, 0xdd, 0xd1, 0xf4, 0x32, 0xae, 0xf4, - 0xb5, 0xd0, 0xdc, 0xae, 0x64, 0xf5, 0xf2, 0xbb, 0x32, 0x7c, 0x3f, 0x48, 0x57, 0xfa, 0x6e, 0xb0, - 0xb9, 0x5d, 0xc9, 0xea, 0xe5, 0x77, 0x65, 0xf8, 0xfd, 0x55, 0xf4, 0xd6, 0xe9, 0xcc, 0xb7, 0xd2, - 0x6f, 0x5c, 0x2c, 0x36, 0xa5, 0x55, 0xb9, 0x3d, 0x8a, 0x56, 0xea, 0x44, 0x00, 0x26, 0xd4, 0x7d, - 0x73, 0x3d, 0x2f, 0x8d, 0x84, 0x57, 0xde, 0xbe, 0x10, 0x3c, 0x35, 0x17, 0x81, 0x49, 0x7d, 0xb5, - 0xb3, 0x2e, 0x40, 0x70, 0xd0, 0xe6, 0x95, 0x5b, 0x17, 0xc3, 0xa7, 0x16, 0x7f, 0x67, 0x80, 0xe5, - 0xd3, 0xaf, 0x5a, 0xb9, 0xbb, 0xd8, 0xa9, 0x14, 0x95, 0xbd, 0x97, 0xa6, 0x48, 0x7d, 0xfd, 0xa5, - 0x01, 0xe0, 0x90, 0xcf, 0x19, 0x9b, 0xb9, 0xb7, 0xdf, 0x80, 0x6e, 0x65, 0x7b, 0x74, 0xdd, 0xc4, - 0xad, 0xca, 0xc4, 0xcf, 0x3f, 0x7b, 0x72, 0xc3, 0xd8, 0x7e, 0xef, 0xe9, 0xf3, 0x15, 0xe3, 0x93, - 0xe7, 0x2b, 0xc6, 0x3f, 0x9f, 0xaf, 0x18, 0x1f, 0xbe, 0x58, 0x19, 0xfb, 0xe4, 0xc5, 0xca, 0xd8, - 0x5f, 0x5f, 0xac, 0x8c, 0xfd, 0xf8, 0x3b, 0x3e, 0xe1, 0xcd, 0x76, 0xc3, 0x72, 0x69, 0xa0, 0xff, - 0xf1, 0x58, 0xef, 0x5a, 0x5d, 0x4f, 0xff, 0x6f, 0xd8, 0xb9, 0x55, 0x7f, 0x9c, 0xfd, 0xe7, 0xa1, - 0xfc, 0x37, 0x49, 0x63, 0x52, 0x7e, 0xc9, 0xfa, 0xfa, 0xff, 0x02, 0x00, 0x00, 0xff, 0xff, 0x84, - 0xa1, 0x79, 0x6d, 0xb8, 0x1d, 0x00, 0x00, + // 2100 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe4, 0x59, 0xcf, 0x6f, 0x1c, 0x49, + 0xf5, 0x77, 0x8f, 0xc7, 0xce, 0x4c, 0xd9, 0x71, 0xec, 0xb2, 0xb3, 0x6e, 0x4f, 0xb2, 0x1e, 0x67, + 0xbe, 0xfb, 0xdd, 0xb5, 0xc2, 0xa6, 0x67, 0x13, 0xd8, 0x20, 0x4c, 0x40, 0xf2, 0x8f, 0x40, 0xbc, + 0xe0, 0xc4, 0xdb, 0x0e, 0x59, 0x09, 0x24, 0x5a, 0x35, 0xdd, 0x95, 0x9e, 0x52, 0xa6, 0xbb, 0x5a, + 0x5d, 0x35, 0xe3, 0x98, 0x13, 0xda, 0xd3, 0x1e, 0x77, 0x25, 0x0e, 0x1c, 0xf7, 0x00, 0x07, 0x24, + 0x90, 0x72, 0x58, 0x6e, 0xfc, 0x01, 0x91, 0xb8, 0x2c, 0x7b, 0x42, 0x08, 0x05, 0x94, 0x1c, 0x96, + 0x0b, 0x17, 0x6e, 0xdc, 0x50, 0xfd, 0xe8, 0x9e, 0xee, 0x99, 0xb1, 0xdd, 0x9e, 0x28, 0xec, 0x81, + 0xcb, 0xa8, 0xbb, 0xde, 0x7b, 0x9f, 0xf7, 0xa3, 0xea, 0xbd, 0x57, 0xaf, 0x07, 0xbc, 0x4d, 0x42, + 0x8e, 0x63, 0xb7, 0x8d, 0x48, 0xe8, 0x30, 0xec, 0x76, 0x63, 0xc2, 0x8f, 0x9a, 0xae, 0xdb, 0x6b, + 0x46, 0x31, 0xed, 0x11, 0x0f, 0xc7, 0xcd, 0xde, 0xf5, 0x26, 0x7f, 0x6c, 0x45, 0x31, 0xe5, 0x14, + 0xfe, 0xdf, 0x08, 0x6e, 0xcb, 0x75, 0x7b, 0x56, 0xc2, 0x6d, 0xf5, 0xae, 0xd7, 0x16, 0x50, 0x40, + 0x42, 0xda, 0x94, 0xbf, 0x4a, 0xae, 0x76, 0xd9, 0xa7, 0xd4, 0xef, 0xe0, 0x26, 0x8a, 0x48, 0x13, + 0x85, 0x21, 0xe5, 0x88, 0x13, 0x1a, 0x32, 0x4d, 0xad, 0x6b, 0xaa, 0x7c, 0x6b, 0x75, 0x1f, 0x36, + 0x39, 0x09, 0x30, 0xe3, 0x28, 0x88, 0x34, 0xc3, 0xea, 0x20, 0x83, 0xd7, 0x8d, 0x25, 0x82, 0xa6, + 0xaf, 0x0c, 0xd2, 0x51, 0x78, 0xa4, 0x49, 0x4b, 0x3e, 0xf5, 0xa9, 0x7c, 0x6c, 0x8a, 0xa7, 0x44, + 0xc0, 0xa5, 0x2c, 0xa0, 0xcc, 0x51, 0x04, 0xf5, 0xa2, 0x49, 0xcb, 0xea, 0xad, 0x19, 0x30, 0x5f, + 0xb8, 0x1e, 0x30, 0x3f, 0xb1, 0x92, 0xb4, 0xdc, 0xa6, 0x4b, 0x63, 0xdc, 0x74, 0x3b, 0x04, 0x87, + 0x5c, 0x50, 0xd5, 0x93, 0x66, 0xb8, 0x51, 0x24, 0x94, 0x69, 0xa0, 0x94, 0x4c, 0x53, 0x80, 0x76, + 0x88, 0xdf, 0xe6, 0x0a, 0x8a, 0x35, 0x39, 0x0e, 0x3d, 0x1c, 0x07, 0x44, 0x29, 0xe8, 0xbf, 0x25, + 0x56, 0x64, 0xe8, 0xfc, 0x28, 0xc2, 0xac, 0x89, 0x05, 0x5e, 0xe8, 0x62, 0xc5, 0xd0, 0xf8, 0xb7, + 0x01, 0x96, 0xf6, 0x98, 0xbf, 0xc9, 0x18, 0xf1, 0xc3, 0x6d, 0x1a, 0xb2, 0x6e, 0x80, 0xe3, 0x1f, + 0xe0, 0x23, 0xf8, 0x3a, 0xa8, 0x28, 0xdb, 0x88, 0x67, 0x1a, 0x6b, 0xc6, 0x7a, 0x75, 0xab, 0x64, + 0x1a, 0xf6, 0x39, 0xb9, 0xb6, 0xeb, 0xc1, 0x6f, 0x82, 0xf3, 0x89, 0x6d, 0x0e, 0xf2, 0xbc, 0xd8, + 0x2c, 0x49, 0x1e, 0xf8, 0xaf, 0x67, 0xf5, 0xb9, 0x23, 0x14, 0x74, 0x36, 0x1a, 0x62, 0x15, 0x33, + 0xd6, 0xb0, 0x67, 0x13, 0xc6, 0x4d, 0xcf, 0x8b, 0xe1, 0x15, 0x30, 0xeb, 0x6a, 0x35, 0xce, 0x23, + 0x7c, 0x64, 0x4e, 0x0a, 0x39, 0x7b, 0xc6, 0xcd, 0xa8, 0x7e, 0x07, 0x4c, 0x0b, 0x6b, 0x70, 0x6c, + 0x96, 0x25, 0xa8, 0xf9, 0xc5, 0x67, 0xd7, 0x96, 0x74, 0xd4, 0x37, 0x15, 0xea, 0x01, 0x8f, 0x49, + 0xe8, 0xdb, 0x9a, 0x0f, 0xd6, 0x41, 0x0a, 0x20, 0xec, 0x9d, 0x92, 0x98, 0x20, 0x59, 0xda, 0xf5, + 0x36, 0x16, 0x3f, 0xfa, 0xb4, 0x3e, 0xf1, 0x8f, 0x4f, 0xeb, 0x13, 0x1f, 0x7e, 0xf9, 0xe4, 0xaa, + 0x96, 0x6a, 0xac, 0x82, 0xcb, 0xa3, 0x5c, 0xb7, 0x31, 0x8b, 0x68, 0xc8, 0x70, 0xe3, 0xb9, 0x01, + 0x5e, 0xdf, 0x63, 0xfe, 0x41, 0xb7, 0x15, 0x10, 0x9e, 0x30, 0xec, 0x11, 0xd6, 0xc2, 0x6d, 0xd4, + 0x23, 0xb4, 0x1b, 0xc3, 0x9b, 0xa0, 0xca, 0x24, 0x95, 0xe3, 0x58, 0x47, 0xe9, 0x78, 0x63, 0xfb, + 0xac, 0x70, 0x1f, 0xcc, 0x06, 0x19, 0x1c, 0x19, 0xbc, 0x99, 0x1b, 0x6f, 0x5b, 0xa4, 0xe5, 0x5a, + 0xd9, 0xed, 0xb5, 0x32, 0x1b, 0xda, 0xbb, 0x6e, 0x65, 0x75, 0xdb, 0x39, 0x84, 0xc1, 0x08, 0x4c, + 0x0e, 0x45, 0xe0, 0xb5, 0x6c, 0x04, 0xfa, 0xa6, 0x34, 0xde, 0x02, 0xff, 0x7f, 0xa2, 0x8f, 0x69, + 0x34, 0xfe, 0x54, 0x1a, 0x11, 0x8d, 0x1d, 0xda, 0x6d, 0x75, 0xf0, 0x03, 0xca, 0x49, 0xe8, 0x8f, + 0x1d, 0x0d, 0x07, 0x2c, 0x7b, 0xdd, 0xa8, 0x43, 0x5c, 0xc4, 0xb1, 0xd3, 0xa3, 0x1c, 0x3b, 0xc9, + 0x21, 0xd5, 0x81, 0x79, 0x2b, 0x1b, 0x07, 0x79, 0x8c, 0xad, 0x9d, 0x44, 0xe0, 0x01, 0xe5, 0xf8, + 0xb6, 0x66, 0xb7, 0x2f, 0x7a, 0xa3, 0x96, 0xe1, 0x4f, 0xc1, 0x32, 0x09, 0x1f, 0xc6, 0xc8, 0x15, + 0x45, 0xc0, 0x69, 0x75, 0xa8, 0xfb, 0xc8, 0x69, 0x63, 0xe4, 0xe1, 0x58, 0x06, 0x6a, 0xe6, 0xc6, + 0x9b, 0xa7, 0x45, 0xfe, 0x8e, 0xe4, 0xb6, 0x2f, 0xf6, 0x61, 0xb6, 0x04, 0x8a, 0x5a, 0x1e, 0x0c, + 0x7e, 0xf9, 0xa5, 0x82, 0x9f, 0x0d, 0x69, 0x1a, 0xfc, 0x5f, 0x19, 0xe0, 0xc2, 0x1e, 0xf3, 0x7f, + 0x14, 0x79, 0x88, 0xe3, 0x7d, 0x14, 0xa3, 0x80, 0x89, 0x70, 0xa3, 0x2e, 0x6f, 0x53, 0x51, 0x38, + 0x4e, 0x0f, 0x77, 0xca, 0x0a, 0x77, 0xc1, 0x74, 0x24, 0x11, 0x74, 0x74, 0xbf, 0x66, 0x15, 0x28, + 0xd3, 0x96, 0x52, 0xba, 0x55, 0x7e, 0xfa, 0xac, 0x3e, 0x61, 0x6b, 0x80, 0x8d, 0x39, 0xe9, 0x4f, + 0x0a, 0xdd, 0x58, 0x01, 0xcb, 0x03, 0x56, 0xa6, 0x1e, 0xfc, 0xb5, 0x02, 0x16, 0xf7, 0x98, 0x9f, + 0x78, 0xb9, 0xe9, 0x79, 0x44, 0x84, 0x11, 0xae, 0x0c, 0xd6, 0x99, 0x7e, 0x8d, 0xf9, 0x3e, 0x98, + 0x23, 0x21, 0xe1, 0x04, 0x75, 0x9c, 0x36, 0x16, 0x7b, 0xa3, 0x0d, 0xae, 0xc9, 0xdd, 0x12, 0xb5, + 0xd5, 0xd2, 0x15, 0x55, 0xee, 0x90, 0xe0, 0xd0, 0xf6, 0x9d, 0xd7, 0x72, 0x6a, 0x51, 0xd4, 0x1c, + 0x1f, 0x87, 0x98, 0x11, 0xe6, 0xb4, 0x11, 0x6b, 0xcb, 0x4d, 0x9f, 0xb5, 0x67, 0xf4, 0xda, 0x1d, + 0xc4, 0xda, 0x62, 0x0b, 0x5b, 0x24, 0x44, 0xf1, 0x91, 0xe2, 0x28, 0x4b, 0x0e, 0xa0, 0x96, 0x24, + 0xc3, 0x36, 0x00, 0x2c, 0x42, 0x87, 0xa1, 0x23, 0xba, 0x8d, 0xac, 0x30, 0xc2, 0x10, 0xd5, 0x49, + 0xac, 0xa4, 0x93, 0x58, 0xf7, 0x93, 0x56, 0xb4, 0x55, 0x11, 0x86, 0x7c, 0xfc, 0xb7, 0xba, 0x61, + 0x57, 0xa5, 0x9c, 0xa0, 0xc0, 0xbb, 0x60, 0xbe, 0x1b, 0xb6, 0x68, 0xe8, 0x91, 0xd0, 0x77, 0x22, + 0x1c, 0x13, 0xea, 0x99, 0xd3, 0x12, 0x6a, 0x65, 0x08, 0x6a, 0x47, 0x37, 0x2d, 0x85, 0xf4, 0x4b, + 0x81, 0x74, 0x21, 0x15, 0xde, 0x97, 0xb2, 0xf0, 0x7d, 0x00, 0x5d, 0xb7, 0x27, 0x4d, 0xa2, 0x5d, + 0x9e, 0x20, 0x9e, 0x2b, 0x8e, 0x38, 0xef, 0xba, 0xbd, 0xfb, 0x4a, 0x5a, 0x43, 0xfe, 0x04, 0x2c, + 0xf3, 0x18, 0x85, 0xec, 0x21, 0x8e, 0x07, 0x71, 0x2b, 0xc5, 0x71, 0x2f, 0x26, 0x18, 0x79, 0xf0, + 0x3b, 0x60, 0x2d, 0x4d, 0x94, 0x18, 0x7b, 0x84, 0xf1, 0x98, 0xb4, 0xba, 0x32, 0x2b, 0x93, 0xbc, + 0x32, 0xab, 0xf2, 0x10, 0xac, 0x26, 0x7c, 0x76, 0x8e, 0xed, 0x7b, 0x9a, 0x0b, 0xde, 0x03, 0x6f, + 0xc8, 0x3c, 0x66, 0xc2, 0x38, 0x27, 0x87, 0x24, 0x55, 0x07, 0x84, 0x31, 0x81, 0x06, 0xd6, 0x8c, + 0xf5, 0x49, 0xfb, 0x8a, 0xe2, 0xdd, 0xc7, 0xf1, 0x4e, 0x86, 0xf3, 0x7e, 0x86, 0x11, 0x5e, 0x03, + 0xb0, 0x4d, 0x18, 0xa7, 0x31, 0x71, 0x51, 0xc7, 0xc1, 0x21, 0x8f, 0x09, 0x66, 0xe6, 0x8c, 0x14, + 0x5f, 0xe8, 0x53, 0x6e, 0x2b, 0x02, 0x7c, 0x0f, 0x5c, 0x39, 0x56, 0xa9, 0xe3, 0xb6, 0x51, 0x18, + 0xe2, 0x8e, 0x39, 0x2b, 0x5d, 0xa9, 0x7b, 0xc7, 0xe8, 0xdc, 0x56, 0x6c, 0x70, 0x11, 0x4c, 0x71, + 0x1a, 0x39, 0x77, 0xcd, 0xf3, 0x6b, 0xc6, 0xfa, 0x79, 0xbb, 0xcc, 0x69, 0x74, 0x17, 0xbe, 0x03, + 0x96, 0x7a, 0xa8, 0x43, 0x3c, 0xc4, 0x69, 0xcc, 0x9c, 0x88, 0x1e, 0xe2, 0xd8, 0x71, 0x51, 0x64, + 0xce, 0x49, 0x1e, 0xd8, 0xa7, 0xed, 0x0b, 0xd2, 0x36, 0x8a, 0xe0, 0x55, 0xb0, 0x90, 0xae, 0x3a, + 0x0c, 0x73, 0xc9, 0x7e, 0x41, 0xb2, 0x5f, 0x48, 0x09, 0x07, 0x98, 0x0b, 0xde, 0xcb, 0xa0, 0x8a, + 0x3a, 0x1d, 0x7a, 0xd8, 0x21, 0x8c, 0x9b, 0xf3, 0x6b, 0x93, 0xeb, 0x55, 0xbb, 0xbf, 0x00, 0x6b, + 0xa0, 0xe2, 0xe1, 0xf0, 0x48, 0x12, 0x17, 0x24, 0x31, 0x7d, 0xcf, 0x57, 0x1d, 0x58, 0xbc, 0xea, + 0x5c, 0x02, 0xd5, 0x40, 0xd4, 0x17, 0x8e, 0x1e, 0x61, 0x73, 0x71, 0xcd, 0x58, 0x2f, 0xdb, 0x95, + 0x80, 0x84, 0x07, 0xe2, 0x1d, 0x5a, 0x60, 0x51, 0x6a, 0x77, 0x48, 0x28, 0xf6, 0xb7, 0x87, 0x9d, + 0x1e, 0xea, 0x30, 0x73, 0x69, 0xcd, 0x58, 0xaf, 0xd8, 0x0b, 0x92, 0xb4, 0xab, 0x29, 0x0f, 0x50, + 0x87, 0x6d, 0xcc, 0xe7, 0xeb, 0x8e, 0x69, 0x34, 0xfe, 0x60, 0x00, 0x98, 0x29, 0x2f, 0x36, 0x0e, + 0x68, 0x0f, 0x75, 0x4e, 0xaa, 0x2e, 0x9b, 0xa0, 0xca, 0x44, 0xd8, 0x65, 0x3e, 0x97, 0xce, 0x90, + 0xcf, 0x15, 0x21, 0x26, 0xd3, 0x39, 0x17, 0x8b, 0xc9, 0xc2, 0xb1, 0x18, 0x61, 0x7e, 0x04, 0x16, + 0xf6, 0x98, 0x2f, 0xad, 0xc6, 0x89, 0x0f, 0x83, 0x6d, 0xc5, 0x18, 0x6c, 0x2b, 0xd0, 0x02, 0x53, + 0xf4, 0x50, 0xdc, 0x93, 0x4a, 0xa7, 0xe8, 0x56, 0x6c, 0x1b, 0x40, 0xe8, 0x55, 0xcf, 0x8d, 0x4b, + 0x60, 0x65, 0x48, 0x63, 0x5a, 0xac, 0x7f, 0x67, 0x80, 0x8b, 0x22, 0x9a, 0x6d, 0x14, 0xfa, 0xd8, + 0xc6, 0x87, 0x28, 0xf6, 0x76, 0x70, 0x48, 0x03, 0x06, 0x1b, 0xe0, 0xbc, 0x27, 0x9f, 0x1c, 0x4e, + 0xc5, 0xc5, 0xcf, 0x34, 0xe4, 0xf9, 0x98, 0x51, 0x8b, 0xf7, 0xe9, 0xa6, 0xe7, 0xc1, 0x75, 0x30, + 0xdf, 0xe7, 0x89, 0xa5, 0x06, 0xb3, 0x24, 0xd9, 0xe6, 0x12, 0x36, 0xa5, 0x77, 0xec, 0x00, 0x0e, + 0xf6, 0x9d, 0xba, 0xbc, 0x9a, 0x0c, 0x9b, 0x9b, 0x3a, 0xf4, 0x4f, 0x03, 0x54, 0xf6, 0x98, 0x7f, + 0x2f, 0xe2, 0xbb, 0xe1, 0xff, 0xc2, 0xd5, 0x16, 0x82, 0xf9, 0xc4, 0xdd, 0x34, 0x06, 0x7f, 0x34, + 0x40, 0x55, 0x2d, 0xde, 0xeb, 0xf2, 0x57, 0x16, 0x84, 0xbe, 0x87, 0x93, 0xe3, 0x79, 0x58, 0x2e, + 0xe6, 0xe1, 0xa2, 0xcc, 0x18, 0xe5, 0x4c, 0xea, 0xe2, 0xaf, 0x4b, 0xf2, 0x4a, 0x2f, 0x8a, 0x9c, + 0x16, 0xdf, 0xa6, 0x81, 0xae, 0xb6, 0x36, 0xe2, 0x78, 0xd8, 0x2d, 0xa3, 0xa0, 0x5b, 0xd9, 0x70, + 0x95, 0x86, 0xc3, 0x75, 0x1b, 0x94, 0x63, 0xc4, 0xb1, 0xf6, 0xf9, 0xba, 0xa8, 0x15, 0x7f, 0x79, + 0x56, 0xbf, 0xa4, 0xfc, 0x66, 0xde, 0x23, 0x8b, 0xd0, 0x66, 0x80, 0x78, 0xdb, 0xfa, 0x21, 0xf6, + 0x91, 0x7b, 0xb4, 0x83, 0xdd, 0x2f, 0x3e, 0xbb, 0x06, 0x74, 0x58, 0x76, 0xb0, 0x6b, 0x4b, 0xf1, + 0xff, 0xda, 0xf1, 0x78, 0x13, 0xbc, 0x71, 0x52, 0x98, 0xd2, 0x78, 0x3e, 0x99, 0x94, 0x17, 0xba, + 0x74, 0x2e, 0xa0, 0x1e, 0x79, 0x28, 0xae, 0xd7, 0xa2, 0x61, 0x2e, 0x81, 0x29, 0x4e, 0x78, 0x07, + 0xeb, 0xba, 0xa4, 0x5e, 0xe0, 0x1a, 0x98, 0xf1, 0x30, 0x73, 0x63, 0x12, 0xc9, 0x66, 0x5e, 0x52, + 0x29, 0x90, 0x59, 0xca, 0x95, 0xe4, 0xc9, 0x7c, 0x49, 0x4e, 0x1b, 0x61, 0xb9, 0x40, 0x23, 0x9c, + 0x3a, 0x5b, 0x23, 0x9c, 0x2e, 0xd0, 0x08, 0xcf, 0x9d, 0xd4, 0x08, 0x2b, 0x27, 0x35, 0xc2, 0xea, + 0x98, 0x8d, 0x10, 0x14, 0x6b, 0x84, 0x33, 0xc5, 0x1b, 0xe1, 0x15, 0x50, 0x3f, 0x66, 0xc7, 0xd2, + 0x5d, 0xfd, 0xfd, 0x94, 0xcc, 0x9d, 0xed, 0x18, 0x23, 0xde, 0xef, 0x36, 0xe3, 0x4e, 0x6f, 0x2b, + 0x83, 0x99, 0xd1, 0xdf, 0xcf, 0x0f, 0x40, 0x25, 0xc0, 0x1c, 0x79, 0x88, 0x23, 0x3d, 0x68, 0xbd, + 0x5b, 0x68, 0xd6, 0x48, 0xad, 0xd7, 0xc2, 0xfa, 0x56, 0x9f, 0x82, 0xc1, 0x0f, 0x0d, 0xb0, 0xa2, + 0xaf, 0xf8, 0xe4, 0x67, 0xd2, 0x39, 0x47, 0x4e, 0x24, 0x98, 0xe3, 0x98, 0xc9, 0xd3, 0x33, 0x73, + 0xe3, 0xf6, 0x99, 0x54, 0xed, 0xe6, 0xd0, 0xf6, 0x53, 0x30, 0xdb, 0x24, 0xc7, 0x50, 0x60, 0x17, + 0x98, 0xea, 0x34, 0xb2, 0x36, 0x8a, 0xe4, 0x85, 0xbe, 0x6f, 0x82, 0x9a, 0x0f, 0xbe, 0x5d, 0x6c, + 0xb2, 0x12, 0x20, 0x07, 0x0a, 0x23, 0xa3, 0xf8, 0xb5, 0x68, 0xe4, 0x3a, 0x7c, 0x0c, 0x56, 0xd2, + 0x03, 0x8a, 0x3d, 0x27, 0x96, 0xed, 0xce, 0x51, 0x8d, 0x55, 0x0f, 0x13, 0xb7, 0x0a, 0xe9, 0xdd, + 0xec, 0xa3, 0xe4, 0x7a, 0xe6, 0x32, 0x1a, 0x4d, 0x80, 0x21, 0xc8, 0xcc, 0xbf, 0x59, 0x6f, 0xd5, + 0xc0, 0xf1, 0xad, 0x42, 0x5a, 0x77, 0x53, 0x84, 0x8c, 0xaf, 0x4b, 0x64, 0xc4, 0xaa, 0xee, 0xf2, + 0xfd, 0x69, 0xf9, 0x96, 0xbc, 0xb2, 0xe4, 0x8f, 0x6d, 0x72, 0xa8, 0x4f, 0xbd, 0x2c, 0x35, 0x3e, + 0x99, 0x96, 0xa7, 0x5e, 0x0d, 0xa7, 0xe9, 0xa9, 0x4f, 0xaf, 0x50, 0x46, 0xa1, 0x2b, 0xd4, 0xa0, + 0x9a, 0xd2, 0xd0, 0x9d, 0x6c, 0x07, 0x2c, 0x84, 0xf8, 0xd0, 0x91, 0xdc, 0x8e, 0x6e, 0x26, 0xa7, + 0xb6, 0xc2, 0x0b, 0x21, 0x3e, 0xbc, 0x27, 0x24, 0xf4, 0x32, 0x7c, 0x3f, 0x93, 0x39, 0xe5, 0x97, + 0xc8, 0x9c, 0xc2, 0x39, 0x33, 0xf5, 0xd5, 0xe7, 0xcc, 0xf4, 0x57, 0x94, 0x33, 0xe7, 0x5e, 0x65, + 0xce, 0xac, 0x81, 0x59, 0x71, 0x1c, 0xd2, 0x0a, 0x59, 0x51, 0x07, 0x26, 0xc4, 0x87, 0xdb, 0xba, + 0x48, 0x1e, 0x9b, 0x55, 0xd5, 0x57, 0x93, 0x55, 0xc3, 0x43, 0x40, 0x3e, 0x25, 0x92, 0x8c, 0xba, + 0xf1, 0x74, 0x16, 0x4c, 0xee, 0x31, 0x1f, 0x7e, 0x62, 0x80, 0x85, 0xe1, 0xef, 0xc3, 0xc5, 0xec, + 0x1a, 0xf5, 0x7d, 0xb5, 0xb6, 0x39, 0xb6, 0x68, 0x9a, 0xed, 0xbf, 0x35, 0x40, 0xed, 0x84, 0xef, + 0xb2, 0x5b, 0x45, 0x35, 0x1c, 0x8f, 0x51, 0x7b, 0xef, 0xe5, 0x31, 0x4e, 0x30, 0x37, 0xf7, 0xe1, + 0x74, 0x4c, 0x73, 0xb3, 0x18, 0xe3, 0x9a, 0x3b, 0xea, 0x6b, 0x23, 0xfc, 0xc8, 0x00, 0x73, 0x83, + 0xb7, 0x83, 0xa2, 0xf0, 0x79, 0xb9, 0xda, 0x77, 0xc7, 0x93, 0xcb, 0x99, 0x32, 0x50, 0xb2, 0x0b, + 0x9b, 0x92, 0x97, 0x2b, 0x6e, 0xca, 0xe8, 0x7c, 0x90, 0xa6, 0x0c, 0x4c, 0xe8, 0x85, 0x4d, 0xc9, + 0xcb, 0x15, 0x37, 0x65, 0xf4, 0x7c, 0x2e, 0x6a, 0xf9, 0x6c, 0xee, 0x5b, 0xf0, 0x37, 0xce, 0xe6, + 0x9b, 0x92, 0xaa, 0xdd, 0x1a, 0x47, 0x2a, 0x35, 0x22, 0x00, 0x53, 0x6a, 0x9e, 0xbe, 0x56, 0x14, + 0x46, 0xb2, 0xd7, 0xde, 0x3d, 0x13, 0x7b, 0xaa, 0x2e, 0x02, 0xd3, 0x7a, 0x74, 0xb5, 0xce, 0x00, + 0x70, 0xaf, 0xcb, 0x6b, 0x37, 0xcf, 0xc6, 0x9f, 0x6a, 0xfc, 0x8d, 0x01, 0x56, 0x8e, 0x1f, 0x25, + 0x0b, 0x57, 0xb1, 0x63, 0x21, 0x6a, 0xbb, 0x2f, 0x0d, 0x91, 0xda, 0xfa, 0x0b, 0x03, 0xc0, 0x11, + 0x9f, 0x6b, 0x36, 0x0a, 0xa7, 0xdf, 0x90, 0x6c, 0x6d, 0x6b, 0x7c, 0xd9, 0xc4, 0xac, 0xda, 0xd4, + 0xcf, 0xbf, 0x7c, 0x72, 0xd5, 0xd8, 0xfa, 0xe0, 0xe9, 0xf3, 0x55, 0xe3, 0xf3, 0xe7, 0xab, 0xc6, + 0xdf, 0x9f, 0xaf, 0x1a, 0x1f, 0xbf, 0x58, 0x9d, 0xf8, 0xfc, 0xc5, 0xea, 0xc4, 0x9f, 0x5f, 0xac, + 0x4e, 0xfc, 0xf8, 0x3b, 0x3e, 0xe1, 0xed, 0x6e, 0xcb, 0x72, 0x69, 0xa0, 0xff, 0x58, 0x6d, 0xf6, + 0xb5, 0x5e, 0x4b, 0xff, 0x17, 0xed, 0xdd, 0x6c, 0x3e, 0xce, 0xff, 0x39, 0x2a, 0xff, 0x06, 0x6a, + 0x4d, 0xcb, 0x2f, 0x75, 0x5f, 0xff, 0x4f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xb1, 0x80, 0x8d, 0x79, + 0x98, 0x1e, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -3246,6 +3266,18 @@ func (m *MsgCreateConsumer) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if m.InfractionParameters != nil { + { + size, err := m.InfractionParameters.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x3a + } if m.AllowlistedRewardDenoms != nil { { size, err := m.AllowlistedRewardDenoms.MarshalToSizedBuffer(dAtA[:i]) @@ -3359,6 +3391,18 @@ func (m *MsgUpdateConsumer) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if m.InfractionParameters != nil { + { + size, err := m.InfractionParameters.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x4a + } if len(m.NewChainId) > 0 { i -= len(m.NewChainId) copy(dAtA[i:], m.NewChainId) @@ -3950,6 +3994,10 @@ func (m *MsgCreateConsumer) Size() (n int) { l = m.AllowlistedRewardDenoms.Size() n += 1 + l + sovTx(uint64(l)) } + if m.InfractionParameters != nil { + l = m.InfractionParameters.Size() + n += 1 + l + sovTx(uint64(l)) + } return n } @@ -4004,6 +4052,10 @@ func (m *MsgUpdateConsumer) Size() (n int) { if l > 0 { n += 1 + l + sovTx(uint64(l)) } + if m.InfractionParameters != nil { + l = m.InfractionParameters.Size() + n += 1 + l + sovTx(uint64(l)) + } return n } @@ -7371,6 +7423,42 @@ func (m *MsgCreateConsumer) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field InfractionParameters", 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.InfractionParameters == nil { + m.InfractionParameters = &InfractionParameters{} + } + if err := m.InfractionParameters.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipTx(dAtA[iNdEx:]) @@ -7775,6 +7863,42 @@ func (m *MsgUpdateConsumer) Unmarshal(dAtA []byte) error { } m.NewChainId = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex + case 9: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field InfractionParameters", 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.InfractionParameters == nil { + m.InfractionParameters = &InfractionParameters{} + } + if err := m.InfractionParameters.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipTx(dAtA[iNdEx:]) diff --git a/x/ccv/types/shared_params.go b/x/ccv/types/shared_params.go index aa90134f3f..b2fd60db4b 100644 --- a/x/ccv/types/shared_params.go +++ b/x/ccv/types/shared_params.go @@ -108,6 +108,16 @@ func ValidateStringFraction(i interface{}) error { return nil } +func ValidateFraction(dec math.LegacyDec) error { + if dec.IsNegative() { + return fmt.Errorf("param cannot be negative, got %s", dec) + } + if dec.Sub(math.LegacyNewDec(1)).IsPositive() { + return fmt.Errorf("param cannot be greater than 1, got %s", dec) + } + return nil +} + func CalculateTrustPeriod(unbondingPeriod time.Duration, defaultTrustPeriodFraction string) (time.Duration, error) { trustDec, err := math.LegacyNewDecFromStr(defaultTrustPeriodFraction) if err != nil { From 973dbee2be9b5cd8f2313739930f7418db647e2a Mon Sep 17 00:00:00 2001 From: stana-ethernal Date: Thu, 21 Nov 2024 17:42:08 +0100 Subject: [PATCH 02/14] additional tests --- .../keeper/infraction_parameters_test.go | 216 ++++++++++++++++++ x/ccv/provider/keeper/msg_server_test.go | 62 ++++- 2 files changed, 277 insertions(+), 1 deletion(-) create mode 100644 x/ccv/provider/keeper/infraction_parameters_test.go diff --git a/x/ccv/provider/keeper/infraction_parameters_test.go b/x/ccv/provider/keeper/infraction_parameters_test.go new file mode 100644 index 0000000000..11168c03a1 --- /dev/null +++ b/x/ccv/provider/keeper/infraction_parameters_test.go @@ -0,0 +1,216 @@ +package keeper_test + +import ( + "testing" + "time" + + "cosmossdk.io/math" + testkeeper "github.com/cosmos/interchain-security/v6/testutil/keeper" + providertypes "github.com/cosmos/interchain-security/v6/x/ccv/provider/types" + "github.com/golang/mock/gomock" + "github.com/stretchr/testify/require" +) + +func TestUpdateQueuedInfractionParams_RemoveIdenticalItem(t *testing.T) { + k, ctx, ctrl, _ := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t)) + defer ctrl.Finish() + + consumerID := "consumer1" + initialParams := providertypes.InfractionParameters{ + DoubleSign: &providertypes.SlashJailParameters{ + JailDuration: 1000 * time.Second, + SlashFraction: math.LegacyNewDecWithPrec(4, 1), + }, + Downtime: &providertypes.SlashJailParameters{ + JailDuration: 500 * time.Second, + SlashFraction: math.LegacyNewDec(0), + }, + } + + // Set initial infraction parameters + require.NoError(t, k.SetInfractionParameters(ctx, consumerID, initialParams)) + + // Queue identical parameters + require.NoError(t, k.UpdateQueuedInfractionParams(ctx, consumerID, initialParams)) + + // Verify queue is empty + hasQueued := k.HasQueuedInfractionParameters(ctx, consumerID) + require.False(t, hasQueued) +} + +func TestUpdateQueuedInfractionParams_UpdateDifferentItem(t *testing.T) { + k, ctx, ctrl, mocks := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t)) + defer ctrl.Finish() + + mocks.MockStakingKeeper.EXPECT().UnbondingTime(ctx).Return(time.Second, nil).AnyTimes() + + consumerID := "consumer2" + initialParams := providertypes.InfractionParameters{ + DoubleSign: &providertypes.SlashJailParameters{ + JailDuration: 1000 * time.Second, + SlashFraction: math.LegacyNewDecWithPrec(4, 1), + }, + Downtime: &providertypes.SlashJailParameters{ + JailDuration: 500 * time.Second, + SlashFraction: math.LegacyNewDec(0), + }, + } + newParams := providertypes.InfractionParameters{ + DoubleSign: &providertypes.SlashJailParameters{ + JailDuration: 2000 * time.Second, + SlashFraction: math.LegacyNewDecWithPrec(5, 1), + }, + Downtime: &providertypes.SlashJailParameters{ + JailDuration: 1000 * time.Second, + SlashFraction: math.LegacyNewDec(1), + }, + } + + // Set initial infraction parameters + require.NoError(t, k.SetInfractionParameters(ctx, consumerID, initialParams)) + + // Queue different parameters + require.NoError(t, k.UpdateQueuedInfractionParams(ctx, consumerID, newParams)) + + // Verify queue has updated parameters + queuedParams, err := k.GetQueuedInfractionParameters(ctx, consumerID) + require.NoError(t, err) + require.Equal(t, newParams, queuedParams) +} + +func TestUpdateQueuedInfractionParams_OnlyLastItemInQueue(t *testing.T) { + k, ctx, ctrl, mocks := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t)) + defer ctrl.Finish() + + mocks.MockStakingKeeper.EXPECT().UnbondingTime(ctx).Return(time.Second, nil).AnyTimes() + + initialParams := providertypes.InfractionParameters{ + DoubleSign: &providertypes.SlashJailParameters{ + JailDuration: 1000 * time.Second, + SlashFraction: math.LegacyNewDecWithPrec(4, 1), + }, + Downtime: &providertypes.SlashJailParameters{ + JailDuration: 500 * time.Second, + SlashFraction: math.LegacyNewDec(0), + }, + } + + consumerID := "consumer3" + paramsList := []providertypes.InfractionParameters{ + { + DoubleSign: &providertypes.SlashJailParameters{ + JailDuration: 1000 * time.Second, + SlashFraction: math.LegacyNewDecWithPrec(4, 1), + }, + Downtime: &providertypes.SlashJailParameters{ + JailDuration: 500 * time.Second, + SlashFraction: math.LegacyNewDec(0), + }, + }, + { + DoubleSign: &providertypes.SlashJailParameters{ + JailDuration: 1500 * time.Second, + SlashFraction: math.LegacyNewDecWithPrec(3, 1), + }, + Downtime: &providertypes.SlashJailParameters{ + JailDuration: 600 * time.Second, + SlashFraction: math.LegacyNewDec(0), + }, + }, + } + + // Set initial infraction parameters + require.NoError(t, k.SetInfractionParameters(ctx, consumerID, initialParams)) + + // Queue multiple parameters + for _, params := range paramsList { + require.NoError(t, k.UpdateQueuedInfractionParams(ctx, consumerID, params)) + } + + // Verify only the last one is kept in the queue + queuedParams, err := k.GetQueuedInfractionParameters(ctx, consumerID) + require.NoError(t, err) + require.Equal(t, paramsList[len(paramsList)-1], queuedParams) +} + +func TestBeginBlockUpdateInfractionParameters_MixedTiming(t *testing.T) { + keeper, ctx, ctrl, mocks := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t)) + defer ctrl.Finish() + + unbondingTime := time.Second + mocks.MockStakingKeeper.EXPECT().UnbondingTime(gomock.Any()).Return(unbondingTime, nil).AnyTimes() + + // Define old and new InfractionParameters + oldInfractionParams := providertypes.InfractionParameters{ + DoubleSign: &providertypes.SlashJailParameters{ + JailDuration: 1000 * time.Second, + SlashFraction: math.LegacyNewDecWithPrec(4, 1), // 0.4 + }, + Downtime: &providertypes.SlashJailParameters{ + JailDuration: 500 * time.Second, + SlashFraction: math.LegacyNewDec(0), + }, + } + newInfractionParams := providertypes.InfractionParameters{ + DoubleSign: &providertypes.SlashJailParameters{ + JailDuration: 1200 * time.Second, + SlashFraction: math.LegacyNewDecWithPrec(5, 1), // 0.5 + }, + Downtime: &providertypes.SlashJailParameters{ + JailDuration: 600 * time.Second, + SlashFraction: math.LegacyNewDecWithPrec(1, 1), // 0.1 + }, + } + + // Define consumers + consumerIds := []string{"consumer1", "consumer2", "consumer3", "consumer4"} + + // Set old infraction parameters for all consumers + for _, consumerId := range consumerIds { + err := keeper.SetInfractionParameters(ctx, consumerId, oldInfractionParams) + require.NoError(t, err) + } + + // Create contexts for different time scenarios + currentTime := ctx.BlockTime() + ctxWithTimeBefore := ctx.WithBlockTime(currentTime.Add(-2 * unbondingTime)) + ctxWithTimeAfter := ctx.WithBlockTime(currentTime.Add(2 * unbondingTime)) + + // Queue updates for consumers + err := keeper.UpdateQueuedInfractionParams(ctxWithTimeBefore, "consumer1", newInfractionParams) + require.NoError(t, err) + err = keeper.UpdateQueuedInfractionParams(ctxWithTimeBefore, "consumer2", newInfractionParams) + require.NoError(t, err) + err = keeper.UpdateQueuedInfractionParams(ctxWithTimeAfter, "consumer3", newInfractionParams) + require.NoError(t, err) + err = keeper.UpdateQueuedInfractionParams(ctxWithTimeAfter, "consumer4", newInfractionParams) + require.NoError(t, err) + + // Call BeginBlockUpdateInfractionParameters with current context + err = keeper.BeginBlockUpdateInfractionParameters(ctx) + require.NoError(t, err) + + // Confirm queue state + require.True(t, keeper.HasQueuedInfractionParameters(ctx, "consumer3")) + require.True(t, keeper.HasQueuedInfractionParameters(ctx, "consumer4")) + require.False(t, keeper.HasQueuedInfractionParameters(ctx, "consumer1")) + require.False(t, keeper.HasQueuedInfractionParameters(ctx, "consumer2")) + + // Confirm infraction parameters are updated for consumer1 and consumer2 + params1, err := keeper.GetInfractionParameters(ctx, "consumer1") + require.NoError(t, err) + require.Equal(t, params1, newInfractionParams) + + params2, err := keeper.GetInfractionParameters(ctx, "consumer2") + require.NoError(t, err) + require.Equal(t, params2, newInfractionParams) + + // Confirm infraction parameters are not updated for consumer3 and consumer4 + params3, err := keeper.GetInfractionParameters(ctx, "consumer3") + require.NoError(t, err) + require.Equal(t, params3, oldInfractionParams) + + params4, err := keeper.GetInfractionParameters(ctx, "consumer4") + require.NoError(t, err) + require.Equal(t, params4, oldInfractionParams) +} diff --git a/x/ccv/provider/keeper/msg_server_test.go b/x/ccv/provider/keeper/msg_server_test.go index 9e60ab484f..953fecd0f7 100644 --- a/x/ccv/provider/keeper/msg_server_test.go +++ b/x/ccv/provider/keeper/msg_server_test.go @@ -4,7 +4,9 @@ import ( "testing" "time" + "cosmossdk.io/math" "github.com/cosmos/ibc-go/v8/modules/core/02-client/types" + "github.com/golang/mock/gomock" "github.com/stretchr/testify/require" @@ -16,9 +18,12 @@ import ( ) func TestCreateConsumer(t *testing.T) { - providerKeeper, ctx, ctrl, _ := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t)) + providerKeeper, ctx, ctrl, mocks := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t)) defer ctrl.Finish() + mocks.MockSlashingKeeper.EXPECT().DowntimeJailDuration(gomock.Any()).Return(time.Second*600, nil).AnyTimes() + mocks.MockSlashingKeeper.EXPECT().SlashFractionDoubleSign(gomock.Any()).Return(math.LegacyNewDec(0), nil).AnyTimes() + msgServer := providerkeeper.NewMsgServerImpl(&providerKeeper) consumerMetadata := providertypes.ConsumerMetadata{ @@ -41,6 +46,11 @@ func TestCreateConsumer(t *testing.T) { require.Equal(t, "submitter", ownerAddress) phase := providerKeeper.GetConsumerPhase(ctx, "0") require.Equal(t, providertypes.CONSUMER_PHASE_REGISTERED, phase) + infractionParam, err := providerKeeper.GetInfractionParameters(ctx, response.ConsumerId) + require.NoError(t, err) + expectedInfractionParameters, err := providertypes.DefaultConsumerInfractionParameters(ctx, mocks.MockSlashingKeeper) + require.NoError(t, err) + require.Equal(t, expectedInfractionParameters, infractionParam) consumerMetadata = providertypes.ConsumerMetadata{ Name: "chain name", @@ -69,6 +79,11 @@ func TestUpdateConsumer(t *testing.T) { providerKeeper, ctx, ctrl, mocks := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t)) defer ctrl.Finish() + mocks.MockSlashingKeeper.EXPECT().DowntimeJailDuration(gomock.Any()).Return(time.Second*600, nil).AnyTimes() + mocks.MockSlashingKeeper.EXPECT().SlashFractionDoubleSign(gomock.Any()).Return(math.LegacyNewDec(0), nil).AnyTimes() + unbondingTime := 2 * time.Second + mocks.MockStakingKeeper.EXPECT().UnbondingTime(gomock.Any()).Return(unbondingTime, nil).AnyTimes() + msgServer := providerkeeper.NewMsgServerImpl(&providerKeeper) // try to update a non-existing (i.e., no consumer id exists) @@ -142,6 +157,16 @@ func TestUpdateConsumer(t *testing.T) { expectedInitializationParameters := testkeeper.GetTestInitializationParameters() expectedInitializationParameters.InitialHeight.RevisionNumber = 1 expectedPowerShapingParameters := testkeeper.GetTestPowerShapingParameters() + expectedInfractionParameters := providertypes.InfractionParameters{ + DoubleSign: &providertypes.SlashJailParameters{ + JailDuration: 1000 * time.Second, + SlashFraction: math.LegacyNewDecWithPrec(4, 1), // 0.4 + }, + Downtime: &providertypes.SlashJailParameters{ + JailDuration: 500 * time.Second, + SlashFraction: math.LegacyNewDec(0), + }, + } expectedOwnerAddress := "cosmos1dkas8mu4kyhl5jrh4nzvm65qz588hy9qcz08la" expectedChainId = "updatedChainId-1" @@ -151,6 +176,7 @@ func TestUpdateConsumer(t *testing.T) { Metadata: &expectedConsumerMetadata, InitializationParameters: &expectedInitializationParameters, PowerShapingParameters: &expectedPowerShapingParameters, + InfractionParameters: &expectedInfractionParameters, NewChainId: expectedChainId, }) require.NoError(t, err) @@ -175,6 +201,11 @@ func TestUpdateConsumer(t *testing.T) { require.NoError(t, err) require.Equal(t, expectedPowerShapingParameters, actualPowerShapingParameters) + // assert that infraction parameters were updated + actualInfractionParameters, err := providerKeeper.GetInfractionParameters(ctx, consumerId) + require.NoError(t, err) + require.Equal(t, expectedInfractionParameters, actualInfractionParameters) + // assert that the chain id has been updated actualChainId, err := providerKeeper.GetConsumerChainId(ctx, consumerId) require.NoError(t, err) @@ -282,6 +313,35 @@ func TestUpdateConsumer(t *testing.T) { require.NoError(t, err) require.Equal(t, expectedPowerShapingParameters, actualPowerShapingParameters) + // assert that we can update the infraction parameters of a launched chain + providerKeeper.SetConsumerPhase(ctx, consumerId, providertypes.CONSUMER_PHASE_LAUNCHED) + newExpectedInfractionParameters := providertypes.InfractionParameters{ + DoubleSign: &providertypes.SlashJailParameters{ + JailDuration: 2000 * time.Second, + SlashFraction: math.LegacyNewDecWithPrec(6, 1), // 0.6 + }, + Downtime: &providertypes.SlashJailParameters{ + JailDuration: 1000 * time.Second, + SlashFraction: math.LegacyNewDecWithPrec(2, 1), + }, + } + _, err = msgServer.UpdateConsumer(ctx, + &providertypes.MsgUpdateConsumer{ + Owner: expectedOwnerAddress, ConsumerId: consumerId, + Metadata: nil, + InitializationParameters: nil, + PowerShapingParameters: nil, + InfractionParameters: &newExpectedInfractionParameters, + }) + require.NoError(t, err) + // infraction parameters are queued and not updated yet to newExpectedInfractionParameters since the chain is launched + require.Equal(t, expectedInfractionParameters, actualInfractionParameters) + // trigger update of queud infraction params after unbonding time is passed + providerKeeper.BeginBlockUpdateInfractionParameters(ctx.WithBlockTime(ctx.BlockTime().Add(2 * unbondingTime))) + actualInfractionParameters, err = providerKeeper.GetInfractionParameters(ctx, consumerId) + require.NoError(t, err) + require.Equal(t, newExpectedInfractionParameters, actualInfractionParameters) + // assert that if we call `MsgUpdateConsumer` with a spawn time of zero on an initialized chain, the chain // will not be scheduled to launch and will move back to its Registered phase providerKeeper.SetConsumerPhase(ctx, consumerId, providertypes.CONSUMER_PHASE_INITIALIZED) From 99d4eea130d562afaf6a3481fc4c47dcc08fae31 Mon Sep 17 00:00:00 2001 From: stana-ethernal Date: Fri, 22 Nov 2024 20:22:17 +0100 Subject: [PATCH 03/14] relay test fixes --- testutil/keeper/expectations.go | 21 ++++++++++- .../provider/keeper/consumer_equivocation.go | 18 ++++----- .../keeper/consumer_equivocation_test.go | 4 +- x/ccv/provider/keeper/relay.go | 2 +- x/ccv/provider/keeper/relay_test.go | 37 +++++++++++++++---- 5 files changed, 60 insertions(+), 22 deletions(-) diff --git a/testutil/keeper/expectations.go b/testutil/keeper/expectations.go index 12e3c338e1..984fca6859 100644 --- a/testutil/keeper/expectations.go +++ b/testutil/keeper/expectations.go @@ -91,7 +91,7 @@ func GetMocksForDeleteConsumerChain(ctx sdk.Context, mocks *MockedKeepers) []*go func GetMocksForHandleSlashPacket(ctx sdk.Context, mocks MockedKeepers, expectedProviderValConsAddr providertypes.ProviderConsAddress, - valToReturn stakingtypes.Validator, expectJailing bool, + valToReturn stakingtypes.Validator, expectJailing bool, valAddr []byte, ) []*gomock.Call { // These first two calls are always made. calls := []*gomock.Call{ @@ -102,16 +102,33 @@ func GetMocksForHandleSlashPacket(ctx sdk.Context, mocks MockedKeepers, mocks.MockSlashingKeeper.EXPECT().IsTombstoned(ctx, expectedProviderValConsAddr.ToSdkConsAddr()).Return(false).Times(1), + + // called in slash fn + mocks.MockStakingKeeper.EXPECT().GetValidatorByConsAddr( + ctx, expectedProviderValConsAddr.ToSdkConsAddr()).Return( + valToReturn, nil, + ).Times(1), + mocks.MockSlashingKeeper.EXPECT().IsTombstoned(ctx, + expectedProviderValConsAddr.ToSdkConsAddr()).Return(false).Times(1), + mocks.MockStakingKeeper.EXPECT().GetUnbondingDelegationsFromValidator(ctx, + valAddr).Return([]stakingtypes.UnbondingDelegation{}, nil).Times(1), + mocks.MockStakingKeeper.EXPECT().GetRedelegationsFromSrcValidator(ctx, + valAddr).Return([]stakingtypes.Redelegation{}, nil).Times(1), + mocks.MockStakingKeeper.EXPECT().GetLastValidatorPower(ctx, + valAddr).Return(int64(100), nil).Times(1), + mocks.MockStakingKeeper.EXPECT().PowerReduction(ctx).Return(sdk.DefaultPowerReduction).Times(1), + mocks.MockStakingKeeper.EXPECT().SlashWithInfractionReason(ctx, expectedProviderValConsAddr.ToSdkConsAddr(), gomock.Any(), + gomock.Any(), gomock.Any(), gomock.Any()).Return(math.NewInt(0), nil).Times(1), } if expectJailing { + // jail calls = append(calls, mocks.MockStakingKeeper.EXPECT().Jail( gomock.Eq(ctx), gomock.Eq(expectedProviderValConsAddr.ToSdkConsAddr()), ).Return(nil)) // JailUntil is set in this code path. - calls = append(calls, mocks.MockSlashingKeeper.EXPECT().DowntimeJailDuration(ctx).Return(time.Hour, nil).Times(1)) calls = append(calls, mocks.MockSlashingKeeper.EXPECT().JailUntil(ctx, expectedProviderValConsAddr.ToSdkConsAddr(), gomock.Any()).Return(nil).Times(1)) } diff --git a/x/ccv/provider/keeper/consumer_equivocation.go b/x/ccv/provider/keeper/consumer_equivocation.go index db20e6e538..27f23b0ceb 100644 --- a/x/ccv/provider/keeper/consumer_equivocation.go +++ b/x/ccv/provider/keeper/consumer_equivocation.go @@ -80,7 +80,7 @@ func (k Keeper) HandleConsumerDoubleVoting( return err } - if err = k.SlashValidator(ctx, providerAddr, infractionParams.DoubleSign, stakingtypes.Infraction_INFRACTION_DOUBLE_SIGN); err != nil { + if err = k.SlashValidator(ctx, providerAddr, infractionParams.DoubleSign, stakingtypes.Infraction_INFRACTION_DOUBLE_SIGN, evidence.VoteA.Height); err != nil { return err } if err = k.JailAndTombstoneValidator(ctx, providerAddr, infractionParams.DoubleSign); err != nil { @@ -203,7 +203,7 @@ func (k Keeper) HandleConsumerMisbehaviour(ctx sdk.Context, consumerId string, m consumerId, types.NewConsumerConsAddress(sdk.ConsAddress(v.Address.Bytes())), ) - err := k.SlashValidator(ctx, providerAddr, infractionParams.DoubleSign, stakingtypes.Infraction_INFRACTION_DOUBLE_SIGN) + err := k.SlashValidator(ctx, providerAddr, infractionParams.DoubleSign, stakingtypes.Infraction_INFRACTION_DOUBLE_SIGN, 0) if err != nil { logger.Error("failed to slash validator: %s", err) continue @@ -492,7 +492,12 @@ func (k Keeper) ComputePowerToSlash(ctx sdk.Context, validator stakingtypes.Vali } // SlashValidator slashes validator with given provider Address -func (k Keeper) SlashValidator(ctx sdk.Context, providerAddr types.ProviderConsAddress, slashingParams *types.SlashJailParameters, slashingReason stakingtypes.Infraction) error { +func (k Keeper) SlashValidator( + ctx sdk.Context, + providerAddr types.ProviderConsAddress, + slashingParams *types.SlashJailParameters, + slashingReason stakingtypes.Infraction, + infractionHeight int64) error { validator, err := k.stakingKeeper.GetValidatorByConsAddr(ctx, providerAddr.ToSdkConsAddr()) if err != nil && errors.Is(err, stakingtypes.ErrNoValidatorFound) { return errorsmod.Wrapf(slashingtypes.ErrNoValidatorForAddress, "provider consensus address: %s", providerAddr.String()) @@ -529,12 +534,7 @@ func (k Keeper) SlashValidator(ctx sdk.Context, providerAddr types.ProviderConsA powerReduction := k.stakingKeeper.PowerReduction(ctx) totalPower := k.ComputePowerToSlash(ctx, validator, undelegations, redelegations, lastPower, powerReduction) - consAdrr, err := validator.GetConsAddr() - if err != nil { - return err - } - - _, err = k.stakingKeeper.SlashWithInfractionReason(ctx, consAdrr, 0, totalPower, slashingParams.SlashFraction, slashingReason) + _, err = k.stakingKeeper.SlashWithInfractionReason(ctx, providerAddr.ToSdkConsAddr(), infractionHeight, totalPower, slashingParams.SlashFraction, slashingReason) return err } diff --git a/x/ccv/provider/keeper/consumer_equivocation_test.go b/x/ccv/provider/keeper/consumer_equivocation_test.go index d16bf5a7c7..f9c2b35a0f 100644 --- a/x/ccv/provider/keeper/consumer_equivocation_test.go +++ b/x/ccv/provider/keeper/consumer_equivocation_test.go @@ -739,7 +739,7 @@ func TestSlashValidator(t *testing.T) { } gomock.InOrder(expectedCalls...) - keeper.SlashValidator(ctx, providerAddr, getTestInfractionParameters().DoubleSign, stakingtypes.Infraction_INFRACTION_DOUBLE_SIGN) + keeper.SlashValidator(ctx, providerAddr, getTestInfractionParameters().DoubleSign, stakingtypes.Infraction_INFRACTION_DOUBLE_SIGN, 0) } // TestSlashValidatorDoesNotSlashIfValidatorIsUnbonded asserts that `SlashValidator` does not call @@ -766,7 +766,7 @@ func TestSlashValidatorDoesNotSlashIfValidatorIsUnbonded(t *testing.T) { } gomock.InOrder(expectedCalls...) - keeper.SlashValidator(ctx, providerAddr, getTestInfractionParameters().DoubleSign, stakingtypes.Infraction_INFRACTION_DOUBLE_SIGN) + keeper.SlashValidator(ctx, providerAddr, getTestInfractionParameters().DoubleSign, stakingtypes.Infraction_INFRACTION_DOUBLE_SIGN, 0) } func TestEquivocationEvidenceMinHeightCRUD(t *testing.T) { diff --git a/x/ccv/provider/keeper/relay.go b/x/ccv/provider/keeper/relay.go index fb40638900..5c76ec30cf 100644 --- a/x/ccv/provider/keeper/relay.go +++ b/x/ccv/provider/keeper/relay.go @@ -485,7 +485,7 @@ func (k Keeper) HandleSlashPacket(ctx sdk.Context, consumerId string, data ccv.S } // slash validator - if err = k.SlashValidator(ctx, providerConsAddr, infractionParams.Downtime, stakingtypes.Infraction_INFRACTION_DOWNTIME); err != nil { + if err = k.SlashValidator(ctx, providerConsAddr, infractionParams.Downtime, stakingtypes.Infraction_INFRACTION_DOWNTIME, int64(infractionHeight)); err != nil { k.Logger(ctx).Error("failed to slash vaidator", providerConsAddr.ToSdkConsAddr().String(), "err", err.Error()) return } diff --git a/x/ccv/provider/keeper/relay_test.go b/x/ccv/provider/keeper/relay_test.go index e63edea760..45d0b7e4fc 100644 --- a/x/ccv/provider/keeper/relay_test.go +++ b/x/ccv/provider/keeper/relay_test.go @@ -6,6 +6,7 @@ import ( "testing" "time" + authcodec "github.com/cosmos/cosmos-sdk/x/auth/codec" capabilitytypes "github.com/cosmos/ibc-go/modules/capability/types" clienttypes "github.com/cosmos/ibc-go/v8/modules/core/02-client/types" channeltypes "github.com/cosmos/ibc-go/v8/modules/core/04-channel/types" @@ -186,6 +187,12 @@ func TestOnRecvDowntimeSlashPacket(t *testing.T) { }) require.NoError(t, err) + // set consumer infraction parameters + err = providerKeeper.SetInfractionParameters(ctx, consumerId0, *getTestInfractionParameters()) + require.NoError(t, err) + err = providerKeeper.SetInfractionParameters(ctx, consumerId1, *getTestInfractionParameters()) + require.NoError(t, err) + // Also bounced for chain-2 ackResult, err = executeOnRecvSlashPacket(t, &providerKeeper, ctx, channelId1, 2, packetData) require.Equal(t, ccv.SlashPacketBouncedResult, ackResult) @@ -200,12 +207,15 @@ func TestOnRecvDowntimeSlashPacket(t *testing.T) { // Mock call to GetEffectiveValPower, so that it returns 2. providerAddr := providertypes.NewProviderConsAddress(packetData.Validator.Address) + valAddr := sdk.ValAddress(packetData.Validator.Address).String() + valOper, err := providerKeeper.ValidatorAddressCodec().StringToBytes(valAddr) + require.NoError(t, err) calls := []*gomock.Call{ mocks.MockStakingKeeper.EXPECT().GetValidatorByConsAddr(ctx, providerAddr.ToSdkConsAddr()). Return(stakingtypes.Validator{ // provided address must be valid so it can be processed correctly // by k.ValidatorAddressCodec().StringToBytes(val.GetOperator()) call in GetEffectiveValPower() - OperatorAddress: sdk.ValAddress(packetData.Validator.Address).String(), + OperatorAddress: valAddr, }, nil).Times(1), mocks.MockStakingKeeper.EXPECT().GetLastValidatorPower(ctx, gomock.Any()). Return(int64(2), nil).Times(1), @@ -214,7 +224,7 @@ func TestOnRecvDowntimeSlashPacket(t *testing.T) { // Add mocks for slash packet handling calls = append(calls, testkeeper.GetMocksForHandleSlashPacket( - ctx, mocks, providerAddr, stakingtypes.Validator{Jailed: false}, true)..., + ctx, mocks, providerAddr, stakingtypes.Validator{Jailed: false, OperatorAddress: valAddr}, true, valOper)..., ) gomock.InOrder(calls...) @@ -343,6 +353,11 @@ func TestHandleSlashPacket(t *testing.T) { providerConsAddr := cryptotestutil.NewCryptoIdentityFromIntSeed(7842334).ProviderConsAddress() consumerConsAddr := cryptotestutil.NewCryptoIdentityFromIntSeed(784987634).ConsumerConsAddress() + valOperAddr := cryptotestutil.NewCryptoIdentityFromIntSeed(7842334).SDKValOpAddressString() + valAddrCodec := authcodec.NewBech32Codec(sdk.GetConfig().GetBech32ValidatorAddrPrefix()) + valOperAddrBytes, err := valAddrCodec.StringToBytes(valOperAddr) + require.NoError(t, err) + testCases := []struct { name string packetData ccv.SlashPacketData @@ -431,9 +446,10 @@ func TestHandleSlashPacket(t *testing.T) { ) []*gomock.Call { return testkeeper.GetMocksForHandleSlashPacket( ctx, mocks, - providerConsAddr, // expected provider cons addr returned from GetProviderAddrFromConsumerAddr - stakingtypes.Validator{Jailed: false}, // staking keeper val to return - true) // expectJailing = true + providerConsAddr, // expected provider cons addr returned from GetProviderAddrFromConsumerAddr + stakingtypes.Validator{Jailed: false, OperatorAddress: valOperAddr}, // staking keeper val to return + true, // expectJailing = true + valOperAddrBytes) }, 1, consumerConsAddr, @@ -449,9 +465,10 @@ func TestHandleSlashPacket(t *testing.T) { ) []*gomock.Call { return testkeeper.GetMocksForHandleSlashPacket( ctx, mocks, - providerConsAddr, // expected provider cons addr returned from GetProviderAddrFromConsumerAddr - stakingtypes.Validator{Jailed: true}, // staking keeper val to return - false) // expectJailing = false, validator is already jailed. + providerConsAddr, // expected provider cons addr returned from GetProviderAddrFromConsumerAddr + stakingtypes.Validator{Jailed: true, OperatorAddress: valOperAddr}, // staking keeper val to return + false, // expectJailing = false, validator is already jailed. + valOperAddrBytes) }, 1, consumerConsAddr, @@ -477,6 +494,10 @@ func TestHandleSlashPacket(t *testing.T) { err := providerKeeper.SetConsumerValidator(ctx, chainId, providertypes.ConsensusValidator{ProviderConsAddr: providerConsAddr.Address.Bytes()}) require.NoError(t, err) + // set infraction params + err = providerKeeper.SetInfractionParameters(ctx, chainId, *getTestInfractionParameters()) + require.NoError(t, err) + // Execute method and assert expected mock calls. providerKeeper.HandleSlashPacket(ctx, chainId, tc.packetData) From 86fc22c55615b5f4bd55556f422e12fb2635f702 Mon Sep 17 00:00:00 2001 From: stana-ethernal Date: Mon, 25 Nov 2024 08:57:50 +0100 Subject: [PATCH 04/14] integration tests fix --- tests/integration/double_vote.go | 7 ++++--- tests/integration/misbehaviour.go | 3 ++- testutil/ibc_testing/generic_setup.go | 4 ++++ testutil/keeper/unit_test_helpers.go | 14 ++++++++++++++ 4 files changed, 24 insertions(+), 4 deletions(-) diff --git a/tests/integration/double_vote.go b/tests/integration/double_vote.go index e558b11d2b..d4471a5c4a 100644 --- a/tests/integration/double_vote.go +++ b/tests/integration/double_vote.go @@ -257,10 +257,10 @@ func (s *CCVTestSuite) TestHandleConsumerDoubleVoting() { // verifies that the val gets slashed and has fewer tokens after the slashing val, _ := s.providerApp.GetTestStakingKeeper().GetValidator(provCtx, provAddr.ToSdkConsAddr().Bytes()) - slashFraction, err := s.providerApp.GetTestSlashingKeeper().SlashFractionDoubleSign(provCtx) + infractionParam, err := s.providerApp.GetProviderKeeper().GetInfractionParameters(provCtx, tc.consumerId) s.Require().NoError(err) actualTokens := math.LegacyNewDecFromInt(val.GetTokens()) - s.Require().True(initialTokens.Sub(initialTokens.Mul(slashFraction)).Equal(actualTokens)) + s.Require().True(initialTokens.Sub(initialTokens.Mul(infractionParam.DoubleSign.SlashFraction)).Equal(actualTokens)) } else { s.Require().Error(err) @@ -409,8 +409,9 @@ func (s *CCVTestSuite) TestHandleConsumerDoubleVotingSlashesUndelegationsAndRele ) s.Require().NoError(err) - slashFraction, err := s.providerApp.GetTestSlashingKeeper().SlashFractionDoubleSign(s.providerCtx()) + infractionParam, err := s.providerApp.GetProviderKeeper().GetInfractionParameters(s.providerCtx(), s.getFirstBundle().ConsumerId) s.Require().NoError(err) + slashFraction := infractionParam.DoubleSign.SlashFraction // check undelegations are slashed ubds, _ = s.providerApp.GetTestStakingKeeper().GetUnbondingDelegation(s.providerCtx(), delAddr, valAddr) diff --git a/tests/integration/misbehaviour.go b/tests/integration/misbehaviour.go index 86752ee466..a7a4153034 100644 --- a/tests/integration/misbehaviour.go +++ b/tests/integration/misbehaviour.go @@ -80,8 +80,9 @@ func (s *CCVTestSuite) TestHandleConsumerMisbehaviour() { s.Require().True(s.providerApp.GetTestSlashingKeeper().IsTombstoned(s.providerCtx(), provAddr.ToSdkConsAddr())) validator, _ := s.providerApp.GetTestStakingKeeper().GetValidator(s.providerCtx(), provAddr.ToSdkConsAddr().Bytes()) - slashFraction, err := s.providerApp.GetTestSlashingKeeper().SlashFractionDoubleSign(s.providerCtx()) + infractionParam, err := s.providerApp.GetProviderKeeper().GetInfractionParameters(s.providerCtx(), s.getFirstBundle().ConsumerId) s.Require().NoError(err) + slashFraction := infractionParam.DoubleSign.SlashFraction actualTokens := math.LegacyNewDecFromInt(validator.GetTokens()) s.Require().True(initialTokens.Sub(initialTokens.Mul(slashFraction)).Equal(actualTokens)) } diff --git a/testutil/ibc_testing/generic_setup.go b/testutil/ibc_testing/generic_setup.go index e208b5b29a..940971f77f 100644 --- a/testutil/ibc_testing/generic_setup.go +++ b/testutil/ibc_testing/generic_setup.go @@ -156,6 +156,8 @@ func AddConsumer[Tp testutil.ProviderApp, Tc testutil.ConsumerApp]( powerShapingParameters := testkeeper.GetTestPowerShapingParameters() powerShapingParameters.Top_N = consumerTopNParams[index] // isn't used in CreateConsumerClient + infractionPrameters := testkeeper.GetTestInfractionParameters() + consumerId := providerKeeper.FetchAndIncrementConsumerId(providerChain.GetContext()) providerKeeper.SetConsumerChainId(providerChain.GetContext(), consumerId, chainID) err := providerKeeper.SetConsumerMetadata(providerChain.GetContext(), consumerId, consumerMetadata) @@ -164,6 +166,8 @@ func AddConsumer[Tp testutil.ProviderApp, Tc testutil.ConsumerApp]( s.Require().NoError(err) err = providerKeeper.SetConsumerPowerShapingParameters(providerChain.GetContext(), consumerId, powerShapingParameters) s.Require().NoError(err) + err = providerKeeper.SetInfractionParameters(providerChain.GetContext(), consumerId, infractionPrameters) + s.Require().NoError(err) providerKeeper.SetConsumerPhase(providerChain.GetContext(), consumerId, providertypes.CONSUMER_PHASE_INITIALIZED) if chainID == firstConsumerChainID { FirstConsumerID = consumerId diff --git a/testutil/keeper/unit_test_helpers.go b/testutil/keeper/unit_test_helpers.go index b6038025ed..6da3384b23 100644 --- a/testutil/keeper/unit_test_helpers.go +++ b/testutil/keeper/unit_test_helpers.go @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/require" "cosmossdk.io/log" + math "cosmossdk.io/math" "cosmossdk.io/store" "cosmossdk.io/store/metrics" storetypes "cosmossdk.io/store/types" @@ -300,6 +301,19 @@ func GetTestInitializationParameters() providertypes.ConsumerInitializationParam } } +func GetTestInfractionParameters() providertypes.InfractionParameters { + return providertypes.InfractionParameters{ + DoubleSign: &providertypes.SlashJailParameters{ + JailDuration: 1200 * time.Second, + SlashFraction: math.LegacyNewDecWithPrec(5, 1), // 0.5 + }, + Downtime: &providertypes.SlashJailParameters{ + JailDuration: 600 * time.Second, + SlashFraction: math.LegacyNewDec(0), + }, + } +} + func GetTestPowerShapingParameters() providertypes.PowerShapingParameters { return providertypes.PowerShapingParameters{ Top_N: 0, From f1e7c6a2283d8bb05039f24aec7a646c5bd646e1 Mon Sep 17 00:00:00 2001 From: stana-ethernal Date: Tue, 26 Nov 2024 11:26:25 +0100 Subject: [PATCH 05/14] migrations --- x/ccv/provider/migrations/migrator.go | 13 +++++++ x/ccv/provider/migrations/v9/migrations.go | 39 +++++++++++++++++++ .../provider/migrations/v9/migrations_test.go | 35 +++++++++++++++++ x/ccv/provider/module.go | 6 ++- 4 files changed, 92 insertions(+), 1 deletion(-) create mode 100644 x/ccv/provider/migrations/v9/migrations.go create mode 100644 x/ccv/provider/migrations/v9/migrations_test.go diff --git a/x/ccv/provider/migrations/migrator.go b/x/ccv/provider/migrations/migrator.go index 6f5a11f1d3..201380c2e0 100644 --- a/x/ccv/provider/migrations/migrator.go +++ b/x/ccv/provider/migrations/migrator.go @@ -11,6 +11,7 @@ import ( providerkeeper "github.com/cosmos/interchain-security/v6/x/ccv/provider/keeper" v7 "github.com/cosmos/interchain-security/v6/x/ccv/provider/migrations/v7" v8 "github.com/cosmos/interchain-security/v6/x/ccv/provider/migrations/v8" + v9 "github.com/cosmos/interchain-security/v6/x/ccv/provider/migrations/v9" ) // Migrator is a struct for handling in-place store migrations. @@ -96,3 +97,15 @@ func (m Migrator) Migrate7to8(ctx sdktypes.Context) error { return nil } + +// Migrate8to9 migrates x/ccvprovider state from consensus version 8 to 9. +// The migration consists of the following actions: +// - insert infraction parameters for each consumer +func (m Migrator) Migrate8to9(ctx sdktypes.Context) error { + store := ctx.KVStore(m.storeKey) + if err := v9.MigrateConsumerInfractionParams(ctx, store, m.providerKeeper); err != nil { + return err + } + + return nil +} diff --git a/x/ccv/provider/migrations/v9/migrations.go b/x/ccv/provider/migrations/v9/migrations.go new file mode 100644 index 0000000000..df6c7d0057 --- /dev/null +++ b/x/ccv/provider/migrations/v9/migrations.go @@ -0,0 +1,39 @@ +package v9 + +import ( + "time" + + "cosmossdk.io/math" + storetypes "cosmossdk.io/store/types" + + sdk "github.com/cosmos/cosmos-sdk/types" + + providerkeeper "github.com/cosmos/interchain-security/v6/x/ccv/provider/keeper" + providertypes "github.com/cosmos/interchain-security/v6/x/ccv/provider/types" +) + +func MigrateConsumerInfractionParams(ctx sdk.Context, store storetypes.KVStore, pk providerkeeper.Keeper) error { + infractionParameters := defaultInfractionParams() + + activeConsumerIds := pk.GetAllActiveConsumerIds(ctx) + for _, consumerId := range activeConsumerIds { + if err := pk.SetInfractionParameters(ctx, consumerId, infractionParameters); err != nil { + return err + } + } + + return nil +} + +func defaultInfractionParams() providertypes.InfractionParameters { + return providertypes.InfractionParameters{ + DoubleSign: &providertypes.SlashJailParameters{ + JailDuration: time.Duration(1<<63 - 1), // the largest value a time.Duration can hold 9223372036854775807 (approximately 292 years) + SlashFraction: math.LegacyNewDecWithPrec(5, 2), // 0.05 + }, + Downtime: &providertypes.SlashJailParameters{ + JailDuration: 600 * time.Second, + SlashFraction: math.LegacyNewDec(0), // no slashing for downtime on the consumer + }, + } +} diff --git a/x/ccv/provider/migrations/v9/migrations_test.go b/x/ccv/provider/migrations/v9/migrations_test.go new file mode 100644 index 0000000000..21080078b8 --- /dev/null +++ b/x/ccv/provider/migrations/v9/migrations_test.go @@ -0,0 +1,35 @@ +package v9 + +import ( + "testing" + + "github.com/stretchr/testify/require" + + testutil "github.com/cosmos/interchain-security/v6/testutil/keeper" +) + +func TestSetDefaultConsumerInfractionParams(t *testing.T) { + t.Helper() + inMemParams := testutil.NewInMemKeeperParams(t) + k, ctx, ctrl, _ := testutil.GetProviderKeeperAndCtx(t, inMemParams) + defer ctrl.Finish() + + store := ctx.KVStore(inMemParams.StoreKey) + + activeConsumerIds := k.GetAllActiveConsumerIds(ctx) + + for _, consumerId := range activeConsumerIds { + _, err := k.GetInfractionParameters(ctx, consumerId) + require.Error(t, err) + } + + err := MigrateConsumerInfractionParams(ctx, store, k) + require.NoError(t, err) + + defaultInfractionParams := defaultInfractionParams() + for _, consumerId := range activeConsumerIds { + infractionParams, err := k.GetInfractionParameters(ctx, consumerId) + require.NoError(t, err) + require.Equal(t, defaultInfractionParams, infractionParams) + } +} diff --git a/x/ccv/provider/module.go b/x/ccv/provider/module.go index 233d0b36c9..744b17f984 100644 --- a/x/ccv/provider/module.go +++ b/x/ccv/provider/module.go @@ -147,6 +147,10 @@ func (am AppModule) RegisterServices(cfg module.Configurator) { if err := cfg.RegisterMigration(providertypes.ModuleName, 7, migrator.Migrate7to8); err != nil { panic(fmt.Sprintf("failed to register migrator for %s: %s -- from 7 -> 8", providertypes.ModuleName, err)) } + if err := cfg.RegisterMigration(providertypes.ModuleName, 8, migrator.Migrate8to9); err != nil { + panic(fmt.Sprintf("failed to register migrator for %s: %s -- from 8 -> 9", providertypes.ModuleName, err)) + } + } // InitGenesis performs genesis initialization for the provider module. It returns validator updates @@ -168,7 +172,7 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.Raw } // ConsensusVersion implements AppModule/ConsensusVersion. -func (AppModule) ConsensusVersion() uint64 { return 8 } +func (AppModule) ConsensusVersion() uint64 { return 9 } // BeginBlock implements the AppModule interface func (am AppModule) BeginBlock(ctx context.Context) error { From 6d9f644eed3fa887ecb3ad88f515d45f67e57649 Mon Sep 17 00:00:00 2001 From: stana-ethernal Date: Tue, 26 Nov 2024 12:25:27 +0100 Subject: [PATCH 06/14] slash with right params --- testutil/keeper/expectations.go | 14 -------------- x/ccv/provider/keeper/consumer_equivocation.go | 18 +++++++++--------- .../keeper/consumer_equivocation_test.go | 4 ++-- x/ccv/provider/keeper/relay.go | 4 +++- 4 files changed, 14 insertions(+), 26 deletions(-) diff --git a/testutil/keeper/expectations.go b/testutil/keeper/expectations.go index 984fca6859..d5bf6ac9ea 100644 --- a/testutil/keeper/expectations.go +++ b/testutil/keeper/expectations.go @@ -103,20 +103,6 @@ func GetMocksForHandleSlashPacket(ctx sdk.Context, mocks MockedKeepers, mocks.MockSlashingKeeper.EXPECT().IsTombstoned(ctx, expectedProviderValConsAddr.ToSdkConsAddr()).Return(false).Times(1), - // called in slash fn - mocks.MockStakingKeeper.EXPECT().GetValidatorByConsAddr( - ctx, expectedProviderValConsAddr.ToSdkConsAddr()).Return( - valToReturn, nil, - ).Times(1), - mocks.MockSlashingKeeper.EXPECT().IsTombstoned(ctx, - expectedProviderValConsAddr.ToSdkConsAddr()).Return(false).Times(1), - mocks.MockStakingKeeper.EXPECT().GetUnbondingDelegationsFromValidator(ctx, - valAddr).Return([]stakingtypes.UnbondingDelegation{}, nil).Times(1), - mocks.MockStakingKeeper.EXPECT().GetRedelegationsFromSrcValidator(ctx, - valAddr).Return([]stakingtypes.Redelegation{}, nil).Times(1), - mocks.MockStakingKeeper.EXPECT().GetLastValidatorPower(ctx, - valAddr).Return(int64(100), nil).Times(1), - mocks.MockStakingKeeper.EXPECT().PowerReduction(ctx).Return(sdk.DefaultPowerReduction).Times(1), mocks.MockStakingKeeper.EXPECT().SlashWithInfractionReason(ctx, expectedProviderValConsAddr.ToSdkConsAddr(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(math.NewInt(0), nil).Times(1), } diff --git a/x/ccv/provider/keeper/consumer_equivocation.go b/x/ccv/provider/keeper/consumer_equivocation.go index 27f23b0ceb..439dc80bce 100644 --- a/x/ccv/provider/keeper/consumer_equivocation.go +++ b/x/ccv/provider/keeper/consumer_equivocation.go @@ -80,7 +80,7 @@ func (k Keeper) HandleConsumerDoubleVoting( return err } - if err = k.SlashValidator(ctx, providerAddr, infractionParams.DoubleSign, stakingtypes.Infraction_INFRACTION_DOUBLE_SIGN, evidence.VoteA.Height); err != nil { + if err = k.SlashValidator(ctx, providerAddr, infractionParams.DoubleSign); err != nil { return err } if err = k.JailAndTombstoneValidator(ctx, providerAddr, infractionParams.DoubleSign); err != nil { @@ -203,7 +203,7 @@ func (k Keeper) HandleConsumerMisbehaviour(ctx sdk.Context, consumerId string, m consumerId, types.NewConsumerConsAddress(sdk.ConsAddress(v.Address.Bytes())), ) - err := k.SlashValidator(ctx, providerAddr, infractionParams.DoubleSign, stakingtypes.Infraction_INFRACTION_DOUBLE_SIGN, 0) + err := k.SlashValidator(ctx, providerAddr, infractionParams.DoubleSign) if err != nil { logger.Error("failed to slash validator: %s", err) continue @@ -492,12 +492,7 @@ func (k Keeper) ComputePowerToSlash(ctx sdk.Context, validator stakingtypes.Vali } // SlashValidator slashes validator with given provider Address -func (k Keeper) SlashValidator( - ctx sdk.Context, - providerAddr types.ProviderConsAddress, - slashingParams *types.SlashJailParameters, - slashingReason stakingtypes.Infraction, - infractionHeight int64) error { +func (k Keeper) SlashValidator(ctx sdk.Context, providerAddr types.ProviderConsAddress, slashingParams *types.SlashJailParameters) error { validator, err := k.stakingKeeper.GetValidatorByConsAddr(ctx, providerAddr.ToSdkConsAddr()) if err != nil && errors.Is(err, stakingtypes.ErrNoValidatorFound) { return errorsmod.Wrapf(slashingtypes.ErrNoValidatorForAddress, "provider consensus address: %s", providerAddr.String()) @@ -534,7 +529,12 @@ func (k Keeper) SlashValidator( powerReduction := k.stakingKeeper.PowerReduction(ctx) totalPower := k.ComputePowerToSlash(ctx, validator, undelegations, redelegations, lastPower, powerReduction) - _, err = k.stakingKeeper.SlashWithInfractionReason(ctx, providerAddr.ToSdkConsAddr(), infractionHeight, totalPower, slashingParams.SlashFraction, slashingReason) + consAdrr, err := validator.GetConsAddr() + if err != nil { + return err + } + + _, err = k.stakingKeeper.SlashWithInfractionReason(ctx, consAdrr, 0, totalPower, slashingParams.SlashFraction, stakingtypes.Infraction_INFRACTION_DOUBLE_SIGN) return err } diff --git a/x/ccv/provider/keeper/consumer_equivocation_test.go b/x/ccv/provider/keeper/consumer_equivocation_test.go index f9c2b35a0f..1e740a4aae 100644 --- a/x/ccv/provider/keeper/consumer_equivocation_test.go +++ b/x/ccv/provider/keeper/consumer_equivocation_test.go @@ -739,7 +739,7 @@ func TestSlashValidator(t *testing.T) { } gomock.InOrder(expectedCalls...) - keeper.SlashValidator(ctx, providerAddr, getTestInfractionParameters().DoubleSign, stakingtypes.Infraction_INFRACTION_DOUBLE_SIGN, 0) + keeper.SlashValidator(ctx, providerAddr, getTestInfractionParameters().DoubleSign) } // TestSlashValidatorDoesNotSlashIfValidatorIsUnbonded asserts that `SlashValidator` does not call @@ -766,7 +766,7 @@ func TestSlashValidatorDoesNotSlashIfValidatorIsUnbonded(t *testing.T) { } gomock.InOrder(expectedCalls...) - keeper.SlashValidator(ctx, providerAddr, getTestInfractionParameters().DoubleSign, stakingtypes.Infraction_INFRACTION_DOUBLE_SIGN, 0) + keeper.SlashValidator(ctx, providerAddr, getTestInfractionParameters().DoubleSign) } func TestEquivocationEvidenceMinHeightCRUD(t *testing.T) { diff --git a/x/ccv/provider/keeper/relay.go b/x/ccv/provider/keeper/relay.go index 5c76ec30cf..790bf8b10b 100644 --- a/x/ccv/provider/keeper/relay.go +++ b/x/ccv/provider/keeper/relay.go @@ -485,7 +485,9 @@ func (k Keeper) HandleSlashPacket(ctx sdk.Context, consumerId string, data ccv.S } // slash validator - if err = k.SlashValidator(ctx, providerConsAddr, infractionParams.Downtime, stakingtypes.Infraction_INFRACTION_DOWNTIME, int64(infractionHeight)); err != nil { + _, err = k.stakingKeeper.SlashWithInfractionReason(ctx, providerConsAddr.ToSdkConsAddr(), int64(infractionHeight), + data.Validator.Power, infractionParams.Downtime.SlashFraction, stakingtypes.Infraction_INFRACTION_DOWNTIME) + if err != nil { k.Logger(ctx).Error("failed to slash vaidator", providerConsAddr.ToSdkConsAddr().String(), "err", err.Error()) return } From 544331ee9625649a5c6eff9b9b717111cfbfc87c Mon Sep 17 00:00:00 2001 From: stana-ethernal Date: Tue, 26 Nov 2024 13:37:48 +0100 Subject: [PATCH 07/14] comment fix --- testutil/keeper/expectations.go | 2 +- x/ccv/provider/keeper/infraction_parameters.go | 4 ++-- x/ccv/provider/keeper/relay_test.go | 12 +++--------- 3 files changed, 6 insertions(+), 12 deletions(-) diff --git a/testutil/keeper/expectations.go b/testutil/keeper/expectations.go index d5bf6ac9ea..52221cf283 100644 --- a/testutil/keeper/expectations.go +++ b/testutil/keeper/expectations.go @@ -91,7 +91,7 @@ func GetMocksForDeleteConsumerChain(ctx sdk.Context, mocks *MockedKeepers) []*go func GetMocksForHandleSlashPacket(ctx sdk.Context, mocks MockedKeepers, expectedProviderValConsAddr providertypes.ProviderConsAddress, - valToReturn stakingtypes.Validator, expectJailing bool, valAddr []byte, + valToReturn stakingtypes.Validator, expectJailing bool, ) []*gomock.Call { // These first two calls are always made. calls := []*gomock.Call{ diff --git a/x/ccv/provider/keeper/infraction_parameters.go b/x/ccv/provider/keeper/infraction_parameters.go index 5dd63f3849..8abf21a5b6 100644 --- a/x/ccv/provider/keeper/infraction_parameters.go +++ b/x/ccv/provider/keeper/infraction_parameters.go @@ -162,8 +162,8 @@ func (k Keeper) RemoveConsumerInfractionQueuedData(ctx sdk.Context, consumerId s // UpdateQueuedInfractionParams updates the infraction parameters in the time queue. // Parameters for the specific consumer already exist in the queue: -// - If the new parameters are the same as the current queued parameters, the existing entry is removed to cancel the update. -// - If the new parameters are different, the existing entry is removed and new entry is added to the queue to schedule the update. +// - If the new parameters are the same as the current infraction parameters, the existing queued entry is removed to cancel the update. +// - If the new parameters are different from both queued and current parameters, the existing entry is removed and new entry is added to the queue to schedule the update. // // Parameters for the specific consumer do not exist in the update queue and the new parameters differ from the consumer current infraction parameters, // a new entry is added to the queue to schedule the update. diff --git a/x/ccv/provider/keeper/relay_test.go b/x/ccv/provider/keeper/relay_test.go index 45d0b7e4fc..5f31bc3a43 100644 --- a/x/ccv/provider/keeper/relay_test.go +++ b/x/ccv/provider/keeper/relay_test.go @@ -6,7 +6,6 @@ import ( "testing" "time" - authcodec "github.com/cosmos/cosmos-sdk/x/auth/codec" capabilitytypes "github.com/cosmos/ibc-go/modules/capability/types" clienttypes "github.com/cosmos/ibc-go/v8/modules/core/02-client/types" channeltypes "github.com/cosmos/ibc-go/v8/modules/core/04-channel/types" @@ -208,8 +207,6 @@ func TestOnRecvDowntimeSlashPacket(t *testing.T) { // Mock call to GetEffectiveValPower, so that it returns 2. providerAddr := providertypes.NewProviderConsAddress(packetData.Validator.Address) valAddr := sdk.ValAddress(packetData.Validator.Address).String() - valOper, err := providerKeeper.ValidatorAddressCodec().StringToBytes(valAddr) - require.NoError(t, err) calls := []*gomock.Call{ mocks.MockStakingKeeper.EXPECT().GetValidatorByConsAddr(ctx, providerAddr.ToSdkConsAddr()). Return(stakingtypes.Validator{ @@ -224,7 +221,7 @@ func TestOnRecvDowntimeSlashPacket(t *testing.T) { // Add mocks for slash packet handling calls = append(calls, testkeeper.GetMocksForHandleSlashPacket( - ctx, mocks, providerAddr, stakingtypes.Validator{Jailed: false, OperatorAddress: valAddr}, true, valOper)..., + ctx, mocks, providerAddr, stakingtypes.Validator{Jailed: false, OperatorAddress: valAddr}, true)..., ) gomock.InOrder(calls...) @@ -354,9 +351,6 @@ func TestHandleSlashPacket(t *testing.T) { consumerConsAddr := cryptotestutil.NewCryptoIdentityFromIntSeed(784987634).ConsumerConsAddress() valOperAddr := cryptotestutil.NewCryptoIdentityFromIntSeed(7842334).SDKValOpAddressString() - valAddrCodec := authcodec.NewBech32Codec(sdk.GetConfig().GetBech32ValidatorAddrPrefix()) - valOperAddrBytes, err := valAddrCodec.StringToBytes(valOperAddr) - require.NoError(t, err) testCases := []struct { name string @@ -449,7 +443,7 @@ func TestHandleSlashPacket(t *testing.T) { providerConsAddr, // expected provider cons addr returned from GetProviderAddrFromConsumerAddr stakingtypes.Validator{Jailed: false, OperatorAddress: valOperAddr}, // staking keeper val to return true, // expectJailing = true - valOperAddrBytes) + ) }, 1, consumerConsAddr, @@ -468,7 +462,7 @@ func TestHandleSlashPacket(t *testing.T) { providerConsAddr, // expected provider cons addr returned from GetProviderAddrFromConsumerAddr stakingtypes.Validator{Jailed: true, OperatorAddress: valOperAddr}, // staking keeper val to return false, // expectJailing = false, validator is already jailed. - valOperAddrBytes) + ) }, 1, consumerConsAddr, From e9f7021e6a1e5f47ab50baedc3c05cd443f4c3be Mon Sep 17 00:00:00 2001 From: stana-ethernal Date: Tue, 26 Nov 2024 15:30:41 +0100 Subject: [PATCH 08/14] docs --- .../provider/2403-customizable-slashing-jailing.md | 0 .../2403-customizable-slashing-jailing.md | 2 ++ docs/docs/features/slashing.md | 10 +++++++--- 3 files changed, 9 insertions(+), 3 deletions(-) create mode 100644 .changelog/unreleased/features/provider/2403-customizable-slashing-jailing.md create mode 100644 .changelog/unreleased/state-breaking/2403-customizable-slashing-jailing.md diff --git a/.changelog/unreleased/features/provider/2403-customizable-slashing-jailing.md b/.changelog/unreleased/features/provider/2403-customizable-slashing-jailing.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.changelog/unreleased/state-breaking/2403-customizable-slashing-jailing.md b/.changelog/unreleased/state-breaking/2403-customizable-slashing-jailing.md new file mode 100644 index 0000000000..2115bfdc14 --- /dev/null +++ b/.changelog/unreleased/state-breaking/2403-customizable-slashing-jailing.md @@ -0,0 +1,2 @@ +- Allow consumer chains to customize the slashing and jailing conditions. Every consumer chain can decide the punishment for every type of infraction. + ([\#2403](https://github.com/cosmos/interchain-security/pull/2403)) \ No newline at end of file diff --git a/docs/docs/features/slashing.md b/docs/docs/features/slashing.md index ac69445b7e..36451c2562 100644 --- a/docs/docs/features/slashing.md +++ b/docs/docs/features/slashing.md @@ -14,8 +14,8 @@ The ICS protocol differentiates between downtime and equivocation infractions. ## Downtime Infractions Downtime infractions are reported by consumer chains and are acted upon on the provider as soon as they are received. -Instead of slashing, the provider will **_only jail_** offending validator for the duration of time established by the provider chain parameters. -Note that validators are only jailed for downtime on consumer chains that they opted in to validate on, +The provider will jail and slash the offending validator. The jailing duration and slashing fraction are determined by the consumer's downtime infraction parameters on the provider chain. +Note that validators are only slashed and jailed for downtime on consumer chains that they opted in to validate on, or in the case of Top N chains, where they are automatically opted in by being in the Top N% of the validator set on the provider. For preventing malicious consumer chains from harming the provider, [slash throttling](../adrs/adr-002-throttle.md) (also known as _jail throttling_) ensures that only a fraction of the provider validator set can be jailed at any given time. @@ -24,7 +24,7 @@ For preventing malicious consumer chains from harming the provider, [slash throt Equivocation infractions are reported by external agents (e.g., relayers) that can submit to the provider evidence of light client or double signing attacks observed on a consumer chain. The evidence is submitted by sending `MsgSubmitConsumerMisbehaviour` or `MsgSubmitConsumerDoubleVoting` messages to the provider. -When valid evidence is received, the malicious validators are slashed, jailed, and tombstoned on the provider. +When valid evidence is received, the malicious validators are slashed, jailed, and tombstoned on the provider. The jailing duration and slashing fraction are determined by the consumer's double sign infraction parameters on the provider chain. This is enabled through the _cryptographic verification of equivocation_ feature. For more details, see [ADR-005](../adrs/adr-005-cryptographic-equivocation-verification.md) and [ADR-013](../adrs/adr-013-equivocation-slashing.md). @@ -597,3 +597,7 @@ The following command demonstrates how to run a Hermes instance in _evidence mod hermes evidence --chain ``` Note that `hermes evidence` takes a `--check-past-blocks` option giving the possibility to look for older evidence (default is 100). + +### Infraction parameters + +Jailing and slashing for misbehavior on a consumer chain are governed by parameters defined on the provider chain for that specific consumer chain. To create or update these infraction parameters, use the MsgCreateConsumer or MsgUpdateConsumer messages. When creating a consumer chain, if custom infraction parameters are not specified, default values from the provider are applied. For updates, parameters can be modified immediately if the chain is in the pre-launch phase. If the chain has already launched, the update will be scheduled to take effect after the unbonding period expires. This ensures that changes are applied seamlessly based on the chain's lifecycle. \ No newline at end of file From 1288a3f66d0e4b5f7aaf752181dfdcd066cf937b Mon Sep 17 00:00:00 2001 From: stana-ethernal Date: Wed, 27 Nov 2024 12:27:26 +0100 Subject: [PATCH 09/14] Revert "migrations" This reverts commit f1e7c6a2283d8bb05039f24aec7a646c5bd646e1. --- x/ccv/provider/migrations/migrator.go | 13 ------- x/ccv/provider/migrations/v9/migrations.go | 39 ------------------- .../provider/migrations/v9/migrations_test.go | 35 ----------------- x/ccv/provider/module.go | 6 +-- 4 files changed, 1 insertion(+), 92 deletions(-) delete mode 100644 x/ccv/provider/migrations/v9/migrations.go delete mode 100644 x/ccv/provider/migrations/v9/migrations_test.go diff --git a/x/ccv/provider/migrations/migrator.go b/x/ccv/provider/migrations/migrator.go index 201380c2e0..6f5a11f1d3 100644 --- a/x/ccv/provider/migrations/migrator.go +++ b/x/ccv/provider/migrations/migrator.go @@ -11,7 +11,6 @@ import ( providerkeeper "github.com/cosmos/interchain-security/v6/x/ccv/provider/keeper" v7 "github.com/cosmos/interchain-security/v6/x/ccv/provider/migrations/v7" v8 "github.com/cosmos/interchain-security/v6/x/ccv/provider/migrations/v8" - v9 "github.com/cosmos/interchain-security/v6/x/ccv/provider/migrations/v9" ) // Migrator is a struct for handling in-place store migrations. @@ -97,15 +96,3 @@ func (m Migrator) Migrate7to8(ctx sdktypes.Context) error { return nil } - -// Migrate8to9 migrates x/ccvprovider state from consensus version 8 to 9. -// The migration consists of the following actions: -// - insert infraction parameters for each consumer -func (m Migrator) Migrate8to9(ctx sdktypes.Context) error { - store := ctx.KVStore(m.storeKey) - if err := v9.MigrateConsumerInfractionParams(ctx, store, m.providerKeeper); err != nil { - return err - } - - return nil -} diff --git a/x/ccv/provider/migrations/v9/migrations.go b/x/ccv/provider/migrations/v9/migrations.go deleted file mode 100644 index df6c7d0057..0000000000 --- a/x/ccv/provider/migrations/v9/migrations.go +++ /dev/null @@ -1,39 +0,0 @@ -package v9 - -import ( - "time" - - "cosmossdk.io/math" - storetypes "cosmossdk.io/store/types" - - sdk "github.com/cosmos/cosmos-sdk/types" - - providerkeeper "github.com/cosmos/interchain-security/v6/x/ccv/provider/keeper" - providertypes "github.com/cosmos/interchain-security/v6/x/ccv/provider/types" -) - -func MigrateConsumerInfractionParams(ctx sdk.Context, store storetypes.KVStore, pk providerkeeper.Keeper) error { - infractionParameters := defaultInfractionParams() - - activeConsumerIds := pk.GetAllActiveConsumerIds(ctx) - for _, consumerId := range activeConsumerIds { - if err := pk.SetInfractionParameters(ctx, consumerId, infractionParameters); err != nil { - return err - } - } - - return nil -} - -func defaultInfractionParams() providertypes.InfractionParameters { - return providertypes.InfractionParameters{ - DoubleSign: &providertypes.SlashJailParameters{ - JailDuration: time.Duration(1<<63 - 1), // the largest value a time.Duration can hold 9223372036854775807 (approximately 292 years) - SlashFraction: math.LegacyNewDecWithPrec(5, 2), // 0.05 - }, - Downtime: &providertypes.SlashJailParameters{ - JailDuration: 600 * time.Second, - SlashFraction: math.LegacyNewDec(0), // no slashing for downtime on the consumer - }, - } -} diff --git a/x/ccv/provider/migrations/v9/migrations_test.go b/x/ccv/provider/migrations/v9/migrations_test.go deleted file mode 100644 index 21080078b8..0000000000 --- a/x/ccv/provider/migrations/v9/migrations_test.go +++ /dev/null @@ -1,35 +0,0 @@ -package v9 - -import ( - "testing" - - "github.com/stretchr/testify/require" - - testutil "github.com/cosmos/interchain-security/v6/testutil/keeper" -) - -func TestSetDefaultConsumerInfractionParams(t *testing.T) { - t.Helper() - inMemParams := testutil.NewInMemKeeperParams(t) - k, ctx, ctrl, _ := testutil.GetProviderKeeperAndCtx(t, inMemParams) - defer ctrl.Finish() - - store := ctx.KVStore(inMemParams.StoreKey) - - activeConsumerIds := k.GetAllActiveConsumerIds(ctx) - - for _, consumerId := range activeConsumerIds { - _, err := k.GetInfractionParameters(ctx, consumerId) - require.Error(t, err) - } - - err := MigrateConsumerInfractionParams(ctx, store, k) - require.NoError(t, err) - - defaultInfractionParams := defaultInfractionParams() - for _, consumerId := range activeConsumerIds { - infractionParams, err := k.GetInfractionParameters(ctx, consumerId) - require.NoError(t, err) - require.Equal(t, defaultInfractionParams, infractionParams) - } -} diff --git a/x/ccv/provider/module.go b/x/ccv/provider/module.go index 744b17f984..233d0b36c9 100644 --- a/x/ccv/provider/module.go +++ b/x/ccv/provider/module.go @@ -147,10 +147,6 @@ func (am AppModule) RegisterServices(cfg module.Configurator) { if err := cfg.RegisterMigration(providertypes.ModuleName, 7, migrator.Migrate7to8); err != nil { panic(fmt.Sprintf("failed to register migrator for %s: %s -- from 7 -> 8", providertypes.ModuleName, err)) } - if err := cfg.RegisterMigration(providertypes.ModuleName, 8, migrator.Migrate8to9); err != nil { - panic(fmt.Sprintf("failed to register migrator for %s: %s -- from 8 -> 9", providertypes.ModuleName, err)) - } - } // InitGenesis performs genesis initialization for the provider module. It returns validator updates @@ -172,7 +168,7 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.Raw } // ConsensusVersion implements AppModule/ConsensusVersion. -func (AppModule) ConsensusVersion() uint64 { return 9 } +func (AppModule) ConsensusVersion() uint64 { return 8 } // BeginBlock implements the AppModule interface func (am AppModule) BeginBlock(ctx context.Context) error { From 69ec878bb060642cd82ed11f3a9d7c8a04d2ebf3 Mon Sep 17 00:00:00 2001 From: stana-ethernal Date: Wed, 27 Nov 2024 14:06:36 +0100 Subject: [PATCH 10/14] cr fix --- .../2403-customizable-slashing-jailing.md | 1 + .../2403-customizable-slashing-jailing.md | 0 .../2403-customizable-slashing-jailing.md | 3 +- docs/docs/build/modules/02-provider.md | 40 ++++++++++++++++--- docs/docs/features/slashing.md | 2 +- .../ccv/provider/v1/provider.proto | 2 +- testutil/keeper/expectations.go | 6 +-- x/ccv/provider/keeper/msg_server.go | 9 +++-- x/ccv/provider/keeper/relay.go | 18 ++++----- x/ccv/provider/types/provider.pb.go | 34 ++++++++-------- 10 files changed, 72 insertions(+), 43 deletions(-) create mode 100644 .changelog/unreleased/features/2403-customizable-slashing-jailing.md delete mode 100644 .changelog/unreleased/features/provider/2403-customizable-slashing-jailing.md diff --git a/.changelog/unreleased/features/2403-customizable-slashing-jailing.md b/.changelog/unreleased/features/2403-customizable-slashing-jailing.md new file mode 100644 index 0000000000..733860a5c7 --- /dev/null +++ b/.changelog/unreleased/features/2403-customizable-slashing-jailing.md @@ -0,0 +1 @@ +- `[x/provider]` Enable the customization of the slashing and jailing conditions for infractions committed by validators on consumer chains (as per [ADR 020](https://cosmos.github.io/interchain-security/adrs/adr-020-cutomizable_slashing_and_jailing)). Every consumer chain can decide the punishment for every type of infraction. \ No newline at end of file diff --git a/.changelog/unreleased/features/provider/2403-customizable-slashing-jailing.md b/.changelog/unreleased/features/provider/2403-customizable-slashing-jailing.md deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/.changelog/unreleased/state-breaking/2403-customizable-slashing-jailing.md b/.changelog/unreleased/state-breaking/2403-customizable-slashing-jailing.md index 2115bfdc14..733860a5c7 100644 --- a/.changelog/unreleased/state-breaking/2403-customizable-slashing-jailing.md +++ b/.changelog/unreleased/state-breaking/2403-customizable-slashing-jailing.md @@ -1,2 +1 @@ -- Allow consumer chains to customize the slashing and jailing conditions. Every consumer chain can decide the punishment for every type of infraction. - ([\#2403](https://github.com/cosmos/interchain-security/pull/2403)) \ No newline at end of file +- `[x/provider]` Enable the customization of the slashing and jailing conditions for infractions committed by validators on consumer chains (as per [ADR 020](https://cosmos.github.io/interchain-security/adrs/adr-020-cutomizable_slashing_and_jailing)). Every consumer chain can decide the punishment for every type of infraction. \ No newline at end of file diff --git a/docs/docs/build/modules/02-provider.md b/docs/docs/build/modules/02-provider.md index ef7d475193..baecb4d64e 100644 --- a/docs/docs/build/modules/02-provider.md +++ b/docs/docs/build/modules/02-provider.md @@ -482,8 +482,8 @@ message MsgChangeRewardDenoms { `MsgCreateConsumer` enables a user to create a consumer chain. Both the `chain_id` and `metadata` fields are mandatory. -The `initialization_parameters`, `power_shaping_parameters`, and `allowlisted_reward_denoms` fields are optional. -The parameters not provided are set to their zero value. +The `initialization_parameters`, `power_shaping_parameters`, `infraction_parameters` and `allowlisted_reward_denoms` fields are optional. +The parameters not provided are set to their zero value. If `infraction_parameters` are not set, the default values currently configured on the provider are used. The owner of the created consumer chain is the submitter of the message. This message cannot be submitted as part of a governance proposal, i.e., the submitter cannot be the gov module account address. @@ -516,6 +516,9 @@ message MsgCreateConsumer { // allowlisted reward denoms by the consumer chain AllowlistedRewardDenoms allowlisted_reward_denoms = 6; + + // infraction parameters for slashing and jailing + InfractionParameters infraction_parameters = 7; } ``` @@ -524,11 +527,11 @@ message MsgCreateConsumer { `MsgUpdateConsumer` enables the owner of a consumer chain to update its parameters (e.g., set a new owner). Note that only the `owner` (i.e., signer) and `consumer_id` fields are mandatory. -The others field are optional. Not providing one of them will leave the existing values unchanged. -Providing one of `metadata`, `initialization_parameters`, `power_shaping_parameters`, or `allowlisted_reward_denoms` +The others field are optional. Not providing one of them will leave the existing values unchanged. For `infraction_parameters` it is possible to update separately `downtime` and `double_sign` parameters by providing just desired one. +Providing one of `metadata`, `initialization_parameters`, `power_shaping_parameters`, `infraction_parameters.double_sign`, `infraction_parameters.downtime` or `allowlisted_reward_denoms` will update all the containing fields. If one of the containing fields is missing, it will be set to its zero value. -For example, updating the `initialization_parameters` without specifying the `spawn_time`, will set the `spawn_time` to zero. +For example, updating the `initialization_parameters` without specifying the `spawn_time`, will set the `spawn_time` to zero. If the `initialization_parameters` field is set and `initialization_parameters.spawn_time > 0`, then the consumer chain will be scheduled to launch at `spawn_time`. Updating the `spawn_time` from a positive value to zero will remove the consumer chain from the list of scheduled to launch chains. @@ -568,6 +571,9 @@ message MsgUpdateConsumer { // to update the chain id of the chain (can only be updated if the chain has not yet launched) string new_chain_id = 8; + + // infraction parameters for slashing and jailing + InfractionParameters infraction_parameters = 9; } ``` @@ -829,6 +835,7 @@ In the `BeginBlock` of the provider module the following actions are performed: - Remove every stopped consumer chain for which the removal time has passed. - Replenish the throttling meter if necessary. - Distribute ICS rewards to the opted in validators. +- Update consumer infraction parameters with the queued infraction parameters that were added to the queue before a time period greater than the unbonding time. Note that for every consumer chain, the computation of its initial validator set is based on the consumer's [power shaping parameters](../../features/power-shaping.md) and the [validators that opted in on that consumer](../../features/partial-set-security.md). @@ -2873,7 +2880,17 @@ grpcurl -plaintext -d '{"consumer_id": "0"}' localhost:9090 interchain_security. "validatorSetCap": 50, "minStake": "1000", "allowInactiveVals": true - } + }, + "infraction_parameters":{ + "double_sign":{ + "slash_fraction":"0.050000000000000000", + "jail_duration":"9223372036.854775807s" + }, + "downtime":{ + "slash_fraction":"0.000000000000000000", + "jail_duration":"600s" + } + } } ``` @@ -3572,6 +3589,17 @@ Output: "minStake": "1000", "allowInactiveVals": true } + , + "infraction_parameters":{ + "double_sign":{ + "slash_fraction":"0.050000000000000000", + "jail_duration":"9223372036.854775807s" + }, + "downtime":{ + "slash_fraction":"0.000000000000000000", + "jail_duration":"600s" + } + } } ``` diff --git a/docs/docs/features/slashing.md b/docs/docs/features/slashing.md index 36451c2562..6bb4f25299 100644 --- a/docs/docs/features/slashing.md +++ b/docs/docs/features/slashing.md @@ -15,7 +15,7 @@ The ICS protocol differentiates between downtime and equivocation infractions. Downtime infractions are reported by consumer chains and are acted upon on the provider as soon as they are received. The provider will jail and slash the offending validator. The jailing duration and slashing fraction are determined by the consumer's downtime infraction parameters on the provider chain. -Note that validators are only slashed and jailed for downtime on consumer chains that they opted in to validate on, +By default, validators are **_only jailed_** for downtime on consumer chains that they opted in to validate on, or in the case of Top N chains, where they are automatically opted in by being in the Top N% of the validator set on the provider. For preventing malicious consumer chains from harming the provider, [slash throttling](../adrs/adr-002-throttle.md) (also known as _jail throttling_) ensures that only a fraction of the provider validator set can be jailed at any given time. diff --git a/proto/interchain_security/ccv/provider/v1/provider.proto b/proto/interchain_security/ccv/provider/v1/provider.proto index 4cec258646..a99778ba32 100644 --- a/proto/interchain_security/ccv/provider/v1/provider.proto +++ b/proto/interchain_security/ccv/provider/v1/provider.proto @@ -572,6 +572,6 @@ message SlashJailParameters { (amino.dont_omitempty) = true ]; // for permanent jailing use 9223372036854775807 which is the largest value a time.Duration can hold (approximately 292 years) - google.protobuf.Duration jail_duration = 8 + google.protobuf.Duration jail_duration = 2 [ (gogoproto.nullable) = false, (gogoproto.stdduration) = true ]; } \ No newline at end of file diff --git a/testutil/keeper/expectations.go b/testutil/keeper/expectations.go index 52221cf283..3ae55eebf1 100644 --- a/testutil/keeper/expectations.go +++ b/testutil/keeper/expectations.go @@ -102,12 +102,12 @@ func GetMocksForHandleSlashPacket(ctx sdk.Context, mocks MockedKeepers, mocks.MockSlashingKeeper.EXPECT().IsTombstoned(ctx, expectedProviderValConsAddr.ToSdkConsAddr()).Return(false).Times(1), - - mocks.MockStakingKeeper.EXPECT().SlashWithInfractionReason(ctx, expectedProviderValConsAddr.ToSdkConsAddr(), gomock.Any(), - gomock.Any(), gomock.Any(), gomock.Any()).Return(math.NewInt(0), nil).Times(1), } if expectJailing { + // slash + calls = append(calls, mocks.MockStakingKeeper.EXPECT().SlashWithInfractionReason(ctx, expectedProviderValConsAddr.ToSdkConsAddr(), gomock.Any(), + gomock.Any(), gomock.Any(), gomock.Any()).Return(math.NewInt(0), nil).Times(1)) // jail calls = append(calls, mocks.MockStakingKeeper.EXPECT().Jail( gomock.Eq(ctx), diff --git a/x/ccv/provider/keeper/msg_server.go b/x/ccv/provider/keeper/msg_server.go index c82f901154..273d347c2a 100644 --- a/x/ccv/provider/keeper/msg_server.go +++ b/x/ccv/provider/keeper/msg_server.go @@ -634,10 +634,11 @@ func (k msgServer) UpdateConsumer(goCtx context.Context, msg *types.MsgUpdateCon return &resp, errorsmod.Wrapf(types.ErrInvalidConsumerInfractionParameters, "cannot set infraction parameters") } - } - if err = k.Keeper.UpdateQueuedInfractionParams(ctx, consumerId, newInfractionParams); err != nil { - return &resp, errorsmod.Wrapf(types.ErrInvalidConsumerInfractionParameters, - "cannot update consumer infraction time queue") + } else { + if err = k.Keeper.UpdateQueuedInfractionParams(ctx, consumerId, newInfractionParams); err != nil { + return &resp, errorsmod.Wrapf(types.ErrInvalidConsumerInfractionParameters, + "cannot update consumer infraction time queue") + } } } diff --git a/x/ccv/provider/keeper/relay.go b/x/ccv/provider/keeper/relay.go index 790bf8b10b..33a7e05e4c 100644 --- a/x/ccv/provider/keeper/relay.go +++ b/x/ccv/provider/keeper/relay.go @@ -484,16 +484,16 @@ func (k Keeper) HandleSlashPacket(ctx sdk.Context, consumerId string, data ccv.S return } - // slash validator - _, err = k.stakingKeeper.SlashWithInfractionReason(ctx, providerConsAddr.ToSdkConsAddr(), int64(infractionHeight), - data.Validator.Power, infractionParams.Downtime.SlashFraction, stakingtypes.Infraction_INFRACTION_DOWNTIME) - if err != nil { - k.Logger(ctx).Error("failed to slash vaidator", providerConsAddr.ToSdkConsAddr().String(), "err", err.Error()) - return - } - - // jail validator if !validator.IsJailed() { + // slash validator + _, err = k.stakingKeeper.SlashWithInfractionReason(ctx, providerConsAddr.ToSdkConsAddr(), int64(infractionHeight), + data.Validator.Power, infractionParams.Downtime.SlashFraction, stakingtypes.Infraction_INFRACTION_DOWNTIME) + if err != nil { + k.Logger(ctx).Error("failed to slash vaidator", providerConsAddr.ToSdkConsAddr().String(), "err", err.Error()) + return + } + + // jail validator err := k.stakingKeeper.Jail(ctx, providerConsAddr.ToSdkConsAddr()) if err != nil { k.Logger(ctx).Error("failed to jail vaidator", providerConsAddr.ToSdkConsAddr().String(), "err", err.Error()) diff --git a/x/ccv/provider/types/provider.pb.go b/x/ccv/provider/types/provider.pb.go index eb9b7a61ec..b45af3359f 100644 --- a/x/ccv/provider/types/provider.pb.go +++ b/x/ccv/provider/types/provider.pb.go @@ -1942,7 +1942,7 @@ func (m *InfractionParameters) GetDowntime() *SlashJailParameters { type SlashJailParameters struct { SlashFraction cosmossdk_io_math.LegacyDec `protobuf:"bytes,1,opt,name=slash_fraction,json=slashFraction,proto3,customtype=cosmossdk.io/math.LegacyDec" json:"slash_fraction"` // for permanent jailing use 9223372036854775807 which is the largest value a time.Duration can hold (approximately 292 years) - JailDuration time.Duration `protobuf:"bytes,8,opt,name=jail_duration,json=jailDuration,proto3,stdduration" json:"jail_duration"` + JailDuration time.Duration `protobuf:"bytes,2,opt,name=jail_duration,json=jailDuration,proto3,stdduration" json:"jail_duration"` } func (m *SlashJailParameters) Reset() { *m = SlashJailParameters{} } @@ -2020,7 +2020,7 @@ func init() { } var fileDescriptor_f22ec409a72b7b72 = []byte{ - // 2413 bytes of a gzipped FileDescriptorProto + // 2414 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x19, 0x4b, 0x6c, 0x1b, 0xc7, 0x55, 0x2b, 0x52, 0x12, 0x39, 0xd4, 0x87, 0x1a, 0x29, 0x32, 0x25, 0x2b, 0x24, 0xbd, 0x69, 0x02, 0x35, 0xae, 0xc9, 0x48, 0x01, 0x02, 0xc3, 0x6d, 0x10, 0x50, 0x24, 0x63, 0xd1, 0x1f, 0x99, 0x5d, @@ -2159,19 +2159,19 @@ var fileDescriptor_f22ec409a72b7b72 = []byte{ 0x60, 0xd1, 0x9f, 0xa5, 0xa2, 0x90, 0x93, 0xf5, 0x70, 0xf7, 0x3d, 0x11, 0xbd, 0x7f, 0x7f, 0x5c, 0xb8, 0xec, 0x97, 0x0a, 0x66, 0x1e, 0x95, 0x08, 0x2d, 0xdb, 0x88, 0xf7, 0x4a, 0x77, 0x70, 0x17, 0x19, 0xc3, 0x1a, 0x36, 0xfe, 0xfa, 0xc5, 0x35, 0x10, 0x14, 0xa0, 0x1a, 0x36, 0xfc, 0xd2, 0xb1, - 0x20, 0xa5, 0x45, 0x91, 0xb9, 0x07, 0x16, 0x3e, 0x46, 0xc4, 0xd2, 0xc3, 0x1f, 0x39, 0x9e, 0xe7, - 0x41, 0x7b, 0x5e, 0x70, 0x86, 0xf0, 0xb7, 0xff, 0xa8, 0x80, 0x85, 0xa8, 0x6f, 0xeb, 0x21, 0x86, - 0x61, 0x1e, 0x6c, 0x54, 0xef, 0xed, 0xb7, 0xee, 0xdf, 0xad, 0x6b, 0x7a, 0x73, 0xaf, 0xd2, 0xaa, - 0xeb, 0xf7, 0xf7, 0x5b, 0xcd, 0x7a, 0xb5, 0xf1, 0x61, 0xa3, 0x5e, 0xcb, 0x4e, 0xc1, 0xd7, 0xc1, - 0xfa, 0x09, 0xbc, 0x56, 0xbf, 0xd9, 0x68, 0xb5, 0xeb, 0x5a, 0xbd, 0x96, 0x55, 0xce, 0x60, 0x6f, - 0xec, 0x37, 0xda, 0x8d, 0xca, 0x9d, 0xc6, 0x83, 0x7a, 0x2d, 0x3b, 0x0d, 0x2f, 0x83, 0x4b, 0x27, - 0xf0, 0x77, 0x2a, 0xf7, 0xf7, 0xab, 0x7b, 0xf5, 0x5a, 0x36, 0x01, 0x37, 0xc0, 0xda, 0x09, 0x64, - 0xab, 0x7d, 0xaf, 0xd9, 0xac, 0xd7, 0xb2, 0xc9, 0x33, 0x70, 0xb5, 0xfa, 0x9d, 0x7a, 0xbb, 0x5e, - 0xcb, 0xce, 0x6c, 0x24, 0x3f, 0xf9, 0x55, 0x7e, 0x6a, 0xf7, 0xa3, 0xaf, 0x9e, 0xe4, 0x95, 0xaf, - 0x9f, 0xe4, 0x95, 0x7f, 0x3c, 0xc9, 0x2b, 0x9f, 0x3e, 0xcd, 0x4f, 0x7d, 0xfd, 0x34, 0x3f, 0xf5, - 0xb7, 0xa7, 0xf9, 0xa9, 0x07, 0xef, 0x9f, 0xae, 0xd5, 0xa3, 0xbb, 0xbf, 0x16, 0xfd, 0x38, 0x33, - 0x78, 0xaf, 0xfc, 0x68, 0xfc, 0x97, 0x31, 0x59, 0xc6, 0x3b, 0xb3, 0xf2, 0x3c, 0xdf, 0xfd, 0x5f, - 0x00, 0x00, 0x00, 0xff, 0xff, 0x35, 0xc8, 0xcf, 0x24, 0x4a, 0x1b, 0x00, 0x00, + 0x20, 0xa5, 0x45, 0x91, 0xb9, 0x07, 0x16, 0x3e, 0x46, 0xc4, 0xd2, 0xc3, 0x1f, 0x39, 0x02, 0x8b, + 0x26, 0x4a, 0x1b, 0xf3, 0x82, 0x33, 0x84, 0xbf, 0xfd, 0x47, 0x05, 0x2c, 0x44, 0x7d, 0x5b, 0x0f, + 0x31, 0x0c, 0xf3, 0x60, 0xa3, 0x7a, 0x6f, 0xbf, 0x75, 0xff, 0x6e, 0x5d, 0xd3, 0x9b, 0x7b, 0x95, + 0x56, 0x5d, 0xbf, 0xbf, 0xdf, 0x6a, 0xd6, 0xab, 0x8d, 0x0f, 0x1b, 0xf5, 0x5a, 0x76, 0x0a, 0xbe, + 0x0e, 0xd6, 0x4f, 0xe0, 0xb5, 0xfa, 0xcd, 0x46, 0xab, 0x5d, 0xd7, 0xea, 0xb5, 0xac, 0x72, 0x06, + 0x7b, 0x63, 0xbf, 0xd1, 0x6e, 0x54, 0xee, 0x34, 0x1e, 0xd4, 0x6b, 0xd9, 0x69, 0x78, 0x19, 0x5c, + 0x3a, 0x81, 0xbf, 0x53, 0xb9, 0xbf, 0x5f, 0xdd, 0xab, 0xd7, 0xb2, 0x09, 0xb8, 0x01, 0xd6, 0x4e, + 0x20, 0x5b, 0xed, 0x7b, 0xcd, 0x66, 0xbd, 0x96, 0x4d, 0x9e, 0x81, 0xab, 0xd5, 0xef, 0xd4, 0xdb, + 0xf5, 0x5a, 0x76, 0x66, 0x23, 0xf9, 0xc9, 0xaf, 0xf2, 0x53, 0xbb, 0x1f, 0x7d, 0xf5, 0x24, 0xaf, + 0x7c, 0xfd, 0x24, 0xaf, 0xfc, 0xe3, 0x49, 0x5e, 0xf9, 0xf4, 0x69, 0x7e, 0xea, 0xeb, 0xa7, 0xf9, + 0xa9, 0xbf, 0x3d, 0xcd, 0x4f, 0x3d, 0x78, 0xff, 0x74, 0xad, 0x1e, 0xdd, 0xfd, 0xb5, 0xe8, 0xc7, + 0x99, 0xc1, 0x7b, 0xe5, 0x47, 0xe3, 0xbf, 0x8c, 0xc9, 0x32, 0xde, 0x99, 0x95, 0xe7, 0xf9, 0xee, + 0xff, 0x02, 0x00, 0x00, 0xff, 0xff, 0xf1, 0x1b, 0x2e, 0x6d, 0x4a, 0x1b, 0x00, 0x00, } func (m *ConsumerAdditionProposal) Marshal() (dAtA []byte, err error) { @@ -3604,7 +3604,7 @@ func (m *SlashJailParameters) MarshalToSizedBuffer(dAtA []byte) (int, error) { i -= n24 i = encodeVarintProvider(dAtA, i, uint64(n24)) i-- - dAtA[i] = 0x42 + dAtA[i] = 0x12 { size := m.SlashFraction.Size() i -= size @@ -8682,7 +8682,7 @@ func (m *SlashJailParameters) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex - case 8: + case 2: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field JailDuration", wireType) } From 2b0eb1576c510161da3564374344c56e6af9d467 Mon Sep 17 00:00:00 2001 From: stana-ethernal Date: Thu, 28 Nov 2024 10:34:43 +0100 Subject: [PATCH 11/14] updrade.md update --- UPGRADING.md | 47 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 45 insertions(+), 2 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index d487f8e26f..3ab564b48f 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -1,7 +1,43 @@ -# Upgrading Replicated Security +# Upgrading Interchain Security ## Unreleased +### Provider + +```golang +func SetConsumerInfractionParams(ctx sdk.Context, pk providerkeeper.Keeper) error { + infractionParameters := DefaultInfractionParams() + + activeConsumerIds := pk.GetAllActiveConsumerIds(ctx) + for _, consumerId := range activeConsumerIds { + if err := pk.SetInfractionParameters(ctx, consumerId, infractionParameters); err != nil { + return err + } + } + + return nil +} + +func DefaultInfractionParams() providertypes.InfractionParameters { + return providertypes.InfractionParameters{ + DoubleSign: &providertypes.SlashJailParameters{ + JailDuration: time.Duration(1<<63 - 1), // the largest value a time.Duration can hold 9223372036854775807 (approximately 292 years) + SlashFraction: math.LegacyNewDecWithPrec(5, 2), // 0.05 + }, + Downtime: &providertypes.SlashJailParameters{ + JailDuration: 600 * time.Second, + SlashFraction: math.LegacyNewDec(0), // no slashing for downtime on the consumer + }, + } +} +``` + +## v6.3.x + +Upgrading from `v6.2.0` will not require state migration. To upgrade from lower versions, please check the sections below. + +## v6.2.x + ### Consumer Upgrading a consumer from v4.4.x to v4.5.x and from v5.x or v6.1.x to v6.2.x requires state migrations. The following migrators should be added to the upgrade handler of the consumer chain: @@ -22,6 +58,13 @@ func InitializeConsumerId(ctx sdk.Context, consumerKeeper consumerkeeper.Keeper) } ``` +## [v6.1.x](https://github.com/cosmos/interchain-security/releases/tag/v6.1.0) + +Upgrading from `v6.0.0` will not require state migration. + + +## [v6.0.x](https://github.com/cosmos/interchain-security/releases/tag/v6.0.0) + ### Provider Upgrading a provider from v5.1.x requires state migrations. The following migrators should be added to the upgrade handler of the provider chain: @@ -378,4 +421,4 @@ Upgrading a provider from `v1.1.0-multiden` to `v2.0.0` will require state migra ### Consumer -Upgrading a consumer from `v1.2.0-multiden` to `v2.0.0` will NOT require state migrations. +Upgrading a consumer from `v1.2.0-multiden` to `v2.0.0` will NOT require state migrations. \ No newline at end of file From a068fcb0a434234de16cdd8eb69849a14690290a Mon Sep 17 00:00:00 2001 From: stana-ethernal Date: Mon, 2 Dec 2024 09:43:10 +0100 Subject: [PATCH 12/14] cr fix --- UPGRADING.md | 3 +++ x/ccv/provider/client/cli/tx.go | 36 ++++++++++++++++----------------- 2 files changed, 21 insertions(+), 18 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index 3ab564b48f..748995c23b 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -4,7 +4,10 @@ ### Provider +Upgrading a provider from v6.2.0 requires state migrations. The following migrators should be added to the upgrade handler of the provider chain: + ```golang +// Initializes infraction parameters for each active consumer. During slashing and jailing of validators for misbehavior on the consumer chain, the parameters defined for that specific consumer will be used. Initially, default values are set, which can later be customized for each consumer as needed. func SetConsumerInfractionParams(ctx sdk.Context, pk providerkeeper.Keeper) error { infractionParameters := DefaultInfractionParams() diff --git a/x/ccv/provider/client/cli/tx.go b/x/ccv/provider/client/cli/tx.go index 754b9ebc12..2708af5811 100644 --- a/x/ccv/provider/client/cli/tx.go +++ b/x/ccv/provider/client/cli/tx.go @@ -257,15 +257,15 @@ where create_consumer.json has the following structure: "allow_inactive_vals": false, "prioritylist": ["cosmosvalcons..."] }, - "infraction_parameters": { - "double_sign": { - "slash_fraction": "0.05", - "jail_duration": "9223372036854775807" - }, - "downtime": { - "slash_fraction": "0.0001", - "jail_duration": "600000000000" - } + "infraction_parameters":{ + "double_sign":{ + "slash_fraction":"0.05", + "jail_duration":"9223372036854775807" + }, + "downtime":{ + "slash_fraction":"0.0001", + "jail_duration":"600000000000" + } }, "allowlisted_reward_denoms": { "denoms": ["ibc/...", "ibc/..."] @@ -366,16 +366,16 @@ where update_consumer.json has the following structure: "allow_inactive_vals": false, "prioritylist": ["cosmosvalcons..."] }, - "infraction_parameters": { - "double_sign": { - "slash_fraction": "0.05", - "jail_duration": "9223372036854775807" - }, - "downtime": { - "slash_fraction": "0.0001", - "jail_duration": "600000000000" - } + "infraction_parameters":{ + "double_sign":{ + "slash_fraction":"0.05", + "jail_duration":"9223372036854775807" }, + "downtime":{ + "slash_fraction":"0.0001", + "jail_duration":"600000000000" + } + }, "allowlisted_reward_denoms": { "denoms": ["ibc/...", "ibc/..."] } From b66600ca189fb481705455bd4e072ba9f0ad4c3a Mon Sep 17 00:00:00 2001 From: github-actions Date: Tue, 3 Dec 2024 09:25:49 +0000 Subject: [PATCH 13/14] Update testing documentation --- scripts/test_doc/test_documentation.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/test_doc/test_documentation.md b/scripts/test_doc/test_documentation.md index 016e9cefe6..d8cf18e62e 100644 --- a/scripts/test_doc/test_documentation.md +++ b/scripts/test_doc/test_documentation.md @@ -65,8 +65,8 @@ | Function | Short Description | |----------|-------------------| [TestHandleConsumerMisbehaviour](../../tests/integration/misbehaviour.go#L25) | TestHandleConsumerMisbehaviour tests the handling of consumer misbehavior.
Details* Set up a CCV channel and send an empty VSC packet to ensure that the consumer client revision height is greater than 0.
* Construct a Misbehaviour object with two conflicting headers and process the equivocation evidence.
* Verify that the provider chain correctly processes this misbehavior.
* Ensure that all involved validators are jailed, tombstoned, and slashed according to the expected outcomes.
* Assert that their tokens are adjusted based on the slashing fraction.
| - [TestGetByzantineValidators](../../tests/integration/misbehaviour.go#L101) | TestGetByzantineValidators checks the GetByzantineValidators function on various instances of misbehaviour.
Details* Set up a provider and consumer chain.
* Create a header with a subset of the validators on the consumer chain, then create a second header (in a variety of different ways),
and check which validators are considered Byzantine by calling the GetByzantineValidators function.
* The test scenarios are:
- when one of the headers is empty, the function should return an error
- when one of the headers has a corrupted validator set (e.g. by a validator having a different public key), the function should return an error
- when the signatures in one of the headers are corrupted, the function should return an error
- when the attack is an amnesia attack (i.e. the headers have different block IDs), no validator is considered byzantine
- for non-amnesia misbehaviour, all validators that signed both headers are considered byzantine
| - [TestCheckMisbehaviour](../../tests/integration/misbehaviour.go#L399) | TestCheckMisbehaviour tests that the CheckMisbehaviour function correctly checks for misbehaviour.
Details* Set up a provider and consumer chain.
* Create a valid client header and then create a misbehaviour by creating a second header in a variety of different ways.
* Check that the CheckMisbehaviour function correctly checks for misbehaviour by verifying that
it returns an error when the misbehaviour is invalid and no error when the misbehaviour is valid.
* The test scenarios are:
- both headers are identical (returns an error)
- the misbehaviour is not for the consumer chain (returns an error)
- passing an invalid client id (returns an error)
- passing a misbehaviour with different header height (returns an error)
- passing a misbehaviour older than the min equivocation evidence height (returns an error)
- one header of the misbehaviour has insufficient voting power (returns an error)
- passing a valid misbehaviour (no error)

* Test does not test actually submitting the misbehaviour to the chain or freezing the client.
| + [TestGetByzantineValidators](../../tests/integration/misbehaviour.go#L102) | TestGetByzantineValidators checks the GetByzantineValidators function on various instances of misbehaviour.
Details* Set up a provider and consumer chain.
* Create a header with a subset of the validators on the consumer chain, then create a second header (in a variety of different ways),
and check which validators are considered Byzantine by calling the GetByzantineValidators function.
* The test scenarios are:
- when one of the headers is empty, the function should return an error
- when one of the headers has a corrupted validator set (e.g. by a validator having a different public key), the function should return an error
- when the signatures in one of the headers are corrupted, the function should return an error
- when the attack is an amnesia attack (i.e. the headers have different block IDs), no validator is considered byzantine
- for non-amnesia misbehaviour, all validators that signed both headers are considered byzantine
| + [TestCheckMisbehaviour](../../tests/integration/misbehaviour.go#L400) | TestCheckMisbehaviour tests that the CheckMisbehaviour function correctly checks for misbehaviour.
Details* Set up a provider and consumer chain.
* Create a valid client header and then create a misbehaviour by creating a second header in a variety of different ways.
* Check that the CheckMisbehaviour function correctly checks for misbehaviour by verifying that
it returns an error when the misbehaviour is invalid and no error when the misbehaviour is valid.
* The test scenarios are:
- both headers are identical (returns an error)
- the misbehaviour is not for the consumer chain (returns an error)
- passing an invalid client id (returns an error)
- passing a misbehaviour with different header height (returns an error)
- passing a misbehaviour older than the min equivocation evidence height (returns an error)
- one header of the misbehaviour has insufficient voting power (returns an error)
- passing a valid misbehaviour (no error)

* Test does not test actually submitting the misbehaviour to the chain or freezing the client.
| # [normal_operations.go](../../tests/integration/normal_operations.go) From 6d4f5c0b3bc3aa21ef51895de57d6e17c5972362 Mon Sep 17 00:00:00 2001 From: mpoke Date: Tue, 3 Dec 2024 11:35:26 +0100 Subject: [PATCH 14/14] update changelog entries --- .../features/2403-customizable-slashing-jailing.md | 6 +++++- .../state-breaking/2403-customizable-slashing-jailing.md | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/.changelog/unreleased/features/2403-customizable-slashing-jailing.md b/.changelog/unreleased/features/2403-customizable-slashing-jailing.md index 733860a5c7..9357ea1a6d 100644 --- a/.changelog/unreleased/features/2403-customizable-slashing-jailing.md +++ b/.changelog/unreleased/features/2403-customizable-slashing-jailing.md @@ -1 +1,5 @@ -- `[x/provider]` Enable the customization of the slashing and jailing conditions for infractions committed by validators on consumer chains (as per [ADR 020](https://cosmos.github.io/interchain-security/adrs/adr-020-cutomizable_slashing_and_jailing)). Every consumer chain can decide the punishment for every type of infraction. \ No newline at end of file +- `[x/provider]` Enable the customization of the slashing and jailing conditions + for infractions committed by validators on consumer chains (as per + [ADR 020](https://cosmos.github.io/interchain-security/adrs/adr-020-cutomizable_slashing_and_jailing)). + Every consumer chain can decide the punishment for every type of infraction. + ([\#2403](https://github.com/cosmos/interchain-security/pull/2403)) \ No newline at end of file diff --git a/.changelog/unreleased/state-breaking/2403-customizable-slashing-jailing.md b/.changelog/unreleased/state-breaking/2403-customizable-slashing-jailing.md index 733860a5c7..9357ea1a6d 100644 --- a/.changelog/unreleased/state-breaking/2403-customizable-slashing-jailing.md +++ b/.changelog/unreleased/state-breaking/2403-customizable-slashing-jailing.md @@ -1 +1,5 @@ -- `[x/provider]` Enable the customization of the slashing and jailing conditions for infractions committed by validators on consumer chains (as per [ADR 020](https://cosmos.github.io/interchain-security/adrs/adr-020-cutomizable_slashing_and_jailing)). Every consumer chain can decide the punishment for every type of infraction. \ No newline at end of file +- `[x/provider]` Enable the customization of the slashing and jailing conditions + for infractions committed by validators on consumer chains (as per + [ADR 020](https://cosmos.github.io/interchain-security/adrs/adr-020-cutomizable_slashing_and_jailing)). + Every consumer chain can decide the punishment for every type of infraction. + ([\#2403](https://github.com/cosmos/interchain-security/pull/2403)) \ No newline at end of file