From 01f9698b4450f623922220c5b1e06668d63e74e8 Mon Sep 17 00:00:00 2001 From: Stana Miric Date: Tue, 3 Dec 2024 12:25:53 +0100 Subject: [PATCH] feat!: Customizable Slashing and Jailing (#2403) * Customizable Slashing and Jailing * additional tests * relay test fixes * integration tests fix * migrations * slash with right params * comment fix * docs * Revert "migrations" This reverts commit f1e7c6a2283d8bb05039f24aec7a646c5bd646e1. * cr fix * updrade.md update * cr fix * Update testing documentation * update changelog entries --------- Co-authored-by: github-actions Co-authored-by: mpoke --- .../2403-customizable-slashing-jailing.md | 5 + .../2403-customizable-slashing-jailing.md | 5 + UPGRADING.md | 50 +- docs/docs/build/modules/02-provider.md | 34 +- docs/docs/features/slashing.md | 10 +- .../ccv/provider/v1/provider.proto | 19 + .../ccv/provider/v1/query.proto | 5 +- .../ccv/provider/v1/tx.proto | 6 + scripts/test_doc/test_documentation.md | 4 +- tests/integration/double_vote.go | 7 +- tests/integration/misbehaviour.go | 3 +- testutil/ibc_testing/generic_setup.go | 4 + testutil/keeper/expectations.go | 5 +- testutil/keeper/unit_test_helpers.go | 14 + 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 | 31 +- x/ccv/provider/keeper/grpc_query_test.go | 30 +- .../provider/keeper/infraction_parameters.go | 258 ++++++ .../keeper/infraction_parameters_test.go | 216 +++++ x/ccv/provider/keeper/msg_server.go | 56 ++ x/ccv/provider/keeper/msg_server_test.go | 62 +- x/ccv/provider/keeper/relay.go | 24 +- x/ccv/provider/keeper/relay_test.go | 31 +- 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 | 481 ++++++----- x/ccv/provider/types/tx.pb.go | 386 ++++++--- x/ccv/types/shared_params.go | 10 + 37 files changed, 2258 insertions(+), 532 deletions(-) create mode 100644 .changelog/unreleased/features/2403-customizable-slashing-jailing.md create mode 100644 .changelog/unreleased/state-breaking/2403-customizable-slashing-jailing.md create mode 100644 x/ccv/provider/keeper/infraction_parameters.go create mode 100644 x/ccv/provider/keeper/infraction_parameters_test.go 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..9357ea1a6d --- /dev/null +++ b/.changelog/unreleased/features/2403-customizable-slashing-jailing.md @@ -0,0 +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. + ([\#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 new file mode 100644 index 0000000000..9357ea1a6d --- /dev/null +++ b/.changelog/unreleased/state-breaking/2403-customizable-slashing-jailing.md @@ -0,0 +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. + ([\#2403](https://github.com/cosmos/interchain-security/pull/2403)) \ No newline at end of file diff --git a/UPGRADING.md b/UPGRADING.md index d487f8e26f..748995c23b 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -1,7 +1,46 @@ -# Upgrading Replicated Security +# Upgrading Interchain Security ## Unreleased +### 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() + + 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 +61,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 +424,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 diff --git a/docs/docs/build/modules/02-provider.md b/docs/docs/build/modules/02-provider.md index 2a211bec42..af2ad60065 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; } ``` @@ -528,7 +531,7 @@ The others fields are optional. Not providing one of them will leave the existin Providing one of `metadata`, `initialization_parameters`, `power_shaping_parameters`, 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). @@ -2874,6 +2881,16 @@ grpcurl -plaintext -d '{"consumer_id": "0"}' localhost:9090 interchain_security. "minStake": "1000", "allowInactiveVals": true }, + "infraction_parameters":{ + "double_sign":{ + "slash_fraction":"0.050000000000000000", + "jail_duration":"9223372036.854775807s" + }, + "downtime":{ + "slash_fraction":"0.000000000000000000", + "jail_duration":"600s" + } + }, "clientId": "07-tendermint-28" } ``` @@ -3573,6 +3590,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 ac69445b7e..6bb4f25299 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. +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. @@ -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 diff --git a/proto/interchain_security/ccv/provider/v1/provider.proto b/proto/interchain_security/ccv/provider/v1/provider.proto index 138e5fa23b..a99778ba32 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 = 2 + [ (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 0e312096ab..79398fa2df 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,9 +399,10 @@ message QueryConsumerChainResponse { ConsumerMetadata metadata = 5 [ (gogoproto.nullable) = false ]; ConsumerInitializationParameters init_params = 6; PowerShapingParameters power_shaping_params = 7; + InfractionParameters infraction_parameters = 8; // corresponds to the id of the client that is created during launch - string client_id = 8; + string client_id = 9; } 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/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) 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/expectations.go b/testutil/keeper/expectations.go index 12e3c338e1..3ae55eebf1 100644 --- a/testutil/keeper/expectations.go +++ b/testutil/keeper/expectations.go @@ -105,13 +105,16 @@ func GetMocksForHandleSlashPacket(ctx sdk.Context, mocks MockedKeepers, } 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), 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/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, diff --git a/x/ccv/provider/client/cli/tx.go b/x/ccv/provider/client/cli/tx.go index 1894ad7b36..2708af5811 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..439dc80bce 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); 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) 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) 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, 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 d85b963127..1e740a4aae 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) } // 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) } 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 42c8efa8ae..4ea4503fce 100644 --- a/x/ccv/provider/keeper/consumer_lifecycle.go +++ b/x/ccv/provider/keeper/consumer_lifecycle.go @@ -526,6 +526,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 9ee25bcaf7..03ae214a90 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,23 +624,30 @@ 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) + } + // The client id might not exist in case the consumer chain has not yet launched or in case the chain has been deleted. // That's why we do not check if the client id is found. clientId, _ := k.GetConsumerClientId(ctx, consumerId) return &types.QueryConsumerChainResponse{ - ChainId: chainId, - ConsumerId: consumerId, - OwnerAddress: ownerAddress, - Phase: phase.String(), - Metadata: metadata, - InitParams: &initParams, - PowerShapingParams: &powerParams, - ClientId: clientId, + ChainId: chainId, + ConsumerId: consumerId, + OwnerAddress: ownerAddress, + Phase: phase.String(), + Metadata: metadata, + InitParams: &initParams, + PowerShapingParams: &powerParams, + InfractionParameters: &infractionParams, + ClientId: clientId, }, 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 b6fdfab243..b5a7ced0ba 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(), }) } @@ -588,17 +593,20 @@ 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) providerKeeper.SetConsumerClientId(ctx, consumerId, clientId) 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{}, - ClientId: clientId, + 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(), + ClientId: clientId, } // expect no error when neither the consumer init and power shaping params are set @@ -646,8 +654,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) @@ -678,6 +688,7 @@ func TestQueryConsumerChains(t *testing.T) { ChainId: chainID, Metadata: metadata, InitializationParameters: &initializationParameters, + InfractionParameters: getTestInfractionParameters(), } resp, err := msgServer.CreateConsumer(ctx, &msg) require.NoError(t, err) @@ -696,6 +707,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..8abf21a5b6 --- /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 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. +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/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.go b/x/ccv/provider/keeper/msg_server.go index d55a8a1201..273d347c2a 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,40 @@ 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") + } + } else { + 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/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) diff --git a/x/ccv/provider/keeper/relay.go b/x/ccv/provider/keeper/relay.go index f0fcb0f75a..33a7e05e4c 100644 --- a/x/ccv/provider/keeper/relay.go +++ b/x/ccv/provider/keeper/relay.go @@ -478,20 +478,30 @@ 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()) - // jail validator + infractionParams, err := k.GetInfractionParameters(ctx, consumerId) + if err != nil { + k.Logger(ctx).Error("failed to get infraction parameters", "err", err.Error()) + return + } + if !validator.IsJailed() { - err := k.stakingKeeper.Jail(ctx, providerConsAddr.ToSdkConsAddr()) + // 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 jail vaidator", providerConsAddr.ToSdkConsAddr().String(), "err", err.Error()) + k.Logger(ctx).Error("failed to slash vaidator", providerConsAddr.ToSdkConsAddr().String(), "err", err.Error()) return } - k.Logger(ctx).Info("HandleSlashPacket - validator jailed", "provider cons addr", providerConsAddr.String()) - jailDuration, err := k.slashingKeeper.DowntimeJailDuration(ctx) + + // jail validator + err := k.stakingKeeper.Jail(ctx, providerConsAddr.ToSdkConsAddr()) if err != nil { - k.Logger(ctx).Error("failed to get jail duration", "err", err.Error()) + k.Logger(ctx).Error("failed to jail vaidator", providerConsAddr.ToSdkConsAddr().String(), "err", err.Error()) return } - jailEndTime := ctx.BlockTime().Add(jailDuration) + k.Logger(ctx).Info("HandleSlashPacket - validator jailed", "provider cons addr", providerConsAddr.String()) + + 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/keeper/relay_test.go b/x/ccv/provider/keeper/relay_test.go index e63edea760..5f31bc3a43 100644 --- a/x/ccv/provider/keeper/relay_test.go +++ b/x/ccv/provider/keeper/relay_test.go @@ -186,6 +186,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 +206,13 @@ 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() 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 +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}, true)..., + ctx, mocks, providerAddr, stakingtypes.Validator{Jailed: false, OperatorAddress: valAddr}, true)..., ) gomock.InOrder(calls...) @@ -343,6 +350,8 @@ func TestHandleSlashPacket(t *testing.T) { providerConsAddr := cryptotestutil.NewCryptoIdentityFromIntSeed(7842334).ProviderConsAddress() consumerConsAddr := cryptotestutil.NewCryptoIdentityFromIntSeed(784987634).ConsumerConsAddress() + valOperAddr := cryptotestutil.NewCryptoIdentityFromIntSeed(7842334).SDKValOpAddressString() + testCases := []struct { name string packetData ccv.SlashPacketData @@ -431,9 +440,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 + ) }, 1, consumerConsAddr, @@ -449,9 +459,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. + ) }, 1, consumerConsAddr, @@ -477,6 +488,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) 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..b45af3359f 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,2,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, + // 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, + 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, 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) { @@ -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] = 0x12 + { + 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 2: + 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 41c9731adb..447b74d194 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,15 +1746,16 @@ 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"` // corresponds to the id of the client that is created during launch - ClientId string `protobuf:"bytes,8,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty"` + ClientId string `protobuf:"bytes,9,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty"` } func (m *QueryConsumerChainResponse) Reset() { *m = QueryConsumerChainResponse{} } @@ -1830,6 +1840,13 @@ func (m *QueryConsumerChainResponse) GetPowerShapingParams() *PowerShapingParame return nil } +func (m *QueryConsumerChainResponse) GetInfractionParameters() *InfractionParameters { + if m != nil { + return m.InfractionParameters + } + return nil +} + func (m *QueryConsumerChainResponse) GetClientId() string { if m != nil { return m.ClientId @@ -1968,166 +1985,168 @@ func init() { } var fileDescriptor_422512d7b7586cd7 = []byte{ - // 2535 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, 0x6f, 0xc8, 0xad, 0x69, 0x7a, 0x29, 0x52, 0xd4, 0x0d, 0xec, 0x16, 0xe8, 0xa5, 0x87, 0xa6, - 0x45, 0xcf, 0xc5, 0x0c, 0x87, 0xdc, 0x25, 0xcd, 0xd5, 0x92, 0x5a, 0xdd, 0x96, 0x33, 0xef, 0xfd, - 0xe6, 0xbd, 0x37, 0xef, 0xbd, 0x79, 0xef, 0x49, 0xa0, 0x4a, 0x6c, 0x86, 0x3d, 0x63, 0x07, 0x11, - 0x5b, 0xa7, 0xd8, 0xd8, 0xf3, 0x08, 0x6b, 0x55, 0x0d, 0xa3, 0x59, 0x75, 0x3d, 0xa7, 0x49, 0x4c, - 0xec, 0x55, 0x9b, 0x0b, 0xd5, 0xfb, 0x7b, 0xd8, 0x6b, 0x55, 0x5c, 0xcf, 0x61, 0x0e, 0x3c, 0x9b, - 0xc0, 0x50, 0x31, 0x8c, 0x66, 0x25, 0x60, 0xa8, 0x34, 0x17, 0x4a, 0xa7, 0xeb, 0x8e, 0x53, 0xb7, - 0x70, 0x15, 0xb9, 0xa4, 0x8a, 0x6c, 0xdb, 0x61, 0x88, 0x11, 0xc7, 0xa6, 0x3e, 0x44, 0x69, 0xa2, - 0xee, 0xd4, 0x1d, 0xf1, 0xb3, 0xca, 0x7f, 0xc9, 0xd5, 0xb2, 0xe4, 0x11, 0x5f, 0xdb, 0x7b, 0x1f, - 0x55, 0x19, 0x69, 0x60, 0xca, 0x50, 0xc3, 0x95, 0x04, 0x8b, 0x69, 0x44, 0x0d, 0xa5, 0xf0, 0x79, - 0xe6, 0xbb, 0xf1, 0x34, 0x17, 0xaa, 0x74, 0x07, 0x79, 0xd8, 0xd4, 0x0d, 0xc7, 0xa6, 0x7b, 0x8d, - 0x90, 0xe3, 0xdc, 0x3e, 0x1c, 0x0f, 0x88, 0x87, 0x25, 0xd9, 0x69, 0x86, 0x6d, 0x13, 0x7b, 0x0d, - 0x62, 0xb3, 0xaa, 0xe1, 0xb5, 0x5c, 0xe6, 0x54, 0x77, 0x71, 0x2b, 0xd0, 0xf0, 0x94, 0xe1, 0xd0, - 0x86, 0x43, 0x75, 0x5f, 0x49, 0xff, 0x43, 0x6e, 0xbd, 0xec, 0x7f, 0x55, 0x29, 0x43, 0xbb, 0xc4, - 0xae, 0x57, 0x9b, 0x0b, 0xdb, 0x98, 0xa1, 0x85, 0xe0, 0x5b, 0x52, 0xcd, 0x49, 0xaa, 0x6d, 0x44, - 0xb1, 0x6f, 0xfe, 0x90, 0xd0, 0x45, 0x75, 0x62, 0x0b, 0x7b, 0xfa, 0xb4, 0xea, 0x65, 0x30, 0xf5, - 0x1e, 0xa7, 0x58, 0x96, 0x8a, 0xac, 0x61, 0x1b, 0x53, 0x42, 0x35, 0x7c, 0x7f, 0x0f, 0x53, 0x06, - 0xcb, 0xa0, 0x10, 0xa8, 0xa8, 0x13, 0xb3, 0xa8, 0xcc, 0x28, 0xb3, 0xa3, 0x1a, 0x08, 0x96, 0xd6, - 0x4d, 0xf5, 0x11, 0x38, 0x9d, 0xcc, 0x4f, 0x5d, 0xc7, 0xa6, 0x18, 0x7e, 0x08, 0xc6, 0xea, 0xfe, - 0x92, 0x4e, 0x19, 0x62, 0x58, 0x40, 0x14, 0x16, 0xe7, 0x2b, 0xdd, 0x3c, 0xa1, 0xb9, 0x50, 0x89, - 0x61, 0x6d, 0x72, 0xbe, 0xda, 0xd0, 0x97, 0x4f, 0xca, 0x03, 0xda, 0xd1, 0x7a, 0xc7, 0x9a, 0xfa, - 0x1b, 0x05, 0x94, 0x22, 0xa7, 0x2f, 0x73, 0xbc, 0x50, 0xf8, 0xeb, 0x60, 0xd8, 0xdd, 0x41, 0xd4, - 0x3f, 0x73, 0x7c, 0x71, 0xb1, 0x92, 0xc2, 0xfb, 0xc2, 0xc3, 0x37, 0x38, 0xa7, 0xe6, 0x03, 0xc0, - 0x55, 0x00, 0xda, 0x96, 0x2b, 0xe6, 0x84, 0x0a, 0xdf, 0xab, 0xc8, 0xab, 0xe1, 0x66, 0xae, 0xf8, - 0x5e, 0x2e, 0xcd, 0x5c, 0xd9, 0x40, 0x75, 0x2c, 0xa5, 0xd0, 0x3a, 0x38, 0xd5, 0x5f, 0x2b, 0x31, - 0x73, 0x07, 0x02, 0x4b, 0x6b, 0xd5, 0xc0, 0x88, 0x10, 0x8f, 0x16, 0x95, 0x99, 0xc1, 0xd9, 0xc2, - 0xe2, 0x5c, 0x3a, 0x91, 0xf9, 0xb6, 0x26, 0x39, 0xe1, 0x5a, 0x82, 0xac, 0xdf, 0xef, 0x29, 0xab, - 0x2f, 0x40, 0x44, 0xd8, 0xcf, 0x86, 0xc1, 0xb0, 0x80, 0x86, 0xa7, 0x40, 0xde, 0x17, 0x21, 0x74, - 0x81, 0x23, 0xe2, 0x7b, 0xdd, 0x84, 0x53, 0x60, 0xd4, 0xb0, 0x08, 0xb6, 0x19, 0xdf, 0xcb, 0x89, - 0xbd, 0xbc, 0xbf, 0xb0, 0x6e, 0xc2, 0xe3, 0x60, 0x98, 0x39, 0xae, 0x7e, 0xab, 0x38, 0x38, 0xa3, - 0xcc, 0x8e, 0x69, 0x43, 0xcc, 0x71, 0x6f, 0xc1, 0x39, 0x00, 0x1b, 0xc4, 0xd6, 0x5d, 0xe7, 0x01, - 0xf7, 0x29, 0x5b, 0xf7, 0x29, 0x86, 0x66, 0x94, 0xd9, 0x41, 0x6d, 0xbc, 0x41, 0xec, 0x0d, 0xbe, - 0xb1, 0x6e, 0x6f, 0x71, 0xda, 0x79, 0x30, 0xd1, 0x44, 0x16, 0x31, 0x11, 0x73, 0x3c, 0x2a, 0x59, - 0x0c, 0xe4, 0x16, 0x87, 0x05, 0x1e, 0x6c, 0xef, 0x09, 0xa6, 0x65, 0xe4, 0xc2, 0x39, 0xf0, 0x62, - 0xb8, 0xaa, 0x53, 0xcc, 0x04, 0xf9, 0x88, 0x20, 0x3f, 0x16, 0x6e, 0x6c, 0x62, 0xc6, 0x69, 0x4f, - 0x83, 0x51, 0x64, 0x59, 0xce, 0x03, 0x8b, 0x50, 0x56, 0x3c, 0x32, 0x33, 0x38, 0x3b, 0xaa, 0xb5, - 0x17, 0x60, 0x09, 0xe4, 0x4d, 0x6c, 0xb7, 0xc4, 0x66, 0x5e, 0x6c, 0x86, 0xdf, 0x70, 0x22, 0xf0, - 0xac, 0x51, 0xa1, 0xb1, 0xf4, 0x92, 0x0f, 0x40, 0xbe, 0x81, 0x19, 0x32, 0x11, 0x43, 0x45, 0x20, - 0xec, 0xfe, 0x5a, 0x26, 0x97, 0xbb, 0x29, 0x99, 0xa5, 0xaf, 0x87, 0x60, 0xdc, 0xc8, 0xdc, 0x64, - 0x3c, 0xca, 0x71, 0xb1, 0x30, 0xa3, 0xcc, 0x0e, 0x69, 0xf9, 0x06, 0xb1, 0x37, 0xf9, 0x37, 0xac, - 0x80, 0xe3, 0x42, 0x68, 0x9d, 0xd8, 0xc8, 0x60, 0xa4, 0x89, 0xf5, 0x26, 0xb2, 0x68, 0xf1, 0xe8, - 0x8c, 0x32, 0x9b, 0xd7, 0x5e, 0x14, 0x5b, 0xeb, 0x72, 0xe7, 0x0e, 0xb2, 0x68, 0x3c, 0xa4, 0xc7, - 0xe2, 0x21, 0x0d, 0x1f, 0x82, 0x53, 0xa1, 0x15, 0xb0, 0xa9, 0x7b, 0xf8, 0x01, 0xf2, 0x4c, 0xdd, - 0xc4, 0xb6, 0xd3, 0xa0, 0xc5, 0x71, 0xa1, 0xd7, 0x3b, 0xa9, 0xf4, 0x5a, 0x6a, 0xa3, 0x68, 0x02, - 0xe4, 0x9a, 0xc0, 0xd0, 0x26, 0x51, 0xf2, 0x06, 0x54, 0xc1, 0x51, 0xd7, 0x23, 0x0e, 0x07, 0x13, - 0x66, 0x3f, 0x26, 0xcc, 0x1e, 0x59, 0x53, 0x7f, 0xa1, 0x80, 0x33, 0x22, 0x84, 0xee, 0x04, 0xb7, - 0x19, 0x98, 0x6f, 0xc9, 0x34, 0xbd, 0x20, 0xf4, 0x2f, 0x81, 0x17, 0x02, 0x49, 0x74, 0x64, 0x9a, - 0x1e, 0xa6, 0xd4, 0xf7, 0xdc, 0x1a, 0xfc, 0xee, 0x49, 0x79, 0xbc, 0x85, 0x1a, 0xd6, 0x45, 0x55, - 0x6e, 0xa8, 0xda, 0xb1, 0x80, 0x76, 0xc9, 0x5f, 0x89, 0xdb, 0x28, 0x17, 0xb7, 0xd1, 0xc5, 0xfc, - 0xc7, 0x9f, 0x97, 0x07, 0xfe, 0xf9, 0x79, 0x79, 0x40, 0xbd, 0x0d, 0xd4, 0xfd, 0xc4, 0x91, 0x81, - 0xfd, 0x0a, 0x78, 0x21, 0x04, 0x8c, 0xc8, 0xa3, 0x1d, 0x33, 0x3a, 0xe8, 0xb9, 0x34, 0xcf, 0x2b, - 0xb8, 0xd1, 0x21, 0x5d, 0x87, 0x82, 0xc9, 0x80, 0xc9, 0x0a, 0xc6, 0x0e, 0xe9, 0x4b, 0xc1, 0xa8, - 0x38, 0x6d, 0x05, 0x93, 0x0d, 0xfe, 0x9c, 0x71, 0xd5, 0x29, 0x70, 0x4a, 0x00, 0x6e, 0xed, 0x78, - 0x0e, 0x63, 0x16, 0x16, 0xb9, 0x5c, 0xea, 0xa5, 0xfe, 0x31, 0x48, 0xe9, 0xb1, 0x5d, 0x79, 0x4c, - 0x19, 0x14, 0xa8, 0x85, 0xe8, 0x8e, 0xde, 0xc0, 0x0c, 0x7b, 0xe2, 0x84, 0x41, 0x0d, 0x88, 0xa5, - 0x9b, 0x7c, 0x05, 0x2e, 0x82, 0x13, 0x1d, 0x04, 0xba, 0xf0, 0x34, 0x64, 0x1b, 0x58, 0xa8, 0x38, - 0xa8, 0x1d, 0x6f, 0x93, 0x2e, 0x05, 0x5b, 0xf0, 0x47, 0xa0, 0x68, 0xe3, 0x87, 0x4c, 0xf7, 0xb0, - 0x6b, 0x61, 0x9b, 0xd0, 0x1d, 0xdd, 0x40, 0xb6, 0xc9, 0x95, 0xc5, 0x22, 0x73, 0x15, 0x16, 0x4b, - 0x15, 0xbf, 0xbe, 0xa8, 0x04, 0xf5, 0x45, 0x65, 0x2b, 0xa8, 0x2f, 0x6a, 0x79, 0x1e, 0xac, 0x9f, - 0xfc, 0xad, 0xac, 0x68, 0x27, 0x39, 0x8a, 0x16, 0x80, 0x2c, 0x07, 0x18, 0xea, 0xab, 0x60, 0x4e, - 0xa8, 0xa4, 0xe1, 0x3a, 0xf7, 0x79, 0x0f, 0x9b, 0x81, 0x8f, 0x44, 0xc2, 0x42, 0x5a, 0x60, 0x05, - 0x9c, 0x4f, 0x45, 0x2d, 0x2d, 0x72, 0x12, 0x8c, 0xc8, 0xd0, 0x54, 0x44, 0xb4, 0xc8, 0x2f, 0xf5, - 0x5d, 0xf0, 0x8a, 0x80, 0x59, 0xb2, 0xac, 0x0d, 0x44, 0x3c, 0x7a, 0x07, 0x59, 0x1c, 0x87, 0x5f, - 0x42, 0xad, 0xd5, 0x46, 0x4c, 0xf9, 0xcc, 0xff, 0x4a, 0x91, 0x3a, 0xf4, 0x80, 0x93, 0x42, 0xdd, - 0x07, 0x2f, 0xba, 0x88, 0x78, 0x3c, 0x13, 0xf1, 0x12, 0x49, 0x78, 0x84, 0x7c, 0xd2, 0x56, 0x53, - 0xa5, 0x0e, 0x7e, 0x86, 0x7f, 0x04, 0x3f, 0x21, 0xf4, 0x38, 0xbb, 0x6d, 0x8b, 0x71, 0x37, 0x42, - 0xa2, 0xfe, 0x57, 0x01, 0x67, 0x7a, 0x72, 0xc1, 0xd5, 0xae, 0x79, 0x61, 0xea, 0xbb, 0x27, 0xe5, - 0x49, 0x3f, 0x6c, 0xe2, 0x14, 0x09, 0x09, 0x62, 0x35, 0x21, 0xfc, 0x72, 0x71, 0x9c, 0x38, 0x45, - 0x42, 0x1c, 0x5e, 0x01, 0x47, 0x43, 0xaa, 0x5d, 0xdc, 0x92, 0xee, 0x76, 0xba, 0xd2, 0x2e, 0x10, - 0x2b, 0x7e, 0x81, 0x58, 0xd9, 0xd8, 0xdb, 0xb6, 0x88, 0x71, 0x03, 0xb7, 0xb4, 0xf0, 0xaa, 0x6e, - 0xe0, 0x96, 0x3a, 0x01, 0xa0, 0xb8, 0x97, 0x0d, 0xe4, 0xa1, 0xb6, 0x0f, 0xfd, 0x18, 0x1c, 0x8f, - 0xac, 0xca, 0x6b, 0x59, 0x07, 0x23, 0xae, 0x58, 0x91, 0x55, 0xd8, 0xf9, 0x94, 0x77, 0xc1, 0x59, - 0xe4, 0xa3, 0x24, 0x01, 0xd4, 0x9b, 0xd2, 0x1f, 0x22, 0x85, 0xcc, 0x6d, 0x97, 0x61, 0x73, 0xdd, - 0x0e, 0x33, 0x45, 0xfa, 0x32, 0xf2, 0xbe, 0x74, 0xfa, 0x5e, 0x70, 0x61, 0x9d, 0xf4, 0x52, 0x67, - 0x5d, 0x10, 0xbb, 0x2f, 0x1c, 0xc4, 0xc2, 0x54, 0x47, 0x81, 0x10, 0xbd, 0x40, 0x4c, 0xd5, 0x25, - 0x30, 0x1d, 0x39, 0xf2, 0x00, 0x52, 0x7f, 0x7a, 0x04, 0xcc, 0x74, 0xc1, 0x08, 0x7f, 0xf5, 0xfb, - 0x14, 0xc5, 0x3d, 0x24, 0x97, 0xd1, 0x43, 0x60, 0x11, 0x0c, 0x8b, 0xc2, 0x49, 0xf8, 0xd6, 0x60, - 0x2d, 0x57, 0x54, 0x34, 0x7f, 0x01, 0xbe, 0x05, 0x86, 0x3c, 0x9e, 0xe3, 0x86, 0x84, 0x34, 0xe7, - 0xf8, 0xfd, 0x7e, 0xf3, 0xa4, 0x3c, 0xe5, 0x97, 0x8a, 0xd4, 0xdc, 0xad, 0x10, 0xa7, 0xda, 0x40, - 0x6c, 0xa7, 0xf2, 0x2e, 0xae, 0x23, 0xa3, 0x75, 0x0d, 0x1b, 0x45, 0x45, 0x13, 0x2c, 0xf0, 0x1c, - 0x18, 0x0f, 0xa5, 0xf2, 0xd1, 0x87, 0x45, 0x7e, 0x1d, 0x0b, 0x56, 0x45, 0x41, 0x06, 0xef, 0x81, - 0x62, 0x48, 0x66, 0x38, 0x8d, 0x06, 0xa1, 0x94, 0x38, 0xb6, 0x2e, 0x4e, 0x1d, 0x11, 0xa7, 0x9e, - 0x4d, 0x71, 0xaa, 0x76, 0x32, 0x00, 0x59, 0x0e, 0x31, 0x34, 0x2e, 0xc5, 0x3d, 0x50, 0x0c, 0x4d, - 0x1b, 0x87, 0x3f, 0x92, 0x01, 0x3e, 0x00, 0x89, 0xc1, 0xdf, 0x00, 0x05, 0x13, 0x53, 0xc3, 0x23, - 0xae, 0x28, 0xa5, 0xf3, 0xc2, 0xf2, 0x67, 0x83, 0x52, 0x3a, 0xe8, 0xb9, 0x82, 0x3a, 0xfa, 0x5a, - 0x9b, 0x54, 0xc6, 0x4a, 0x27, 0x37, 0xbc, 0x07, 0x4e, 0x85, 0xb2, 0x3a, 0x2e, 0xf6, 0x44, 0x81, - 0x1a, 0xf8, 0x83, 0x28, 0x23, 0x6b, 0x67, 0xbe, 0xfe, 0xe2, 0xc2, 0x4b, 0x12, 0x3d, 0xf4, 0x1f, - 0xe9, 0x07, 0x9b, 0xcc, 0x23, 0x76, 0x5d, 0x9b, 0x0c, 0x30, 0x6e, 0x4b, 0x88, 0xc0, 0x4d, 0x4e, - 0x82, 0x91, 0x9f, 0x20, 0x62, 0x61, 0x53, 0x54, 0x9e, 0x79, 0x4d, 0x7e, 0xc1, 0x8b, 0x60, 0x84, - 0xf7, 0x5d, 0x7b, 0x54, 0xd4, 0x8d, 0xe3, 0x8b, 0x6a, 0x37, 0xf1, 0x6b, 0x8e, 0x6d, 0x6e, 0x0a, - 0x4a, 0x4d, 0x72, 0xc0, 0x2d, 0x10, 0x7a, 0xa3, 0xce, 0x9c, 0x5d, 0x6c, 0xfb, 0x55, 0xe5, 0x68, - 0xed, 0xbc, 0xb4, 0xea, 0x89, 0xe7, 0xad, 0xba, 0x6e, 0xb3, 0xaf, 0xbf, 0xb8, 0x00, 0xe4, 0x21, - 0xeb, 0x36, 0xd3, 0xc6, 0x03, 0x8c, 0x2d, 0x01, 0xc1, 0x5d, 0x27, 0x44, 0xf5, 0x5d, 0x67, 0xcc, - 0x77, 0x9d, 0x60, 0xd5, 0x77, 0x9d, 0xd7, 0xc1, 0xa4, 0x8c, 0x5e, 0x4c, 0x75, 0x63, 0xcf, 0xf3, - 0x78, 0x8f, 0x81, 0x5d, 0xc7, 0xd8, 0x11, 0x35, 0x68, 0x5e, 0x3b, 0x11, 0x6e, 0x2f, 0xfb, 0xbb, - 0x2b, 0x7c, 0x53, 0xfd, 0x58, 0x01, 0xe5, 0xae, 0x71, 0x2d, 0xd3, 0x07, 0x06, 0xa0, 0x9d, 0x19, - 0xe4, 0xbb, 0xb4, 0x92, 0x2a, 0x17, 0xf6, 0x8a, 0x76, 0xad, 0x03, 0x58, 0xbd, 0x0f, 0xe6, 0x13, - 0x9a, 0xbd, 0x90, 0xf6, 0x3a, 0xa2, 0x5b, 0x8e, 0xfc, 0xc2, 0x87, 0x53, 0xb8, 0xaa, 0x77, 0xc0, - 0x42, 0x86, 0x23, 0xa5, 0x39, 0xce, 0x74, 0xa4, 0x18, 0x62, 0x06, 0xc9, 0xb3, 0xd0, 0x4e, 0x74, - 0xa2, 0x28, 0x3d, 0x9f, 0x5c, 0xe6, 0x46, 0x63, 0x26, 0x6d, 0xea, 0x4c, 0xd4, 0x33, 0x97, 0x5e, - 0xcf, 0x3a, 0x78, 0x35, 0x9d, 0x38, 0x52, 0xc5, 0x37, 0x64, 0xaa, 0x53, 0xd2, 0x67, 0x05, 0xc1, - 0xa0, 0xaa, 0x32, 0xc3, 0xd7, 0x2c, 0xc7, 0xd8, 0xa5, 0xef, 0xdb, 0x8c, 0x58, 0xb7, 0xf0, 0x43, - 0xdf, 0xd7, 0x82, 0xd7, 0xf6, 0xae, 0x2c, 0xd8, 0x93, 0x69, 0xa4, 0x04, 0xaf, 0x81, 0xc9, 0x6d, - 0xb1, 0xaf, 0xef, 0x71, 0x02, 0x5d, 0x54, 0x9c, 0xbe, 0x3f, 0x2b, 0xa2, 0xa3, 0x9b, 0xd8, 0x4e, - 0x60, 0x57, 0x97, 0x64, 0xf5, 0xbd, 0x1c, 0x9a, 0x6e, 0xd5, 0x73, 0x1a, 0xcb, 0xb2, 0xc3, 0x0e, - 0xcc, 0x1d, 0xe9, 0xc2, 0x95, 0x68, 0x17, 0xae, 0xae, 0x82, 0xb3, 0xfb, 0x42, 0xb4, 0x4b, 0xeb, - 0xfd, 0x5f, 0xbb, 0x77, 0x64, 0xdd, 0x1e, 0xf1, 0xad, 0xd4, 0x6f, 0xe5, 0xb7, 0x83, 0x49, 0xb3, - 0x9a, 0xd4, 0xa7, 0x47, 0x66, 0x10, 0xb9, 0xe8, 0x0c, 0xe2, 0x2c, 0x18, 0x73, 0x1e, 0xd8, 0x1d, - 0x8e, 0x34, 0x28, 0xf6, 0x8f, 0x8a, 0xc5, 0x20, 0x41, 0x86, 0x2d, 0xfb, 0x50, 0xb7, 0x96, 0x7d, - 0xf8, 0x30, 0x5b, 0xf6, 0x8f, 0x40, 0x81, 0xd8, 0x84, 0xe9, 0xb2, 0xde, 0x1a, 0x11, 0xd8, 0x2b, - 0x99, 0xb0, 0xd7, 0x6d, 0xc2, 0x08, 0xb2, 0xc8, 0x4f, 0xc5, 0x38, 0x46, 0x54, 0x61, 0xbc, 0x6f, - 0xa1, 0x1a, 0xe0, 0xc8, 0x7e, 0x55, 0x06, 0x1b, 0x60, 0xc2, 0x1f, 0x8b, 0xd0, 0x1d, 0xe4, 0x12, - 0xbb, 0x1e, 0x1c, 0x78, 0x44, 0x1c, 0xf8, 0x76, 0xba, 0x02, 0x8f, 0x03, 0x6c, 0xfa, 0xfc, 0x1d, - 0xc7, 0x40, 0x37, 0xbe, 0x4e, 0xa3, 0x8e, 0x96, 0x8f, 0x39, 0x5a, 0x2d, 0x96, 0x79, 0xe5, 0xfc, - 0x8e, 0xb7, 0x4a, 0xa9, 0xdd, 0x64, 0x37, 0x56, 0x51, 0x45, 0x30, 0xa4, 0xaf, 0xac, 0x81, 0x60, - 0x0c, 0xa8, 0x33, 0xd2, 0x08, 0x46, 0x8a, 0xe9, 0x7a, 0xb4, 0x42, 0xbd, 0x0d, 0xb8, 0xf8, 0x4d, - 0x19, 0x0c, 0x8b, 0xd3, 0xe0, 0x3f, 0x14, 0x30, 0x91, 0x74, 0x2e, 0xbc, 0x9a, 0xfd, 0x59, 0x88, - 0x8e, 0x50, 0x4b, 0x4b, 0x7d, 0x20, 0xf8, 0x0a, 0xab, 0xd7, 0x7f, 0xf6, 0xa7, 0xbf, 0x7f, 0x96, - 0xab, 0xc1, 0xab, 0xbd, 0x07, 0xee, 0xa1, 0x75, 0xa5, 0x9e, 0xd5, 0x47, 0x1d, 0xf6, 0x7e, 0x0c, - 0xff, 0xa2, 0xc8, 0xce, 0x20, 0xfa, 0x40, 0xc0, 0x2b, 0xd9, 0x85, 0x8c, 0xcc, 0x5a, 0x4b, 0x57, - 0x0f, 0x0e, 0x20, 0x95, 0x5c, 0x12, 0x4a, 0xbe, 0x0d, 0xdf, 0xca, 0xa0, 0xa4, 0x3f, 0xf2, 0xac, - 0x3e, 0x12, 0xc1, 0xfc, 0x18, 0x7e, 0x9a, 0x93, 0x39, 0x26, 0x71, 0x18, 0x03, 0x57, 0xd3, 0xcb, - 0xb8, 0xdf, 0x70, 0xa9, 0xb4, 0xd6, 0x37, 0x8e, 0x54, 0x79, 0x5b, 0xa8, 0xfc, 0x43, 0x78, 0x37, - 0xc5, 0x1f, 0x52, 0xc2, 0xa1, 0x66, 0xa4, 0xab, 0x8c, 0x5e, 0x6f, 0xf5, 0x51, 0xfc, 0x4d, 0x4d, - 0xb2, 0x49, 0x67, 0x2b, 0x74, 0x20, 0x9b, 0x24, 0xcc, 0xa3, 0x0e, 0x64, 0x93, 0xa4, 0x41, 0xd2, - 0xc1, 0x6c, 0x12, 0x51, 0x3b, 0x6e, 0x93, 0x78, 0x1b, 0xfe, 0x18, 0xfe, 0x41, 0x91, 0x5d, 0x73, - 0x64, 0xc8, 0x04, 0x2f, 0xa7, 0xd7, 0x21, 0x69, 0x76, 0x55, 0xba, 0x72, 0x60, 0x7e, 0xa9, 0xfb, - 0x9b, 0x42, 0xf7, 0x45, 0x38, 0xdf, 0x5b, 0x77, 0x26, 0x01, 0xfc, 0xbf, 0xaa, 0xc0, 0x5f, 0xe6, - 0xe4, 0x23, 0xbf, 0xff, 0xd4, 0x08, 0xde, 0x4e, 0x2f, 0x62, 0xaa, 0x69, 0x55, 0x69, 0xe3, 0xf0, - 0x00, 0xa5, 0x11, 0x6e, 0x08, 0x23, 0xac, 0xc0, 0xe5, 0xde, 0x46, 0xf0, 0x42, 0xc4, 0x76, 0x54, - 0x44, 0xc6, 0xd5, 0xf0, 0xe7, 0x39, 0x59, 0x3f, 0xed, 0x3b, 0xb7, 0x82, 0xb7, 0xd2, 0x6b, 0x91, - 0x66, 0x9e, 0x56, 0xba, 0x7d, 0x68, 0x78, 0xd2, 0x28, 0x2b, 0xc2, 0x28, 0x57, 0xe0, 0xa5, 0xde, - 0x46, 0x91, 0x5e, 0xae, 0xbb, 0x1c, 0x35, 0x96, 0xfe, 0x7f, 0xa7, 0x80, 0x42, 0xc7, 0x60, 0x08, - 0xbe, 0x91, 0x5e, 0xce, 0xc8, 0x80, 0xa9, 0xf4, 0x66, 0x76, 0x46, 0xa9, 0xc9, 0xbc, 0xd0, 0x64, - 0x0e, 0xce, 0xf6, 0xd6, 0xc4, 0x2f, 0x65, 0xda, 0xbe, 0xbd, 0xff, 0x70, 0x28, 0x8b, 0x6f, 0xa7, - 0x9a, 0x5a, 0x65, 0xf1, 0xed, 0x74, 0x73, 0xab, 0x2c, 0xbe, 0xed, 0x70, 0x10, 0x9d, 0xd8, 0x7a, - 0xbb, 0xa1, 0x8c, 0x5d, 0xe6, 0xef, 0x73, 0x72, 0xc4, 0x9b, 0xa6, 0xd9, 0x83, 0xef, 0x1f, 0xf4, - 0x81, 0xde, 0xb7, 0x5f, 0x2d, 0xdd, 0x39, 0x6c, 0x58, 0x69, 0xa9, 0xbb, 0xc2, 0x52, 0x5b, 0x50, - 0xcb, 0x5c, 0x0d, 0xe8, 0x2e, 0xf6, 0xda, 0x46, 0x4b, 0x7a, 0x12, 0x7f, 0x9b, 0x03, 0x2f, 0xa7, - 0xe9, 0x1e, 0xe1, 0x46, 0x1f, 0x0f, 0x7d, 0x62, 0x5f, 0x5c, 0x7a, 0xef, 0x10, 0x11, 0xa5, 0xa5, - 0x0c, 0x61, 0xa9, 0x7b, 0xf0, 0xc3, 0x2c, 0x96, 0x8a, 0x0e, 0xcb, 0x7a, 0x57, 0x11, 0xff, 0x56, - 0xc0, 0x64, 0x97, 0xd9, 0x07, 0x5c, 0xee, 0x67, 0x72, 0x12, 0x18, 0xe6, 0x5a, 0x7f, 0x20, 0xd9, - 0xe3, 0x2b, 0xd4, 0xb8, 0x6b, 0x7c, 0xfd, 0x4b, 0x91, 0x0d, 0x6f, 0x52, 0x5f, 0x0f, 0x33, 0xcc, - 0x8b, 0xf6, 0x99, 0x1d, 0x94, 0x56, 0xfb, 0x85, 0xc9, 0x5e, 0x3d, 0x77, 0x19, 0x43, 0xc0, 0xff, - 0xc4, 0xff, 0x39, 0x21, 0x3a, 0x28, 0x80, 0x6b, 0xd9, 0xaf, 0x28, 0x71, 0x5a, 0x51, 0xba, 0xde, - 0x3f, 0x50, 0x1f, 0x3d, 0x03, 0x31, 0xab, 0x8f, 0xc2, 0x1e, 0xf6, 0x31, 0xfc, 0x6b, 0x50, 0x0b, - 0x46, 0xd2, 0x53, 0x96, 0x5a, 0x30, 0x69, 0x1e, 0x52, 0xba, 0x72, 0x60, 0x7e, 0xa9, 0xda, 0xaa, - 0x50, 0xed, 0x2a, 0xbc, 0x9c, 0x35, 0x01, 0xc6, 0xbc, 0xf8, 0x7f, 0x0a, 0x28, 0x76, 0xeb, 0xa8, - 0xe1, 0xb5, 0x03, 0xf7, 0xa6, 0x1d, 0x4d, 0x7d, 0x69, 0xa5, 0x4f, 0x14, 0xa9, 0xf1, 0x4d, 0xa1, - 0xf1, 0x1a, 0x5c, 0xc9, 0xde, 0xe5, 0x8a, 0x39, 0x40, 0x54, 0xf1, 0xda, 0x07, 0x5f, 0x3e, 0x9d, - 0x56, 0xbe, 0x7a, 0x3a, 0xad, 0x7c, 0xfb, 0x74, 0x5a, 0xf9, 0xe4, 0xd9, 0xf4, 0xc0, 0x57, 0xcf, - 0xa6, 0x07, 0xfe, 0xfc, 0x6c, 0x7a, 0xe0, 0xee, 0xa5, 0x3a, 0x61, 0x3b, 0x7b, 0xdb, 0x15, 0xc3, - 0x69, 0xc8, 0x7f, 0xaf, 0xea, 0x38, 0xf1, 0x42, 0x78, 0x62, 0xf3, 0xf5, 0xea, 0xc3, 0x58, 0xd1, - 0xdd, 0x72, 0x31, 0xdd, 0x1e, 0x11, 0x03, 0x86, 0x1f, 0xfc, 0x3f, 0x00, 0x00, 0xff, 0xff, 0x42, - 0x06, 0x36, 0xb2, 0xfe, 0x26, 0x00, 0x00, + // 2572 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x5a, 0xcd, 0x6f, 0x1b, 0xc7, + 0x15, 0xd7, 0x52, 0x1f, 0xa6, 0x86, 0x96, 0x1c, 0x8f, 0x65, 0x8b, 0xa6, 0x1c, 0x51, 0x5e, 0xc7, + 0xad, 0x22, 0xc7, 0xa4, 0xa4, 0x22, 0x1f, 0x76, 0xe2, 0x0f, 0x51, 0x96, 0x64, 0xc2, 0xb1, 0xad, + 0xac, 0x14, 0x07, 0x70, 0xea, 0x6e, 0x47, 0xbb, 0x63, 0x6a, 0x2a, 0x72, 0x77, 0xbd, 0x33, 0xa2, + 0xcd, 0x1a, 0xbe, 0xb4, 0x97, 0x1c, 0x5a, 0x20, 0x41, 0xd1, 0x73, 0x73, 0xee, 0xa1, 0x28, 0x8a, + 0xa0, 0x7f, 0x43, 0x6e, 0x75, 0xd3, 0x4b, 0x91, 0xa2, 0x6e, 0x61, 0xb7, 0x40, 0x2f, 0x3d, 0x34, + 0x2d, 0x7a, 0x2e, 0x66, 0x76, 0x76, 0xc9, 0x5d, 0x2f, 0xc5, 0x5d, 0x51, 0xbd, 0x69, 0x67, 0xde, + 0xfb, 0xbd, 0x8f, 0x79, 0xf3, 0xe6, 0xbd, 0x47, 0x81, 0x32, 0xb1, 0x18, 0x76, 0x8d, 0x6d, 0x44, + 0x2c, 0x9d, 0x62, 0x63, 0xd7, 0x25, 0xac, 0x55, 0x36, 0x8c, 0x66, 0xd9, 0x71, 0xed, 0x26, 0x31, + 0xb1, 0x5b, 0x6e, 0x2e, 0x94, 0x1f, 0xec, 0x62, 0xb7, 0x55, 0x72, 0x5c, 0x9b, 0xd9, 0xf0, 0x4c, + 0x0c, 0x43, 0xc9, 0x30, 0x9a, 0x25, 0x9f, 0xa1, 0xd4, 0x5c, 0x28, 0x9c, 0xaa, 0xd9, 0x76, 0xad, + 0x8e, 0xcb, 0xc8, 0x21, 0x65, 0x64, 0x59, 0x36, 0x43, 0x8c, 0xd8, 0x16, 0xf5, 0x20, 0x0a, 0x13, + 0x35, 0xbb, 0x66, 0x8b, 0x3f, 0xcb, 0xfc, 0x2f, 0xb9, 0x5a, 0x94, 0x3c, 0xe2, 0x6b, 0x6b, 0xf7, + 0x7e, 0x99, 0x91, 0x06, 0xa6, 0x0c, 0x35, 0x1c, 0x49, 0xb0, 0x98, 0x44, 0xd5, 0x40, 0x0b, 0x8f, + 0x67, 0xbe, 0x1b, 0x4f, 0x73, 0xa1, 0x4c, 0xb7, 0x91, 0x8b, 0x4d, 0xdd, 0xb0, 0x2d, 0xba, 0xdb, + 0x08, 0x38, 0xce, 0xee, 0xc1, 0xf1, 0x90, 0xb8, 0x58, 0x92, 0x9d, 0x62, 0xd8, 0x32, 0xb1, 0xdb, + 0x20, 0x16, 0x2b, 0x1b, 0x6e, 0xcb, 0x61, 0x76, 0x79, 0x07, 0xb7, 0x7c, 0x0b, 0x4f, 0x1a, 0x36, + 0x6d, 0xd8, 0x54, 0xf7, 0x8c, 0xf4, 0x3e, 0xe4, 0xd6, 0x6b, 0xde, 0x57, 0x99, 0x32, 0xb4, 0x43, + 0xac, 0x5a, 0xb9, 0xb9, 0xb0, 0x85, 0x19, 0x5a, 0xf0, 0xbf, 0x25, 0xd5, 0x9c, 0xa4, 0xda, 0x42, + 0x14, 0x7b, 0xee, 0x0f, 0x08, 0x1d, 0x54, 0x23, 0x96, 0xf0, 0xa7, 0x47, 0xab, 0x5e, 0x06, 0x53, + 0x1f, 0x70, 0x8a, 0x65, 0x69, 0xc8, 0x1a, 0xb6, 0x30, 0x25, 0x54, 0xc3, 0x0f, 0x76, 0x31, 0x65, + 0xb0, 0x08, 0x72, 0xbe, 0x89, 0x3a, 0x31, 0xf3, 0xca, 0x8c, 0x32, 0x3b, 0xaa, 0x01, 0x7f, 0xa9, + 0x6a, 0xaa, 0x8f, 0xc1, 0xa9, 0x78, 0x7e, 0xea, 0xd8, 0x16, 0xc5, 0xf0, 0x63, 0x30, 0x56, 0xf3, + 0x96, 0x74, 0xca, 0x10, 0xc3, 0x02, 0x22, 0xb7, 0x38, 0x5f, 0xea, 0x16, 0x09, 0xcd, 0x85, 0x52, + 0x04, 0x6b, 0x83, 0xf3, 0x55, 0x86, 0xbe, 0x7c, 0x56, 0x1c, 0xd0, 0x0e, 0xd7, 0x3a, 0xd6, 0xd4, + 0x5f, 0x29, 0xa0, 0x10, 0x92, 0xbe, 0xcc, 0xf1, 0x02, 0xe5, 0xaf, 0x83, 0x61, 0x67, 0x1b, 0x51, + 0x4f, 0xe6, 0xf8, 0xe2, 0x62, 0x29, 0x41, 0xf4, 0x05, 0xc2, 0xd7, 0x39, 0xa7, 0xe6, 0x01, 0xc0, + 0x55, 0x00, 0xda, 0x9e, 0xcb, 0x67, 0x84, 0x09, 0xdf, 0x2a, 0xc9, 0xa3, 0xe1, 0x6e, 0x2e, 0x79, + 0x51, 0x2e, 0xdd, 0x5c, 0x5a, 0x47, 0x35, 0x2c, 0xb5, 0xd0, 0x3a, 0x38, 0xd5, 0x5f, 0x2a, 0x11, + 0x77, 0xfb, 0x0a, 0x4b, 0x6f, 0x55, 0xc0, 0x88, 0x50, 0x8f, 0xe6, 0x95, 0x99, 0xc1, 0xd9, 0xdc, + 0xe2, 0x5c, 0x32, 0x95, 0xf9, 0xb6, 0x26, 0x39, 0xe1, 0x5a, 0x8c, 0xae, 0xdf, 0xee, 0xa9, 0xab, + 0xa7, 0x40, 0x48, 0xd9, 0x1f, 0x8f, 0x80, 0x61, 0x01, 0x0d, 0x4f, 0x82, 0xac, 0xa7, 0x42, 0x10, + 0x02, 0x87, 0xc4, 0x77, 0xd5, 0x84, 0x53, 0x60, 0xd4, 0xa8, 0x13, 0x6c, 0x31, 0xbe, 0x97, 0x11, + 0x7b, 0x59, 0x6f, 0xa1, 0x6a, 0xc2, 0x63, 0x60, 0x98, 0xd9, 0x8e, 0x7e, 0x2b, 0x3f, 0x38, 0xa3, + 0xcc, 0x8e, 0x69, 0x43, 0xcc, 0x76, 0x6e, 0xc1, 0x39, 0x00, 0x1b, 0xc4, 0xd2, 0x1d, 0xfb, 0x21, + 0x8f, 0x29, 0x4b, 0xf7, 0x28, 0x86, 0x66, 0x94, 0xd9, 0x41, 0x6d, 0xbc, 0x41, 0xac, 0x75, 0xbe, + 0x51, 0xb5, 0x36, 0x39, 0xed, 0x3c, 0x98, 0x68, 0xa2, 0x3a, 0x31, 0x11, 0xb3, 0x5d, 0x2a, 0x59, + 0x0c, 0xe4, 0xe4, 0x87, 0x05, 0x1e, 0x6c, 0xef, 0x09, 0xa6, 0x65, 0xe4, 0xc0, 0x39, 0x70, 0x34, + 0x58, 0xd5, 0x29, 0x66, 0x82, 0x7c, 0x44, 0x90, 0x1f, 0x09, 0x36, 0x36, 0x30, 0xe3, 0xb4, 0xa7, + 0xc0, 0x28, 0xaa, 0xd7, 0xed, 0x87, 0x75, 0x42, 0x59, 0xfe, 0xd0, 0xcc, 0xe0, 0xec, 0xa8, 0xd6, + 0x5e, 0x80, 0x05, 0x90, 0x35, 0xb1, 0xd5, 0x12, 0x9b, 0x59, 0xb1, 0x19, 0x7c, 0xc3, 0x09, 0x3f, + 0xb2, 0x46, 0x85, 0xc5, 0x32, 0x4a, 0x3e, 0x02, 0xd9, 0x06, 0x66, 0xc8, 0x44, 0x0c, 0xe5, 0x81, + 0xf0, 0xfb, 0x9b, 0xa9, 0x42, 0xee, 0xa6, 0x64, 0x96, 0xb1, 0x1e, 0x80, 0x71, 0x27, 0x73, 0x97, + 0xf1, 0x5b, 0x8e, 0xf3, 0xb9, 0x19, 0x65, 0x76, 0x48, 0xcb, 0x36, 0x88, 0xb5, 0xc1, 0xbf, 0x61, + 0x09, 0x1c, 0x13, 0x4a, 0xeb, 0xc4, 0x42, 0x06, 0x23, 0x4d, 0xac, 0x37, 0x51, 0x9d, 0xe6, 0x0f, + 0xcf, 0x28, 0xb3, 0x59, 0xed, 0xa8, 0xd8, 0xaa, 0xca, 0x9d, 0x3b, 0xa8, 0x4e, 0xa3, 0x57, 0x7a, + 0x2c, 0x7a, 0xa5, 0xe1, 0x23, 0x70, 0x32, 0xf0, 0x02, 0x36, 0x75, 0x17, 0x3f, 0x44, 0xae, 0xa9, + 0x9b, 0xd8, 0xb2, 0x1b, 0x34, 0x3f, 0x2e, 0xec, 0x7a, 0x2f, 0x91, 0x5d, 0x4b, 0x6d, 0x14, 0x4d, + 0x80, 0x5c, 0x13, 0x18, 0xda, 0x24, 0x8a, 0xdf, 0x80, 0x2a, 0x38, 0xec, 0xb8, 0xc4, 0xe6, 0x60, + 0xc2, 0xed, 0x47, 0x84, 0xdb, 0x43, 0x6b, 0xd0, 0x02, 0xc7, 0x89, 0x75, 0xdf, 0xe5, 0x06, 0xd9, + 0x96, 0xee, 0x20, 0x17, 0x35, 0x30, 0xc3, 0x2e, 0xcd, 0xbf, 0x22, 0x34, 0xbb, 0x90, 0x48, 0xb3, + 0x6a, 0x80, 0xb0, 0x1e, 0x00, 0x68, 0x13, 0x24, 0x66, 0x55, 0xfd, 0xa9, 0x02, 0x4e, 0x8b, 0x2b, + 0x7b, 0xc7, 0x8f, 0x1e, 0xff, 0xb8, 0x96, 0x4c, 0xd3, 0xf5, 0x53, 0xcd, 0x25, 0xf0, 0x8a, 0x8f, + 0xaf, 0x23, 0xd3, 0x74, 0x31, 0xa5, 0xde, 0x4d, 0xa9, 0xc0, 0x6f, 0x9e, 0x15, 0xc7, 0x5b, 0xa8, + 0x51, 0xbf, 0xa8, 0xca, 0x0d, 0x55, 0x3b, 0xe2, 0xd3, 0x2e, 0x79, 0x2b, 0xd1, 0x33, 0xc9, 0x44, + 0xcf, 0xe4, 0x62, 0xf6, 0x93, 0xcf, 0x8b, 0x03, 0xff, 0xf8, 0xbc, 0x38, 0xa0, 0xde, 0x06, 0xea, + 0x5e, 0xea, 0xc8, 0x44, 0xf2, 0x3a, 0x78, 0x25, 0x00, 0x0c, 0xe9, 0xa3, 0x1d, 0x31, 0x3a, 0xe8, + 0xb9, 0x36, 0x2f, 0x1b, 0xb8, 0xde, 0xa1, 0x5d, 0x87, 0x81, 0xf1, 0x80, 0xf1, 0x06, 0x46, 0x84, + 0xf4, 0x65, 0x60, 0x58, 0x9d, 0xb6, 0x81, 0xf1, 0x0e, 0x7f, 0xc9, 0xb9, 0xea, 0x14, 0x38, 0x29, + 0x00, 0x37, 0xb7, 0x5d, 0x9b, 0xb1, 0x3a, 0x16, 0x6f, 0x87, 0xb4, 0x4b, 0xfd, 0xbd, 0xff, 0x84, + 0x44, 0x76, 0xa5, 0x98, 0x22, 0xc8, 0xd1, 0x3a, 0xa2, 0xdb, 0xba, 0x88, 0x06, 0x21, 0x61, 0x50, + 0x03, 0x62, 0xe9, 0x26, 0x5f, 0x81, 0x8b, 0xe0, 0x78, 0x07, 0x81, 0x2e, 0x22, 0x1b, 0x59, 0x06, + 0x16, 0x26, 0x0e, 0x6a, 0xc7, 0xda, 0xa4, 0x4b, 0xfe, 0x16, 0xfc, 0x1e, 0xc8, 0x5b, 0xf8, 0x11, + 0xd3, 0x5d, 0xec, 0xd4, 0xb1, 0x45, 0xe8, 0xb6, 0x6e, 0x20, 0xcb, 0xe4, 0xc6, 0x62, 0x91, 0x29, + 0x73, 0x8b, 0x85, 0x92, 0x57, 0xcf, 0x94, 0xfc, 0x7a, 0xa6, 0xb4, 0xe9, 0xd7, 0x33, 0x95, 0x2c, + 0x4f, 0x0e, 0x9f, 0xfe, 0xa5, 0xa8, 0x68, 0x27, 0x38, 0x8a, 0xe6, 0x83, 0x2c, 0xfb, 0x18, 0xea, + 0x1b, 0x60, 0x4e, 0x98, 0xa4, 0xe1, 0x1a, 0xbf, 0x63, 0x2e, 0x36, 0xfd, 0x18, 0x09, 0x5d, 0x43, + 0xe9, 0x81, 0x15, 0x70, 0x2e, 0x11, 0xb5, 0xf4, 0xc8, 0x09, 0x30, 0x22, 0x53, 0x81, 0x22, 0x6e, + 0xa7, 0xfc, 0x52, 0xdf, 0x07, 0xaf, 0x0b, 0x98, 0xa5, 0x7a, 0x7d, 0x1d, 0x11, 0x97, 0xde, 0x41, + 0x75, 0x8e, 0xc3, 0x0f, 0xa1, 0xd2, 0x6a, 0x23, 0x26, 0x2c, 0x2b, 0x7e, 0xa1, 0x48, 0x1b, 0x7a, + 0xc0, 0x49, 0xa5, 0x1e, 0x80, 0xa3, 0x0e, 0x22, 0x2e, 0xcf, 0x7c, 0xbc, 0x24, 0x13, 0x11, 0x21, + 0x9f, 0xd0, 0xd5, 0x44, 0x09, 0x81, 0xcb, 0xf0, 0x44, 0x70, 0x09, 0x41, 0xc4, 0x59, 0x6d, 0x5f, + 0x8c, 0x3b, 0x21, 0x12, 0xf5, 0x3f, 0x0a, 0x38, 0xdd, 0x93, 0x0b, 0xae, 0x76, 0xcd, 0x0b, 0x53, + 0xdf, 0x3c, 0x2b, 0x4e, 0x7a, 0xd7, 0x26, 0x4a, 0x11, 0x93, 0x20, 0x56, 0x63, 0xae, 0x5f, 0x26, + 0x8a, 0x13, 0xa5, 0x88, 0xb9, 0x87, 0x57, 0xc0, 0xe1, 0x80, 0x6a, 0x07, 0xb7, 0x64, 0xb8, 0x9d, + 0x2a, 0xb5, 0x0b, 0xd2, 0x92, 0x57, 0x90, 0x96, 0xd6, 0x77, 0xb7, 0xea, 0xc4, 0xb8, 0x81, 0x5b, + 0x5a, 0x70, 0x54, 0x37, 0x70, 0x4b, 0x9d, 0x00, 0x50, 0x9c, 0x8b, 0xc8, 0x90, 0x41, 0x0c, 0x7d, + 0x1f, 0x1c, 0x0b, 0xad, 0xca, 0x63, 0xa9, 0x82, 0x11, 0x91, 0xa0, 0xa9, 0xac, 0xfa, 0xce, 0x25, + 0x3c, 0x0b, 0xce, 0x22, 0x1f, 0x41, 0x09, 0xa0, 0xde, 0x94, 0xf1, 0x10, 0x2a, 0x9c, 0x6e, 0x3b, + 0x0c, 0x9b, 0x55, 0x2b, 0xc8, 0x14, 0xc9, 0xcb, 0xd6, 0x07, 0x32, 0xe8, 0x7b, 0xc1, 0x05, 0x75, + 0xd9, 0xab, 0x9d, 0x75, 0x48, 0xe4, 0xbc, 0xb0, 0x7f, 0x17, 0xa6, 0x3a, 0x0a, 0x92, 0xf0, 0x01, + 0x62, 0xaa, 0x2e, 0x81, 0xe9, 0x90, 0xc8, 0x7d, 0x68, 0xfd, 0xd9, 0x21, 0x30, 0xd3, 0x05, 0x23, + 0xf8, 0xab, 0xdf, 0xa7, 0x28, 0x1a, 0x21, 0x99, 0x94, 0x11, 0x02, 0xf3, 0x60, 0x58, 0x14, 0x6a, + 0x22, 0xb6, 0x06, 0x2b, 0x99, 0xbc, 0xa2, 0x79, 0x0b, 0xf0, 0x02, 0x18, 0x72, 0x79, 0x8e, 0x1b, + 0x12, 0xda, 0x9c, 0xe5, 0xe7, 0xfb, 0xf5, 0xb3, 0xe2, 0x94, 0x57, 0x9a, 0x52, 0x73, 0xa7, 0x44, + 0xec, 0x72, 0x03, 0xb1, 0xed, 0xd2, 0xfb, 0xb8, 0x86, 0x8c, 0xd6, 0x35, 0x6c, 0xe4, 0x15, 0x4d, + 0xb0, 0xc0, 0xb3, 0x60, 0x3c, 0xd0, 0xca, 0x43, 0x1f, 0x16, 0xf9, 0x75, 0xcc, 0x5f, 0x15, 0x05, + 0x20, 0xbc, 0x07, 0xf2, 0x01, 0x99, 0x61, 0x37, 0x1a, 0x84, 0x52, 0x5e, 0x25, 0x08, 0xa9, 0x23, + 0x42, 0xea, 0x99, 0x04, 0x52, 0xb5, 0x13, 0x3e, 0xc8, 0x72, 0x80, 0xa1, 0x71, 0x2d, 0xee, 0x81, + 0x7c, 0xe0, 0xda, 0x28, 0xfc, 0xa1, 0x14, 0xf0, 0x3e, 0x48, 0x04, 0xfe, 0x06, 0xc8, 0x99, 0x98, + 0x1a, 0x2e, 0x71, 0x44, 0xe9, 0x9e, 0x15, 0x9e, 0x3f, 0xe3, 0x97, 0xee, 0x7e, 0x8f, 0xe7, 0xd7, + 0xed, 0xd7, 0xda, 0xa4, 0xf2, 0xae, 0x74, 0x72, 0xc3, 0x7b, 0xe0, 0x64, 0xa0, 0xab, 0xed, 0x60, + 0x57, 0x14, 0xc4, 0x7e, 0x3c, 0x88, 0xb2, 0xb5, 0x72, 0xfa, 0xab, 0x2f, 0xce, 0xbf, 0x2a, 0xd1, + 0x83, 0xf8, 0x91, 0x71, 0xb0, 0xc1, 0x5c, 0x62, 0xd5, 0xb4, 0x49, 0x1f, 0xe3, 0xb6, 0x84, 0xf0, + 0xc3, 0xe4, 0x04, 0x18, 0xf9, 0x01, 0x22, 0x75, 0x6c, 0x8a, 0x4a, 0x37, 0xab, 0xc9, 0x2f, 0x78, + 0x11, 0x8c, 0xf0, 0x3e, 0x6f, 0x97, 0x8a, 0x3a, 0x75, 0x7c, 0x51, 0xed, 0xa6, 0x7e, 0xc5, 0xb6, + 0xcc, 0x0d, 0x41, 0xa9, 0x49, 0x0e, 0xb8, 0x09, 0x82, 0x68, 0xd4, 0x99, 0xbd, 0x83, 0x2d, 0xaf, + 0x8a, 0x1d, 0xad, 0x9c, 0x93, 0x5e, 0x3d, 0xfe, 0xb2, 0x57, 0xab, 0x16, 0xfb, 0xea, 0x8b, 0xf3, + 0x40, 0x0a, 0xa9, 0x5a, 0x4c, 0x1b, 0xf7, 0x31, 0x36, 0x05, 0x04, 0x0f, 0x9d, 0x00, 0xd5, 0x0b, + 0x9d, 0x31, 0x2f, 0x74, 0xfc, 0x55, 0x2f, 0x74, 0xde, 0x02, 0x93, 0xf2, 0xf6, 0x62, 0xaa, 0x1b, + 0xbb, 0xae, 0xcb, 0x7b, 0x1a, 0xec, 0xd8, 0xc6, 0xb6, 0xa8, 0x79, 0xb3, 0xda, 0xf1, 0x60, 0x7b, + 0xd9, 0xdb, 0x5d, 0xe1, 0x9b, 0xea, 0x27, 0x0a, 0x28, 0x76, 0xbd, 0xd7, 0x32, 0x7d, 0x60, 0x00, + 0xda, 0x99, 0x41, 0xbe, 0x4b, 0x2b, 0x89, 0x72, 0x61, 0xaf, 0xdb, 0xae, 0x75, 0x00, 0xab, 0x0f, + 0xc0, 0x7c, 0x4c, 0x73, 0x19, 0xd0, 0x5e, 0x47, 0x74, 0xd3, 0x96, 0x5f, 0xf8, 0x60, 0x0a, 0x57, + 0xf5, 0x0e, 0x58, 0x48, 0x21, 0x52, 0xba, 0xe3, 0x74, 0x47, 0x8a, 0x21, 0xa6, 0x9f, 0x3c, 0x73, + 0xed, 0x44, 0x27, 0x8a, 0xd2, 0x73, 0xf1, 0x65, 0x6e, 0xf8, 0xce, 0x24, 0x4d, 0x9d, 0xb1, 0x76, + 0x66, 0x92, 0xdb, 0x59, 0x03, 0x6f, 0x24, 0x53, 0x47, 0x9a, 0xf8, 0xb6, 0x4c, 0x75, 0x4a, 0xf2, + 0xac, 0x20, 0x18, 0x54, 0x55, 0x66, 0xf8, 0x4a, 0xdd, 0x36, 0x76, 0xe8, 0x87, 0x16, 0x23, 0xf5, + 0x5b, 0xf8, 0x91, 0x17, 0x6b, 0xfe, 0x6b, 0x7b, 0x57, 0x16, 0xec, 0xf1, 0x34, 0x52, 0x83, 0x37, + 0xc1, 0xe4, 0x96, 0xd8, 0xd7, 0x77, 0x39, 0x81, 0x2e, 0x2a, 0x4e, 0x2f, 0x9e, 0x15, 0xd1, 0x41, + 0x4e, 0x6c, 0xc5, 0xb0, 0xab, 0x4b, 0xb2, 0xfa, 0x5e, 0x0e, 0x5c, 0xb7, 0xea, 0xda, 0x8d, 0x65, + 0xd9, 0xd1, 0xfb, 0xee, 0x0e, 0x75, 0xfd, 0x4a, 0xb8, 0xeb, 0x57, 0x57, 0xc1, 0x99, 0x3d, 0x21, + 0xda, 0xa5, 0xf5, 0xde, 0xaf, 0xdd, 0x7b, 0xb2, 0x6e, 0x0f, 0xc5, 0x56, 0xe2, 0xb7, 0xf2, 0xe9, + 0x50, 0xdc, 0x6c, 0x28, 0xb1, 0xf4, 0xd0, 0xcc, 0x23, 0x13, 0x9e, 0x79, 0x9c, 0x01, 0x63, 0xf6, + 0x43, 0xab, 0x23, 0x90, 0x06, 0xc5, 0xfe, 0x61, 0xb1, 0xe8, 0x27, 0xc8, 0x60, 0x44, 0x30, 0xd4, + 0x6d, 0x44, 0x30, 0x7c, 0x90, 0x23, 0x82, 0xfb, 0x20, 0x47, 0x2c, 0xc2, 0x74, 0x59, 0x6f, 0x8d, + 0x08, 0xec, 0x95, 0x54, 0xd8, 0x55, 0x8b, 0x30, 0x82, 0xea, 0xe4, 0x87, 0x28, 0xd2, 0x18, 0x03, + 0x8e, 0xec, 0x55, 0x65, 0xb0, 0x01, 0x26, 0xbc, 0x31, 0x0c, 0xdd, 0x46, 0x0e, 0xb1, 0x6a, 0xbe, + 0xc0, 0x43, 0x42, 0xe0, 0xbb, 0xc9, 0x0a, 0x3c, 0x0e, 0xb0, 0xe1, 0xf1, 0x77, 0x88, 0x81, 0x4e, + 0x74, 0x9d, 0x76, 0xef, 0xf6, 0xb3, 0xff, 0x97, 0x6e, 0x3f, 0x1c, 0xd8, 0xa3, 0x91, 0xc0, 0xae, + 0x44, 0x32, 0xbd, 0x9c, 0x4f, 0xf2, 0xd6, 0x2c, 0x71, 0x58, 0xee, 0x44, 0x2a, 0xb8, 0x10, 0x86, + 0x8c, 0xcd, 0x35, 0xe0, 0x8f, 0x39, 0x75, 0x46, 0x1a, 0xfe, 0xc8, 0x34, 0x59, 0x4f, 0x98, 0xab, + 0xb5, 0x01, 0x17, 0xbf, 0x2e, 0x82, 0x61, 0x21, 0x0d, 0xfe, 0x5d, 0x01, 0x13, 0x71, 0x72, 0xe1, + 0xd5, 0xf4, 0xcf, 0x50, 0x78, 0x44, 0x5c, 0x58, 0xea, 0x03, 0xc1, 0x33, 0x58, 0xbd, 0xfe, 0xa3, + 0x3f, 0xfc, 0xed, 0x67, 0x99, 0x0a, 0xbc, 0xda, 0xfb, 0x07, 0x85, 0xc0, 0xbb, 0xd2, 0xce, 0xf2, + 0xe3, 0x0e, 0x7f, 0x3f, 0x81, 0x7f, 0x52, 0x64, 0x27, 0x12, 0x7e, 0x90, 0xe0, 0x95, 0xf4, 0x4a, + 0x86, 0x66, 0xc9, 0x85, 0xab, 0xfb, 0x07, 0x90, 0x46, 0x2e, 0x09, 0x23, 0xdf, 0x85, 0x17, 0x52, + 0x18, 0xe9, 0x8d, 0x74, 0xcb, 0x8f, 0x45, 0xf2, 0x78, 0x02, 0x3f, 0xcb, 0xc8, 0x9c, 0x16, 0x3b, + 0xfc, 0x81, 0xab, 0xc9, 0x75, 0xdc, 0x6b, 0x98, 0x55, 0x58, 0xeb, 0x1b, 0x47, 0x9a, 0xbc, 0x25, + 0x4c, 0xfe, 0x2e, 0xbc, 0x9b, 0xe0, 0x87, 0xa2, 0x60, 0x68, 0x1b, 0xea, 0x62, 0xc3, 0xc7, 0x5b, + 0x7e, 0x1c, 0x7d, 0xc3, 0xe3, 0x7c, 0xd2, 0xd9, 0x7a, 0xed, 0xcb, 0x27, 0x31, 0xf3, 0xaf, 0x7d, + 0xf9, 0x24, 0x6e, 0x70, 0xb5, 0x3f, 0x9f, 0x84, 0xcc, 0x8e, 0xfa, 0x24, 0xda, 0xf6, 0x3f, 0x81, + 0xbf, 0x53, 0x64, 0x97, 0x1e, 0x1a, 0x6a, 0xc1, 0xcb, 0xc9, 0x6d, 0x88, 0x9b, 0x95, 0x15, 0xae, + 0xec, 0x9b, 0x5f, 0xda, 0xfe, 0x8e, 0xb0, 0x7d, 0x11, 0xce, 0xf7, 0xb6, 0x9d, 0x49, 0x00, 0xef, + 0x57, 0x23, 0xf8, 0xf3, 0x8c, 0x2c, 0x2a, 0xf6, 0x9e, 0x52, 0xc1, 0xdb, 0xc9, 0x55, 0x4c, 0x34, + 0x1d, 0x2b, 0xac, 0x1f, 0x1c, 0xa0, 0x74, 0xc2, 0x0d, 0xe1, 0x84, 0x15, 0xb8, 0xdc, 0xdb, 0x09, + 0x6e, 0x80, 0xd8, 0xbe, 0x15, 0xa1, 0x71, 0x3c, 0xfc, 0x49, 0x46, 0xd6, 0x6b, 0x7b, 0xce, 0xc9, + 0xe0, 0xad, 0xe4, 0x56, 0x24, 0x99, 0xdf, 0x15, 0x6e, 0x1f, 0x18, 0x9e, 0x74, 0xca, 0x8a, 0x70, + 0xca, 0x15, 0x78, 0xa9, 0xb7, 0x53, 0x64, 0x94, 0xeb, 0x0e, 0x47, 0x8d, 0xa4, 0xff, 0xdf, 0x28, + 0x20, 0xd7, 0x31, 0x88, 0x82, 0x6f, 0x27, 0xd7, 0x33, 0x34, 0xd0, 0x2a, 0xbc, 0x93, 0x9e, 0x51, + 0x5a, 0x32, 0x2f, 0x2c, 0x99, 0x83, 0xb3, 0xbd, 0x2d, 0xf1, 0x4a, 0xa7, 0x76, 0x6c, 0xef, 0x3d, + 0x8c, 0x4a, 0x13, 0xdb, 0x89, 0xa6, 0x64, 0x69, 0x62, 0x3b, 0xd9, 0x9c, 0x2c, 0x4d, 0x6c, 0xdb, + 0x1c, 0x44, 0x27, 0x96, 0xde, 0x6e, 0x60, 0x23, 0x87, 0xf9, 0xdb, 0x8c, 0x1c, 0x29, 0x27, 0x69, + 0x2e, 0xe1, 0x87, 0xfb, 0x7d, 0xa0, 0xf7, 0xec, 0x8f, 0x0b, 0x77, 0x0e, 0x1a, 0x56, 0x7a, 0xea, + 0xae, 0xf0, 0xd4, 0x26, 0xd4, 0x52, 0x57, 0x03, 0xba, 0x83, 0xdd, 0xb6, 0xd3, 0xe2, 0x9e, 0xc4, + 0x5f, 0x67, 0xc0, 0x6b, 0x49, 0xba, 0x55, 0xb8, 0xde, 0xc7, 0x43, 0x1f, 0xdb, 0x87, 0x17, 0x3e, + 0x38, 0x40, 0x44, 0xe9, 0x29, 0x43, 0x78, 0xea, 0x1e, 0xfc, 0x38, 0x8d, 0xa7, 0xc2, 0xc3, 0xb9, + 0xde, 0x55, 0xc4, 0xbf, 0x14, 0x30, 0xd9, 0x65, 0xd6, 0x02, 0x97, 0xfb, 0x99, 0xd4, 0xf8, 0x8e, + 0xb9, 0xd6, 0x1f, 0x48, 0xfa, 0xfb, 0x15, 0x58, 0xdc, 0xf5, 0x7e, 0xfd, 0x53, 0x91, 0x0d, 0x76, + 0xdc, 0x1c, 0x01, 0xa6, 0x98, 0x4f, 0xed, 0x31, 0xab, 0x28, 0xac, 0xf6, 0x0b, 0x93, 0xbe, 0x7a, + 0xee, 0x32, 0xf6, 0x80, 0xff, 0x8e, 0xfe, 0xf3, 0x45, 0x78, 0x30, 0x01, 0xd7, 0xd2, 0x1f, 0x51, + 0xec, 0x74, 0xa4, 0x70, 0xbd, 0x7f, 0xa0, 0x3e, 0x7a, 0x06, 0x62, 0x96, 0x1f, 0x07, 0x3d, 0xec, + 0x13, 0xf8, 0x67, 0xbf, 0x16, 0x0c, 0xa5, 0xa7, 0x34, 0xb5, 0x60, 0xdc, 0xfc, 0xa5, 0x70, 0x65, + 0xdf, 0xfc, 0xd2, 0xb4, 0x55, 0x61, 0xda, 0x55, 0x78, 0x39, 0x6d, 0x02, 0x8c, 0x44, 0xf1, 0x7f, + 0x15, 0x90, 0xef, 0xd6, 0x51, 0xc3, 0x6b, 0xfb, 0xee, 0x4d, 0x3b, 0x9a, 0xfa, 0xc2, 0x4a, 0x9f, + 0x28, 0xd2, 0xe2, 0x9b, 0xc2, 0xe2, 0x35, 0xb8, 0x92, 0xbe, 0xcb, 0x15, 0x73, 0x80, 0xb0, 0xe1, + 0x95, 0x8f, 0xbe, 0x7c, 0x3e, 0xad, 0x3c, 0x7d, 0x3e, 0xad, 0xfc, 0xf5, 0xf9, 0xb4, 0xf2, 0xe9, + 0x8b, 0xe9, 0x81, 0xa7, 0x2f, 0xa6, 0x07, 0xfe, 0xf8, 0x62, 0x7a, 0xe0, 0xee, 0xa5, 0x1a, 0x61, + 0xdb, 0xbb, 0x5b, 0x25, 0xc3, 0x6e, 0xc8, 0x7f, 0x1f, 0xeb, 0x90, 0x78, 0x3e, 0x90, 0xd8, 0x7c, + 0xab, 0xfc, 0x28, 0x52, 0x74, 0xb7, 0x1c, 0x4c, 0xb7, 0x46, 0xc4, 0x80, 0xe1, 0x3b, 0xff, 0x0b, + 0x00, 0x00, 0xff, 0xff, 0xe4, 0xe9, 0x89, 0x3d, 0xde, 0x27, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -2986,6 +3005,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]) @@ -3278,12 +3311,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 { @@ -4092,6 +4125,18 @@ func (m *QueryConsumerChainResponse) MarshalToSizedBuffer(dAtA []byte) (int, err copy(dAtA[i:], m.ClientId) i = encodeVarintQuery(dAtA, i, uint64(len(m.ClientId))) i-- + dAtA[i] = 0x4a + } + 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 { @@ -4209,12 +4254,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 @@ -4354,6 +4399,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 } @@ -4789,6 +4838,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)) + } l = len(m.ClientId) if l > 0 { n += 1 + l + sovQuery(uint64(l)) @@ -5653,6 +5706,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:]) @@ -8573,6 +8662,42 @@ func (m *QueryConsumerChainResponse) Unmarshal(dAtA []byte) error { } 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 + case 9: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field ClientId", wireType) } 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 {