@ -20,6 +20,9 @@ import (
"math"
"math/big"
staking2 "github.com/harmony-one/harmony/staking"
"github.com/harmony-one/harmony/staking/network"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/rlp"
"github.com/harmony-one/harmony/core/types"
@ -291,7 +294,6 @@ func (st *StateTransition) StakingTransitionDb() (usedGas uint64, err error) {
homestead := st . evm . ChainConfig ( ) . IsS3 ( st . evm . EpochNumber ) // s3 includes homestead
// Pay intrinsic gas
// TODO: propose staking-specific formula for staking transaction
gas , err := IntrinsicGas ( st . data , false , homestead , msg . Type ( ) == types . StakeCreateVal )
if err != nil {
@ -354,7 +356,15 @@ func (st *StateTransition) StakingTransitionDb() (usedGas uint64, err error) {
if msg . From ( ) != stkMsg . DelegatorAddress {
return 0 , errInvalidSigner
}
err = st . verifyAndApplyCollectRewards ( stkMsg )
collectedRewards , err := st . verifyAndApplyCollectRewards ( stkMsg )
if err == nil {
st . state . AddLog ( & types . Log {
Address : stkMsg . DelegatorAddress ,
Topics : [ ] common . Hash { staking2 . CollectRewardsTopic } ,
Data : collectedRewards . Bytes ( ) ,
BlockNumber : st . evm . BlockNumber . Uint64 ( ) ,
} )
}
default :
return 0 , staking . ErrInvalidStakingKind
}
@ -373,10 +383,10 @@ func (st *StateTransition) verifyAndApplyCreateValidatorTx(
if err != nil {
return err
}
if err := st . state . UpdateValidatorWrapper ( wrapper . Validator . Address , wrapper ) ; err != nil {
if err := st . state . UpdateValidatorWrapper ( wrapper . Address , wrapper ) ; err != nil {
return err
}
st . state . SetValidatorFlag ( wrapper . Validator . Address )
st . state . SetValidatorFlag ( wrapper . Address )
st . state . SubBalance ( wrapper . Address , createValidator . Amount )
return nil
}
@ -396,11 +406,10 @@ func (st *StateTransition) verifyAndApplyDelegateTx(delegate *staking.Delegate)
if err != nil {
return err
}
if err := st . state . UpdateValidatorWrapper ( wrapper . Validator . Address , wrapper ) ; err != nil {
return err
}
st . state . SubBalance ( delegate . DelegatorAddress , balanceToBeDeducted )
return nil
return st . state . UpdateValidatorWrapper ( wrapper . Address , wrapper )
}
func ( st * StateTransition ) verifyAndApplyUndelegateTx ( undelegate * staking . Undelegate ) error {
@ -408,28 +417,29 @@ func (st *StateTransition) verifyAndApplyUndelegateTx(undelegate *staking.Undele
if err != nil {
return err
}
return st . state . UpdateValidatorWrapper ( wrapper . Validator . Address , wrapper )
return st . state . UpdateValidatorWrapper ( wrapper . Address , wrapper )
}
func ( st * StateTransition ) verifyAndApplyCollectRewards ( collectRewards * staking . CollectRewards ) error {
func ( st * StateTransition ) verifyAndApplyCollectRewards ( collectRewards * staking . CollectRewards ) ( * big . Int , error ) {
if st . bc == nil {
return errors . New ( "[CollectRewards] No chain context provided" )
return network . NoReward , errors . New ( "[CollectRewards] No chain context provided" )
}
// TODO(audit): make sure the delegation index is always consistent with onchain data
delegations , err := st . bc . ReadDelegationsByDelegator ( collectRewards . DelegatorAddress )
if err != nil {
return err
return network . NoReward , err
}
updatedValidatorWrappers , totalRewards , err := VerifyAndCollectRewardsFromDelegation (
st . state , delegations ,
)
if err != nil {
return err
return network . NoReward , err
}
for _ , wrapper := range updatedValidatorWrappers {
if err := st . state . UpdateValidatorWrapper ( wrapper . Validator . Address , wrapper ) ; err != nil {
return err
if err := st . state . UpdateValidatorWrapper ( wrapper . Address , wrapper ) ; err != nil {
return network . NoReward , err
}
}
st . state . AddBalance ( collectRewards . DelegatorAddress , totalRewards )
return nil
return totalRewards , nil
}