github.com/jeffallen/go-ethereum@v1.1.4-0.20150910155051-571d3236c49c/core/block_processor.go (about)

     1  // Copyright 2014 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package core
    18  
    19  import (
    20  	"fmt"
    21  	"math/big"
    22  	"sync"
    23  	"time"
    24  
    25  	"github.com/ethereum/go-ethereum/common"
    26  	"github.com/ethereum/go-ethereum/core/state"
    27  	"github.com/ethereum/go-ethereum/core/types"
    28  	"github.com/ethereum/go-ethereum/crypto"
    29  	"github.com/ethereum/go-ethereum/event"
    30  	"github.com/ethereum/go-ethereum/logger"
    31  	"github.com/ethereum/go-ethereum/logger/glog"
    32  	"github.com/ethereum/go-ethereum/params"
    33  	"github.com/ethereum/go-ethereum/pow"
    34  	"gopkg.in/fatih/set.v0"
    35  )
    36  
    37  const (
    38  	// must be bumped when consensus algorithm is changed, this forces the upgradedb
    39  	// command to be run (forces the blocks to be imported again using the new algorithm)
    40  	BlockChainVersion = 3
    41  )
    42  
    43  type BlockProcessor struct {
    44  	chainDb common.Database
    45  	// Mutex for locking the block processor. Blocks can only be handled one at a time
    46  	mutex sync.Mutex
    47  	// Canonical block chain
    48  	bc *ChainManager
    49  	// non-persistent key/value memory storage
    50  	mem map[string]*big.Int
    51  	// Proof of work used for validating
    52  	Pow pow.PoW
    53  
    54  	events event.Subscription
    55  
    56  	eventMux *event.TypeMux
    57  }
    58  
    59  // TODO: type GasPool big.Int
    60  //
    61  // GasPool is implemented by state.StateObject. This is a historical
    62  // coincidence. Gas tracking should move out of StateObject.
    63  
    64  // GasPool tracks the amount of gas available during
    65  // execution of the transactions in a block.
    66  type GasPool interface {
    67  	AddGas(gas, price *big.Int)
    68  	SubGas(gas, price *big.Int) error
    69  }
    70  
    71  func NewBlockProcessor(db common.Database, pow pow.PoW, chainManager *ChainManager, eventMux *event.TypeMux) *BlockProcessor {
    72  	sm := &BlockProcessor{
    73  		chainDb:  db,
    74  		mem:      make(map[string]*big.Int),
    75  		Pow:      pow,
    76  		bc:       chainManager,
    77  		eventMux: eventMux,
    78  	}
    79  	return sm
    80  }
    81  
    82  func (sm *BlockProcessor) TransitionState(statedb *state.StateDB, parent, block *types.Block, transientProcess bool) (receipts types.Receipts, err error) {
    83  	gp := statedb.GetOrNewStateObject(block.Coinbase())
    84  	gp.SetGasLimit(block.GasLimit())
    85  
    86  	// Process the transactions on to parent state
    87  	receipts, err = sm.ApplyTransactions(gp, statedb, block, block.Transactions(), transientProcess)
    88  	if err != nil {
    89  		return nil, err
    90  	}
    91  
    92  	return receipts, nil
    93  }
    94  
    95  func (self *BlockProcessor) ApplyTransaction(gp GasPool, statedb *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *big.Int, transientProcess bool) (*types.Receipt, *big.Int, error) {
    96  	_, gas, err := ApplyMessage(NewEnv(statedb, self.bc, tx, header), tx, gp)
    97  	if err != nil {
    98  		return nil, nil, err
    99  	}
   100  
   101  	// Update the state with pending changes
   102  	statedb.SyncIntermediate()
   103  
   104  	usedGas.Add(usedGas, gas)
   105  	receipt := types.NewReceipt(statedb.Root().Bytes(), usedGas)
   106  	receipt.TxHash = tx.Hash()
   107  	receipt.GasUsed = new(big.Int).Set(gas)
   108  	if MessageCreatesContract(tx) {
   109  		from, _ := tx.From()
   110  		receipt.ContractAddress = crypto.CreateAddress(from, tx.Nonce())
   111  	}
   112  
   113  	logs := statedb.GetLogs(tx.Hash())
   114  	receipt.SetLogs(logs)
   115  	receipt.Bloom = types.CreateBloom(types.Receipts{receipt})
   116  
   117  	glog.V(logger.Debug).Infoln(receipt)
   118  
   119  	// Notify all subscribers
   120  	if !transientProcess {
   121  		go self.eventMux.Post(TxPostEvent{tx})
   122  		go self.eventMux.Post(logs)
   123  	}
   124  
   125  	return receipt, gas, err
   126  }
   127  func (self *BlockProcessor) ChainManager() *ChainManager {
   128  	return self.bc
   129  }
   130  
   131  func (self *BlockProcessor) ApplyTransactions(gp GasPool, statedb *state.StateDB, block *types.Block, txs types.Transactions, transientProcess bool) (types.Receipts, error) {
   132  	var (
   133  		receipts      types.Receipts
   134  		totalUsedGas  = big.NewInt(0)
   135  		err           error
   136  		cumulativeSum = new(big.Int)
   137  		header        = block.Header()
   138  	)
   139  
   140  	for i, tx := range txs {
   141  		statedb.StartRecord(tx.Hash(), block.Hash(), i)
   142  
   143  		receipt, txGas, err := self.ApplyTransaction(gp, statedb, header, tx, totalUsedGas, transientProcess)
   144  		if err != nil {
   145  			return nil, err
   146  		}
   147  
   148  		if err != nil {
   149  			glog.V(logger.Core).Infoln("TX err:", err)
   150  		}
   151  		receipts = append(receipts, receipt)
   152  
   153  		cumulativeSum.Add(cumulativeSum, new(big.Int).Mul(txGas, tx.GasPrice()))
   154  	}
   155  
   156  	if block.GasUsed().Cmp(totalUsedGas) != 0 {
   157  		return nil, ValidationError(fmt.Sprintf("gas used error (%v / %v)", block.GasUsed(), totalUsedGas))
   158  	}
   159  
   160  	if transientProcess {
   161  		go self.eventMux.Post(PendingBlockEvent{block, statedb.Logs()})
   162  	}
   163  
   164  	return receipts, err
   165  }
   166  
   167  func (sm *BlockProcessor) RetryProcess(block *types.Block) (logs state.Logs, err error) {
   168  	// Processing a blocks may never happen simultaneously
   169  	sm.mutex.Lock()
   170  	defer sm.mutex.Unlock()
   171  
   172  	if !sm.bc.HasBlock(block.ParentHash()) {
   173  		return nil, ParentError(block.ParentHash())
   174  	}
   175  	parent := sm.bc.GetBlock(block.ParentHash())
   176  
   177  	// FIXME Change to full header validation. See #1225
   178  	errch := make(chan bool)
   179  	go func() { errch <- sm.Pow.Verify(block) }()
   180  
   181  	logs, _, err = sm.processWithParent(block, parent)
   182  	if !<-errch {
   183  		return nil, ValidationError("Block's nonce is invalid (= %x)", block.Nonce)
   184  	}
   185  
   186  	return logs, err
   187  }
   188  
   189  // Process block will attempt to process the given block's transactions and applies them
   190  // on top of the block's parent state (given it exists) and will return wether it was
   191  // successful or not.
   192  func (sm *BlockProcessor) Process(block *types.Block) (logs state.Logs, receipts types.Receipts, err error) {
   193  	// Processing a blocks may never happen simultaneously
   194  	sm.mutex.Lock()
   195  	defer sm.mutex.Unlock()
   196  
   197  	if sm.bc.HasBlock(block.Hash()) {
   198  		return nil, nil, &KnownBlockError{block.Number(), block.Hash()}
   199  	}
   200  
   201  	if !sm.bc.HasBlock(block.ParentHash()) {
   202  		return nil, nil, ParentError(block.ParentHash())
   203  	}
   204  	parent := sm.bc.GetBlock(block.ParentHash())
   205  	return sm.processWithParent(block, parent)
   206  }
   207  
   208  func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (logs state.Logs, receipts types.Receipts, err error) {
   209  	// Create a new state based on the parent's root (e.g., create copy)
   210  	state := state.New(parent.Root(), sm.chainDb)
   211  	header := block.Header()
   212  	uncles := block.Uncles()
   213  	txs := block.Transactions()
   214  
   215  	// Block validation
   216  	if err = ValidateHeader(sm.Pow, header, parent, false, false); err != nil {
   217  		return
   218  	}
   219  
   220  	// There can be at most two uncles
   221  	if len(uncles) > 2 {
   222  		return nil, nil, ValidationError("Block can only contain maximum 2 uncles (contained %v)", len(uncles))
   223  	}
   224  
   225  	receipts, err = sm.TransitionState(state, parent, block, false)
   226  	if err != nil {
   227  		return
   228  	}
   229  
   230  	// Validate the received block's bloom with the one derived from the generated receipts.
   231  	// For valid blocks this should always validate to true.
   232  	rbloom := types.CreateBloom(receipts)
   233  	if rbloom != header.Bloom {
   234  		err = fmt.Errorf("unable to replicate block's bloom=%x", rbloom)
   235  		return
   236  	}
   237  
   238  	// The transactions Trie's root (R = (Tr [[i, RLP(T1)], [i, RLP(T2)], ... [n, RLP(Tn)]]))
   239  	// can be used by light clients to make sure they've received the correct Txs
   240  	txSha := types.DeriveSha(txs)
   241  	if txSha != header.TxHash {
   242  		err = fmt.Errorf("invalid transaction root hash. received=%x calculated=%x", header.TxHash, txSha)
   243  		return
   244  	}
   245  
   246  	// Tre receipt Trie's root (R = (Tr [[H1, R1], ... [Hn, R1]]))
   247  	receiptSha := types.DeriveSha(receipts)
   248  	if receiptSha != header.ReceiptHash {
   249  		err = fmt.Errorf("invalid receipt root hash. received=%x calculated=%x", header.ReceiptHash, receiptSha)
   250  		return
   251  	}
   252  
   253  	// Verify UncleHash before running other uncle validations
   254  	unclesSha := types.CalcUncleHash(uncles)
   255  	if unclesSha != header.UncleHash {
   256  		err = fmt.Errorf("invalid uncles root hash. received=%x calculated=%x", header.UncleHash, unclesSha)
   257  		return
   258  	}
   259  
   260  	// Verify uncles
   261  	if err = sm.VerifyUncles(state, block, parent); err != nil {
   262  		return
   263  	}
   264  	// Accumulate static rewards; block reward, uncle's and uncle inclusion.
   265  	AccumulateRewards(state, header, uncles)
   266  
   267  	// Commit state objects/accounts to a temporary trie (does not save)
   268  	// used to calculate the state root.
   269  	state.SyncObjects()
   270  	if header.Root != state.Root() {
   271  		err = fmt.Errorf("invalid merkle root. received=%x got=%x", header.Root, state.Root())
   272  		return
   273  	}
   274  
   275  	// Sync the current block's state to the database
   276  	state.Sync()
   277  
   278  	return state.Logs(), receipts, nil
   279  }
   280  
   281  var (
   282  	big8  = big.NewInt(8)
   283  	big32 = big.NewInt(32)
   284  )
   285  
   286  // AccumulateRewards credits the coinbase of the given block with the
   287  // mining reward. The total reward consists of the static block reward
   288  // and rewards for included uncles. The coinbase of each uncle block is
   289  // also rewarded.
   290  func AccumulateRewards(statedb *state.StateDB, header *types.Header, uncles []*types.Header) {
   291  	reward := new(big.Int).Set(BlockReward)
   292  	r := new(big.Int)
   293  	for _, uncle := range uncles {
   294  		r.Add(uncle.Number, big8)
   295  		r.Sub(r, header.Number)
   296  		r.Mul(r, BlockReward)
   297  		r.Div(r, big8)
   298  		statedb.AddBalance(uncle.Coinbase, r)
   299  
   300  		r.Div(BlockReward, big32)
   301  		reward.Add(reward, r)
   302  	}
   303  	statedb.AddBalance(header.Coinbase, reward)
   304  }
   305  
   306  func (sm *BlockProcessor) VerifyUncles(statedb *state.StateDB, block, parent *types.Block) error {
   307  	uncles := set.New()
   308  	ancestors := make(map[common.Hash]*types.Block)
   309  	for _, ancestor := range sm.bc.GetBlocksFromHash(block.ParentHash(), 7) {
   310  		ancestors[ancestor.Hash()] = ancestor
   311  		// Include ancestors uncles in the uncle set. Uncles must be unique.
   312  		for _, uncle := range ancestor.Uncles() {
   313  			uncles.Add(uncle.Hash())
   314  		}
   315  	}
   316  	ancestors[block.Hash()] = block
   317  	uncles.Add(block.Hash())
   318  
   319  	for i, uncle := range block.Uncles() {
   320  		hash := uncle.Hash()
   321  		if uncles.Has(hash) {
   322  			// Error not unique
   323  			return UncleError("uncle[%d](%x) not unique", i, hash[:4])
   324  		}
   325  		uncles.Add(hash)
   326  
   327  		if ancestors[hash] != nil {
   328  			branch := fmt.Sprintf("  O - %x\n  |\n", block.Hash())
   329  			for h := range ancestors {
   330  				branch += fmt.Sprintf("  O - %x\n  |\n", h)
   331  			}
   332  			glog.Infoln(branch)
   333  			return UncleError("uncle[%d](%x) is ancestor", i, hash[:4])
   334  		}
   335  
   336  		if ancestors[uncle.ParentHash] == nil || uncle.ParentHash == parent.Hash() {
   337  			return UncleError("uncle[%d](%x)'s parent is not ancestor (%x)", i, hash[:4], uncle.ParentHash[0:4])
   338  		}
   339  
   340  		if err := ValidateHeader(sm.Pow, uncle, ancestors[uncle.ParentHash], true, true); err != nil {
   341  			return ValidationError(fmt.Sprintf("uncle[%d](%x) header invalid: %v", i, hash[:4], err))
   342  		}
   343  	}
   344  
   345  	return nil
   346  }
   347  
   348  // GetBlockReceipts returns the receipts beloniging to the block hash
   349  func (sm *BlockProcessor) GetBlockReceipts(bhash common.Hash) types.Receipts {
   350  	if block := sm.ChainManager().GetBlock(bhash); block != nil {
   351  		return GetBlockReceipts(sm.chainDb, block.Hash())
   352  	}
   353  
   354  	return nil
   355  }
   356  
   357  // GetLogs returns the logs of the given block. This method is using a two step approach
   358  // where it tries to get it from the (updated) method which gets them from the receipts or
   359  // the depricated way by re-processing the block.
   360  func (sm *BlockProcessor) GetLogs(block *types.Block) (logs state.Logs, err error) {
   361  	receipts := GetBlockReceipts(sm.chainDb, block.Hash())
   362  	// coalesce logs
   363  	for _, receipt := range receipts {
   364  		logs = append(logs, receipt.Logs()...)
   365  	}
   366  	return logs, nil
   367  }
   368  
   369  // See YP section 4.3.4. "Block Header Validity"
   370  // Validates a block. Returns an error if the block is invalid.
   371  func ValidateHeader(pow pow.PoW, block *types.Header, parent *types.Block, checkPow, uncle bool) error {
   372  	if big.NewInt(int64(len(block.Extra))).Cmp(params.MaximumExtraDataSize) == 1 {
   373  		return fmt.Errorf("Block extra data too long (%d)", len(block.Extra))
   374  	}
   375  
   376  	if uncle {
   377  		if block.Time.Cmp(common.MaxBig) == 1 {
   378  			return BlockTSTooBigErr
   379  		}
   380  	} else {
   381  		if block.Time.Cmp(big.NewInt(time.Now().Unix())) == 1 {
   382  			return BlockFutureErr
   383  		}
   384  	}
   385  	if block.Time.Cmp(parent.Time()) != 1 {
   386  		return BlockEqualTSErr
   387  	}
   388  
   389  	expd := CalcDifficulty(block.Time.Uint64(), parent.Time().Uint64(), parent.Number(), parent.Difficulty())
   390  	if expd.Cmp(block.Difficulty) != 0 {
   391  		return fmt.Errorf("Difficulty check failed for block %v, %v", block.Difficulty, expd)
   392  	}
   393  
   394  	var a, b *big.Int
   395  	a = parent.GasLimit()
   396  	a = a.Sub(a, block.GasLimit)
   397  	a.Abs(a)
   398  	b = parent.GasLimit()
   399  	b = b.Div(b, params.GasLimitBoundDivisor)
   400  	if !(a.Cmp(b) < 0) || (block.GasLimit.Cmp(params.MinGasLimit) == -1) {
   401  		return fmt.Errorf("GasLimit check failed for block %v (%v > %v)", block.GasLimit, a, b)
   402  	}
   403  
   404  	num := parent.Number()
   405  	num.Sub(block.Number, num)
   406  	if num.Cmp(big.NewInt(1)) != 0 {
   407  		return BlockNumberErr
   408  	}
   409  
   410  	if checkPow {
   411  		// Verify the nonce of the block. Return an error if it's not valid
   412  		if !pow.Verify(types.NewBlockWithHeader(block)) {
   413  			return ValidationError("Block's nonce is invalid (= %x)", block.Nonce)
   414  		}
   415  	}
   416  
   417  	return nil
   418  }