Skip to content

Commit

Permalink
feat: Adds validator qgb checks (#137)
Browse files Browse the repository at this point in the history
* first pass on tests fixes

* fixes the rest of unit tests

* remove unnecessary comments

* uses default eth address when starting sim network

* cosmetics

* comments failing test

* comments failing test

* adds orchestrator/ethereum address checks for validators when creating and editing

* uses correct error codes for eth/orch address errors

* uncomments test and fixes it from commit 434b308

* adds zero eth address check when creating/updating validator

* attempts to fix duplicate eth address in sim network

* revert squashed changes

* uses unwrapped context for msg_server orch/eth validation

* increase DefaultGenTxGas to accomodate new qgb validator changes

* scaffolds an ethereum address from orchestrator address in staking simulation to have a deterministic way of creating it

* fix eth address creation from orch address in operations

* increase DefaultGenTxGas

* increase DefaultGenTxGas

* simpler way of creating an eth address from orch address in operations
  • Loading branch information
rach-id authored May 9, 2022
1 parent f5d3545 commit d9dc2cd
Show file tree
Hide file tree
Showing 7 changed files with 114 additions and 49 deletions.
2 changes: 1 addition & 1 deletion simapp/helpers/test_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import (

// SimAppChainID hardcoded chainID for simulation
const (
DefaultGenTxGas = 1000000
DefaultGenTxGas = 2600000 // An increase is needed when adding checks to staking/msg_server.go
SimAppChainID = "simulation-app"
)

Expand Down
3 changes: 1 addition & 2 deletions simapp/simd/cmd/testnet.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,7 @@ Example:

return InitTestnet(
clientCtx, cmd, config, mbm, genBalIterator, outputDir, chainID, minGasPrices,
nodeDirPrefix, nodeDaemonHome, startingIPAddress, keyringBackend, algo,
numValidators,
nodeDirPrefix, nodeDaemonHome, startingIPAddress, keyringBackend, algo, numValidators,
)
},
}
Expand Down
48 changes: 41 additions & 7 deletions x/staking/keeper/msg_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,17 +70,17 @@ func (k msgServer) CreateValidator(goCtx context.Context, msg *types.MsgCreateVa
}
}

orchAddr, err := sdk.AccAddressFromBech32(msg.Orchestrator)
orchAddr, err := k.validateOrchestratorAddress(ctx, msg.Orchestrator)
if err != nil {
return nil, err
}

evmAddr, err := types.NewEthAddress(msg.EthAddress)
evmAddr, err := k.validateEthereumAddress(ctx, msg.EthAddress)
if err != nil {
return nil, err
}

validator, err := types.NewValidator(valAddr, pk, msg.Description, orchAddr, *evmAddr)
validator, err := types.NewValidator(valAddr, pk, msg.Description, orchAddr, evmAddr)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -177,14 +177,22 @@ func (k msgServer) EditValidator(goCtx context.Context, msg *types.MsgEditValida
validator.MinSelfDelegation = (*msg.MinSelfDelegation)
}

if msg.EthAddress != "" {
validator.EthAddress = msg.EthAddress
}

if msg.Orchestrator != "" {
_, err := k.validateOrchestratorAddress(ctx, msg.Orchestrator)
if err != nil {
return nil, err
}
validator.Orchestrator = msg.Orchestrator
}

if msg.EthAddress != "" {
_, err := k.validateEthereumAddress(ctx, msg.EthAddress)
if err != nil {
return nil, err
}
validator.EthAddress = msg.EthAddress
}

k.SetValidator(ctx, validator)

