Table of contents
written in front
Now my understanding of some of the codes is not enough, and I will come back and modify them after I gradually study in depth.
The understanding of some codes refers to the contents of the Ethereum Yellow Paper.
Link: https://ethereum.github.io/yellowpaper/paper.pdf
some custom types
type name | Location | definition |
---|---|---|
Hash | common/types.go | 32bytes |
Address | common/types.go | 20byte |
Bloom | core/types/bloom9.go | 256byte(filter) |
GasPool | core/gaspool.go | uint64 |
some structs
Receipt
Located at core\types\receipt.go
In order to facilitate indexing, searching transactions and zero-knowledge proofs of transactions, some information in transaction execution is encoded to form Receipt
Reference Yellow Book 4.3.1
name | definition |
---|---|
Type | Transaction Type |
PostState | The MPT tree root of StateDB is equivalent to the status of all accounts after the execution of the current Block transaction |
Status | The status of the current transaction |
CumulativeGasUsed | Cumulative gas usage |
Bloom | Bloom filter, used to quickly verify whether a given Log is generated for this transaction |
Logs | Log collection generated during transaction execution |
TxHash | Transaction hash value |
ContractAddress | The transaction corresponds to the smart contract address |
GasUsed | Amount of Gas used |
BlockHash | block hash |
BlockNumber | block number |
TransactionIndex | transaction index |
Log
Located in core\types\log.go,
the event and log mechanisms are defined in Ethereum, which are used to represent the log of a contract.
name | definition |
---|---|
Address | The contract address corresponding to the event |
Topics | For retrieving logs use |
Data | The ABI-encoded content provided by the contract |
BlockNumber | block number |
TxHash | transaction hash |
TxIndex | The index of the transaction corresponding to the Log in the block |
BlockHash | The block hash of the transaction corresponding to the Log |
Index | The index of the log in the block |
Removed | This field is true when a chain reorganization has occurred and the log has been restored. Therefore, if you query the log through the filter, you should pay more attention to this field. |
Header
Located in core\types\block.go
represents the block header
name | definition |
---|---|
ParentHash | The hash value of the parent block |
UncleHash | Uncle block RLP code hash |
Coinbase | miner address |
Root | The root hash of the world state |
TxHash | Root hash of transaction information |
ReceiptHash | The root hash of the receipt information |
Bloom | bloom filter |
Difficulty | Difficulty factor of mining |
Number | block number |
GasLimit | Gas consumption limit in the block |
GasUsed | The total amount of Gas consumed after the block transaction is completed |
Time | The time when the block was generated (it seems not very accurate) |
Extra | Information recorded by block creators (miners) |
MixDigest | The hash value generated by the digest generated by the hashimotoFull function can be used to combine nonce for workload proof |
Nonce | Pow enumeration guessed value |
BaseFee | The new block header option of EIP-1559 allows the agreement to enforce the minimum fee without incentivizing miners and transaction parties to trade off-chain and form an off-chain market. |
ChainConfig
Located in params\config.go
represents the configuration of the blockchain
name | definition |
---|---|
DAOForkBlock | The block number of the DAO hard fork |
DAOForkSupport | Does the current node support DAO hard fork? |
BlockChain
位于core\blockchain.go
待补充
Transaction
位于core\types\transaction.go
其中txdata是一个接口,定义如下,位于相同位置
位于core\types\transaction.go
名字 | 定义 |
---|---|
inner | 交易相关共识内容 |
time | 交易时间 |
hash | 交易hash值 |
size | 交易大小 |
from | 交易发起方 |
Block
位于core\types\block.go
表示区块
名字 | 定义 |
---|---|
ParentHash | 父区块的hash值 |
UncleHash | 叔区块RLP编码hash |
Coinbase | 矿工地址 |
Root | 世界状态的根hash |
TxHash | 交易信息的根hash |
ReceiptHash | 收据信息的根hash |
Bloom | 布隆过滤器 |
Difficulty | 挖矿的难度系数 |
StateProcessor
位于core\state_processor.go
名字 | 定义 |
---|---|
config | 区块配置 |
bc | 区块链 |
engine | 用于区块奖励的共识引擎 |
BlockContext
位于core\vm\evm.go
表示区块上下文,很多属性和前面是重复的。
名字 | 定义 |
---|---|
CoinBase | 矿工地址 |
GasLimit | Gas的限制量 |
BlockNumber | 区块号 |
Time | 时间 |
Difficulty | 难度 |
BaseFee | 协议执行最低费用 |
evm
位于core\vm\evm.go
待补充
名字 | 定义 |
---|---|
interpreter | 解释编译程序 |
Message
位于core\types\transaction.go
派生的事务(待补充)
名字 | 定义 |
---|---|
nonce | 即为交易中的nonce,用来交易排序,交易校验以避免双花 |
gasLimit | 当前消息gas最大限制 |
gasPrice | 油价 |
gasFeeCap | 用户所能支付给矿工的最大单价限额 |
gasTipCap | 小费,即在网络拥堵的情况下支付给矿工的小费,这个也意味着矿工有优先选择权。支付该费用,则优先打包区块 |
StateDB
位于core\state\statedb.go
StateDB结构用于存储所有的与Merkle trie相关的存储, 包括一些循环state结构
accessList
位于core\state\access_list.go
每个事务的访问列表,在某些形式的 EVM 执行过程中会触及的账户和合约存储位置的列表
Engine
位于consensus\consensus.go
engine是一个算法无关的用作共识层面的引擎
相关函数
Process
位于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
函数计算区块奖励并加入到最终状态中。
NewEVMBlockContext
位于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
Located in core/vm/evm.go,
it builds a virtual machine based on previous context information, other configurations and content, and calls NewEVMInterpreter
functions to build a corresponding interpreter.
// 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
Establish the corresponding EVM interpreter according to the different chain rules adopted
// 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
Located in core\types\transaction.go
returns the transaction as a message format
// 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
Located in core\state\statedb.go,
this function is called when the EVM needs to generate a new state to set the hash and sequence number of the current transaction
// 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))
}
Located in consensus\ethash\consensus.go
This function accumulates block and uncle block rewards and sets them in the final state of the head.