イーサリアム go-ethereum のソースコードの勉強 (1) Process 関数に関連するカスタム型と構造体から始める

前に書いた

現在、いくつかのコードの理解が十分ではありません。徐々に深く勉強してから、戻ってきて修正します。
一部のコードの理解は、イーサリアム イエロー ペーパーの内容を参照しています。
リンク: https://ethereum.github.io/yellowpaper/paper.pdf

いくつかのカスタムタイプ

型名 位置 意味
ハッシュ 共通/types.go 32バイト
住所 共通/types.go 20バイト
咲く コア/タイプ/bloom9.go 256byte(フィルター)
ガスプール core/gaspool.go uint64

いくつかの構造体

レシート

core\types\receipt.go にあります。
インデックス作成、トランザクションの検索、およびトランザクションのゼロ知識証明を容易にするために、トランザクション実行の一部の情報がコード化されて、領収書リファレンス
ここに画像の説明を挿入
イエロー ブック 4.3.1を形成します。

名前 意味
タイプ 取引タイプ
PostState StateDB の MPT ツリー ルートは、現在のブロック トランザクションの実行後のすべてのアカウントのステータスに相当します。
スターテス 現在の取引状況
累積ガス使用量 累積ガス使用量
咲く ブルーム フィルター。特定のログがこのトランザクションに対して生成されているかどうかをすばやく確認するために使用されます。
ログ トランザクション実行時に発生するログ収集
送信ハッシュ トランザクションのハッシュ値
契約住所 トランザクションはスマート コントラクト アドレスに対応します
使用ガス ガス使用量
ブロックハッシュ ブロックハッシュ
ブロック番号 ブロック番号
トランザクション インデックス トランザクション インデックス

ログ

core\types\log.go にあり、
イベントとログのメカニズムは Ethereum で定義されており、コントラクトのログを表すために使用されます。
ここに画像の説明を挿入

名前 意味
住所 イベントに対応する契約アドレス
トピック ログを取得するには、次を使用します
データ コントラクトによって提供される ABI エンコードされたコンテンツ
ブロック番号 ブロック番号
送信ハッシュ トランザクション ハッシュ
送信インデックス ブロック内のログに対応するトランザクションのインデックス
ブロックハッシュ ログに対応するトランザクションのブロック ハッシュ
索引 ブロック内のログのインデックス
削除されました このフィールドは、チェーンの再編成が発生し、ログが復元された場合に true になります。したがって、フィルターを介してログを照会する場合は、このフィールドにもっと注意を払う必要があります。

ヘッダ

ここに画像の説明を挿入
core\types\block.go にあり、
ブロック ヘッダーを表します

名前 意味
親ハッシュ 親ブロックのハッシュ値
ハッシュおじさん アンクル ブロック RLP コード ハッシュ
コインベース マイナーアドレス
世界状態のルートハッシュ
送信ハッシュ 取引情報のルートハッシュ
レシートハッシュ レシート情報のルートハッシュ
咲く ブルームフィルター
困難 マイニングの難易度
番号 ブロック番号
ガスリミット ブロック内のガス消費量上限
使用ガス ブロックトランザクションが完了した後に消費されたガスの合計量
時間 ブロックが生成された時刻 (あまり正確ではないようです)
追加 ブロック作成者(マイナー)が記録した情報
ミックスダイジェスト hashimotoFull 関数によって生成されたダイジェストによって生成されたハッシュ値を使用して、ノンスを組み合わせてワークロードプルーフにすることができます
ノンス 電力列挙の推測値
基本料金 EIP-1559 の新しいブロック ヘッダー オプションにより、マイナーや取引関係者にオフチェーンでの取引やオフチェーン市場の形成を奨励することなく、最低料金を強制することができます。

ChainConfig

params\config.go にあり、
ブロックチェーンの構成を表します
ここに画像の説明を挿入

名前 意味
DAOフォークブロック DAOハードフォークのブロック番号
DAOフォークのサポート 現在のノードは DAO ハードフォークをサポートしていますか?

ブロックチェーン

ここに画像の説明を挿入

位于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

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, &copy); 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 = &copy
		}
	}

	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
}

準備

core\state\statedb.go にある
この関数は、EVM が現在のトランザクションのハッシュとシーケンス番号を設定するために新しい状態を生成する必要があるときに呼び出されます。

// 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 にあります。
この関数は、ブロックとアンクル ブロックの報酬を累積し、頭の最終状態に設定します。

おすすめ

転載: blog.csdn.net/eliforsharon/article/details/126094636