Skip to content

Commit

Permalink
feat(operator): validate and load genesis
Browse files Browse the repository at this point in the history
  • Loading branch information
MaxMustermann2 committed Apr 3, 2024
1 parent bf2d5f7 commit b310aa8
Show file tree
Hide file tree
Showing 4 changed files with 464 additions and 15 deletions.
32 changes: 31 additions & 1 deletion x/operator/keeper/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,37 @@ import (
)

func (k Keeper) InitGenesis(ctx sdk.Context, state types.GenesisState) []abci.ValidatorUpdate {
// TODO
for _, op := range state.Operators {
op := op
if err := k.SetOperatorInfo(ctx, op.EarningsAddr, &op); err != nil {
panic(err)
}
}
for _, record := range state.OperatorRecords {
addr := record.OperatorAddress
// #nosec G703 // already validated
operatorAddr, _ := sdk.AccAddressFromBech32(addr)
bootstrapping := false
for _, detail := range record.Chains {
// opt into the specified chain (TODO: avs address format)
if err := k.OptIn(ctx, operatorAddr, detail.ChainID); err != nil {
panic(err)
}
// #nosec G703 // already validated
key, _ := types.HexStringToPubKey(detail.ConsensusKey)
// then set pub key
if err := k.SetOperatorConsKeyForChainID(
ctx, operatorAddr, detail.ChainID, key,
); err != nil {
panic(err)
}
bootstrapping = bootstrapping || ctx.ChainID() == detail.ChainID
}
if !bootstrapping {
// TODO: consider removing this check
panic("registered an operator but they aren't bootstrapping the current chain")
}
}
return []abci.ValidatorUpdate{}
}

Expand Down
65 changes: 52 additions & 13 deletions x/operator/types/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,33 +3,72 @@ package types
import errorsmod "cosmossdk.io/errors"

var (
ErrNoKeyInTheStore = errorsmod.Register(ModuleName, 0, "there is not the key for in the store")
ErrNoKeyInTheStore = errorsmod.Register(
ModuleName, 0,
"there is not the key for in the store",
)

ErrCliCmdInputArg = errorsmod.Register(ModuleName, 1, "there is an error in the input client command args")
ErrCliCmdInputArg = errorsmod.Register(
ModuleName, 1,
"there is an error in the input client command args",
)

ErrSlashInfo = errorsmod.Register(ModuleName, 2, "there is an error in the field of slash info")
ErrSlashInfo = errorsmod.Register(
ModuleName, 2,
"there is an error in the field of slash info",
)

ErrSlashInfoExist = errorsmod.Register(ModuleName, 3, "the slash info exists")
ErrSlashInfoExist = errorsmod.Register(
ModuleName, 3,
"the slash info exists",
)

ErrParameterInvalid = errorsmod.Register(ModuleName, 4, "the input parameter is invalid")
ErrParameterInvalid = errorsmod.Register(
ModuleName, 4,
"the input parameter is invalid",
)

ErrAlreadyOptedIn = errorsmod.Register(ModuleName, 5, "the operator has already opted in the avs")
ErrAlreadyOptedIn = errorsmod.Register(
ModuleName, 5,
"the operator has already opted in the avs",
)

ErrNotOptedIn = errorsmod.Register(ModuleName, 6, "the operator hasn't opted in the avs")
ErrNotOptedIn = errorsmod.Register(
ModuleName, 6,
"the operator hasn't opted in the avs",
)

ErrTheValueIsNegative = errorsmod.Register(ModuleName, 7, "the value is negative")
ErrTheValueIsNegative = errorsmod.Register(
ModuleName, 7,
"the value is negative",
)

ErrSlashContractNotMatch = errorsmod.Register(ModuleName, 8, "the slash contract isn't the slash contract address saved in the opted-in info")
ErrSlashContractNotMatch = errorsmod.Register(
ModuleName, 8,
"the slash contract isn't the slash contract address saved in the opted-in info",
)

ErrSlashOccurredHeight = errorsmod.Register(ModuleName, 9, "the occurred height of slash event is error")
ErrSlashOccurredHeight = errorsmod.Register(
ModuleName, 9,
"the occurred height of slash event is error",
)

// add for dogfood
ErrConsKeyAlreadyInUse = errorsmod.Register(
ModuleName,
10,
ModuleName, 10,
"consensus key already in use by another operator",
)

ErrAlreadyOptingOut = errorsmod.Register(
ModuleName, 11, "operator already opting out",
)

ErrInvalidPubKey = errorsmod.Register(
ModuleName, 12,
"invalid public key",
)

ErrInvalidGenesisData = errorsmod.Register(
ModuleName, 13,
"the genesis data supplied is invalid",
)
)
105 changes: 104 additions & 1 deletion x/operator/types/genesis.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
package types