ctx.EventManager().EmitEvents(sdk.Events{
Expand Down Expand Up @@ -390,3 +398,29 @@ func (k msgServer) Undelegate(goCtx context.Context, msg *types.MsgUndelegate) (
CompletionTime: completionTime,
}, nil
}

func (k msgServer) validateEthereumAddress(ctx sdk.Context, ethAddr string) (types.EthAddress, error) {
evmAddr, err := types.NewEthAddress(ethAddr)
if err != nil {
return types.EthAddress{}, err
}
if evmAddr.GetAddress() == types.EthZeroAddress {
return types.EthAddress{}, types.ErrValidatorEthereumZeroAddress
}
if _, found := k.GetValidatorByEthereumAddress(ctx, *evmAddr); found {
return types.EthAddress{}, types.ErrValidatorEthereumAddressExists
}
return *evmAddr, nil
}

func (k msgServer) validateOrchestratorAddress(ctx sdk.Context, orchAddr string) (sdk.AccAddress, error) {
addr, err := sdk.AccAddressFromBech32(orchAddr)
if err != nil {
return sdk.AccAddress{}, err
}
// FIXME should we add the zero accAddr check?
if _, found := k.GetValidatorByOrchestratorAddress(ctx, addr); found {
return sdk.AccAddress{}, types.ErrValidatorOrchestratorAddressExists
}
return addr, nil
}
26 changes: 26 additions & 0 deletions x/staking/keeper/validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,32 @@ func (k Keeper) mustGetValidatorByConsAddr(ctx sdk.Context, consAddr sdk.ConsAdd
return validator
}

func (k Keeper) GetValidatorByOrchestratorAddress(ctx sdk.Context, orch sdk.AccAddress) (types.Validator, bool) {
// TODO optimise these queries and even add grpc queries for them.
// Issue: https://github.com/celestiaorg/cosmos-sdk/issues/129
validators := k.GetAllValidators(ctx)
for _, val := range validators {
if val.Orchestrator == orch.String() {
return val, true
}
}

return types.Validator{}, false
}

func (k Keeper) GetValidatorByEthereumAddress(ctx sdk.Context, eth types.EthAddress) (types.Validator, bool) {
// TODO optimise these queries and even add grpc queries for them.
// Issue: https://github.com/celestiaorg/cosmos-sdk/issues/129
validators := k.GetAllValidators(ctx)
for _, val := range validators {
if val.EthAddress == eth.GetAddress() {
return val, true
}
}

return types.Validator{}, false
}

// set the main record holding validator details
func (k Keeper) SetValidator(ctx sdk.Context, validator types.Validator) {
store := ctx.KVStore(k.storeKey)
Expand Down
4 changes: 3 additions & 1 deletion x/staking/simulation/operations.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,8 +146,10 @@ func SimulateMsgCreateValidator(ak types.AccountKeeper, bk types.BankKeeper, k k
simtypes.RandomDecAmount(r, maxCommission),
)

ethAddr, _ := types.NewEthAddress("0x91DEd26b5f38B065FC0204c7929Da6b2A21277Cd")
orchAddr := simAccount.Address
// create an Ethereum address from the orchestrator address
// this is mainly to have a deterministic way of generating an Ethereum address on every run // to have a long enough bytes array
ethAddr, _ := types.NewEthAddress("0x" + fmt.Sprintf("%X", simAccount.Address.Bytes()))

msg, err := types.NewMsgCreateValidator(address, simAccount.ConsKey.PubKey(), selfDelegation, description, commission, sdk.OneInt(), orchAddr, *ethAddr)
if err != nil {
Expand Down
79 changes: 41 additions & 38 deletions x/staking/types/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,42 +11,45 @@ import (
//
// REF: https://github.com/cosmos/cosmos-sdk/issues/5450
var (
ErrEmptyValidatorAddr = sdkerrors.Register(ModuleName, 2, "empty validator address")
ErrNoValidatorFound = sdkerrors.Register(ModuleName, 3, "validator does not exist")
ErrValidatorOwnerExists = sdkerrors.Register(ModuleName, 4, "validator already exist for this operator address; must use new validator operator address")
ErrValidatorPubKeyExists = sdkerrors.Register(ModuleName, 5, "validator already exist for this pubkey; must use new validator pubkey")
ErrValidatorPubKeyTypeNotSupported = sdkerrors.Register(ModuleName, 6, "validator pubkey type is not supported")
ErrValidatorJailed = sdkerrors.Register(ModuleName, 7, "validator for this address is currently jailed")
ErrBadRemoveValidator = sdkerrors.Register(ModuleName, 8, "failed to remove validator")
ErrCommissionNegative = sdkerrors.Register(ModuleName, 9, "commission must be positive")
ErrCommissionHuge = sdkerrors.Register(ModuleName, 10, "commission cannot be more than 100%")
ErrCommissionGTMaxRate = sdkerrors.Register(ModuleName, 11, "commission cannot be more than the max rate")
ErrCommissionUpdateTime = sdkerrors.Register(ModuleName, 12, "commission cannot be changed more than once in 24h")
ErrCommissionChangeRateNegative = sdkerrors.Register(ModuleName, 13, "commission change rate must be positive")
ErrCommissionChangeRateGTMaxRate = sdkerrors.Register(ModuleName, 14, "commission change rate cannot be more than the max rate")
ErrCommissionGTMaxChangeRate = sdkerrors.Register(ModuleName, 15, "commission cannot be changed more than max change rate")
ErrSelfDelegationBelowMinimum = sdkerrors.Register(ModuleName, 16, "validator's self delegation must be greater than their minimum self delegation")
ErrMinSelfDelegationDecreased = sdkerrors.Register(ModuleName, 17, "minimum self delegation cannot be decrease")
ErrEmptyDelegatorAddr = sdkerrors.Register(ModuleName, 18, "empty delegator address")
ErrNoDelegation = sdkerrors.Register(ModuleName, 19, "no delegation for (address, validator) tuple")
ErrBadDelegatorAddr = sdkerrors.Register(ModuleName, 20, "delegator does not exist with address")
ErrNoDelegatorForAddress = sdkerrors.Register(ModuleName, 21, "delegator does not contain delegation")
ErrInsufficientShares = sdkerrors.Register(ModuleName, 22, "insufficient delegation shares")
ErrDelegationValidatorEmpty = sdkerrors.Register(ModuleName, 23, "cannot delegate to an empty validator")
ErrNotEnoughDelegationShares = sdkerrors.Register(ModuleName, 24, "not enough delegation shares")
ErrNotMature = sdkerrors.Register(ModuleName, 25, "entry not mature")
ErrNoUnbondingDelegation = sdkerrors.Register(ModuleName, 26, "no unbonding delegation found")
ErrMaxUnbondingDelegationEntries = sdkerrors.Register(ModuleName, 27, "too many unbonding delegation entries for (delegator, validator) tuple")
ErrNoRedelegation = sdkerrors.Register(ModuleName, 28, "no redelegation found")
ErrSelfRedelegation = sdkerrors.Register(ModuleName, 29, "cannot redelegate to the same validator")
ErrTinyRedelegationAmount = sdkerrors.Register(ModuleName, 30, "too few tokens to redelegate (truncates to zero tokens)")
ErrBadRedelegationDst = sdkerrors.Register(ModuleName, 31, "redelegation destination validator not found")
ErrTransitiveRedelegation = sdkerrors.Register(ModuleName, 32, "redelegation to this validator already in progress; first redelegation to this validator must complete before next redelegation")
ErrMaxRedelegationEntries = sdkerrors.Register(ModuleName, 33, "too many redelegation entries for (delegator, src-validator, dst-validator) tuple")
ErrDelegatorShareExRateInvalid = sdkerrors.Register(ModuleName, 34, "cannot delegate to validators with invalid (zero) ex-rate")
ErrBothShareMsgsGiven = sdkerrors.Register(ModuleName, 35, "both shares amount and shares percent provided")
ErrNeitherShareMsgsGiven = sdkerrors.Register(ModuleName, 36, "neither shares amount nor shares percent provided")
ErrInvalidHistoricalInfo = sdkerrors.Register(ModuleName, 37, "invalid historical info")
ErrNoHistoricalInfo = sdkerrors.Register(ModuleName, 38, "no historical info found")
ErrEmptyValidatorPubKey = sdkerrors.Register(ModuleName, 39, "empty validator public key")
ErrEmptyValidatorAddr = sdkerrors.Register(ModuleName, 2, "empty validator address")
ErrNoValidatorFound = sdkerrors.Register(ModuleName, 3, "validator does not exist")
ErrValidatorOwnerExists = sdkerrors.Register(ModuleName, 4, "validator already exist for this operator address; must use new validator operator address")
ErrValidatorPubKeyExists = sdkerrors.Register(ModuleName, 5, "validator already exist for this pubkey; must use new validator pubkey")
ErrValidatorPubKeyTypeNotSupported = sdkerrors.Register(ModuleName, 6, "validator pubkey type is not supported")
ErrValidatorJailed = sdkerrors.Register(ModuleName, 7, "validator for this address is currently jailed")
ErrBadRemoveValidator = sdkerrors.Register(ModuleName, 8, "failed to remove validator")
ErrCommissionNegative = sdkerrors.Register(ModuleName, 9, "commission must be positive")
ErrCommissionHuge = sdkerrors.Register(ModuleName, 10, "commission cannot be more than 100%")
ErrCommissionGTMaxRate = sdkerrors.Register(ModuleName, 11, "commission cannot be more than the max rate")
ErrCommissionUpdateTime = sdkerrors.Register(ModuleName, 12, "commission cannot be changed more than once in 24h")
ErrCommissionChangeRateNegative = sdkerrors.Register(ModuleName, 13, "commission change rate must be positive")
ErrCommissionChangeRateGTMaxRate = sdkerrors.Register(ModuleName, 14, "commission change rate cannot be more than the max rate")
ErrCommissionGTMaxChangeRate = sdkerrors.Register(ModuleName, 15, "commission cannot be changed more than max change rate")
ErrSelfDelegationBelowMinimum = sdkerrors.Register(ModuleName, 16, "validator's self delegation must be greater than their minimum self delegation")
ErrMinSelfDelegationDecreased = sdkerrors.Register(ModuleName, 17, "minimum self delegation cannot be decrease")
ErrEmptyDelegatorAddr = sdkerrors.Register(ModuleName, 18, "empty delegator address")
ErrNoDelegation = sdkerrors.Register(ModuleName, 19, "no delegation for (address, validator) tuple")
ErrBadDelegatorAddr = sdkerrors.Register(ModuleName, 20, "delegator does not exist with address")
ErrNoDelegatorForAddress = sdkerrors.Register(ModuleName, 21, "delegator does not contain delegation")
ErrInsufficientShares = sdkerrors.Register(ModuleName, 22, "insufficient delegation shares")
ErrDelegationValidatorEmpty = sdkerrors.Register(ModuleName, 23, "cannot delegate to an empty validator")
ErrNotEnoughDelegationShares = sdkerrors.Register(ModuleName, 24, "not enough delegation shares")
ErrNotMature = sdkerrors.Register(ModuleName, 25, "entry not mature")
ErrNoUnbondingDelegation = sdkerrors.Register(ModuleName, 26, "no unbonding delegation found")
ErrMaxUnbondingDelegationEntries = sdkerrors.Register(ModuleName, 27, "too many unbonding delegation entries for (delegator, validator) tuple")
ErrNoRedelegation = sdkerrors.Register(ModuleName, 28, "no redelegation found")
ErrSelfRedelegation = sdkerrors.Register(ModuleName, 29, "cannot redelegate to the same validator")
ErrTinyRedelegationAmount = sdkerrors.Register(ModuleName, 30, "too few tokens to redelegate (truncates to zero tokens)")
ErrBadRedelegationDst = sdkerrors.Register(ModuleName, 31, "redelegation destination validator not found")
ErrTransitiveRedelegation = sdkerrors.Register(ModuleName, 32, "redelegation to this validator already in progress; first redelegation to this validator must complete before next redelegation")
ErrMaxRedelegationEntries = sdkerrors.Register(ModuleName, 33, "too many redelegation entries for (delegator, src-validator, dst-validator) tuple")
ErrDelegatorShareExRateInvalid = sdkerrors.Register(ModuleName, 34, "cannot delegate to validators with invalid (zero) ex-rate")
ErrBothShareMsgsGiven = sdkerrors.Register(ModuleName, 35, "both shares amount and shares percent provided")
ErrNeitherShareMsgsGiven = sdkerrors.Register(ModuleName, 36, "neither shares amount nor shares percent provided")
ErrInvalidHistoricalInfo = sdkerrors.Register(ModuleName, 37, "invalid historical info")
ErrNoHistoricalInfo = sdkerrors.Register(ModuleName, 38, "no historical info found")
ErrEmptyValidatorPubKey = sdkerrors.Register(ModuleName, 39, "empty validator public key")
ErrValidatorOrchestratorAddressExists = sdkerrors.Register(ModuleName, 40, "validator already exist for this orchestrator address; must use new validator orchestrator address")
ErrValidatorEthereumAddressExists = sdkerrors.Register(ModuleName, 41, "validator already exist for this ethereum address; must use new validator ethereum address")
ErrValidatorEthereumZeroAddress = sdkerrors.Register(ModuleName, 42, "cannot use zero address for ethereum address; must use a non zero validator ethereum address")
)
1 change: 1 addition & 0 deletions x/staking/types/ethereum.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
const (
// ETHContractAddressLen is the length of contract address strings
ETHContractAddressLen = 42
EthZeroAddress = "0x0000000000000000000000000000000000000000"
)

// EthAddress Regular EthAddress
Expand Down

0 comments on commit d9dc2cd

Please sign in to comment.