Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Adds validator qgb checks #137

Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
0e9a2db
first pass on tests fixes
rach-id May 3, 2022
49fadc4
fixes the rest of unit tests
rach-id May 4, 2022
c3fe6aa
remove unnecessary comments
rach-id May 5, 2022
168a6fe
uses default eth address when starting sim network
rach-id May 5, 2022
af04769
cosmetics
rach-id May 5, 2022
bbf69d4
comments failing test
rach-id May 5, 2022
a910030
comments failing test
rach-id May 5, 2022
756f041
adds orchestrator/ethereum address checks for validators when creatin…
rach-id May 5, 2022
e70bbd8
uses correct error codes for eth/orch address errors
rach-id May 5, 2022
f53f9d6
uncomments test and fixes it from commit 434b308ce4dc968070c47952d948…
rach-id May 5, 2022
edf6b87
Merge branch 'fix_tests_after_qgb_changes' into adds_validator_qgb_ch…
rach-id May 5, 2022
8568eac
adds zero eth address check when creating/updating validator
rach-id May 6, 2022
b6fbf3a
attempts to fix duplicate eth address in sim network
rach-id May 6, 2022
a10f734
Merge branch 'rachid/orchestrator-address' into adds_validator_qgb_ch…
rach-id May 6, 2022
3dbbe6c
revert squashed changes
rach-id May 6, 2022
a547c1b
uses unwrapped context for msg_server orch/eth validation
rach-id May 7, 2022
03e8b0c
increase DefaultGenTxGas to accomodate new qgb validator changes
rach-id May 9, 2022
fd79550
scaffolds an ethereum address from orchestrator address in staking si…
rach-id May 9, 2022
a799b09
fix eth address creation from orch address in operations
rach-id May 9, 2022
fa29549
increase DefaultGenTxGas
rach-id May 9, 2022
308853d
increase DefaultGenTxGas
rach-id May 9, 2022
176d296
simpler way of creating an eth address from orch address in operations
rach-id May 9, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you sure you want to error when a validator exists if you're trying to edit it?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't want to have duplicate orchestrator or Ethereum address. If some other validatore has that address, we shouldnt continue. No?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For inserting a new validator, yes. But editing a validator (not sure what that even means?) requires the validator to exist prior to being edited, no?

Copy link
Member Author

@rach-id rach-id May 9, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We look first if the validator exists by its address. Then, we start checking if the new orchestrator address has been given to some other validator.
So, that one is looking for a validator by orchestrator address. If any other validator has that orchestrator address, we stop.
Or I am missing something

Copy link
Member

@evan-forbes evan-forbes May 9, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this makes sense, we want to throw an error if someone is trying to update their vaildator with an invalid orchestrator address. If we don't, then we won't be able to verify their attestations, and while it wouldn't be protocol breaking, I think it would be a terrible UX, as they'd have to debug why they can't submit signatures.

we're also checking that the validator exists on line 143

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
6 changes: 5 additions & 1 deletion x/staking/simulation/operations.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,8 +146,12 @@ 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
bytesOrchAddressWithoutPrefix := simAccount.Address.Bytes()[len([]byte(sdk.Bech32MainPrefix)):]
doubleOrchAddressBytes := append(bytesOrchAddressWithoutPrefix, bytesOrchAddressWithoutPrefix...) // to have a long enough bytes array
ethAddr, _ := types.NewEthAddress("0x" + fmt.Sprintf("%X", doubleOrchAddressBytes[:(types.ETHContractAddressLen/2)-1]))

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