github.com/hxy-daniel/soda-study@v0.0.0-20210825114314-29b7dcb300f1/SODA_code/go-ethereum/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  	"github.com/ethereum/go-ethereum/common"
    21  	"github.com/ethereum/go-ethereum/consensus"
    22  	"github.com/ethereum/go-ethereum/consensus/misc"
    23  	"github.com/ethereum/go-ethereum/core/state"
    24  	"github.com/ethereum/go-ethereum/core/types"
    25  	"github.com/ethereum/go-ethereum/core/vm"
    26  	"github.com/ethereum/go-ethereum/crypto"
    27  	"github.com/ethereum/go-ethereum/params"
    28  	//add new 
    29  	"github.com/ethereum/collector"
    30  	// "syscall"
    31  	"strconv"
    32  	"fmt"
    33  	"github.com/ethereum/go-ethereum/tingrong"
    34  	"github.com/ethereum/go-ethereum/cmd/pluginManage"
    35  	"github.com/ethereum/go-ethereum/fei"
    36  )
    37  
    38  // StateProcessor is a basic Processor, which takes care of transitioning
    39  // state from one point to another.
    40  //
    41  // StateProcessor implements Processor.
    42  type StateProcessor struct {
    43  	config *params.ChainConfig // Chain configuration options
    44  	bc     *BlockChain         // Canonical block chain 规范区块链
    45  	engine consensus.Engine    // Consensus engine used for block rewards
    46  }
    47  
    48  // NewStateProcessor initialises a new StateProcessor.
    49  func NewStateProcessor(config *params.ChainConfig, bc *BlockChain, engine consensus.Engine) *StateProcessor {
    50  	return &StateProcessor{
    51  		config: config,
    52  		bc:     bc,
    53  		engine: engine,
    54  	}
    55  }
    56  
    57  // Process processes the state changes according to the Ethereum rules by running
    58  // the transaction messages using the statedb and applying any rewards to both
    59  // the processor (coinbase) and any included uncles.
    60  //
    61  // Process returns the receipts and logs accumulated during the process and
    62  // returns the amount of gas that was used in the process. If any of the
    63  // transactions failed to execute due to insufficient gas it will return an error.
    64  func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg vm.Config) (types.Receipts, []*types.Log, uint64, error) {
    65  	var (
    66  		receipts types.Receipts
    67  		usedGas  = new(uint64)
    68  		header   = block.Header()
    69  		allLogs  []*types.Log
    70  		gp       = new(GasPool).AddGas(block.GasLimit())
    71  	)
    72  	// Mutate the block and state according to any hard-fork specs / 根据任何硬分叉规范改变块和状态
    73  	if p.config.DAOForkSupport && p.config.DAOForkBlock != nil && p.config.DAOForkBlock.Cmp(block.Number()) == 0 {
    74  		misc.ApplyDAOHardFork(statedb)
    75  	}
    76  
    77  	//add new
    78  	// 区块收集器
    79  	// 如果plg.plugins[handle_BLOCK_INFO]存在,即需要该信息
    80  	if p.config.TransferDataPlg.GetOpcodeRegister("handle_BLOCK_INFO"){
    81  		blockcollector := collector.NewBlockCollector()
    82  		blockcollector.Op = "Block"+fmt.Sprintf("%v", header.Number)
    83  		blockcollector.ParentHash = header.ParentHash.String()
    84  		blockcollector.UncleHash = header.UncleHash.String()
    85  		blockcollector.Coinbase = header.Coinbase.String()
    86  		blockcollector.StateRoot = header.Root.String()
    87  		blockcollector.TxHashRoot = header.TxHash.String()
    88  		blockcollector.ReceiptHash = header.ReceiptHash.String()
    89  		blockcollector.Difficulty = header.Difficulty.String()
    90  		blockcollector.Number = header.Number.String()
    91  		blockcollector.GasLimit = header.GasLimit
    92  		blockcollector.GasUsed = header.GasUsed
    93  		blockcollector.Time = header.Time
    94  		blockcollector.Extra = header.Extra
    95  		blockcollector.MixDigest = header.MixDigest.String()
    96  		blockcollector.Nonce = header.Nonce.Uint64()
    97  
    98  		// TransferDataPlg:/cmd/pluginManage/pluginManage.go/PluginManages 即调用PluginManages的SendDataToPlugin()函数
    99  		p.config.TransferDataPlg.SendDataToPlugin("handle_BLOCK_INFO",blockcollector.SendBlockInfo("handle_BLOCK_INFO"))
   100  	}
   101  	//add new
   102  
   103  	// Iterate over and process the individual transactions
   104  	for i, tx := range block.Transactions() {
   105  		statedb.Prepare(tx.Hash(), block.Hash(), i)
   106  		receipt, _, err := ApplyTransaction(p.config, p.bc, nil, gp, statedb, header, tx, usedGas, cfg)
   107  		if err != nil {
   108  			return nil, nil, 0, err
   109  		}
   110  		receipts = append(receipts, receipt)
   111  		allLogs = append(allLogs, receipt.Logs...)
   112  	}
   113  
   114  	
   115  
   116  	// Finalize the block, applying any consensus engine specific extras (e.g. block rewards) / 完成区块,应用任何共识引擎特定的附加功能(比如区块奖励)
   117  	p.engine.Finalize(p.bc, header, statedb, block.Transactions(), block.Uncles())
   118  
   119  	return receipts, allLogs, *usedGas, nil
   120  }
   121  
   122  // ApplyTransaction attempts to apply a transaction to the given state database
   123  // and uses the input parameters for its environment. It returns the receipt
   124  // for the transaction, gas used and an error if the transaction failed,
   125  // indicating the block was invalid.
   126  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) (*types.Receipt, uint64, error) {
   127  	msg, err := tx.AsMessage(types.MakeSigner(config, header.Number))
   128  	if err != nil {
   129  		return nil, 0, err
   130  	}
   131  
   132  	// Create a new context to be used in the EVM environment
   133  	context := NewEVMContext(msg, header, bc, author)
   134  	// Create a new environment which holds all relevant information
   135  	// about the transaction and calling mechanisms.
   136  	vmenv := vm.NewEVM(context, statedb, config, cfg)
   137  
   138  	//add new 
   139  	// 交易收集器:外部交易,SODA_code/go-ethereum/core/vm/interpreter.go/和SODA_code/go-ethereum/core/vm/instructions.go中还有内部交易
   140  	vmenv.SetTxStart(true)
   141  	vmenv.ChainConfig().TransferDataPlg.Start()
   142  
   143  	//feifei add new --api
   144  	if fei.IsReg {
   145  		// //whole folder fresh有问题,如果全部移除,是无法删掉旧的的。需要用new去新增
   146  		// pluginManage.StartRun(vmenv.ChainConfig().TransferDataPlg)
   147  		// fei.IsReg = false
   148  
   149  		//single plugin
   150  		pluginManage.RegisterPlugin(vmenv.ChainConfig().TransferDataPlg, fei.RegPath)
   151  		fei.RegPath = fei.Clear
   152  		fei.IsReg = false
   153  	}
   154  
   155  	if fei.IsUn {
   156  		vmenv.ChainConfig().TransferDataPlg.UnRegisterPlg()
   157  		fei.IsUn = false
   158  		fei.UnPlg = fei.Clear
   159  	}
   160  
   161  	tingrong.CALL_LAYER = 0
   162  	tingrong.CALL_STACK = nil
   163  	tingrong.ALL_STACK = nil
   164  	tingrong.EXTERNAL_FLAG = true
   165  	tingrong.BLOCKING_FLAG = false
   166  	tingrong.PLUGIN_SNAPSHOT_ID = 0 
   167  	tingrong.CALLVALID_MAP = make(map[int]bool)
   168  	tingrong.TxHash =  tx.Hash().String()
   169  
   170  	// if vmenv.BlockNumber.Int64() >= 2300001{
   171  	// 	if vmenv.ChainConfig().TransferDataPlg.GetOpcodeRegister("ENDSIGNAL") {
   172  	// 		vmenv.ChainConfig().TransferDataPlg.SendDataToPlugin("ENDSIGNAL", collector.SendFlag("ENDSIGNAL"))
   173  	// 	}
   174  	// 	fmt.Println("!!!!!!!!!!!!!!   ", vmenv.BlockNumber, "   EXIT")
   175  	// 	syscall.Kill(syscall.Getpid(), syscall.SIGINT)
   176  	// }
   177  
   178  
   179  	if msg.To() != nil{
   180  		tingrong.CALL_LAYER += 1
   181  		tingrong.CALL_STACK = append(tingrong.CALL_STACK,msg.To().String()+"#"+strconv.Itoa(tingrong.CALL_LAYER))
   182  		tingrong.ALL_STACK = append(tingrong.ALL_STACK,msg.To().String())
   183  	}
   184  
   185  	if vmenv.ChainConfig().TransferDataPlg.GetOpcodeRegister("TXSTART"){
   186  		vmenv.ChainConfig().TransferDataPlg.SendDataToPlugin("TXSTART", collector.SendFlag("TXSTART"))
   187  	}
   188  
   189  	tcstart := collector.NewTransCollector()
   190  
   191  	//external collector
   192  	if vmenv.ChainConfig().TransferDataPlg.GetOpcodeRegister("EXTERNALINFOSTART"){
   193  		tcstart.Op = "EXTERNALINFOSTART"
   194  		tcstart.TxHash = tx.Hash().String()
   195  		tcstart.BlockNumber = vmenv.BlockNumber.String()
   196  		tcstart.BlockTime = vmenv.Time.String()
   197  		tcstart.From = msg.From().String()
   198  		tcstart.Value = msg.Value().String()
   199  		tcstart.GasPrice = msg.GasPrice().String()
   200  		tcstart.GasLimit = msg.Gas()
   201  		tcstart.Nonce = tx.Nonce()
   202  		tcstart.CallLayer = 1
   203  		if msg.To() != nil {
   204  			tcstart.CallType = "CALL"
   205  			tcstart.To = msg.To().String()
   206  			
   207  			callcollector := collector.NewCallCollector()
   208  			if vmenv.StateDB.Exist(*msg.To()) {
   209  				callcollector.ContractCode = vmenv.StateDB.GetCode(*msg.To())
   210  			}
   211  			callcollector.InputData = msg.Data()			
   212  			tcstart.CallInfo = *callcollector
   213  		}
   214  		vmenv.ChainConfig().TransferDataPlg.SendDataToPlugin("EXTERNALINFOSTART", tcstart.SendTransInfo("EXTERNALINFOSTART"))
   215  
   216  	}
   217  
   218  	
   219  	//add new 
   220  
   221  	// Apply the transaction to the current state (included in the env)
   222  	_, gas, failed, err := ApplyMessage(vmenv, msg, gp)
   223  
   224  
   225  	//add new 
   226  	if tingrong.BLOCKING_FLAG == true{
   227  		statedb.RevertToSnapshot(tingrong.PLUGIN_SNAPSHOT_ID)
   228  	}
   229  	//add new 
   230  
   231  
   232  	tcend := collector.NewTransCollector()
   233  
   234  	//add new 
   235  	if vmenv.ChainConfig().TransferDataPlg.GetOpcodeRegister("EXTERNALINFOEND"){
   236  		tcend.Op = "EXTERNALINFOEND"
   237  		tcend.TxHash = tx.Hash().String()
   238  		tcend.GasUsed = gas
   239  		tcend.CallLayer = 1
   240  	}
   241  	//add new 
   242  
   243  	if err != nil {
   244  		//add new 
   245  		if vmenv.ChainConfig().TransferDataPlg.GetOpcodeRegister("EXTERNALINFOEND"){
   246  			tcend.IsSuccess = false
   247  			vmenv.ChainConfig().TransferDataPlg.SendDataToPlugin("EXTERNALINFOEND", tcend.SendTransInfo("EXTERNALINFOEND"))	
   248  		}
   249  		//add new 
   250  		return nil, 0, err
   251  	}
   252  	// Update the state with pending changes
   253  	var root []byte
   254  	if config.IsByzantium(header.Number) {
   255  		statedb.Finalise(true)
   256  	} else {
   257  		root = statedb.IntermediateRoot(config.IsEIP158(header.Number)).Bytes()
   258  	}
   259  	*usedGas += gas
   260  
   261  	// Create a new receipt for the transaction, storing the intermediate root and gas used by the tx
   262  	// based on the eip phase, we're passing whether the root touch-delete accounts.
   263  	receipt := types.NewReceipt(root, failed, *usedGas)
   264  	receipt.TxHash = tx.Hash()
   265  	receipt.GasUsed = gas
   266  	// if the transaction created a contract, store the creation address in the receipt.
   267  	if msg.To() == nil {
   268  		receipt.ContractAddress = crypto.CreateAddress(vmenv.Context.Origin, tx.Nonce())
   269  		//add new 
   270  		if vmenv.ChainConfig().TransferDataPlg.GetOpcodeRegister("EXTERNALINFOEND"){
   271  			tcend.CallType = "CREATE"
   272  			tcend.To = receipt.ContractAddress.String()
   273  			createcollector := collector.NewCreateCollector()
   274  			createcollector.ContractAddr = receipt.ContractAddress.String()
   275  			createcollector.ContractDeployCode = msg.Data()	
   276  			if vmenv.StateDB.Exist(receipt.ContractAddress) {
   277  				createcollector.ContractRuntimeCode = vmenv.StateDB.GetCode(receipt.ContractAddress)
   278  			}		
   279  			tcend.CreateInfo = *createcollector
   280  		}
   281  		//add new 
   282  	}
   283  	// Set the receipt logs and create a bloom for filtering
   284  	receipt.Logs = statedb.GetLogs(tx.Hash())
   285  	receipt.Bloom = types.CreateBloom(types.Receipts{receipt})
   286  	receipt.BlockHash = statedb.BlockHash()
   287  	receipt.BlockNumber = header.Number
   288  	receipt.TransactionIndex = uint(statedb.TxIndex())
   289  
   290  	//add new 
   291  	if !failed {
   292  		if vmenv.ChainConfig().TransferDataPlg.GetOpcodeRegister("EXTERNALINFOEND"){
   293  			tcend.IsSuccess = true
   294  			vmenv.ChainConfig().TransferDataPlg.SendDataToPlugin("EXTERNALINFOEND", tcend.SendTransInfo("EXTERNALINFOEND"))
   295  		}
   296  	} else {
   297  		if vmenv.ChainConfig().TransferDataPlg.GetOpcodeRegister("EXTERNALINFOEND"){
   298  			tcend.IsSuccess = false
   299  			vmenv.ChainConfig().TransferDataPlg.SendDataToPlugin("EXTERNALINFOEND", tcend.SendTransInfo("EXTERNALINFOEND"))
   300  		}
   301  	}
   302  
   303  	tingrong.CALL_STACK = tingrong.CALL_STACK[:len(tingrong.CALL_STACK)-1]
   304  
   305  	if vmenv.ChainConfig().TransferDataPlg.GetOpcodeRegister("TXEND"){
   306  		vmenv.ChainConfig().TransferDataPlg.SendDataToPlugin("TXEND", collector.SendFlag("TXEND"))
   307  		vmenv.ChainConfig().TransferDataPlg.Stop()
   308  	}
   309  
   310  	
   311  	//add new 
   312  
   313  	return receipt, gas, err
   314  }