交易的大致流程:
//交易执行的大体流程
// state_processor.go
func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg vm.Config) (types.Receipts, []*types.Log, uint64, error) {
var (
receipts types.Receipts //接收交易返回的
usedGas = new(uint64) //交易花费的gas
header = block.Header()
allLogs []*types.Log //日志信息数组
gp = new(GasPool).AddGas(block.GasLimit()) //说明当前交易还有多少Gas可以使用
)
// Mutate the block and state according to any hard-fork specs
//判断当前区块是否出现硬分叉
if p.config.DAOForkSupport && p.config.DAOForkBlock != nil && p.config.DAOForkBlock.Cmp(block.Number()) == 0 {
misc.ApplyDAOHardFork(statedb)//将硬分叉后合约gas转到系统固定dao账户上
}
// Iterate over and process the individual transactions
//遍历区块上的所有交易
for i, tx := range block.Transactions() {
statedb.Prepare(tx.Hash(), block.Hash(), i)
//执行交易,并且获取receipt对象,receipt中还包含了log数组其记录了Tx中一小步的操作
receipt, _ , err := ApplyTransaction(p.config, p.bc, nil, gp, statedb, header, tx, usedGas, cfg)
if err != nil {
return nil, nil, 0, err
}
receipts = append(receipts, receipt)
allLogs = append(allLogs, receipt.Logs...)
}
// Finalize the block, applying any consensus engine specific extras (e.g. block rewards)
p.engine.Finalize(p.bc, header, statedb, block.Transactions(), block.Uncles(), receipts)
return receipts, allLogs, *usedGas, nil
}
// state_processor.go
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) {
//MakeSigner根据区块配置和区块头编号进行签名,签名过程会根据以太坊预计的四个阶段来分别签名
//AsMessage主要是封装当前的交易信息,并且在通过内部的Sender函数返回发送者地址,之后该地址通过
//r,s,v,恢复签名->公钥->地址
//而对交易进行签名是通过signTx函数,将tx信息进行hash,之后和私钥一起secp256k1.sign(hash, privKey)进行签名
msg, err := tx.AsMessage(types.MakeSigner(config, header.Number))
if err != nil {
return nil, 0, err
}
//NewEVMContext(msg, header, bc, author)创建EVM的上下文环境
context := NewEVMContext(msg, header, bc, author)
// Create a new environment which holds all relevant information
// about the transaction and calling mechanisms.
//vm.NewEVM(context, statedb, config, cfg)创建EVM对象,并在内部创建一个evm.interpreter(虚拟机解析器)
vmenv := vm.NewEVM(context, statedb, config, cfg)
// Apply the transaction to the current state (included in the env)
//通过EVM对象来执行Message(msg) 其中包括解释器解释执行智能合约
_, gas, failed, err := ApplyMessage(vmenv, msg, gp)
if err != nil {
return nil, 0, err
}
// Update the state with pending changes
var root []byte
//判断是否分叉情况( `config.IsByzantium(header.Number)` )
if config.IsByzantium(header.Number) {
statedb.Finalise(true)
} else {//如果不是,获取当前的statedb的状态树根哈希
root = statedb.IntermediateRoot(config.IsEIP158(header.Number)).Bytes()
}
*usedGas += gas
// Create a new receipt for the transaction, storing the intermediate root and gas used by the tx
// based on the eip phase, we're passing whether the root touch-delete accounts.
//Receipt 中有一个Log类型的数组,其中每一个Log