diff options
author | Felix Lange <fjl@twurst.com> | 2015-06-16 18:41:50 +0800 |
---|---|---|
committer | Jeffrey Wilcke <geffobscura@gmail.com> | 2015-06-30 00:51:47 +0800 |
commit | 1d42888d3047dabfb352c94a2051e7af14d2a509 (patch) | |
tree | 8ca68ca98bd697f26f2033a5480e78ccbf064162 /core/block_processor.go | |
parent | 654564e164b3b6f7f4ba1e8bbd6fcd64776068fa (diff) | |
download | dexon-1d42888d3047dabfb352c94a2051e7af14d2a509.tar dexon-1d42888d3047dabfb352c94a2051e7af14d2a509.tar.gz dexon-1d42888d3047dabfb352c94a2051e7af14d2a509.tar.bz2 dexon-1d42888d3047dabfb352c94a2051e7af14d2a509.tar.lz dexon-1d42888d3047dabfb352c94a2051e7af14d2a509.tar.xz dexon-1d42888d3047dabfb352c94a2051e7af14d2a509.tar.zst dexon-1d42888d3047dabfb352c94a2051e7af14d2a509.zip |
core/types: make blocks immutable
Diffstat (limited to 'core/block_processor.go')
-rw-r--r-- | core/block_processor.go | 95 |
1 files changed, 49 insertions, 46 deletions
diff --git a/core/block_processor.go b/core/block_processor.go index e30ced312..2fd8c04c0 100644 --- a/core/block_processor.go +++ b/core/block_processor.go @@ -57,8 +57,8 @@ func NewBlockProcessor(db, extra common.Database, pow pow.PoW, chainManager *Cha } func (sm *BlockProcessor) TransitionState(statedb *state.StateDB, parent, block *types.Block, transientProcess bool) (receipts types.Receipts, err error) { - coinbase := statedb.GetOrNewStateObject(block.Header().Coinbase) - coinbase.SetGasLimit(block.Header().GasLimit) + coinbase := statedb.GetOrNewStateObject(block.Coinbase()) + coinbase.SetGasLimit(block.GasLimit()) // Process the transactions on to parent state receipts, err = sm.ApplyTransactions(coinbase, statedb, block, block.Transactions(), transientProcess) @@ -69,11 +69,11 @@ func (sm *BlockProcessor) TransitionState(statedb *state.StateDB, parent, block return receipts, nil } -func (self *BlockProcessor) ApplyTransaction(coinbase *state.StateObject, statedb *state.StateDB, block *types.Block, tx *types.Transaction, usedGas *big.Int, transientProcess bool) (*types.Receipt, *big.Int, error) { +func (self *BlockProcessor) ApplyTransaction(coinbase *state.StateObject, statedb *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *big.Int, transientProcess bool) (*types.Receipt, *big.Int, error) { // If we are mining this block and validating we want to set the logs back to 0 cb := statedb.GetStateObject(coinbase.Address()) - _, gas, err := ApplyMessage(NewEnv(statedb, self.bc, tx, block), tx, cb) + _, gas, err := ApplyMessage(NewEnv(statedb, self.bc, tx, header), tx, cb) if err != nil && (IsNonceErr(err) || state.IsGasLimitErr(err) || IsInvalidTxErr(err)) { return nil, nil, err } @@ -108,12 +108,13 @@ func (self *BlockProcessor) ApplyTransactions(coinbase *state.StateObject, state totalUsedGas = big.NewInt(0) err error cumulativeSum = new(big.Int) + header = block.Header() ) for i, tx := range txs { statedb.StartRecord(tx.Hash(), block.Hash(), i) - receipt, txGas, err := self.ApplyTransaction(coinbase, statedb, block, tx, totalUsedGas, transientProcess) + receipt, txGas, err := self.ApplyTransaction(coinbase, statedb, header, tx, totalUsedGas, transientProcess) if err != nil && (IsNonceErr(err) || state.IsGasLimitErr(err) || IsInvalidTxErr(err)) { return nil, err } @@ -142,11 +143,10 @@ func (sm *BlockProcessor) RetryProcess(block *types.Block) (logs state.Logs, err sm.mutex.Lock() defer sm.mutex.Unlock() - header := block.Header() - if !sm.bc.HasBlock(header.ParentHash) { - return nil, ParentError(header.ParentHash) + if !sm.bc.HasBlock(block.ParentHash()) { + return nil, ParentError(block.ParentHash()) } - parent := sm.bc.GetBlock(header.ParentHash) + parent := sm.bc.GetBlock(block.ParentHash()) // FIXME Change to full header validation. See #1225 errch := make(chan bool) @@ -168,30 +168,32 @@ func (sm *BlockProcessor) Process(block *types.Block) (logs state.Logs, err erro sm.mutex.Lock() defer sm.mutex.Unlock() - header := block.Header() - if sm.bc.HasBlock(header.Hash()) { - return nil, &KnownBlockError{header.Number, header.Hash()} + if sm.bc.HasBlock(block.Hash()) { + return nil, &KnownBlockError{block.Number(), block.Hash()} } - if !sm.bc.HasBlock(header.ParentHash) { - return nil, ParentError(header.ParentHash) + if !sm.bc.HasBlock(block.ParentHash()) { + return nil, ParentError(block.ParentHash()) } - parent := sm.bc.GetBlock(header.ParentHash) + parent := sm.bc.GetBlock(block.ParentHash()) return sm.processWithParent(block, parent) } func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (logs state.Logs, err error) { // Create a new state based on the parent's root (e.g., create copy) state := state.New(parent.Root(), sm.db) + header := block.Header() + uncles := block.Uncles() + txs := block.Transactions() // Block validation - if err = ValidateHeader(sm.Pow, block.Header(), parent.Header(), false); err != nil { + if err = ValidateHeader(sm.Pow, header, parent.Header(), false); err != nil { return } // There can be at most two uncles - if len(block.Uncles()) > 2 { - return nil, ValidationError("Block can only contain maximum 2 uncles (contained %v)", len(block.Uncles())) + if len(uncles) > 2 { + return nil, ValidationError("Block can only contain maximum 2 uncles (contained %v)", len(uncles)) } receipts, err := sm.TransitionState(state, parent, block, false) @@ -199,8 +201,6 @@ func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (logs st return } - header := block.Header() - // Validate the received block's bloom with the one derived from the generated receipts. // For valid blocks this should always validate to true. rbloom := types.CreateBloom(receipts) @@ -211,7 +211,7 @@ func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (logs st // The transactions Trie's root (R = (Tr [[i, RLP(T1)], [i, RLP(T2)], ... [n, RLP(Tn)]])) // can be used by light clients to make sure they've received the correct Txs - txSha := types.DeriveSha(block.Transactions()) + txSha := types.DeriveSha(txs) if txSha != header.TxHash { err = fmt.Errorf("invalid transaction root hash. received=%x calculated=%x", header.TxHash, txSha) return @@ -225,7 +225,7 @@ func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (logs st } // Verify UncleHash before running other uncle validations - unclesSha := block.CalculateUnclesHash() + unclesSha := types.CalcUncleHash(uncles) if unclesSha != header.UncleHash { err = fmt.Errorf("invalid uncles root hash. received=%x calculated=%x", header.UncleHash, unclesSha) return @@ -236,7 +236,7 @@ func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (logs st return } // Accumulate static rewards; block reward, uncle's and uncle inclusion. - AccumulateRewards(state, block) + AccumulateRewards(state, header, uncles) // Commit state objects/accounts to a temporary trie (does not save) // used to calculate the state root. @@ -260,11 +260,34 @@ func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (logs st return state.Logs(), nil } +// 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. +func AccumulateRewards(statedb *state.StateDB, header *types.Header, uncles []*types.Header) { + reward := new(big.Int).Set(BlockReward) + + for _, uncle := range uncles { + num := new(big.Int).Add(big.NewInt(8), uncle.Number) + num.Sub(num, header.Number) + + r := new(big.Int) + r.Mul(BlockReward, num) + r.Div(r, big.NewInt(8)) + + statedb.AddBalance(uncle.Coinbase, r) + + reward.Add(reward, new(big.Int).Div(BlockReward, big.NewInt(32))) + } + + // Get the account associated with the coinbase + statedb.AddBalance(header.Coinbase, reward) +} + func (sm *BlockProcessor) VerifyUncles(statedb *state.StateDB, block, parent *types.Block) error { ancestors := set.New() uncles := set.New() ancestorHeaders := make(map[common.Hash]*types.Header) - for _, ancestor := range sm.bc.GetAncestors(block, 7) { + for _, ancestor := range sm.bc.GetBlocksFromHash(block.ParentHash(), 7) { ancestorHeaders[ancestor.Hash()] = ancestor.Header() ancestors.Add(ancestor.Hash()) // Include ancestors uncles in the uncle set. Uncles must be unique. @@ -325,7 +348,7 @@ func (sm *BlockProcessor) GetLogs(block *types.Block) (logs state.Logs, err erro // TODO: remove backward compatibility var ( - parent = sm.bc.GetBlock(block.Header().ParentHash) + parent = sm.bc.GetBlock(block.ParentHash()) state = state.New(parent.Root(), sm.db) ) @@ -341,7 +364,7 @@ func ValidateHeader(pow pow.PoW, block, parent *types.Header, checkPow bool) err return fmt.Errorf("Block extra data too long (%d)", len(block.Extra)) } - expd := CalcDifficulty(block, parent) + expd := CalcDifficulty(int64(block.Time), int64(parent.Time), parent.Difficulty) if expd.Cmp(block.Difficulty) != 0 { return fmt.Errorf("Difficulty check failed for block %v, %v", block.Difficulty, expd) } @@ -375,26 +398,6 @@ func ValidateHeader(pow pow.PoW, block, parent *types.Header, checkPow bool) err return nil } -func AccumulateRewards(statedb *state.StateDB, block *types.Block) { - reward := new(big.Int).Set(BlockReward) - - for _, uncle := range block.Uncles() { - num := new(big.Int).Add(big.NewInt(8), uncle.Number) - num.Sub(num, block.Number()) - - r := new(big.Int) - r.Mul(BlockReward, num) - r.Div(r, big.NewInt(8)) - - statedb.AddBalance(uncle.Coinbase, r) - - reward.Add(reward, new(big.Int).Div(BlockReward, big.NewInt(32))) - } - - // Get the account associated with the coinbase - statedb.AddBalance(block.Header().Coinbase, reward) -} - func getBlockReceipts(db common.Database, bhash common.Hash) (receipts types.Receipts, err error) { var rdata []byte rdata, err = db.Get(append(receiptsPre, bhash[:]...)) |