github.com/haliliceylan/bsc@v1.1.10-0.20220501224556-eb78d644ebcb/core/state_processor.go (about)

     1  // Copyright 2015 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  	"bytes"
    21  	"errors"
    22  	"fmt"
    23  	"math/big"
    24  	"math/rand"
    25  	"sync"
    26  	"time"
    27  
    28  	"github.com/ethereum/go-ethereum/common"
    29  	"github.com/ethereum/go-ethereum/common/gopool"
    30  	"github.com/ethereum/go-ethereum/consensus"
    31  	"github.com/ethereum/go-ethereum/consensus/misc"
    32  	"github.com/ethereum/go-ethereum/core/rawdb"
    33  	"github.com/ethereum/go-ethereum/core/state"
    34  	"github.com/ethereum/go-ethereum/core/state/snapshot"
    35  	"github.com/ethereum/go-ethereum/core/systemcontracts"
    36  	"github.com/ethereum/go-ethereum/core/types"
    37  	"github.com/ethereum/go-ethereum/core/vm"
    38  	"github.com/ethereum/go-ethereum/crypto"
    39  	"github.com/ethereum/go-ethereum/log"
    40  	"github.com/ethereum/go-ethereum/params"
    41  	"github.com/ethereum/go-ethereum/rlp"
    42  )
    43  
    44  const (
    45  	fullProcessCheck       = 21 // On diff sync mode, will do full process every fullProcessCheck randomly
    46  	recentTime             = 1024 * 3
    47  	recentDiffLayerTimeout = 5
    48  	farDiffLayerTimeout    = 2
    49  )
    50  
    51  // StateProcessor is a basic Processor, which takes care of transitioning
    52  // state from one point to another.
    53  //
    54  // StateProcessor implements Processor.
    55  type StateProcessor struct {
    56  	config *params.ChainConfig // Chain configuration options
    57  	bc     *BlockChain         // Canonical block chain
    58  	engine consensus.Engine    // Consensus engine used for block rewards
    59  }
    60  
    61  // NewStateProcessor initialises a new StateProcessor.
    62  func NewStateProcessor(config *params.ChainConfig, bc *BlockChain, engine consensus.Engine) *StateProcessor {
    63  	return &StateProcessor{
    64  		config: config,
    65  		bc:     bc,
    66  		engine: engine,
    67  	}
    68  }
    69  
    70  type LightStateProcessor struct {
    71  	check int64
    72  	StateProcessor
    73  }
    74  
    75  func NewLightStateProcessor(config *params.ChainConfig, bc *BlockChain, engine consensus.Engine) *LightStateProcessor {
    76  	randomGenerator := rand.New(rand.NewSource(int64(time.Now().Nanosecond())))
    77  	check := randomGenerator.Int63n(fullProcessCheck)
    78  	return &LightStateProcessor{
    79  		check:          check,
    80  		StateProcessor: *NewStateProcessor(config, bc, engine),
    81  	}
    82  }
    83  
    84  func (p *LightStateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg vm.Config) (*state.StateDB, types.Receipts, []*types.Log, uint64, error) {
    85  	allowLightProcess := true
    86  	if posa, ok := p.engine.(consensus.PoSA); ok {
    87  		allowLightProcess = posa.AllowLightProcess(p.bc, block.Header())
    88  	}
    89  	// random fallback to full process
    90  	if allowLightProcess && block.NumberU64()%fullProcessCheck != uint64(p.check) && len(block.Transactions()) != 0 {
    91  		var pid string
    92  		if peer, ok := block.ReceivedFrom.(PeerIDer); ok {
    93  			pid = peer.ID()
    94  		}
    95  		var diffLayer *types.DiffLayer
    96  		var diffLayerTimeout = recentDiffLayerTimeout
    97  		if time.Now().Unix()-int64(block.Time()) > recentTime {
    98  			diffLayerTimeout = farDiffLayerTimeout
    99  		}
   100  		for tried := 0; tried < diffLayerTimeout; tried++ {
   101  			// wait a bit for the diff layer
   102  			diffLayer = p.bc.GetUnTrustedDiffLayer(block.Hash(), pid)
   103  			if diffLayer != nil {
   104  				break
   105  			}
   106  			time.Sleep(time.Millisecond)
   107  		}
   108  		if diffLayer != nil {
   109  			if err := diffLayer.Receipts.DeriveFields(p.bc.chainConfig, block.Hash(), block.NumberU64(), block.Transactions()); err != nil {
   110  				log.Error("Failed to derive block receipts fields", "hash", block.Hash(), "number", block.NumberU64(), "err", err)
   111  				// fallback to full process
   112  				return p.StateProcessor.Process(block, statedb, cfg)
   113  			}
   114  
   115  			receipts, logs, gasUsed, err := p.LightProcess(diffLayer, block, statedb)
   116  			if err == nil {
   117  				log.Info("do light process success at block", "num", block.NumberU64())
   118  				return statedb, receipts, logs, gasUsed, nil
   119  			}
   120  			log.Error("do light process err at block", "num", block.NumberU64(), "err", err)
   121  			p.bc.removeDiffLayers(diffLayer.DiffHash)
   122  			// prepare new statedb
   123  			statedb.StopPrefetcher()
   124  			parent := p.bc.GetHeader(block.ParentHash(), block.NumberU64()-1)
   125  			statedb, err = state.New(parent.Root, p.bc.stateCache, p.bc.snaps)
   126  			if err != nil {
   127  				return statedb, nil, nil, 0, err
   128  			}
   129  			statedb.SetExpectedStateRoot(block.Root())
   130  			if p.bc.pipeCommit {
   131  				statedb.EnablePipeCommit()
   132  			}
   133  			// Enable prefetching to pull in trie node paths while processing transactions
   134  			statedb.StartPrefetcher("chain")
   135  		}
   136  	}
   137  	// fallback to full process
   138  	return p.StateProcessor.Process(block, statedb, cfg)
   139  }
   140  
   141  func (p *LightStateProcessor) LightProcess(diffLayer *types.DiffLayer, block *types.Block, statedb *state.StateDB) (types.Receipts, []*types.Log, uint64, error) {
   142  	statedb.MarkLightProcessed()
   143  	fullDiffCode := make(map[common.Hash][]byte, len(diffLayer.Codes))
   144  	diffTries := make(map[common.Address]state.Trie)
   145  	diffCode := make(map[common.Hash][]byte)
   146  
   147  	snapDestructs, snapAccounts, snapStorage, err := statedb.DiffLayerToSnap(diffLayer)
   148  	if err != nil {
   149  		return nil, nil, 0, err
   150  	}
   151  
   152  	for _, c := range diffLayer.Codes {
   153  		fullDiffCode[c.Hash] = c.Code
   154  	}
   155  	stateTrie, err := statedb.Trie()
   156  	if err != nil {
   157  		return nil, nil, 0, err
   158  	}
   159  	for des := range snapDestructs {
   160  		stateTrie.TryDelete(des[:])
   161  	}
   162  	threads := gopool.Threads(len(snapAccounts))
   163  
   164  	iteAccounts := make([]common.Address, 0, len(snapAccounts))
   165  	for diffAccount := range snapAccounts {
   166  		iteAccounts = append(iteAccounts, diffAccount)
   167  	}
   168  
   169  	errChan := make(chan error, threads)
   170  	exitChan := make(chan struct{})
   171  	var snapMux sync.RWMutex
   172  	var stateMux, diffMux sync.Mutex
   173  	for i := 0; i < threads; i++ {
   174  		start := i * len(iteAccounts) / threads
   175  		end := (i + 1) * len(iteAccounts) / threads
   176  		if i+1 == threads {
   177  			end = len(iteAccounts)
   178  		}
   179  		go func(start, end int) {
   180  			for index := start; index < end; index++ {
   181  				select {
   182  				// fast fail
   183  				case <-exitChan:
   184  					return
   185  				default:
   186  				}
   187  				diffAccount := iteAccounts[index]
   188  				snapMux.RLock()
   189  				blob := snapAccounts[diffAccount]
   190  				snapMux.RUnlock()
   191  				addrHash := crypto.Keccak256Hash(diffAccount[:])
   192  				latestAccount, err := snapshot.FullAccount(blob)
   193  				if err != nil {
   194  					errChan <- err
   195  					return
   196  				}
   197  
   198  				// fetch previous state
   199  				var previousAccount state.Account
   200  				stateMux.Lock()
   201  				enc, err := stateTrie.TryGet(diffAccount[:])
   202  				stateMux.Unlock()
   203  				if err != nil {
   204  					errChan <- err
   205  					return
   206  				}
   207  				if len(enc) != 0 {
   208  					if err := rlp.DecodeBytes(enc, &previousAccount); err != nil {
   209  						errChan <- err
   210  						return
   211  					}
   212  				}
   213  				if latestAccount.Balance == nil {
   214  					latestAccount.Balance = new(big.Int)
   215  				}
   216  				if previousAccount.Balance == nil {
   217  					previousAccount.Balance = new(big.Int)
   218  				}
   219  				if previousAccount.Root == (common.Hash{}) {
   220  					previousAccount.Root = types.EmptyRootHash
   221  				}
   222  				if len(previousAccount.CodeHash) == 0 {
   223  					previousAccount.CodeHash = types.EmptyCodeHash
   224  				}
   225  
   226  				// skip no change account
   227  				if previousAccount.Nonce == latestAccount.Nonce &&
   228  					bytes.Equal(previousAccount.CodeHash, latestAccount.CodeHash) &&
   229  					previousAccount.Balance.Cmp(latestAccount.Balance) == 0 &&
   230  					previousAccount.Root == common.BytesToHash(latestAccount.Root) {
   231  					// It is normal to receive redundant message since the collected message is redundant.
   232  					log.Debug("receive redundant account change in diff layer", "account", diffAccount, "num", block.NumberU64())
   233  					snapMux.Lock()
   234  					delete(snapAccounts, diffAccount)
   235  					delete(snapStorage, diffAccount)
   236  					snapMux.Unlock()
   237  					continue
   238  				}
   239  
   240  				// update code
   241  				codeHash := common.BytesToHash(latestAccount.CodeHash)
   242  				if !bytes.Equal(latestAccount.CodeHash, previousAccount.CodeHash) &&
   243  					!bytes.Equal(latestAccount.CodeHash, types.EmptyCodeHash) {
   244  					if code, exist := fullDiffCode[codeHash]; exist {
   245  						if crypto.Keccak256Hash(code) != codeHash {
   246  							errChan <- fmt.Errorf("code and code hash mismatch, account %s", diffAccount.String())
   247  							return
   248  						}
   249  						diffMux.Lock()
   250  						diffCode[codeHash] = code
   251  						diffMux.Unlock()
   252  					} else {
   253  						rawCode := rawdb.ReadCode(p.bc.db, codeHash)
   254  						if len(rawCode) == 0 {
   255  							errChan <- fmt.Errorf("missing code, account %s", diffAccount.String())
   256  							return
   257  						}
   258  					}
   259  				}
   260  
   261  				//update storage
   262  				latestRoot := common.BytesToHash(latestAccount.Root)
   263  				if latestRoot != previousAccount.Root {
   264  					accountTrie, err := statedb.Database().OpenStorageTrie(addrHash, previousAccount.Root)
   265  					if err != nil {
   266  						errChan <- err
   267  						return
   268  					}
   269  					snapMux.RLock()
   270  					storageChange, exist := snapStorage[diffAccount]
   271  					snapMux.RUnlock()
   272  
   273  					if !exist {
   274  						errChan <- errors.New("missing storage change in difflayer")
   275  						return
   276  					}
   277  					for k, v := range storageChange {
   278  						if len(v) != 0 {
   279  							accountTrie.TryUpdate([]byte(k), v)
   280  						} else {
   281  							accountTrie.TryDelete([]byte(k))
   282  						}
   283  					}
   284  
   285  					// check storage root
   286  					accountRootHash := accountTrie.Hash()
   287  					if latestRoot != accountRootHash {
   288  						errChan <- errors.New("account storage root mismatch")
   289  						return
   290  					}
   291  					diffMux.Lock()
   292  					diffTries[diffAccount] = accountTrie
   293  					diffMux.Unlock()
   294  				} else {
   295  					snapMux.Lock()
   296  					delete(snapStorage, diffAccount)
   297  					snapMux.Unlock()
   298  				}
   299  
   300  				// can't trust the blob, need encode by our-self.
   301  				latestStateAccount := state.Account{
   302  					Nonce:    latestAccount.Nonce,
   303  					Balance:  latestAccount.Balance,
   304  					Root:     common.BytesToHash(latestAccount.Root),
   305  					CodeHash: latestAccount.CodeHash,
   306  				}
   307  				bz, err := rlp.EncodeToBytes(&latestStateAccount)
   308  				if err != nil {
   309  					errChan <- err
   310  					return
   311  				}
   312  				stateMux.Lock()
   313  				err = stateTrie.TryUpdate(diffAccount[:], bz)
   314  				stateMux.Unlock()
   315  				if err != nil {
   316  					errChan <- err
   317  					return
   318  				}
   319  			}
   320  			errChan <- nil
   321  		}(start, end)
   322  	}
   323  
   324  	for i := 0; i < threads; i++ {
   325  		err := <-errChan
   326  		if err != nil {
   327  			close(exitChan)
   328  			return nil, nil, 0, err
   329  		}
   330  	}
   331  
   332  	var allLogs []*types.Log
   333  	var gasUsed uint64
   334  	for _, receipt := range diffLayer.Receipts {
   335  		allLogs = append(allLogs, receipt.Logs...)
   336  		gasUsed += receipt.GasUsed
   337  	}
   338  
   339  	// Do validate in advance so that we can fall back to full process
   340  	if err := p.bc.validator.ValidateState(block, statedb, diffLayer.Receipts, gasUsed); err != nil {
   341  		log.Error("validate state failed during diff sync", "error", err)
   342  		return nil, nil, 0, err
   343  	}
   344  
   345  	// remove redundant storage change
   346  	for account := range snapStorage {
   347  		if _, exist := snapAccounts[account]; !exist {
   348  			log.Warn("receive redundant storage change in diff layer")
   349  			delete(snapStorage, account)
   350  		}
   351  	}
   352  
   353  	// remove redundant code
   354  	if len(fullDiffCode) != len(diffLayer.Codes) {
   355  		diffLayer.Codes = make([]types.DiffCode, 0, len(diffCode))
   356  		for hash, code := range diffCode {
   357  			diffLayer.Codes = append(diffLayer.Codes, types.DiffCode{
   358  				Hash: hash,
   359  				Code: code,
   360  			})
   361  		}
   362  	}
   363  
   364  	statedb.SetSnapData(snapDestructs, snapAccounts, snapStorage)
   365  	if len(snapAccounts) != len(diffLayer.Accounts) || len(snapStorage) != len(diffLayer.Storages) {
   366  		diffLayer.Destructs, diffLayer.Accounts, diffLayer.Storages = statedb.SnapToDiffLayer()
   367  	}
   368  	statedb.SetDiff(diffLayer, diffTries, diffCode)
   369  
   370  	return diffLayer.Receipts, allLogs, gasUsed, nil
   371  }
   372  
   373  // Process processes the state changes according to the Ethereum rules by running
   374  // the transaction messages using the statedb and applying any rewards to both
   375  // the processor (coinbase) and any included uncles.
   376  //
   377  // Process returns the receipts and logs accumulated during the process and
   378  // returns the amount of gas that was used in the process. If any of the
   379  // transactions failed to execute due to insufficient gas it will return an error.
   380  func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg vm.Config) (*state.StateDB, types.Receipts, []*types.Log, uint64, error) {
   381  	var (
   382  		usedGas = new(uint64)
   383  		header  = block.Header()
   384  		allLogs []*types.Log
   385  		gp      = new(GasPool).AddGas(block.GasLimit())
   386  	)
   387  	signer := types.MakeSigner(p.bc.chainConfig, block.Number())
   388  	var receipts = make([]*types.Receipt, 0)
   389  	// Mutate the block and state according to any hard-fork specs
   390  	if p.config.DAOForkSupport && p.config.DAOForkBlock != nil && p.config.DAOForkBlock.Cmp(block.Number()) == 0 {
   391  		misc.ApplyDAOHardFork(statedb)
   392  	}
   393  	// Handle upgrade build-in system contract code
   394  	systemcontracts.UpgradeBuildInSystemContract(p.config, block.Number(), statedb)
   395  
   396  	blockContext := NewEVMBlockContext(header, p.bc, nil)
   397  	vmenv := vm.NewEVM(blockContext, vm.TxContext{}, statedb, p.config, cfg)
   398  
   399  	txNum := len(block.Transactions())
   400  	// Iterate over and process the individual transactions
   401  	posa, isPoSA := p.engine.(consensus.PoSA)
   402  	commonTxs := make([]*types.Transaction, 0, txNum)
   403  
   404  	// initilise bloom processors
   405  	bloomProcessors := NewAsyncReceiptBloomGenerator(txNum)
   406  	statedb.MarkFullProcessed()
   407  
   408  	// usually do have two tx, one for validator set contract, another for system reward contract.
   409  	systemTxs := make([]*types.Transaction, 0, 2)
   410  	for i, tx := range block.Transactions() {
   411  		if isPoSA {
   412  			if isSystemTx, err := posa.IsSystemTransaction(tx, block.Header()); err != nil {
   413  				return statedb, nil, nil, 0, err
   414  			} else if isSystemTx {
   415  				systemTxs = append(systemTxs, tx)
   416  				continue
   417  			}
   418  		}
   419  
   420  		msg, err := tx.AsMessage(signer)
   421  		if err != nil {
   422  			return statedb, nil, nil, 0, err
   423  		}
   424  		statedb.Prepare(tx.Hash(), block.Hash(), i)
   425  		receipt, err := applyTransaction(msg, p.config, p.bc, nil, gp, statedb, header, tx, usedGas, vmenv, bloomProcessors)
   426  		if err != nil {
   427  			return statedb, nil, nil, 0, fmt.Errorf("could not apply tx %d [%v]: %w", i, tx.Hash().Hex(), err)
   428  		}
   429  
   430  		commonTxs = append(commonTxs, tx)
   431  		receipts = append(receipts, receipt)
   432  	}
   433  	bloomProcessors.Close()
   434  
   435  	// Finalize the block, applying any consensus engine specific extras (e.g. block rewards)
   436  	err := p.engine.Finalize(p.bc, header, statedb, &commonTxs, block.Uncles(), &receipts, &systemTxs, usedGas)
   437  	if err != nil {
   438  		return statedb, receipts, allLogs, *usedGas, err
   439  	}
   440  	for _, receipt := range receipts {
   441  		allLogs = append(allLogs, receipt.Logs...)
   442  	}
   443  
   444  	return statedb, receipts, allLogs, *usedGas, nil
   445  }
   446  
   447  func applyTransaction(msg types.Message, config *params.ChainConfig, bc ChainContext, author *common.Address, gp *GasPool, statedb *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *uint64, evm *vm.EVM, receiptProcessors ...ReceiptProcessor) (*types.Receipt, error) {
   448  	// Create a new context to be used in the EVM environment.
   449  	txContext := NewEVMTxContext(msg)
   450  	evm.Reset(txContext, statedb)
   451  
   452  	// Apply the transaction to the current state (included in the env).
   453  	result, err := ApplyMessage(evm, msg, gp)
   454  	if err != nil {
   455  		return nil, err
   456  	}
   457  
   458  	// Update the state with pending changes.
   459  	var root []byte
   460  	if config.IsByzantium(header.Number) {
   461  		statedb.Finalise(true)
   462  	} else {
   463  		root = statedb.IntermediateRoot(config.IsEIP158(header.Number)).Bytes()
   464  	}
   465  	*usedGas += result.UsedGas
   466  
   467  	// Create a new receipt for the transaction, storing the intermediate root and gas used
   468  	// by the tx.
   469  	receipt := &types.Receipt{Type: tx.Type(), PostState: root, CumulativeGasUsed: *usedGas}
   470  	if result.Failed() {
   471  		receipt.Status = types.ReceiptStatusFailed
   472  	} else {
   473  		receipt.Status = types.ReceiptStatusSuccessful
   474  	}
   475  	receipt.TxHash = tx.Hash()
   476  	receipt.GasUsed = result.UsedGas
   477  
   478  	// If the transaction created a contract, store the creation address in the receipt.
   479  	if msg.To() == nil {
   480  		receipt.ContractAddress = crypto.CreateAddress(evm.TxContext.Origin, tx.Nonce())
   481  	}
   482  
   483  	// Set the receipt logs and create the bloom filter.
   484  	receipt.Logs = statedb.GetLogs(tx.Hash())
   485  	receipt.BlockHash = statedb.BlockHash()
   486  	receipt.BlockNumber = header.Number
   487  	receipt.TransactionIndex = uint(statedb.TxIndex())
   488  	for _, receiptProcessor := range receiptProcessors {
   489  		receiptProcessor.Apply(receipt)
   490  	}
   491  	return receipt, err
   492  }
   493  
   494  // ApplyTransaction attempts to apply a transaction to the given state database
   495  // and uses the input parameters for its environment. It returns the receipt
   496  // for the transaction, gas used and an error if the transaction failed,
   497  // indicating the block was invalid.
   498  func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *common.Address, gp *GasPool, statedb *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *uint64, cfg vm.Config, receiptProcessors ...ReceiptProcessor) (*types.Receipt, error) {
   499  	msg, err := tx.AsMessage(types.MakeSigner(config, header.Number))
   500  	if err != nil {
   501  		return nil, err
   502  	}
   503  	// Create a new context to be used in the EVM environment
   504  	blockContext := NewEVMBlockContext(header, bc, author)
   505  	vmenv := vm.NewEVM(blockContext, vm.TxContext{}, statedb, config, cfg)
   506  	defer func() {
   507  		ite := vmenv.Interpreter()
   508  		vm.EVMInterpreterPool.Put(ite)
   509  		vm.EvmPool.Put(vmenv)
   510  	}()
   511  	return applyTransaction(msg, config, bc, author, gp, statedb, header, tx, usedGas, vmenv, receiptProcessors...)
   512  }