diff --git a/app/app.go b/app/app.go index cca9e7c28..8b5ac52d9 100644 --- a/app/app.go +++ b/app/app.go @@ -591,6 +591,10 @@ func NewExocoreApp( app.AssetsKeeper, // assets for vote power ) + (&app.OperatorKeeper).SetHooks( + app.StakingKeeper.OperatorHooks(), + ) + (&app.EpochsKeeper).SetHooks( app.StakingKeeper.EpochsHooks(), ) diff --git a/app/ethtest_helper.go b/app/ethtest_helper.go index e4fcdcfaa..44bc857ef 100644 --- a/app/ethtest_helper.go +++ b/app/ethtest_helper.go @@ -4,6 +4,7 @@ import ( "encoding/json" "time" + "cosmossdk.io/math" "cosmossdk.io/simapp" "github.com/cosmos/cosmos-sdk/baseapp" "github.com/cosmos/cosmos-sdk/codec" @@ -252,6 +253,8 @@ func genesisStateWithValSet(codec codec.Codec, genesisState simapp.GenesisState, Power: 1, }, }, + []dogfoodtypes.EpochToOperatorAddrs{}, []dogfoodtypes.EpochToConsensusAddrs{}, + []dogfoodtypes.EpochToUndelegationRecordKeys{}, math.NewInt(1), ) genesisState[dogfoodtypes.ModuleName] = codec.MustMarshalJSON(dogfoodGenesis) diff --git a/app/export.go b/app/export.go index 5e88b207b..20d95fb8d 100644 --- a/app/export.go +++ b/app/export.go @@ -75,14 +75,13 @@ func (app *ExocoreApp) ExportAppStateAndValidators( return servertypes.ExportedApp{}, err } - validators, err := app.StakingKeeper.WriteValidators(ctx) - if err != nil { - return servertypes.ExportedApp{}, err - } + // the x/dogfood validator set is exported in its `val_set` key, and hence, + // does not need to be part of the app export. in other words, we do not + // duplicate the exported validator set. besides, as far as i can tell, the + // SDK does not use the Validators member of the ExportedApp struct. return servertypes.ExportedApp{ AppState: appState, - Validators: validators, Height: height, ConsensusParams: app.BaseApp.GetConsensusParams(ctx), }, nil diff --git a/app/test_helpers.go b/app/test_helpers.go index a2c7191d0..84f1cedda 100644 --- a/app/test_helpers.go +++ b/app/test_helpers.go @@ -10,6 +10,7 @@ import ( "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/crypto" + "cosmossdk.io/math" "cosmossdk.io/simapp" dbm "github.com/cometbft/cometbft-db" abci "github.com/cometbft/cometbft/abci/types" @@ -267,6 +268,8 @@ func GenesisStateWithValSet(app *ExocoreApp, genesisState simapp.GenesisState, delegationGenesis := delegationtypes.NewGenesis(delegationsByStaker) genesisState[delegationtypes.ModuleName] = app.AppCodec().MustMarshalJSON(delegationGenesis) + // create a dogfood genesis with just the validator set, that is, the bare + // minimum valid genesis required to start a chain. dogfoodGenesis := dogfoodtypes.NewGenesis( dogfoodtypes.DefaultParams(), []dogfoodtypes.GenesisValidator{ { @@ -274,6 +277,9 @@ func GenesisStateWithValSet(app *ExocoreApp, genesisState simapp.GenesisState, Power: 1, }, }, + []dogfoodtypes.EpochToOperatorAddrs{}, []dogfoodtypes.EpochToConsensusAddrs{}, + []dogfoodtypes.EpochToUndelegationRecordKeys{}, + math.NewInt(1), // total vote power ) genesisState[dogfoodtypes.ModuleName] = app.AppCodec().MustMarshalJSON(dogfoodGenesis) diff --git a/cmd/exocored/testnet.go b/cmd/exocored/testnet.go index 43e8333b6..77c165446 100644 --- a/cmd/exocored/testnet.go +++ b/cmd/exocored/testnet.go @@ -12,6 +12,7 @@ import ( "sort" "strings" + "cosmossdk.io/math" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" @@ -459,6 +460,7 @@ func getTestExocoreGenesis( Power: power, }) } + totalPower := math.NewInt(power * int64(len(operatorAddrs))) return assetstypes.NewGenesis( assetstypes.DefaultParams(), clientChains, []assetstypes.StakingAssetInfo{ @@ -482,6 +484,10 @@ func getTestExocoreGenesis( []string{assetID}, ), validators, + []dogfoodtypes.EpochToOperatorAddrs{}, + []dogfoodtypes.EpochToConsensusAddrs{}, + []dogfoodtypes.EpochToUndelegationRecordKeys{}, + totalPower, ) } diff --git a/go.mod b/go.mod index 35933663c..1dddb488d 100644 --- a/go.mod +++ b/go.mod @@ -31,6 +31,7 @@ require ( github.com/smartystreets/goconvey v1.6.4 github.com/spf13/cast v1.5.1 github.com/spf13/cobra v1.7.0 + github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.16.0 github.com/stretchr/testify v1.8.4 go.opencensus.io v0.24.0 @@ -40,6 +41,7 @@ require ( golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 google.golang.org/genproto/googleapis/api v0.0.0-20231212172506-995d672761c0 google.golang.org/grpc v1.60.1 + google.golang.org/protobuf v1.33.0 gopkg.in/yaml.v2 v2.4.0 sigs.k8s.io/yaml v1.3.0 ) @@ -201,7 +203,6 @@ require ( github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d // indirect github.com/spf13/afero v1.10.0 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect - github.com/spf13/pflag v1.0.5 // indirect github.com/status-im/keycard-go v0.2.0 // indirect github.com/subosito/gotenv v1.4.2 // indirect github.com/supranational/blst v0.3.11 // indirect @@ -232,7 +233,6 @@ require ( google.golang.org/appengine v1.6.8 // indirect google.golang.org/genproto v0.0.0-20240102182953-50ed04b92917 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240108191215-35c7eff3a6b1 // indirect - google.golang.org/protobuf v1.33.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/local_node.sh b/local_node.sh index a6df40561..a9446c33a 100755 --- a/local_node.sh +++ b/local_node.sh @@ -115,10 +115,11 @@ if [[ $overwrite == "y" || $overwrite == "Y" ]]; then jq '.app_state["delegation"]["delegations"][0]["delegations"][0]["per_operator_amounts"][0]["value"]["amount"]="5000"' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" # x/dogfood - jq '.app_state["dogfood"]["initial_val_set"][0]["public_key"]="0xf0f6919e522c5b97db2c8255bff743f9dfddd7ad9fc37cb0c1670b480d0f9914"' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" - jq '.app_state["dogfood"]["initial_val_set"][0]["power"]="5000"' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" + jq '.app_state["dogfood"]["val_set"][0]["public_key"]="0xf0f6919e522c5b97db2c8255bff743f9dfddd7ad9fc37cb0c1670b480d0f9914"' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" + jq '.app_state["dogfood"]["val_set"][0]["power"]="5000"' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" # change the epoch to an hour when starting a local node, which facilitates the testing. jq '.app_state["dogfood"]["params"]["epoch_identifier"]="hour"' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" + jq '.app_state["dogfood"]["last_total_power"]="5000"' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" # x/epochs HOUR_EPOCH='{ diff --git a/proto/exocore/dogfood/v1/genesis.proto b/proto/exocore/dogfood/v1/genesis.proto index c81b3070c..ee2005560 100644 --- a/proto/exocore/dogfood/v1/genesis.proto +++ b/proto/exocore/dogfood/v1/genesis.proto @@ -2,24 +2,78 @@ syntax = "proto3"; package exocore.dogfood.v1; +import "amino/amino.proto"; import "gogoproto/gogo.proto"; import "exocore/dogfood/v1/params.proto"; option go_package = "github.com/ExocoreNetwork/exocore/x/dogfood/types"; -// GenesisState defines the dogfood module's genesis state. +// GenesisState defines the dogfood module's genesis state. Note that, as always, +// `genesis` is a misnomer. Ideally, this state can be exported at any point in +// time (or height), and reimported elsewhere where it will be the new genesis +// potentially at a non-zero height. In other words, it is the entire, current, +// state of the module. message GenesisState { // params refers to the parameters of the module. Params params = 1 [(gogoproto.nullable) = false]; - // initial_val_set is the initial validator set. - repeated GenesisValidator initial_val_set = 2 + // val_set is the initial validator set. it onyl represents the active + // validators. + repeated GenesisValidator val_set = 2 [ (gogoproto.nullable) = false ]; + + // opt_out_expiries is a list of (future) epochs at the end of which the + // corresponding operators' opt-out will expire. we store this, as well as its reverse + // lookup. + repeated EpochToOperatorAddrs opt_out_expiries = 3 + [ (gogoproto.nullable) = false ]; + + // epochs_consensus_addrs is a list of epochs at the end of which the corresponding + // consensus addresses should be pruned from the operator module. + repeated EpochToConsensusAddrs consensus_addrs_to_prune = 4 + [ (gogoproto.nullable) = false ]; + + // undelegation_maturities is a list of epochs at the end of which the corresponding + // undelegations will mature. we store its reverse lookup as well. + repeated EpochToUndelegationRecordKeys undelegation_maturities = 5 + [ (gogoproto.nullable) = false ]; + + // data against HistoricalInfoBytePrefix is not made available in the module + // state for import / export. this is in line with Cosmos SDK. + + // the data indexed by the pending keys is created within the epochs hooks + // which happen in the BeginBlocker. it is applied during the EndBlocker and + // then immediately cleared. + // remember that data can be exported from a node that is stopped. + // a node can be stopped only if it has committed a block. if a full + // block is committed, data that is saved to state during BeginBlock + // and cleared at EndBlock will not be available. hence, we don't need + // to make data for any of the `pending` keys available here. + + // last_total_power tracks the total voting power as of the last validator set + // update. such an update is most likely to be at the end of the last epoch (or the + // beginning of this one, to be more precise) and less likely to be at other blocks, + // since the validator set can otherwise only change as a result of slashing events. + bytes last_total_power = 6 [ + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", + (gogoproto.nullable) = false, + (amino.dont_omitempty) = true + ]; + + // validator_updates is a list of validator updates applied at the end of the previous + // block. it is then cleared at the end of the next block, and hence, is available + // for other modules to access during that block. however, for a new chain, it does + // not make sense for it to exist, since all of the validators should be considered + // as an update. this behaviour is the same as the Cosmos SDK. } // GenesisValidator defines a genesis validator. It is a helper struct -// used for serializing the genesis state. +// used for serializing the genesis state. The only reason it is a different +// structure is to support importing hex public keys from Solidity. +// TODO: consider this set up when resolving issue 73 about storage +// optimization between dogfood and operator modules. +// https://github.com/ExocoreNetwork/exocore/issues/73 message GenesisValidator { // public_key is the consensus public key of the validator. It should // be exactly 32 bytes, but this is not enforced in protobuf. @@ -27,3 +81,34 @@ message GenesisValidator { // power is the voting power of the validator. int64 power = 2; } + +// EpochToOperatorAddress is used to store a mapping from epoch to a list of +// operator account addresses. +message EpochToOperatorAddrs { + // epoch is the epoch in question. + int64 epoch = 1; + // operator_acc_addrs is the list of account addresses to expire at this epoch. + // It is of type string for human readability of the genesis file. + repeated string operator_acc_addrs = 2; +} + +// EpochToConsensusAddrs is used to store a mapping from the epoch to a list of +// consensus addresses. +message EpochToConsensusAddrs { + // epoch is the epoch in question. + int64 epoch = 1; + // cons_addrs is the list of consensus addresses to prune at this epoch. + // It is of type string for human readability of the genesis file. + repeated string cons_addrs = 2; +} + +// EpochToUndelegationRecordKeys is used to store a mapping from an epoch to a list of +// undelegations which mature at that epoch. +message EpochToUndelegationRecordKeys { + // epoch is the epoch in question. + int64 epoch = 1; + // undelegation_record_keys is the list of undelegations (defined by the record key) + // to expire at this epoch. + // It is of type string for human readability of the genesis file. + repeated string undelegation_record_keys = 2; +} \ No newline at end of file diff --git a/proto/exocore/operator/v1/query.proto b/proto/exocore/operator/v1/query.proto index e04768f28..757d093c8 100644 --- a/proto/exocore/operator/v1/query.proto +++ b/proto/exocore/operator/v1/query.proto @@ -45,6 +45,8 @@ message QueryOperatorConsKeyRequest { message QueryOperatorConsKeyResponse { // public_key is the consensus public key of the operator. tendermint.crypto.PublicKey public_key = 1 [ (gogoproto.nullable) = false ]; + // opting_out is a flag to indicate if the operator is opting out of consensus. + bool opting_out = 2; } // QueryOperatorConsAddressRequest is the request to obtain the consensus address of the operator @@ -63,6 +65,8 @@ message QueryOperatorConsAddressResponse { // cons_addr is the consensus address corresponding to the consensus public key // currently in use by the operator. string cons_addr = 1; + // opting_out is a flag to indicate if the operator is opting out of consensus. + bool opting_out = 2; } // QueryAllOperatorConsKeysByChainIDRequest is the request to obtain all operator addresses @@ -92,6 +96,8 @@ message OperatorConsKeyPair { string operator_acc_addr = 1; // public_key is the consensus public key of the operator. tendermint.crypto.PublicKey public_key = 2; + // opting_out is a flag to indicate if the operator is opting out of consensus. + bool opting_out = 3; } // QueryAllOperatorConsAddrsByChainIDRequest is the request to obtain all operator addresses @@ -121,6 +127,8 @@ message OperatorConsAddrPair { // cons_addr is the consensus address corresponding to the consensus public key // currently in use by the operator. string cons_addr = 2; + // opting_out is a flag to indicate if the operator is opting out of consensus. + bool opting_out = 3; } // Query defines the gRPC querier service. diff --git a/proto/exocore/operator/v1/tx.proto b/proto/exocore/operator/v1/tx.proto index 51375767b..889a7ac4e 100644 --- a/proto/exocore/operator/v1/tx.proto +++ b/proto/exocore/operator/v1/tx.proto @@ -145,6 +145,9 @@ message OptIntoAVSReq { [(cosmos_proto.scalar) = "cosmos.AddressString"]; // avs_address is the address of the AVS - either an 0x address or a chainID. string avs_address = 2; + // optional parameter to provide the consensus key or the BLS key, depending + // on the AVS. we still have to design this fully. + string public_key = 3; } // OptIntoAVSResponse is the response to a opt into an AVS request. @@ -187,33 +190,16 @@ message SetConsKeyReq { // SetConsKeyResponse is the response to SetConsKeyReq. message SetConsKeyResponse {} -// InitConsKeyRemovalReq is the request for an operator to stop validating on a chain. It -// allows the operator to remove their consensus key from the specified chain. It must be -// followed by a separate call to OptOutOfAVS to remove the operator from the AVS. -message InitConsKeyRemovalReq { - option (cosmos.msg.v1.signer) = "address"; - option (amino.name) = "cosmos-sdk/InitConsKeyRemovalReq"; - option (gogoproto.equal) = false; - option (gogoproto.goproto_getters) = false; - // address is the operator address - string address = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"]; - // chain_id is the identifier for the chain that wants to opt out. - string chain_id = 2 [(gogoproto.customname) = "ChainID"]; -} - -// InitConsKeyRemovalResponse defines the InitConsKeyRemovalReq response. -message InitConsKeyRemovalResponse {} - // Msg defines the operator Msg service. service Msg { option (cosmos.msg.v1.service) = true; // RegisterOperator registers a new operator. rpc RegisterOperator(RegisterOperatorReq) returns (RegisterOperatorResponse); - // SetConsKey sets the operator's consensus key for a chain. + // SetConsKey sets the operator's consensus key for a chain. To do this, the operator + // must have previously opted into the chain. + // TODO; rationalize this with non-chain AVSs wherein other keys can be set. rpc SetConsKey(SetConsKeyReq) returns (SetConsKeyResponse) {}; - // InitConsKeyRemoval removes the operator's consensus key for a chain. - rpc InitConsKeyRemoval(InitConsKeyRemovalReq) returns (InitConsKeyRemovalResponse) {}; // OptIntoAVS opts an operator into an AVS. rpc OptIntoAVS(OptIntoAVSReq) returns (OptIntoAVSResponse); diff --git a/testutil/utils.go b/testutil/utils.go index 82a4d53bd..a1ad89754 100644 --- a/testutil/utils.go +++ b/testutil/utils.go @@ -229,6 +229,8 @@ func (suite *BaseTestSuite) SetupWithGenesisValSet(genAccs []authtypes.GenesisAc delegationGenesis := delegationtypes.NewGenesis(delegationsByStaker) genesisState[delegationtypes.ModuleName] = app.AppCodec().MustMarshalJSON(delegationGenesis) + // create a dogfood genesis with just the validator set, that is, the bare + // minimum valid genesis required to start a chain. dogfoodGenesis := dogfoodtypes.NewGenesis( dogfoodtypes.DefaultParams(), []dogfoodtypes.GenesisValidator{ { @@ -240,6 +242,10 @@ func (suite *BaseTestSuite) SetupWithGenesisValSet(genAccs []authtypes.GenesisAc Power: 1, }, }, + []dogfoodtypes.EpochToOperatorAddrs{}, + []dogfoodtypes.EpochToConsensusAddrs{}, + []dogfoodtypes.EpochToUndelegationRecordKeys{}, + math.NewInt(2), // must match total vote power ) genesisState[dogfoodtypes.ModuleName] = app.AppCodec().MustMarshalJSON(dogfoodGenesis) diff --git a/x/delegation/keeper/genesis.go b/x/delegation/keeper/genesis.go index 7dd1577bd..9f029d661 100644 --- a/x/delegation/keeper/genesis.go +++ b/x/delegation/keeper/genesis.go @@ -1,6 +1,7 @@ package keeper import ( + errorsmod "cosmossdk.io/errors" assetstype "github.com/ExocoreNetwork/exocore/x/assets/types" delegationtype "github.com/ExocoreNetwork/exocore/x/delegation/types" abci "github.com/cometbft/cometbft/abci/types" @@ -44,7 +45,7 @@ func (k Keeper) InitGenesis( // they are the LzNonce and TxHash } if err := k.delegateTo(ctx, delegationParams, false); err != nil { - panic(err) + panic(errorsmod.Wrap(err, "failed to delegate to operator")) } } } diff --git a/x/delegation/types/keys.go b/x/delegation/types/keys.go index 3f5bdfc83..9fb5ba84a 100644 --- a/x/delegation/types/keys.go +++ b/x/delegation/types/keys.go @@ -4,6 +4,7 @@ import ( "strings" assetstypes "github.com/ExocoreNetwork/exocore/x/assets/types" + sdk "github.com/cosmos/cosmos-sdk/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" @@ -74,6 +75,8 @@ func ParseStakerAssetIDAndOperatorAddrFromKey(key []byte) (keys *SingleDelegatio return &SingleDelegationInfoReq{StakerID: stringList[0], AssetID: stringList[1], OperatorAddr: stringList[2]}, nil } +// GetUndelegationRecordKey returns the key for the undelegation record. The caller must ensure that the parameters +// are valid; this function performs no validation whatsoever. func GetUndelegationRecordKey(blockHeight, lzNonce uint64, txHash string, operatorAddr string) []byte { return []byte(strings.Join([]string{operatorAddr, hexutil.EncodeUint64(blockHeight), hexutil.EncodeUint64(lzNonce), txHash}, "/")) } @@ -90,6 +93,10 @@ func ParseUndelegationRecordKey(key []byte) (field *UndelegationKeyFields, err e if err != nil { return nil, err } + operatorAccAddr, err := sdk.AccAddressFromBech32(stringList[0]) + if err != nil { + return nil, err + } height, err := hexutil.DecodeUint64(stringList[1]) if err != nil { return nil, err @@ -99,10 +106,11 @@ func ParseUndelegationRecordKey(key []byte) (field *UndelegationKeyFields, err e return nil, err } return &UndelegationKeyFields{ - OperatorAddr: stringList[0], + OperatorAddr: operatorAccAddr.String(), BlockHeight: height, LzNonce: lzNonce, - TxHash: stringList[3], + // TODO: validate the TxHash? + TxHash: stringList[3], }, nil } diff --git a/x/dogfood/keeper/genesis.go b/x/dogfood/keeper/genesis.go index b26d45bef..4d4557d93 100644 --- a/x/dogfood/keeper/genesis.go +++ b/x/dogfood/keeper/genesis.go @@ -6,7 +6,10 @@ import ( "github.com/ExocoreNetwork/exocore/x/dogfood/types" operatortypes "github.com/ExocoreNetwork/exocore/x/operator/types" abci "github.com/cometbft/cometbft/abci/types" + cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" sdk "github.com/cosmos/cosmos-sdk/types" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + "github.com/ethereum/go-ethereum/common/hexutil" ) // InitGenesis initializes the module's state from a provided genesis state. @@ -19,7 +22,7 @@ func (k Keeper) InitGenesis( // so, it must be done here. by extension, the `InitGenesis` of the epochs module // should be called before that of this module. epochID := genState.Params.EpochIdentifier - _, found := k.epochsKeeper.GetEpochInfo(ctx, epochID) + epochInfo, found := k.epochsKeeper.GetEpochInfo(ctx, epochID) if !found { // the panic is suitable here because it is being done at genesis, when the node // is not running. it means that the genesis file is malformed. @@ -35,9 +38,8 @@ func (k Keeper) InitGenesis( // validator. this is because the operator may not have enough minimum self delegation // to be considered, or may not be in the top N operators. so checking that count here // is meaningless as well. - totalPower := sdk.NewInt(0) - out := make([]abci.ValidatorUpdate, 0, len(genState.InitialValSet)) - for _, val := range genState.InitialValSet { + out := make([]abci.ValidatorUpdate, 0, len(genState.ValSet)) + for _, val := range genState.ValSet { // #nosec G703 // already validated consKey, _ := operatortypes.HexStringToPubKey(val.PublicKey) // #nosec G703 // this only fails if the key is of a type not already defined. @@ -55,9 +57,47 @@ func (k Keeper) InitGenesis( PubKey: *consKey, Power: val.Power, }) - totalPower = totalPower.Add(sdk.NewInt(val.Power)) } - k.SetLastTotalPower(ctx, totalPower) + for i := range genState.OptOutExpiries { + obj := genState.OptOutExpiries[i] + epoch := obj.Epoch + if epoch < epochInfo.CurrentEpoch { + panic(fmt.Sprintf("epoch %d is in the past", epoch)) + } + for _, addr := range obj.OperatorAccAddrs { + // #nosec G703 // already validated + operatorAddr, _ := sdk.AccAddressFromBech32(addr) + k.AppendOptOutToFinish(ctx, epoch, operatorAddr) + k.SetOperatorOptOutFinishEpoch(ctx, operatorAddr, epoch) + } + } + for i := range genState.ConsensusAddrsToPrune { + obj := genState.ConsensusAddrsToPrune[i] + epoch := obj.Epoch + if epoch < epochInfo.CurrentEpoch { + panic(fmt.Sprintf("epoch %d is in the past", epoch)) + } + for _, addr := range obj.ConsAddrs { + // #nosec G703 // already validated + accAddr, _ := sdk.ConsAddressFromBech32(addr) + k.AppendConsensusAddrToPrune(ctx, epoch, accAddr) + } + } + for i := range genState.UndelegationMaturities { + obj := genState.UndelegationMaturities[i] + epoch := obj.Epoch + if epoch < epochInfo.CurrentEpoch { + panic(fmt.Sprintf("epoch %d is in the past", epoch)) + } + for _, recordKey := range obj.UndelegationRecordKeys { + // #nosec G703 // already validated + recordKeyBytes, _ := hexutil.Decode(recordKey) + k.AppendUndelegationToMature(ctx, epoch, recordKeyBytes) + k.SetUndelegationMaturityEpoch(ctx, recordKeyBytes, epoch) + } + } + // ApplyValidatorChanges only gets changes and hence the vote power must be set here. + k.SetLastTotalPower(ctx, genState.LastTotalPower) // ApplyValidatorChanges will sort it internally return k.ApplyValidatorChanges( @@ -69,6 +109,26 @@ func (k Keeper) InitGenesis( func (k Keeper) ExportGenesis(ctx sdk.Context) *types.GenesisState { genesis := types.DefaultGenesis() genesis.Params = k.GetDogfoodParams(ctx) - // TODO(mm) - return genesis + validators := []types.GenesisValidator{} + k.IterateBondedValidatorsByPower(ctx, func(_ int64, val stakingtypes.ValidatorI) bool { + // #nosec G703 // already validated + pubKey, _ := val.ConsPubKey() + // #nosec G703 // already validated + convKey, _ := cryptocodec.ToTmPubKeyInterface(pubKey) + validators = append(validators, + types.GenesisValidator{ + PublicKey: hexutil.Encode(convKey.Bytes()), + Power: val.GetConsensusPower(sdk.DefaultPowerReduction), + }, + ) + return false /* stop */ + }) + return types.NewGenesis( + k.GetDogfoodParams(ctx), + validators, + k.GetAllOptOutsToFinish(ctx), + k.GetAllConsAddrsToPrune(ctx), + k.GetAllUndelegationsToMature(ctx), + k.GetLastTotalPower(ctx), + ) } diff --git a/x/dogfood/keeper/impl_sdk.go b/x/dogfood/keeper/impl_sdk.go index f6bbd2a2f..b4aedf176 100644 --- a/x/dogfood/keeper/impl_sdk.go +++ b/x/dogfood/keeper/impl_sdk.go @@ -4,10 +4,7 @@ import ( "sort" "cosmossdk.io/math" - operatortypes "github.com/ExocoreNetwork/exocore/x/operator/types" abci "github.com/cometbft/cometbft/abci/types" - tmtypes "github.com/cometbft/cometbft/types" - cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" sdk "github.com/cosmos/cosmos-sdk/types" evidencetypes "github.com/cosmos/cosmos-sdk/x/evidence/types" genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types" @@ -179,7 +176,7 @@ func (k Keeper) ApplyAndReturnValidatorSetUpdates( // IterateBondedValidatorsByPower is an implementation of the staking interface expected by // the SDK's gov module and by our oracle module. func (k Keeper) IterateBondedValidatorsByPower( - ctx sdk.Context, f func(int64, stakingtypes.ValidatorI) bool, + ctx sdk.Context, f func(int64, stakingtypes.ValidatorI) (stop bool), ) { // this is the bonded validators, that is, those that are currently in this module. prevList := k.GetAllExocoreValidators(ctx) @@ -189,13 +186,14 @@ func (k Keeper) IterateBondedValidatorsByPower( for i, v := range prevList { pk, err := v.ConsPubKey() if err != nil { - // will only happen if there is an error in deserialization. + ctx.Logger().Error("Failed to deserialize public key; skipping", "error", err, "i", i) continue } val, found := k.operatorKeeper.ValidatorByConsAddrForChainID( ctx, sdk.GetConsAddress(pk), ctx.ChainID(), ) if !found { + ctx.Logger().Error("Operator address not found; skipping", "consAddress", sdk.GetConsAddress(pk), "i", i) continue } // the voting power is fetched from this module and not the operator module @@ -227,43 +225,3 @@ func (k Keeper) IterateDelegations( ) { panic("unimplemented on this keeper") } - -// WriteValidators returns all the currently active validators. This is called by the export -// CLI. which must ensure that `ctx.ChainID()` is set. -func (k Keeper) WriteValidators( - ctx sdk.Context, -) ([]tmtypes.GenesisValidator, error) { - validators := k.GetAllExocoreValidators(ctx) - sort.SliceStable(validators, func(i, j int) bool { - return validators[i].Power > validators[j].Power - }) - vals := make([]tmtypes.GenesisValidator, len(validators)) - var retErr error - for i, val := range validators { - pk, err := val.ConsPubKey() - if err != nil { - retErr = err - break - } - tmPk, err := cryptocodec.ToTmPubKeyInterface(pk) - if err != nil { - retErr = err - break - } - consAddress := sdk.GetConsAddress(pk) - found, addr := k.operatorKeeper.GetOperatorAddressForChainIDAndConsAddr( - ctx, ctx.ChainID(), consAddress, - ) - if !found { - retErr = operatortypes.ErrNoKeyInTheStore - break - } - vals[i] = tmtypes.GenesisValidator{ - Address: consAddress.Bytes(), - PubKey: tmPk, - Power: val.Power, - Name: addr.String(), // TODO - } - } - return vals, retErr -} diff --git a/x/dogfood/keeper/opt_out.go b/x/dogfood/keeper/opt_out.go index 8a9352b88..0c6299bca 100644 --- a/x/dogfood/keeper/opt_out.go +++ b/x/dogfood/keeper/opt_out.go @@ -5,6 +5,17 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) +// SetOptOutInformation sets information related to an operator's opt out. +func (k Keeper) SetOptOutInformation( + ctx sdk.Context, addr sdk.AccAddress, +) { + unbondingCompletionEpoch := k.GetUnbondingCompletionEpoch(ctx) + k.AppendOptOutToFinish(ctx, unbondingCompletionEpoch, addr) + k.SetOperatorOptOutFinishEpoch(ctx, addr, unbondingCompletionEpoch) + // CompleteOperatorKeyRemovalForChainID calls DeleteOperatorAddressForChainIDAndConsAddr, + // so we do not need to save ConsensusAddrToPrune in the unbonding case. +} + // AppendOptOutToFinish appends an operator address to the list of operator addresses that have // opted out and will be finished at the end of the provided epoch. func (k Keeper) AppendOptOutToFinish( @@ -56,6 +67,33 @@ func (k Keeper) ClearOptOutsToFinish(ctx sdk.Context, epoch int64) { store.Delete(key) } +// GetAllOptOutsToFinish gets a list of epochs and the corresponding operator addresses +// whose opt outs are scheduled to finish at the end of those epochs. It is ordered, +// first by the epoch and then by the operator address bytes. +func (k Keeper) GetAllOptOutsToFinish(ctx sdk.Context) []types.EpochToOperatorAddrs { + store := ctx.KVStore(k.storeKey) + iterator := sdk.KVStorePrefixIterator(store, []byte{types.OptOutsToFinishBytePrefix}) + defer iterator.Close() + + res := []types.EpochToOperatorAddrs{} + + for ; iterator.Valid(); iterator.Next() { + epoch, _ := types.SafeUint64ToInt64(sdk.BigEndianToUint64(iterator.Key()[1:])) + var addrs types.AccountAddresses + k.cdc.MustUnmarshal(iterator.Value(), &addrs) + subRes := []string{} + for _, addr := range addrs.GetList() { + subRes = append(subRes, sdk.AccAddress(addr).String()) + } + res = append(res, types.EpochToOperatorAddrs{ + Epoch: epoch, + OperatorAccAddrs: subRes, + }) + } + + return res +} + // SetOperatorOptOutFinishEpoch sets the epoch at which an operator's opt out will be finished. func (k Keeper) SetOperatorOptOutFinishEpoch( ctx sdk.Context, operatorAddr sdk.AccAddress, epoch int64, @@ -142,3 +180,30 @@ func (k Keeper) setConsensusAddrsToPrune( } store.Set(key, bz) } + +// GetAllConsAddrsToPrune gets a list of epochs and the corresponding consensus addresses +// which should be pruned from the operator module at the end of that epoch. It is ordered, +// first by the epoch and then by the consensus address bytes. +func (k Keeper) GetAllConsAddrsToPrune(ctx sdk.Context) []types.EpochToConsensusAddrs { + store := ctx.KVStore(k.storeKey) + iterator := sdk.KVStorePrefixIterator(store, []byte{types.OptOutsToFinishBytePrefix}) + defer iterator.Close() + + res := []types.EpochToConsensusAddrs{} + + for ; iterator.Valid(); iterator.Next() { + epoch, _ := types.SafeUint64ToInt64(sdk.BigEndianToUint64(iterator.Key()[1:])) + var addrs types.ConsensusAddresses + k.cdc.MustUnmarshal(iterator.Value(), &addrs) + subRes := []string{} + for _, addr := range addrs.GetList() { + subRes = append(subRes, sdk.ConsAddress(addr).String()) + } + res = append(res, types.EpochToConsensusAddrs{ + Epoch: epoch, + ConsAddrs: subRes, + }) + } + + return res +} diff --git a/x/dogfood/keeper/query.go b/x/dogfood/keeper/query.go index 6bf6bfe73..0208d7632 100644 --- a/x/dogfood/keeper/query.go +++ b/x/dogfood/keeper/query.go @@ -2,7 +2,6 @@ package keeper import ( "context" - "encoding/hex" "github.com/ExocoreNetwork/exocore/x/dogfood/types" "google.golang.org/grpc/codes" @@ -93,11 +92,11 @@ func (k Keeper) QueryValidator( } ctx := sdk.UnwrapSDKContext(goCtx) consAddress := req.ConsAddr - consAddressbytes, err := hex.DecodeString(consAddress) + consAddressBytes, err := sdk.ConsAddressFromBech32(consAddress) if err != nil { return nil, status.Error(codes.InvalidArgument, "invalid consensus address") } - validator, found := k.GetExocoreValidator(ctx, consAddressbytes) + validator, found := k.GetExocoreValidator(ctx, consAddressBytes) if !found { return nil, status.Error(codes.NotFound, "validator not found") } diff --git a/x/dogfood/keeper/unbonding.go b/x/dogfood/keeper/unbonding.go index 45caaa0d2..3bc21dd22 100644 --- a/x/dogfood/keeper/unbonding.go +++ b/x/dogfood/keeper/unbonding.go @@ -3,19 +3,9 @@ package keeper import ( "github.com/ExocoreNetwork/exocore/x/dogfood/types" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/ethereum/go-ethereum/common/hexutil" ) -// SetOptOutInformation sets information related to an operator's opt out. -func (k Keeper) SetOptOutInformation( - ctx sdk.Context, addr sdk.AccAddress, -) { - unbondingCompletionEpoch := k.GetUnbondingCompletionEpoch(ctx) - k.AppendOptOutToFinish(ctx, unbondingCompletionEpoch, addr) - k.SetOperatorOptOutFinishEpoch(ctx, addr, unbondingCompletionEpoch) - // CompleteOperatorKeyRemovalForChainID calls DeleteOperatorAddressForChainIDAndConsAddr, - // so we do not need to save ConsensusAddrToPrune in the unbonding case. -} - // GetUnbondingCompletionEpoch returns the epoch at the end of which // an unbonding triggered in this epoch will be completed. func (k Keeper) GetUnbondingCompletionEpoch( @@ -87,6 +77,33 @@ func (k Keeper) setUndelegationsToMature( store.Set(key, val) } +// GetAllUndelegationsToMature gets a list of epochs and the corresponding undelegation record +// keys which are scheduled to mature at the end of that epoch. It is ordered, first by the +// epoch and then by the record key's bytes. +func (k Keeper) GetAllUndelegationsToMature(ctx sdk.Context) []types.EpochToUndelegationRecordKeys { + store := ctx.KVStore(k.storeKey) + iterator := sdk.KVStorePrefixIterator(store, []byte{types.OptOutsToFinishBytePrefix}) + defer iterator.Close() + + res := []types.EpochToUndelegationRecordKeys{} + + for ; iterator.Valid(); iterator.Next() { + epoch, _ := types.SafeUint64ToInt64(sdk.BigEndianToUint64(iterator.Key()[1:])) + var recordKeys types.UndelegationRecordKeys + k.cdc.MustUnmarshal(iterator.Value(), &recordKeys) + subRes := []string{} + for _, recordKey := range recordKeys.GetList() { + subRes = append(subRes, hexutil.Encode(recordKey)) + } + res = append(res, types.EpochToUndelegationRecordKeys{ + Epoch: epoch, + UndelegationRecordKeys: subRes, + }) + } + + return res +} + // GetUndelegationMaturityEpoch gets the maturity epoch for the undelegation record. func (k Keeper) GetUndelegationMaturityEpoch( ctx sdk.Context, recordKey []byte, diff --git a/x/dogfood/types/genesis.go b/x/dogfood/types/genesis.go index 792e300f2..619b6b1d5 100644 --- a/x/dogfood/types/genesis.go +++ b/x/dogfood/types/genesis.go @@ -2,22 +2,43 @@ package types import ( errorsmod "cosmossdk.io/errors" + "cosmossdk.io/math" + delegationtypes "github.com/ExocoreNetwork/exocore/x/delegation/types" operatortypes "github.com/ExocoreNetwork/exocore/x/operator/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/ethereum/go-ethereum/common/hexutil" ) // NewGenesis creates a new genesis state with the provided parameters and -// validators. -func NewGenesis(params Params, vals []GenesisValidator) *GenesisState { +// data. +func NewGenesis( + params Params, + vals []GenesisValidator, + expiries []EpochToOperatorAddrs, + consAddrs []EpochToConsensusAddrs, + recordKeys []EpochToUndelegationRecordKeys, + power math.Int, +) *GenesisState { return &GenesisState{ - Params: params, - InitialValSet: vals, + Params: params, + ValSet: vals, + OptOutExpiries: expiries, + ConsensusAddrsToPrune: consAddrs, + UndelegationMaturities: recordKeys, + LastTotalPower: power, } } // DefaultGenesis returns the default genesis state. func DefaultGenesis() *GenesisState { - // no initial validators intentionally, so that the caller must set them. - return NewGenesis(DefaultParams(), []GenesisValidator{}) + return NewGenesis( + DefaultParams(), + []GenesisValidator{}, + []EpochToOperatorAddrs{}, + []EpochToConsensusAddrs{}, + []EpochToUndelegationRecordKeys{}, + math.ZeroInt(), + ) } // Validate performs basic genesis state validation returning an error upon any @@ -25,16 +46,17 @@ func DefaultGenesis() *GenesisState { func (gs GenesisState) Validate() error { // #nosec G701 // ok on 64-bit systems. maxValidators := int(gs.Params.MaxValidators) - if len(gs.InitialValSet) > maxValidators { + if len(gs.ValSet) > maxValidators { return errorsmod.Wrapf( ErrInvalidGenesisData, "too many validators %d", - len(gs.InitialValSet), + len(gs.ValSet), ) } // do not complain about 0 validators, let Tendermint do that. - vals := make(map[string]struct{}, len(gs.InitialValSet)) - for _, val := range gs.InitialValSet { + vals := make(map[string]struct{}, len(gs.ValSet)) + totalPower := int64(0) + for _, val := range gs.ValSet { // check for duplicates if _, ok := vals[val.PublicKey]; ok { return errorsmod.Wrapf( @@ -63,6 +85,170 @@ func (gs GenesisState) Validate() error { power, ) } + totalPower += power + } + + // we don't know the current epoch, since this is stateless validation. + // to check epoochs aren't duplicated. + epochs := make(map[int64]struct{}, len(gs.OptOutExpiries)) + // to check that there is no duplicate address - not by per epoch but overall. + addrsMap := make(map[string]struct{}) + for _, obj := range gs.OptOutExpiries { + epoch := obj.Epoch + if _, ok := epochs[epoch]; ok { + return errorsmod.Wrapf( + ErrInvalidGenesisData, + "duplicate epoch %d", epoch, + ) + } + // the first epoch in the epochs module is 1. this epoch is first + // incremented, and then AfterEpochEnd is called with a value of 2. + // therefore, the first epoch in the dogfood module is 2. all expiries + // must happen at the end of this epoch or any epoch thereafter. + // TODO: we should fix this bug in our fork of the epochs module. + if epoch <= 1 { + return errorsmod.Wrapf( + ErrInvalidGenesisData, + "epoch %d should be > 1", epoch, + ) + } + epochs[epoch] = struct{}{} + addrs := obj.OperatorAccAddrs + if len(addrs) == 0 { + return errorsmod.Wrapf( + ErrInvalidGenesisData, + "empty operator addresses for epoch %d", epoch, + ) + } + for _, addr := range addrs { + if _, err := sdk.AccAddressFromBech32(addr); err != nil { + return errorsmod.Wrapf( + ErrInvalidGenesisData, + "invalid operator address %s: %s", + addr, err, + ) + } + if _, ok := addrsMap[addr]; ok { + return errorsmod.Wrapf( + ErrInvalidGenesisData, + "duplicate operator address %s", addr, + ) + } + addrsMap[addr] = struct{}{} + } + } + + epochs = make(map[int64]struct{}, len(gs.ConsensusAddrsToPrune)) + addrsMap = make(map[string]struct{}) + for _, obj := range gs.ConsensusAddrsToPrune { + epoch := obj.Epoch + if _, ok := epochs[epoch]; ok { + return errorsmod.Wrapf( + ErrInvalidGenesisData, + "duplicate epoch %d", epoch, + ) + } + epochs[epoch] = struct{}{} + if epoch <= 1 { + return errorsmod.Wrapf( + ErrInvalidGenesisData, + "epoch %d should be > 1", epoch, + ) + } + addrs := obj.ConsAddrs + if len(addrs) == 0 { + return errorsmod.Wrapf( + ErrInvalidGenesisData, + "empty consensus addresses for epoch %d", epoch, + ) + } + for _, addr := range addrs { + if _, err := sdk.ConsAddressFromBech32(addr); err != nil { + return errorsmod.Wrapf( + ErrInvalidGenesisData, + "invalid consensus address %s: %s", + addr, err, + ) + } + if _, ok := addrsMap[addr]; ok { + return errorsmod.Wrapf( + ErrInvalidGenesisData, + "duplicate consensus address %s", addr, + ) + } + addrsMap[addr] = struct{}{} + } + } + + epochs = make(map[int64]struct{}, len(gs.UndelegationMaturities)) + recordKeysMap := make(map[string]struct{}) + for _, obj := range gs.UndelegationMaturities { + epoch := obj.Epoch + if _, ok := epochs[epoch]; ok { + return errorsmod.Wrapf( + ErrInvalidGenesisData, + "duplicate epoch %d", epoch, + ) + } + if epoch <= 1 { + return errorsmod.Wrapf( + ErrInvalidGenesisData, + "epoch %d should be > 1", epoch, + ) + } + epochs[epoch] = struct{}{} + recordKeys := obj.UndelegationRecordKeys + if len(recordKeys) == 0 { + return errorsmod.Wrapf( + ErrInvalidGenesisData, + "empty record keys for epoch %d", epoch, + ) + } + for _, recordKey := range recordKeys { + if _, ok := recordKeysMap[recordKey]; ok { + return errorsmod.Wrapf( + ErrInvalidGenesisData, + "duplicate record key %s", recordKey, + ) + } + if recordBytes, err := hexutil.Decode(recordKey); err != nil { + return errorsmod.Wrapf( + ErrInvalidGenesisData, + "invalid record key (non hex) %s: %s", + recordKey, err, + ) + } else if _, err := delegationtypes.ParseUndelegationRecordKey(recordBytes); err != nil { + return errorsmod.Wrapf( + ErrInvalidGenesisData, + "invalid record key (parse) %s: %s", + recordKey, err, + ) + } + recordKeysMap[recordKey] = struct{}{} + } + } + + if gs.LastTotalPower.IsNil() { + return errorsmod.Wrapf( + ErrInvalidGenesisData, + "nil last total power", + ) + } + + if !gs.LastTotalPower.IsPositive() { + return errorsmod.Wrapf( + ErrInvalidGenesisData, + "non-positive last total power %s", + gs.LastTotalPower, + ) + } + + if !gs.LastTotalPower.Equal(math.NewInt(totalPower)) { + return errorsmod.Wrapf( + ErrInvalidGenesisData, + "last total power mismatch %s, expected %d", + gs.LastTotalPower, totalPower, + ) } return gs.Params.Validate() diff --git a/x/dogfood/types/genesis.pb.go b/x/dogfood/types/genesis.pb.go index e900011d4..ae2a4b767 100644 --- a/x/dogfood/types/genesis.pb.go +++ b/x/dogfood/types/genesis.pb.go @@ -5,6 +5,8 @@ package types import ( fmt "fmt" + github_com_cosmos_cosmos_sdk_types "github.com/cosmos/cosmos-sdk/types" + _ "github.com/cosmos/cosmos-sdk/types/tx/amino" _ "github.com/cosmos/gogoproto/gogoproto" proto "github.com/cosmos/gogoproto/proto" io "io" @@ -23,12 +25,32 @@ var _ = math.Inf // proto package needs to be updated. const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package -// GenesisState defines the dogfood module's genesis state. +// GenesisState defines the dogfood module's genesis state. Note that, as always, +// `genesis` is a misnomer. Ideally, this state can be exported at any point in +// time (or height), and reimported elsewhere where it will be the new genesis +// potentially at a non-zero height. In other words, it is the entire, current, +// state of the module. type GenesisState struct { // params refers to the parameters of the module. Params Params `protobuf:"bytes,1,opt,name=params,proto3" json:"params"` - // initial_val_set is the initial validator set. - InitialValSet []GenesisValidator `protobuf:"bytes,2,rep,name=initial_val_set,json=initialValSet,proto3" json:"initial_val_set"` + // val_set is the initial validator set. it onyl represents the active + // validators. + ValSet []GenesisValidator `protobuf:"bytes,2,rep,name=val_set,json=valSet,proto3" json:"val_set"` + // opt_out_expiries is a list of (future) epochs at the end of which the + // corresponding operators' opt-out will expire. we store this, as well as its reverse + // lookup. + OptOutExpiries []EpochToOperatorAddrs `protobuf:"bytes,3,rep,name=opt_out_expiries,json=optOutExpiries,proto3" json:"opt_out_expiries"` + // epochs_consensus_addrs is a list of epochs at the end of which the corresponding + // consensus addresses should be pruned from the operator module. + ConsensusAddrsToPrune []EpochToConsensusAddrs `protobuf:"bytes,4,rep,name=consensus_addrs_to_prune,json=consensusAddrsToPrune,proto3" json:"consensus_addrs_to_prune"` + // undelegation_maturities is a list of epochs at the end of which the corresponding + // undelegations will mature. we store its reverse lookup as well. + UndelegationMaturities []EpochToUndelegationRecordKeys `protobuf:"bytes,5,rep,name=undelegation_maturities,json=undelegationMaturities,proto3" json:"undelegation_maturities"` + // last_total_power tracks the total voting power as of the last validator set + // update. such an update is most likely to be at the end of the last epoch (or the + // beginning of this one, to be more precise) and less likely to be at other blocks, + // since the validator set can otherwise only change as a result of slashing events. + LastTotalPower github_com_cosmos_cosmos_sdk_types.Int `protobuf:"bytes,6,opt,name=last_total_power,json=lastTotalPower,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Int" json:"last_total_power"` } func (m *GenesisState) Reset() { *m = GenesisState{} } @@ -71,15 +93,40 @@ func (m *GenesisState) GetParams() Params { return Params{} } -func (m *GenesisState) GetInitialValSet() []GenesisValidator { +func (m *GenesisState) GetValSet() []GenesisValidator { if m != nil { - return m.InitialValSet + return m.ValSet + } + return nil +} + +func (m *GenesisState) GetOptOutExpiries() []EpochToOperatorAddrs { + if m != nil { + return m.OptOutExpiries + } + return nil +} + +func (m *GenesisState) GetConsensusAddrsToPrune() []EpochToConsensusAddrs { + if m != nil { + return m.ConsensusAddrsToPrune + } + return nil +} + +func (m *GenesisState) GetUndelegationMaturities() []EpochToUndelegationRecordKeys { + if m != nil { + return m.UndelegationMaturities } return nil } // GenesisValidator defines a genesis validator. It is a helper struct -// used for serializing the genesis state. +// used for serializing the genesis state. The only reason it is a different +// structure is to support importing hex public keys from Solidity. +// TODO: consider this set up when resolving issue 73 about storage +// optimization between dogfood and operator modules. +// https://github.com/ExocoreNetwork/exocore/issues/73 type GenesisValidator struct { // public_key is the consensus public key of the validator. It should // be exactly 32 bytes, but this is not enforced in protobuf. @@ -135,34 +182,227 @@ func (m *GenesisValidator) GetPower() int64 { return 0 } +// EpochToOperatorAddress is used to store a mapping from epoch to a list of +// operator account addresses. +type EpochToOperatorAddrs struct { + // epoch is the epoch in question. + Epoch int64 `protobuf:"varint,1,opt,name=epoch,proto3" json:"epoch,omitempty"` + // operator_acc_addrs is the list of account addresses to expire at this epoch. + // It is of type string for human readability of the genesis file. + OperatorAccAddrs []string `protobuf:"bytes,2,rep,name=operator_acc_addrs,json=operatorAccAddrs,proto3" json:"operator_acc_addrs,omitempty"` +} + +func (m *EpochToOperatorAddrs) Reset() { *m = EpochToOperatorAddrs{} } +func (m *EpochToOperatorAddrs) String() string { return proto.CompactTextString(m) } +func (*EpochToOperatorAddrs) ProtoMessage() {} +func (*EpochToOperatorAddrs) Descriptor() ([]byte, []int) { + return fileDescriptor_1a9d908a27866b1b, []int{2} +} +func (m *EpochToOperatorAddrs) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *EpochToOperatorAddrs) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_EpochToOperatorAddrs.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 *EpochToOperatorAddrs) XXX_Merge(src proto.Message) { + xxx_messageInfo_EpochToOperatorAddrs.Merge(m, src) +} +func (m *EpochToOperatorAddrs) XXX_Size() int { + return m.Size() +} +func (m *EpochToOperatorAddrs) XXX_DiscardUnknown() { + xxx_messageInfo_EpochToOperatorAddrs.DiscardUnknown(m) +} + +var xxx_messageInfo_EpochToOperatorAddrs proto.InternalMessageInfo + +func (m *EpochToOperatorAddrs) GetEpoch() int64 { + if m != nil { + return m.Epoch + } + return 0 +} + +func (m *EpochToOperatorAddrs) GetOperatorAccAddrs() []string { + if m != nil { + return m.OperatorAccAddrs + } + return nil +} + +// EpochToConsensusAddrs is used to store a mapping from the epoch to a list of +// consensus addresses. +type EpochToConsensusAddrs struct { + // epoch is the epoch in question. + Epoch int64 `protobuf:"varint,1,opt,name=epoch,proto3" json:"epoch,omitempty"` + // cons_addrs is the list of consensus addresses to prune at this epoch. + // It is of type string for human readability of the genesis file. + ConsAddrs []string `protobuf:"bytes,2,rep,name=cons_addrs,json=consAddrs,proto3" json:"cons_addrs,omitempty"` +} + +func (m *EpochToConsensusAddrs) Reset() { *m = EpochToConsensusAddrs{} } +func (m *EpochToConsensusAddrs) String() string { return proto.CompactTextString(m) } +func (*EpochToConsensusAddrs) ProtoMessage() {} +func (*EpochToConsensusAddrs) Descriptor() ([]byte, []int) { + return fileDescriptor_1a9d908a27866b1b, []int{3} +} +func (m *EpochToConsensusAddrs) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *EpochToConsensusAddrs) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_EpochToConsensusAddrs.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 *EpochToConsensusAddrs) XXX_Merge(src proto.Message) { + xxx_messageInfo_EpochToConsensusAddrs.Merge(m, src) +} +func (m *EpochToConsensusAddrs) XXX_Size() int { + return m.Size() +} +func (m *EpochToConsensusAddrs) XXX_DiscardUnknown() { + xxx_messageInfo_EpochToConsensusAddrs.DiscardUnknown(m) +} + +var xxx_messageInfo_EpochToConsensusAddrs proto.InternalMessageInfo + +func (m *EpochToConsensusAddrs) GetEpoch() int64 { + if m != nil { + return m.Epoch + } + return 0 +} + +func (m *EpochToConsensusAddrs) GetConsAddrs() []string { + if m != nil { + return m.ConsAddrs + } + return nil +} + +// EpochToUndelegationRecordKeys is used to store a mapping from an epoch to a list of +// undelegations which mature at that epoch. +type EpochToUndelegationRecordKeys struct { + // epoch is the epoch in question. + Epoch int64 `protobuf:"varint,1,opt,name=epoch,proto3" json:"epoch,omitempty"` + // undelegation_record_keys is the list of undelegations (defined by the record key) + // to expire at this epoch. + // It is of type string for human readability of the genesis file. + UndelegationRecordKeys []string `protobuf:"bytes,2,rep,name=undelegation_record_keys,json=undelegationRecordKeys,proto3" json:"undelegation_record_keys,omitempty"` +} + +func (m *EpochToUndelegationRecordKeys) Reset() { *m = EpochToUndelegationRecordKeys{} } +func (m *EpochToUndelegationRecordKeys) String() string { return proto.CompactTextString(m) } +func (*EpochToUndelegationRecordKeys) ProtoMessage() {} +func (*EpochToUndelegationRecordKeys) Descriptor() ([]byte, []int) { + return fileDescriptor_1a9d908a27866b1b, []int{4} +} +func (m *EpochToUndelegationRecordKeys) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *EpochToUndelegationRecordKeys) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_EpochToUndelegationRecordKeys.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 *EpochToUndelegationRecordKeys) XXX_Merge(src proto.Message) { + xxx_messageInfo_EpochToUndelegationRecordKeys.Merge(m, src) +} +func (m *EpochToUndelegationRecordKeys) XXX_Size() int { + return m.Size() +} +func (m *EpochToUndelegationRecordKeys) XXX_DiscardUnknown() { + xxx_messageInfo_EpochToUndelegationRecordKeys.DiscardUnknown(m) +} + +var xxx_messageInfo_EpochToUndelegationRecordKeys proto.InternalMessageInfo + +func (m *EpochToUndelegationRecordKeys) GetEpoch() int64 { + if m != nil { + return m.Epoch + } + return 0 +} + +func (m *EpochToUndelegationRecordKeys) GetUndelegationRecordKeys() []string { + if m != nil { + return m.UndelegationRecordKeys + } + return nil +} + func init() { proto.RegisterType((*GenesisState)(nil), "exocore.dogfood.v1.GenesisState") proto.RegisterType((*GenesisValidator)(nil), "exocore.dogfood.v1.GenesisValidator") + proto.RegisterType((*EpochToOperatorAddrs)(nil), "exocore.dogfood.v1.EpochToOperatorAddrs") + proto.RegisterType((*EpochToConsensusAddrs)(nil), "exocore.dogfood.v1.EpochToConsensusAddrs") + proto.RegisterType((*EpochToUndelegationRecordKeys)(nil), "exocore.dogfood.v1.EpochToUndelegationRecordKeys") } func init() { proto.RegisterFile("exocore/dogfood/v1/genesis.proto", fileDescriptor_1a9d908a27866b1b) } var fileDescriptor_1a9d908a27866b1b = []byte{ - // 302 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x90, 0xbd, 0x6a, 0x32, 0x41, - 0x18, 0x85, 0x77, 0xf4, 0xfb, 0x04, 0xc7, 0x84, 0x84, 0xc1, 0x42, 0x84, 0x8c, 0x8b, 0xa4, 0xb0, - 0x9a, 0x41, 0xd3, 0xa4, 0x16, 0x82, 0x85, 0x10, 0xc2, 0x0a, 0x16, 0x69, 0x64, 0xd4, 0x37, 0x9b, - 0xc1, 0xd5, 0x77, 0x99, 0x1d, 0xff, 0xee, 0x22, 0x17, 0x90, 0x0b, 0xb2, 0xb4, 0x4c, 0x15, 0x82, - 0xde, 0x48, 0xc8, 0xce, 0x24, 0x45, 0x62, 0x37, 0x3f, 0x0f, 0xcf, 0x39, 0x1c, 0x1a, 0xc2, 0x06, - 0x27, 0x68, 0x40, 0x4e, 0x31, 0x7e, 0x42, 0x9c, 0xca, 0x55, 0x5b, 0xc6, 0xb0, 0x80, 0x4c, 0x67, - 0x22, 0x35, 0x68, 0x91, 0x31, 0x4f, 0x08, 0x4f, 0x88, 0x55, 0xbb, 0x5e, 0x8d, 0x31, 0xc6, 0xfc, - 0x5b, 0x7e, 0x9d, 0x1c, 0x59, 0x6f, 0x9c, 0x70, 0xa5, 0xca, 0xa8, 0xb9, 0x57, 0x35, 0x5f, 0x09, - 0x3d, 0xeb, 0x39, 0xf9, 0xc0, 0x2a, 0x0b, 0xec, 0x96, 0x96, 0x1c, 0x50, 0x23, 0x21, 0x69, 0x55, - 0x3a, 0x75, 0xf1, 0x37, 0x4c, 0x3c, 0xe4, 0x44, 0xf7, 0xdf, 0xee, 0xbd, 0x11, 0x44, 0x9e, 0x67, - 0x11, 0xbd, 0xd0, 0x0b, 0x6d, 0xb5, 0x4a, 0x46, 0x2b, 0x95, 0x8c, 0x32, 0xb0, 0xb5, 0x42, 0x58, - 0x6c, 0x55, 0x3a, 0xd7, 0xa7, 0x14, 0x3e, 0x74, 0xa8, 0x12, 0x3d, 0x55, 0x16, 0x8d, 0x97, 0x9d, - 0x7b, 0xc5, 0x50, 0x25, 0x03, 0xb0, 0xcd, 0x1e, 0xbd, 0xfc, 0x0d, 0xb2, 0x2b, 0x4a, 0xd3, 0xe5, - 0x38, 0xd1, 0x93, 0xd1, 0x0c, 0xb6, 0x79, 0xcb, 0x72, 0x54, 0x76, 0x2f, 0x7d, 0xd8, 0xb2, 0x2a, - 0xfd, 0x9f, 0xe2, 0x1a, 0x4c, 0xad, 0x10, 0x92, 0x56, 0x31, 0x72, 0x97, 0x6e, 0x7f, 0x77, 0xe0, - 0x64, 0x7f, 0xe0, 0xe4, 0xe3, 0xc0, 0xc9, 0xcb, 0x91, 0x07, 0xfb, 0x23, 0x0f, 0xde, 0x8e, 0x3c, - 0x78, 0x6c, 0xc7, 0xda, 0x3e, 0x2f, 0xc7, 0x62, 0x82, 0x73, 0x79, 0xe7, 0x7a, 0xde, 0x83, 0x5d, - 0xa3, 0x99, 0xc9, 0xef, 0xf1, 0x36, 0x3f, 0xf3, 0xd9, 0x6d, 0x0a, 0xd9, 0xb8, 0x94, 0x6f, 0x77, - 0xf3, 0x19, 0x00, 0x00, 0xff, 0xff, 0x94, 0xc2, 0x5a, 0x03, 0xaa, 0x01, 0x00, 0x00, + // 578 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x93, 0xc1, 0x4e, 0xdb, 0x30, + 0x18, 0xc7, 0x1b, 0x0a, 0x4c, 0x35, 0x08, 0x75, 0x16, 0x6c, 0x11, 0x12, 0xa1, 0xaa, 0xa6, 0xa9, + 0x9b, 0xb6, 0x44, 0x85, 0x0b, 0x57, 0x40, 0x08, 0x4d, 0x6c, 0x03, 0x05, 0x36, 0x4d, 0x48, 0x53, + 0x64, 0x1c, 0x2f, 0x8d, 0x9a, 0xe6, 0xb3, 0x6c, 0xa7, 0xb4, 0x6f, 0xb1, 0x67, 0xd8, 0x69, 0xc7, + 0x3d, 0x06, 0x47, 0x8e, 0xd3, 0x0e, 0x68, 0x6a, 0x0f, 0x7b, 0x8d, 0xc9, 0x4e, 0x82, 0xda, 0xad, + 0xf4, 0xd2, 0xda, 0x5f, 0xfe, 0xdf, 0xef, 0xef, 0xe4, 0xef, 0x0f, 0x35, 0xd8, 0x00, 0x28, 0x08, + 0xe6, 0x85, 0x10, 0x7d, 0x01, 0x08, 0xbd, 0x7e, 0xdb, 0x8b, 0x58, 0xca, 0x64, 0x2c, 0x5d, 0x2e, + 0x40, 0x01, 0xc6, 0x85, 0xc2, 0x2d, 0x14, 0x6e, 0xbf, 0xbd, 0xf9, 0x98, 0xf4, 0xe2, 0x14, 0x3c, + 0xf3, 0x9b, 0xcb, 0x36, 0xd7, 0x23, 0x88, 0xc0, 0x2c, 0x3d, 0xbd, 0x2a, 0xaa, 0xdb, 0x33, 0xf0, + 0x9c, 0x08, 0xd2, 0x2b, 0xe8, 0xcd, 0x6f, 0x8b, 0x68, 0xf5, 0x38, 0xf7, 0x3b, 0x57, 0x44, 0x31, + 0xbc, 0x87, 0x96, 0x73, 0x81, 0x6d, 0x35, 0xac, 0xd6, 0xca, 0xce, 0xa6, 0xfb, 0xbf, 0xbf, 0x7b, + 0x66, 0x14, 0x07, 0x8b, 0x37, 0x77, 0xdb, 0x15, 0xbf, 0xd0, 0xe3, 0x43, 0xf4, 0xa8, 0x4f, 0x92, + 0x40, 0x32, 0x65, 0x2f, 0x34, 0xaa, 0xad, 0x95, 0x9d, 0x67, 0xb3, 0x5a, 0x0b, 0xb3, 0x8f, 0x24, + 0x89, 0x43, 0xa2, 0x40, 0x94, 0x90, 0x3e, 0x49, 0xce, 0x99, 0xc2, 0x9f, 0x50, 0x1d, 0xb8, 0x0a, + 0x20, 0x53, 0x01, 0x1b, 0xf0, 0x58, 0xc4, 0x4c, 0xda, 0x55, 0x43, 0x6b, 0xcd, 0xa2, 0x1d, 0x71, + 0xa0, 0x9d, 0x0b, 0x38, 0xe5, 0x4c, 0x68, 0xd8, 0x7e, 0x18, 0x8a, 0xf2, 0x58, 0x6b, 0xc0, 0xd5, + 0x69, 0xa6, 0x8e, 0x0a, 0x0a, 0xee, 0x20, 0x9b, 0x42, 0x2a, 0x59, 0x2a, 0x33, 0x19, 0x10, 0x2d, + 0x0c, 0x14, 0x04, 0x5c, 0x64, 0x29, 0xb3, 0x17, 0x8d, 0xc3, 0x8b, 0x39, 0x0e, 0x87, 0x65, 0xeb, + 0xa4, 0xc5, 0x06, 0x9d, 0xaa, 0x5e, 0xc0, 0x99, 0xa6, 0x61, 0x8e, 0x9e, 0x66, 0x69, 0xc8, 0x12, + 0x16, 0x11, 0x15, 0x43, 0x1a, 0xf4, 0x88, 0xca, 0x44, 0xac, 0xf4, 0xab, 0x2c, 0x19, 0xa3, 0xf6, + 0x1c, 0xa3, 0x0f, 0x13, 0x9d, 0x3e, 0xa3, 0x20, 0xc2, 0x13, 0x36, 0x2c, 0x0d, 0x9f, 0x4c, 0x72, + 0xdf, 0xdd, 0x63, 0xf1, 0x67, 0x54, 0x4f, 0x88, 0x54, 0x81, 0x02, 0x45, 0x92, 0x80, 0xc3, 0x35, + 0x13, 0xf6, 0x72, 0xc3, 0x6a, 0xad, 0x1e, 0xec, 0xea, 0xbe, 0x5f, 0x77, 0xdb, 0xcf, 0xa3, 0x58, + 0x75, 0xb2, 0x2b, 0x97, 0x42, 0xcf, 0xa3, 0x20, 0x7b, 0x20, 0x8b, 0xbf, 0xd7, 0x32, 0xec, 0x7a, + 0x6a, 0xc8, 0x99, 0x74, 0xdf, 0xa4, 0xea, 0xfb, 0x9f, 0x1f, 0x2f, 0x2d, 0x7f, 0x4d, 0xc3, 0x2e, + 0x34, 0xeb, 0x4c, 0xa3, 0x9a, 0xc7, 0xa8, 0xfe, 0x6f, 0x6c, 0x78, 0x0b, 0x21, 0x9e, 0x5d, 0x25, + 0x31, 0x0d, 0xba, 0x6c, 0x68, 0xee, 0x4a, 0xcd, 0xaf, 0xe5, 0x95, 0x13, 0x36, 0xc4, 0xeb, 0x68, + 0x29, 0x3f, 0xc6, 0x42, 0xc3, 0x6a, 0x55, 0xfd, 0x7c, 0xd3, 0xbc, 0x44, 0xeb, 0xb3, 0x12, 0xd3, + 0x6a, 0xa6, 0xeb, 0x86, 0x53, 0xf5, 0xf3, 0x0d, 0x7e, 0x85, 0x30, 0x14, 0xb2, 0x80, 0x50, 0x9a, + 0x87, 0x66, 0xee, 0x56, 0xcd, 0xaf, 0x97, 0x4f, 0xf6, 0x29, 0x35, 0x8c, 0xe6, 0x5b, 0xb4, 0x31, + 0x33, 0xab, 0x07, 0xe0, 0x5b, 0x08, 0xe9, 0xf4, 0xa6, 0xa0, 0x35, 0x5d, 0xc9, 0x69, 0x80, 0xb6, + 0xe6, 0x06, 0xf2, 0x00, 0x75, 0x0f, 0xd9, 0x53, 0xd1, 0x0b, 0xd3, 0xa0, 0x3f, 0x51, 0xe9, 0x31, + 0x15, 0xe1, 0x44, 0xc0, 0x27, 0x37, 0x23, 0xc7, 0xba, 0x1d, 0x39, 0xd6, 0xef, 0x91, 0x63, 0x7d, + 0x1d, 0x3b, 0x95, 0xdb, 0xb1, 0x53, 0xf9, 0x39, 0x76, 0x2a, 0x97, 0xed, 0x89, 0xe8, 0x8e, 0xf2, + 0x7b, 0xf3, 0x9e, 0xa9, 0x6b, 0x10, 0x5d, 0xaf, 0x9c, 0xee, 0xc1, 0xfd, 0x7c, 0x9b, 0x24, 0xaf, + 0x96, 0xcd, 0x70, 0xef, 0xfe, 0x0d, 0x00, 0x00, 0xff, 0xff, 0xc3, 0x73, 0x71, 0xf4, 0x5e, 0x04, + 0x00, 0x00, } func (m *GenesisState) Marshal() (dAtA []byte, err error) { @@ -185,10 +425,62 @@ func (m *GenesisState) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l - if len(m.InitialValSet) > 0 { - for iNdEx := len(m.InitialValSet) - 1; iNdEx >= 0; iNdEx-- { + { + size := m.LastTotalPower.Size() + i -= size + if _, err := m.LastTotalPower.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x32 + if len(m.UndelegationMaturities) > 0 { + for iNdEx := len(m.UndelegationMaturities) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.UndelegationMaturities[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x2a + } + } + if len(m.ConsensusAddrsToPrune) > 0 { + for iNdEx := len(m.ConsensusAddrsToPrune) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.ConsensusAddrsToPrune[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + } + } + if len(m.OptOutExpiries) > 0 { + for iNdEx := len(m.OptOutExpiries) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.OptOutExpiries[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + } + if len(m.ValSet) > 0 { + for iNdEx := len(m.ValSet) - 1; iNdEx >= 0; iNdEx-- { { - size, err := m.InitialValSet[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + size, err := m.ValSet[iNdEx].MarshalToSizedBuffer(dAtA[:i]) if err != nil { return 0, err } @@ -247,6 +539,117 @@ func (m *GenesisValidator) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *EpochToOperatorAddrs) 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 *EpochToOperatorAddrs) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *EpochToOperatorAddrs) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.OperatorAccAddrs) > 0 { + for iNdEx := len(m.OperatorAccAddrs) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.OperatorAccAddrs[iNdEx]) + copy(dAtA[i:], m.OperatorAccAddrs[iNdEx]) + i = encodeVarintGenesis(dAtA, i, uint64(len(m.OperatorAccAddrs[iNdEx]))) + i-- + dAtA[i] = 0x12 + } + } + if m.Epoch != 0 { + i = encodeVarintGenesis(dAtA, i, uint64(m.Epoch)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *EpochToConsensusAddrs) 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 *EpochToConsensusAddrs) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *EpochToConsensusAddrs) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.ConsAddrs) > 0 { + for iNdEx := len(m.ConsAddrs) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.ConsAddrs[iNdEx]) + copy(dAtA[i:], m.ConsAddrs[iNdEx]) + i = encodeVarintGenesis(dAtA, i, uint64(len(m.ConsAddrs[iNdEx]))) + i-- + dAtA[i] = 0x12 + } + } + if m.Epoch != 0 { + i = encodeVarintGenesis(dAtA, i, uint64(m.Epoch)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *EpochToUndelegationRecordKeys) 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 *EpochToUndelegationRecordKeys) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *EpochToUndelegationRecordKeys) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.UndelegationRecordKeys) > 0 { + for iNdEx := len(m.UndelegationRecordKeys) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.UndelegationRecordKeys[iNdEx]) + copy(dAtA[i:], m.UndelegationRecordKeys[iNdEx]) + i = encodeVarintGenesis(dAtA, i, uint64(len(m.UndelegationRecordKeys[iNdEx]))) + i-- + dAtA[i] = 0x12 + } + } + if m.Epoch != 0 { + i = encodeVarintGenesis(dAtA, i, uint64(m.Epoch)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + func encodeVarintGenesis(dAtA []byte, offset int, v uint64) int { offset -= sovGenesis(v) base := offset @@ -266,12 +669,32 @@ func (m *GenesisState) Size() (n int) { _ = l l = m.Params.Size() n += 1 + l + sovGenesis(uint64(l)) - if len(m.InitialValSet) > 0 { - for _, e := range m.InitialValSet { + if len(m.ValSet) > 0 { + for _, e := range m.ValSet { + l = e.Size() + n += 1 + l + sovGenesis(uint64(l)) + } + } + if len(m.OptOutExpiries) > 0 { + for _, e := range m.OptOutExpiries { + l = e.Size() + n += 1 + l + sovGenesis(uint64(l)) + } + } + if len(m.ConsensusAddrsToPrune) > 0 { + for _, e := range m.ConsensusAddrsToPrune { + l = e.Size() + n += 1 + l + sovGenesis(uint64(l)) + } + } + if len(m.UndelegationMaturities) > 0 { + for _, e := range m.UndelegationMaturities { l = e.Size() n += 1 + l + sovGenesis(uint64(l)) } } + l = m.LastTotalPower.Size() + n += 1 + l + sovGenesis(uint64(l)) return n } @@ -291,17 +714,71 @@ func (m *GenesisValidator) Size() (n int) { return n } -func sovGenesis(x uint64) (n int) { - return (math_bits.Len64(x|1) + 6) / 7 -} -func sozGenesis(x uint64) (n int) { - return sovGenesis(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +func (m *EpochToOperatorAddrs) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Epoch != 0 { + n += 1 + sovGenesis(uint64(m.Epoch)) + } + if len(m.OperatorAccAddrs) > 0 { + for _, s := range m.OperatorAccAddrs { + l = len(s) + n += 1 + l + sovGenesis(uint64(l)) + } + } + return n } -func (m *GenesisState) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx + +func (m *EpochToConsensusAddrs) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Epoch != 0 { + n += 1 + sovGenesis(uint64(m.Epoch)) + } + if len(m.ConsAddrs) > 0 { + for _, s := range m.ConsAddrs { + l = len(s) + n += 1 + l + sovGenesis(uint64(l)) + } + } + return n +} + +func (m *EpochToUndelegationRecordKeys) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Epoch != 0 { + n += 1 + sovGenesis(uint64(m.Epoch)) + } + if len(m.UndelegationRecordKeys) > 0 { + for _, s := range m.UndelegationRecordKeys { + l = len(s) + n += 1 + l + sovGenesis(uint64(l)) + } + } + return n +} + +func sovGenesis(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozGenesis(x uint64) (n int) { + return sovGenesis(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *GenesisState) 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 { @@ -361,7 +838,7 @@ func (m *GenesisState) Unmarshal(dAtA []byte) error { iNdEx = postIndex case 2: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field InitialValSet", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field ValSet", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -388,8 +865,143 @@ func (m *GenesisState) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.InitialValSet = append(m.InitialValSet, GenesisValidator{}) - if err := m.InitialValSet[len(m.InitialValSet)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + m.ValSet = append(m.ValSet, GenesisValidator{}) + if err := m.ValSet[len(m.ValSet)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field OptOutExpiries", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.OptOutExpiries = append(m.OptOutExpiries, EpochToOperatorAddrs{}) + if err := m.OptOutExpiries[len(m.OptOutExpiries)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ConsensusAddrsToPrune", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ConsensusAddrsToPrune = append(m.ConsensusAddrsToPrune, EpochToConsensusAddrs{}) + if err := m.ConsensusAddrsToPrune[len(m.ConsensusAddrsToPrune)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field UndelegationMaturities", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.UndelegationMaturities = append(m.UndelegationMaturities, EpochToUndelegationRecordKeys{}) + if err := m.UndelegationMaturities[len(m.UndelegationMaturities)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field LastTotalPower", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.LastTotalPower.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex @@ -515,6 +1127,309 @@ func (m *GenesisValidator) Unmarshal(dAtA []byte) error { } return nil } +func (m *EpochToOperatorAddrs) 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 ErrIntOverflowGenesis + } + 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: EpochToOperatorAddrs: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: EpochToOperatorAddrs: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Epoch", wireType) + } + m.Epoch = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Epoch |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field OperatorAccAddrs", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.OperatorAccAddrs = append(m.OperatorAccAddrs, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenesis(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenesis + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *EpochToConsensusAddrs) 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 ErrIntOverflowGenesis + } + 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: EpochToConsensusAddrs: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: EpochToConsensusAddrs: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Epoch", wireType) + } + m.Epoch = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Epoch |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ConsAddrs", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ConsAddrs = append(m.ConsAddrs, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenesis(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenesis + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *EpochToUndelegationRecordKeys) 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 ErrIntOverflowGenesis + } + 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: EpochToUndelegationRecordKeys: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: EpochToUndelegationRecordKeys: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Epoch", wireType) + } + m.Epoch = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Epoch |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field UndelegationRecordKeys", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.UndelegationRecordKeys = append(m.UndelegationRecordKeys, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenesis(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenesis + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func skipGenesis(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 diff --git a/x/dogfood/types/genesis_test.go b/x/dogfood/types/genesis_test.go index df1887f49..a7a129a49 100644 --- a/x/dogfood/types/genesis_test.go +++ b/x/dogfood/types/genesis_test.go @@ -3,8 +3,13 @@ package types_test import ( "testing" + "cosmossdk.io/math" + testutiltx "github.com/ExocoreNetwork/exocore/testutil/tx" + delegationtypes "github.com/ExocoreNetwork/exocore/x/delegation/types" "github.com/ExocoreNetwork/exocore/x/dogfood/types" "github.com/cometbft/cometbft/crypto/ed25519" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/stretchr/testify/suite" ) @@ -22,11 +27,22 @@ func TestGenesisTestSuite(t *testing.T) { func (suite *GenesisTestSuite) TestValidateGenesis() { sharedKey := hexutil.Encode(ed25519.GenPrivKey().PubKey().Bytes()) + operator1 := sdk.AccAddress(testutiltx.GenerateAddress().Bytes()) + consAddr1 := sdk.ConsAddress(operator1) + recordKey := hexutil.Encode( + delegationtypes.GetUndelegationRecordKey( + 1000, // block height + 1, // layer zero nonce + common.BytesToHash([]byte("tx hash")).Hex(), + operator1.String(), + ), + ) params := types.DefaultParams() testCases := []struct { name string genState *types.GenesisState expPass bool + expError string malleate func(*types.GenesisState) }{ { @@ -34,19 +50,26 @@ func (suite *GenesisTestSuite) TestValidateGenesis() { genState: &types.GenesisState{ Params: params, }, - expPass: true, + expPass: false, // difference between 0 and 1 voting power + expError: "nil last total power", }, { name: "default", genState: types.DefaultGenesis(), - expPass: true, + expPass: false, // 0 voting power isn't permitted + expError: "non-positive last total power", }, { name: "NewGenesis call", genState: types.NewGenesis( params, []types.GenesisValidator{}, + []types.EpochToOperatorAddrs{}, + []types.EpochToConsensusAddrs{}, + []types.EpochToUndelegationRecordKeys{}, + math.ZeroInt(), ), - expPass: true, + expPass: false, // 0 voting power isn't permitted + expError: "non-positive last total power", }, { name: "too many validators", @@ -60,21 +83,25 @@ func (suite *GenesisTestSuite) TestValidateGenesis() { key := hexutil.Encode( ed25519.GenPrivKey().PubKey().Bytes(), ) - gs.InitialValSet = append(gs.InitialValSet, + gs.ValSet = append(gs.ValSet, types.GenesisValidator{ PublicKey: key, Power: 5, }, ) } + gs.LastTotalPower = math.NewInt( + int64(len(gs.ValSet) * 5), + ) }, - expPass: false, + expPass: false, + expError: "too many validators", }, { name: "duplicate keys", genState: &types.GenesisState{ Params: params, - InitialValSet: []types.GenesisValidator{ + ValSet: []types.GenesisValidator{ { PublicKey: sharedKey, Power: 5, @@ -84,64 +111,534 @@ func (suite *GenesisTestSuite) TestValidateGenesis() { Power: 10, }, }, + LastTotalPower: math.NewInt(10), }, - expPass: false, + expPass: false, + expError: "duplicate public key", }, { name: "key with missing 0x prefix", genState: &types.GenesisState{ Params: params, - InitialValSet: []types.GenesisValidator{ + ValSet: []types.GenesisValidator{ { // remove 2 chars and add 2 chars PublicKey: sharedKey[2:] + "ab", Power: 5, }, }, + LastTotalPower: math.NewInt(5), }, - expPass: false, + expPass: false, + expError: "invalid public key", }, { // also covers empty key name: "key with the wrong length", genState: &types.GenesisState{ Params: params, - InitialValSet: []types.GenesisValidator{ + ValSet: []types.GenesisValidator{ { PublicKey: sharedKey + "ab", Power: 5, }, }, + LastTotalPower: math.NewInt(5), }, - expPass: false, + expPass: false, + expError: "invalid public key", }, { name: "non hex key", genState: &types.GenesisState{ Params: params, - InitialValSet: []types.GenesisValidator{ + ValSet: []types.GenesisValidator{ { // replace last 2 chars with non-hex PublicKey: sharedKey[:64] + "ss", Power: 5, }, }, + LastTotalPower: math.NewInt(5), + }, + expPass: false, + expError: "invalid public key", + }, + { + name: "negative vote power", + genState: &types.GenesisState{ + Params: params, + ValSet: []types.GenesisValidator{ + { + PublicKey: sharedKey, + Power: -1, + }, + }, + LastTotalPower: math.NewInt(1), }, - expPass: false, + expPass: false, + expError: "invalid power", }, { name: "valid genesis with one validator", genState: &types.GenesisState{ Params: params, - InitialValSet: []types.GenesisValidator{ + ValSet: []types.GenesisValidator{ + { + PublicKey: sharedKey, + Power: 5, + }, + }, + LastTotalPower: math.NewInt(5), + }, + expPass: true, + }, + { + name: "duplicate epoch in expiries", + genState: &types.GenesisState{ + Params: params, + ValSet: []types.GenesisValidator{ + { + PublicKey: sharedKey, + Power: 5, + }, + }, + LastTotalPower: math.NewInt(5), + OptOutExpiries: []types.EpochToOperatorAddrs{ + { + Epoch: 2, + OperatorAccAddrs: []string{ + operator1.String(), + }, + }, + { + Epoch: 2, + OperatorAccAddrs: []string{ + operator1.String(), + }, + }, + }, + }, + expPass: false, + expError: "duplicate epoch", + }, + { + name: "epoch 1 for expiries", + genState: &types.GenesisState{ + Params: params, + ValSet: []types.GenesisValidator{ + { + PublicKey: sharedKey, + Power: 5, + }, + }, + LastTotalPower: math.NewInt(5), + OptOutExpiries: []types.EpochToOperatorAddrs{ + { + Epoch: 1, + OperatorAccAddrs: []string{ + operator1.String(), + }, + }, + }, + }, + expPass: false, + expError: "should be > 1", + }, + { + name: "empty operator addrs for expiry epoch", + genState: &types.GenesisState{ + Params: params, + ValSet: []types.GenesisValidator{ + { + PublicKey: sharedKey, + Power: 5, + }, + }, + LastTotalPower: math.NewInt(5), + OptOutExpiries: []types.EpochToOperatorAddrs{ + { + Epoch: 2, + }, + }, + }, + expPass: false, + expError: "empty operator addresses for epoch", + }, + { + name: "duplicate addrs for expiry epoch", + genState: &types.GenesisState{ + Params: params, + ValSet: []types.GenesisValidator{ + { + PublicKey: sharedKey, + Power: 5, + }, + }, + LastTotalPower: math.NewInt(5), + OptOutExpiries: []types.EpochToOperatorAddrs{ + { + Epoch: 2, + OperatorAccAddrs: []string{ + operator1.String(), + operator1.String(), + }, + }, + }, + }, + expPass: false, + expError: "duplicate operator address", + }, + { + name: "invalid addr for expiry epoch", + genState: &types.GenesisState{ + Params: params, + ValSet: []types.GenesisValidator{ + { + PublicKey: sharedKey, + Power: 5, + }, + }, + LastTotalPower: math.NewInt(5), + OptOutExpiries: []types.EpochToOperatorAddrs{ + { + Epoch: 2, + OperatorAccAddrs: []string{ + "invalid address", + }, + }, + }, + }, + expPass: false, + expError: "invalid operator address", + }, + { + name: "valid with expiries", + genState: &types.GenesisState{ + Params: params, + ValSet: []types.GenesisValidator{ + { + PublicKey: sharedKey, + Power: 5, + }, + }, + LastTotalPower: math.NewInt(5), + OptOutExpiries: []types.EpochToOperatorAddrs{ + { + Epoch: 2, + OperatorAccAddrs: []string{ + operator1.String(), + }, + }, + }, + }, + expPass: true, + }, + { + name: "duplicate epoch in pruning", + genState: &types.GenesisState{ + Params: params, + ValSet: []types.GenesisValidator{ + { + PublicKey: sharedKey, + Power: 5, + }, + }, + LastTotalPower: math.NewInt(5), + ConsensusAddrsToPrune: []types.EpochToConsensusAddrs{ + { + Epoch: 2, + ConsAddrs: []string{ + consAddr1.String(), + }, + }, + { + Epoch: 2, + ConsAddrs: []string{ + consAddr1.String(), + }, + }, + }, + }, + expPass: false, + expError: "duplicate epoch", + }, + { + name: "epoch 1 for pruning", + genState: &types.GenesisState{ + Params: params, + ValSet: []types.GenesisValidator{ + { + PublicKey: sharedKey, + Power: 5, + }, + }, + LastTotalPower: math.NewInt(5), + ConsensusAddrsToPrune: []types.EpochToConsensusAddrs{ + { + Epoch: 1, + ConsAddrs: []string{ + consAddr1.String(), + }, + }, + }, + }, + expPass: false, + expError: "should be > 1", + }, + { + name: "empty cons addrs for pruning", + genState: &types.GenesisState{ + Params: params, + ValSet: []types.GenesisValidator{ + { + PublicKey: sharedKey, + Power: 5, + }, + }, + LastTotalPower: math.NewInt(5), + ConsensusAddrsToPrune: []types.EpochToConsensusAddrs{ + { + Epoch: 2, + }, + }, + }, + expPass: false, + expError: "empty consensus addresses for epoch", + }, + { + name: "duplicate cons addrs for pruning", + genState: &types.GenesisState{ + Params: params, + ValSet: []types.GenesisValidator{ + { + PublicKey: sharedKey, + Power: 5, + }, + }, + LastTotalPower: math.NewInt(5), + ConsensusAddrsToPrune: []types.EpochToConsensusAddrs{ + { + Epoch: 2, + ConsAddrs: []string{ + consAddr1.String(), + consAddr1.String(), + }, + }, + }, + }, + expPass: false, + expError: "duplicate consensus address", + }, + { + name: "valid with pruning", + genState: &types.GenesisState{ + Params: params, + ValSet: []types.GenesisValidator{ { PublicKey: sharedKey, Power: 5, }, }, + LastTotalPower: math.NewInt(5), + ConsensusAddrsToPrune: []types.EpochToConsensusAddrs{ + { + Epoch: 2, + ConsAddrs: []string{ + consAddr1.String(), + }, + }, + }, }, expPass: true, }, + { + name: "invalid cons addrs for pruning", + genState: &types.GenesisState{ + Params: params, + ValSet: []types.GenesisValidator{ + { + PublicKey: sharedKey, + Power: 5, + }, + }, + LastTotalPower: math.NewInt(5), + ConsensusAddrsToPrune: []types.EpochToConsensusAddrs{ + { + Epoch: 2, + ConsAddrs: []string{ + "invalid cons address", + }, + }, + }, + }, + expPass: false, + expError: "invalid consensus address", + }, + { + name: "duplicate epoch in undelegations", + genState: &types.GenesisState{ + Params: params, + ValSet: []types.GenesisValidator{ + { + PublicKey: sharedKey, + Power: 5, + }, + }, + LastTotalPower: math.NewInt(5), + UndelegationMaturities: []types.EpochToUndelegationRecordKeys{ + { + Epoch: 2, + UndelegationRecordKeys: []string{ + recordKey, + }, + }, + { + Epoch: 2, + UndelegationRecordKeys: []string{ + recordKey, + }, + }, + }, + }, + expPass: false, + expError: "duplicate epoch", + }, + { + name: "epoch 1 for undelegations", + genState: &types.GenesisState{ + Params: params, + ValSet: []types.GenesisValidator{ + { + PublicKey: sharedKey, + Power: 5, + }, + }, + LastTotalPower: math.NewInt(5), + UndelegationMaturities: []types.EpochToUndelegationRecordKeys{ + { + Epoch: 1, + UndelegationRecordKeys: []string{ + recordKey, + }, + }, + }, + }, + expPass: false, + expError: "should be > 1", + }, + { + name: "empty record keys for undelegations", + genState: &types.GenesisState{ + Params: params, + ValSet: []types.GenesisValidator{ + { + PublicKey: sharedKey, + Power: 5, + }, + }, + LastTotalPower: math.NewInt(5), + UndelegationMaturities: []types.EpochToUndelegationRecordKeys{ + { + Epoch: 2, + }, + }, + }, + expPass: false, + expError: "empty record keys for epoch", + }, + { + name: "duplicate undelegation record keys", + genState: &types.GenesisState{ + Params: params, + ValSet: []types.GenesisValidator{ + { + PublicKey: sharedKey, + Power: 5, + }, + }, + LastTotalPower: math.NewInt(5), + UndelegationMaturities: []types.EpochToUndelegationRecordKeys{ + { + Epoch: 2, + UndelegationRecordKeys: []string{ + recordKey, + recordKey, + }, + }, + }, + }, + expPass: false, + expError: "duplicate record key", + }, + { + name: "valid with undelegation record key", + genState: &types.GenesisState{ + Params: params, + ValSet: []types.GenesisValidator{ + { + PublicKey: sharedKey, + Power: 5, + }, + }, + LastTotalPower: math.NewInt(5), + UndelegationMaturities: []types.EpochToUndelegationRecordKeys{ + { + Epoch: 2, + UndelegationRecordKeys: []string{ + recordKey, + }, + }, + }, + }, + expPass: true, + }, + { + name: "undelegation record key: not hex", + genState: &types.GenesisState{ + Params: params, + ValSet: []types.GenesisValidator{ + { + PublicKey: sharedKey, + Power: 5, + }, + }, + LastTotalPower: math.NewInt(5), + UndelegationMaturities: []types.EpochToUndelegationRecordKeys{ + { + Epoch: 2, + UndelegationRecordKeys: []string{ + "not hex", + }, + }, + }, + }, + expPass: false, + expError: "invalid record key (non hex)", + }, + { + name: "undelegation record key: can't parse", + genState: &types.GenesisState{ + Params: params, + ValSet: []types.GenesisValidator{ + { + PublicKey: sharedKey, + Power: 5, + }, + }, + LastTotalPower: math.NewInt(5), + UndelegationMaturities: []types.EpochToUndelegationRecordKeys{ + { + Epoch: 2, + UndelegationRecordKeys: []string{ + "0x1234", + }, + }, + }, + }, + expPass: false, + expError: "invalid record key (parse)", + }, } for _, tc := range testCases { @@ -154,6 +651,10 @@ func (suite *GenesisTestSuite) TestValidateGenesis() { suite.Require().NoError(err, tc.name) } else { suite.Require().Error(err, tc.name) + suite.Require().Condition(func() bool { + return len(tc.expError) > 0 + }, "expError not set for %s", tc.name) + suite.Require().ErrorContains(err, tc.expError, tc.name) } // fmt.Println(tc.name, err) } diff --git a/x/dogfood/types/keys.go b/x/dogfood/types/keys.go index 4e6b4c871..05852c96b 100644 --- a/x/dogfood/types/keys.go +++ b/x/dogfood/types/keys.go @@ -18,8 +18,9 @@ const ( // ExocoreValidatorBytePrefix is the prefix for the validator store. ExocoreValidatorBytePrefix byte = iota + 1 - // QueuedOperationsByte is the byte used to store the queue of operations. - QueuedOperationsByte + // QueuedOperationsByte was the byte used to store the queue of operations. + // It is no longer used, but it is retained for backward compatibility. + _ // OptOutsToFinishBytePrefix is the byte used to store the list of operator addresses whose // opt outs are maturing at the provided epoch. @@ -37,9 +38,10 @@ const ( // that will mature at the provided epoch. UnbondingReleaseMaturityBytePrefix - // PendingOperationsByte is the byte used to store the list of operations to be applied at - // the end of the current block. - PendingOperationsByte + // PendingOperationsByte was the byte used to store the list of operations to be applied at + // the end of the current block. It is no longer used, and is retained for backward + // compatibility. + _ // PendingOptOutsByte is the byte used to store the list of operator addresses whose opt // outs will be made effective at the end of the current block. @@ -74,11 +76,6 @@ func ExocoreValidatorKey(address sdk.AccAddress) []byte { return append([]byte{ExocoreValidatorBytePrefix}, address.Bytes()...) } -// QueuedOperationsKey returns the key for the queued operations store. -func QueuedOperationsKey() []byte { - return []byte{QueuedOperationsByte} -} - // OptOutsToFinishKey returns the key for the operator opt out maturity store (epoch -> list of // addresses). func OptOutsToFinishKey(epoch int64) ([]byte, bool) { @@ -124,11 +121,6 @@ func UnbondingReleaseMaturityKey(epoch int64) ([]byte, bool) { ), true } -// PendingOperationsKey returns the key for the pending operations store. -func PendingOperationsKey() []byte { - return []byte{PendingOperationsByte} -} - // PendingOptOutsKey returns the key for the pending opt-outs store. func PendingOptOutsKey() []byte { return []byte{PendingOptOutsByte} diff --git a/x/operator/client/cli/tx.go b/x/operator/client/cli/tx.go index 1131d7711..b36347d63 100644 --- a/x/operator/client/cli/tx.go +++ b/x/operator/client/cli/tx.go @@ -42,7 +42,6 @@ func NewTxCmd() *cobra.Command { // are they really a property of the operator or of the respective AVS? // operator vs dogfood vs appchain coordinator CmdSetConsKey(), - CmdInitConsKeyRemoval(), ) return txCmd } @@ -194,9 +193,10 @@ func buildCommission(rateStr, maxRateStr, maxChangeRateStr string) ( // CmdOptIntoAVS returns a CLI command handler for creating a OptIntoAVSReq transaction. func CmdOptIntoAVS() *cobra.Command { cmd := &cobra.Command{ - Use: "opt-into-avs ", - Short: "opt into an AVS by specifying its address or the chain id", - Args: cobra.ExactArgs(1), + Use: "opt-into-avs ", + Short: "opt into an AVS by specifying its address or the chain id, with an optional public key", + Example: "exocore tx operator opt-into-avs exocoretestnet_233-1 $(exocored tendermint show-validator)", + Args: cobra.RangeArgs(1, 2), RunE: func(cmd *cobra.Command, args []string) error { clientCtx, err := client.GetClientTxContext(cmd) if err != nil { @@ -206,6 +206,9 @@ func CmdOptIntoAVS() *cobra.Command { FromAddress: clientCtx.GetFromAddress().String(), AvsAddress: args[0], } + if len(args) == 2 { + msg.PublicKey = args[1] + } return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) }, } @@ -254,25 +257,3 @@ func CmdSetConsKey() *cobra.Command { } return cmd } - -// CmdInitConsKeyRemoval returns a CLI command handler for creating an InitConsKeyRemovalReq -// transaction. -func CmdInitConsKeyRemoval() *cobra.Command { - cmd := &cobra.Command{ - Use: "init-cons-key-removal ", - Short: "initiate consensus key removal for a chain", - Args: cobra.ExactArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - clientCtx, err := client.GetClientTxContext(cmd) - if err != nil { - return err - } - msg := &types.InitConsKeyRemovalReq{ - Address: clientCtx.GetFromAddress().String(), - ChainID: args[0], - } - return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) - }, - } - return cmd -} diff --git a/x/operator/keeper/consensus_keys.go b/x/operator/keeper/consensus_keys.go index 0f403b1fb..2816979d6 100644 --- a/x/operator/keeper/consensus_keys.go +++ b/x/operator/keeper/consensus_keys.go @@ -256,39 +256,19 @@ func (k Keeper) GetOperatorAddressForChainIDAndConsAddr( } // InitiateOperatorKeyRemovalForChainID initiates an operator removing their key from the -// chain id. It validates whether the operator is registered, and that it is not frozen, and -// that the chain is present within the system. It also checks if the operator is already -// removing the key. -// The operator must first call this method, and then call `OptOut` to complete the process. -// TODO: currently there is no penalty for operators failing to complete this and the data -// is also mismatched (ex: while the operator is removed from the validator set, the opt out -// height is the height of calling OptOut). We should rationalize this somehow. +// chain id. The caller must validate that the chainID is registered and that the address +// is an operator, that is not frozen, and that the operator is currently opted in. func (k *Keeper) InitiateOperatorKeyRemovalForChainID( ctx sdk.Context, opAccAddr sdk.AccAddress, chainID string, -) error { - // check if we are an operator - if !k.IsOperator(ctx, opAccAddr) { - return delegationtypes.ErrOperatorNotExist - } - // check for slashing - if k.slashKeeper.IsOperatorFrozen(ctx, opAccAddr) { - return delegationtypes.ErrOperatorIsFrozen - } - // check if the chain id is valid - if chainID != ctx.ChainID() { - return types.ErrUnknownChainID - } - found, key := k.getOperatorConsKeyForChainID(ctx, opAccAddr, chainID) - if !found { - return types.ErrNotOptedIn - } - if k.IsOperatorRemovingKeyFromChainID(ctx, opAccAddr, chainID) { - return types.ErrAlreadyRemovingKey - } +) { + // found will always be true, since the operator has registered into the chain + // and during registration a key must be set. + _, key := k.getOperatorConsKeyForChainID(ctx, opAccAddr, chainID) + // we don't check if the operator is already opted out, because this function + // can only be called if the operator is currently opted in. store := ctx.KVStore(k.storeKey) store.Set(types.KeyForOperatorKeyRemovalForChainID(opAccAddr, chainID), []byte{}) k.Hooks().AfterOperatorKeyRemovalInitiated(ctx, opAccAddr, chainID, key) - return nil } // IsOperatorRemovingKeyFromChainID returns true if the operator is removing the consensus diff --git a/x/operator/keeper/grpc_query.go b/x/operator/keeper/grpc_query.go index c8a5fcaea..30040819b 100644 --- a/x/operator/keeper/grpc_query.go +++ b/x/operator/keeper/grpc_query.go @@ -63,6 +63,7 @@ func (k *Keeper) QueryOperatorConsKeyForChainID( } return &operatortypes.QueryOperatorConsKeyResponse{ PublicKey: *key, + OptingOut: k.IsOperatorRemovingKeyFromChainID(ctx, addr, req.Chain), }, nil } @@ -91,7 +92,8 @@ func (k Keeper) QueryOperatorConsAddressForChainID( return nil, err } return &operatortypes.QueryOperatorConsAddressResponse{ - ConsAddr: consAddr.String(), + ConsAddr: consAddr.String(), + OptingOut: k.IsOperatorRemovingKeyFromChainID(ctx, addr, req.Chain), }, nil } @@ -118,6 +120,7 @@ func (k Keeper) QueryAllOperatorConsKeysByChainID( res = append(res, &operatortypes.OperatorConsKeyPair{ OperatorAccAddr: addr.String(), PublicKey: ret, + OptingOut: k.IsOperatorRemovingKeyFromChainID(ctx, addr, req.Chain), }) return nil }) @@ -157,6 +160,7 @@ func (k Keeper) QueryAllOperatorConsAddrsByChainID( res = append(res, &operatortypes.OperatorConsAddrPair{ OperatorAccAddr: addr.String(), ConsAddr: consAddr.String(), + OptingOut: k.IsOperatorRemovingKeyFromChainID(ctx, addr, req.Chain), }) return nil }) diff --git a/x/operator/keeper/msg_server.go b/x/operator/keeper/msg_server.go index b26fbe44f..2f79e3771 100644 --- a/x/operator/keeper/msg_server.go +++ b/x/operator/keeper/msg_server.go @@ -3,6 +3,7 @@ package keeper import ( context "context" + errorsmod "cosmossdk.io/errors" "github.com/ExocoreNetwork/exocore/x/operator/types" sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -20,23 +21,55 @@ func (k *Keeper) RegisterOperator(ctx context.Context, req *types.RegisterOperat } // OptIntoAVS is an implementation of the msg server for the operator module. -func (k Keeper) OptIntoAVS(ctx context.Context, req *types.OptIntoAVSReq) (*types.OptIntoAVSResponse, error) { - c := sdk.UnwrapSDKContext(ctx) +func (k Keeper) OptIntoAVS(ctx context.Context, req *types.OptIntoAVSReq) (res *types.OptIntoAVSResponse, err error) { + uncachedCtx := sdk.UnwrapSDKContext(ctx) + // only write if both calls succeed + c, writeFunc := uncachedCtx.CacheContext() + defer func() { + if err == nil { + writeFunc() + } + }() + // TODO: use some form of an AVS to key-type registry here, possibly from within the AVS module to determine + // if a key is required and that it is appropriately supplied. + if req.AvsAddress == c.ChainID() { + if len(req.PublicKey) == 0 { + return nil, errorsmod.Wrap(types.ErrInvalidPubKey, "a key is required but was not supplied") + } + } else { + if len(req.PublicKey) > 0 { + return nil, errorsmod.Wrap(types.ErrInvalidPubKey, "a key is not required but was supplied") + } + } // #nosec G703 // already validated accAddr, _ := sdk.AccAddressFromBech32(req.FromAddress) - err := k.OptIn(c, accAddr, req.AvsAddress) + err = k.OptIn(c, accAddr, req.AvsAddress) if err != nil { return nil, err } + if len(req.PublicKey) > 0 { + // we have to validate just the key; we previously validated that ctx.ChainID() == req.AvsAddress + keyObj, _ := types.ValidateConsensusKeyJSON(req.PublicKey) + if err := k.SetOperatorConsKeyForChainID(c, accAddr, req.AvsAddress, keyObj); err != nil { + return nil, err + } + } return &types.OptIntoAVSResponse{}, nil } // OptOutOfAVS is an implementation of the msg server for the operator module. -func (k Keeper) OptOutOfAVS(ctx context.Context, req *types.OptOutOfAVSReq) (*types.OptOutOfAVSResponse, error) { - c := sdk.UnwrapSDKContext(ctx) +func (k Keeper) OptOutOfAVS(ctx context.Context, req *types.OptOutOfAVSReq) (res *types.OptOutOfAVSResponse, err error) { + uncachedCtx := sdk.UnwrapSDKContext(ctx) + // only write if both calls succeed + c, writeFunc := uncachedCtx.CacheContext() + defer func() { + if err == nil { + writeFunc() + } + }() // #nosec G703 // already validated accAddr, _ := sdk.AccAddressFromBech32(req.FromAddress) - err := k.OptOut(c, accAddr, req.AvsAddress) + err = k.OptOut(c, accAddr, req.AvsAddress) if err != nil { return nil, err } @@ -48,24 +81,10 @@ func (k Keeper) SetConsKey(ctx context.Context, req *types.SetConsKeyReq) (*type c := sdk.UnwrapSDKContext(ctx) // #nosec G703 // already validated accAddr, _ := sdk.AccAddressFromBech32(req.Address) - // #nosec G703 // already validated, including type - _, keyString, _ := types.ParseConsensusKeyFromJSON(req.PublicKey) // #nosec G703 // already validated - keyObj, _ := types.StringToPubKey(keyString) + keyObj, _ := types.ValidateConsensusKeyJSON(req.PublicKey) if err := k.SetOperatorConsKeyForChainID(c, accAddr, req.ChainID, keyObj); err != nil { return nil, err } return &types.SetConsKeyResponse{}, nil } - -// InitConsKeyRemoval is an implementation of the msg server for the operator module. -func (k Keeper) InitConsKeyRemoval(ctx context.Context, req *types.InitConsKeyRemovalReq) (*types.InitConsKeyRemovalResponse, error) { - c := sdk.UnwrapSDKContext(ctx) - // #nosec G703 // already validated - accAddr, _ := sdk.AccAddressFromBech32(req.Address) - err := k.InitiateOperatorKeyRemovalForChainID(c, accAddr, req.ChainID) - if err != nil { - return nil, err - } - return &types.InitConsKeyRemovalResponse{}, nil -} diff --git a/x/operator/keeper/operator.go b/x/operator/keeper/operator.go index e0e7afa29..20fde39a2 100644 --- a/x/operator/keeper/operator.go +++ b/x/operator/keeper/operator.go @@ -157,10 +157,7 @@ func (k *Keeper) IsOptedIn(ctx sdk.Context, operatorAddr, avsAddr string) bool { if err != nil { return false } - if optedInfo.OptedOutHeight != operatortypes.DefaultOptedOutHeight { - return false - } - return true + return optedInfo.OptedOutHeight == operatortypes.DefaultOptedOutHeight } func (k *Keeper) IsActive(ctx sdk.Context, operatorAddr sdk.AccAddress, avsAddr string) bool { @@ -177,10 +174,6 @@ func (k *Keeper) IsActive(ctx sdk.Context, operatorAddr sdk.AccAddress, avsAddr // frozen - either temporarily or permanently return false } - if avsAddr == ctx.ChainID() { - // if in the process of opting out, return false - return !k.IsOperatorRemovingKeyFromChainID(ctx, operatorAddr, avsAddr) - } return true } diff --git a/x/operator/keeper/opt.go b/x/operator/keeper/opt.go index 2bfcff6b0..1c474a447 100644 --- a/x/operator/keeper/opt.go +++ b/x/operator/keeper/opt.go @@ -57,7 +57,20 @@ func (k *Keeper) OptIn(ctx sdk.Context, operatorAddress sdk.AccAddress, avsAddr } // OptOut call this function to opt out of AVS -func (k *Keeper) OptOut(ctx sdk.Context, operatorAddress sdk.AccAddress, avsAddr string) error { +func (k *Keeper) OptOut(ctx sdk.Context, operatorAddress sdk.AccAddress, avsAddr string) (err error) { + // avsAddr should be an evm contract address or a chain id. + if !common.IsHexAddress(avsAddr) { + if avsAddr != ctx.ChainID() { // TODO: other chain ids besides this chain's. + return types.ErrInvalidAvsAddr + } + defer func() { + if err == nil { + // does not fail, because it performs no validations, just stores a key-value pair. + // all validations are instead performed by this function. + k.InitiateOperatorKeyRemovalForChainID(ctx, operatorAddress, avsAddr) + } + }() + } if !k.IsOperator(ctx, operatorAddress) { return delegationtypes.ErrOperatorNotExist } @@ -65,26 +78,15 @@ func (k *Keeper) OptOut(ctx sdk.Context, operatorAddress sdk.AccAddress, avsAddr if !k.IsOptedIn(ctx, operatorAddress.String(), avsAddr) { return types.ErrNotOptedIn } - if !common.IsHexAddress(avsAddr) { - if avsAddr == ctx.ChainID() { - found, _ := k.getOperatorConsKeyForChainID(ctx, operatorAddress, avsAddr) - if found { - // if the key exists, it should be in the process of being removed. - // TODO: if slashing is moved to a snapshot approach, opt out should only be - // performed if the key doesn't exist. - if !k.IsOperatorRemovingKeyFromChainID(ctx, operatorAddress, avsAddr) { - return types.ErrOperatorNotRemovingKey - } - } - } else { - return types.ErrInvalidAvsAddr - } + // do not allow frozen operators to do anything meaningful + if k.slashKeeper.IsOperatorFrozen(ctx, operatorAddress) { + return delegationtypes.ErrOperatorIsFrozen } // DeleteOperatorUSDValue, delete the operator voting power, it can facilitate to // update the voting powers of all opted-in operators at the end of epoch. // there isn't going to be any reward for the operator in this opted-out epoch. - err := k.DeleteOperatorUSDValue(ctx, avsAddr, operatorAddress.String()) + err = k.DeleteOperatorUSDValue(ctx, avsAddr, operatorAddress.String()) if err != nil { return err } @@ -93,6 +95,10 @@ func (k *Keeper) OptOut(ctx sdk.Context, operatorAddress sdk.AccAddress, avsAddr handleFunc := func(info *types.OptedInfo) { // #nosec G701 info.OptedOutHeight = uint64(ctx.BlockHeight()) + // the opt out, although is requested now, is made effective at the end of the current epoch. + // so this is not necessarily the OptedOutHeight, rather, it is the OptOutRequestHeight. + // the height is not directly used, beyond ascertaining whether the operator is currently opted in/out. + // so the difference due to the epoch scheduling is not too big a concern. } err = k.HandleOptedInfo(ctx, operatorAddress.String(), avsAddr, handleFunc) if err != nil { diff --git a/x/operator/types/codec.go b/x/operator/types/codec.go index 97cd63bab..c070cb825 100644 --- a/x/operator/types/codec.go +++ b/x/operator/types/codec.go @@ -35,7 +35,6 @@ func RegisterInterfaces(registry codectypes.InterfaceRegistry) { &OptIntoAVSReq{}, &OptOutOfAVSReq{}, &SetConsKeyReq{}, - &InitConsKeyRemovalReq{}, ) msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc) } diff --git a/x/operator/types/consensus_keys.go b/x/operator/types/consensus_keys.go index a0a2b05dc..b02123877 100644 --- a/x/operator/types/consensus_keys.go +++ b/x/operator/types/consensus_keys.go @@ -79,3 +79,17 @@ func TMCryptoPublicKeyToConsAddr(k *tmprotocrypto.PublicKey) (sdk.ConsAddress, e } return sdk.GetConsAddress(sdkK), nil } + +// ValidateConsensusKey checks that the key is a JSON with `@type` and `key` keys +// with the former bearing exactly value `/cosmos.crypto.ed25519.PubKey`, and the +// latter being a valid base64-encoded public key. +func ValidateConsensusKeyJSON(key string) (res *tmprotocrypto.PublicKey, err error) { + if keyType, keyString, err := ParseConsensusKeyFromJSON(key); err != nil { + return nil, errorsmod.Wrap(err, "invalid public key") + } else if keyType != "/cosmos.crypto.ed25519.PubKey" { + return nil, errorsmod.Wrap(ErrParameterInvalid, "invalid public key type") + } else if res, err = StringToPubKey(keyString); err != nil { + return nil, errorsmod.Wrap(err, "invalid public key") + } + return res, nil +} diff --git a/x/operator/types/msg.go b/x/operator/types/msg.go index bcefbf5df..588fb4f16 100644 --- a/x/operator/types/msg.go +++ b/x/operator/types/msg.go @@ -12,8 +12,6 @@ const ( TypeRegisterOperatorReq = "register_operator" // TypeSetConsKeyReq is the type for the SetConsKeyReq message. TypeSetConsKeyReq = "set_cons_key" - // TypeInitConsKeyRemovalReq is the type for the InitConsKeyRemovalReq message. - TypeInitConsKeyRemovalReq = "init_cons_key_removal" // TypeOptIntoAVSReq is the type for the OptIntoAVSReq message. TypeOptIntoAVSReq = "opt_into_avs" // TypeOptOutOfAVSReq is the type for the OptOutOfAVSReq message. @@ -26,7 +24,6 @@ var ( _ sdk.Msg = &OptIntoAVSReq{} _ sdk.Msg = &OptOutOfAVSReq{} _ sdk.Msg = &SetConsKeyReq{} - _ sdk.Msg = &InitConsKeyRemovalReq{} ) // GetSigners returns the expected signers for the message. @@ -72,12 +69,8 @@ func (m *SetConsKeyReq) ValidateBasic() error { if !types.IsValidChainID(m.ChainID) { return errorsmod.Wrap(ErrParameterInvalid, "invalid chain id") } - if keyType, keyString, err := ParseConsensusKeyFromJSON(m.PublicKey); err != nil { - return errorsmod.Wrap(err, "invalid public key") - } else if keyType != "/cosmos.crypto.ed25519.PubKey" { - return errorsmod.Wrap(ErrParameterInvalid, "invalid public key type") - } else if _, err := StringToPubKey(keyString); err != nil { - return errorsmod.Wrap(err, "invalid public key") + if _, err := ValidateConsensusKeyJSON(m.PublicKey); err != nil { + return errorsmod.Wrapf(ErrParameterInvalid, "invalid public key because %s", err) } return nil } @@ -97,38 +90,6 @@ func (m *SetConsKeyReq) GetSignBytes() []byte { return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(m)) } -// GetSigners returns the expected signers for the message. -func (m *InitConsKeyRemovalReq) GetSigners() []sdk.AccAddress { - addr := sdk.MustAccAddressFromBech32(m.Address) - return []sdk.AccAddress{addr} -} - -// ValidateBasic does a sanity check of the provided data -func (m *InitConsKeyRemovalReq) ValidateBasic() error { - if _, err := sdk.AccAddressFromBech32(m.Address); err != nil { - return errorsmod.Wrap(err, "invalid from address") - } - if !types.IsValidChainID(m.ChainID) { - return errorsmod.Wrap(ErrParameterInvalid, "invalid chain id") - } - return nil -} - -// Route returns the transaction route. -func (m *InitConsKeyRemovalReq) Route() string { - return RouterKey -} - -// Type returns the transaction type. -func (m *InitConsKeyRemovalReq) Type() string { - return TypeInitConsKeyRemovalReq -} - -// GetSignBytes returns the bytes all expected signers must sign over. -func (m *InitConsKeyRemovalReq) GetSignBytes() []byte { - return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(m)) -} - // GetSigners returns the expected signers for the message. func (m *OptIntoAVSReq) GetSigners() []sdk.AccAddress { addr := sdk.MustAccAddressFromBech32(m.FromAddress) diff --git a/x/operator/types/query.pb.go b/x/operator/types/query.pb.go index 8c82284c4..63ed4f8e5 100644 --- a/x/operator/types/query.pb.go +++ b/x/operator/types/query.pb.go @@ -240,6 +240,8 @@ func (m *QueryOperatorConsKeyRequest) GetChain() string { type QueryOperatorConsKeyResponse struct { // public_key is the consensus public key of the operator. PublicKey crypto.PublicKey `protobuf:"bytes,1,opt,name=public_key,json=publicKey,proto3" json:"public_key"` + // opting_out is a flag to indicate if the operator is opting out of consensus. + OptingOut bool `protobuf:"varint,2,opt,name=opting_out,json=optingOut,proto3" json:"opting_out,omitempty"` } func (m *QueryOperatorConsKeyResponse) Reset() { *m = QueryOperatorConsKeyResponse{} } @@ -282,6 +284,13 @@ func (m *QueryOperatorConsKeyResponse) GetPublicKey() crypto.PublicKey { return crypto.PublicKey{} } +func (m *QueryOperatorConsKeyResponse) GetOptingOut() bool { + if m != nil { + return m.OptingOut + } + return false +} + // QueryOperatorConsAddressRequest is the request to obtain the consensus address of the operator // for a specific chain ID. type QueryOperatorConsAddressRequest struct { @@ -345,6 +354,8 @@ type QueryOperatorConsAddressResponse struct { // cons_addr is the consensus address corresponding to the consensus public key // currently in use by the operator. ConsAddr string `protobuf:"bytes,1,opt,name=cons_addr,json=consAddr,proto3" json:"cons_addr,omitempty"` + // opting_out is a flag to indicate if the operator is opting out of consensus. + OptingOut bool `protobuf:"varint,2,opt,name=opting_out,json=optingOut,proto3" json:"opting_out,omitempty"` } func (m *QueryOperatorConsAddressResponse) Reset() { *m = QueryOperatorConsAddressResponse{} } @@ -387,6 +398,13 @@ func (m *QueryOperatorConsAddressResponse) GetConsAddr() string { return "" } +func (m *QueryOperatorConsAddressResponse) GetOptingOut() bool { + if m != nil { + return m.OptingOut + } + return false +} + // QueryAllOperatorConsKeysByChainIDRequest is the request to obtain all operator addresses // and consensus keys for a specific chain ID, with pagination. type QueryAllOperatorConsKeysByChainIDRequest struct { @@ -514,6 +532,8 @@ type OperatorConsKeyPair struct { OperatorAccAddr string `protobuf:"bytes,1,opt,name=operator_acc_addr,json=operatorAccAddr,proto3" json:"operator_acc_addr,omitempty"` // public_key is the consensus public key of the operator. PublicKey *crypto.PublicKey `protobuf:"bytes,2,opt,name=public_key,json=publicKey,proto3" json:"public_key,omitempty"` + // opting_out is a flag to indicate if the operator is opting out of consensus. + OptingOut bool `protobuf:"varint,3,opt,name=opting_out,json=optingOut,proto3" json:"opting_out,omitempty"` } func (m *OperatorConsKeyPair) Reset() { *m = OperatorConsKeyPair{} } @@ -563,6 +583,13 @@ func (m *OperatorConsKeyPair) GetPublicKey() *crypto.PublicKey { return nil } +func (m *OperatorConsKeyPair) GetOptingOut() bool { + if m != nil { + return m.OptingOut + } + return false +} + // QueryAllOperatorConsAddrsByChainIDRequest is the request to obtain all operator addresses // and consensus addresses for a specific chain ID, with pagination. type QueryAllOperatorConsAddrsByChainIDRequest struct { @@ -692,6 +719,8 @@ type OperatorConsAddrPair struct { // cons_addr is the consensus address corresponding to the consensus public key // currently in use by the operator. ConsAddr string `protobuf:"bytes,2,opt,name=cons_addr,json=consAddr,proto3" json:"cons_addr,omitempty"` + // opting_out is a flag to indicate if the operator is opting out of consensus. + OptingOut bool `protobuf:"varint,3,opt,name=opting_out,json=optingOut,proto3" json:"opting_out,omitempty"` } func (m *OperatorConsAddrPair) Reset() { *m = OperatorConsAddrPair{} } @@ -741,6 +770,13 @@ func (m *OperatorConsAddrPair) GetConsAddr() string { return "" } +func (m *OperatorConsAddrPair) GetOptingOut() bool { + if m != nil { + return m.OptingOut + } + return false +} + func init() { proto.RegisterType((*GetOperatorInfoReq)(nil), "exocore.operator.v1.GetOperatorInfoReq") proto.RegisterType((*QueryAllOperatorsRequest)(nil), "exocore.operator.v1.QueryAllOperatorsRequest") @@ -760,63 +796,65 @@ func init() { func init() { proto.RegisterFile("exocore/operator/v1/query.proto", fileDescriptor_f91e795a3cecbdbf) } var fileDescriptor_f91e795a3cecbdbf = []byte{ - // 891 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x56, 0xdf, 0x4f, 0xd3, 0x50, - 0x14, 0x5e, 0xa7, 0x18, 0x77, 0xd1, 0x28, 0x97, 0x3d, 0x8c, 0x42, 0x06, 0x34, 0x46, 0xc6, 0x22, - 0xad, 0x1b, 0xe0, 0x83, 0x88, 0x84, 0xf1, 0x2b, 0x88, 0x51, 0x2c, 0x89, 0x89, 0xbe, 0x2c, 0x5d, - 0x77, 0x29, 0x0d, 0xa3, 0xb7, 0xb4, 0x1d, 0xd2, 0x10, 0x7c, 0xf0, 0x49, 0xdf, 0x8c, 0x3e, 0x9a, - 0xf8, 0x57, 0xf8, 0x1f, 0xf8, 0xc2, 0x83, 0x0f, 0xa8, 0x2f, 0x3e, 0xa1, 0x61, 0xfe, 0x21, 0xa6, - 0xb7, 0xb7, 0x5b, 0x3b, 0xba, 0xad, 0x23, 0xc4, 0xb7, 0xb5, 0x3d, 0xf7, 0x7c, 0xdf, 0x77, 0xce, - 0x77, 0xcf, 0x19, 0x18, 0x46, 0xfb, 0x58, 0xc6, 0x06, 0x12, 0xb0, 0x8e, 0x0c, 0xc9, 0xc2, 0x86, - 0xb0, 0x97, 0x13, 0x76, 0xab, 0xc8, 0xb0, 0x79, 0xdd, 0xc0, 0x16, 0x86, 0xfd, 0x34, 0x80, 0xf7, - 0x02, 0xf8, 0xbd, 0x1c, 0x9b, 0x95, 0xb1, 0xb9, 0x83, 0x4d, 0xa1, 0x24, 0x99, 0xc8, 0x8d, 0x16, - 0xf6, 0x72, 0x25, 0x64, 0x49, 0x39, 0x41, 0x97, 0x14, 0x55, 0x93, 0x2c, 0x15, 0x6b, 0x6e, 0x02, - 0x76, 0xc0, 0x8d, 0x2d, 0x92, 0x27, 0xc1, 0x7d, 0xa0, 0x9f, 0x86, 0xc2, 0xc0, 0xad, 0x7d, 0xfa, - 0x35, 0xa9, 0x60, 0x05, 0xbb, 0xa7, 0x9c, 0x5f, 0xde, 0x19, 0x05, 0x63, 0xa5, 0x82, 0x04, 0x49, - 0x57, 0x05, 0x49, 0xd3, 0xb0, 0x45, 0xb0, 0xea, 0x19, 0x2d, 0xa4, 0x95, 0x91, 0xb1, 0xa3, 0x6a, - 0x96, 0x20, 0x1b, 0xb6, 0x6e, 0x61, 0x61, 0x1b, 0xd9, 0xf4, 0x2b, 0xb7, 0x01, 0xe0, 0x0a, 0xb2, - 0x9e, 0x52, 0xb0, 0x55, 0x6d, 0x13, 0x8b, 0x68, 0x17, 0xce, 0x82, 0xeb, 0x1e, 0x7e, 0x51, 0x2a, - 0x97, 0x8d, 0x14, 0x33, 0xc2, 0x64, 0x12, 0x85, 0xd4, 0x8f, 0x2f, 0x13, 0x49, 0x4a, 0x77, 0xbe, - 0x5c, 0x36, 0x90, 0x69, 0x6e, 0x58, 0x86, 0xaa, 0x29, 0xe2, 0x35, 0x2f, 0xdc, 0x79, 0xcd, 0x95, - 0x40, 0xea, 0x99, 0x53, 0x81, 0xf9, 0x4a, 0xc5, 0xcb, 0x6c, 0x8a, 0x68, 0xb7, 0x8a, 0x4c, 0x0b, - 0x2e, 0x03, 0xd0, 0xa8, 0x07, 0xc9, 0xdb, 0x9b, 0xbf, 0xcd, 0xd3, 0xa4, 0x4e, 0xf1, 0x78, 0xb7, - 0xd4, 0xb4, 0x78, 0xfc, 0xba, 0xa4, 0x20, 0x7a, 0x56, 0xf4, 0x9d, 0xe4, 0x3e, 0x30, 0x60, 0x20, - 0x04, 0xc4, 0xd4, 0xb1, 0x66, 0x22, 0x78, 0x07, 0xc0, 0x86, 0x00, 0x59, 0x26, 0x22, 0xcc, 0x14, - 0x33, 0x72, 0x29, 0x93, 0x10, 0x6f, 0xd6, 0xb9, 0xca, 0xb2, 0x43, 0xd7, 0x84, 0x2b, 0x01, 0x4e, - 0x71, 0xc2, 0x69, 0xac, 0x23, 0x27, 0x17, 0x2a, 0x40, 0xaa, 0x08, 0x06, 0x09, 0x27, 0x8f, 0xd0, - 0x02, 0xd6, 0xcc, 0x35, 0x64, 0x7b, 0xda, 0xb3, 0xa0, 0xef, 0x0c, 0x2b, 0xb7, 0xb4, 0xe2, 0x8d, - 0x26, 0x52, 0x30, 0x09, 0x7a, 0xe4, 0x2d, 0x49, 0x75, 0xe9, 0x24, 0x44, 0xf7, 0x81, 0x93, 0xc0, - 0x50, 0x38, 0x00, 0xd5, 0x3d, 0x0f, 0x80, 0x5e, 0x2d, 0x55, 0x54, 0xb9, 0xb8, 0x8d, 0x6c, 0x5a, - 0xdd, 0x21, 0xbe, 0xe1, 0x00, 0xde, 0x75, 0x00, 0xbf, 0x4e, 0x82, 0xd6, 0x90, 0x5d, 0xb8, 0x7c, - 0x74, 0x32, 0x1c, 0x13, 0x13, 0xba, 0xf7, 0x82, 0x93, 0xc1, 0xf0, 0x19, 0x08, 0xda, 0xec, 0x8b, - 0xd3, 0x31, 0x07, 0x46, 0x5a, 0x83, 0x50, 0x2d, 0x83, 0x20, 0x21, 0x63, 0xcd, 0xf4, 0x67, 0xbf, - 0x2a, 0xd3, 0x38, 0xee, 0x2d, 0x03, 0x32, 0xcd, 0xed, 0xa7, 0xc5, 0x30, 0x0b, 0xf6, 0x82, 0x03, - 0xb2, 0xba, 0xe8, 0xf1, 0xad, 0x73, 0x60, 0x7c, 0x1c, 0x9a, 0x9c, 0x18, 0x3f, 0xb7, 0x13, 0xbf, - 0x31, 0x60, 0x3c, 0x02, 0x15, 0xaa, 0xea, 0xb9, 0xcf, 0x99, 0x44, 0x9e, 0x73, 0x19, 0x89, 0x33, - 0x7b, 0xf3, 0x19, 0x3e, 0x64, 0xb2, 0xf0, 0x4d, 0x39, 0xd7, 0x25, 0xd5, 0x68, 0x78, 0xd8, 0x03, - 0xba, 0x38, 0x0f, 0xbf, 0x06, 0xfd, 0x21, 0x88, 0x5d, 0xf5, 0x7c, 0x26, 0xe0, 0xc2, 0x78, 0x67, - 0x17, 0xfa, 0xfd, 0xf7, 0xae, 0x45, 0x39, 0xc9, 0x55, 0xfd, 0xcf, 0xad, 0x3d, 0x66, 0x40, 0x36, - 0x0a, 0x17, 0xda, 0xdb, 0x17, 0xa0, 0x3f, 0xd8, 0xdb, 0xc6, 0xd8, 0xe9, 0xcd, 0x8f, 0x77, 0x6c, - 0xae, 0x93, 0x95, 0x74, 0xb7, 0x0f, 0x37, 0x63, 0x5d, 0xe4, 0x88, 0x4a, 0x86, 0x61, 0x76, 0xd5, - 0xdf, 0xc0, 0xcd, 0x8c, 0x07, 0x6f, 0x66, 0xfe, 0x6b, 0x02, 0xf4, 0x90, 0x9a, 0xc1, 0x4f, 0x0c, - 0xe8, 0x0b, 0xdc, 0x72, 0x67, 0xbd, 0xc0, 0xb1, 0xd0, 0x3a, 0x9c, 0x5d, 0x42, 0xec, 0x68, 0xdb, - 0x82, 0x39, 0x51, 0xdc, 0xfd, 0x37, 0x3f, 0xff, 0x7e, 0x8c, 0x4f, 0xc1, 0xbc, 0x10, 0xb6, 0x36, - 0xeb, 0x7a, 0x54, 0x6d, 0x13, 0x0b, 0x07, 0x81, 0x8d, 0x76, 0x08, 0x3f, 0x7b, 0xec, 0xfc, 0x0b, - 0x04, 0x4e, 0x84, 0x82, 0xb6, 0xda, 0x66, 0x2c, 0x1f, 0x35, 0xdc, 0xed, 0x04, 0x97, 0x25, 0x84, - 0x6f, 0x41, 0x2e, 0x94, 0xb0, 0x54, 0xa9, 0x14, 0x71, 0x9d, 0xca, 0x77, 0x06, 0xa4, 0xc3, 0x86, - 0xfd, 0x32, 0x36, 0xa8, 0xf1, 0xe0, 0xdd, 0xd6, 0xf0, 0xe1, 0x2b, 0x88, 0xcd, 0x75, 0x71, 0x82, - 0x72, 0x7e, 0x44, 0x38, 0x2f, 0xc2, 0x42, 0xfb, 0x22, 0x7b, 0xc3, 0xcc, 0x5f, 0x68, 0xea, 0xa3, - 0x43, 0xe1, 0x80, 0xdc, 0xcb, 0x43, 0x78, 0xc2, 0x00, 0xae, 0xd5, 0xe0, 0xf7, 0xe9, 0x9a, 0x8a, - 0xc6, 0x32, 0xb8, 0x96, 0xd8, 0xe9, 0x2e, 0x4f, 0x51, 0x7d, 0x6b, 0x44, 0xdf, 0x12, 0x5c, 0x88, - 0xa0, 0xcf, 0x51, 0xd3, 0x56, 0xe0, 0x6f, 0x06, 0x8c, 0x76, 0x5c, 0x06, 0x70, 0x36, 0x92, 0x6d, - 0x5a, 0xed, 0x33, 0xf6, 0xe1, 0x79, 0x8f, 0x53, 0xc5, 0x33, 0x44, 0xf1, 0x34, 0x9c, 0xec, 0xe8, - 0xc2, 0xc6, 0x8a, 0xaa, 0x2b, 0xac, 0x79, 0x2d, 0x6c, 0x3b, 0x13, 0x61, 0x74, 0x8e, 0xa1, 0x83, - 0x9d, 0x9d, 0x3b, 0xf7, 0x79, 0x2a, 0xf2, 0x01, 0x11, 0x79, 0x0f, 0x4e, 0x45, 0x14, 0x49, 0x66, - 0xb5, 0xa7, 0xb2, 0xf0, 0xf8, 0xe8, 0x34, 0xcd, 0x1c, 0x9f, 0xa6, 0x99, 0x3f, 0xa7, 0x69, 0xe6, - 0x7d, 0x2d, 0x1d, 0x3b, 0xae, 0xa5, 0x63, 0xbf, 0x6a, 0xe9, 0xd8, 0xcb, 0xbc, 0xa2, 0x5a, 0x5b, - 0xd5, 0x12, 0x2f, 0xe3, 0x1d, 0x61, 0xc9, 0xcd, 0xfc, 0x04, 0x59, 0xaf, 0xb0, 0xb1, 0x5d, 0x07, - 0xda, 0x6f, 0x40, 0x59, 0xb6, 0x8e, 0xcc, 0xd2, 0x15, 0xf2, 0x67, 0x7b, 0xf2, 0x5f, 0x00, 0x00, - 0x00, 0xff, 0xff, 0xae, 0x71, 0x00, 0xfa, 0x5b, 0x0c, 0x00, 0x00, + // 928 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x56, 0xcf, 0x4f, 0xe3, 0x46, + 0x14, 0xce, 0x84, 0x52, 0x91, 0xa1, 0x55, 0xcb, 0x90, 0x43, 0x30, 0x34, 0x80, 0x55, 0x95, 0x10, + 0x15, 0xbb, 0x09, 0xd0, 0x43, 0x29, 0xad, 0x08, 0xbf, 0x44, 0xa9, 0x0a, 0x35, 0x52, 0xa5, 0xf6, + 0xd0, 0xc8, 0x71, 0x06, 0x63, 0x11, 0x3c, 0xc6, 0x9e, 0x50, 0x2c, 0x44, 0x55, 0xf5, 0xd4, 0xde, + 0xaa, 0xf6, 0x58, 0xb5, 0x7f, 0xc5, 0xfe, 0x07, 0x7b, 0xe1, 0xb0, 0x07, 0x76, 0xf7, 0xb2, 0x27, + 0x76, 0x45, 0xf6, 0x0f, 0x59, 0x79, 0x3c, 0x4e, 0xe2, 0xe0, 0x24, 0x0e, 0x42, 0x7b, 0x8b, 0xed, + 0x37, 0xef, 0xfb, 0xbe, 0xf7, 0xbe, 0x79, 0x2f, 0x70, 0x1a, 0x9f, 0x13, 0x8d, 0xd8, 0x58, 0x26, + 0x16, 0xb6, 0x55, 0x4a, 0x6c, 0xf9, 0xac, 0x20, 0x9f, 0xd6, 0xb1, 0xed, 0x4a, 0x96, 0x4d, 0x28, + 0x41, 0xe3, 0x3c, 0x40, 0x0a, 0x02, 0xa4, 0xb3, 0x82, 0x90, 0xd7, 0x88, 0x73, 0x42, 0x1c, 0xb9, + 0xa2, 0x3a, 0xd8, 0x8f, 0x96, 0xcf, 0x0a, 0x15, 0x4c, 0xd5, 0x82, 0x6c, 0xa9, 0xba, 0x61, 0xaa, + 0xd4, 0x20, 0xa6, 0x9f, 0x40, 0x98, 0xf0, 0x63, 0xcb, 0xec, 0x49, 0xf6, 0x1f, 0xf8, 0xa7, 0xa9, + 0x28, 0x70, 0x7a, 0xce, 0xbf, 0xa6, 0x75, 0xa2, 0x13, 0xff, 0x94, 0xf7, 0x2b, 0x38, 0xa3, 0x13, + 0xa2, 0xd7, 0xb0, 0xac, 0x5a, 0x86, 0xac, 0x9a, 0x26, 0xa1, 0x0c, 0xab, 0x99, 0x91, 0x62, 0xb3, + 0x8a, 0xed, 0x13, 0xc3, 0xa4, 0xb2, 0x66, 0xbb, 0x16, 0x25, 0xf2, 0x31, 0x76, 0xf9, 0x57, 0xf1, + 0x00, 0xa2, 0x6d, 0x4c, 0xf7, 0x38, 0xd8, 0x8e, 0x79, 0x48, 0x14, 0x7c, 0x8a, 0x56, 0xe1, 0xfb, + 0x01, 0x7e, 0x59, 0xad, 0x56, 0xed, 0x0c, 0x98, 0x01, 0xb9, 0x54, 0x29, 0xf3, 0xec, 0xd1, 0x42, + 0x9a, 0xd3, 0x5d, 0xab, 0x56, 0x6d, 0xec, 0x38, 0x07, 0xd4, 0x36, 0x4c, 0x5d, 0x79, 0x2f, 0x08, + 0xf7, 0x5e, 0x8b, 0x15, 0x98, 0xf9, 0xde, 0xab, 0xc0, 0x5a, 0xad, 0x16, 0x64, 0x76, 0x14, 0x7c, + 0x5a, 0xc7, 0x0e, 0x45, 0x5b, 0x10, 0xb6, 0xea, 0xc1, 0xf2, 0x8e, 0x16, 0x3f, 0x91, 0x78, 0x52, + 0xaf, 0x78, 0x92, 0x5f, 0x6a, 0x5e, 0x3c, 0x69, 0x5f, 0xd5, 0x31, 0x3f, 0xab, 0xb4, 0x9d, 0x14, + 0xff, 0x06, 0x70, 0x22, 0x02, 0xc4, 0xb1, 0x88, 0xe9, 0x60, 0xf4, 0x29, 0x44, 0x2d, 0x01, 0x9a, + 0xc6, 0x44, 0x38, 0x19, 0x30, 0x33, 0x94, 0x4b, 0x29, 0x1f, 0x36, 0xb9, 0x6a, 0x9a, 0x47, 0xd7, + 0x41, 0xdb, 0x21, 0x4e, 0x49, 0xc6, 0x69, 0xae, 0x2f, 0x27, 0x1f, 0x2a, 0x44, 0xaa, 0x0c, 0x27, + 0x19, 0xa7, 0x80, 0xd0, 0x3a, 0x31, 0x9d, 0x5d, 0xec, 0x06, 0xda, 0xf3, 0x70, 0xec, 0x0e, 0x2b, + 0xbf, 0xb4, 0xca, 0x07, 0x1d, 0xa4, 0x50, 0x1a, 0x0e, 0x6b, 0x47, 0xaa, 0xe1, 0xd3, 0x49, 0x29, + 0xfe, 0x83, 0xf8, 0x1b, 0x80, 0x53, 0xd1, 0x08, 0x5c, 0xf8, 0x1a, 0x84, 0x56, 0xbd, 0x52, 0x33, + 0xb4, 0xf2, 0x31, 0x76, 0x79, 0x79, 0xa7, 0xa4, 0x96, 0x05, 0x24, 0xdf, 0x02, 0xd2, 0x3e, 0x0b, + 0xda, 0xc5, 0x6e, 0xe9, 0x9d, 0xab, 0x9b, 0xe9, 0x84, 0x92, 0xb2, 0x82, 0x17, 0xe8, 0x23, 0x08, + 0x89, 0x45, 0x0d, 0x53, 0x2f, 0x93, 0x3a, 0x65, 0xf0, 0x23, 0x4a, 0xca, 0x7f, 0xb3, 0x57, 0xa7, + 0xa2, 0x06, 0xa7, 0xef, 0x30, 0xe0, 0x66, 0x78, 0x38, 0x9d, 0x3f, 0xc3, 0x99, 0xee, 0x20, 0x5c, + 0xea, 0x24, 0x4c, 0x69, 0xc4, 0x74, 0xda, 0xb3, 0x8f, 0x68, 0x3c, 0xae, 0x9f, 0x88, 0x3f, 0x00, + 0xcc, 0x75, 0xba, 0x87, 0x97, 0xd2, 0x29, 0xb9, 0xeb, 0x1e, 0x87, 0x9d, 0x8d, 0x40, 0x4e, 0x93, + 0x22, 0x68, 0xa3, 0xd8, 0x61, 0xe4, 0xe4, 0xbd, 0x8d, 0xfc, 0x04, 0xc0, 0xf9, 0x18, 0x54, 0xb8, + 0xe8, 0x1f, 0xda, 0x8c, 0xcd, 0xd4, 0x7b, 0x77, 0x99, 0x19, 0x7b, 0xb4, 0x98, 0x93, 0x22, 0x06, + 0x93, 0xd4, 0x91, 0x73, 0x5f, 0x35, 0xec, 0xd6, 0x15, 0x08, 0x80, 0x1e, 0xee, 0x0a, 0xfc, 0x07, + 0xe0, 0x78, 0x04, 0xe4, 0x40, 0x9e, 0x58, 0x09, 0x99, 0x38, 0xd9, 0xdf, 0xc4, 0xdd, 0xed, 0x3b, + 0xd4, 0xd9, 0xf9, 0x3f, 0xbb, 0x94, 0x9b, 0x4d, 0x82, 0xb7, 0xdc, 0xfa, 0x6b, 0x00, 0xf3, 0x71, + 0xb8, 0xf0, 0xde, 0xff, 0x08, 0xc7, 0xc3, 0xbd, 0x6f, 0x4d, 0xb5, 0xd1, 0xe2, 0x7c, 0xdf, 0xe6, + 0x7b, 0x59, 0x59, 0xf7, 0xc7, 0x48, 0x27, 0xd6, 0xc3, 0xb5, 0xff, 0x57, 0x98, 0x8e, 0xc2, 0x1c, + 0xa8, 0xfd, 0xa1, 0x8b, 0x9d, 0xec, 0x79, 0xb1, 0x3b, 0xdb, 0x5b, 0x7c, 0x9c, 0x82, 0xc3, 0xac, + 0xa4, 0xe8, 0x5f, 0x00, 0xc7, 0x42, 0x33, 0xc4, 0x5b, 0x6e, 0x68, 0x2e, 0xb2, 0x4c, 0x77, 0x57, + 0xa0, 0x30, 0xdb, 0xb3, 0x9e, 0x5e, 0x94, 0xf8, 0xc5, 0xef, 0xcf, 0x5f, 0xff, 0x93, 0x5c, 0x42, + 0x45, 0x39, 0x6a, 0x69, 0x37, 0xe5, 0x1a, 0xe6, 0x21, 0x91, 0x2f, 0x42, 0xfb, 0xf4, 0x12, 0xfd, + 0x1f, 0xb0, 0x6b, 0x5f, 0x5f, 0x68, 0x21, 0x12, 0xb4, 0xdb, 0x2e, 0x15, 0xa4, 0xb8, 0xe1, 0x7e, + 0xa3, 0xc4, 0x3c, 0x23, 0xfc, 0x31, 0x12, 0x23, 0x09, 0xab, 0xb5, 0x5a, 0x99, 0x34, 0xa9, 0x3c, + 0x05, 0x30, 0x1b, 0xb5, 0x69, 0xb6, 0x88, 0xcd, 0x7d, 0x89, 0x3e, 0xeb, 0x0e, 0x1f, 0xbd, 0x00, + 0x85, 0xc2, 0x00, 0x27, 0x38, 0xe7, 0x6f, 0x18, 0xe7, 0x0d, 0x54, 0xea, 0x5d, 0xe4, 0x60, 0x16, + 0xb6, 0x17, 0x9a, 0xdb, 0xec, 0x52, 0xbe, 0x60, 0xd7, 0xf6, 0x12, 0xdd, 0x00, 0x28, 0x76, 0x5b, + 0x2b, 0x6d, 0xba, 0x96, 0xe2, 0xb1, 0x0c, 0x2f, 0x3d, 0x61, 0x79, 0xc0, 0x53, 0x5c, 0xdf, 0x2e, + 0xd3, 0xb7, 0x89, 0xd6, 0x63, 0xe8, 0xf3, 0xd4, 0xf4, 0x14, 0xf8, 0x12, 0xc0, 0xd9, 0xbe, 0xbb, + 0x04, 0xad, 0xc6, 0xb2, 0x4d, 0xb7, 0x75, 0x28, 0x7c, 0x75, 0xdf, 0xe3, 0x5c, 0xf1, 0x0a, 0x53, + 0xbc, 0x8c, 0x16, 0xfb, 0xba, 0xb0, 0xb5, 0xe1, 0x9a, 0x0a, 0x1b, 0x41, 0x0b, 0x7b, 0x8e, 0x4c, + 0x14, 0x9f, 0x63, 0xe4, 0xdc, 0x17, 0xbe, 0xbe, 0xf7, 0x79, 0x2e, 0xf2, 0x4b, 0x26, 0xf2, 0x73, + 0xb4, 0x14, 0x53, 0x24, 0x1b, 0xe5, 0x81, 0xca, 0xd2, 0xb7, 0x57, 0xb7, 0x59, 0x70, 0x7d, 0x9b, + 0x05, 0xaf, 0x6e, 0xb3, 0xe0, 0xaf, 0x46, 0x36, 0x71, 0xdd, 0xc8, 0x26, 0x5e, 0x34, 0xb2, 0x89, + 0x9f, 0x8a, 0xba, 0x41, 0x8f, 0xea, 0x15, 0x49, 0x23, 0x27, 0xf2, 0xa6, 0x9f, 0xf9, 0x3b, 0x4c, + 0x7f, 0x21, 0xf6, 0x71, 0x13, 0xe8, 0xbc, 0x05, 0x45, 0x5d, 0x0b, 0x3b, 0x95, 0x77, 0xd9, 0x5f, + 0xfd, 0xc5, 0x37, 0x01, 0x00, 0x00, 0xff, 0xff, 0x3a, 0xfd, 0xf5, 0x2b, 0xd9, 0x0c, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -1261,6 +1299,16 @@ func (m *QueryOperatorConsKeyResponse) MarshalToSizedBuffer(dAtA []byte) (int, e _ = i var l int _ = l + if m.OptingOut { + i-- + if m.OptingOut { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x10 + } { size, err := m.PublicKey.MarshalToSizedBuffer(dAtA[:i]) if err != nil { @@ -1331,6 +1379,16 @@ func (m *QueryOperatorConsAddressResponse) MarshalToSizedBuffer(dAtA []byte) (in _ = i var l int _ = l + if m.OptingOut { + i-- + if m.OptingOut { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x10 + } if len(m.ConsAddr) > 0 { i -= len(m.ConsAddr) copy(dAtA[i:], m.ConsAddr) @@ -1452,6 +1510,16 @@ func (m *OperatorConsKeyPair) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if m.OptingOut { + i-- + if m.OptingOut { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x18 + } if m.PublicKey != nil { { size, err := m.PublicKey.MarshalToSizedBuffer(dAtA[:i]) @@ -1585,6 +1653,16 @@ func (m *OperatorConsAddrPair) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if m.OptingOut { + i-- + if m.OptingOut { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x18 + } if len(m.ConsAddr) > 0 { i -= len(m.ConsAddr) copy(dAtA[i:], m.ConsAddr) @@ -1683,6 +1761,9 @@ func (m *QueryOperatorConsKeyResponse) Size() (n int) { _ = l l = m.PublicKey.Size() n += 1 + l + sovQuery(uint64(l)) + if m.OptingOut { + n += 2 + } return n } @@ -1713,6 +1794,9 @@ func (m *QueryOperatorConsAddressResponse) Size() (n int) { if l > 0 { n += 1 + l + sovQuery(uint64(l)) } + if m.OptingOut { + n += 2 + } return n } @@ -1766,6 +1850,9 @@ func (m *OperatorConsKeyPair) Size() (n int) { l = m.PublicKey.Size() n += 1 + l + sovQuery(uint64(l)) } + if m.OptingOut { + n += 2 + } return n } @@ -1819,6 +1906,9 @@ func (m *OperatorConsAddrPair) Size() (n int) { if l > 0 { n += 1 + l + sovQuery(uint64(l)) } + if m.OptingOut { + n += 2 + } return n } @@ -2290,6 +2380,26 @@ func (m *QueryOperatorConsKeyResponse) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field OptingOut", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.OptingOut = bool(v != 0) default: iNdEx = preIndex skippy, err := skipQuery(dAtA[iNdEx:]) @@ -2486,6 +2596,26 @@ func (m *QueryOperatorConsAddressResponse) Unmarshal(dAtA []byte) error { } m.ConsAddr = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field OptingOut", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.OptingOut = bool(v != 0) default: iNdEx = preIndex skippy, err := skipQuery(dAtA[iNdEx:]) @@ -2842,6 +2972,26 @@ func (m *OperatorConsKeyPair) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field OptingOut", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.OptingOut = bool(v != 0) default: iNdEx = preIndex skippy, err := skipQuery(dAtA[iNdEx:]) @@ -3194,6 +3344,26 @@ func (m *OperatorConsAddrPair) Unmarshal(dAtA []byte) error { } m.ConsAddr = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field OptingOut", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.OptingOut = bool(v != 0) default: iNdEx = preIndex skippy, err := skipQuery(dAtA[iNdEx:]) diff --git a/x/operator/types/tx.pb.go b/x/operator/types/tx.pb.go index a3fd11a6f..97c8639b1 100644 --- a/x/operator/types/tx.pb.go +++ b/x/operator/types/tx.pb.go @@ -583,6 +583,9 @@ type OptIntoAVSReq struct { FromAddress string `protobuf:"bytes,1,opt,name=from_address,json=fromAddress,proto3" json:"from_address,omitempty"` // avs_address is the address of the AVS - either an 0x address or a chainID. AvsAddress string `protobuf:"bytes,2,opt,name=avs_address,json=avsAddress,proto3" json:"avs_address,omitempty"` + // optional parameter to provide the consensus key or the BLS key, depending + // on the AVS. we still have to design this fully. + PublicKey string `protobuf:"bytes,3,opt,name=public_key,json=publicKey,proto3" json:"public_key,omitempty"` } func (m *OptIntoAVSReq) Reset() { *m = OptIntoAVSReq{} } @@ -816,86 +819,6 @@ func (m *SetConsKeyResponse) XXX_DiscardUnknown() { var xxx_messageInfo_SetConsKeyResponse proto.InternalMessageInfo -// InitConsKeyRemovalReq is the request for an operator to stop validating on a chain. It -// allows the operator to remove their consensus key from the specified chain. It must be -// followed by a separate call to OptOutOfAVS to remove the operator from the AVS. -type InitConsKeyRemovalReq struct { - // address is the operator address - Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` - // chain_id is the identifier for the chain that wants to opt out. - ChainID string `protobuf:"bytes,2,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` -} - -func (m *InitConsKeyRemovalReq) Reset() { *m = InitConsKeyRemovalReq{} } -func (m *InitConsKeyRemovalReq) String() string { return proto.CompactTextString(m) } -func (*InitConsKeyRemovalReq) ProtoMessage() {} -func (*InitConsKeyRemovalReq) Descriptor() ([]byte, []int) { - return fileDescriptor_b229d5663e4df167, []int{15} -} -func (m *InitConsKeyRemovalReq) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *InitConsKeyRemovalReq) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_InitConsKeyRemovalReq.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 *InitConsKeyRemovalReq) XXX_Merge(src proto.Message) { - xxx_messageInfo_InitConsKeyRemovalReq.Merge(m, src) -} -func (m *InitConsKeyRemovalReq) XXX_Size() int { - return m.Size() -} -func (m *InitConsKeyRemovalReq) XXX_DiscardUnknown() { - xxx_messageInfo_InitConsKeyRemovalReq.DiscardUnknown(m) -} - -var xxx_messageInfo_InitConsKeyRemovalReq proto.InternalMessageInfo - -// InitConsKeyRemovalResponse defines the InitConsKeyRemovalReq response. -type InitConsKeyRemovalResponse struct { -} - -func (m *InitConsKeyRemovalResponse) Reset() { *m = InitConsKeyRemovalResponse{} } -func (m *InitConsKeyRemovalResponse) String() string { return proto.CompactTextString(m) } -func (*InitConsKeyRemovalResponse) ProtoMessage() {} -func (*InitConsKeyRemovalResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_b229d5663e4df167, []int{16} -} -func (m *InitConsKeyRemovalResponse) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *InitConsKeyRemovalResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_InitConsKeyRemovalResponse.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 *InitConsKeyRemovalResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_InitConsKeyRemovalResponse.Merge(m, src) -} -func (m *InitConsKeyRemovalResponse) XXX_Size() int { - return m.Size() -} -func (m *InitConsKeyRemovalResponse) XXX_DiscardUnknown() { - xxx_messageInfo_InitConsKeyRemovalResponse.DiscardUnknown(m) -} - -var xxx_messageInfo_InitConsKeyRemovalResponse proto.InternalMessageInfo - func init() { proto.RegisterEnum("exocore.operator.v1.SlashType", SlashType_name, SlashType_value) proto.RegisterType((*DecValueField)(nil), "exocore.operator.v1.DecValueField") @@ -913,93 +836,88 @@ func init() { proto.RegisterType((*OptOutOfAVSResponse)(nil), "exocore.operator.v1.OptOutOfAVSResponse") proto.RegisterType((*SetConsKeyReq)(nil), "exocore.operator.v1.SetConsKeyReq") proto.RegisterType((*SetConsKeyResponse)(nil), "exocore.operator.v1.SetConsKeyResponse") - proto.RegisterType((*InitConsKeyRemovalReq)(nil), "exocore.operator.v1.InitConsKeyRemovalReq") - proto.RegisterType((*InitConsKeyRemovalResponse)(nil), "exocore.operator.v1.InitConsKeyRemovalResponse") } func init() { proto.RegisterFile("exocore/operator/v1/tx.proto", fileDescriptor_b229d5663e4df167) } var fileDescriptor_b229d5663e4df167 = []byte{ - // 1262 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x57, 0xcd, 0x6f, 0x1b, 0x45, - 0x14, 0xf7, 0x26, 0x69, 0x12, 0x3f, 0xe7, 0xc3, 0x9d, 0xf4, 0xc3, 0x5d, 0x8a, 0x9d, 0x6c, 0x69, - 0x49, 0x23, 0x62, 0x2b, 0x81, 0x22, 0x35, 0x80, 0x84, 0xf3, 0x51, 0xd5, 0x6a, 0x1a, 0x57, 0xeb, - 0xb4, 0x52, 0x29, 0xd2, 0x6a, 0xb3, 0x9e, 0x38, 0x4b, 0x76, 0x77, 0x96, 0x9d, 0xb1, 0x69, 0x7a, - 0x42, 0x88, 0x03, 0xe2, 0xc4, 0x15, 0x89, 0x43, 0x0f, 0x08, 0x71, 0x42, 0x3d, 0xf4, 0x5a, 0x21, - 0x6e, 0x3d, 0x56, 0x3d, 0x21, 0x0e, 0x11, 0x4a, 0x0f, 0xe5, 0x4f, 0xe0, 0x88, 0xe6, 0x63, 0x9d, - 0x75, 0xb3, 0xe9, 0x87, 0x0a, 0x5c, 0x5a, 0xcf, 0x6f, 0x7e, 0xef, 0xcd, 0xef, 0xbd, 0x79, 0xef, - 0x4d, 0x16, 0x4e, 0xe3, 0xdb, 0xc4, 0x21, 0x11, 0xae, 0x90, 0x10, 0x47, 0x36, 0x23, 0x51, 0xa5, - 0x33, 0x57, 0x61, 0xb7, 0xcb, 0x61, 0x44, 0x18, 0x41, 0x13, 0x6a, 0xb7, 0x1c, 0xef, 0x96, 0x3b, - 0x73, 0xfa, 0x51, 0xdb, 0x77, 0x03, 0x52, 0x11, 0xff, 0x4a, 0x9e, 0x7e, 0xd2, 0x21, 0xd4, 0x27, - 0xb4, 0xe2, 0xd3, 0x16, 0xb7, 0xf7, 0x69, 0x4b, 0x6d, 0xbc, 0xa5, 0x36, 0x28, 0xb3, 0xb7, 0xdd, - 0x80, 0x6f, 0x6e, 0x60, 0x66, 0xcf, 0xc5, 0x6b, 0xc5, 0x3a, 0x25, 0x59, 0x96, 0x58, 0x55, 0xe4, - 0x42, 0x6d, 0x1d, 0x6b, 0x91, 0x16, 0x91, 0x38, 0xff, 0x25, 0x51, 0x03, 0xc3, 0xe8, 0x32, 0x76, - 0x6e, 0xd8, 0x5e, 0x1b, 0x5f, 0x72, 0xb1, 0xd7, 0x44, 0xeb, 0x30, 0x68, 0xfb, 0xa4, 0x1d, 0xb0, - 0x82, 0x36, 0xa9, 0x4d, 0x67, 0x17, 0x3f, 0x7c, 0xb8, 0x5b, 0xca, 0xfc, 0xb1, 0x5b, 0x3a, 0xd7, - 0x72, 0xd9, 0x56, 0x7b, 0xa3, 0xec, 0x10, 0x5f, 0xf9, 0x55, 0xff, 0xcd, 0xd2, 0xe6, 0x76, 0x85, - 0xed, 0x84, 0x98, 0x96, 0x97, 0xb1, 0xf3, 0xf8, 0xfe, 0x2c, 0xa8, 0x63, 0x97, 0xb1, 0x63, 0x2a, - 0x5f, 0xc6, 0x0e, 0xe8, 0x4b, 0x9e, 0x8b, 0x03, 0xb6, 0xb4, 0x65, 0xbb, 0xc1, 0x8a, 0x1d, 0x05, - 0x6e, 0xd0, 0xaa, 0x36, 0x9b, 0xd1, 0xaa, 0x4b, 0x19, 0xba, 0x05, 0x47, 0xb1, 0x84, 0x2c, 0x37, - 0xd8, 0x24, 0x96, 0xe7, 0x52, 0x7e, 0x7c, 0xff, 0x74, 0x6e, 0xbe, 0x52, 0x4e, 0x49, 0x5c, 0x39, - 0xdd, 0x57, 0x2d, 0xd8, 0x24, 0xe6, 0xb8, 0xf2, 0xc4, 0x17, 0xdc, 0xb9, 0xf1, 0xbd, 0x76, 0xd8, - 0xd9, 0x9c, 0x82, 0x3e, 0x06, 0xe4, 0xdd, 0xb1, 0x1c, 0x41, 0xb0, 0x1c, 0xce, 0xb0, 0xdc, 0xa6, - 0x88, 0x7d, 0x60, 0x71, 0x62, 0x6f, 0xb7, 0x34, 0xbe, 0x7a, 0x27, 0x61, 0x5d, 0x5b, 0x36, 0xc7, - 0xbd, 0x1e, 0xa0, 0x89, 0x2e, 0xc2, 0xa9, 0x1e, 0xf3, 0x38, 0x14, 0xbb, 0xd9, 0x8c, 0x0a, 0x7d, - 0x3c, 0x89, 0xe6, 0x09, 0x27, 0x55, 0x80, 0xf1, 0x5b, 0x1f, 0x8c, 0xd4, 0x55, 0x5c, 0x42, 0xcd, - 0x19, 0x18, 0x55, 0xe6, 0x54, 0xda, 0x8b, 0x4b, 0x30, 0x47, 0x62, 0x90, 0x5b, 0xa1, 0x29, 0x18, - 0xb1, 0xc3, 0x30, 0x22, 0x1d, 0x9c, 0x3c, 0x23, 0xa7, 0x30, 0x41, 0x79, 0x07, 0x50, 0x9c, 0x2f, - 0xcb, 0xc7, 0xcc, 0x16, 0x79, 0x2d, 0xf4, 0x0b, 0x62, 0x3e, 0xde, 0xb9, 0x8a, 0x99, 0x2d, 0x4e, - 0xf5, 0x40, 0x4f, 0x8b, 0x40, 0x49, 0x18, 0x98, 0xd4, 0x5e, 0xf1, 0x22, 0x78, 0xde, 0xcd, 0x93, - 0x07, 0x63, 0x96, 0xf2, 0xaf, 0x02, 0x38, 0xc4, 0xf7, 0x5d, 0x4a, 0x5d, 0x12, 0x14, 0x8e, 0x08, - 0xef, 0x46, 0x59, 0x15, 0x4d, 0x5c, 0xce, 0xaa, 0xbc, 0xcb, 0x4b, 0x5d, 0xe6, 0x62, 0x96, 0x57, - 0xe2, 0xcf, 0x4f, 0xef, 0xcd, 0x68, 0x66, 0xc2, 0x81, 0xf1, 0x83, 0x06, 0xd9, 0x7a, 0xc8, 0x70, - 0x53, 0x84, 0x72, 0x16, 0xc6, 0xa8, 0x67, 0xd3, 0x2d, 0xcb, 0x21, 0x01, 0x8b, 0x6c, 0x47, 0x95, - 0xb1, 0x39, 0x2a, 0xd0, 0x25, 0x05, 0xa2, 0x73, 0x30, 0x4e, 0xb8, 0x8d, 0xe5, 0x06, 0xd6, 0x16, - 0x76, 0x5b, 0x5b, 0x4c, 0x64, 0x71, 0xc0, 0x1c, 0x25, 0xd2, 0xd5, 0x65, 0x01, 0xa2, 0x69, 0xc8, - 0x4b, 0x1e, 0x69, 0xb3, 0x98, 0xd8, 0x2f, 0x88, 0x63, 0x02, 0xaf, 0xb7, 0x99, 0x62, 0x9e, 0x80, - 0xc1, 0xcf, 0x6c, 0xd7, 0xc3, 0x4d, 0x91, 0xaf, 0x61, 0x53, 0xad, 0x8c, 0x07, 0x1a, 0x1c, 0x55, - 0xf2, 0xaa, 0x94, 0x62, 0xd6, 0x60, 0x36, 0xc3, 0xaf, 0xd5, 0x65, 0xb5, 0x80, 0x25, 0xba, 0xac, - 0x16, 0xb0, 0xb8, 0xcb, 0x90, 0x09, 0x47, 0x3a, 0xbc, 0x93, 0x65, 0x45, 0xbc, 0x66, 0xeb, 0x4a, - 0x57, 0xc6, 0xdf, 0x7d, 0x5c, 0xbf, 0xbc, 0xf1, 0x06, 0xcf, 0xe1, 0xab, 0xa4, 0xf9, 0x3c, 0xe4, - 0x69, 0x7b, 0xc3, 0x77, 0x19, 0x4f, 0x61, 0x22, 0xcf, 0xfd, 0xe6, 0x78, 0x17, 0x57, 0xf9, 0x9b, - 0x82, 0x11, 0xdc, 0xe1, 0x25, 0x98, 0xc8, 0x72, 0xbf, 0x99, 0x13, 0x98, 0xa2, 0x9c, 0x87, 0x7c, - 0x18, 0x11, 0x07, 0x53, 0xba, 0xef, 0x6d, 0x40, 0x7a, 0xeb, 0xe2, 0x8a, 0xfa, 0x06, 0x64, 0x5d, - 0x6a, 0x75, 0x30, 0x23, 0xb8, 0x29, 0x4a, 0x6c, 0xd8, 0x1c, 0x76, 0xe9, 0x0d, 0xb1, 0x46, 0x2d, - 0xc8, 0x4b, 0xf1, 0x61, 0x44, 0x42, 0x12, 0x31, 0x5e, 0x86, 0x83, 0xff, 0x42, 0xc6, 0xc6, 0x85, - 0xd7, 0x6b, 0x5d, 0xa7, 0xe8, 0x23, 0x00, 0x79, 0x10, 0xb7, 0x28, 0x0c, 0x4d, 0x6a, 0xd3, 0x63, - 0xf3, 0xc5, 0xd4, 0x3e, 0x12, 0x99, 0x5d, 0xdf, 0x09, 0xb1, 0x99, 0xa5, 0xf1, 0x4f, 0xe3, 0x57, - 0x0d, 0x26, 0x4c, 0xdc, 0x72, 0x29, 0xc3, 0x51, 0x7c, 0x05, 0x26, 0xfe, 0x1c, 0x7d, 0x00, 0x23, - 0x9b, 0x11, 0xf1, 0x45, 0x77, 0x62, 0x4a, 0x55, 0x09, 0x15, 0x1e, 0xdf, 0x9f, 0x3d, 0xa6, 0xd4, - 0x54, 0xe5, 0x4e, 0x83, 0x45, 0x6e, 0xd0, 0x32, 0x73, 0x9c, 0xad, 0x20, 0x74, 0x01, 0x06, 0xc4, - 0x2c, 0xe8, 0x13, 0x7d, 0x37, 0x95, 0xaa, 0x26, 0x39, 0x92, 0x4c, 0x41, 0x5f, 0x78, 0xef, 0x9b, - 0xbb, 0xa5, 0xcc, 0x5f, 0x77, 0x4b, 0x99, 0xaf, 0x9e, 0xde, 0x9b, 0xc9, 0x5d, 0xda, 0x77, 0xf8, - 0xed, 0xd3, 0x7b, 0x33, 0x27, 0x13, 0xc9, 0x49, 0xda, 0x1a, 0x3a, 0x14, 0x0e, 0x06, 0x40, 0x43, - 0x12, 0x50, 0x6c, 0xfc, 0xa8, 0xc1, 0x68, 0x3d, 0x64, 0xb5, 0x80, 0x91, 0xea, 0x8d, 0xc6, 0x6b, - 0xc7, 0x55, 0x82, 0x9c, 0xdd, 0xa1, 0x5d, 0x5b, 0x39, 0x13, 0xc1, 0xee, 0x50, 0x45, 0x58, 0xb8, - 0xf0, 0xbc, 0x08, 0x0a, 0x3d, 0x11, 0x24, 0x44, 0x19, 0xc7, 0x00, 0x25, 0x01, 0x25, 0xfe, 0x27, - 0x0d, 0xc6, 0xea, 0x21, 0xab, 0xb7, 0x59, 0x7d, 0xf3, 0x7f, 0x51, 0xff, 0xfe, 0xf3, 0xd4, 0x9f, - 0xea, 0x55, 0x9f, 0x50, 0x65, 0x1c, 0x87, 0x89, 0x1e, 0x44, 0xe9, 0x7f, 0xa0, 0xc1, 0x68, 0x03, - 0xb3, 0x25, 0x12, 0xd0, 0x2b, 0x78, 0x87, 0xcb, 0x9f, 0x87, 0xa1, 0x97, 0x55, 0x1e, 0x13, 0xd1, - 0x39, 0x18, 0xee, 0xbe, 0x98, 0x72, 0xe4, 0xe4, 0xf6, 0x76, 0x4b, 0x43, 0xf1, 0x4b, 0x39, 0xe4, - 0xa8, 0x17, 0xf2, 0x4d, 0x80, 0xb0, 0xbd, 0xe1, 0xb9, 0x8e, 0xb5, 0x8d, 0x77, 0xd4, 0x2b, 0x94, - 0x95, 0xc8, 0x15, 0xbc, 0xb3, 0x30, 0x97, 0x8c, 0x2d, 0x76, 0xfe, 0xec, 0xad, 0xf4, 0xa8, 0xe5, - 0xb7, 0x92, 0x04, 0x54, 0x54, 0xbf, 0x68, 0x70, 0xbc, 0x16, 0xb8, 0xfb, 0xb8, 0x4f, 0x3a, 0xb6, - 0xf7, 0x1f, 0x47, 0xb7, 0x70, 0xf1, 0x30, 0xf9, 0x93, 0x09, 0xf9, 0xa9, 0xb2, 0x8c, 0xd3, 0xa0, - 0xa7, 0x6d, 0xc8, 0x70, 0x66, 0x3c, 0xc8, 0x76, 0xe7, 0x02, 0xd2, 0xe1, 0x44, 0x63, 0xb5, 0xda, - 0xb8, 0x6c, 0xad, 0xdf, 0xbc, 0xb6, 0x62, 0x5d, 0x5f, 0x6b, 0x5c, 0x5b, 0x59, 0xaa, 0x5d, 0xaa, - 0xad, 0x2c, 0xe7, 0x33, 0xe8, 0x34, 0x14, 0x12, 0x7b, 0xb5, 0xb5, 0xc6, 0x7a, 0x75, 0x6d, 0xdd, - 0x12, 0x50, 0x5e, 0x43, 0x67, 0x61, 0x2a, 0xb1, 0xbb, 0x56, 0x8f, 0x09, 0xd5, 0xb5, 0x95, 0xfa, - 0xf5, 0x86, 0xa2, 0xf5, 0xcd, 0x7f, 0x3d, 0x00, 0xfd, 0x57, 0x69, 0x0b, 0x6d, 0x43, 0xfe, 0xd9, - 0x9e, 0x45, 0xd3, 0xa9, 0x63, 0x22, 0x65, 0x36, 0xe9, 0xb3, 0x2f, 0xc9, 0x94, 0x21, 0xa2, 0x5b, - 0x00, 0xfb, 0xf7, 0x88, 0x8c, 0xf4, 0xd9, 0x98, 0xbc, 0x79, 0xfd, 0xed, 0x17, 0x72, 0x54, 0x31, - 0x64, 0x10, 0x05, 0x74, 0x30, 0xbb, 0x68, 0x26, 0xd5, 0x41, 0xea, 0xfd, 0xe8, 0x95, 0x97, 0xe6, - 0x76, 0x0f, 0xbd, 0x09, 0xb0, 0x3f, 0x2f, 0x0e, 0x89, 0xa8, 0x67, 0xc2, 0x1c, 0x12, 0xd1, 0xc1, - 0xa1, 0x83, 0x3e, 0x85, 0x5c, 0xa2, 0x97, 0xd1, 0x99, 0xc3, 0xec, 0x12, 0xfd, 0xaf, 0x4f, 0xbf, - 0x98, 0x24, 0xbd, 0xeb, 0x47, 0xbe, 0xe4, 0x7f, 0x5a, 0x2d, 0xae, 0x3e, 0xdc, 0x2b, 0x6a, 0x8f, - 0xf6, 0x8a, 0xda, 0x9f, 0x7b, 0x45, 0xed, 0xbb, 0x27, 0xc5, 0xcc, 0xa3, 0x27, 0xc5, 0xcc, 0xef, - 0x4f, 0x8a, 0x99, 0x4f, 0xe6, 0x13, 0x8f, 0xe2, 0x8a, 0x74, 0xba, 0x86, 0xd9, 0x17, 0x24, 0xda, - 0xae, 0xc4, 0x9f, 0x3e, 0xb7, 0xf7, 0x3f, 0x7e, 0xc4, 0x23, 0xb9, 0x31, 0x28, 0xbe, 0x32, 0xde, - 0xfd, 0x27, 0x00, 0x00, 0xff, 0xff, 0x85, 0xf8, 0xd5, 0xb9, 0x1d, 0x0d, 0x00, 0x00, + // 1212 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x56, 0xcf, 0x6f, 0x1b, 0x45, + 0x14, 0xf6, 0xc6, 0x69, 0x12, 0x3f, 0xc7, 0xb1, 0x3b, 0x29, 0xad, 0x6b, 0x8a, 0xdd, 0x6c, 0x69, + 0x71, 0x23, 0x62, 0x2b, 0x81, 0x22, 0x51, 0x40, 0xc2, 0x71, 0x5c, 0xd5, 0x6a, 0x6a, 0x57, 0xeb, + 0xb4, 0x52, 0x29, 0xd2, 0x6a, 0xb3, 0x9e, 0x38, 0x4b, 0xec, 0x9d, 0x65, 0x67, 0x6c, 0xea, 0x9e, + 0x10, 0x27, 0xc4, 0x05, 0xae, 0x48, 0x1c, 0x7a, 0x42, 0x1c, 0x7b, 0xe8, 0xb5, 0x42, 0x88, 0x4b, + 0x8f, 0x55, 0x4f, 0x88, 0x43, 0x84, 0x92, 0x43, 0xf8, 0x13, 0x38, 0xa2, 0xf9, 0xb1, 0xce, 0xba, + 0x71, 0x9a, 0x56, 0x41, 0x5c, 0x12, 0xcf, 0xf7, 0xbe, 0xf7, 0xcd, 0x7b, 0x6f, 0xde, 0x9b, 0x1d, + 0x38, 0x87, 0xef, 0x13, 0x9b, 0xf8, 0xb8, 0x48, 0x3c, 0xec, 0x5b, 0x8c, 0xf8, 0xc5, 0xde, 0x62, + 0x91, 0xdd, 0x2f, 0x78, 0x3e, 0x61, 0x04, 0xcd, 0x2a, 0x6b, 0x21, 0xb0, 0x16, 0x7a, 0x8b, 0x99, + 0x93, 0x56, 0xc7, 0x71, 0x49, 0x51, 0xfc, 0x95, 0xbc, 0xcc, 0x19, 0x9b, 0xd0, 0x0e, 0xa1, 0xc5, + 0x0e, 0x6d, 0x71, 0xff, 0x0e, 0x6d, 0x29, 0xc3, 0xdb, 0xca, 0x40, 0x99, 0xb5, 0xe5, 0xb8, 0xdc, + 0xb8, 0x8e, 0x99, 0xb5, 0x18, 0xac, 0x15, 0xeb, 0xac, 0x64, 0x99, 0x62, 0x55, 0x94, 0x0b, 0x65, + 0x3a, 0xd5, 0x22, 0x2d, 0x22, 0x71, 0xfe, 0x4b, 0xa2, 0x3a, 0x86, 0xc4, 0x0a, 0xb6, 0xef, 0x58, + 0xed, 0x2e, 0xbe, 0xe6, 0xe0, 0x76, 0x13, 0xad, 0xc1, 0x84, 0xd5, 0x21, 0x5d, 0x97, 0xa5, 0xb5, + 0xf3, 0x5a, 0x3e, 0xb6, 0xfc, 0xf1, 0xd3, 0xed, 0x5c, 0xe4, 0xcf, 0xed, 0xdc, 0xa5, 0x96, 0xc3, + 0x36, 0xbb, 0xeb, 0x05, 0x9b, 0x74, 0x94, 0xae, 0xfa, 0xb7, 0x40, 0x9b, 0x5b, 0x45, 0xd6, 0xf7, + 0x30, 0x2d, 0xac, 0x60, 0xfb, 0xf9, 0xe3, 0x05, 0x50, 0xdb, 0xae, 0x60, 0xdb, 0x50, 0x5a, 0x7a, + 0x1f, 0x32, 0xe5, 0xb6, 0x83, 0x5d, 0x56, 0xde, 0xb4, 0x1c, 0xb7, 0x62, 0xf9, 0xae, 0xe3, 0xb6, + 0x4a, 0xcd, 0xa6, 0xbf, 0xea, 0x50, 0x86, 0xee, 0xc1, 0x49, 0x2c, 0x21, 0xd3, 0x71, 0x37, 0x88, + 0xd9, 0x76, 0x28, 0xdf, 0x3e, 0x9a, 0x8f, 0x2f, 0x15, 0x0b, 0x23, 0x0a, 0x57, 0x18, 0xad, 0x55, + 0x75, 0x37, 0x88, 0x91, 0x54, 0x4a, 0x7c, 0xc1, 0xc5, 0xf5, 0x1f, 0xb5, 0xc3, 0xf6, 0xe6, 0x14, + 0xf4, 0x29, 0xa0, 0xf6, 0x03, 0xd3, 0x16, 0x04, 0xd3, 0xe6, 0x0c, 0xd3, 0x69, 0x8a, 0xdc, 0xc7, + 0x97, 0x67, 0x77, 0xb6, 0x73, 0xc9, 0xd5, 0x07, 0x21, 0xef, 0xea, 0x8a, 0x91, 0x6c, 0x0f, 0x01, + 0x4d, 0xf4, 0x21, 0x9c, 0x1d, 0x72, 0x0f, 0x52, 0xb1, 0x9a, 0x4d, 0x3f, 0x3d, 0xc6, 0x8b, 0x68, + 0x9c, 0xb6, 0x47, 0x06, 0xa0, 0xff, 0x36, 0x06, 0xd3, 0x75, 0x95, 0x97, 0x88, 0xe6, 0x02, 0x24, + 0x94, 0x3b, 0x95, 0xfe, 0xe2, 0x10, 0x8c, 0xe9, 0x00, 0xe4, 0x5e, 0x68, 0x0e, 0xa6, 0x2d, 0xcf, + 0xf3, 0x49, 0x0f, 0x87, 0xf7, 0x88, 0x2b, 0x4c, 0x50, 0xde, 0x05, 0x14, 0xd4, 0xcb, 0xec, 0x60, + 0x66, 0x89, 0xba, 0xa6, 0xa3, 0x82, 0x98, 0x0a, 0x2c, 0x37, 0x31, 0xb3, 0xc4, 0xae, 0x6d, 0xc8, + 0x8c, 0xca, 0x40, 0x85, 0x30, 0x7e, 0x5e, 0x7b, 0xcd, 0x83, 0xe0, 0x75, 0x37, 0xce, 0x1c, 0xcc, + 0x59, 0x86, 0x7f, 0x13, 0xc0, 0x26, 0x9d, 0x8e, 0x43, 0xa9, 0x43, 0xdc, 0xf4, 0x09, 0xa1, 0xae, + 0x17, 0x54, 0xd3, 0x04, 0xed, 0xac, 0xda, 0xbb, 0x50, 0x1e, 0x30, 0x97, 0x63, 0xbc, 0x13, 0x7f, + 0xd9, 0x7b, 0x34, 0xaf, 0x19, 0x21, 0x01, 0xfd, 0x27, 0x0d, 0x62, 0x75, 0x8f, 0xe1, 0xa6, 0x48, + 0xe5, 0x22, 0xcc, 0xd0, 0xb6, 0x45, 0x37, 0x4d, 0x9b, 0xb8, 0xcc, 0xb7, 0x6c, 0xd5, 0xc6, 0x46, + 0x42, 0xa0, 0x65, 0x05, 0xa2, 0x4b, 0x90, 0x24, 0xdc, 0xc7, 0x74, 0x5c, 0x73, 0x13, 0x3b, 0xad, + 0x4d, 0x26, 0xaa, 0x38, 0x6e, 0x24, 0x88, 0x94, 0xba, 0x2e, 0x40, 0x94, 0x87, 0x94, 0xe4, 0x91, + 0x2e, 0x0b, 0x88, 0x51, 0x41, 0x9c, 0x11, 0x78, 0xbd, 0xcb, 0x14, 0xf3, 0x34, 0x4c, 0x7c, 0x61, + 0x39, 0x6d, 0xdc, 0x14, 0xf5, 0x9a, 0x32, 0xd4, 0x4a, 0x7f, 0xa2, 0xc1, 0x49, 0x15, 0x5e, 0x89, + 0x52, 0xcc, 0x1a, 0xcc, 0x62, 0xf8, 0x58, 0x53, 0x56, 0x75, 0x59, 0x68, 0xca, 0xaa, 0x2e, 0x0b, + 0xa6, 0x0c, 0x19, 0x70, 0xa2, 0xc7, 0x27, 0x59, 0x76, 0xc4, 0x31, 0x47, 0x57, 0x4a, 0xe9, 0xff, + 0x8c, 0xf1, 0xf8, 0xe5, 0x89, 0x37, 0x78, 0x0d, 0x5f, 0xa7, 0xcc, 0x97, 0x21, 0x45, 0xbb, 0xeb, + 0x1d, 0x87, 0xf1, 0x12, 0x86, 0xea, 0x1c, 0x35, 0x92, 0x03, 0x5c, 0xd5, 0x6f, 0x0e, 0xa6, 0x71, + 0x8f, 0xb7, 0x60, 0xa8, 0xca, 0x51, 0x23, 0x2e, 0x30, 0x45, 0xb9, 0x0c, 0x29, 0xcf, 0x27, 0x36, + 0xa6, 0x74, 0x5f, 0x6d, 0x5c, 0xaa, 0x0d, 0x70, 0x45, 0x7d, 0x13, 0x62, 0x0e, 0x35, 0x7b, 0x98, + 0x11, 0xdc, 0x14, 0x2d, 0x36, 0x65, 0x4c, 0x39, 0xf4, 0x8e, 0x58, 0xa3, 0x16, 0xa4, 0x64, 0xf0, + 0x9e, 0x4f, 0x3c, 0xe2, 0x33, 0xde, 0x86, 0x13, 0xff, 0x41, 0xc5, 0x92, 0x42, 0xf5, 0xd6, 0x40, + 0x14, 0x7d, 0x02, 0x20, 0x37, 0xe2, 0x1e, 0xe9, 0xc9, 0xf3, 0x5a, 0x7e, 0x66, 0x29, 0x3b, 0x72, + 0x8e, 0x44, 0x65, 0xd7, 0xfa, 0x1e, 0x36, 0x62, 0x34, 0xf8, 0xa9, 0xff, 0xaa, 0xc1, 0xac, 0x81, + 0x5b, 0x0e, 0x65, 0xd8, 0x0f, 0x8e, 0xc0, 0xc0, 0x5f, 0xa2, 0x8f, 0x60, 0x7a, 0xc3, 0x27, 0x1d, + 0x31, 0x9d, 0x98, 0x52, 0xd5, 0x42, 0xe9, 0xe7, 0x8f, 0x17, 0x4e, 0xa9, 0x68, 0x4a, 0xd2, 0xd2, + 0x60, 0xbe, 0xe3, 0xb6, 0x8c, 0x38, 0x67, 0x2b, 0x08, 0x5d, 0x81, 0x71, 0x71, 0x17, 0x8c, 0x89, + 0xb9, 0x9b, 0x1b, 0x19, 0x4d, 0xf8, 0x4a, 0x32, 0x04, 0xfd, 0xea, 0xfb, 0xdf, 0x3e, 0xcc, 0x45, + 0xfe, 0x7e, 0x98, 0x8b, 0x7c, 0xb3, 0xf7, 0x68, 0x3e, 0x7e, 0x6d, 0x5f, 0xf0, 0xbb, 0xbd, 0x47, + 0xf3, 0x67, 0x42, 0xc5, 0x09, 0xfb, 0xea, 0x19, 0x48, 0x1f, 0x4c, 0x80, 0x7a, 0xc4, 0xa5, 0x58, + 0xff, 0x5d, 0x83, 0x44, 0xdd, 0x63, 0x55, 0x97, 0x91, 0xd2, 0x9d, 0xc6, 0xb1, 0xf3, 0xca, 0x41, + 0xdc, 0xea, 0xd1, 0x81, 0xaf, 0xbc, 0x13, 0xc1, 0xea, 0xd1, 0x80, 0xf0, 0x16, 0x80, 0xd7, 0x5d, + 0x6f, 0x3b, 0xb6, 0xb9, 0x85, 0xfb, 0xea, 0x2a, 0x8c, 0x49, 0xe4, 0x06, 0xee, 0x5f, 0xbd, 0xf2, + 0xb2, 0x04, 0xd3, 0x43, 0x09, 0x86, 0x62, 0xd6, 0x4f, 0x01, 0x0a, 0x03, 0x2a, 0xb7, 0x9f, 0x35, + 0x98, 0xa9, 0x7b, 0xac, 0xde, 0x65, 0xf5, 0x8d, 0xff, 0x23, 0xb9, 0xab, 0x1f, 0xbc, 0x2c, 0xfa, + 0xb3, 0xc3, 0xd1, 0x87, 0xa2, 0xd2, 0xdf, 0x80, 0xd9, 0x21, 0x44, 0xc5, 0xff, 0x44, 0x83, 0x44, + 0x03, 0xb3, 0x32, 0x71, 0xe9, 0x0d, 0xdc, 0xe7, 0xe1, 0x2f, 0xc1, 0xe4, 0xab, 0x46, 0x1e, 0x10, + 0xd1, 0x25, 0x98, 0x1a, 0x7c, 0x50, 0xe5, 0x8d, 0x14, 0xdf, 0xd9, 0xce, 0x4d, 0x06, 0x1f, 0xd2, + 0x49, 0x5b, 0x7d, 0x40, 0x8f, 0x38, 0x99, 0xc5, 0x70, 0x6e, 0x81, 0xf8, 0x8b, 0xa7, 0x32, 0x14, + 0x2d, 0x3f, 0x95, 0x30, 0x20, 0xb3, 0x9a, 0x6f, 0x43, 0x6c, 0x30, 0x67, 0x28, 0x03, 0xa7, 0x1b, + 0xab, 0xa5, 0xc6, 0x75, 0x73, 0xed, 0xee, 0xad, 0x8a, 0x79, 0xbb, 0xd6, 0xb8, 0x55, 0x29, 0x57, + 0xaf, 0x55, 0x2b, 0x2b, 0xa9, 0x08, 0x3a, 0x07, 0xe9, 0x90, 0xad, 0x5a, 0x6b, 0xac, 0x95, 0x6a, + 0x6b, 0xa6, 0x80, 0x52, 0x1a, 0xba, 0x08, 0x73, 0x21, 0x6b, 0xad, 0x1e, 0x10, 0x4a, 0xb5, 0x4a, + 0xfd, 0x76, 0x43, 0xd1, 0xc6, 0x96, 0xbe, 0x8f, 0x42, 0xf4, 0x26, 0x6d, 0xa1, 0x2d, 0x48, 0xbd, + 0x38, 0x03, 0x28, 0x3f, 0x72, 0xec, 0x46, 0xcc, 0x7a, 0x66, 0xe1, 0x15, 0x99, 0x32, 0x45, 0x74, + 0x0f, 0x60, 0x3f, 0x71, 0xa4, 0x8f, 0xbe, 0x6b, 0xc2, 0xa5, 0xca, 0xbc, 0x73, 0x24, 0x47, 0xf5, + 0x44, 0x04, 0xdd, 0x05, 0xd8, 0xef, 0xf5, 0x43, 0xc4, 0x87, 0xa6, 0xe3, 0x10, 0xf1, 0x83, 0x03, + 0x83, 0x3e, 0x87, 0x78, 0xa8, 0x0f, 0xd1, 0x85, 0xc3, 0xfc, 0x42, 0xbd, 0x9b, 0xc9, 0x1f, 0x4d, + 0x92, 0xea, 0x99, 0x13, 0x5f, 0xf3, 0x57, 0xc3, 0xf2, 0xea, 0xd3, 0x9d, 0xac, 0xf6, 0x6c, 0x27, + 0xab, 0xfd, 0xb5, 0x93, 0xd5, 0x7e, 0xd8, 0xcd, 0x46, 0x9e, 0xed, 0x66, 0x23, 0x7f, 0xec, 0x66, + 0x23, 0x9f, 0x2d, 0x85, 0xee, 0xfb, 0x8a, 0x14, 0xad, 0x61, 0xf6, 0x15, 0xf1, 0xb7, 0x8a, 0xc1, + 0xab, 0xfe, 0xfe, 0xfe, 0xbb, 0x5e, 0xdc, 0xff, 0xeb, 0x13, 0xe2, 0x01, 0xfd, 0xde, 0xbf, 0x01, + 0x00, 0x00, 0xff, 0xff, 0x31, 0x4a, 0x45, 0x23, 0xf8, 0x0b, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -1016,10 +934,10 @@ const _ = grpc.SupportPackageIsVersion4 type MsgClient interface { // RegisterOperator registers a new operator. RegisterOperator(ctx context.Context, in *RegisterOperatorReq, opts ...grpc.CallOption) (*RegisterOperatorResponse, error) - // SetConsKey sets the operator's consensus key for a chain. + // SetConsKey sets the operator's consensus key for a chain. To do this, the operator + // must have previously opted into the chain. + // TODO; rationalize this with non-chain AVSs wherein other keys can be set. SetConsKey(ctx context.Context, in *SetConsKeyReq, opts ...grpc.CallOption) (*SetConsKeyResponse, error) - // InitConsKeyRemoval removes the operator's consensus key for a chain. - InitConsKeyRemoval(ctx context.Context, in *InitConsKeyRemovalReq, opts ...grpc.CallOption) (*InitConsKeyRemovalResponse, error) // OptIntoAVS opts an operator into an AVS. OptIntoAVS(ctx context.Context, in *OptIntoAVSReq, opts ...grpc.CallOption) (*OptIntoAVSResponse, error) // OptOutOfAVS opts an operator out of an AVS. @@ -1052,15 +970,6 @@ func (c *msgClient) SetConsKey(ctx context.Context, in *SetConsKeyReq, opts ...g return out, nil } -func (c *msgClient) InitConsKeyRemoval(ctx context.Context, in *InitConsKeyRemovalReq, opts ...grpc.CallOption) (*InitConsKeyRemovalResponse, error) { - out := new(InitConsKeyRemovalResponse) - err := c.cc.Invoke(ctx, "/exocore.operator.v1.Msg/InitConsKeyRemoval", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - func (c *msgClient) OptIntoAVS(ctx context.Context, in *OptIntoAVSReq, opts ...grpc.CallOption) (*OptIntoAVSResponse, error) { out := new(OptIntoAVSResponse) err := c.cc.Invoke(ctx, "/exocore.operator.v1.Msg/OptIntoAVS", in, out, opts...) @@ -1083,10 +992,10 @@ func (c *msgClient) OptOutOfAVS(ctx context.Context, in *OptOutOfAVSReq, opts .. type MsgServer interface { // RegisterOperator registers a new operator. RegisterOperator(context.Context, *RegisterOperatorReq) (*RegisterOperatorResponse, error) - // SetConsKey sets the operator's consensus key for a chain. + // SetConsKey sets the operator's consensus key for a chain. To do this, the operator + // must have previously opted into the chain. + // TODO; rationalize this with non-chain AVSs wherein other keys can be set. SetConsKey(context.Context, *SetConsKeyReq) (*SetConsKeyResponse, error) - // InitConsKeyRemoval removes the operator's consensus key for a chain. - InitConsKeyRemoval(context.Context, *InitConsKeyRemovalReq) (*InitConsKeyRemovalResponse, error) // OptIntoAVS opts an operator into an AVS. OptIntoAVS(context.Context, *OptIntoAVSReq) (*OptIntoAVSResponse, error) // OptOutOfAVS opts an operator out of an AVS. @@ -1103,9 +1012,6 @@ func (*UnimplementedMsgServer) RegisterOperator(ctx context.Context, req *Regist func (*UnimplementedMsgServer) SetConsKey(ctx context.Context, req *SetConsKeyReq) (*SetConsKeyResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method SetConsKey not implemented") } -func (*UnimplementedMsgServer) InitConsKeyRemoval(ctx context.Context, req *InitConsKeyRemovalReq) (*InitConsKeyRemovalResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method InitConsKeyRemoval not implemented") -} func (*UnimplementedMsgServer) OptIntoAVS(ctx context.Context, req *OptIntoAVSReq) (*OptIntoAVSResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method OptIntoAVS not implemented") } @@ -1153,24 +1059,6 @@ func _Msg_SetConsKey_Handler(srv interface{}, ctx context.Context, dec func(inte return interceptor(ctx, in, info, handler) } -func _Msg_InitConsKeyRemoval_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(InitConsKeyRemovalReq) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(MsgServer).InitConsKeyRemoval(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/exocore.operator.v1.Msg/InitConsKeyRemoval", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(MsgServer).InitConsKeyRemoval(ctx, req.(*InitConsKeyRemovalReq)) - } - return interceptor(ctx, in, info, handler) -} - func _Msg_OptIntoAVS_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(OptIntoAVSReq) if err := dec(in); err != nil { @@ -1219,10 +1107,6 @@ var _Msg_serviceDesc = grpc.ServiceDesc{ MethodName: "SetConsKey", Handler: _Msg_SetConsKey_Handler, }, - { - MethodName: "InitConsKeyRemoval", - Handler: _Msg_InitConsKeyRemoval_Handler, - }, { MethodName: "OptIntoAVS", Handler: _Msg_OptIntoAVS_Handler, @@ -1655,6 +1539,13 @@ func (m *OptIntoAVSReq) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if len(m.PublicKey) > 0 { + i -= len(m.PublicKey) + copy(dAtA[i:], m.PublicKey) + i = encodeVarintTx(dAtA, i, uint64(len(m.PublicKey))) + i-- + dAtA[i] = 0x1a + } if len(m.AvsAddress) > 0 { i -= len(m.AvsAddress) copy(dAtA[i:], m.AvsAddress) @@ -1822,66 +1713,6 @@ func (m *SetConsKeyResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } -func (m *InitConsKeyRemovalReq) 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 *InitConsKeyRemovalReq) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *InitConsKeyRemovalReq) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.ChainID) > 0 { - i -= len(m.ChainID) - copy(dAtA[i:], m.ChainID) - i = encodeVarintTx(dAtA, i, uint64(len(m.ChainID))) - i-- - dAtA[i] = 0x12 - } - if len(m.Address) > 0 { - i -= len(m.Address) - copy(dAtA[i:], m.Address) - i = encodeVarintTx(dAtA, i, uint64(len(m.Address))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *InitConsKeyRemovalResponse) 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 *InitConsKeyRemovalResponse) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *InitConsKeyRemovalResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - return len(dAtA) - i, nil -} - func encodeVarintTx(dAtA []byte, offset int, v uint64) int { offset -= sovTx(v) base := offset @@ -2067,6 +1898,10 @@ func (m *OptIntoAVSReq) Size() (n int) { if l > 0 { n += 1 + l + sovTx(uint64(l)) } + l = len(m.PublicKey) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } return n } @@ -2135,32 +1970,6 @@ func (m *SetConsKeyResponse) Size() (n int) { return n } -func (m *InitConsKeyRemovalReq) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.Address) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - l = len(m.ChainID) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - return n -} - -func (m *InitConsKeyRemovalResponse) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - return n -} - func sovTx(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -3382,6 +3191,38 @@ func (m *OptIntoAVSReq) Unmarshal(dAtA []byte) error { } m.AvsAddress = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field PublicKey", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.PublicKey = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipTx(dAtA[iNdEx:]) @@ -3813,170 +3654,6 @@ func (m *SetConsKeyResponse) Unmarshal(dAtA []byte) error { } return nil } -func (m *InitConsKeyRemovalReq) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: InitConsKeyRemovalReq: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: InitConsKeyRemovalReq: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthTx - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthTx - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Address = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ChainID", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthTx - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthTx - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.ChainID = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipTx(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *InitConsKeyRemovalResponse) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: InitConsKeyRemovalResponse: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: InitConsKeyRemovalResponse: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - default: - iNdEx = preIndex - skippy, err := skipTx(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} func skipTx(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0