From 5fa30d41f7622525d4c4acf41a8d991d4e508dd8 Mon Sep 17 00:00:00 2001 From: MaxMustermann2 <82761650+MaxMustermann2@users.noreply.github.com> Date: Mon, 4 Mar 2024 12:55:40 +0000 Subject: [PATCH 1/7] feat(dogfood): add asset_ids param --- proto/exocore/dogfood/v1/params.proto | 5 ++ x/dogfood/keeper/params.go | 14 +++- x/dogfood/types/params.go | 65 +++++++++++++++--- x/dogfood/types/params.pb.go | 99 ++++++++++++++++++++++----- 4 files changed, 151 insertions(+), 32 deletions(-) diff --git a/proto/exocore/dogfood/v1/params.proto b/proto/exocore/dogfood/v1/params.proto index 4d3f94a8d..790908699 100644 --- a/proto/exocore/dogfood/v1/params.proto +++ b/proto/exocore/dogfood/v1/params.proto @@ -20,4 +20,9 @@ message Params { uint32 max_validators = 3; // HistoricalEntries is the number of historical entries to persist. uint32 historical_entries = 4; + // AssetIDs is the ids of the assets which will be accepted by the module. + // It must be within the list of assets supported by the restaking module. + // The typical format of these IDs is + // lower(assetAddress) + _ + hex(clientChainLzID) + repeated string asset_ids = 5 [(gogoproto.customname) = "AssetIDs"]; } diff --git a/x/dogfood/keeper/params.go b/x/dogfood/keeper/params.go index f2bb7af60..782f57921 100644 --- a/x/dogfood/keeper/params.go +++ b/x/dogfood/keeper/params.go @@ -3,6 +3,7 @@ package keeper import ( "github.com/ExocoreNetwork/exocore/x/dogfood/types" sdk "github.com/cosmos/cosmos-sdk/types" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" ) // GetEpochsUntilUnbonded returns the number of epochs after which an unbonding that is made @@ -25,7 +26,7 @@ func (k Keeper) GetEpochIdentifier(ctx sdk.Context) string { // the chain. It is a parameter of the dogfood module. func (k Keeper) GetMaxValidators(ctx sdk.Context) uint32 { var maxValidators uint32 - k.paramstore.Get(ctx, types.KeyMaxValidators, &maxValidators) + k.paramstore.Get(ctx, stakingtypes.KeyMaxValidators, &maxValidators) return maxValidators } @@ -33,10 +34,18 @@ func (k Keeper) GetMaxValidators(ctx sdk.Context) uint32 { // entries are used by the IBC module. The return value is a parameter of the dogfood module. func (k Keeper) GetHistoricalEntries(ctx sdk.Context) uint32 { var historicalEntries uint32 - k.paramstore.Get(ctx, types.KeyHistoricalEntries, &historicalEntries) + k.paramstore.Get(ctx, stakingtypes.KeyHistoricalEntries, &historicalEntries) return historicalEntries } +// GetAssetIDs returns the asset IDs that are accepted by the dogfood module. It is a parameter +// of the dogfood module. +func (k Keeper) GetAssetIDs(ctx sdk.Context) []string { + var assetIDs []string + k.paramstore.Get(ctx, types.KeyAssetIDs, &assetIDs) + return assetIDs +} + // SetParams sets the params for the dogfood module. func (k Keeper) SetParams(ctx sdk.Context, params types.Params) { k.paramstore.SetParamSet(ctx, ¶ms) @@ -52,5 +61,6 @@ func (k Keeper) GetDogfoodParams(ctx sdk.Context) (params types.Params) { k.GetEpochIdentifier(ctx), k.GetMaxValidators(ctx), k.GetHistoricalEntries(ctx), + k.GetAssetIDs(ctx), ) } diff --git a/x/dogfood/types/params.go b/x/dogfood/types/params.go index f1b272b56..ff96ee280 100644 --- a/x/dogfood/types/params.go +++ b/x/dogfood/types/params.go @@ -2,12 +2,14 @@ package types import ( "fmt" + "strings" paramtypes "github.com/cosmos/cosmos-sdk/x/params/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + "github.com/ethereum/go-ethereum/common/hexutil" "gopkg.in/yaml.v2" - epochTypes "github.com/evmos/evmos/v14/x/epochs/types" + epochtypes "github.com/evmos/evmos/v14/x/epochs/types" ) var _ paramtypes.ParamSet = (*Params)(nil) @@ -20,21 +22,24 @@ const ( DefaultEpochsUntilUnbonded = 7 // DefaultEpochIdentifier is the epoch identifier which is used, by default, to identify the // epoch. Note that the options include week, day or hour. - DefaultEpochIdentifier = epochTypes.HourEpochID - // DefaultMaxValidators is the default maximum number of bonded validators. + DefaultEpochIdentifier = epochtypes.HourEpochID + // DefaultMaxValidators is the default maximum number of bonded validators. It is defined as + // a copy here so that we can use a value other than that in x/staking, if necessary. DefaultMaxValidators = stakingtypes.DefaultMaxValidators // DefaultHistorical entries is the number of entries of historical staking data to persist. - // Apps that don't use IBC can ignore this value by not adding the staking module to the - // application module manager's SetOrderBeginBlockers. + // It is defined as a copy here so that we can use a value other than that in x/staking, if + // necessary. DefaultHistoricalEntries = stakingtypes.DefaultHistoricalEntries + // DefaultAssetIDs is the default asset IDs accepted by the dogfood module. If multiple + // asset IDs are to be supported by default, separate them with a pipe character. + DefaultAssetIDs = "0xdac17f958d2ee523a2206206994597c13d831ec7_0x65" ) // Reflection based keys for params subspace. var ( KeyEpochsUntilUnbonded = []byte("EpochsUntilUnbonded") KeyEpochIdentifier = []byte("EpochIdentifier") - KeyMaxValidators = []byte("MaxValidators") - KeyHistoricalEntries = []byte("HistoricalEntries") + KeyAssetIDs = []byte("AssetIDs") ) // ParamKeyTable returns a key table with the necessary registered params. @@ -48,12 +53,14 @@ func NewParams( epochIdentifier string, maxValidators uint32, historicalEntries uint32, + assetIDs []string, ) Params { return Params{ EpochsUntilUnbonded: epochsUntilUnbonded, EpochIdentifier: epochIdentifier, MaxValidators: maxValidators, HistoricalEntries: historicalEntries, + AssetIDs: assetIDs, } } @@ -64,6 +71,7 @@ func DefaultParams() Params { DefaultEpochIdentifier, DefaultMaxValidators, DefaultHistoricalEntries, + strings.Split(DefaultAssetIDs, "|"), ) } @@ -78,18 +86,23 @@ func (p *Params) ParamSetPairs() paramtypes.ParamSetPairs { paramtypes.NewParamSetPair( KeyEpochIdentifier, &p.EpochIdentifier, - epochTypes.ValidateEpochIdentifierInterface, + epochtypes.ValidateEpochIdentifierInterface, ), paramtypes.NewParamSetPair( - KeyMaxValidators, + stakingtypes.KeyMaxValidators, &p.MaxValidators, ValidatePositiveUint32, ), paramtypes.NewParamSetPair( - KeyHistoricalEntries, + stakingtypes.KeyHistoricalEntries, &p.HistoricalEntries, ValidatePositiveUint32, ), + paramtypes.NewParamSetPair( + KeyAssetIDs, + &p.AssetIDs, + ValidateAssetIDs, + ), } } @@ -98,7 +111,7 @@ func (p Params) Validate() error { if err := ValidatePositiveUint32(p.EpochsUntilUnbonded); err != nil { return fmt.Errorf("epochs until unbonded: %w", err) } - if err := epochTypes.ValidateEpochIdentifierInterface(p.EpochIdentifier); err != nil { + if err := epochtypes.ValidateEpochIdentifierInterface(p.EpochIdentifier); err != nil { return fmt.Errorf("epoch identifier: %w", err) } if err := ValidatePositiveUint32(p.MaxValidators); err != nil { @@ -129,3 +142,33 @@ func (p Params) String() string { } return string(out) } + +// ValidateAssetIDs checks whether the supplied value is a valid asset ID. +func ValidateAssetIDs(i interface{}) error { + if val, ok := i.([]string); !ok { + return fmt.Errorf("invalid parameter type: %T", i) + } else if len(val) == 0 { + return fmt.Errorf("invalid parameter value: %v", val) + } else { + for _, assetID := range val { + if !strings.Contains(assetID, "_") { + return fmt.Errorf("invalid parameter value (missing underscore): %v", val) + } + split := strings.Split(assetID, "_") + if len(split) != 2 { + return fmt.Errorf( + "invalid parameter value (unexpected number of underscores): %v", val, + ) + } + if len(split[0]) == 0 || len(split[1]) == 0 { + return fmt.Errorf("invalid parameter value (empty parts): %v", val) + } + // i cannot validate the address because it may be on a client chain and i have + // no idea what format or length it may have. i can only validate the chain ID. + if _, err := hexutil.DecodeUint64(split[1]); err != nil { + return fmt.Errorf("invalid parameter value (not a number): %v", split[1]) + } + } + } + return nil +} diff --git a/x/dogfood/types/params.pb.go b/x/dogfood/types/params.pb.go index 1b35e818a..a59e27d9e 100644 --- a/x/dogfood/types/params.pb.go +++ b/x/dogfood/types/params.pb.go @@ -36,6 +36,11 @@ type Params struct { MaxValidators uint32 `protobuf:"varint,3,opt,name=max_validators,json=maxValidators,proto3" json:"max_validators,omitempty"` // HistoricalEntries is the number of historical entries to persist. HistoricalEntries uint32 `protobuf:"varint,4,opt,name=historical_entries,json=historicalEntries,proto3" json:"historical_entries,omitempty"` + // AssetIDs is the ids of the assets which will be accepted by the module. + // It must be within the list of assets supported by the restaking module. + // The typical format of these IDs is + // lower(assetAddress) + _ + hex(clientChainLzID) + AssetIDs []string `protobuf:"bytes,5,rep,name=asset_ids,json=assetIds,proto3" json:"asset_ids,omitempty"` } func (m *Params) Reset() { *m = Params{} } @@ -98,6 +103,13 @@ func (m *Params) GetHistoricalEntries() uint32 { return 0 } +func (m *Params) GetAssetIDs() []string { + if m != nil { + return m.AssetIDs + } + return nil +} + func init() { proto.RegisterType((*Params)(nil), "exocore.dogfood.v1.Params") } @@ -105,25 +117,27 @@ func init() { func init() { proto.RegisterFile("exocore/dogfood/v1/params.proto", fileDescriptor_e8747fb70c97d97f) } var fileDescriptor_e8747fb70c97d97f = []byte{ - // 290 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x44, 0x90, 0x3f, 0x4b, 0xc3, 0x40, - 0x18, 0x87, 0x73, 0x5a, 0x0a, 0x1e, 0xd4, 0x3f, 0xa7, 0x42, 0x70, 0xb8, 0x16, 0x41, 0xa8, 0x83, - 0x39, 0xaa, 0x9b, 0xa3, 0xd0, 0x41, 0x04, 0x91, 0x42, 0x1d, 0x5c, 0xc2, 0x35, 0x77, 0x4d, 0x0f, - 0x9b, 0xbc, 0xe1, 0xee, 0x1a, 0xe3, 0xb7, 0x70, 0x74, 0xf4, 0xbb, 0xb8, 0x38, 0x76, 0x74, 0x94, - 0xe4, 0x8b, 0x48, 0x2f, 0x31, 0x6e, 0xc7, 0xef, 0x79, 0xee, 0x1d, 0x1e, 0xdc, 0x97, 0x05, 0x44, - 0xa0, 0x25, 0x13, 0x10, 0xcf, 0x01, 0x04, 0xcb, 0x47, 0x2c, 0xe3, 0x9a, 0x27, 0x26, 0xc8, 0x34, - 0x58, 0x20, 0xa4, 0x11, 0x82, 0x46, 0x08, 0xf2, 0xd1, 0xc9, 0x51, 0x0c, 0x31, 0x38, 0xcc, 0x36, - 0xaf, 0xda, 0x3c, 0xfd, 0x44, 0xb8, 0xfb, 0xe0, 0xbe, 0x92, 0x4b, 0x7c, 0x2c, 0x33, 0x88, 0x16, - 0x26, 0x5c, 0xa5, 0x56, 0x2d, 0xc3, 0x55, 0x3a, 0x83, 0x54, 0x48, 0xe1, 0xa3, 0x01, 0x1a, 0xf6, - 0x26, 0x87, 0x35, 0x9c, 0x6e, 0xd8, 0xb4, 0x41, 0xe4, 0x1c, 0xef, 0xbb, 0x39, 0x54, 0x42, 0xa6, - 0x56, 0xcd, 0x95, 0xd4, 0xfe, 0xd6, 0x00, 0x0d, 0x77, 0x26, 0x7b, 0x6e, 0xbf, 0x6d, 0x67, 0x72, - 0x86, 0x77, 0x13, 0x5e, 0x84, 0x39, 0x5f, 0x2a, 0xc1, 0x2d, 0x68, 0xe3, 0x6f, 0xbb, 0xbb, 0xbd, - 0x84, 0x17, 0x8f, 0xed, 0x48, 0x2e, 0x30, 0x59, 0x28, 0x63, 0x41, 0xab, 0x88, 0x2f, 0x43, 0x99, - 0x5a, 0xad, 0xa4, 0xf1, 0x3b, 0x4e, 0x3d, 0xf8, 0x27, 0xe3, 0x1a, 0x5c, 0x77, 0xde, 0x3f, 0xfa, - 0xde, 0xcd, 0xdd, 0x57, 0x49, 0xd1, 0xba, 0xa4, 0xe8, 0xa7, 0xa4, 0xe8, 0xad, 0xa2, 0xde, 0xba, - 0xa2, 0xde, 0x77, 0x45, 0xbd, 0xa7, 0x51, 0xac, 0xec, 0x62, 0x35, 0x0b, 0x22, 0x48, 0xd8, 0xb8, - 0x8e, 0x72, 0x2f, 0xed, 0x0b, 0xe8, 0x67, 0xf6, 0x17, 0xb1, 0x68, 0x33, 0xda, 0xd7, 0x4c, 0x9a, - 0x59, 0xd7, 0x95, 0xb9, 0xfa, 0x0d, 0x00, 0x00, 0xff, 0xff, 0x52, 0x3e, 0xbb, 0xe0, 0x66, 0x01, + // 322 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x44, 0x90, 0x3f, 0x4f, 0x02, 0x31, + 0x18, 0x87, 0xaf, 0x82, 0x04, 0x1a, 0xf1, 0x4f, 0xd5, 0xe4, 0xe2, 0x70, 0x10, 0x13, 0x13, 0x18, + 0xbc, 0x0b, 0xba, 0xb9, 0x49, 0x64, 0x20, 0x26, 0xc6, 0x90, 0xe0, 0xe0, 0xd2, 0x94, 0x6b, 0x39, + 0x1a, 0xb9, 0x7b, 0x2f, 0x6d, 0xc1, 0xf3, 0x5b, 0x38, 0x3a, 0xfa, 0x71, 0x1c, 0x19, 0x9d, 0x8c, + 0x39, 0x76, 0x3f, 0x83, 0xa1, 0x87, 0xb8, 0x35, 0xcf, 0xf3, 0xeb, 0x3b, 0x3c, 0xb8, 0x21, 0x32, + 0x08, 0x41, 0x89, 0x80, 0x43, 0x34, 0x06, 0xe0, 0xc1, 0xbc, 0x13, 0xa4, 0x4c, 0xb1, 0x58, 0xfb, + 0xa9, 0x02, 0x03, 0x84, 0xac, 0x07, 0xfe, 0x7a, 0xe0, 0xcf, 0x3b, 0x27, 0x47, 0x11, 0x44, 0x60, + 0x75, 0xb0, 0x7a, 0x15, 0xcb, 0xd3, 0x1f, 0x84, 0x2b, 0xf7, 0xf6, 0x2b, 0xb9, 0xc0, 0xc7, 0x22, + 0x85, 0x70, 0xa2, 0xe9, 0x2c, 0x31, 0x72, 0x4a, 0x67, 0xc9, 0x08, 0x12, 0x2e, 0xb8, 0x8b, 0x9a, + 0xa8, 0x55, 0x1f, 0x1c, 0x16, 0x72, 0xb8, 0x72, 0xc3, 0xb5, 0x22, 0x6d, 0xbc, 0x6f, 0x31, 0x95, + 0x5c, 0x24, 0x46, 0x8e, 0xa5, 0x50, 0xee, 0x56, 0x13, 0xb5, 0x6a, 0x83, 0x3d, 0xcb, 0xfb, 0x1b, + 0x4c, 0xce, 0xf0, 0x6e, 0xcc, 0x32, 0x3a, 0x67, 0x53, 0xc9, 0x99, 0x01, 0xa5, 0xdd, 0x92, 0xbd, + 0x5b, 0x8f, 0x59, 0xf6, 0xb0, 0x81, 0xe4, 0x1c, 0x93, 0x89, 0xd4, 0x06, 0x94, 0x0c, 0xd9, 0x94, + 0x8a, 0xc4, 0x28, 0x29, 0xb4, 0x5b, 0xb6, 0xd3, 0x83, 0x7f, 0xd3, 0x2b, 0x04, 0x69, 0xe3, 0x1a, + 0xd3, 0x5a, 0x18, 0x2a, 0xb9, 0x76, 0xb7, 0x9b, 0xa5, 0x56, 0xad, 0xbb, 0x93, 0x7f, 0x35, 0xaa, + 0xd7, 0x2b, 0xd8, 0xbf, 0xd1, 0x83, 0xaa, 0xd5, 0x7d, 0xae, 0xaf, 0xca, 0x6f, 0xef, 0x0d, 0xa7, + 0x7b, 0xfb, 0x91, 0x7b, 0x68, 0x91, 0x7b, 0xe8, 0x3b, 0xf7, 0xd0, 0xeb, 0xd2, 0x73, 0x16, 0x4b, + 0xcf, 0xf9, 0x5c, 0x7a, 0xce, 0x63, 0x27, 0x92, 0x66, 0x32, 0x1b, 0xf9, 0x21, 0xc4, 0x41, 0xaf, + 0xe8, 0x77, 0x27, 0xcc, 0x33, 0xa8, 0xa7, 0xe0, 0xaf, 0x77, 0xb6, 0x29, 0x6e, 0x5e, 0x52, 0xa1, + 0x47, 0x15, 0x1b, 0xf1, 0xf2, 0x37, 0x00, 0x00, 0xff, 0xff, 0xc1, 0x8d, 0x3f, 0x7c, 0x91, 0x01, 0x00, 0x00, } @@ -147,6 +161,15 @@ func (m *Params) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if len(m.AssetIDs) > 0 { + for iNdEx := len(m.AssetIDs) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.AssetIDs[iNdEx]) + copy(dAtA[i:], m.AssetIDs[iNdEx]) + i = encodeVarintParams(dAtA, i, uint64(len(m.AssetIDs[iNdEx]))) + i-- + dAtA[i] = 0x2a + } + } if m.HistoricalEntries != 0 { i = encodeVarintParams(dAtA, i, uint64(m.HistoricalEntries)) i-- @@ -202,6 +225,12 @@ func (m *Params) Size() (n int) { if m.HistoricalEntries != 0 { n += 1 + sovParams(uint64(m.HistoricalEntries)) } + if len(m.AssetIDs) > 0 { + for _, s := range m.AssetIDs { + l = len(s) + n += 1 + l + sovParams(uint64(l)) + } + } return n } @@ -329,6 +358,38 @@ func (m *Params) Unmarshal(dAtA []byte) error { break } } + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AssetIDs", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowParams + } + 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 ErrInvalidLengthParams + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthParams + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.AssetIDs = append(m.AssetIDs, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipParams(dAtA[iNdEx:]) From db09367930c70ccaf6b87b91ccf8b2d2191979db Mon Sep 17 00:00:00 2001 From: MaxMustermann2 <82761650+MaxMustermann2@users.noreply.github.com> Date: Mon, 4 Mar 2024 20:40:58 +0000 Subject: [PATCH 2/7] feat(dogfood): move to average pricing --- proto/exocore/dogfood/v1/dogfood.proto | 54 +- x/dogfood/keeper/abci.go | 107 ++- x/dogfood/keeper/genesis.go | 21 +- x/dogfood/keeper/impl_delegation_hooks.go | 103 +-- x/dogfood/keeper/impl_epochs_hooks.go | 12 +- x/dogfood/keeper/impl_operator_hooks.go | 141 +--- x/dogfood/keeper/keeper.go | 41 +- x/dogfood/keeper/pending.go | 30 - x/dogfood/keeper/queue.go | 45 -- x/dogfood/keeper/unbonding.go | 11 +- x/dogfood/keeper/validators.go | 70 +- x/dogfood/module.go | 4 +- x/dogfood/types/dogfood.pb.go | 903 ++++++++-------------- x/dogfood/types/expected_keepers.go | 10 + x/dogfood/types/keys.go | 17 + 15 files changed, 582 insertions(+), 987 deletions(-) delete mode 100644 x/dogfood/keeper/queue.go diff --git a/proto/exocore/dogfood/v1/dogfood.proto b/proto/exocore/dogfood/v1/dogfood.proto index 8f5ad37f5..c66e975e7 100644 --- a/proto/exocore/dogfood/v1/dogfood.proto +++ b/proto/exocore/dogfood/v1/dogfood.proto @@ -8,6 +8,7 @@ import "google/protobuf/timestamp.proto"; import "cosmos/staking/v1beta1/staking.proto"; import "cosmos_proto/cosmos.proto"; +import "tendermint/abci/types.proto"; import "tendermint/crypto/keys.proto"; option go_package = "github.com/ExocoreNetwork/exocore/x/dogfood/types"; @@ -27,52 +28,6 @@ message ExocoreValidator { ]; } -// OperationType is used to indicate the type of operation that is being -// cached by the module to create the updated validator set. -enum OperationType { - option (gogoproto.goproto_enum_prefix) = false; - // KeyOpUnspecified is used to indicate that the operation type is not specified. - // This should never be used. - OPERATION_TYPE_UNSPECIFIED = 0 [ (gogoproto.enumvalue_customname) = "KeyOpUnspecified" ]; - // KeyAddition is used to indicate that the operation is a key addition. - OPERATION_TYPE_ADDITION_OR_UPDATE = 1 [ (gogoproto.enumvalue_customname) = "KeyAdditionOrUpdate" ]; - // KeyRemoval is used to indicate that the operation is a key removal. Typically - // this is done due to key replacement mechanism and not directly. - OPERATION_TYPE_REMOVAL = 2 [ (gogoproto.enumvalue_customname) = "KeyRemoval" ]; -} - -// QueueResultType is used to indicate the result of the queue operation. -enum QueueResultType { - option (gogoproto.goproto_enum_prefix) = false; - // QueueResultUnspecified is used to indicate that the queue result type is not specified. - QUEUE_RESULT_TYPE_UNSPECIFIED = 0 [ (gogoproto.enumvalue_customname) = "QueueResultUnspecified" ]; - // QueueResultSuccess is used to indicate that the queue operation was successful. - QUEUE_RESULT_TYPE_SUCCESS = 1 [ (gogoproto.enumvalue_customname) = "QueueResultSuccess" ]; - // QueueResultExists is used to indicate that the queue operation failed because the - // operation already exists in the queue. - QUEUE_RESULT_TYPE_EXISTS = 2 [ (gogoproto.enumvalue_customname) = "QueueResultExists" ]; - // QueueResultRemoved is used to indicate that the queue operation resulted in an existing - // operation being removed from the queue. - QUEUE_RESULT_TYPE_REMOVED = 3 [ (gogoproto.enumvalue_customname) = "QueueResultRemoved" ]; -} - -// Operation is used to indicate the operation that is being cached by the module -// to create the updated validator set. -message Operation { - // OperationType is the type of the operation (addition / removal). - OperationType operation_type = 1; - // OperatorAddress is the sdk.AccAddress of the operator. - bytes operator_address = 2; - // PubKey is the public key for which the operation is being applied. - tendermint.crypto.PublicKey pub_key = 3 [(gogoproto.nullable) = false]; -} - -// Operations is a collection of Operation. -message Operations { - // list is the list of operations. - repeated Operation list = 1 [(gogoproto.nullable) = false]; -} - // AccountAddresses represents a list of account addresses. It is used to store the list of // operator addresses whose operations are maturing at an epoch. message AccountAddresses { @@ -110,4 +65,11 @@ message HeaderSubset { bytes next_validators_hash = 2; // state after txs from the previous block bytes app_hash = 3; +} + +// KeyPowerMapping is a mapping of the consensus public key (as a string) +// to the power of the key. +message KeyPowerMapping { + // list is the actual mapping of the consensus public key to the power. + map list = 1; } \ No newline at end of file diff --git a/x/dogfood/keeper/abci.go b/x/dogfood/keeper/abci.go index a9641c68d..b1f4522a1 100644 --- a/x/dogfood/keeper/abci.go +++ b/x/dogfood/keeper/abci.go @@ -1,12 +1,21 @@ package keeper import ( - "github.com/ExocoreNetwork/exocore/x/dogfood/types" + "sort" + abci "github.com/cometbft/cometbft/abci/types" + tmprotocrypto "github.com/cometbft/cometbft/proto/tendermint/crypto" sdk "github.com/cosmos/cosmos-sdk/types" ) func (k Keeper) EndBlock(ctx sdk.Context) []abci.ValidatorUpdate { + id, _ := k.getValidatorSetID(ctx, ctx.BlockHeight()) + if !k.IsEpochEnd(ctx) { + // save the same id for the next block height. + k.setValidatorSetID(ctx, ctx.BlockHeight()+1, id) + return []abci.ValidatorUpdate{} + } + defer k.ClearEpochEnd(ctx) // start with clearing the hold on the undelegations. undelegations := k.GetPendingUndelegations(ctx) for _, undelegation := range undelegations.GetList() { @@ -30,40 +39,78 @@ func (k Keeper) EndBlock(ctx sdk.Context) []abci.ValidatorUpdate { } k.ClearPendingConsensusAddrs(ctx) // finally, perform the actual operations of vote power changes. - operations := k.GetPendingOperations(ctx) - id, _ := k.getValidatorSetID(ctx, ctx.BlockHeight()) - if len(operations.GetList()) == 0 { - // there is no validator set change, so we just increment the block height - // and retain the same val set id mapping. - k.setValidatorSetID(ctx, ctx.BlockHeight()+1, id) + // 1. find all operator keys for the chain. + // 2. find last stored operator keys + their powers. + // 3. find newest vote power for the operator keys, and sort them. + // 4. loop through #1 and see if anything has changed. + // if it hasn't, do nothing for that operator key. + // if it has, queue an update. + prev := k.getKeyPowerMapping(ctx).List + var res []abci.ValidatorUpdate + operators, keys := k.operatorKeeper.GetActiveOperatorsForChainId(ctx, ctx.ChainID()) + powers, err := k.restakingKeeper.GetAvgDelegatedValue( + ctx, operators, k.GetAssetIDs(ctx), + ) + if err != nil { return []abci.ValidatorUpdate{} } - res := make([]abci.ValidatorUpdate, 0, len(operations.GetList())) - for _, operation := range operations.GetList() { - switch operation.OperationType { - case types.KeyAdditionOrUpdate: - power, err := k.restakingKeeper.GetOperatorAssetValue( - ctx, operation.OperatorAddress, - ) - if err != nil { - // this should never happen, but if it does, we just skip the operation. - continue - } - res = append(res, abci.ValidatorUpdate{ - PubKey: operation.PubKey, - Power: power, - }) - case types.KeyRemoval: - res = append(res, abci.ValidatorUpdate{ - PubKey: operation.PubKey, - Power: 0, - }) - case types.KeyOpUnspecified: - // this should never happen, but if it does, we just skip the operation. + operators, keys, powers = sortByPower(operators, keys, powers) + for i := range operators { + key := keys[i] + power := powers[i] + // find the previous power. + prevPower, found := prev[key.String()] + if found && prevPower == power { + delete(prev, key.String()) continue } + // either the key was not in the previous set, + // or the power has changed. + res = append(res, abci.ValidatorUpdate{ + PubKey: key, + Power: power, + }) + } + // the remaining keys in prev have lost their power. + for key, _ := range prev { + bz := []byte(key) + var keyObj tmprotocrypto.PublicKey + k.cdc.MustUnmarshal(bz, &keyObj) + res = append(res, abci.ValidatorUpdate{ + PubKey: keyObj, + Power: 0, + }) } // call via wrapper function so that validator info is stored. // the id is incremented by 1 for the next block. - return k.ApplyValidatorChanges(ctx, res, id+1, false) + return k.ApplyValidatorChanges(ctx, res, id+1) +} + +func sortByPower( + operatorAddrs []sdk.AccAddress, + pubKeys []tmprotocrypto.PublicKey, + powers []int64, +) ([]sdk.AccAddress, []tmprotocrypto.PublicKey, []int64) { + // Create a slice of indices + indices := make([]int, len(powers)) + for i := range indices { + indices[i] = i + } + + // Sort the indices slice based on the powers slice + sort.SliceStable(indices, func(i, j int) bool { + return powers[indices[i]] > powers[indices[j]] + }) + + // Reorder all slices using the sorted indices + sortedOperatorAddrs := make([]sdk.AccAddress, len(operatorAddrs)) + sortedPubKeys := make([]tmprotocrypto.PublicKey, len(pubKeys)) + sortedPowers := make([]int64, len(powers)) + for i, idx := range indices { + sortedOperatorAddrs[i] = operatorAddrs[idx] + sortedPubKeys[i] = pubKeys[idx] + sortedPowers[i] = powers[idx] + } + + return sortedOperatorAddrs, sortedPubKeys, sortedPowers } diff --git a/x/dogfood/keeper/genesis.go b/x/dogfood/keeper/genesis.go index e0544924d..416d08093 100644 --- a/x/dogfood/keeper/genesis.go +++ b/x/dogfood/keeper/genesis.go @@ -1,6 +1,8 @@ package keeper import ( + "fmt" + "github.com/ExocoreNetwork/exocore/x/dogfood/types" abci "github.com/cometbft/cometbft/abci/types" sdk "github.com/cosmos/cosmos-sdk/types" @@ -21,13 +23,28 @@ func (k Keeper) InitGenesis( // is not running. it means that the genesis file is malformed. panic("epoch info not found") } - return k.ApplyValidatorChanges(ctx, genState.ValSet, types.InitialValidatorSetID, true) + // apply the same logic to the staking assets. + for _, assetID := range genState.Params.AssetIDs { + if !k.restakingKeeper.IsStakingAsset(ctx, assetID) { + panic(fmt.Errorf("staking asset %s not found", assetID)) + } + } + // genState must not be malformed. + if len(genState.ValSet) > int(k.GetMaxValidators(ctx)) { + panic(fmt.Errorf( + "cannot have more than %d validators in the genesis state", + k.GetMaxValidators(ctx), + )) + } + return k.ApplyValidatorChanges( + ctx, genState.ValSet, types.InitialValidatorSetID, + ) } // ExportGenesis returns the module's exported genesis func (k Keeper) ExportGenesis(ctx sdk.Context) *types.GenesisState { genesis := types.DefaultGenesis() genesis.Params = k.GetDogfoodParams(ctx) - + // TODO(mm) return genesis } diff --git a/x/dogfood/keeper/impl_delegation_hooks.go b/x/dogfood/keeper/impl_delegation_hooks.go index e32442853..bf459ec0d 100644 --- a/x/dogfood/keeper/impl_delegation_hooks.go +++ b/x/dogfood/keeper/impl_delegation_hooks.go @@ -22,100 +22,33 @@ func (k *Keeper) DelegationHooks() DelegationHooksWrapper { // AfterDelegation is called after a delegation is made. func (wrapper DelegationHooksWrapper) AfterDelegation( - ctx sdk.Context, operator sdk.AccAddress, + sdk.Context, sdk.AccAddress, ) { - found, pubKey, err := wrapper.keeper.operatorKeeper.GetOperatorConsKeyForChainId( - ctx, operator, ctx.ChainID(), - ) - if err != nil { - // the operator keeper can offer two errors: not an operator and not a chain. - // both of these should not happen here because the dogfooding genesis will - // register the chain, and the operator must be known to the delegation module - // when it calls this hook. - panic(err) - } - if found { - if !wrapper.keeper.operatorKeeper.IsOperatorOptingOutFromChainId( - ctx, operator, ctx.ChainID(), - ) { - // only queue the operation if operator is still opted into the chain. - res := wrapper.keeper.QueueOperation( - ctx, operator, pubKey, types.KeyAdditionOrUpdate, - ) - switch res { - case types.QueueResultExists: - // nothing to do because the operation is in the queue already. - case types.QueueResultRemoved: - // a KeyRemoval was in the queue which has now been cleared from the queue. - // the KeyRemoval can only be in the queue if the operator is opting out from - // the chain, or has replaced their key. if it is the former, it means that - // there is some inconsistency. if it is the latter, it means that the operator - // module just reported the old key in `GetOperatorConsKeyForChainId`, which - // should not happen. - panic("unexpected removal of operation from queue") - case types.QueueResultSuccess: - // best case, nothing to do. - case types.QueueResultUnspecified: - panic("unspecified queue result") - } - } - } + // we do nothing here, since the vote power for all operators is calculated + // in the end separately. even if we knew the amount of the delegation, the + // average exchange rate for the epoch is unknown. } // AfterUndelegationStarted is called after an undelegation is started. func (wrapper DelegationHooksWrapper) AfterUndelegationStarted( ctx sdk.Context, operator sdk.AccAddress, recordKey []byte, ) { - found, pubKey, err := wrapper.keeper.operatorKeeper.GetOperatorConsKeyForChainId( + var unbondingCompletionEpoch int64 + if wrapper.keeper.operatorKeeper.IsOperatorOptingOutFromChainId( ctx, operator, ctx.ChainID(), - ) - if err != nil { - panic(err) - } - if found { - // note that this is still key addition or update because undelegation does not remove - // the operator from the list. it only decreases their vote power. - if !wrapper.keeper.operatorKeeper.IsOperatorOptingOutFromChainId( - ctx, operator, ctx.ChainID(), - ) { - // only queue the operation if operator is still opted into the chain. - res := wrapper.keeper.QueueOperation( - ctx, operator, pubKey, types.KeyAdditionOrUpdate, - ) - switch res { - case types.QueueResultExists: - // nothing to do - case types.QueueResultRemoved: - // KeyRemoval + KeyAdditionOrUpdate => Removed - // KeyRemoval can happen - // 1. if the operator is opting out from the chain,which is inconsistent. - // 2. if the operator is replacing their old key, which should not be returned - // by `GetOperatorConsKeyForChainId`. - panic("unexpected removal of operation from queue") - case types.QueueResultSuccess: - // best case, nothing to do. - case types.QueueResultUnspecified: - panic("unspecified queue result") - } - } - // now handle the unbonding timeline. - wrapper.keeper.delegationKeeper.IncrementUndelegationHoldCount(ctx, recordKey) - // mark for unbonding release. - // note that we aren't supporting redelegation yet, so this undelegated amount will be - // held until the end of the unbonding period or the operator opt out period, whichever - // is first. - var unbondingCompletionEpoch int64 - if wrapper.keeper.operatorKeeper.IsOperatorOptingOutFromChainId( - ctx, operator, ctx.ChainID(), - ) { - unbondingCompletionEpoch = wrapper.keeper.GetOperatorOptOutFinishEpoch( - ctx, operator, - ) - } else { - unbondingCompletionEpoch = wrapper.keeper.GetUnbondingCompletionEpoch(ctx) - } - wrapper.keeper.AppendUndelegationToMature(ctx, unbondingCompletionEpoch, recordKey) + ) { + // if the operator is opting out, we need to use the finish epoch of the opt out. + unbondingCompletionEpoch = wrapper.keeper.GetOperatorOptOutFinishEpoch(ctx, operator) + // even if the operator opts back in, the undelegated vote power does not reappear + // in the picture. slashable events between undelegation and opt in cannot occur + // because the operator is not in the validator set. + } else { + // otherwise, we use the default unbonding completion epoch. + unbondingCompletionEpoch = wrapper.keeper.GetUnbondingCompletionEpoch(ctx) + // if the operator opts out after this, the undelegation will mature before the opt out. + // so this is not a concern. } + wrapper.keeper.AppendUndelegationToMature(ctx, unbondingCompletionEpoch, recordKey) } // AfterUndelegationCompleted is called after an undelegation is completed. diff --git a/x/dogfood/keeper/impl_epochs_hooks.go b/x/dogfood/keeper/impl_epochs_hooks.go index c17314a89..c3bed17db 100644 --- a/x/dogfood/keeper/impl_epochs_hooks.go +++ b/x/dogfood/keeper/impl_epochs_hooks.go @@ -22,7 +22,7 @@ func (k *Keeper) EpochsHooks() EpochsHooksWrapper { return EpochsHooksWrapper{k} } -// AfterEpochEnd is called after an epoch ends. +// AfterEpochEnd is called after an epoch ends. It is called during the BeginBlock function. func (wrapper EpochsHooksWrapper) AfterEpochEnd( ctx sdk.Context, identifier string, epoch int64, ) { @@ -32,17 +32,19 @@ func (wrapper EpochsHooksWrapper) AfterEpochEnd( // note that this hook is called during BeginBlock, and the "pending" operations will be // applied within this block. however, for clarity, it is highlighted that unbonding // takes N epochs + 1 block to complete. - operations := wrapper.keeper.GetQueuedOperations(ctx) - wrapper.keeper.SetPendingOperations(ctx, types.Operations{List: operations}) - wrapper.keeper.ClearQueuedOperations(ctx) + wrapper.keeper.MarkEpochEnd(ctx) + // find the opt outs that mature when this epoch ends, and move them to pending. optOuts := wrapper.keeper.GetOptOutsToFinish(ctx, epoch) wrapper.keeper.SetPendingOptOuts(ctx, types.AccountAddresses{List: optOuts}) wrapper.keeper.ClearOptOutsToFinish(ctx, epoch) + // next, find the consensus addresses that are to be pruned, and move them to pending. consAddresses := wrapper.keeper.GetConsensusAddrsToPrune(ctx, epoch) wrapper.keeper.SetPendingConsensusAddrs( ctx, types.ConsensusAddresses{List: consAddresses}, ) wrapper.keeper.ClearConsensusAddrsToPrune(ctx, epoch) + // finally, find the undelegations that mature when this epoch ends, and move them to + // pending. undelegations := wrapper.keeper.GetUndelegationsToMature(ctx, epoch) wrapper.keeper.SetPendingUndelegations( ctx, types.UndelegationRecordKeys{ @@ -56,5 +58,5 @@ func (wrapper EpochsHooksWrapper) AfterEpochEnd( func (wrapper EpochsHooksWrapper) BeforeEpochStart( sdk.Context, string, int64, ) { - // nothing to do + // no-op } diff --git a/x/dogfood/keeper/impl_operator_hooks.go b/x/dogfood/keeper/impl_operator_hooks.go index 3599d6565..795b76dd9 100644 --- a/x/dogfood/keeper/impl_operator_hooks.go +++ b/x/dogfood/keeper/impl_operator_hooks.go @@ -21,127 +21,56 @@ func (k *Keeper) OperatorHooks() OperatorHooksWrapper { return OperatorHooksWrapper{k} } -// Hooks assumptions: Assuming I is opt-in, O is opt-out and R is key replacement, these are all -// possible within the same epoch, for a fresh operator. -// I O -// I R -// I R O -// This is not possible for a fresh operator to do: -// I O R -// R I O -// R I -// For an operator that is already opted in, the list looks like follows: -// R O -// O I (reversing the decision to opt out) -// O I R -// R O I -// The impossible list looks like: -// O R -// O R I -// Replacing the key with the same key is not possible, so it is not covered. -// The assumption is that these are enforced (allowed/denied) by the operator module. - -// Cases for a fresh operator: -// I + O => KeyAdditionOrUpdate + KeyRemoval => Success + Removed => covered. -// I + R => KeyAdditionOrUpdate (old) + KeyAdditionOrUpdate (new) + KeyRemoval (old) => -// Success + Success + Removed + => not considered unbonding of the old key since it -// was not yet effective => covered. -// I + R + O => KeyAdditionOrUpdate (old) + KeyAdditionOrUpdate (new) + KeyRemoval (old) + -// KeyRemoval (new) => -// Success (old) + Success (new) + Removed (old) + Removed (new) => covered - -// Cases for an operator that has already opted in: -// R + O => KeyAdditionOrUpdate (new) + KeyRemoval (old) + KeyRemoval (new) => -// Success (new) + Success (old) + Removed (new) => -// unbonding data made (old) => covered. -// O + I -// O + I case 1 => KeyRemoval (old) + KeyAdditionOrUpdate (new) => Success (old) + Success (new) -// => unbonding data made (old) => covered. -// O + I case 2 => KeyRemoval (old) + KeyAdditionOrUpdate (old) => Success (old) + Removed (old) -// => unbonding data made (old) and then cleared => covered. -// O + I + R -// O + I + R case 1 => KeyRemoval (old) + KeyAdditionOrUpdate (old) + KeyRemoval (old) + -// KeyAdditionOrUpdate (new) => Success (old) + Removed (old) + Success (old) + -// Success (new) => unbonding data old made + cleared + made => covered. -// O + I + R case 2 => -// AfterOperatorOptOut(old) => Success => unbonding data made for old -// AfterOperatorOptIn(new) => Success => no data changed -// AfterOperatorKeyReplacement(new, new2) => -// new2 operation KeyAdditionOrUpdate => Success => no data changed -// new operation KeyRemoval => Removed => no data changed -// => covered -// R + O + I => KeyAdditionOrUpdate (new) + KeyRemoval (old) + KeyRemoval (new) + -// KeyAdditionOrUpdate (X) -// Success + Success (=> unbonding data for old) + Removed (=> no data) + -// case 1 => X == new => Success => no change => covered -// case 2 => X == old => Removed => unbonding data for old removed => covered. -// case 3 => X == abc => Success => no change and unbonding data for old is not removed => -// covered. - // AfterOperatorOptIn is the implementation of the operator hooks. func (h OperatorHooksWrapper) AfterOperatorOptIn( - ctx sdk.Context, addr sdk.AccAddress, - chainID string, pubKey tmprotocrypto.PublicKey, + ctx sdk.Context, addr sdk.AccAddress, chainID string, key tmprotocrypto.PublicKey, ) { - if strings.Compare(ctx.ChainID(), chainID) == 0 { - // res == Removed, it means operator has opted back in - // res == Success, there is no additional information to store - // res == Exists, there is nothing to do - if res := h.keeper.QueueOperation( - ctx, addr, pubKey, types.KeyAdditionOrUpdate, - ); res == types.QueueResultRemoved { - // the old operation was key removal, which is now removed from the queue. - // so all of the changes that were associated with it need to be undone. - h.keeper.ClearUnbondingInformation(ctx, addr, pubKey) - } - } + // an operator opting in does not meaningfully affect this module, since + // this information will be fetched at the end of the epoch + // and the operator's vote power will be calculated then. + // however, we will still clear the unbonding information, if it exists. + h.keeper.ClearUnbondingInformation(ctx, addr, key) } // AfterOperatorKeyReplacement is the implementation of the operator hooks. func (h OperatorHooksWrapper) AfterOperatorKeyReplacement( - ctx sdk.Context, addr sdk.AccAddress, - newKey tmprotocrypto.PublicKey, oldKey tmprotocrypto.PublicKey, - chainID string, + ctx sdk.Context, operator sdk.AccAddress, oldKey tmprotocrypto.PublicKey, + newKey tmprotocrypto.PublicKey, chainID string, ) { if strings.Compare(chainID, ctx.ChainID()) == 0 { - // remove the old key - // res == Removed, it means operator had added this key and is now removing it. - // no additional information to clear. - // res == Success, the old key should be pruned from the operator module. - // res == Exists, there is nothing to do. - if res := h.keeper.QueueOperation( - ctx, addr, oldKey, types.KeyRemoval, - ); res == types.QueueResultSuccess { - // the old key can be marked for pruning - h.keeper.SetUnbondingInformation(ctx, addr, oldKey, false) - } - // add the new key - // res == Removed, it means operator has added their original key again - // res == Success, there is no additional information to store - // res == Exists, there is no nothing to do - if res := h.keeper.QueueOperation( - ctx, addr, newKey, types.KeyAdditionOrUpdate, - ); res == types.QueueResultRemoved { - // see AfterOperatorOptIn for explanation - h.keeper.ClearUnbondingInformation(ctx, addr, newKey) - } + // a key replacement means that the old key needs to be pruned upon maturity. + h.keeper.SetUnbondingInformation(ctx, operator, oldKey, false) + h.keeper.ClearUnbondingInformation(ctx, operator, newKey) } + // // remove the old key + // // res == Removed, it means operator had added this key and is now removing it. + // // no additional information to clear. + // // res == Success, the old key should be pruned from the operator module. + // // res == Exists, there is nothing to do. + // if res := h.keeper.QueueOperation( + // ctx, addr, oldKey, types.KeyRemoval, + // ); res == types.QueueResultSuccess { + // // the old key can be marked for pruning + // h.keeper.SetUnbondingInformation(ctx, addr, oldKey, false) + // } + // // add the new key + // // res == Removed, it means operator has added their original key again + // // res == Success, there is no additional information to store + // // res == Exists, there is no nothing to do + // if res := h.keeper.QueueOperation( + // ctx, addr, newKey, types.KeyAdditionOrUpdate, + // ); res == types.QueueResultRemoved { + // // see AfterOperatorOptIn for explanation + // h.keeper.ClearUnbondingInformation(ctx, addr, newKey) + // } + // } } // AfterOperatorOptOutInitiated is the implementation of the operator hooks. func (h OperatorHooksWrapper) AfterOperatorOptOutInitiated( - ctx sdk.Context, addr sdk.AccAddress, - chainID string, pubKey tmprotocrypto.PublicKey, + ctx sdk.Context, operator sdk.AccAddress, chainID string, key tmprotocrypto.PublicKey, ) { if strings.Compare(chainID, ctx.ChainID()) == 0 { - // res == Removed means operator had opted in and is now opting out. nothing to do if - // it is within the same epoch. - // res == Success, set up pruning deadline and opt out completion deadline - // res == Exists, there is nothing to do (should never happen) - if res := h.keeper.QueueOperation( - ctx, addr, pubKey, types.KeyRemoval, - ); res == types.QueueResultSuccess { - h.keeper.SetUnbondingInformation(ctx, addr, pubKey, true) - } + h.keeper.SetUnbondingInformation(ctx, operator, key, true) } } diff --git a/x/dogfood/keeper/keeper.go b/x/dogfood/keeper/keeper.go index e85f961d0..a0ba33e63 100644 --- a/x/dogfood/keeper/keeper.go +++ b/x/dogfood/keeper/keeper.go @@ -81,37 +81,26 @@ func (k Keeper) Hooks() types.DogfoodHooks { return k.dogfoodHooks } -// GetQueuedKeyOperations returns the list of operations that are queued for execution at the -// end of the current epoch. -func (k Keeper) GetQueuedOperations( - ctx sdk.Context, -) []types.Operation { +// MarkEpochEnd marks the end of the epoch. It is called within the BeginBlocker to inform +// the module to apply the validator updates at the end of this block. +func (k Keeper) MarkEpochEnd(ctx sdk.Context) { store := ctx.KVStore(k.storeKey) - bz := store.Get(types.QueuedOperationsKey()) - if bz == nil { - return []types.Operation{} - } - var operations types.Operations - if err := operations.Unmarshal(bz); err != nil { - // TODO(mm): any failure to unmarshal is treated as no operations or panic? - return []types.Operation{} - } - return operations.GetList() + key := types.EpochEndKey() + store.Set(key, []byte{1}) } -// ClearQueuedOperations clears the operations to be executed at the end of the epoch. -func (k Keeper) ClearQueuedOperations(ctx sdk.Context) { +// IsEpochEnd returns true if the epoch ended in the beginning of this block, or the end of the +// previous block. +func (k Keeper) IsEpochEnd(ctx sdk.Context) bool { store := ctx.KVStore(k.storeKey) - store.Delete(types.QueuedOperationsKey()) + key := types.EpochEndKey() + return store.Has(key) } -// setQueuedOperations is a private, internal function used to update the current queue of -// operations to be executed at the end of the epoch with the supplied value. -func (k Keeper) setQueuedOperations(ctx sdk.Context, operations types.Operations) { +// ClearEpochEnd clears the epoch end marker. It is called after the epoch end operations are +// applied. +func (k Keeper) ClearEpochEnd(ctx sdk.Context) { store := ctx.KVStore(k.storeKey) - bz, err := operations.Marshal() - if err != nil { - panic(err) - } - store.Set(types.QueuedOperationsKey(), bz) + key := types.EpochEndKey() + store.Delete(key) } diff --git a/x/dogfood/keeper/pending.go b/x/dogfood/keeper/pending.go index 9bf05ae17..e3cf92288 100644 --- a/x/dogfood/keeper/pending.go +++ b/x/dogfood/keeper/pending.go @@ -5,36 +5,6 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) -// SetPendingOperations sets the pending operations to be applied at the end of the block. -func (k Keeper) SetPendingOperations(ctx sdk.Context, operations types.Operations) { - store := ctx.KVStore(k.storeKey) - bz, err := operations.Marshal() - if err != nil { - panic(err) - } - store.Set(types.PendingOperationsKey(), bz) -} - -// GetPendingOperations returns the pending operations to be applied at the end of the block. -func (k Keeper) GetPendingOperations(ctx sdk.Context) types.Operations { - store := ctx.KVStore(k.storeKey) - bz := store.Get(types.PendingOperationsKey()) - if bz == nil { - return types.Operations{} - } - var operations types.Operations - if err := operations.Unmarshal(bz); err != nil { - return types.Operations{} - } - return operations -} - -// ClearPendingOperations clears the pending operations to be applied at the end of the block. -func (k Keeper) ClearPendingOperations(ctx sdk.Context) { - store := ctx.KVStore(k.storeKey) - store.Delete(types.PendingOperationsKey()) -} - // SetPendingOptOuts sets the pending opt-outs to be applied at the end of the block. func (k Keeper) SetPendingOptOuts(ctx sdk.Context, addrs types.AccountAddresses) { store := ctx.KVStore(k.storeKey) diff --git a/x/dogfood/keeper/queue.go b/x/dogfood/keeper/queue.go deleted file mode 100644 index 07cedfb32..000000000 --- a/x/dogfood/keeper/queue.go +++ /dev/null @@ -1,45 +0,0 @@ -package keeper - -import ( - "github.com/ExocoreNetwork/exocore/x/dogfood/types" - tmprotocrypto "github.com/cometbft/cometbft/proto/tendermint/crypto" - sdk "github.com/cosmos/cosmos-sdk/types" -) - -// QueueOperation adds an operation to the consensus public key queue. If a similar operation -// already exists, the queue is not modified and QueueResultExists is returned. If a reverse -// operation already exists (removal + addition, or addition + removal), the old operation is -// dropped from the queue and QueueResultRemoved is returned. In the case that the operation is -// added to the queue, QueueResultSuccess is returned. -func (k Keeper) QueueOperation( - ctx sdk.Context, addr sdk.AccAddress, - key tmprotocrypto.PublicKey, operationType types.OperationType, -) types.QueueResultType { - if operationType == types.KeyOpUnspecified { - // should never happen - panic("invalid operation type") - } - currentQueue := k.GetQueuedOperations(ctx) - indexToDelete := len(currentQueue) - for i, operation := range currentQueue { - if operation.PubKey.Equal(key) { - if operation.OperationType == operationType { - return types.QueueResultExists - } - // reverse operation exists, remove it - indexToDelete = i - break - } - } - ret := types.QueueResultSuccess - if indexToDelete > len(currentQueue) { - currentQueue = append(currentQueue[:indexToDelete], currentQueue[indexToDelete+1:]...) - ret = types.QueueResultRemoved - } else { - operation := types.Operation{OperationType: operationType, OperatorAddress: addr, PubKey: key} - currentQueue = append(currentQueue, operation) - } - operations := types.Operations{List: currentQueue} - k.setQueuedOperations(ctx, operations) - return ret -} diff --git a/x/dogfood/keeper/unbonding.go b/x/dogfood/keeper/unbonding.go index 4070c87dc..4092acc8c 100644 --- a/x/dogfood/keeper/unbonding.go +++ b/x/dogfood/keeper/unbonding.go @@ -17,7 +17,7 @@ func (k Keeper) ClearUnbondingInformation( k.RemoveOptOutToFinish(ctx, optOutEpoch, addr) consAddress, err := types.TMCryptoPublicKeyToConsAddr(pubKey) if err != nil { - panic(err) + return } k.DeleteConsensusAddrToPrune(ctx, optOutEpoch, consAddress) } @@ -27,13 +27,13 @@ func (k Keeper) SetUnbondingInformation( ctx sdk.Context, addr sdk.AccAddress, pubKey tmprotocrypto.PublicKey, isOptingOut bool, ) { unbondingCompletionEpoch := k.GetUnbondingCompletionEpoch(ctx) - k.AppendOptOutToFinish(ctx, unbondingCompletionEpoch, addr) if isOptingOut { + k.AppendOptOutToFinish(ctx, unbondingCompletionEpoch, addr) k.SetOperatorOptOutFinishEpoch(ctx, addr, unbondingCompletionEpoch) } consAddress, err := types.TMCryptoPublicKeyToConsAddr(pubKey) if err != nil { - panic(err) + return } k.AppendConsensusAddrToPrune(ctx, unbondingCompletionEpoch, consAddress) } @@ -44,12 +44,9 @@ func (k Keeper) GetUnbondingCompletionEpoch( ctx sdk.Context, ) int64 { unbondingEpochs := k.GetEpochsUntilUnbonded(ctx) - epochInfo, found := k.epochsKeeper.GetEpochInfo( + epochInfo, _ := k.epochsKeeper.GetEpochInfo( ctx, k.GetEpochIdentifier(ctx), ) - if !found { - panic("current epoch not found") - } // if i execute the transaction at epoch 5, the vote power change // goes into effect at the beginning of epoch 6. the information // should be held for 7 epochs, so it should be deleted at the diff --git a/x/dogfood/keeper/validators.go b/x/dogfood/keeper/validators.go index 13336a37f..219fbb2ba 100644 --- a/x/dogfood/keeper/validators.go +++ b/x/dogfood/keeper/validators.go @@ -30,11 +30,11 @@ func (k Keeper) UnbondingTime(ctx sdk.Context) time.Duration { // ApplyValidatorChanges returns the validator set as is. However, it also // stores the validators that are added or those that are removed, and updates -// the power for the existing validators. It also allows any hooks registered +// the stored power for the existing validators. It also allows any hooks registered // on the keeper to be executed. Lastly, it stores the validator set against the // provided validator set id. func (k Keeper) ApplyValidatorChanges( - ctx sdk.Context, changes []abci.ValidatorUpdate, valSetID uint64, genesis bool, + ctx sdk.Context, changes []abci.ValidatorUpdate, valSetID uint64, ) []abci.ValidatorUpdate { ret := []abci.ValidatorUpdate{} for _, change := range changes { @@ -42,16 +42,20 @@ func (k Keeper) ApplyValidatorChanges( pubkey, err := cryptocodec.FromTmProtoPublicKey(change.GetPubKey()) if err != nil { // An error here would indicate that this change is invalid. + // The change is received either from the genesis file, or from + // other parts of the module. // In no situation it should happen, however, if it does, // we do not panic. Simply skip the change. continue } + // the address is just derived from the public key and + // has no correlation with the operator address on Exocore. addr := pubkey.Address() val, found := k.GetValidator(ctx, addr) - switch found { case true: - // update or delete an existing validator + // update or delete an existing validator. + // contract: power must not be negative. if change.Power < 1 { k.DeleteValidator(ctx, addr) } else { @@ -60,12 +64,12 @@ func (k Keeper) ApplyValidatorChanges( } case false: if change.Power > 0 { - // create a new validator - the address is just derived from the public key and - // has no correlation with the operator address on Exocore + // create a new validator. ocVal, err := types.NewExocoreValidator(addr, change.Power, pubkey) if err != nil { continue } + // guard for errors within the hook. cc, writeFunc := ctx.CacheContext() k.SetValidator(cc, ocVal) err = k.Hooks().AfterValidatorBonded(cc, sdk.ConsAddress(addr), nil) @@ -84,7 +88,7 @@ func (k Keeper) ApplyValidatorChanges( ret = append(ret, change) } - // store the validator set against the provided validator set id + // store the updated validator set against the provided validator set id lastVals := types.Validators{} for _, v := range k.GetAllExocoreValidators(ctx) { // we stored the validators above, so this will never fail. @@ -97,16 +101,15 @@ func (k Keeper) ApplyValidatorChanges( val.Status = stakingtypes.Bonded // Compute tokens from voting power val.Tokens = sdk.TokensFromConsensusPower(v.Power, sdk.DefaultPowerReduction) - lastVals.List = append(lastVals.GetList(), val) + lastVals.List = append(lastVals.List, val) } k.setValidatorSet(ctx, valSetID, &lastVals) - if !genesis { - // the val set change is effective as of the next block, so height + 1. - k.setValidatorSetID(ctx, ctx.BlockHeight()+1, valSetID) - } else { - // the val set change is effective immediately. - k.setValidatorSetID(ctx, ctx.BlockHeight(), valSetID) - } + // this validator set is effective as of the next block, so use height + 1. + // this statement is true for genesis as well, since ctx.BlockHeight() is + // reported as 0 during InitGenesis. + k.setValidatorSetID(ctx, ctx.BlockHeight()+1, valSetID) + // store this to compare against, in the next round. + k.saveKeyPowerMapping(ctx, ret) return ret } @@ -227,8 +230,8 @@ func (k Keeper) deleteValidatorSet(ctx sdk.Context, id uint64) { // event. Otherwise, it is constant. The header, however, will change at every block. Since // the Cosmos SDK does not allow for the retrieval of a past block header, we store the header // ourselves in this function. The validator set is stored when it changes at the end of an -// epoch or at a slashing event in the corresponding functions. It is called within the EndBlock -// of the module, so it is kept public. +// epoch or at a slashing event in the corresponding functions. The function is called within +// the EndBlock of the module, so it is kept public. func (k Keeper) TrackHistoricalInfo(ctx sdk.Context) { // Get the number of historical entries to persist, as the number of block heights. // #nosec G701 // uint32 fits into int64 always. @@ -253,9 +256,16 @@ func (k Keeper) TrackHistoricalInfo(ctx sdk.Context) { break } } + // even if numHistoricalEntries is 0, this will work because it is called after the + // validatorSetID for height + 1 is stored. + // on the opposite side of things, if numHistoricalEntries is too large, currentID + // will be 0, and the loop will not run. currentID, _ := k.getValidatorSetID(ctx, ctx.BlockHeight()-numHistoricalEntries+1, ) + // lastDeletedID will be the lowest deleted id since we are working backwards + // from the latest height to the oldest height. this, and upto but not including + // currentID, are the ids to delete. for i := lastDeletedID; i < currentID; i++ { k.deleteValidatorSet(ctx, i) } @@ -269,7 +279,7 @@ func (k Keeper) TrackHistoricalInfo(ctx sdk.Context) { k.storeBlockHeader(ctx) // we have stored: - // before TrackHistoricalInfo: ValidatorSetID for height, and the validator set. + // outside of TrackHistoricalInfo: ValidatorSetID for height, and the validator set. // within TrackHistoricalInfo: the header. // this is enough information to answer the GetHistoricalInfo query. } @@ -373,3 +383,27 @@ func (k Keeper) storeBlockHeader(ctx sdk.Context) { value := k.cdc.MustMarshal(&header) store.Set(key, value) } + +// saveKeyPowerMapping stores a mapping from the key string to the power. +func (k Keeper) saveKeyPowerMapping(ctx sdk.Context, updates []abci.ValidatorUpdate) { + store := ctx.KVStore(k.storeKey) + m := make(map[string]int64, len(updates)) + for _, update := range updates { + // do not use the stringer interface here so that it can be deserialized. + m[string(k.cdc.MustMarshal(&update.PubKey))] = update.Power + } + bz := k.cdc.MustMarshal(&types.KeyPowerMapping{List: m}) + store.Set(types.KeyPowerMappingKey(), bz) +} + +// getKeyPowerMapping gets the most recently stored mapping from the key string to the power. +func (k Keeper) getKeyPowerMapping(ctx sdk.Context) types.KeyPowerMapping { + store := ctx.KVStore(k.storeKey) + bz := store.Get(types.KeyPowerMappingKey()) + if bz == nil { + return types.KeyPowerMapping{} + } + var updates types.KeyPowerMapping + k.cdc.MustUnmarshal(bz, &updates) + return updates +} diff --git a/x/dogfood/module.go b/x/dogfood/module.go index 44483fd37..1f0b36e58 100644 --- a/x/dogfood/module.go +++ b/x/dogfood/module.go @@ -163,5 +163,7 @@ func (am AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) {} // EndBlock contains the logic that is automatically triggered at the end of each block func (am AppModule) EndBlock(ctx sdk.Context, _ abci.RequestEndBlock) []abci.ValidatorUpdate { - return am.keeper.EndBlock(ctx) + ret := am.keeper.EndBlock(ctx) + am.keeper.TrackHistoricalInfo(ctx) + return ret } diff --git a/x/dogfood/types/dogfood.pb.go b/x/dogfood/types/dogfood.pb.go index 876f5c4c1..d00b77801 100644 --- a/x/dogfood/types/dogfood.pb.go +++ b/x/dogfood/types/dogfood.pb.go @@ -5,7 +5,8 @@ package types import ( fmt "fmt" - crypto "github.com/cometbft/cometbft/proto/tendermint/crypto" + _ "github.com/cometbft/cometbft/abci/types" + _ "github.com/cometbft/cometbft/proto/tendermint/crypto" _ "github.com/cosmos/cosmos-proto" types "github.com/cosmos/cosmos-sdk/codec/types" types1 "github.com/cosmos/cosmos-sdk/x/staking/types" @@ -31,79 +32,6 @@ var _ = time.Kitchen // proto package needs to be updated. const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package -// OperationType is used to indicate the type of operation that is being -// cached by the module to create the updated validator set. -type OperationType int32 - -const ( - // KeyOpUnspecified is used to indicate that the operation type is not specified. - // This should never be used. - KeyOpUnspecified OperationType = 0 - // KeyAddition is used to indicate that the operation is a key addition. - KeyAdditionOrUpdate OperationType = 1 - // KeyRemoval is used to indicate that the operation is a key removal. Typically - // this is done due to key replacement mechanism and not directly. - KeyRemoval OperationType = 2 -) - -var OperationType_name = map[int32]string{ - 0: "OPERATION_TYPE_UNSPECIFIED", - 1: "OPERATION_TYPE_ADDITION_OR_UPDATE", - 2: "OPERATION_TYPE_REMOVAL", -} - -var OperationType_value = map[string]int32{ - "OPERATION_TYPE_UNSPECIFIED": 0, - "OPERATION_TYPE_ADDITION_OR_UPDATE": 1, - "OPERATION_TYPE_REMOVAL": 2, -} - -func (x OperationType) String() string { - return proto.EnumName(OperationType_name, int32(x)) -} - -func (OperationType) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_071b9989c501c3f2, []int{0} -} - -// QueueResultType is used to indicate the result of the queue operation. -type QueueResultType int32 - -const ( - // QueueResultUnspecified is used to indicate that the queue result type is not specified. - QueueResultUnspecified QueueResultType = 0 - // QueueResultSuccess is used to indicate that the queue operation was successful. - QueueResultSuccess QueueResultType = 1 - // QueueResultExists is used to indicate that the queue operation failed because the - // operation already exists in the queue. - QueueResultExists QueueResultType = 2 - // QueueResultRemoved is used to indicate that the queue operation resulted in an existing - // operation being removed from the queue. - QueueResultRemoved QueueResultType = 3 -) - -var QueueResultType_name = map[int32]string{ - 0: "QUEUE_RESULT_TYPE_UNSPECIFIED", - 1: "QUEUE_RESULT_TYPE_SUCCESS", - 2: "QUEUE_RESULT_TYPE_EXISTS", - 3: "QUEUE_RESULT_TYPE_REMOVED", -} - -var QueueResultType_value = map[string]int32{ - "QUEUE_RESULT_TYPE_UNSPECIFIED": 0, - "QUEUE_RESULT_TYPE_SUCCESS": 1, - "QUEUE_RESULT_TYPE_EXISTS": 2, - "QUEUE_RESULT_TYPE_REMOVED": 3, -} - -func (x QueueResultType) String() string { - return proto.EnumName(QueueResultType_name, int32(x)) -} - -func (QueueResultType) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_071b9989c501c3f2, []int{1} -} - // ExocoreValidator is a validator that is part of the Exocore network. It is // used to validate and sign blocks and transactions. type ExocoreValidator struct { @@ -170,117 +98,6 @@ func (m *ExocoreValidator) GetPubkey() *types.Any { return nil } -// Operation is used to indicate the operation that is being cached by the module -// to create the updated validator set. -type Operation struct { - // OperationType is the type of the operation (addition / removal). - OperationType OperationType `protobuf:"varint,1,opt,name=operation_type,json=operationType,proto3,enum=exocore.dogfood.v1.OperationType" json:"operation_type,omitempty"` - // OperatorAddress is the sdk.AccAddress of the operator. - OperatorAddress []byte `protobuf:"bytes,2,opt,name=operator_address,json=operatorAddress,proto3" json:"operator_address,omitempty"` - // PubKey is the public key for which the operation is being applied. - PubKey crypto.PublicKey `protobuf:"bytes,3,opt,name=pub_key,json=pubKey,proto3" json:"pub_key"` -} - -func (m *Operation) Reset() { *m = Operation{} } -func (m *Operation) String() string { return proto.CompactTextString(m) } -func (*Operation) ProtoMessage() {} -func (*Operation) Descriptor() ([]byte, []int) { - return fileDescriptor_071b9989c501c3f2, []int{1} -} -func (m *Operation) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *Operation) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_Operation.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 *Operation) XXX_Merge(src proto.Message) { - xxx_messageInfo_Operation.Merge(m, src) -} -func (m *Operation) XXX_Size() int { - return m.Size() -} -func (m *Operation) XXX_DiscardUnknown() { - xxx_messageInfo_Operation.DiscardUnknown(m) -} - -var xxx_messageInfo_Operation proto.InternalMessageInfo - -func (m *Operation) GetOperationType() OperationType { - if m != nil { - return m.OperationType - } - return KeyOpUnspecified -} - -func (m *Operation) GetOperatorAddress() []byte { - if m != nil { - return m.OperatorAddress - } - return nil -} - -func (m *Operation) GetPubKey() crypto.PublicKey { - if m != nil { - return m.PubKey - } - return crypto.PublicKey{} -} - -// Operations is a collection of Operation. -type Operations struct { - // list is the list of operations. - List []Operation `protobuf:"bytes,1,rep,name=list,proto3" json:"list"` -} - -func (m *Operations) Reset() { *m = Operations{} } -func (m *Operations) String() string { return proto.CompactTextString(m) } -func (*Operations) ProtoMessage() {} -func (*Operations) Descriptor() ([]byte, []int) { - return fileDescriptor_071b9989c501c3f2, []int{2} -} -func (m *Operations) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *Operations) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_Operations.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 *Operations) XXX_Merge(src proto.Message) { - xxx_messageInfo_Operations.Merge(m, src) -} -func (m *Operations) XXX_Size() int { - return m.Size() -} -func (m *Operations) XXX_DiscardUnknown() { - xxx_messageInfo_Operations.DiscardUnknown(m) -} - -var xxx_messageInfo_Operations proto.InternalMessageInfo - -func (m *Operations) GetList() []Operation { - if m != nil { - return m.List - } - return nil -} - // AccountAddresses represents a list of account addresses. It is used to store the list of // operator addresses whose operations are maturing at an epoch. type AccountAddresses struct { @@ -292,7 +109,7 @@ func (m *AccountAddresses) Reset() { *m = AccountAddresses{} } func (m *AccountAddresses) String() string { return proto.CompactTextString(m) } func (*AccountAddresses) ProtoMessage() {} func (*AccountAddresses) Descriptor() ([]byte, []int) { - return fileDescriptor_071b9989c501c3f2, []int{3} + return fileDescriptor_071b9989c501c3f2, []int{1} } func (m *AccountAddresses) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -339,7 +156,7 @@ func (m *ConsensusAddresses) Reset() { *m = ConsensusAddresses{} } func (m *ConsensusAddresses) String() string { return proto.CompactTextString(m) } func (*ConsensusAddresses) ProtoMessage() {} func (*ConsensusAddresses) Descriptor() ([]byte, []int) { - return fileDescriptor_071b9989c501c3f2, []int{4} + return fileDescriptor_071b9989c501c3f2, []int{2} } func (m *ConsensusAddresses) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -386,7 +203,7 @@ func (m *UndelegationRecordKeys) Reset() { *m = UndelegationRecordKeys{} func (m *UndelegationRecordKeys) String() string { return proto.CompactTextString(m) } func (*UndelegationRecordKeys) ProtoMessage() {} func (*UndelegationRecordKeys) Descriptor() ([]byte, []int) { - return fileDescriptor_071b9989c501c3f2, []int{5} + return fileDescriptor_071b9989c501c3f2, []int{3} } func (m *UndelegationRecordKeys) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -432,7 +249,7 @@ func (m *Validators) Reset() { *m = Validators{} } func (m *Validators) String() string { return proto.CompactTextString(m) } func (*Validators) ProtoMessage() {} func (*Validators) Descriptor() ([]byte, []int) { - return fileDescriptor_071b9989c501c3f2, []int{6} + return fileDescriptor_071b9989c501c3f2, []int{4} } func (m *Validators) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -484,7 +301,7 @@ func (m *HeaderSubset) Reset() { *m = HeaderSubset{} } func (m *HeaderSubset) String() string { return proto.CompactTextString(m) } func (*HeaderSubset) ProtoMessage() {} func (*HeaderSubset) Descriptor() ([]byte, []int) { - return fileDescriptor_071b9989c501c3f2, []int{7} + return fileDescriptor_071b9989c501c3f2, []int{5} } func (m *HeaderSubset) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -534,77 +351,106 @@ func (m *HeaderSubset) GetAppHash() []byte { return nil } +// KeyPowerMapping is a mapping of the consensus public key (as a string) +// to the power of the key. +type KeyPowerMapping struct { + // list is the actual mapping of the consensus public key to the power. + List map[string]int64 `protobuf:"bytes,1,rep,name=list,proto3" json:"list,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"` +} + +func (m *KeyPowerMapping) Reset() { *m = KeyPowerMapping{} } +func (m *KeyPowerMapping) String() string { return proto.CompactTextString(m) } +func (*KeyPowerMapping) ProtoMessage() {} +func (*KeyPowerMapping) Descriptor() ([]byte, []int) { + return fileDescriptor_071b9989c501c3f2, []int{6} +} +func (m *KeyPowerMapping) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *KeyPowerMapping) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_KeyPowerMapping.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 *KeyPowerMapping) XXX_Merge(src proto.Message) { + xxx_messageInfo_KeyPowerMapping.Merge(m, src) +} +func (m *KeyPowerMapping) XXX_Size() int { + return m.Size() +} +func (m *KeyPowerMapping) XXX_DiscardUnknown() { + xxx_messageInfo_KeyPowerMapping.DiscardUnknown(m) +} + +var xxx_messageInfo_KeyPowerMapping proto.InternalMessageInfo + +func (m *KeyPowerMapping) GetList() map[string]int64 { + if m != nil { + return m.List + } + return nil +} + func init() { - proto.RegisterEnum("exocore.dogfood.v1.OperationType", OperationType_name, OperationType_value) - proto.RegisterEnum("exocore.dogfood.v1.QueueResultType", QueueResultType_name, QueueResultType_value) proto.RegisterType((*ExocoreValidator)(nil), "exocore.dogfood.v1.ExocoreValidator") - proto.RegisterType((*Operation)(nil), "exocore.dogfood.v1.Operation") - proto.RegisterType((*Operations)(nil), "exocore.dogfood.v1.Operations") proto.RegisterType((*AccountAddresses)(nil), "exocore.dogfood.v1.AccountAddresses") proto.RegisterType((*ConsensusAddresses)(nil), "exocore.dogfood.v1.ConsensusAddresses") proto.RegisterType((*UndelegationRecordKeys)(nil), "exocore.dogfood.v1.UndelegationRecordKeys") proto.RegisterType((*Validators)(nil), "exocore.dogfood.v1.Validators") proto.RegisterType((*HeaderSubset)(nil), "exocore.dogfood.v1.HeaderSubset") + proto.RegisterType((*KeyPowerMapping)(nil), "exocore.dogfood.v1.KeyPowerMapping") + proto.RegisterMapType((map[string]int64)(nil), "exocore.dogfood.v1.KeyPowerMapping.ListEntry") } func init() { proto.RegisterFile("exocore/dogfood/v1/dogfood.proto", fileDescriptor_071b9989c501c3f2) } var fileDescriptor_071b9989c501c3f2 = []byte{ - // 857 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x54, 0x41, 0x6f, 0xe3, 0x44, - 0x14, 0x8e, 0x9b, 0xb2, 0xbb, 0x4c, 0xbb, 0x5d, 0x33, 0x84, 0x6e, 0x6a, 0xed, 0xa6, 0x6e, 0x84, - 0x50, 0xa8, 0xc0, 0x26, 0x2d, 0x08, 0x04, 0x02, 0x29, 0x6d, 0x8c, 0x1a, 0x65, 0x69, 0xb2, 0x76, - 0xbc, 0x02, 0x2e, 0x96, 0x63, 0xbf, 0xa6, 0x56, 0x13, 0x8f, 0xe5, 0x19, 0x67, 0xeb, 0x7f, 0x80, - 0x72, 0xda, 0x0b, 0xc7, 0x9c, 0x10, 0xff, 0x00, 0x89, 0x13, 0xf7, 0x15, 0xa7, 0x3d, 0x72, 0x5a, - 0x50, 0xfb, 0x0f, 0xb8, 0x71, 0x43, 0xb6, 0xc7, 0xa9, 0xb7, 0xa9, 0x7a, 0x9b, 0x37, 0xef, 0x7d, - 0xf3, 0xbe, 0x6f, 0xe6, 0x9b, 0x87, 0x64, 0x38, 0x27, 0x0e, 0x09, 0x41, 0x75, 0xc9, 0xe8, 0x84, - 0x10, 0x57, 0x9d, 0x36, 0xf3, 0xa5, 0x12, 0x84, 0x84, 0x11, 0x8c, 0x79, 0x85, 0x92, 0x6f, 0x4f, - 0x9b, 0x52, 0x65, 0x44, 0x46, 0x24, 0x4d, 0xab, 0xc9, 0x2a, 0xab, 0x94, 0xb6, 0x46, 0x84, 0x8c, - 0xc6, 0xa0, 0xa6, 0xd1, 0x30, 0x3a, 0x51, 0x6d, 0x3f, 0xe6, 0xa9, 0xed, 0xeb, 0x29, 0xe6, 0x4d, - 0x80, 0x32, 0x7b, 0x12, 0xf0, 0x82, 0xf7, 0x1d, 0x42, 0x27, 0x84, 0xaa, 0x94, 0xd9, 0x67, 0x9e, - 0x3f, 0x52, 0xa7, 0xcd, 0x21, 0x30, 0xbb, 0x99, 0xc7, 0x79, 0x87, 0xac, 0xca, 0xca, 0x5a, 0x67, - 0x01, 0x4f, 0x3d, 0x62, 0xe0, 0xbb, 0x10, 0x4e, 0x3c, 0x9f, 0xa9, 0x4e, 0x18, 0x07, 0x8c, 0xa8, - 0x67, 0x10, 0xf3, 0x6c, 0xfd, 0x57, 0x01, 0x89, 0x5a, 0xa6, 0xe3, 0x99, 0x3d, 0xf6, 0x5c, 0x9b, - 0x91, 0x10, 0x57, 0xd1, 0x5d, 0xdb, 0x75, 0x43, 0xa0, 0xb4, 0x2a, 0xc8, 0x42, 0x63, 0x5d, 0xcf, - 0x43, 0x5c, 0x41, 0x6f, 0x05, 0xe4, 0x39, 0x84, 0xd5, 0x15, 0x59, 0x68, 0x94, 0xf5, 0x2c, 0xc0, - 0x36, 0xba, 0x13, 0x44, 0xc3, 0x33, 0x88, 0xab, 0x65, 0x59, 0x68, 0xac, 0xed, 0x55, 0x94, 0x4c, - 0x95, 0x92, 0xab, 0x52, 0x5a, 0x7e, 0x7c, 0xb0, 0xff, 0xef, 0xeb, 0xed, 0x87, 0xb1, 0x3d, 0x19, - 0x7f, 0x59, 0x77, 0x88, 0x4f, 0xc1, 0xa7, 0x11, 0xb5, 0x32, 0x5c, 0xfd, 0xcf, 0xdf, 0x3e, 0xae, - 0x70, 0xd6, 0x19, 0x47, 0xa5, 0x1f, 0x0d, 0xbb, 0x10, 0xeb, 0xfc, 0xe0, 0xfa, 0x1f, 0x02, 0x7a, - 0xbb, 0x17, 0x40, 0x68, 0x33, 0x8f, 0xf8, 0xf8, 0x08, 0x6d, 0x90, 0x3c, 0xb0, 0x58, 0x1c, 0x40, - 0xca, 0x73, 0x63, 0x6f, 0x47, 0x59, 0x7e, 0x13, 0x65, 0x01, 0x1b, 0xc4, 0x01, 0xe8, 0xf7, 0x49, - 0x31, 0xc4, 0x1f, 0x22, 0x31, 0xdb, 0x20, 0xa1, 0x95, 0x6b, 0x5e, 0x49, 0x35, 0x3f, 0xc8, 0xf7, - 0x5b, 0x5c, 0xfb, 0x57, 0xe8, 0x6e, 0x10, 0x0d, 0xad, 0x2b, 0x99, 0x8f, 0x94, 0xab, 0xab, 0x2d, - 0xd0, 0x1e, 0x7b, 0x4e, 0x17, 0xe2, 0x83, 0xd5, 0x97, 0xaf, 0xb7, 0x4b, 0x29, 0xff, 0x2e, 0xc4, - 0x75, 0x0d, 0xa1, 0x05, 0x0f, 0x8a, 0x3f, 0x47, 0xab, 0x63, 0x8f, 0xb2, 0xaa, 0x20, 0x97, 0x1b, - 0x6b, 0x7b, 0x8f, 0x6f, 0x65, 0xcd, 0x0f, 0x4a, 0x01, 0xf5, 0x0f, 0x90, 0xd8, 0x72, 0x1c, 0x12, - 0xf9, 0x8c, 0xb3, 0x02, 0x8a, 0x71, 0xe1, 0xb0, 0x75, 0x5e, 0xd7, 0x40, 0xf8, 0x30, 0xbf, 0xe3, - 0xdb, 0x2b, 0x3f, 0x42, 0x9b, 0xa6, 0xef, 0xc2, 0x18, 0x46, 0x69, 0x37, 0x1d, 0x1c, 0x12, 0xba, - 0x5d, 0x88, 0x6f, 0xae, 0xee, 0x20, 0xb4, 0xb0, 0x49, 0x72, 0x23, 0x45, 0x19, 0x3b, 0x0a, 0x7f, - 0xc1, 0xdc, 0x9a, 0xdc, 0xaa, 0xca, 0x02, 0xf1, 0x86, 0x94, 0x9f, 0x05, 0xb4, 0x7e, 0x04, 0xb6, - 0x0b, 0xa1, 0x11, 0x0d, 0x29, 0x30, 0xfc, 0x05, 0x5a, 0x4d, 0xcc, 0x9f, 0x3e, 0xe5, 0xda, 0x9e, - 0xb4, 0xe4, 0xa1, 0x41, 0xfe, 0x33, 0x0e, 0xee, 0x25, 0xc7, 0xbc, 0xf8, 0x7b, 0x5b, 0xd0, 0x53, - 0x04, 0xfe, 0x04, 0x55, 0x7c, 0x38, 0x67, 0xd6, 0x74, 0x41, 0xcd, 0x3a, 0xb5, 0xe9, 0x29, 0x7f, - 0x48, 0x9c, 0xe4, 0xae, 0x58, 0x1f, 0xd9, 0xf4, 0x14, 0x6f, 0xa1, 0x7b, 0x76, 0x10, 0x64, 0x55, - 0x65, 0x6e, 0xf1, 0x20, 0x48, 0x52, 0xbb, 0xbf, 0x0b, 0xe8, 0xfe, 0x1b, 0x96, 0xc1, 0x9f, 0x22, - 0xa9, 0xd7, 0xd7, 0xf4, 0xd6, 0xa0, 0xd3, 0x3b, 0xb6, 0x06, 0x3f, 0xf4, 0x35, 0xcb, 0x3c, 0x36, - 0xfa, 0xda, 0x61, 0xe7, 0xdb, 0x8e, 0xd6, 0x16, 0x4b, 0x52, 0x65, 0x36, 0x97, 0xc5, 0x2e, 0xc4, - 0xbd, 0xc0, 0xf4, 0x69, 0x00, 0x8e, 0x77, 0xe2, 0x81, 0x8b, 0xbf, 0x41, 0x3b, 0xd7, 0x50, 0xad, - 0x76, 0xbb, 0x93, 0x46, 0x3d, 0xdd, 0x32, 0xfb, 0xed, 0xd6, 0x40, 0x13, 0x05, 0xe9, 0xe1, 0x6c, - 0x2e, 0xbf, 0xdb, 0x85, 0xb8, 0xe5, 0xba, 0x5e, 0xd2, 0xb1, 0x17, 0x9a, 0x81, 0x6b, 0x33, 0xc0, - 0xbb, 0x68, 0xf3, 0x1a, 0x5e, 0xd7, 0xbe, 0xeb, 0x3d, 0x6b, 0x3d, 0x11, 0x57, 0xa4, 0x8d, 0xd9, - 0x5c, 0x46, 0xc9, 0xf7, 0x80, 0x09, 0x99, 0xda, 0x63, 0x69, 0xf5, 0xa7, 0x5f, 0x6a, 0xa5, 0xdd, - 0xff, 0x04, 0xf4, 0xe0, 0x69, 0x04, 0x11, 0xe8, 0x40, 0xa3, 0x31, 0x4b, 0xb9, 0x7f, 0x8d, 0x1e, - 0x3f, 0x35, 0x35, 0x33, 0x01, 0x1b, 0xe6, 0x93, 0xc1, 0x4d, 0xf4, 0xa5, 0xd9, 0x5c, 0xde, 0x2c, - 0xe0, 0x8a, 0x22, 0x3e, 0x43, 0x5b, 0xcb, 0x70, 0xc3, 0x3c, 0x3c, 0xd4, 0x0c, 0x43, 0x14, 0xa4, - 0xcd, 0xd9, 0x5c, 0xc6, 0x05, 0xa8, 0x11, 0x39, 0x4e, 0xf2, 0x55, 0xf6, 0x51, 0x75, 0x19, 0xa6, - 0x7d, 0xdf, 0x31, 0x06, 0x86, 0xb8, 0x22, 0xbd, 0x37, 0x9b, 0xcb, 0xef, 0x14, 0x50, 0xda, 0xb9, - 0x47, 0x19, 0xbd, 0xb9, 0x57, 0xaa, 0x59, 0x6b, 0x8b, 0xe5, 0xa5, 0x5e, 0xa9, 0x76, 0x70, 0x33, - 0xed, 0x07, 0xdd, 0x97, 0x17, 0x35, 0xe1, 0xd5, 0x45, 0x4d, 0xf8, 0xe7, 0xa2, 0x26, 0xbc, 0xb8, - 0xac, 0x95, 0x5e, 0x5d, 0xd6, 0x4a, 0x7f, 0x5d, 0xd6, 0x4a, 0x3f, 0x36, 0x47, 0x1e, 0x3b, 0x8d, - 0x86, 0x8a, 0x43, 0x26, 0x2a, 0x9f, 0x74, 0xc7, 0xc0, 0x9e, 0x93, 0xf0, 0x4c, 0xcd, 0x47, 0xfc, - 0xf9, 0x62, 0xc8, 0x27, 0xb3, 0x84, 0x0e, 0xef, 0xa4, 0x9e, 0xdb, 0xff, 0x3f, 0x00, 0x00, 0xff, - 0xff, 0x99, 0xab, 0xaa, 0x75, 0x04, 0x06, 0x00, 0x00, + // 598 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x53, 0xcd, 0x6e, 0x13, 0x31, + 0x10, 0x8e, 0x9b, 0x52, 0x5a, 0x37, 0x12, 0x95, 0x15, 0x41, 0x1a, 0x50, 0x12, 0x22, 0x84, 0x72, + 0xa0, 0xbb, 0xa4, 0x3d, 0x50, 0x95, 0x53, 0x82, 0x2a, 0x15, 0x05, 0x50, 0xb5, 0xfc, 0x1c, 0xb8, + 0x44, 0xde, 0xdd, 0xe9, 0x66, 0x95, 0xc4, 0xb6, 0xd6, 0xde, 0xb4, 0xfb, 0x10, 0x48, 0xbd, 0xf0, + 0x08, 0xbc, 0x01, 0x0f, 0x51, 0x71, 0xea, 0x91, 0x53, 0x41, 0xcd, 0x1b, 0xf0, 0x04, 0x68, 0xd7, + 0x76, 0x28, 0x2d, 0xe2, 0x36, 0xe3, 0xef, 0x9b, 0xf1, 0x7c, 0xf3, 0x83, 0x5b, 0x70, 0xc2, 0x03, + 0x9e, 0x80, 0x1b, 0xf2, 0xe8, 0x88, 0xf3, 0xd0, 0x9d, 0x75, 0xad, 0xe9, 0x88, 0x84, 0x2b, 0x4e, + 0x88, 0x61, 0x38, 0xf6, 0x79, 0xd6, 0xad, 0x57, 0x23, 0x1e, 0xf1, 0x02, 0x76, 0x73, 0x4b, 0x33, + 0xeb, 0x9b, 0x11, 0xe7, 0xd1, 0x04, 0xdc, 0xc2, 0xf3, 0xd3, 0x23, 0x97, 0xb2, 0xcc, 0x40, 0xcd, + 0xeb, 0x90, 0x8a, 0xa7, 0x20, 0x15, 0x9d, 0x0a, 0x43, 0x78, 0x14, 0x70, 0x39, 0xe5, 0xd2, 0x95, + 0x8a, 0x8e, 0x63, 0x16, 0xb9, 0xb3, 0xae, 0x0f, 0x8a, 0x76, 0xad, 0x6f, 0x7f, 0xd0, 0xac, 0xa1, + 0xfe, 0x5a, 0x3b, 0x06, 0xba, 0xaf, 0x80, 0x85, 0x90, 0x4c, 0x63, 0xa6, 0x5c, 0xea, 0x07, 0xb1, + 0xab, 0x32, 0x01, 0x16, 0x7c, 0x70, 0x05, 0x0c, 0x92, 0x4c, 0x28, 0xee, 0x8e, 0x21, 0x33, 0x68, + 0xfb, 0x0b, 0xc2, 0x1b, 0xfb, 0x5a, 0xe4, 0x07, 0x3a, 0x89, 0x43, 0xaa, 0x78, 0x42, 0x6a, 0xf8, + 0x36, 0x0d, 0xc3, 0x04, 0xa4, 0xac, 0xa1, 0x16, 0xea, 0x54, 0x3c, 0xeb, 0x92, 0x2a, 0xbe, 0x25, + 0xf8, 0x31, 0x24, 0xb5, 0xa5, 0x16, 0xea, 0x94, 0x3d, 0xed, 0x10, 0x8a, 0x57, 0x44, 0xea, 0x8f, + 0x21, 0xab, 0x95, 0x5b, 0xa8, 0xb3, 0xbe, 0x5d, 0x75, 0xb4, 0x64, 0xc7, 0x4a, 0x76, 0x7a, 0x2c, + 0xeb, 0xef, 0xfc, 0xba, 0x68, 0xde, 0xcb, 0xe8, 0x74, 0xb2, 0xd7, 0x0e, 0x38, 0x93, 0xc0, 0x64, + 0x2a, 0x87, 0x3a, 0xae, 0xfd, 0xed, 0xeb, 0x56, 0xd5, 0x48, 0xd2, 0x35, 0x3a, 0x87, 0xa9, 0x3f, + 0x80, 0xcc, 0x33, 0x89, 0xdb, 0x8f, 0xf1, 0x46, 0x2f, 0x08, 0x78, 0xca, 0x54, 0x4f, 0x97, 0x02, + 0x92, 0x10, 0xbc, 0x3c, 0x89, 0xa5, 0xaa, 0xa1, 0x56, 0xb9, 0x53, 0xf1, 0x0a, 0xbb, 0xdd, 0xc1, + 0xe4, 0x85, 0x4d, 0xfe, 0x7f, 0xe6, 0x13, 0x7c, 0xf7, 0x3d, 0x0b, 0x61, 0x02, 0x11, 0x55, 0x31, + 0x67, 0x1e, 0x04, 0x3c, 0x09, 0x07, 0x90, 0xfd, 0x9b, 0xfd, 0x12, 0xe3, 0x45, 0x7f, 0x24, 0x79, + 0x7e, 0x85, 0xb1, 0xbe, 0xfd, 0xd0, 0x31, 0xa5, 0xdb, 0x81, 0x99, 0x01, 0x3a, 0x8b, 0x88, 0xfe, + 0xf2, 0xd9, 0x45, 0xb3, 0x64, 0x52, 0x7d, 0x46, 0xb8, 0x72, 0x00, 0x34, 0x84, 0xe4, 0x6d, 0xea, + 0x4b, 0x50, 0x64, 0x17, 0x2f, 0xe7, 0x2b, 0x51, 0xf4, 0x7a, 0x7d, 0xbb, 0x7e, 0xa3, 0x79, 0xef, + 0xec, 0xbe, 0xf4, 0x57, 0xf3, 0x34, 0xa7, 0x3f, 0x9a, 0xc8, 0x2b, 0x22, 0xc8, 0x53, 0x5c, 0x65, + 0x70, 0xa2, 0x86, 0xb3, 0x45, 0x69, 0xc3, 0x11, 0x95, 0xa3, 0x62, 0x3a, 0x15, 0x8f, 0xe4, 0xd8, + 0x9f, 0xaa, 0x0f, 0xa8, 0x1c, 0x91, 0x4d, 0xbc, 0x4a, 0x85, 0xd0, 0xac, 0xb2, 0x99, 0xad, 0x10, + 0x39, 0xd4, 0xfe, 0x84, 0xf0, 0x9d, 0x01, 0x64, 0x87, 0xf9, 0x48, 0x5f, 0x53, 0x21, 0x62, 0x16, + 0x91, 0xde, 0x5f, 0x42, 0xb7, 0x9c, 0x9b, 0xf7, 0xe0, 0x5c, 0x0b, 0x71, 0x5e, 0xc5, 0x52, 0xed, + 0x33, 0x95, 0x64, 0x5a, 0x6e, 0xfd, 0x19, 0x5e, 0x5b, 0x3c, 0x91, 0x0d, 0x5c, 0xce, 0xd7, 0x24, + 0x57, 0xba, 0xe6, 0xe5, 0x66, 0xbe, 0x51, 0x33, 0x3a, 0x49, 0xc1, 0x6e, 0x54, 0xe1, 0xec, 0x2d, + 0xed, 0xa2, 0xfe, 0xe0, 0xec, 0xb2, 0x81, 0xce, 0x2f, 0x1b, 0xe8, 0xe7, 0x65, 0x03, 0x9d, 0xce, + 0x1b, 0xa5, 0xf3, 0x79, 0xa3, 0xf4, 0x7d, 0xde, 0x28, 0x7d, 0xec, 0x46, 0xb1, 0x1a, 0xa5, 0xbe, + 0x13, 0xf0, 0xa9, 0x6b, 0x96, 0xf7, 0x0d, 0xa8, 0x63, 0x9e, 0x8c, 0x5d, 0x7b, 0xd2, 0x27, 0x8b, + 0xa3, 0x2e, 0x6e, 0xc1, 0x5f, 0x29, 0xba, 0xb9, 0xf3, 0x3b, 0x00, 0x00, 0xff, 0xff, 0xf5, 0x4e, + 0xb2, 0x58, 0xf4, 0x03, 0x00, 0x00, } func (m *ExocoreValidator) Marshal() (dAtA []byte, err error) { @@ -654,88 +500,6 @@ func (m *ExocoreValidator) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } -func (m *Operation) 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 *Operation) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *Operation) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - { - size, err := m.PubKey.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintDogfood(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x1a - if len(m.OperatorAddress) > 0 { - i -= len(m.OperatorAddress) - copy(dAtA[i:], m.OperatorAddress) - i = encodeVarintDogfood(dAtA, i, uint64(len(m.OperatorAddress))) - i-- - dAtA[i] = 0x12 - } - if m.OperationType != 0 { - i = encodeVarintDogfood(dAtA, i, uint64(m.OperationType)) - i-- - dAtA[i] = 0x8 - } - return len(dAtA) - i, nil -} - -func (m *Operations) 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 *Operations) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *Operations) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.List) > 0 { - for iNdEx := len(m.List) - 1; iNdEx >= 0; iNdEx-- { - { - size, err := m.List[iNdEx].MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintDogfood(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0xa - } - } - return len(dAtA) - i, nil -} - func (m *AccountAddresses) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -903,17 +667,57 @@ func (m *HeaderSubset) MarshalToSizedBuffer(dAtA []byte) (int, error) { i-- dAtA[i] = 0x12 } - n3, err3 := github_com_cosmos_gogoproto_types.StdTimeMarshalTo(m.Time, dAtA[i-github_com_cosmos_gogoproto_types.SizeOfStdTime(m.Time):]) - if err3 != nil { - return 0, err3 + n2, err2 := github_com_cosmos_gogoproto_types.StdTimeMarshalTo(m.Time, dAtA[i-github_com_cosmos_gogoproto_types.SizeOfStdTime(m.Time):]) + if err2 != nil { + return 0, err2 } - i -= n3 - i = encodeVarintDogfood(dAtA, i, uint64(n3)) + i -= n2 + i = encodeVarintDogfood(dAtA, i, uint64(n2)) i-- dAtA[i] = 0xa return len(dAtA) - i, nil } +func (m *KeyPowerMapping) 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 *KeyPowerMapping) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *KeyPowerMapping) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.List) > 0 { + for k := range m.List { + v := m.List[k] + baseI := i + i = encodeVarintDogfood(dAtA, i, uint64(v)) + i-- + dAtA[i] = 0x10 + i -= len(k) + copy(dAtA[i:], k) + i = encodeVarintDogfood(dAtA, i, uint64(len(k))) + i-- + dAtA[i] = 0xa + i = encodeVarintDogfood(dAtA, i, uint64(baseI-i)) + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + func encodeVarintDogfood(dAtA []byte, offset int, v uint64) int { offset -= sovDogfood(v) base := offset @@ -945,39 +749,6 @@ func (m *ExocoreValidator) Size() (n int) { return n } -func (m *Operation) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if m.OperationType != 0 { - n += 1 + sovDogfood(uint64(m.OperationType)) - } - l = len(m.OperatorAddress) - if l > 0 { - n += 1 + l + sovDogfood(uint64(l)) - } - l = m.PubKey.Size() - n += 1 + l + sovDogfood(uint64(l)) - return n -} - -func (m *Operations) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if len(m.List) > 0 { - for _, e := range m.List { - l = e.Size() - n += 1 + l + sovDogfood(uint64(l)) - } - } - return n -} - func (m *AccountAddresses) Size() (n int) { if m == nil { return 0 @@ -1057,6 +828,23 @@ func (m *HeaderSubset) Size() (n int) { return n } +func (m *KeyPowerMapping) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.List) > 0 { + for k, v := range m.List { + _ = k + _ = v + mapEntrySize := 1 + len(k) + sovDogfood(uint64(len(k))) + 1 + sovDogfood(uint64(v)) + n += mapEntrySize + 1 + sovDogfood(uint64(mapEntrySize)) + } + } + return n +} + func sovDogfood(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -1202,7 +990,7 @@ func (m *ExocoreValidator) Unmarshal(dAtA []byte) error { } return nil } -func (m *Operation) Unmarshal(dAtA []byte) error { +func (m *AccountAddresses) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -1225,34 +1013,15 @@ func (m *Operation) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: Operation: wiretype end group for non-group") + return fmt.Errorf("proto: AccountAddresses: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: Operation: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: AccountAddresses: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field OperationType", wireType) - } - m.OperationType = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowDogfood - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.OperationType |= OperationType(b&0x7F) << shift - if b < 0x80 { - break - } - } - case 2: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field OperatorAddress", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field List", wireType) } var byteLen int for shift := uint(0); ; shift += 7 { @@ -1279,43 +1048,8 @@ func (m *Operation) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.OperatorAddress = append(m.OperatorAddress[:0], dAtA[iNdEx:postIndex]...) - if m.OperatorAddress == nil { - m.OperatorAddress = []byte{} - } - iNdEx = postIndex - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field PubKey", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowDogfood - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthDogfood - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthDogfood - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if err := m.PubKey.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } + m.List = append(m.List, make([]byte, postIndex-iNdEx)) + copy(m.List[len(m.List)-1], dAtA[iNdEx:postIndex]) iNdEx = postIndex default: iNdEx = preIndex @@ -1338,7 +1072,7 @@ func (m *Operation) Unmarshal(dAtA []byte) error { } return nil } -func (m *Operations) Unmarshal(dAtA []byte) error { +func (m *ConsensusAddresses) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -1361,17 +1095,17 @@ func (m *Operations) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: Operations: wiretype end group for non-group") + return fmt.Errorf("proto: ConsensusAddresses: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: Operations: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: ConsensusAddresses: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field List", wireType) } - var msglen int + var byteLen int for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowDogfood @@ -1381,25 +1115,23 @@ func (m *Operations) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - msglen |= int(b&0x7F) << shift + byteLen |= int(b&0x7F) << shift if b < 0x80 { break } } - if msglen < 0 { + if byteLen < 0 { return ErrInvalidLengthDogfood } - postIndex := iNdEx + msglen + postIndex := iNdEx + byteLen if postIndex < 0 { return ErrInvalidLengthDogfood } if postIndex > l { return io.ErrUnexpectedEOF } - m.List = append(m.List, Operation{}) - if err := m.List[len(m.List)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } + m.List = append(m.List, make([]byte, postIndex-iNdEx)) + copy(m.List[len(m.List)-1], dAtA[iNdEx:postIndex]) iNdEx = postIndex default: iNdEx = preIndex @@ -1422,7 +1154,7 @@ func (m *Operations) Unmarshal(dAtA []byte) error { } return nil } -func (m *AccountAddresses) Unmarshal(dAtA []byte) error { +func (m *UndelegationRecordKeys) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -1445,10 +1177,10 @@ func (m *AccountAddresses) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: AccountAddresses: wiretype end group for non-group") + return fmt.Errorf("proto: UndelegationRecordKeys: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: AccountAddresses: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: UndelegationRecordKeys: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -1504,7 +1236,7 @@ func (m *AccountAddresses) Unmarshal(dAtA []byte) error { } return nil } -func (m *ConsensusAddresses) Unmarshal(dAtA []byte) error { +func (m *Validators) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -1527,17 +1259,17 @@ func (m *ConsensusAddresses) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: ConsensusAddresses: wiretype end group for non-group") + return fmt.Errorf("proto: Validators: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: ConsensusAddresses: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: Validators: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field List", wireType) } - var byteLen int + var msglen int for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowDogfood @@ -1547,23 +1279,25 @@ func (m *ConsensusAddresses) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - byteLen |= int(b&0x7F) << shift + msglen |= int(b&0x7F) << shift if b < 0x80 { break } } - if byteLen < 0 { + if msglen < 0 { return ErrInvalidLengthDogfood } - postIndex := iNdEx + byteLen + postIndex := iNdEx + msglen if postIndex < 0 { return ErrInvalidLengthDogfood } if postIndex > l { return io.ErrUnexpectedEOF } - m.List = append(m.List, make([]byte, postIndex-iNdEx)) - copy(m.List[len(m.List)-1], dAtA[iNdEx:postIndex]) + m.List = append(m.List, types1.Validator{}) + if err := m.List[len(m.List)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } iNdEx = postIndex default: iNdEx = preIndex @@ -1586,7 +1320,7 @@ func (m *ConsensusAddresses) Unmarshal(dAtA []byte) error { } return nil } -func (m *UndelegationRecordKeys) Unmarshal(dAtA []byte) error { +func (m *HeaderSubset) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -1609,17 +1343,17 @@ func (m *UndelegationRecordKeys) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: UndelegationRecordKeys: wiretype end group for non-group") + return fmt.Errorf("proto: HeaderSubset: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: UndelegationRecordKeys: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: HeaderSubset: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field List", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Time", wireType) } - var byteLen int + var msglen int for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowDogfood @@ -1629,79 +1363,64 @@ func (m *UndelegationRecordKeys) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - byteLen |= int(b&0x7F) << shift + msglen |= int(b&0x7F) << shift if b < 0x80 { break } } - if byteLen < 0 { + if msglen < 0 { return ErrInvalidLengthDogfood } - postIndex := iNdEx + byteLen + postIndex := iNdEx + msglen if postIndex < 0 { return ErrInvalidLengthDogfood } if postIndex > l { return io.ErrUnexpectedEOF } - m.List = append(m.List, make([]byte, postIndex-iNdEx)) - copy(m.List[len(m.List)-1], dAtA[iNdEx:postIndex]) - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipDogfood(dAtA[iNdEx:]) - if err != nil { + if err := github_com_cosmos_gogoproto_types.StdTimeUnmarshal(&m.Time, dAtA[iNdEx:postIndex]); err != nil { return err } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthDogfood + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field NextValidatorsHash", wireType) } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowDogfood + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *Validators) 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 ErrIntOverflowDogfood + if byteLen < 0 { + return ErrInvalidLengthDogfood } - if iNdEx >= l { + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthDogfood + } + if postIndex > l { return io.ErrUnexpectedEOF } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break + m.NextValidatorsHash = append(m.NextValidatorsHash[:0], dAtA[iNdEx:postIndex]...) + if m.NextValidatorsHash == nil { + m.NextValidatorsHash = []byte{} } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: Validators: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: Validators: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: + iNdEx = postIndex + case 3: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field List", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field AppHash", wireType) } - var msglen int + var byteLen int for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowDogfood @@ -1711,24 +1430,24 @@ func (m *Validators) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - msglen |= int(b&0x7F) << shift + byteLen |= int(b&0x7F) << shift if b < 0x80 { break } } - if msglen < 0 { + if byteLen < 0 { return ErrInvalidLengthDogfood } - postIndex := iNdEx + msglen + postIndex := iNdEx + byteLen if postIndex < 0 { return ErrInvalidLengthDogfood } if postIndex > l { return io.ErrUnexpectedEOF } - m.List = append(m.List, types1.Validator{}) - if err := m.List[len(m.List)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err + m.AppHash = append(m.AppHash[:0], dAtA[iNdEx:postIndex]...) + if m.AppHash == nil { + m.AppHash = []byte{} } iNdEx = postIndex default: @@ -1752,7 +1471,7 @@ func (m *Validators) Unmarshal(dAtA []byte) error { } return nil } -func (m *HeaderSubset) Unmarshal(dAtA []byte) error { +func (m *KeyPowerMapping) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -1775,15 +1494,15 @@ func (m *HeaderSubset) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: HeaderSubset: wiretype end group for non-group") + return fmt.Errorf("proto: KeyPowerMapping: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: HeaderSubset: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: KeyPowerMapping: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Time", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field List", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -1810,77 +1529,89 @@ func (m *HeaderSubset) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if err := github_com_cosmos_gogoproto_types.StdTimeUnmarshal(&m.Time, dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field NextValidatorsHash", wireType) - } - var byteLen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowDogfood - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - byteLen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if byteLen < 0 { - return ErrInvalidLengthDogfood - } - postIndex := iNdEx + byteLen - if postIndex < 0 { - return ErrInvalidLengthDogfood - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.NextValidatorsHash = append(m.NextValidatorsHash[:0], dAtA[iNdEx:postIndex]...) - if m.NextValidatorsHash == nil { - m.NextValidatorsHash = []byte{} - } - iNdEx = postIndex - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field AppHash", wireType) - } - var byteLen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowDogfood - } - if iNdEx >= l { - return io.ErrUnexpectedEOF + if m.List == nil { + m.List = make(map[string]int64) + } + var mapkey string + var mapvalue int64 + for iNdEx < postIndex { + entryPreIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowDogfood + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } } - b := dAtA[iNdEx] - iNdEx++ - byteLen |= int(b&0x7F) << shift - if b < 0x80 { - break + fieldNum := int32(wire >> 3) + if fieldNum == 1 { + var stringLenmapkey uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowDogfood + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLenmapkey |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLenmapkey := int(stringLenmapkey) + if intStringLenmapkey < 0 { + return ErrInvalidLengthDogfood + } + postStringIndexmapkey := iNdEx + intStringLenmapkey + if postStringIndexmapkey < 0 { + return ErrInvalidLengthDogfood + } + if postStringIndexmapkey > l { + return io.ErrUnexpectedEOF + } + mapkey = string(dAtA[iNdEx:postStringIndexmapkey]) + iNdEx = postStringIndexmapkey + } else if fieldNum == 2 { + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowDogfood + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + mapvalue |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + } else { + iNdEx = entryPreIndex + skippy, err := skipDogfood(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthDogfood + } + if (iNdEx + skippy) > postIndex { + return io.ErrUnexpectedEOF + } + iNdEx += skippy } } - if byteLen < 0 { - return ErrInvalidLengthDogfood - } - postIndex := iNdEx + byteLen - if postIndex < 0 { - return ErrInvalidLengthDogfood - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.AppHash = append(m.AppHash[:0], dAtA[iNdEx:postIndex]...) - if m.AppHash == nil { - m.AppHash = []byte{} - } + m.List[mapkey] = mapvalue iNdEx = postIndex default: iNdEx = preIndex diff --git a/x/dogfood/types/expected_keepers.go b/x/dogfood/types/expected_keepers.go index 06ca74df4..a652b9902 100644 --- a/x/dogfood/types/expected_keepers.go +++ b/x/dogfood/types/expected_keepers.go @@ -55,6 +55,12 @@ type OperatorKeeper interface { ) (bool, sdk.AccAddress) IsOperatorJailedForChainId(sdk.Context, sdk.AccAddress, string) bool Jail(sdk.Context, sdk.ConsAddress, string) + // GetActiveOperatorsForChainId should return a list of operators and their public keys. + // These operators should not be in the process of opting our, and should not be jailed + // whether permanently or temporarily. + GetActiveOperatorsForChainId( + sdk.Context, string, + ) ([]sdk.AccAddress, []tmprotocrypto.PublicKey) } // DelegationKeeper represents the expected keeper interface for the delegation module. @@ -72,6 +78,10 @@ type EpochsHooks interface { // RestakingKeeper represents the expected keeper interface for the restaking module. type RestakingKeeper interface { GetOperatorAssetValue(sdk.Context, sdk.AccAddress) (int64, error) + IsStakingAsset(sdk.Context, string) bool + GetAvgDelegatedValue( + sdk.Context, []sdk.AccAddress, []string, + ) ([]int64, error) } // SlashingKeeper represents the expected keeper interface for the (exo-)slashing module. diff --git a/x/dogfood/types/keys.go b/x/dogfood/types/keys.go index 1303fb4d0..849b5ec54 100644 --- a/x/dogfood/types/keys.go +++ b/x/dogfood/types/keys.go @@ -53,6 +53,7 @@ const ( // PendingUndelegationsByte is the byte used to store the list of undelegations that will // mature at the end of the current block. PendingUndelegationsByte + // ValidatorSetBytePrefix is the prefix for the historical validator set store. ValidatorSetBytePrefix @@ -61,6 +62,12 @@ const ( // HeaderBytePrefix is the prefix for the header store. HeaderBytePrefix + + // EpochEndByte is the byte key for the epoch end store. + EpochEndByte + + // KeyPowerMappingByte is the byte key for the consensus key to vote power mapping store. + KeyPowerMappingByte ) // ExocoreValidatorKey returns the key for the validator store. @@ -169,6 +176,16 @@ func PendingUndelegationsKey() []byte { return []byte{PendingUndelegationsByte} } +// EpochEndKey returns the key for the epoch end store. +func EpochEndKey() []byte { + return []byte{EpochEndByte} +} + +// KeyPowerMappingKey returns the key for the consensus key to vote power mapping store. +func KeyPowerMappingKey() []byte { + return []byte{KeyPowerMappingByte} +} + // SafeInt64ToUint64 is a wrapper function to convert an int64 // to a uint64. It returns (0, false) if the conversion is not possible. // This is safe as long as the int64 is non-negative. From 4960d4343584abceba0ed24750996eb34dbe66c9 Mon Sep 17 00:00:00 2001 From: MaxMustermann2 <82761650+MaxMustermann2@users.noreply.github.com> Date: Tue, 5 Mar 2024 00:16:47 +0000 Subject: [PATCH 3/7] fix(dogfood): relint, add epoch id for avg --- proto/exocore/dogfood/v1/dogfood.proto | 2 - x/dogfood/keeper/abci.go | 13 ++++- x/dogfood/keeper/genesis.go | 2 +- x/dogfood/keeper/impl_operator_hooks.go | 22 ------- x/dogfood/types/dogfood.pb.go | 78 ++++++++++++------------- x/dogfood/types/expected_keepers.go | 2 +- 6 files changed, 50 insertions(+), 69 deletions(-) diff --git a/proto/exocore/dogfood/v1/dogfood.proto b/proto/exocore/dogfood/v1/dogfood.proto index c66e975e7..28f16e9e5 100644 --- a/proto/exocore/dogfood/v1/dogfood.proto +++ b/proto/exocore/dogfood/v1/dogfood.proto @@ -8,8 +8,6 @@ import "google/protobuf/timestamp.proto"; import "cosmos/staking/v1beta1/staking.proto"; import "cosmos_proto/cosmos.proto"; -import "tendermint/abci/types.proto"; -import "tendermint/crypto/keys.proto"; option go_package = "github.com/ExocoreNetwork/exocore/x/dogfood/types"; diff --git a/x/dogfood/keeper/abci.go b/x/dogfood/keeper/abci.go index b1f4522a1..e012a18f8 100644 --- a/x/dogfood/keeper/abci.go +++ b/x/dogfood/keeper/abci.go @@ -49,15 +49,24 @@ func (k Keeper) EndBlock(ctx sdk.Context) []abci.ValidatorUpdate { var res []abci.ValidatorUpdate operators, keys := k.operatorKeeper.GetActiveOperatorsForChainId(ctx, ctx.ChainID()) powers, err := k.restakingKeeper.GetAvgDelegatedValue( - ctx, operators, k.GetAssetIDs(ctx), + ctx, operators, k.GetAssetIDs(ctx), k.GetEpochIdentifier(ctx), ) if err != nil { return []abci.ValidatorUpdate{} } operators, keys, powers = sortByPower(operators, keys, powers) + maxVals := k.GetMaxValidators(ctx) for i := range operators { + if i >= int(maxVals) { // #nosec G701 // #nosec G701 // ok if 64-bit. + // we have reached the maximum number of validators. + break + } key := keys[i] power := powers[i] + if power < 1 { + // we have reached the bottom of the rung. + break + } // find the previous power. prevPower, found := prev[key.String()] if found && prevPower == power { @@ -72,7 +81,7 @@ func (k Keeper) EndBlock(ctx sdk.Context) []abci.ValidatorUpdate { }) } // the remaining keys in prev have lost their power. - for key, _ := range prev { + for key := range prev { bz := []byte(key) var keyObj tmprotocrypto.PublicKey k.cdc.MustUnmarshal(bz, &keyObj) diff --git a/x/dogfood/keeper/genesis.go b/x/dogfood/keeper/genesis.go index 416d08093..18be3db6b 100644 --- a/x/dogfood/keeper/genesis.go +++ b/x/dogfood/keeper/genesis.go @@ -30,7 +30,7 @@ func (k Keeper) InitGenesis( } } // genState must not be malformed. - if len(genState.ValSet) > int(k.GetMaxValidators(ctx)) { + if len(genState.ValSet) > int(k.GetMaxValidators(ctx)) { // #nosec G701 // ok if 64-bit. panic(fmt.Errorf( "cannot have more than %d validators in the genesis state", k.GetMaxValidators(ctx), diff --git a/x/dogfood/keeper/impl_operator_hooks.go b/x/dogfood/keeper/impl_operator_hooks.go index 795b76dd9..0a37fbd0e 100644 --- a/x/dogfood/keeper/impl_operator_hooks.go +++ b/x/dogfood/keeper/impl_operator_hooks.go @@ -42,28 +42,6 @@ func (h OperatorHooksWrapper) AfterOperatorKeyReplacement( h.keeper.SetUnbondingInformation(ctx, operator, oldKey, false) h.keeper.ClearUnbondingInformation(ctx, operator, newKey) } - // // remove the old key - // // res == Removed, it means operator had added this key and is now removing it. - // // no additional information to clear. - // // res == Success, the old key should be pruned from the operator module. - // // res == Exists, there is nothing to do. - // if res := h.keeper.QueueOperation( - // ctx, addr, oldKey, types.KeyRemoval, - // ); res == types.QueueResultSuccess { - // // the old key can be marked for pruning - // h.keeper.SetUnbondingInformation(ctx, addr, oldKey, false) - // } - // // add the new key - // // res == Removed, it means operator has added their original key again - // // res == Success, there is no additional information to store - // // res == Exists, there is no nothing to do - // if res := h.keeper.QueueOperation( - // ctx, addr, newKey, types.KeyAdditionOrUpdate, - // ); res == types.QueueResultRemoved { - // // see AfterOperatorOptIn for explanation - // h.keeper.ClearUnbondingInformation(ctx, addr, newKey) - // } - // } } // AfterOperatorOptOutInitiated is the implementation of the operator hooks. diff --git a/x/dogfood/types/dogfood.pb.go b/x/dogfood/types/dogfood.pb.go index d00b77801..56424d7ad 100644 --- a/x/dogfood/types/dogfood.pb.go +++ b/x/dogfood/types/dogfood.pb.go @@ -5,8 +5,6 @@ package types import ( fmt "fmt" - _ "github.com/cometbft/cometbft/abci/types" - _ "github.com/cometbft/cometbft/proto/tendermint/crypto" _ "github.com/cosmos/cosmos-proto" types "github.com/cosmos/cosmos-sdk/codec/types" types1 "github.com/cosmos/cosmos-sdk/x/staking/types" @@ -412,45 +410,43 @@ func init() { func init() { proto.RegisterFile("exocore/dogfood/v1/dogfood.proto", fileDescriptor_071b9989c501c3f2) } var fileDescriptor_071b9989c501c3f2 = []byte{ - // 598 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x53, 0xcd, 0x6e, 0x13, 0x31, - 0x10, 0x8e, 0x9b, 0x52, 0x5a, 0x37, 0x12, 0x95, 0x15, 0x41, 0x1a, 0x50, 0x12, 0x22, 0x84, 0x72, - 0xa0, 0xbb, 0xa4, 0x3d, 0x50, 0x95, 0x53, 0x82, 0x2a, 0x15, 0x05, 0x50, 0xb5, 0xfc, 0x1c, 0xb8, - 0x44, 0xde, 0xdd, 0xe9, 0x66, 0x95, 0xc4, 0xb6, 0xd6, 0xde, 0xb4, 0xfb, 0x10, 0x48, 0xbd, 0xf0, - 0x08, 0xbc, 0x01, 0x0f, 0x51, 0x71, 0xea, 0x91, 0x53, 0x41, 0xcd, 0x1b, 0xf0, 0x04, 0x68, 0xd7, - 0x76, 0x28, 0x2d, 0xe2, 0x36, 0xe3, 0xef, 0x9b, 0xf1, 0x7c, 0xf3, 0x83, 0x5b, 0x70, 0xc2, 0x03, - 0x9e, 0x80, 0x1b, 0xf2, 0xe8, 0x88, 0xf3, 0xd0, 0x9d, 0x75, 0xad, 0xe9, 0x88, 0x84, 0x2b, 0x4e, - 0x88, 0x61, 0x38, 0xf6, 0x79, 0xd6, 0xad, 0x57, 0x23, 0x1e, 0xf1, 0x02, 0x76, 0x73, 0x4b, 0x33, - 0xeb, 0x9b, 0x11, 0xe7, 0xd1, 0x04, 0xdc, 0xc2, 0xf3, 0xd3, 0x23, 0x97, 0xb2, 0xcc, 0x40, 0xcd, - 0xeb, 0x90, 0x8a, 0xa7, 0x20, 0x15, 0x9d, 0x0a, 0x43, 0x78, 0x14, 0x70, 0x39, 0xe5, 0xd2, 0x95, - 0x8a, 0x8e, 0x63, 0x16, 0xb9, 0xb3, 0xae, 0x0f, 0x8a, 0x76, 0xad, 0x6f, 0x7f, 0xd0, 0xac, 0xa1, - 0xfe, 0x5a, 0x3b, 0x06, 0xba, 0xaf, 0x80, 0x85, 0x90, 0x4c, 0x63, 0xa6, 0x5c, 0xea, 0x07, 0xb1, - 0xab, 0x32, 0x01, 0x16, 0x7c, 0x70, 0x05, 0x0c, 0x92, 0x4c, 0x28, 0xee, 0x8e, 0x21, 0x33, 0x68, - 0xfb, 0x0b, 0xc2, 0x1b, 0xfb, 0x5a, 0xe4, 0x07, 0x3a, 0x89, 0x43, 0xaa, 0x78, 0x42, 0x6a, 0xf8, - 0x36, 0x0d, 0xc3, 0x04, 0xa4, 0xac, 0xa1, 0x16, 0xea, 0x54, 0x3c, 0xeb, 0x92, 0x2a, 0xbe, 0x25, - 0xf8, 0x31, 0x24, 0xb5, 0xa5, 0x16, 0xea, 0x94, 0x3d, 0xed, 0x10, 0x8a, 0x57, 0x44, 0xea, 0x8f, - 0x21, 0xab, 0x95, 0x5b, 0xa8, 0xb3, 0xbe, 0x5d, 0x75, 0xb4, 0x64, 0xc7, 0x4a, 0x76, 0x7a, 0x2c, - 0xeb, 0xef, 0xfc, 0xba, 0x68, 0xde, 0xcb, 0xe8, 0x74, 0xb2, 0xd7, 0x0e, 0x38, 0x93, 0xc0, 0x64, - 0x2a, 0x87, 0x3a, 0xae, 0xfd, 0xed, 0xeb, 0x56, 0xd5, 0x48, 0xd2, 0x35, 0x3a, 0x87, 0xa9, 0x3f, - 0x80, 0xcc, 0x33, 0x89, 0xdb, 0x8f, 0xf1, 0x46, 0x2f, 0x08, 0x78, 0xca, 0x54, 0x4f, 0x97, 0x02, - 0x92, 0x10, 0xbc, 0x3c, 0x89, 0xa5, 0xaa, 0xa1, 0x56, 0xb9, 0x53, 0xf1, 0x0a, 0xbb, 0xdd, 0xc1, - 0xe4, 0x85, 0x4d, 0xfe, 0x7f, 0xe6, 0x13, 0x7c, 0xf7, 0x3d, 0x0b, 0x61, 0x02, 0x11, 0x55, 0x31, - 0x67, 0x1e, 0x04, 0x3c, 0x09, 0x07, 0x90, 0xfd, 0x9b, 0xfd, 0x12, 0xe3, 0x45, 0x7f, 0x24, 0x79, - 0x7e, 0x85, 0xb1, 0xbe, 0xfd, 0xd0, 0x31, 0xa5, 0xdb, 0x81, 0x99, 0x01, 0x3a, 0x8b, 0x88, 0xfe, - 0xf2, 0xd9, 0x45, 0xb3, 0x64, 0x52, 0x7d, 0x46, 0xb8, 0x72, 0x00, 0x34, 0x84, 0xe4, 0x6d, 0xea, - 0x4b, 0x50, 0x64, 0x17, 0x2f, 0xe7, 0x2b, 0x51, 0xf4, 0x7a, 0x7d, 0xbb, 0x7e, 0xa3, 0x79, 0xef, - 0xec, 0xbe, 0xf4, 0x57, 0xf3, 0x34, 0xa7, 0x3f, 0x9a, 0xc8, 0x2b, 0x22, 0xc8, 0x53, 0x5c, 0x65, - 0x70, 0xa2, 0x86, 0xb3, 0x45, 0x69, 0xc3, 0x11, 0x95, 0xa3, 0x62, 0x3a, 0x15, 0x8f, 0xe4, 0xd8, - 0x9f, 0xaa, 0x0f, 0xa8, 0x1c, 0x91, 0x4d, 0xbc, 0x4a, 0x85, 0xd0, 0xac, 0xb2, 0x99, 0xad, 0x10, - 0x39, 0xd4, 0xfe, 0x84, 0xf0, 0x9d, 0x01, 0x64, 0x87, 0xf9, 0x48, 0x5f, 0x53, 0x21, 0x62, 0x16, - 0x91, 0xde, 0x5f, 0x42, 0xb7, 0x9c, 0x9b, 0xf7, 0xe0, 0x5c, 0x0b, 0x71, 0x5e, 0xc5, 0x52, 0xed, - 0x33, 0x95, 0x64, 0x5a, 0x6e, 0xfd, 0x19, 0x5e, 0x5b, 0x3c, 0x91, 0x0d, 0x5c, 0xce, 0xd7, 0x24, - 0x57, 0xba, 0xe6, 0xe5, 0x66, 0xbe, 0x51, 0x33, 0x3a, 0x49, 0xc1, 0x6e, 0x54, 0xe1, 0xec, 0x2d, - 0xed, 0xa2, 0xfe, 0xe0, 0xec, 0xb2, 0x81, 0xce, 0x2f, 0x1b, 0xe8, 0xe7, 0x65, 0x03, 0x9d, 0xce, - 0x1b, 0xa5, 0xf3, 0x79, 0xa3, 0xf4, 0x7d, 0xde, 0x28, 0x7d, 0xec, 0x46, 0xb1, 0x1a, 0xa5, 0xbe, - 0x13, 0xf0, 0xa9, 0x6b, 0x96, 0xf7, 0x0d, 0xa8, 0x63, 0x9e, 0x8c, 0x5d, 0x7b, 0xd2, 0x27, 0x8b, - 0xa3, 0x2e, 0x6e, 0xc1, 0x5f, 0x29, 0xba, 0xb9, 0xf3, 0x3b, 0x00, 0x00, 0xff, 0xff, 0xf5, 0x4e, - 0xb2, 0x58, 0xf4, 0x03, 0x00, 0x00, + // 575 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x53, 0xcf, 0x6e, 0xd3, 0x4e, + 0x10, 0xce, 0x36, 0xfd, 0xf5, 0xd7, 0x6e, 0x23, 0x11, 0xad, 0x22, 0x48, 0x73, 0x70, 0x82, 0x85, + 0x50, 0x0e, 0x74, 0x4d, 0xd2, 0x03, 0x55, 0x39, 0x25, 0xa8, 0x52, 0x51, 0x00, 0x55, 0xe6, 0xcf, + 0x81, 0x4b, 0xb4, 0xb6, 0xa7, 0x8e, 0x15, 0xc7, 0xbb, 0xf2, 0xae, 0xd3, 0xf8, 0x21, 0x90, 0x7a, + 0xe1, 0x11, 0x78, 0x03, 0x1e, 0xa2, 0xe2, 0xd4, 0x23, 0xa7, 0x82, 0x92, 0x37, 0xe0, 0x09, 0x90, + 0xbd, 0x76, 0x80, 0x16, 0x71, 0x9b, 0xd9, 0xef, 0x9b, 0xd9, 0x6f, 0xe7, 0x9b, 0xc5, 0x1d, 0x58, + 0x70, 0x97, 0xc7, 0x60, 0x79, 0xdc, 0x3f, 0xe3, 0xdc, 0xb3, 0xe6, 0xbd, 0x32, 0xa4, 0x22, 0xe6, + 0x8a, 0x13, 0x52, 0x30, 0x68, 0x79, 0x3c, 0xef, 0xb5, 0x1a, 0x3e, 0xf7, 0x79, 0x0e, 0x5b, 0x59, + 0xa4, 0x99, 0xad, 0x3d, 0x9f, 0x73, 0x3f, 0x04, 0x2b, 0xcf, 0x9c, 0xe4, 0xcc, 0x62, 0x51, 0x5a, + 0x40, 0xed, 0x9b, 0x90, 0x0a, 0x66, 0x20, 0x15, 0x9b, 0x89, 0x82, 0xf0, 0xc0, 0xe5, 0x72, 0xc6, + 0xa5, 0x25, 0x15, 0x9b, 0x06, 0x91, 0x6f, 0xcd, 0x7b, 0x0e, 0x28, 0xd6, 0x2b, 0xf3, 0xf2, 0x06, + 0xcd, 0x1a, 0xeb, 0xab, 0x75, 0xa2, 0x21, 0xf3, 0x13, 0xc2, 0xf5, 0x63, 0xad, 0xf4, 0x1d, 0x0b, + 0x03, 0x8f, 0x29, 0x1e, 0x93, 0x26, 0xfe, 0x9f, 0x79, 0x5e, 0x0c, 0x52, 0x36, 0x51, 0x07, 0x75, + 0x6b, 0x76, 0x99, 0x92, 0x06, 0xfe, 0x4f, 0xf0, 0x73, 0x88, 0x9b, 0x1b, 0x1d, 0xd4, 0xad, 0xda, + 0x3a, 0x21, 0x0c, 0x6f, 0x89, 0xc4, 0x99, 0x42, 0xda, 0xac, 0x76, 0x50, 0x77, 0xb7, 0xdf, 0xa0, + 0x5a, 0x37, 0x2d, 0x75, 0xd3, 0x41, 0x94, 0x0e, 0x0f, 0x7e, 0x5c, 0xb7, 0xef, 0xa5, 0x6c, 0x16, + 0x1e, 0x99, 0x2e, 0x8f, 0x24, 0x44, 0x32, 0x91, 0x63, 0x5d, 0x67, 0x7e, 0xf9, 0xbc, 0xdf, 0x28, + 0x74, 0xb9, 0x71, 0x2a, 0x14, 0xa7, 0xa7, 0x89, 0x33, 0x82, 0xd4, 0x2e, 0x1a, 0x9b, 0x0f, 0x71, + 0x7d, 0xe0, 0xba, 0x3c, 0x89, 0xd4, 0x40, 0x4b, 0x01, 0x49, 0x08, 0xde, 0x0c, 0x03, 0xa9, 0x9a, + 0xa8, 0x53, 0xed, 0xd6, 0xec, 0x3c, 0x36, 0xbb, 0x98, 0x3c, 0x2b, 0x9b, 0xff, 0x9b, 0xf9, 0x08, + 0xdf, 0x7d, 0x1b, 0x79, 0x10, 0x82, 0xcf, 0x54, 0xc0, 0x23, 0x1b, 0x5c, 0x1e, 0x7b, 0x23, 0x48, + 0xff, 0xce, 0x7e, 0x8e, 0xf1, 0x7a, 0x3e, 0x92, 0x3c, 0xfd, 0x8d, 0xb1, 0xdb, 0xbf, 0x4f, 0x0b, + 0xe9, 0xe5, 0xd4, 0x0b, 0x17, 0xe8, 0xba, 0x62, 0xb8, 0x79, 0x79, 0xdd, 0xae, 0x14, 0xad, 0x3e, + 0x22, 0x5c, 0x3b, 0x01, 0xe6, 0x41, 0xfc, 0x3a, 0x71, 0x24, 0x28, 0x72, 0x88, 0x37, 0x33, 0x5f, + 0xf3, 0x59, 0xef, 0xf6, 0x5b, 0xb7, 0x86, 0xf7, 0xa6, 0x34, 0x7d, 0xb8, 0x9d, 0xb5, 0xb9, 0xf8, + 0xd6, 0x46, 0x76, 0x5e, 0x41, 0x1e, 0xe3, 0x46, 0x04, 0x0b, 0x35, 0x9e, 0xaf, 0xa5, 0x8d, 0x27, + 0x4c, 0x4e, 0x72, 0x77, 0x6a, 0x36, 0xc9, 0xb0, 0x5f, 0xaa, 0x4f, 0x98, 0x9c, 0x90, 0x3d, 0xbc, + 0xcd, 0x84, 0xd0, 0xac, 0x6a, 0xe1, 0xad, 0x10, 0x19, 0x64, 0x7e, 0x40, 0xf8, 0xce, 0x08, 0xd2, + 0xd3, 0xcc, 0xd2, 0x97, 0x4c, 0x88, 0x20, 0xf2, 0xc9, 0xe0, 0x8f, 0x87, 0xee, 0xd3, 0xdb, 0x4b, + 0x4d, 0x6f, 0x94, 0xd0, 0x17, 0x81, 0x54, 0xc7, 0x91, 0x8a, 0x53, 0xfd, 0xdc, 0xd6, 0x13, 0xbc, + 0xb3, 0x3e, 0x22, 0x75, 0x5c, 0xcd, 0xd6, 0x24, 0x7b, 0xe9, 0x8e, 0x9d, 0x85, 0xd9, 0x46, 0xcd, + 0x59, 0x98, 0x40, 0xb9, 0x51, 0x79, 0x72, 0xb4, 0x71, 0x88, 0x86, 0xa3, 0xcb, 0xa5, 0x81, 0xae, + 0x96, 0x06, 0xfa, 0xbe, 0x34, 0xd0, 0xc5, 0xca, 0xa8, 0x5c, 0xad, 0x8c, 0xca, 0xd7, 0x95, 0x51, + 0x79, 0xdf, 0xf3, 0x03, 0x35, 0x49, 0x1c, 0xea, 0xf2, 0x99, 0x55, 0x2c, 0xef, 0x2b, 0x50, 0xe7, + 0x3c, 0x9e, 0x5a, 0xe5, 0xbf, 0x5c, 0xac, 0x7f, 0xa6, 0x4a, 0x05, 0x48, 0x67, 0x2b, 0x9f, 0xe6, + 0xc1, 0xcf, 0x00, 0x00, 0x00, 0xff, 0xff, 0xdb, 0x8d, 0x64, 0x24, 0xb9, 0x03, 0x00, 0x00, } func (m *ExocoreValidator) Marshal() (dAtA []byte, err error) { diff --git a/x/dogfood/types/expected_keepers.go b/x/dogfood/types/expected_keepers.go index a652b9902..6c6862d9f 100644 --- a/x/dogfood/types/expected_keepers.go +++ b/x/dogfood/types/expected_keepers.go @@ -80,7 +80,7 @@ type RestakingKeeper interface { GetOperatorAssetValue(sdk.Context, sdk.AccAddress) (int64, error) IsStakingAsset(sdk.Context, string) bool GetAvgDelegatedValue( - sdk.Context, []sdk.AccAddress, []string, + sdk.Context, []sdk.AccAddress, []string, string, ) ([]int64, error) } From d54107b357f5f48939af87f7c164ba4fa4e75429 Mon Sep 17 00:00:00 2001 From: MaxMustermann2 <82761650+MaxMustermann2@users.noreply.github.com> Date: Tue, 5 Mar 2024 00:23:45 +0000 Subject: [PATCH 4/7] chore(dogfood): golangci-lint --- x/dogfood/keeper/abci.go | 2 +- x/dogfood/keeper/impl_operator_hooks.go | 4 ++- x/dogfood/keeper/validators.go | 3 +- x/dogfood/types/params.go | 38 ++++++++++++------------- 4 files changed, 25 insertions(+), 22 deletions(-) diff --git a/x/dogfood/keeper/abci.go b/x/dogfood/keeper/abci.go index e012a18f8..ea37126cb 100644 --- a/x/dogfood/keeper/abci.go +++ b/x/dogfood/keeper/abci.go @@ -46,7 +46,7 @@ func (k Keeper) EndBlock(ctx sdk.Context) []abci.ValidatorUpdate { // if it hasn't, do nothing for that operator key. // if it has, queue an update. prev := k.getKeyPowerMapping(ctx).List - var res []abci.ValidatorUpdate + res := make([]abci.ValidatorUpdate, 0, len(prev)) operators, keys := k.operatorKeeper.GetActiveOperatorsForChainId(ctx, ctx.ChainID()) powers, err := k.restakingKeeper.GetAvgDelegatedValue( ctx, operators, k.GetAssetIDs(ctx), k.GetEpochIdentifier(ctx), diff --git a/x/dogfood/keeper/impl_operator_hooks.go b/x/dogfood/keeper/impl_operator_hooks.go index 0a37fbd0e..5e0d027bb 100644 --- a/x/dogfood/keeper/impl_operator_hooks.go +++ b/x/dogfood/keeper/impl_operator_hooks.go @@ -29,7 +29,9 @@ func (h OperatorHooksWrapper) AfterOperatorOptIn( // this information will be fetched at the end of the epoch // and the operator's vote power will be calculated then. // however, we will still clear the unbonding information, if it exists. - h.keeper.ClearUnbondingInformation(ctx, addr, key) + if strings.Compare(chainID, ctx.ChainID()) == 0 { + h.keeper.ClearUnbondingInformation(ctx, addr, key) + } } // AfterOperatorKeyReplacement is the implementation of the operator hooks. diff --git a/x/dogfood/keeper/validators.go b/x/dogfood/keeper/validators.go index 219fbb2ba..ce7beec25 100644 --- a/x/dogfood/keeper/validators.go +++ b/x/dogfood/keeper/validators.go @@ -390,7 +390,8 @@ func (k Keeper) saveKeyPowerMapping(ctx sdk.Context, updates []abci.ValidatorUpd m := make(map[string]int64, len(updates)) for _, update := range updates { // do not use the stringer interface here so that it can be deserialized. - m[string(k.cdc.MustMarshal(&update.PubKey))] = update.Power + key := update.PubKey // prevent implicit memory aliasing. + m[string(k.cdc.MustMarshal(&key))] = update.Power } bz := k.cdc.MustMarshal(&types.KeyPowerMapping{List: m}) store.Set(types.KeyPowerMappingKey(), bz) diff --git a/x/dogfood/types/params.go b/x/dogfood/types/params.go index ff96ee280..a07d14f3e 100644 --- a/x/dogfood/types/params.go +++ b/x/dogfood/types/params.go @@ -145,29 +145,29 @@ func (p Params) String() string { // ValidateAssetIDs checks whether the supplied value is a valid asset ID. func ValidateAssetIDs(i interface{}) error { + var val []string if val, ok := i.([]string); !ok { return fmt.Errorf("invalid parameter type: %T", i) } else if len(val) == 0 { return fmt.Errorf("invalid parameter value: %v", val) - } else { - for _, assetID := range val { - if !strings.Contains(assetID, "_") { - return fmt.Errorf("invalid parameter value (missing underscore): %v", val) - } - split := strings.Split(assetID, "_") - if len(split) != 2 { - return fmt.Errorf( - "invalid parameter value (unexpected number of underscores): %v", val, - ) - } - if len(split[0]) == 0 || len(split[1]) == 0 { - return fmt.Errorf("invalid parameter value (empty parts): %v", val) - } - // i cannot validate the address because it may be on a client chain and i have - // no idea what format or length it may have. i can only validate the chain ID. - if _, err := hexutil.DecodeUint64(split[1]); err != nil { - return fmt.Errorf("invalid parameter value (not a number): %v", split[1]) - } + } + for _, assetID := range val { + if !strings.Contains(assetID, "_") { + return fmt.Errorf("invalid parameter value (missing underscore): %v", val) + } + split := strings.Split(assetID, "_") + if len(split) != 2 { + return fmt.Errorf( + "invalid parameter value (unexpected number of underscores): %v", val, + ) + } + if len(split[0]) == 0 || len(split[1]) == 0 { + return fmt.Errorf("invalid parameter value (empty parts): %v", val) + } + // i cannot validate the address because it may be on a client chain and i have + // no idea what format or length it may have. i can only validate the chain ID. + if _, err := hexutil.DecodeUint64(split[1]); err != nil { + return fmt.Errorf("invalid parameter value (not a number): %v", split[1]) } } return nil From f63507a5117ba16cda3c7f544a95c31481d29ad0 Mon Sep 17 00:00:00 2001 From: MaxMustermann2 <82761650+MaxMustermann2@users.noreply.github.com> Date: Tue, 5 Mar 2024 00:38:44 +0000 Subject: [PATCH 5/7] chore(dogfood): lint gosec again --- x/dogfood/keeper/abci.go | 6 +++++- x/dogfood/keeper/genesis.go | 3 ++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/x/dogfood/keeper/abci.go b/x/dogfood/keeper/abci.go index ea37126cb..62090e8a9 100644 --- a/x/dogfood/keeper/abci.go +++ b/x/dogfood/keeper/abci.go @@ -57,7 +57,8 @@ func (k Keeper) EndBlock(ctx sdk.Context) []abci.ValidatorUpdate { operators, keys, powers = sortByPower(operators, keys, powers) maxVals := k.GetMaxValidators(ctx) for i := range operators { - if i >= int(maxVals) { // #nosec G701 // #nosec G701 // ok if 64-bit. + // #nosec G701 // ok if 64-bit. + if i >= int(maxVals) { // we have reached the maximum number of validators. break } @@ -81,6 +82,9 @@ func (k Keeper) EndBlock(ctx sdk.Context) []abci.ValidatorUpdate { }) } // the remaining keys in prev have lost their power. + // gosec does not like `for key := range prev` while others do not like + // `for key, _ := range prev` + // #nosec G705 for key := range prev { bz := []byte(key) var keyObj tmprotocrypto.PublicKey diff --git a/x/dogfood/keeper/genesis.go b/x/dogfood/keeper/genesis.go index 18be3db6b..76e3758a9 100644 --- a/x/dogfood/keeper/genesis.go +++ b/x/dogfood/keeper/genesis.go @@ -30,7 +30,8 @@ func (k Keeper) InitGenesis( } } // genState must not be malformed. - if len(genState.ValSet) > int(k.GetMaxValidators(ctx)) { // #nosec G701 // ok if 64-bit. + // #nosec G701 // ok if 64-bit. + if len(genState.ValSet) > int(k.GetMaxValidators(ctx)) { panic(fmt.Errorf( "cannot have more than %d validators in the genesis state", k.GetMaxValidators(ctx), From 79bf60fbdeb721bd0f51f96fc75bb4422737a125 Mon Sep 17 00:00:00 2001 From: MaxMustermann2 <82761650+MaxMustermann2@users.noreply.github.com> Date: Tue, 5 Mar 2024 06:07:14 +0000 Subject: [PATCH 6/7] fix(dogfood): use correct string for pubkey --- x/dogfood/keeper/abci.go | 16 ++++++++++------ x/dogfood/keeper/validators.go | 6 +++--- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/x/dogfood/keeper/abci.go b/x/dogfood/keeper/abci.go index 62090e8a9..040aabdf5 100644 --- a/x/dogfood/keeper/abci.go +++ b/x/dogfood/keeper/abci.go @@ -62,23 +62,25 @@ func (k Keeper) EndBlock(ctx sdk.Context) []abci.ValidatorUpdate { // we have reached the maximum number of validators. break } - key := keys[i] power := powers[i] if power < 1 { // we have reached the bottom of the rung. break } // find the previous power. - prevPower, found := prev[key.String()] + key := keys[i] + keyString := string(k.cdc.MustMarshal(&key)) + prevPower, found := prev[keyString] if found && prevPower == power { - delete(prev, key.String()) + delete(prev, keyString) continue } // either the key was not in the previous set, // or the power has changed. res = append(res, abci.ValidatorUpdate{ PubKey: key, - Power: power, + // note that this is the final power and not the change in power. + Power: power, }) } // the remaining keys in prev have lost their power. @@ -86,9 +88,9 @@ func (k Keeper) EndBlock(ctx sdk.Context) []abci.ValidatorUpdate { // `for key, _ := range prev` // #nosec G705 for key := range prev { - bz := []byte(key) + bz := []byte(key) // undo string operation var keyObj tmprotocrypto.PublicKey - k.cdc.MustUnmarshal(bz, &keyObj) + k.cdc.MustUnmarshal(bz, &keyObj) // undo marshal operation res = append(res, abci.ValidatorUpdate{ PubKey: keyObj, Power: 0, @@ -99,6 +101,8 @@ func (k Keeper) EndBlock(ctx sdk.Context) []abci.ValidatorUpdate { return k.ApplyValidatorChanges(ctx, res, id+1) } +// sortByPower sorts operators, their pubkeys, and their powers by the powers. +// the sorting is descending, so the highest power is first. func sortByPower( operatorAddrs []sdk.AccAddress, pubKeys []tmprotocrypto.PublicKey, diff --git a/x/dogfood/keeper/validators.go b/x/dogfood/keeper/validators.go index ce7beec25..df67cb234 100644 --- a/x/dogfood/keeper/validators.go +++ b/x/dogfood/keeper/validators.go @@ -44,7 +44,7 @@ func (k Keeper) ApplyValidatorChanges( // An error here would indicate that this change is invalid. // The change is received either from the genesis file, or from // other parts of the module. - // In no situation it should happen, however, if it does, + // In no situation it should happen; however, if it does, // we do not panic. Simply skip the change. continue } @@ -55,7 +55,7 @@ func (k Keeper) ApplyValidatorChanges( switch found { case true: // update or delete an existing validator. - // contract: power must not be negative. + // assumption: power can not be negative. if change.Power < 1 { k.DeleteValidator(ctx, addr) } else { @@ -69,7 +69,7 @@ func (k Keeper) ApplyValidatorChanges( if err != nil { continue } - // guard for errors within the hook. + // guard for errors within the AfterValidatorBonded hook. cc, writeFunc := ctx.CacheContext() k.SetValidator(cc, ocVal) err = k.Hooks().AfterValidatorBonded(cc, sdk.ConsAddress(addr), nil) From 6a988add0d018d0f0b112548387d1ab111ee07bd Mon Sep 17 00:00:00 2001 From: MaxMustermann2 <82761650+MaxMustermann2@users.noreply.github.com> Date: Tue, 5 Mar 2024 06:08:14 +0000 Subject: [PATCH 7/7] fix(dogfood): ++ the undelegation hold count The line was accidentally deleted. --- x/dogfood/keeper/impl_delegation_hooks.go | 1 + 1 file changed, 1 insertion(+) diff --git a/x/dogfood/keeper/impl_delegation_hooks.go b/x/dogfood/keeper/impl_delegation_hooks.go index bf459ec0d..adbdc021e 100644 --- a/x/dogfood/keeper/impl_delegation_hooks.go +++ b/x/dogfood/keeper/impl_delegation_hooks.go @@ -49,6 +49,7 @@ func (wrapper DelegationHooksWrapper) AfterUndelegationStarted( // so this is not a concern. } wrapper.keeper.AppendUndelegationToMature(ctx, unbondingCompletionEpoch, recordKey) + wrapper.keeper.delegationKeeper.IncrementUndelegationHoldCount(ctx, recordKey) } // AfterUndelegationCompleted is called after an undelegation is completed.