赞
踩
现在自己对其中一些代码的理解还不够,等我逐渐深入学习后回回来再修改的。
其中对于一些代码的理解参考了以太坊黄皮书的内容。
链接: https://ethereum.github.io/yellowpaper/paper.pdf
类型名 | 位置 | 定义 |
---|---|---|
Hash | common/types.go | 32byte |
Address | common/types.go | 20byte |
Bloom | core/types/bloom9.go | 256byte(filter) |
GasPool | core/gaspool.go | uint64 |
位于core\types\receipt.go
为了方便索引、搜索交易和对交易的零知识证明,将交易执行中的某些信息进行编码形成了Receipt
参考黄皮书4.3.1
名字 | 定义 |
---|---|
Type | 交易类型 |
PostState | StateDB的MPT树根,相当于当前Block事务执行后所有账户状态 |
Status | 当前交易的状态 |
CumulativeGasUsed | 累积的Gas使用量 |
Bloom | 布隆过滤器,用来快速验证给定Log是否为这个事务生成 |
Logs | 交易执行过程中生成的log集合 |
TxHash | 交易hash值 |
ContractAddress | 交易对应智能合约地址 |
GasUsed | 使用的Gas量 |
BlockHash | 区块hash |
BlockNumber | 区块号 |
TransactionIndex | 交易索引 |
位于core\types\log.go
以太坊中定义了event和log机制,用于表示一个合约的日志。
名字 | 定义 |
---|---|
Address | 对应事件的合约地址 |
Topics | 用于检索日志时使用 |
Data | 由合约提供的ABI编码的内容 |
BlockNumber | 区块号 |
TxHash | 交易hash |
TxIndex | 该Log对应的交易在区块中的索引 |
BlockHash | 该Log对应的交易所在的区块hash |
Index | 该Log在区块中的索引 |
Removed | 当发生了链重组导致log被恢复,该字段为真。故如果通过过滤器查询log时,要多注意该字段。 |
位于core\types\block.go
表示区块头
名字 | 定义 |
---|---|
ParentHash | 父区块的hash值 |
UncleHash | 叔区块RLP编码hash |
Coinbase | 矿工地址 |
Root | 世界状态的根hash |
TxHash | 交易信息的根hash |
ReceiptHash | 收据信息的根hash |
Bloom | 布隆过滤器 |
Difficulty | 挖矿的难度系数 |
Number | 区块序号 |
GasLimit | 区块内Gas消耗上限 |
GasUsed | 区块交易完成后消耗Gas总量 |
Time | 区块生成的时间(貌似并不太精准) |
Extra | 区块创建者(矿工)记录的信息 |
MixDigest | hashimotoFull函数生成后的digest生成的hash值,可用于结合nonce进行工作量证明 |
Nonce | Pow枚举猜测的值 |
BaseFee | EIP-1559新增的区块头可选项,允许协议强制执行最低费用,而不会激励矿工和交易方在链下交易,形成链外市场。 |
位于params\config.go
代表区块链的配置
名字 | 定义 |
---|---|
DAOForkBlock | DAO硬分叉的区块号 |
DAOForkSupport | 当前节点是否支持DAO硬分叉 |
位于core\blockchain.go
待补充
位于core\types\transaction.go
其中txdata是一个接口,定义如下,位于相同位置
位于core\types\transaction.go
名字 | 定义 |
---|---|
inner | 交易相关共识内容 |
time | 交易时间 |
hash | 交易hash值 |
size | 交易大小 |
from | 交易发起方 |
位于core\types\block.go
表示区块
名字 | 定义 |
---|---|
ParentHash | 父区块的hash值 |
UncleHash | 叔区块RLP编码hash |
Coinbase | 矿工地址 |
Root | 世界状态的根hash |
TxHash | 交易信息的根hash |
ReceiptHash | 收据信息的根hash |
Bloom | 布隆过滤器 |
Difficulty | 挖矿的难度系数 |
位于core\state_processor.go
名字 | 定义 |
---|---|
config | 区块配置 |
bc | 区块链 |
engine | 用于区块奖励的共识引擎 |
位于core\vm\evm.go
表示区块上下文,很多属性和前面是重复的。
名字 | 定义 |
---|---|
CoinBase | 矿工地址 |
GasLimit | Gas的限制量 |
BlockNumber | 区块号 |
Time | 时间 |
Difficulty | 难度 |
BaseFee | 协议执行最低费用 |
位于core\vm\evm.go
待补充
名字 | 定义 |
---|---|
interpreter | 解释编译程序 |
位于core\types\transaction.go
派生的事务(待补充)
名字 | 定义 |
---|---|
nonce | 即为交易中的nonce,用来交易排序,交易校验以避免双花 |
gasLimit | 当前消息gas最大限制 |
gasPrice | 油价 |
gasFeeCap | 用户所能支付给矿工的最大单价限额 |
gasTipCap | 小费,即在网络拥堵的情况下支付给矿工的小费,这个也意味着矿工有优先选择权。支付该费用,则优先打包区块 |
位于core\state\statedb.go
StateDB结构用于存储所有的与Merkle trie相关的存储, 包括一些循环state结构
位于core\state\access_list.go
每个事务的访问列表,在某些形式的 EVM 执行过程中会触及的账户和合约存储位置的列表
位于consensus\consensus.go
engine是一个算法无关的用作共识层面的引擎
位于core\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) header = block.Header() blockHash = block.Hash() blockNumber = block.Number() allLogs []*types.Log gp = new(GasPool).AddGas(block.GasLimit()) ) // 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) } blockContext := NewEVMBlockContext(header, p.bc, nil) vmenv := vm.NewEVM(blockContext, vm.TxContext{}, statedb, p.config, cfg) // Iterate over and process the individual transactions for i, tx := range block.Transactions() { msg, err := tx.AsMessage(types.MakeSigner(p.config, header.Number), header.BaseFee) if err != nil { return nil, nil, 0, fmt.Errorf("could not apply tx %d [%v]: %w", i, tx.Hash().Hex(), err) } statedb.Prepare(tx.Hash(), i) receipt, err := applyTransaction(msg, p.config, p.bc, nil, gp, statedb, blockNumber, blockHash, tx, usedGas, vmenv) if err != nil { return nil, nil, 0, fmt.Errorf("could not apply tx %d [%v]: %w", i, tx.Hash().Hex(), 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()) return receipts, allLogs, *usedGas, nil }
首先该函数判断当前区块是否为DAO硬分叉的区块,若是则调用ApplyDAOHardFork
函数(待补充)。
然后调用NewEVMBlockContext
函数为当前区块创立一个运行上下文。
随后调用NewEVM
函数建立一个以太坊虚拟机,准备编译执行程序。
然后枚举区块中的交易并把它转换为消息格式,随后调用Prepare
函数设置当前状态的交易hash和序号,随后调用applyTransaction
在虚拟机中执行交易相关指令(见以太坊go-ethereum源码研读(二)进一步分析),得到返回的收据后,加入到列表中,并获取其中的日志加入到列表中,最后调用共识引擎的Finalize
函数计算区块奖励并加入到最终状态中。
位于core\evm.go
根据区块头信息,建立并返回一个BlockContext区块上下文信息结构体
func NewEVMBlockContext(header *types.Header, chain ChainContext, author *common.Address) vm.BlockContext { var ( beneficiary common.Address baseFee *big.Int ) // If we don't have an explicit author (i.e. not mining), extract from the header if author == nil { beneficiary, _ = chain.Engine().Author(header) // Ignore error, we're past header validation } else { beneficiary = *author } if header.BaseFee != nil { baseFee = new(big.Int).Set(header.BaseFee) } return vm.BlockContext{ CanTransfer: CanTransfer, Transfer: Transfer, GetHash: GetHashFn(header, chain), Coinbase: beneficiary, BlockNumber: new(big.Int).Set(header.Number), Time: new(big.Int).SetUint64(header.Time), Difficulty: new(big.Int).Set(header.Difficulty), BaseFee: baseFee, GasLimit: header.GasLimit, } }
位于core/vm/evm.go
根据之前的上下文信息,以及其他的配置和内容建立虚拟机,同时调用NewEVMInterpreter
函数建立对应解释器。
// NewEVM returns a new EVM. The returned EVM is not thread safe and should
// only ever be used *once*.
func NewEVM(blockCtx BlockContext, txCtx TxContext, statedb StateDB, chainConfig *params.ChainConfig, config Config) *EVM {
evm := &EVM{
Context: blockCtx,
TxContext: txCtx,
StateDB: statedb,
Config: config,
chainConfig: chainConfig,
chainRules: chainConfig.Rules(blockCtx.BlockNumber, blockCtx.Random != nil),
}
evm.interpreter = NewEVMInterpreter(evm, config)
return evm
}
根据采取的不同链规则不同来建立对应EVM解释器
// NewEVMInterpreter returns a new instance of the Interpreter. func NewEVMInterpreter(evm *EVM, cfg Config) *EVMInterpreter { // If jump table was not initialised we set the default one. if cfg.JumpTable == nil { switch { case evm.chainRules.IsLondon: cfg.JumpTable = &londonInstructionSet case evm.chainRules.IsBerlin: cfg.JumpTable = &berlinInstructionSet case evm.chainRules.IsIstanbul: cfg.JumpTable = &istanbulInstructionSet case evm.chainRules.IsConstantinople: cfg.JumpTable = &constantinopleInstructionSet case evm.chainRules.IsByzantium: cfg.JumpTable = &byzantiumInstructionSet case evm.chainRules.IsEIP158: cfg.JumpTable = &spuriousDragonInstructionSet case evm.chainRules.IsEIP150: cfg.JumpTable = &tangerineWhistleInstructionSet case evm.chainRules.IsHomestead: cfg.JumpTable = &homesteadInstructionSet default: cfg.JumpTable = &frontierInstructionSet } for i, eip := range cfg.ExtraEips { copy := *cfg.JumpTable if err := EnableEIP(eip, ©); err != nil { // Disable it, so caller can check if it's activated or not cfg.ExtraEips = append(cfg.ExtraEips[:i], cfg.ExtraEips[i+1:]...) log.Error("EIP activation failed", "eip", eip, "error", err) } cfg.JumpTable = © } } return &EVMInterpreter{ evm: evm, cfg: cfg, } }
位于core\types\transaction.go
将交易返回为消息格式
// AsMessage returns the transaction as a core.Message. func (tx *Transaction) AsMessage(s Signer, baseFee *big.Int) (Message, error) { msg := Message{ nonce: tx.Nonce(), gasLimit: tx.Gas(), gasPrice: new(big.Int).Set(tx.GasPrice()), gasFeeCap: new(big.Int).Set(tx.GasFeeCap()), gasTipCap: new(big.Int).Set(tx.GasTipCap()), to: tx.To(), amount: tx.Value(), data: tx.Data(), accessList: tx.AccessList(), isFake: false, } // If baseFee provided, set gasPrice to effectiveGasPrice. if baseFee != nil { msg.gasPrice = math.BigMin(msg.gasPrice.Add(msg.gasTipCap, baseFee), msg.gasFeeCap) } var err error msg.from, err = Sender(s, tx) return msg, err }
位于core\state\statedb.go
在EVM需要生成新的状态时调用此函数来设置当前交易的hash和序号
// Prepare sets the current transaction hash and index which are
// used when the EVM emits new state logs.
func (s *StateDB) Prepare(thash common.Hash, ti int) {
s.thash = thash
s.txIndex = ti
s.accessList = newAccessList()
}
// Finalize implements consensus.Engine, accumulating the block and uncle rewards,
// setting the final state on the header
func (ethash *Ethash) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header) {
// Accumulate any block and uncle rewards and commit the final state root
accumulateRewards(chain.Config(), state, header, uncles)
header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number))
}
位于consensus\ethash\consensus.go
该函数累积区块和叔块的奖励并设置在头部的最终状态中。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。