import (
errorsmod "cosmossdk.io/errors"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/ethereum/go-ethereum/common"
)

func NewGenesisState(
operators []OperatorInfo,
records []OperatorConsKeyRecord,
Expand All @@ -18,6 +24,103 @@ func DefaultGenesis() *GenesisState {
// Validate performs basic genesis state validation returning an error upon any
// failure.
func (gs GenesisState) Validate() error {
// TODO
operators := make(map[string]struct{}, len(gs.Operators))
for _, op := range gs.Operators {
address := op.EarningsAddr
if _, found := operators[address]; found {
return errorsmod.Wrapf(
ErrInvalidGenesisData,
"duplicate operator address %s", address,
)
}
_, err := sdk.AccAddressFromBech32(address)
if err != nil {
return errorsmod.Wrapf(
ErrInvalidGenesisData,
"invalid operator address %s: %s", address, err,
)
}
operators[address] = struct{}{}
if op.ClientChainEarningsAddr != nil {
lzIDs := make(map[uint64]struct{}, len(op.ClientChainEarningsAddr.EarningInfoList))
for _, info := range op.ClientChainEarningsAddr.EarningInfoList {
lzID := info.LzClientChainID
if _, found := lzIDs[lzID]; found {
return errorsmod.Wrapf(
ErrInvalidGenesisData,
"duplicate lz client chain id %d", lzID,
)
}
lzIDs[lzID] = struct{}{}
// TODO: consider removing this check for non-EVM chains
if !common.IsHexAddress(info.ClientChainEarningAddr) {
return errorsmod.Wrapf(
ErrInvalidGenesisData,
"invalid client chain earning address %s", info.ClientChainEarningAddr,
)
}
}
}
}
operatorRecords := make(map[string]struct{}, len(gs.OperatorRecords))
keysByChainID := make(map[string]map[string]struct{})
for _, record := range gs.OperatorRecords {
addr := record.OperatorAddress
if _, err := sdk.AccAddressFromBech32(addr); err != nil {
return errorsmod.Wrapf(
ErrInvalidGenesisData,
"invalid operator address %s: %s", record.OperatorAddress, err,
)
}
if _, found := operatorRecords[addr]; found {
return errorsmod.Wrapf(
ErrInvalidGenesisData,
"duplicate operator record for operator %s", addr,
)
}
operatorRecords[addr] = struct{}{}
if _, opFound := operators[addr]; !opFound {
return errorsmod.Wrapf(
ErrInvalidGenesisData,
"operator record for un-registered operator %s", addr,
)
}
for _, chain := range record.Chains {
consensusKeyString := chain.ConsensusKey
if _, found := keysByChainID[chain.ChainID]; !found {
keysByChainID[chain.ChainID] = make(map[string]struct{})
}
if _, err := HexStringToPubKey(consensusKeyString); err != nil {
return errorsmod.Wrapf(
ErrInvalidGenesisData,
"invalid consensus key for operator %s: %s", addr, err,
)
}
// within a chain id, there should not be duplicate consensus keys
if _, found := keysByChainID[chain.ChainID][consensusKeyString]; found {
return errorsmod.Wrapf(
ErrInvalidGenesisData,
"duplicate consensus key for operator %s on chain %s", addr, chain.ChainID,
)
}
keysByChainID[chain.ChainID][consensusKeyString] = struct{}{}
}
}
// i do not know that chain id here, so i cannot check whether
// each registered operator has a key defined for the chain id. but i can:
// ensure that there is a consensus key record (of any chain id) for each operator.
// for bootstrapping, this is bound to happen since the operator registration is contingent
// on the operator having a consensus key for the chain id. however, in the future,
// it may be possible for an operator to opt into an AVS which does not have a consensus
// key requirement, so this check could be removed if we set up the Export case. but i
// think it is better to keep it for now.
if len(operators) != len(operatorRecords) {
// operatorRecords is always a subset of operators, since we do not add any operator
// to operatorRecords unless it is in operators.
return errorsmod.Wrapf(
ErrInvalidGenesisData,
"operator addresses in operators and operator records do not match",
)
}
return nil
}
Loading

0 comments on commit b310aa8

Please sign in to comment.