现在自己对其中一些代码的理解还不够,等我逐渐深入学习后回回来再修改的。
其中对于一些代码的理解参考了以太坊黄皮书的内容。
链接: 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,
}
}
NewEVM
位于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
}
NewEVMInterpreter
根据采取的不同链规则不同来建立对应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,
}
}
AsMessage
位于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
}
Prepare
位于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
// 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
该函数累积区块和叔块的奖励并设置在头部的最终状态中。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)