Validator dedup on identity and bls keys (#2883)

* Remove same-validator redelegation feature which is useless and confusing

* Fix comments

* Detect duplicate name or identity

* check bls dups

* Remove name dedup as it's risky

* equal rather than compare on address

* Add better error content

* Fix travis
pull/2884/head
Rongjian Lan 5 years ago committed by GitHub
parent d4b8c11a8c
commit 044c2dcd4c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 3
      core/evm.go
  2. 58
      core/state_transition.go

@ -41,6 +41,9 @@ type ChainContext interface {
// ReadValidatorSnapshot returns the snapshot of validator at the beginning of current epoch. // ReadValidatorSnapshot returns the snapshot of validator at the beginning of current epoch.
ReadValidatorSnapshot(common.Address) (*staking.ValidatorSnapshot, error) ReadValidatorSnapshot(common.Address) (*staking.ValidatorSnapshot, error)
// ReadValidatorList returns the list of all validators
ReadValidatorList() ([]common.Address, error)
} }
// NewEVMContext creates a new context for use in the EVM. // NewEVMContext creates a new context for use in the EVM.

@ -17,9 +17,12 @@
package core package core
import ( import (
"bytes"
"math" "math"
"math/big" "math/big"
"github.com/harmony-one/harmony/shard"
staking2 "github.com/harmony-one/harmony/staking" staking2 "github.com/harmony-one/harmony/staking"
"github.com/harmony-one/harmony/staking/network" "github.com/harmony-one/harmony/staking/network"
@ -44,6 +47,8 @@ var (
errCommissionRateChangeTooHigh = errors.New("commission rate can not be higher than maximum commission rate") errCommissionRateChangeTooHigh = errors.New("commission rate can not be higher than maximum commission rate")
errNoRewardsToCollect = errors.New("no rewards to collect") errNoRewardsToCollect = errors.New("no rewards to collect")
errNegativeAmount = errors.New("amount can not be negative") errNegativeAmount = errors.New("amount can not be negative")
errDupIdentity = errors.New("validator identity exists")
errDupBlsKey = errors.New("BLS key exists")
) )
/* /*
@ -384,9 +389,52 @@ func (st *StateTransition) StakingTransitionDb() (usedGas uint64, err error) {
return st.gasUsed(), err return st.gasUsed(), err
} }
func (st *StateTransition) checkDuplicateFields(validator common.Address, identity string, blsKeys []shard.BLSPublicKey) error {
addrs, err := st.bc.ReadValidatorList()
if err != nil {
return err
}
checkIdentity := identity != ""
checkBlsKeys := len(blsKeys) != 0
blsKeyMap := map[shard.BLSPublicKey]struct{}{}
for _, key := range blsKeys {
blsKeyMap[key] = struct{}{}
}
for _, addr := range addrs {
if !bytes.Equal(validator.Bytes(), addr.Bytes()) {
wrapper, err := st.state.ValidatorWrapperCopy(addr)
if err != nil {
return err
}
if checkIdentity && wrapper.Identity == identity {
return errors.Wrapf(errDupIdentity, "duplicate identity %s", identity)
}
if checkBlsKeys {
for _, existingKey := range wrapper.SlotPubKeys {
if _, ok := blsKeyMap[existingKey]; ok {
return errors.Wrapf(errDupBlsKey, "duplicate bls key %x", existingKey)
}
}
}
}
}
return nil
}
func (st *StateTransition) verifyAndApplyCreateValidatorTx( func (st *StateTransition) verifyAndApplyCreateValidatorTx(
createValidator *staking.CreateValidator, blockNum *big.Int, createValidator *staking.CreateValidator, blockNum *big.Int,
) error { ) error {
if err := st.checkDuplicateFields(
createValidator.ValidatorAddress,
createValidator.Identity,
createValidator.SlotPubKeys); err != nil {
return err
}
wrapper, err := VerifyAndCreateValidatorFromMsg( wrapper, err := VerifyAndCreateValidatorFromMsg(
st.state, st.evm.EpochNumber, blockNum, createValidator, st.state, st.evm.EpochNumber, blockNum, createValidator,
) )
@ -404,6 +452,16 @@ func (st *StateTransition) verifyAndApplyCreateValidatorTx(
func (st *StateTransition) verifyAndApplyEditValidatorTx( func (st *StateTransition) verifyAndApplyEditValidatorTx(
editValidator *staking.EditValidator, blockNum *big.Int, editValidator *staking.EditValidator, blockNum *big.Int,
) error { ) error {
newBlsKeys := []shard.BLSPublicKey{}
if editValidator.SlotKeyToAdd != nil {
newBlsKeys = append(newBlsKeys, *editValidator.SlotKeyToAdd)
}
if err := st.checkDuplicateFields(
editValidator.ValidatorAddress,
editValidator.Identity,
newBlsKeys); err != nil {
return err
}
wrapper, err := VerifyAndEditValidatorFromMsg( wrapper, err := VerifyAndEditValidatorFromMsg(
st.state, st.bc, st.evm.EpochNumber, blockNum, editValidator, st.state, st.bc, st.evm.EpochNumber, blockNum, editValidator,
) )

Loading…
Cancel
Save