diff --git a/consensus/engine/consensus_engine.go b/consensus/engine/consensus_engine.go index 90ef3316b..a032c5123 100644 --- a/consensus/engine/consensus_engine.go +++ b/consensus/engine/consensus_engine.go @@ -45,6 +45,9 @@ type ChainReader interface { // ReadActiveValidatorList retrieves the list of active validators ReadActiveValidatorList() ([]common.Address, error) + // ReadValidatorList retrieves the list of all validators + ReadValidatorList() ([]common.Address, error) + // Methods needed for EPoS committee assignment calculation committee.StakingCandidatesReader diff --git a/core/state_transition.go b/core/state_transition.go index b63cd10aa..314d51002 100644 --- a/core/state_transition.go +++ b/core/state_transition.go @@ -41,6 +41,7 @@ var ( errCommissionRateChangeTooFast = errors.New("commission rate can not be changed more than MaxChangeRate within the same epoch") errCommissionRateChangeTooHigh = errors.New("commission rate can not be higher than MaxCommissionRate") errNoRewardsToCollect = errors.New("no rewards to collect") + errNegativeAmount = errors.New("amount can not be negative") ) /* @@ -367,6 +368,10 @@ func (st *StateTransition) StakingTransitionDb() (usedGas uint64, err error) { } func (st *StateTransition) applyCreateValidatorTx(createValidator *staking.CreateValidator, blockNum *big.Int) error { + if createValidator.Amount.Sign() == -1 { + return errNegativeAmount + } + if st.state.IsValidator(createValidator.ValidatorAddress) { return errValidatorExist } @@ -429,6 +434,10 @@ func (st *StateTransition) applyEditValidatorTx(editValidator *staking.EditValid } func (st *StateTransition) applyDelegateTx(delegate *staking.Delegate) error { + if delegate.Amount.Sign() == -1 { + return errNegativeAmount + } + if !st.state.IsValidator(delegate.ValidatorAddress) { return errValidatorNotExist } @@ -465,7 +474,7 @@ func (st *StateTransition) applyDelegateTx(delegate *staking.Delegate) error { // Secondly, if all locked token are used, try use the balance. if err == nil && undelegateAmount.Cmp(big.NewInt(0)) > 0 { - stateDB.SubBalance(delegate.DelegatorAddress, delegate.Amount) + stateDB.SubBalance(delegate.DelegatorAddress, undelegateAmount) } return err } @@ -490,6 +499,10 @@ func (st *StateTransition) applyDelegateTx(delegate *staking.Delegate) error { } func (st *StateTransition) applyUndelegateTx(undelegate *staking.Undelegate) error { + if undelegate.Amount.Sign() == -1 { + return errNegativeAmount + } + if !st.state.IsValidator(undelegate.ValidatorAddress) { return errValidatorNotExist } diff --git a/internal/chain/engine.go b/internal/chain/engine.go index 31b637058..a3ccca832 100644 --- a/internal/chain/engine.go +++ b/internal/chain/engine.go @@ -203,12 +203,10 @@ func (e *engineImpl) Finalize( return nil, nil, ctxerror.New("cannot pay block reward").WithCause(err) } - // TODO Shouldnt this logic only apply to beaconchain, right? // Withdraw unlocked tokens to the delegators' accounts // Only do such at the last block of an epoch if header.ShardID() == shard.BeaconChainShardID && len(header.ShardState()) > 0 { - // TODO: make sure we are using the correct validator list - validators, err := chain.ReadActiveValidatorList() + validators, err := chain.ReadValidatorList() if err != nil { return nil, nil, ctxerror.New("failed to read active validators").WithCause(err) }