|
|
|
@ -2,6 +2,7 @@ package chain |
|
|
|
|
|
|
|
|
|
import ( |
|
|
|
|
"encoding/binary" |
|
|
|
|
"math/big" |
|
|
|
|
|
|
|
|
|
"github.com/ethereum/go-ethereum/common" |
|
|
|
|
"github.com/ethereum/go-ethereum/rlp" |
|
|
|
@ -169,9 +170,42 @@ func (e *engineImpl) Finalize( |
|
|
|
|
incxs []*types.CXReceiptsProof, stks []*staking.StakingTransaction) (*types.Block, error) { |
|
|
|
|
// Accumulate any block and uncle rewards and commit the final state root
|
|
|
|
|
// Header seems complete, assemble into a block and return
|
|
|
|
|
// TODO: Block rewards should be done only in beacon chain based on cross-links
|
|
|
|
|
if err := AccumulateRewards(chain, state, header, e.Rewarder()); err != nil { |
|
|
|
|
return nil, ctxerror.New("cannot pay block reward").WithCause(err) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Withdraw unlocked tokens to the delegators' accounts
|
|
|
|
|
// Only do such at the last block of an epoch
|
|
|
|
|
if len(header.ShardState()) > 0 { |
|
|
|
|
// TODO: make sure we are using the correct validator list
|
|
|
|
|
validators := chain.CurrentValidatorAddresses() |
|
|
|
|
for _, validator := range validators { |
|
|
|
|
wrapper := state.GetStakingInfo(validator) |
|
|
|
|
if wrapper != nil { |
|
|
|
|
for i := range wrapper.Delegations { |
|
|
|
|
delegation := wrapper.Delegations[i] |
|
|
|
|
totalWithdraw := big.NewInt(0) |
|
|
|
|
count := 0 |
|
|
|
|
// TODO: need ot make sure the entries are ordered by epoch
|
|
|
|
|
for j := range delegation.Entries { |
|
|
|
|
if delegation.Entries[j].Epoch.Cmp(header.Epoch()) > 14 { // need to wait at least 14 epochs to withdraw;
|
|
|
|
|
totalWithdraw.Add(totalWithdraw, delegation.Entries[j].Amount) |
|
|
|
|
count++ |
|
|
|
|
} else { |
|
|
|
|
break |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
state.AddBalance(delegation.DelegatorAddress, totalWithdraw) |
|
|
|
|
delegation.Entries = delegation.Entries[count:] |
|
|
|
|
} |
|
|
|
|
if err := state.UpdateStakingInfo(validator, wrapper); err != nil { |
|
|
|
|
return nil, ctxerror.New("failed update validator info").WithCause(err) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
header.SetRoot(state.IntermediateRoot(chain.Config().IsS3(header.Epoch()))) |
|
|
|
|
return types.NewBlock(header, txs, receipts, outcxs, incxs, stks), nil |
|
|
|
|
} |
|
|
|
|