go-ethereumではアルゴリズムに依存しないコンセンサスエンジンとして下記のinterfaceが定義されています。
ethashやcliqueはそれぞれ下記を実装しています。
type Engine interface {
// Authorは、指定されたブロックを作成したアカウントのEthereumアドレスを読み出す
// 但し、コンセンサスエンジンが署名に基づいている場合、ヘッダーのコインベースのアドレスと異なる場合がある
Author(header *types.Header) (common.Address, error)
// VerifyHeaderは、ヘッダーが指定されたエンジンのコンセンサスルールに準拠しているかどうかをチェックする
// ここでオプションでシールを検証することも、VerifySealメソッドを使って明示的にシールを検証することもできる
VerifyHeader(chain ChainReader, header *types.Header, seal bool) error
// VerifyHeadersはVerifyHeaderに似ているが、同時に複数のヘッダーを検証する
// このメソッドは、操作を中止するための終了チャネルと非同期に検証結果を取得する結果チャネルを返す(処理は入力スライスの順番)
VerifyHeaders(chain ChainReader, headers []*types.Header, seals []bool) (chan<- struct{}, <-chan error)
// VerifyUnclesは指定されたブロックのUncleが指定されたエンジンのコンセンサスルールに準拠しているかを検証する
VerifyUncles(chain ChainReader, block *types.Block) error
// VerifySealは、ヘッダーの暗号シールが、指定されたエンジンのコンセンサス規則に従って有効かどうかをチェックする
VerifySeal(chain ChainReader, header *types.Header) error
// Prepareは、特定のエンジンのルールに従って、ブロックヘッダーのコンセンサスフィールドを初期化する。変更は関数内で実行される
Prepare(chain ChainReader, header *types.Header) error
// Finalizeは、トランザクション後の状態(ブロック報酬など)に変更し、最終ブロックをまとめる
// 注:ブロックヘッダーと状態データベースは、ファイナライズ時に発生するコンセンサスルール(ブロック報酬など)を反映するように更新される場合がある
Finalize(chain ChainReader, header *types.Header, state *state.StateDB, txs []*types.Transaction,
uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error)
// Sealは、ローカルマイナーのシールを指定された入力ブロックの一番上として新しいブロックを生成する
Seal(chain ChainReader, block *types.Block, stop <-chan struct{}) (*types.Block, error)
// CalcDifficultyは難易度調整アルゴリズム。新しいブロックが持つべきdifficultyを返す
CalcDifficulty(chain ChainReader, time uint64, parent *types.Header) *big.Int
// APIsは、このコンセンサスエンジンが提供するRPC APIを返す
APIs(chain ChainReader) []rpc.API
}
処理される順番
実際にブロック生成は下記の順番でメソッドが呼ばれます。
* Prepare
* Finalize
* Seal
* Seal成功時(マイニング成功時)
* 終わり
* Seal失敗時(マイニングに失敗し他のノードからブロックを受け取った時)
* VerifyHeaders
* Fetcher insert
* fetcher validator call VerifyHeader
* VerifyHeader
* VerifySeal
* fetcher inserter
* BlockChain InsertChain
* peerSet PeersWithoutBlock
* VerifyHeaders
* VerifySeal
* VerifyUncles