Reduce min delegation from 1000 to 100 (#3712)

* Reduce min delegation from 1000 to 100
pull/3716/head
Rongjian Lan 4 years ago committed by GitHub
parent 5a93de7b83
commit 03c4ca4a93
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 23
      core/staking_verifier.go
  2. 44
      core/staking_verifier_test.go
  3. 2
      core/state_transition.go
  4. 2
      core/tx_pool.go
  5. 16
      internal/params/config.go

@ -4,6 +4,8 @@ import (
"bytes" "bytes"
"math/big" "math/big"
"github.com/harmony-one/harmony/internal/params"
"github.com/harmony-one/harmony/crypto/bls" "github.com/harmony-one/harmony/crypto/bls"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
@ -187,11 +189,14 @@ func VerifyAndEditValidatorFromMsg(
} }
const oneThousand = 1000 const oneThousand = 1000
const oneHundred = 100
var ( var (
oneAsBigInt = big.NewInt(denominations.One) oneAsBigInt = big.NewInt(denominations.One)
minimumDelegation = new(big.Int).Mul(oneAsBigInt, big.NewInt(oneThousand)) minimumDelegation = new(big.Int).Mul(oneAsBigInt, big.NewInt(oneThousand))
errDelegationTooSmall = errors.New("minimum delegation amount for a delegator has to be greater than or equal to 1000 ONE") minimumDelegationV2 = new(big.Int).Mul(oneAsBigInt, big.NewInt(oneHundred))
errDelegationTooSmall = errors.New("minimum delegation amount for a delegator has to be greater than or equal to 1000 ONE")
errDelegationTooSmallV2 = errors.New("minimum delegation amount for a delegator has to be greater than or equal to 100 ONE")
) )
// VerifyAndDelegateFromMsg verifies the delegate message using the stateDB // VerifyAndDelegateFromMsg verifies the delegate message using the stateDB
@ -200,7 +205,7 @@ var (
// //
// Note that this function never updates the stateDB, it only reads from stateDB. // Note that this function never updates the stateDB, it only reads from stateDB.
func VerifyAndDelegateFromMsg( func VerifyAndDelegateFromMsg(
stateDB vm.StateDB, epoch *big.Int, msg *staking.Delegate, delegations []staking.DelegationIndex, redelegation bool, stateDB vm.StateDB, epoch *big.Int, msg *staking.Delegate, delegations []staking.DelegationIndex, chainConfig *params.ChainConfig,
) ([]*staking.ValidatorWrapper, *big.Int, map[common.Address]*big.Int, error) { ) ([]*staking.ValidatorWrapper, *big.Int, map[common.Address]*big.Int, error) {
if stateDB == nil { if stateDB == nil {
return nil, nil, nil, errStateDBIsMissing return nil, nil, nil, errStateDBIsMissing
@ -212,7 +217,13 @@ func VerifyAndDelegateFromMsg(
return nil, nil, nil, errNegativeAmount return nil, nil, nil, errNegativeAmount
} }
if msg.Amount.Cmp(minimumDelegation) < 0 { if msg.Amount.Cmp(minimumDelegation) < 0 {
return nil, nil, nil, errDelegationTooSmall if chainConfig.IsMinDelegation100(epoch) {
if msg.Amount.Cmp(minimumDelegationV2) < 0 {
return nil, nil, nil, errDelegationTooSmallV2
}
} else {
return nil, nil, nil, errDelegationTooSmall
}
} }
updatedValidatorWrappers := []*staking.ValidatorWrapper{} updatedValidatorWrappers := []*staking.ValidatorWrapper{}
@ -220,7 +231,7 @@ func VerifyAndDelegateFromMsg(
fromLockedTokens := map[common.Address]*big.Int{} fromLockedTokens := map[common.Address]*big.Int{}
var delegateeWrapper *staking.ValidatorWrapper var delegateeWrapper *staking.ValidatorWrapper
if redelegation { if chainConfig.IsRedelegation(epoch) {
// Check if we can use tokens in undelegation to delegate (redelegate) // Check if we can use tokens in undelegation to delegate (redelegate)
for i := range delegations { for i := range delegations {
delegationIndex := &delegations[i] delegationIndex := &delegations[i]

@ -7,6 +7,8 @@ import (
"strings" "strings"
"testing" "testing"
"github.com/harmony-one/harmony/internal/params"
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/harmony-one/harmony/crypto/bls" "github.com/harmony-one/harmony/crypto/bls"
@ -1000,9 +1002,49 @@ func TestVerifyAndDelegateFromMsg(t *testing.T) {
}(), }(),
expAmt: tenKOnes, expAmt: tenKOnes,
}, },
{
// 17: small amount v2
sdb: makeStateDBForStake(t),
msg: func() staking.Delegate {
msg := defaultMsgDelegate()
msg.Amount = new(big.Int).Mul(big.NewInt(90), oneBig)
return msg
}(),
ds: makeMsgCollectRewards(),
epoch: big.NewInt(100),
redelegate: false,
expErr: errDelegationTooSmallV2,
},
{
// 18: valid amount v2
sdb: makeStateDBForStake(t),
msg: func() staking.Delegate {
msg := defaultMsgDelegate()
msg.Amount = new(big.Int).Mul(big.NewInt(500), oneBig)
return msg
}(),
ds: makeMsgCollectRewards(),
epoch: big.NewInt(100),
redelegate: false,
expVWrappers: func() []staking.ValidatorWrapper {
wrapper := defaultExpVWrapperDelegate()
wrapper.Delegations[1].Amount = new(big.Int).Mul(big.NewInt(500), oneBig)
return []staking.ValidatorWrapper{wrapper}
}(),
expAmt: new(big.Int).Mul(big.NewInt(500), oneBig),
},
} }
for i, test := range tests { for i, test := range tests {
ws, amt, amtRedel, err := VerifyAndDelegateFromMsg(test.sdb, test.epoch, &test.msg, test.ds, test.redelegate) config := &params.ChainConfig{}
config.MinDelegation100Epoch = big.NewInt(100)
if test.redelegate {
config.RedelegationEpoch = test.epoch
} else {
config.RedelegationEpoch = big.NewInt(test.epoch.Int64() + 1)
}
ws, amt, amtRedel, err := VerifyAndDelegateFromMsg(test.sdb, test.epoch, &test.msg, test.ds, config)
if assErr := assertError(err, test.expErr); assErr != nil { if assErr := assertError(err, test.expErr); assErr != nil {
t.Errorf("Test %v: %v", i, assErr) t.Errorf("Test %v: %v", i, assErr)

@ -456,7 +456,7 @@ func (st *StateTransition) verifyAndApplyDelegateTx(delegate *staking.Delegate)
return err return err
} }
updatedValidatorWrappers, balanceToBeDeducted, fromLockedTokens, err := VerifyAndDelegateFromMsg( updatedValidatorWrappers, balanceToBeDeducted, fromLockedTokens, err := VerifyAndDelegateFromMsg(
st.state, st.evm.EpochNumber, delegate, delegations, st.evm.ChainConfig().IsRedelegation(st.evm.EpochNumber)) st.state, st.evm.EpochNumber, delegate, delegations, st.evm.ChainConfig())
if err != nil { if err != nil {
return err return err
} }

@ -840,7 +840,7 @@ func (pool *TxPool) validateStakingTx(tx *staking.StakingTransaction) error {
} }
pendingEpoch := pool.pendingEpoch() pendingEpoch := pool.pendingEpoch()
_, delegateAmt, _, err := VerifyAndDelegateFromMsg( _, delegateAmt, _, err := VerifyAndDelegateFromMsg(
pool.currentState, pendingEpoch, stkMsg, delegations, pool.chainconfig.IsRedelegation(pendingEpoch)) pool.currentState, pendingEpoch, stkMsg, delegations, pool.chainconfig)
if err != nil { if err != nil {
return err return err
} }

@ -51,6 +51,7 @@ var (
RedelegationEpoch: big.NewInt(290), RedelegationEpoch: big.NewInt(290),
NoEarlyUnlockEpoch: big.NewInt(530), // Around Monday Apr 12th 2021, 22:30 UTC NoEarlyUnlockEpoch: big.NewInt(530), // Around Monday Apr 12th 2021, 22:30 UTC
VRFEpoch: EpochTBD, VRFEpoch: EpochTBD,
MinDelegation100Epoch: EpochTBD,
EIP155Epoch: big.NewInt(28), EIP155Epoch: big.NewInt(28),
S3Epoch: big.NewInt(28), S3Epoch: big.NewInt(28),
IstanbulEpoch: big.NewInt(314), IstanbulEpoch: big.NewInt(314),
@ -74,6 +75,7 @@ var (
RedelegationEpoch: big.NewInt(36500), RedelegationEpoch: big.NewInt(36500),
NoEarlyUnlockEpoch: big.NewInt(73580), NoEarlyUnlockEpoch: big.NewInt(73580),
VRFEpoch: EpochTBD, VRFEpoch: EpochTBD,
MinDelegation100Epoch: EpochTBD,
EIP155Epoch: big.NewInt(0), EIP155Epoch: big.NewInt(0),
S3Epoch: big.NewInt(0), S3Epoch: big.NewInt(0),
IstanbulEpoch: big.NewInt(43800), IstanbulEpoch: big.NewInt(43800),
@ -98,6 +100,7 @@ var (
RedelegationEpoch: big.NewInt(0), RedelegationEpoch: big.NewInt(0),
NoEarlyUnlockEpoch: big.NewInt(0), NoEarlyUnlockEpoch: big.NewInt(0),
VRFEpoch: big.NewInt(0), VRFEpoch: big.NewInt(0),
MinDelegation100Epoch: big.NewInt(0),
EIP155Epoch: big.NewInt(0), EIP155Epoch: big.NewInt(0),
S3Epoch: big.NewInt(0), S3Epoch: big.NewInt(0),
IstanbulEpoch: big.NewInt(0), IstanbulEpoch: big.NewInt(0),
@ -122,6 +125,7 @@ var (
RedelegationEpoch: big.NewInt(0), RedelegationEpoch: big.NewInt(0),
NoEarlyUnlockEpoch: big.NewInt(0), NoEarlyUnlockEpoch: big.NewInt(0),
VRFEpoch: big.NewInt(0), VRFEpoch: big.NewInt(0),
MinDelegation100Epoch: big.NewInt(0),
EIP155Epoch: big.NewInt(0), EIP155Epoch: big.NewInt(0),
S3Epoch: big.NewInt(0), S3Epoch: big.NewInt(0),
IstanbulEpoch: big.NewInt(0), IstanbulEpoch: big.NewInt(0),
@ -146,6 +150,7 @@ var (
RedelegationEpoch: big.NewInt(0), RedelegationEpoch: big.NewInt(0),
NoEarlyUnlockEpoch: big.NewInt(0), NoEarlyUnlockEpoch: big.NewInt(0),
VRFEpoch: big.NewInt(0), VRFEpoch: big.NewInt(0),
MinDelegation100Epoch: big.NewInt(0),
EIP155Epoch: big.NewInt(0), EIP155Epoch: big.NewInt(0),
S3Epoch: big.NewInt(0), S3Epoch: big.NewInt(0),
IstanbulEpoch: big.NewInt(0), IstanbulEpoch: big.NewInt(0),
@ -169,6 +174,7 @@ var (
RedelegationEpoch: big.NewInt(0), RedelegationEpoch: big.NewInt(0),
NoEarlyUnlockEpoch: big.NewInt(0), NoEarlyUnlockEpoch: big.NewInt(0),
VRFEpoch: big.NewInt(0), VRFEpoch: big.NewInt(0),
MinDelegation100Epoch: big.NewInt(0),
EIP155Epoch: big.NewInt(0), EIP155Epoch: big.NewInt(0),
S3Epoch: big.NewInt(0), S3Epoch: big.NewInt(0),
IstanbulEpoch: big.NewInt(0), IstanbulEpoch: big.NewInt(0),
@ -194,6 +200,7 @@ var (
big.NewInt(0), // RedelegationEpoch big.NewInt(0), // RedelegationEpoch
big.NewInt(0), // NoEarlyUnlockEpoch big.NewInt(0), // NoEarlyUnlockEpoch
big.NewInt(0), // VRFEpoch big.NewInt(0), // VRFEpoch
big.NewInt(0), // MinDelegation100Epoch
big.NewInt(0), // EIP155Epoch big.NewInt(0), // EIP155Epoch
big.NewInt(0), // S3Epoch big.NewInt(0), // S3Epoch
big.NewInt(0), // IstanbulEpoch big.NewInt(0), // IstanbulEpoch
@ -219,6 +226,7 @@ var (
big.NewInt(0), // RedelegationEpoch big.NewInt(0), // RedelegationEpoch
big.NewInt(0), // NoEarlyUnlockEpoch big.NewInt(0), // NoEarlyUnlockEpoch
big.NewInt(0), // VRFEpoch big.NewInt(0), // VRFEpoch
big.NewInt(0), // MinDelegation100Epoch
big.NewInt(0), // EIP155Epoch big.NewInt(0), // EIP155Epoch
big.NewInt(0), // S3Epoch big.NewInt(0), // S3Epoch
big.NewInt(0), // IstanbulEpoch big.NewInt(0), // IstanbulEpoch
@ -299,6 +307,9 @@ type ChainConfig struct {
// VRFEpoch is the epoch when VRF randomness is enabled // VRFEpoch is the epoch when VRF randomness is enabled
VRFEpoch *big.Int `json:"vrf-epoch,omitempty"` VRFEpoch *big.Int `json:"vrf-epoch,omitempty"`
// MinDelegation100Epoch is the epoch when min delegation is reduced from 1000 ONE to 100 ONE
MinDelegation100Epoch *big.Int `json:"min-delegation-100-epoch,omitempty"`
// EIP155 hard fork epoch (include EIP158 too) // EIP155 hard fork epoch (include EIP158 too)
EIP155Epoch *big.Int `json:"eip155-epoch,omitempty"` EIP155Epoch *big.Int `json:"eip155-epoch,omitempty"`
@ -390,6 +401,11 @@ func (c *ChainConfig) IsVRF(epoch *big.Int) bool {
return isForked(c.VRFEpoch, epoch) return isForked(c.VRFEpoch, epoch)
} }
// IsMinDelegation100 determines whether it is the epoch to reduce min delegation to 100
func (c *ChainConfig) IsMinDelegation100(epoch *big.Int) bool {
return isForked(c.MinDelegation100Epoch, epoch)
}
// IsPreStaking determines whether staking transactions are allowed // IsPreStaking determines whether staking transactions are allowed
func (c *ChainConfig) IsPreStaking(epoch *big.Int) bool { func (c *ChainConfig) IsPreStaking(epoch *big.Int) bool {
return isForked(c.PreStakingEpoch, epoch) return isForked(c.PreStakingEpoch, epoch)

Loading…
Cancel
Save