diff --git a/core/blockchain.go b/core/blockchain.go index a972af5d6..97a616c1c 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -2954,3 +2954,36 @@ func (bc *BlockChain) ValidatorCandidates() []common.Address { func (bc *BlockChain) DelegatorsInformation(addr common.Address) []*staking.Delegation { return make([]*staking.Delegation, 0) } + +// GetECDSAFromCoinbase retrieve corresponding ecdsa address from Coinbase Address +func (bc *BlockChain) GetECDSAFromCoinbase(header *block.Header) (common.Address, error) { + // backward compatibility: before isStaking epoch, coinbase address is the ecdsa address + isStaking := bc.Config().IsStaking(header.Epoch()) + if !isStaking { + return header.Coinbase(), nil + } + + shardState, err := bc.ReadShardState(header.Epoch()) + if err != nil { + return common.Address{}, ctxerror.New("cannot read shard state", + "epoch", header.Epoch(), + "coinbaseAddr", header.Coinbase(), + ).WithCause(err) + } + + committee := shardState.FindCommitteeByID(header.ShardID()) + if committee == nil { + return common.Address{}, ctxerror.New("cannot find shard in the shard state", + "blockNum", header.Number(), + "shardID", header.ShardID(), + "coinbaseAddr", header.Coinbase(), + ) + } + for _, member := range committee.Slots { + // After staking the coinbase address will be the address of bls public key + if utils.GetAddressFromBlsPubKeyBytes(member.BlsPublicKey[:]) == header.Coinbase() { + return member.EcdsaAddress, nil + } + } + return common.Address{}, ctxerror.New("cannot find corresponding ECDSA Address", "coinbaseAddr", header.Coinbase()) +} diff --git a/core/evm.go b/core/evm.go index 0e529ba20..cc85d8aea 100644 --- a/core/evm.go +++ b/core/evm.go @@ -27,6 +27,7 @@ import ( consensus_engine "github.com/harmony-one/harmony/consensus/engine" "github.com/harmony-one/harmony/core/types" "github.com/harmony-one/harmony/core/vm" + "github.com/harmony-one/harmony/internal/utils" ) // ChainContext supports retrieving headers and consensus parameters from the @@ -43,14 +44,21 @@ type ChainContext interface { // ReadValidatorSnapshot returns the snapshot of validator at the beginning of current epoch. ReadValidatorSnapshot(common.Address) (*types2.ValidatorWrapper, error) + + // GetECDSAFromCoinbase retrieves corresponding ECDSA address from the coinbase (BLS Address) + GetECDSAFromCoinbase(*block.Header) (common.Address, error) } // NewEVMContext creates a new context for use in the EVM. func NewEVMContext(msg Message, header *block.Header, chain ChainContext, author *common.Address) vm.Context { // If we don't have an explicit author (i.e. not mining), extract from the header var beneficiary common.Address + var err error if author == nil { - beneficiary, _ = chain.Engine().Author(header) // Ignore error, we're past header validation + beneficiary, err = chain.GetECDSAFromCoinbase(header) // Ignore error, we're past header validation + if err != nil { + utils.Logger().Warn().Msg("oops! We cannot find any beneficiary from header") + } } else { beneficiary = *author } diff --git a/core/state_transition.go b/core/state_transition.go index 3a6e0a142..4a47c9ffb 100644 --- a/core/state_transition.go +++ b/core/state_transition.go @@ -245,8 +245,8 @@ func (st *StateTransition) TransitionDb() (ret []byte, usedGas uint64, failed bo } } st.refundGas() - // TODO: need to move the gas fee to the general block rewards - st.state.AddBalance(st.evm.Coinbase, new(big.Int).Mul(new(big.Int).SetUint64(st.gasUsed()), st.gasPrice)) + txFee := new(big.Int).Mul(new(big.Int).SetUint64(st.gasUsed()), st.gasPrice) + st.state.AddBalance(st.evm.Coinbase, txFee) return ret, st.gasUsed(), vmerr != nil, err } @@ -360,6 +360,9 @@ func (st *StateTransition) StakingTransitionDb() (usedGas uint64, err error) { } st.refundGas() + txFee := new(big.Int).Mul(new(big.Int).SetUint64(st.gasUsed()), st.gasPrice) + st.state.AddBalance(st.evm.Coinbase, txFee) + return st.gasUsed(), err } diff --git a/internal/chain/reward.go b/internal/chain/reward.go index e3685dc13..309506df6 100644 --- a/internal/chain/reward.go +++ b/internal/chain/reward.go @@ -164,8 +164,7 @@ func whatPercentStakedNow( } // AccumulateRewards credits the coinbase of the given block with the mining -// reward. The total reward consists of the static block reward and rewards for -// included uncles. The coinbase of each uncle block is also rewarded. +// reward. The total reward consists of the static block reward func AccumulateRewards( bc engine.ChainReader, state *state.DB, header *block.Header, rewarder reward.Distributor, slasher slash.Slasher,