refactor check duplicates to staking_verifier (#2898)

pull/2902/head
Ganesha Upadhyaya 5 years ago committed by GitHub
parent ab9f3f8e0b
commit 6bc602194c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 65
      core/staking_verifier.go
  2. 213
      core/staking_verifier_test.go
  3. 58
      core/state_transition.go
  4. 7
      core/tx_pool.go
  5. 24
      core/tx_pool_test.go
  6. 23
      test/chain/reward/main.go

@ -23,6 +23,46 @@ var (
errBlockNumMissing = errors.New("no block number was provided")
)
func checkDuplicateFields(
bc ChainContext, state vm.StateDB,
validator common.Address, identity string, blsKeys []shard.BLSPublicKey,
) error {
addrs, err := 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 := 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
}
// TODO: add unit tests to check staking msg verification
// VerifyAndCreateValidatorFromMsg verifies the create validator message using
@ -31,12 +71,14 @@ var (
//
// Note that this function never updates the stateDB, it only reads from stateDB.
func VerifyAndCreateValidatorFromMsg(
stateDB vm.StateDB, epoch *big.Int, blockNum *big.Int, msg *staking.CreateValidator,
stateDB vm.StateDB, chainContext ChainContext, epoch *big.Int, blockNum *big.Int, msg *staking.CreateValidator,
) (*staking.ValidatorWrapper, error) {
if stateDB == nil {
return nil, errStateDBIsMissing
}
if chainContext == nil {
return nil, errChainContextMissing
}
if epoch == nil {
return nil, errEpochMissing
}
@ -51,6 +93,13 @@ func VerifyAndCreateValidatorFromMsg(
errValidatorExist, common2.MustAddressToBech32(msg.ValidatorAddress),
)
}
if err := checkDuplicateFields(
chainContext, stateDB,
msg.ValidatorAddress,
msg.Identity,
msg.SlotPubKeys); err != nil {
return nil, err
}
if !CanTransfer(stateDB, msg.ValidatorAddress, msg.Amount) {
return nil, errInsufficientBalanceForStake
}
@ -82,7 +131,6 @@ func VerifyAndEditValidatorFromMsg(
stateDB vm.StateDB, chainContext ChainContext,
epoch, blockNum *big.Int, msg *staking.EditValidator,
) (*staking.ValidatorWrapper, error) {
if stateDB == nil {
return nil, errStateDBIsMissing
}
@ -95,6 +143,17 @@ func VerifyAndEditValidatorFromMsg(
if !stateDB.IsValidator(msg.ValidatorAddress) {
return nil, errValidatorNotExist
}
newBlsKeys := []shard.BLSPublicKey{}
if msg.SlotKeyToAdd != nil {
newBlsKeys = append(newBlsKeys, *msg.SlotKeyToAdd)
}
if err := checkDuplicateFields(
chainContext, stateDB,
msg.ValidatorAddress,
msg.Identity,
newBlsKeys); err != nil {
return nil, err
}
wrapper, err := stateDB.ValidatorWrapperCopy(msg.ValidatorAddress)
if err != nil {
return nil, err

@ -6,11 +6,17 @@ import (
"testing"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/harmony-one/bls/ffi/go/bls"
blockfactory "github.com/harmony-one/harmony/block/factory"
"github.com/harmony-one/harmony/core/state"
"github.com/harmony-one/harmony/core/vm"
"github.com/harmony-one/harmony/crypto/hash"
chain2 "github.com/harmony-one/harmony/internal/chain"
common2 "github.com/harmony-one/harmony/internal/common"
"github.com/harmony-one/harmony/internal/params"
"github.com/harmony-one/harmony/numeric"
"github.com/harmony-one/harmony/shard"
staking "github.com/harmony-one/harmony/staking/types"
@ -23,6 +29,25 @@ var (
twelveK = new(big.Int).Mul(big.NewInt(12000), big.NewInt(1e18))
)
func createChain(database *ethdb.MemDatabase) *BlockChain {
key, _ := crypto.GenerateKey()
gspec := Genesis{
Config: params.TestChainConfig,
Factory: blockfactory.ForTest,
Alloc: GenesisAlloc{
crypto.PubkeyToAddress(key.PublicKey): {
Balance: big.NewInt(8e18),
},
},
GasLimit: 1e18,
ShardID: 0,
}
genesis := gspec.MustCommit(database)
_ = genesis
chain, _ := NewBlockChain(database, nil, gspec.Config, chain2.Engine, vm.Config{}, nil)
return chain
}
func generateBLSKeySigPair() (shard.BLSPublicKey, shard.BLSSignature) {
p := &bls.PublicKey{}
p.DeserializeHexStr(testBLSPubKey)
@ -75,11 +100,13 @@ func createValidator() *staking.CreateValidator {
// Test CV1: create validator
func TestCV1(t *testing.T) {
statedb, _ := state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase()))
database := ethdb.NewMemDatabase()
statedb, _ := state.New(common.Hash{}, state.NewDatabase(database))
chain := createChain(database)
msg := createValidator()
statedb.AddBalance(msg.ValidatorAddress, tenK)
if _, err := VerifyAndCreateValidatorFromMsg(
statedb, postStakingEpoch, big.NewInt(0), msg,
statedb, chain, postStakingEpoch, big.NewInt(0), msg,
); err != nil {
t.Error("expected", nil, "got", err)
}
@ -87,18 +114,20 @@ func TestCV1(t *testing.T) {
// Test CV3: validator already exists
func TestCV3(t *testing.T) {
statedb, _ := state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase()))
database := ethdb.NewMemDatabase()
statedb, _ := state.New(common.Hash{}, state.NewDatabase(database))
chain := createChain(database)
msg := createValidator()
statedb.AddBalance(msg.ValidatorAddress, tenK)
if _, err := VerifyAndCreateValidatorFromMsg(
statedb, postStakingEpoch, big.NewInt(0), msg,
statedb, chain, postStakingEpoch, big.NewInt(0), msg,
); err != nil {
t.Error("expected", nil, "got", err)
}
statedb.SetValidatorFlag(msg.ValidatorAddress)
if _, err := VerifyAndCreateValidatorFromMsg(
statedb, postStakingEpoch, big.NewInt(0), msg,
statedb, chain, postStakingEpoch, big.NewInt(0), msg,
); !strings.Contains(err.Error(), errValidatorExist.Error()) {
t.Error("expected", errValidatorExist, "got", err)
}
@ -106,13 +135,15 @@ func TestCV3(t *testing.T) {
// Test CV9: name == 140 characters
func TestCV9(t *testing.T) {
statedb, _ := state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase()))
database := ethdb.NewMemDatabase()
statedb, _ := state.New(common.Hash{}, state.NewDatabase(database))
chain := createChain(database)
msg := createValidator()
// name length: 140 characters
msg.Name = "Helloiwfhwifbwfbcerghveugbviuscbhwiefbcusidbcifwefhgciwefherhbfiwuehfciwiuebfcuyiewfhwieufwiweifhcwefhwefhwidsffevjnononwondqmeofniowfndjowe"
statedb.AddBalance(msg.ValidatorAddress, tenK)
if _, err := VerifyAndCreateValidatorFromMsg(
statedb, postStakingEpoch, big.NewInt(0), msg,
statedb, chain, postStakingEpoch, big.NewInt(0), msg,
); err != nil {
t.Error("expected", nil, "got", err)
}
@ -120,13 +151,15 @@ func TestCV9(t *testing.T) {
// Test CV10: identity == 140 characters
func TestCV10(t *testing.T) {
statedb, _ := state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase()))
database := ethdb.NewMemDatabase()
statedb, _ := state.New(common.Hash{}, state.NewDatabase(database))
chain := createChain(database)
msg := createValidator()
// identity length: 140 characters
msg.Identity = "Helloiwfhwifbwfbcerghveugbviuscbhwiefbcusidbcifwefhgciwefherhbfiwuehfciwiuebfcuyiewfhwieufwiweifhcwefhwefhwidsffevjnononwondqmeofniowfndjowe"
statedb.AddBalance(msg.ValidatorAddress, tenK)
if _, err := VerifyAndCreateValidatorFromMsg(
statedb, postStakingEpoch, big.NewInt(0), msg,
statedb, chain, postStakingEpoch, big.NewInt(0), msg,
); err != nil {
t.Error("expected", nil, "got", err)
}
@ -134,13 +167,15 @@ func TestCV10(t *testing.T) {
// Test CV11: website == 140 characters
func TestCV11(t *testing.T) {
statedb, _ := state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase()))
database := ethdb.NewMemDatabase()
statedb, _ := state.New(common.Hash{}, state.NewDatabase(database))
chain := createChain(database)
msg := createValidator()
// website length: 140 characters
msg.Website = "Helloiwfhwifbwfbcerghveugbviuscbhwiefbcusidbcifwefhgciwefherhbfiwuehfciwiuebfcuyiewfhwieufwiweifhcwefhwefhwidsffevjnononwondqmeofniowfndjowe"
statedb.AddBalance(msg.ValidatorAddress, tenK)
if _, err := VerifyAndCreateValidatorFromMsg(
statedb, postStakingEpoch, big.NewInt(0), msg,
statedb, chain, postStakingEpoch, big.NewInt(0), msg,
); err != nil {
t.Error("expected", nil, "got", err)
}
@ -148,13 +183,15 @@ func TestCV11(t *testing.T) {
// Test CV12: security == 140 characters
func TestCV12(t *testing.T) {
statedb, _ := state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase()))
database := ethdb.NewMemDatabase()
statedb, _ := state.New(common.Hash{}, state.NewDatabase(database))
chain := createChain(database)
msg := createValidator()
// security contact length: 140 characters
msg.SecurityContact = "Helloiwfhwifbwfbcerghveugbviuscbhwiefbcusidbcifwefhgciwefherhbfiwuehfciwiuebfcuyiewfhwieufwiweifhcwefhwefhwidsffevjnononwondqmeofniowfndjowe"
statedb.AddBalance(msg.ValidatorAddress, tenK)
if _, err := VerifyAndCreateValidatorFromMsg(
statedb, postStakingEpoch, big.NewInt(0), msg,
statedb, chain, postStakingEpoch, big.NewInt(0), msg,
); err != nil {
t.Error("expected", nil, "got", err)
}
@ -162,13 +199,15 @@ func TestCV12(t *testing.T) {
// Test CV13: details == 280 characters
func TestCV13(t *testing.T) {
statedb, _ := state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase()))
database := ethdb.NewMemDatabase()
statedb, _ := state.New(common.Hash{}, state.NewDatabase(database))
chain := createChain(database)
msg := createValidator()
// details length: 280 characters
msg.Details = "HelloiwfhwifbwfbcerghveugbviuscbhwiefbcusidbcifwefhgciwefherhbfiwuehfciwiuebfcuyiewfhwieufwiweifhcwefhwefhwidsffevjnononwondqmeofniowfndjoweHlloiwfhwifbwfbcerghveugbviuscbhwiefbcusidbcifwefhgciwefherhbfiwuehfciwiuedbfcuyiewfhwieufwiweifhcwefhwefhwidsffevjnononwondqmeofniowfndjowe"
statedb.AddBalance(msg.ValidatorAddress, tenK)
if _, err := VerifyAndCreateValidatorFromMsg(
statedb, postStakingEpoch, big.NewInt(0), msg,
statedb, chain, postStakingEpoch, big.NewInt(0), msg,
); err != nil {
t.Error("expected", nil, "got", err)
}
@ -176,14 +215,16 @@ func TestCV13(t *testing.T) {
// Test CV14: commission rate <= max rate & max change rate <= max rate
func TestCV14(t *testing.T) {
statedb, _ := state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase()))
database := ethdb.NewMemDatabase()
statedb, _ := state.New(common.Hash{}, state.NewDatabase(database))
chain := createChain(database)
msg := createValidator()
statedb.AddBalance(msg.ValidatorAddress, tenK)
// commission rate == max rate && max change rate == max rate
msg.CommissionRates.Rate, _ = numeric.NewDecFromStr("0.5")
msg.CommissionRates.MaxChangeRate, _ = numeric.NewDecFromStr("0.5")
if _, err := VerifyAndCreateValidatorFromMsg(
statedb, postStakingEpoch, big.NewInt(0), msg,
statedb, chain, postStakingEpoch, big.NewInt(0), msg,
); err != nil {
t.Error("expected", nil, "got", err)
}
@ -191,13 +232,15 @@ func TestCV14(t *testing.T) {
// Test CV15: commission rate > max rate
func TestCV15(t *testing.T) {
statedb, _ := state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase()))
database := ethdb.NewMemDatabase()
statedb, _ := state.New(common.Hash{}, state.NewDatabase(database))
chain := createChain(database)
msg := createValidator()
statedb.AddBalance(msg.ValidatorAddress, tenK)
// commission rate: 0.6 > max rate: 0.5
msg.CommissionRates.Rate, _ = numeric.NewDecFromStr("0.6")
if _, err := VerifyAndCreateValidatorFromMsg(
statedb, postStakingEpoch, big.NewInt(0), msg,
statedb, chain, postStakingEpoch, big.NewInt(0), msg,
); err == nil {
t.Error("expected", "commission rate and change rate can not be larger than max commission rate", "got", nil)
}
@ -205,13 +248,15 @@ func TestCV15(t *testing.T) {
// Test CV16: max change rate > max rate
func TestCV16(t *testing.T) {
statedb, _ := state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase()))
database := ethdb.NewMemDatabase()
statedb, _ := state.New(common.Hash{}, state.NewDatabase(database))
chain := createChain(database)
msg := createValidator()
statedb.AddBalance(msg.ValidatorAddress, tenK)
// max change rate: 0.6 > max rate: 0.5
msg.CommissionRates.MaxChangeRate, _ = numeric.NewDecFromStr("0.6")
if _, err := VerifyAndCreateValidatorFromMsg(
statedb, postStakingEpoch, big.NewInt(0), msg,
statedb, chain, postStakingEpoch, big.NewInt(0), msg,
); err == nil {
t.Error("expected", "commission rate and change rate can not be larger than max commission rate", "got", nil)
}
@ -219,13 +264,15 @@ func TestCV16(t *testing.T) {
// Test CV17: max rate == 1
func TestCV17(t *testing.T) {
statedb, _ := state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase()))
database := ethdb.NewMemDatabase()
statedb, _ := state.New(common.Hash{}, state.NewDatabase(database))
chain := createChain(database)
msg := createValidator()
statedb.AddBalance(msg.ValidatorAddress, tenK)
// max rate == 1
msg.CommissionRates.MaxRate, _ = numeric.NewDecFromStr("1")
if _, err := VerifyAndCreateValidatorFromMsg(
statedb, postStakingEpoch, big.NewInt(0), msg,
statedb, chain, postStakingEpoch, big.NewInt(0), msg,
); err != nil {
t.Error("expected", nil, "got", err)
}
@ -233,7 +280,9 @@ func TestCV17(t *testing.T) {
// Test CV18: max rate == 1 && max change rate == 1 && commission rate == 0
func TestCV18(t *testing.T) {
statedb, _ := state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase()))
database := ethdb.NewMemDatabase()
statedb, _ := state.New(common.Hash{}, state.NewDatabase(database))
chain := createChain(database)
msg := createValidator()
statedb.AddBalance(msg.ValidatorAddress, tenK)
// max rate == 1 && max change rate == 1 && commission rate == 0
@ -241,7 +290,7 @@ func TestCV18(t *testing.T) {
msg.CommissionRates.MaxChangeRate, _ = numeric.NewDecFromStr("1")
msg.CommissionRates.Rate, _ = numeric.NewDecFromStr("1")
if _, err := VerifyAndCreateValidatorFromMsg(
statedb, postStakingEpoch, big.NewInt(0), msg,
statedb, chain, postStakingEpoch, big.NewInt(0), msg,
); err != nil {
t.Error("expected", nil, "got", err)
}
@ -249,13 +298,15 @@ func TestCV18(t *testing.T) {
// Test CV19: commission rate == 0
func TestCV19(t *testing.T) {
statedb, _ := state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase()))
database := ethdb.NewMemDatabase()
statedb, _ := state.New(common.Hash{}, state.NewDatabase(database))
chain := createChain(database)
msg := createValidator()
statedb.AddBalance(msg.ValidatorAddress, tenK)
// commission rate == 0
msg.CommissionRates.Rate, _ = numeric.NewDecFromStr("0")
if _, err := VerifyAndCreateValidatorFromMsg(
statedb, postStakingEpoch, big.NewInt(0), msg,
statedb, chain, postStakingEpoch, big.NewInt(0), msg,
); err != nil {
t.Error("expected", nil, "got", err)
}
@ -263,13 +314,15 @@ func TestCV19(t *testing.T) {
// Test CV20: max change rate == 0
func TestCV20(t *testing.T) {
statedb, _ := state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase()))
database := ethdb.NewMemDatabase()
statedb, _ := state.New(common.Hash{}, state.NewDatabase(database))
chain := createChain(database)
msg := createValidator()
statedb.AddBalance(msg.ValidatorAddress, tenK)
// commission rate == 0
msg.CommissionRates.MaxChangeRate, _ = numeric.NewDecFromStr("0")
if _, err := VerifyAndCreateValidatorFromMsg(
statedb, postStakingEpoch, big.NewInt(0), msg,
statedb, chain, postStakingEpoch, big.NewInt(0), msg,
); err != nil {
t.Error("expected", nil, "got", err)
}
@ -277,7 +330,9 @@ func TestCV20(t *testing.T) {
// Test CV21: max change rate == 0 & max rate == 0 & commission rate == 0
func TestCV21(t *testing.T) {
statedb, _ := state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase()))
database := ethdb.NewMemDatabase()
statedb, _ := state.New(common.Hash{}, state.NewDatabase(database))
chain := createChain(database)
msg := createValidator()
statedb.AddBalance(msg.ValidatorAddress, tenK)
// max change rate == 0 & max rate == 0 & commission rate == 0
@ -285,7 +340,7 @@ func TestCV21(t *testing.T) {
msg.CommissionRates.MaxChangeRate, _ = numeric.NewDecFromStr("0")
msg.CommissionRates.Rate, _ = numeric.NewDecFromStr("0")
if _, err := VerifyAndCreateValidatorFromMsg(
statedb, postStakingEpoch, big.NewInt(0), msg,
statedb, chain, postStakingEpoch, big.NewInt(0), msg,
); err != nil {
t.Error("expected", nil, "got", err)
}
@ -293,14 +348,16 @@ func TestCV21(t *testing.T) {
// Test CV22: max change rate == 1 & max rate == 1
func TestCV22(t *testing.T) {
statedb, _ := state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase()))
database := ethdb.NewMemDatabase()
statedb, _ := state.New(common.Hash{}, state.NewDatabase(database))
chain := createChain(database)
msg := createValidator()
statedb.AddBalance(msg.ValidatorAddress, tenK)
// max change rate == 1 & max rate == 1
msg.CommissionRates.MaxRate, _ = numeric.NewDecFromStr("1")
msg.CommissionRates.MaxChangeRate, _ = numeric.NewDecFromStr("1")
if _, err := VerifyAndCreateValidatorFromMsg(
statedb, postStakingEpoch, big.NewInt(0), msg,
statedb, chain, postStakingEpoch, big.NewInt(0), msg,
); err != nil {
t.Error("expected", nil, "got", err)
}
@ -308,13 +365,15 @@ func TestCV22(t *testing.T) {
// Test CV23: commission rate < 0
func TestCV23(t *testing.T) {
statedb, _ := state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase()))
database := ethdb.NewMemDatabase()
statedb, _ := state.New(common.Hash{}, state.NewDatabase(database))
chain := createChain(database)
msg := createValidator()
statedb.AddBalance(msg.ValidatorAddress, tenK)
// commission rate < 0
msg.CommissionRates.Rate, _ = numeric.NewDecFromStr("-0.1")
if _, err := VerifyAndCreateValidatorFromMsg(
statedb, postStakingEpoch, big.NewInt(0), msg,
statedb, chain, postStakingEpoch, big.NewInt(0), msg,
); err == nil {
t.Error("expected", "rate:-0.100000000000000000: commission rate, change rate and max rate should be within 0-100 percent", "got", nil)
}
@ -322,13 +381,15 @@ func TestCV23(t *testing.T) {
// Test CV24: max rate < 0
func TestCV24(t *testing.T) {
statedb, _ := state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase()))
database := ethdb.NewMemDatabase()
statedb, _ := state.New(common.Hash{}, state.NewDatabase(database))
chain := createChain(database)
msg := createValidator()
statedb.AddBalance(msg.ValidatorAddress, tenK)
// max rate < 0
msg.CommissionRates.MaxRate, _ = numeric.NewDecFromStr("-0.001")
if _, err := VerifyAndCreateValidatorFromMsg(
statedb, postStakingEpoch, big.NewInt(0), msg,
statedb, chain, postStakingEpoch, big.NewInt(0), msg,
); err == nil {
t.Error("expected", "rate:-0.001000000000000000: commission rate, change rate and max rate should be within 0-100 percent", "got", nil)
}
@ -336,13 +397,15 @@ func TestCV24(t *testing.T) {
// Test CV25: max change rate < 0
func TestCV25(t *testing.T) {
statedb, _ := state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase()))
database := ethdb.NewMemDatabase()
statedb, _ := state.New(common.Hash{}, state.NewDatabase(database))
chain := createChain(database)
msg := createValidator()
statedb.AddBalance(msg.ValidatorAddress, tenK)
// max rate < 0
msg.CommissionRates.MaxChangeRate, _ = numeric.NewDecFromStr("-0.001")
if _, err := VerifyAndCreateValidatorFromMsg(
statedb, postStakingEpoch, big.NewInt(0), msg,
statedb, chain, postStakingEpoch, big.NewInt(0), msg,
); err == nil {
t.Error("expected", "rate:-0.001000000000000000: commission rate, change rate and max rate should be within 0-100 percent", "got", nil)
}
@ -350,13 +413,15 @@ func TestCV25(t *testing.T) {
// Test CV26: commission rate > 1
func TestCV26(t *testing.T) {
statedb, _ := state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase()))
database := ethdb.NewMemDatabase()
statedb, _ := state.New(common.Hash{}, state.NewDatabase(database))
chain := createChain(database)
msg := createValidator()
statedb.AddBalance(msg.ValidatorAddress, tenK)
// commission rate > 1
msg.CommissionRates.Rate, _ = numeric.NewDecFromStr("1.01")
if _, err := VerifyAndCreateValidatorFromMsg(
statedb, postStakingEpoch, big.NewInt(0), msg,
statedb, chain, postStakingEpoch, big.NewInt(0), msg,
); err == nil {
t.Error("expected", "rate:1.01000000000000000: commission rate, change rate and max rate should be within 0-100 percent", "got", nil)
}
@ -364,13 +429,15 @@ func TestCV26(t *testing.T) {
// Test CV27: max rate > 1
func TestCV27(t *testing.T) {
statedb, _ := state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase()))
database := ethdb.NewMemDatabase()
statedb, _ := state.New(common.Hash{}, state.NewDatabase(database))
chain := createChain(database)
msg := createValidator()
statedb.AddBalance(msg.ValidatorAddress, tenK)
// max rate > 1
msg.CommissionRates.MaxRate, _ = numeric.NewDecFromStr("1.01")
if _, err := VerifyAndCreateValidatorFromMsg(
statedb, postStakingEpoch, big.NewInt(0), msg,
statedb, chain, postStakingEpoch, big.NewInt(0), msg,
); err == nil {
t.Error("expected", "rate:1.01000000000000000: commission rate, change rate and max rate should be within 0-100 percent", "got", nil)
}
@ -378,13 +445,15 @@ func TestCV27(t *testing.T) {
// Test CV28: max change rate > 1
func TestCV28(t *testing.T) {
statedb, _ := state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase()))
database := ethdb.NewMemDatabase()
statedb, _ := state.New(common.Hash{}, state.NewDatabase(database))
chain := createChain(database)
msg := createValidator()
statedb.AddBalance(msg.ValidatorAddress, tenK)
// max change rate > 1
msg.CommissionRates.MaxChangeRate, _ = numeric.NewDecFromStr("1.01")
if _, err := VerifyAndCreateValidatorFromMsg(
statedb, postStakingEpoch, big.NewInt(0), msg,
statedb, chain, postStakingEpoch, big.NewInt(0), msg,
); err == nil {
t.Error("expected", "rate:1.01000000000000000: commission rate, change rate and max rate should be within 0-100 percent", "got", nil)
}
@ -392,14 +461,16 @@ func TestCV28(t *testing.T) {
// Test CV29: amount > MinSelfDelegation
func TestCV29(t *testing.T) {
statedb, _ := state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase()))
database := ethdb.NewMemDatabase()
statedb, _ := state.New(common.Hash{}, state.NewDatabase(database))
chain := createChain(database)
msg := createValidator()
statedb.AddBalance(msg.ValidatorAddress, twelveK)
// amount > MinSelfDelegation
msg.Amount = twelveK
msg.MinSelfDelegation = tenK
if _, err := VerifyAndCreateValidatorFromMsg(
statedb, postStakingEpoch, big.NewInt(0), msg,
statedb, chain, postStakingEpoch, big.NewInt(0), msg,
); err != nil {
t.Error("expected", nil, "got", err)
}
@ -407,14 +478,16 @@ func TestCV29(t *testing.T) {
// Test CV30: amount == MinSelfDelegation
func TestCV30(t *testing.T) {
statedb, _ := state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase()))
database := ethdb.NewMemDatabase()
statedb, _ := state.New(common.Hash{}, state.NewDatabase(database))
chain := createChain(database)
msg := createValidator()
statedb.AddBalance(msg.ValidatorAddress, tenK)
// amount > MinSelfDelegation
msg.Amount = tenK
msg.MinSelfDelegation = tenK
if _, err := VerifyAndCreateValidatorFromMsg(
statedb, postStakingEpoch, big.NewInt(0), msg,
statedb, chain, postStakingEpoch, big.NewInt(0), msg,
); err != nil {
t.Error("expected", nil, "got", err)
}
@ -422,14 +495,16 @@ func TestCV30(t *testing.T) {
// Test CV31: amount < MinSelfDelegation
func TestCV31(t *testing.T) {
statedb, _ := state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase()))
database := ethdb.NewMemDatabase()
statedb, _ := state.New(common.Hash{}, state.NewDatabase(database))
chain := createChain(database)
msg := createValidator()
statedb.AddBalance(msg.ValidatorAddress, tenK)
// amount > MinSelfDelegation
msg.Amount = twelveK
msg.MinSelfDelegation = tenK
if _, err := VerifyAndCreateValidatorFromMsg(
statedb, postStakingEpoch, big.NewInt(0), msg,
statedb, chain, postStakingEpoch, big.NewInt(0), msg,
); err == nil {
t.Error("expected", "min_self_delegation 5000000000000000000, after delegation amount 4000000000000000000: self delegation can not be less than min_self_delegation", "got", nil)
}
@ -437,14 +512,16 @@ func TestCV31(t *testing.T) {
// Test CV32: MaxTotalDelegation < MinSelfDelegation
func TestCV32(t *testing.T) {
statedb, _ := state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase()))
database := ethdb.NewMemDatabase()
statedb, _ := state.New(common.Hash{}, state.NewDatabase(database))
chain := createChain(database)
msg := createValidator()
statedb.AddBalance(msg.ValidatorAddress, tenK)
// MaxTotalDelegation < MinSelfDelegation
msg.MaxTotalDelegation = tenK
msg.MinSelfDelegation = twelveK
if _, err := VerifyAndCreateValidatorFromMsg(
statedb, postStakingEpoch, big.NewInt(0), msg,
statedb, chain, postStakingEpoch, big.NewInt(0), msg,
); err == nil {
t.Error("expected", "max_total_delegation can not be less than min_self_delegation", "got", nil)
}
@ -452,13 +529,15 @@ func TestCV32(t *testing.T) {
// Test CV33: MinSelfDelegation < 1 ONE
func TestCV33(t *testing.T) {
statedb, _ := state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase()))
database := ethdb.NewMemDatabase()
statedb, _ := state.New(common.Hash{}, state.NewDatabase(database))
chain := createChain(database)
msg := createValidator()
statedb.AddBalance(msg.ValidatorAddress, tenK)
// MinSelfDelegation < 10,000 ONE
msg.MinSelfDelegation = big.NewInt(1e18)
if _, err := VerifyAndCreateValidatorFromMsg(
statedb, postStakingEpoch, big.NewInt(0), msg,
statedb, chain, postStakingEpoch, big.NewInt(0), msg,
); err == nil {
t.Error("expected", "delegation-given 1000000000000000000: min_self_delegation has to be greater than 10,000 ONE", "got", nil)
}
@ -466,13 +545,15 @@ func TestCV33(t *testing.T) {
// Test CV34: MinSelfDelegation not specified
func TestCV34(t *testing.T) {
statedb, _ := state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase()))
database := ethdb.NewMemDatabase()
statedb, _ := state.New(common.Hash{}, state.NewDatabase(database))
chain := createChain(database)
msg := createValidator()
statedb.AddBalance(msg.ValidatorAddress, tenK)
// MinSelfDelegation not specified
msg.MinSelfDelegation = nil
if _, err := VerifyAndCreateValidatorFromMsg(
statedb, postStakingEpoch, big.NewInt(0), msg,
statedb, chain, postStakingEpoch, big.NewInt(0), msg,
); err == nil {
t.Error("expected", "MinSelfDelegation can not be nil", "got", nil)
}
@ -480,13 +561,15 @@ func TestCV34(t *testing.T) {
// Test CV35: MinSelfDelegation < 0
func TestCV35(t *testing.T) {
statedb, _ := state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase()))
database := ethdb.NewMemDatabase()
statedb, _ := state.New(common.Hash{}, state.NewDatabase(database))
chain := createChain(database)
msg := createValidator()
statedb.AddBalance(msg.ValidatorAddress, tenK)
// MinSelfDelegation < 0
msg.MinSelfDelegation = big.NewInt(-1)
if _, err := VerifyAndCreateValidatorFromMsg(
statedb, postStakingEpoch, big.NewInt(0), msg,
statedb, chain, postStakingEpoch, big.NewInt(0), msg,
); err == nil {
t.Error("expected", "delegation-given -1: min_self_delegation has to be greater than 1 ONE", "got", nil)
}
@ -494,14 +577,16 @@ func TestCV35(t *testing.T) {
// Test CV36: amount > MaxTotalDelegation
func TestCV36(t *testing.T) {
statedb, _ := state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase()))
database := ethdb.NewMemDatabase()
statedb, _ := state.New(common.Hash{}, state.NewDatabase(database))
chain := createChain(database)
msg := createValidator()
statedb.AddBalance(msg.ValidatorAddress, tenK)
// amount > MaxTotalDelegation
msg.Amount = big.NewInt(4e18)
msg.MaxTotalDelegation = big.NewInt(3e18)
if _, err := VerifyAndCreateValidatorFromMsg(
statedb, postStakingEpoch, big.NewInt(0), msg,
statedb, chain, postStakingEpoch, big.NewInt(0), msg,
); err == nil {
t.Error("expected", "total delegation can not be bigger than max_total_delegation", "got", nil)
}
@ -509,13 +594,15 @@ func TestCV36(t *testing.T) {
// Test CV39: MaxTotalDelegation < 0
func TestCV39(t *testing.T) {
statedb, _ := state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase()))
database := ethdb.NewMemDatabase()
statedb, _ := state.New(common.Hash{}, state.NewDatabase(database))
chain := createChain(database)
msg := createValidator()
statedb.AddBalance(msg.ValidatorAddress, tenK)
// MaxTotalDelegation < 0
msg.MaxTotalDelegation = big.NewInt(-1)
if _, err := VerifyAndCreateValidatorFromMsg(
statedb, postStakingEpoch, big.NewInt(0), msg,
statedb, chain, postStakingEpoch, big.NewInt(0), msg,
); err == nil {
t.Error("expected", "max_total_delegation can not be less than min_self_delegation", "got", nil)
}

@ -17,12 +17,9 @@
package core
import (
"bytes"
"math"
"math/big"
"github.com/harmony-one/harmony/shard"
staking2 "github.com/harmony-one/harmony/staking"
"github.com/harmony-one/harmony/staking/network"
@ -389,54 +386,11 @@ func (st *StateTransition) StakingTransitionDb() (usedGas uint64, err error) {
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(
createValidator *staking.CreateValidator, blockNum *big.Int,
) error {
if err := st.checkDuplicateFields(
createValidator.ValidatorAddress,
createValidator.Identity,
createValidator.SlotPubKeys); err != nil {
return err
}
wrapper, err := VerifyAndCreateValidatorFromMsg(
st.state, st.evm.EpochNumber, blockNum, createValidator,
st.state, st.bc, st.evm.EpochNumber, blockNum, createValidator,
)
if err != nil {
return err
@ -452,16 +406,6 @@ func (st *StateTransition) verifyAndApplyCreateValidatorTx(
func (st *StateTransition) verifyAndApplyEditValidatorTx(
editValidator *staking.EditValidator, blockNum *big.Int,
) 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(
st.state, st.bc, st.evm.EpochNumber, blockNum, editValidator,
)

@ -762,8 +762,11 @@ func (pool *TxPool) validateStakingTx(tx *staking.StakingTransaction) error {
if shard.Schedule.IsLastBlock(currentBlockNumber.Uint64()) {
pendingEpoch = new(big.Int).Add(pendingEpoch, big.NewInt(1))
}
_, err = VerifyAndCreateValidatorFromMsg(pool.currentState, pendingEpoch, pendingBlockNumber, stkMsg)
chainContext, ok := pool.chain.(ChainContext)
if !ok {
chainContext = nil // might use testing blockchain, set to nil for verifier to handle.
}
_, err = VerifyAndCreateValidatorFromMsg(pool.currentState, chainContext, pendingEpoch, pendingBlockNumber, stkMsg)
return err
case staking.DirectiveEditValidator:
msg, err := staking.RLPDecodeStakeMsg(tx.Data(), staking.DirectiveEditValidator)

@ -35,7 +35,9 @@ import (
"github.com/harmony-one/harmony/common/denominations"
"github.com/harmony-one/harmony/core/state"
"github.com/harmony-one/harmony/core/types"
"github.com/harmony-one/harmony/core/vm"
"github.com/harmony-one/harmony/crypto/hash"
chain2 "github.com/harmony-one/harmony/internal/chain"
"github.com/harmony-one/harmony/internal/params"
"github.com/harmony-one/harmony/numeric"
"github.com/harmony-one/harmony/shard"
@ -136,6 +138,26 @@ func pricedTransaction(shardID uint32, nonce uint64, gaslimit uint64, gasprice *
return signedTx
}
func createBlockChain() *BlockChain {
key, _ := crypto.GenerateKey()
gspec := Genesis{
Config: params.TestChainConfig,
Factory: blockfactory.ForTest,
Alloc: GenesisAlloc{
crypto.PubkeyToAddress(key.PublicKey): {
Balance: big.NewInt(8e18),
},
},
GasLimit: 1e18,
ShardID: 0,
}
database := ethdb.NewMemDatabase()
genesis := gspec.MustCommit(database)
_ = genesis
blockchain, _ := NewBlockChain(database, nil, gspec.Config, chain2.Engine, vm.Config{}, nil)
return blockchain
}
func setupTxPool() (*TxPool, *ecdsa.PrivateKey) {
statedb, _ := state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase()))
blockchain := &testBlockChain{statedb, 1e18, new(event.Feed)}
@ -301,6 +323,7 @@ func TestCreateValidatorTransaction(t *testing.T) {
t.Parallel()
pool, _ := setupTxPool()
pool.chain = createBlockChain()
defer pool.Stop()
fromKey, _ := crypto.GenerateKey()
@ -328,6 +351,7 @@ func TestMixedTransactions(t *testing.T) {
t.Parallel()
pool, _ := setupTxPool()
pool.chain = createBlockChain()
defer pool.Stop()
fromKey, _ := crypto.GenerateKey()

@ -6,14 +6,19 @@ import (
"math/rand"
"time"
blockfactory "github.com/harmony-one/harmony/block/factory"
"github.com/harmony-one/harmony/internal/params"
"github.com/harmony-one/harmony/internal/utils"
common2 "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/harmony-one/bls/ffi/go/bls"
"github.com/harmony-one/harmony/core"
"github.com/harmony-one/harmony/core/state"
"github.com/harmony-one/harmony/core/vm"
"github.com/harmony-one/harmony/crypto/hash"
"github.com/harmony-one/harmony/internal/chain"
"github.com/harmony-one/harmony/internal/common"
"github.com/harmony-one/harmony/numeric"
"github.com/harmony-one/harmony/shard"
@ -83,11 +88,27 @@ func createValidator() *staking.CreateValidator {
}
func main() {
key, _ := crypto.GenerateKey()
gspec := core.Genesis{
Config: params.TestChainConfig,
Factory: blockfactory.ForTest,
Alloc: core.GenesisAlloc{
crypto.PubkeyToAddress(key.PublicKey): {
Balance: big.NewInt(8000000000000000000),
},
},
GasLimit: 1e18,
ShardID: 0,
}
database := ethdb.NewMemDatabase()
genesis := gspec.MustCommit(database)
_ = genesis
bc, _ := core.NewBlockChain(database, nil, gspec.Config, chain.Engine, vm.Config{}, nil)
statedb, _ := state.New(common2.Hash{}, state.NewDatabase(ethdb.NewMemDatabase()))
msg := createValidator()
statedb.AddBalance(msg.ValidatorAddress, new(big.Int).Mul(big.NewInt(5e18), big.NewInt(2000)))
validator, err := core.VerifyAndCreateValidatorFromMsg(
statedb, postStakingEpoch, big.NewInt(0), msg,
statedb, bc, postStakingEpoch, big.NewInt(0), msg,
)
if err != nil {
fmt.Print(err)

Loading…
Cancel
Save