Interpretation of Ethereum Source Code: Consensus Module Entry Design

I. Introduction

The main thing is to first sort out the entry file consensus.go of the consensus module, which reflects the entire design idea of ​​Ethereum consensus design. Do the basic work for the further analysis of the consensus algorithm later.

1.1 Module file structure

First look at the file directory of the consensus module:

.
|____misc                ## It seems to be a hard fork-related process. I haven't studied it yet, so I think so
| |____forks.go    
| |____dao.go
|____consensus.go        ## The general rule design of consensus, the entry design of pow is here
|____ethash              ## The specific implementation of pow consensus algorithm
| |____sealer.go
| |____algorithm.go
| |____sealer_test.go
| |____ethash_test.go
| |____consensus.go
| |____algorithm_test.go
| |____api.go
| |____ethash.go
| |____consensus_test.go
|____clique             ## The specific implementation of the poa consensus algorithm, which is mainly used by private chains.
| |____clique.go
| |____snapshot_test.go
| |____api.go
| |____snapshot.go
|____errors.go

It can be roughly seen from this that Ethereum currently implements two consensus algorithms, pow and poa.
Among them, poa is a hybrid algorithm of POW and POS(proof of stake), which is mainly used for private chains. The Ethereum test network (Kovan) adopts the PoA algorithm, and it seems that the deployment of Ethereum as a consortium chain is also The use of this consensus has not been specifically studied.
Here we mainly focus on pow, poa and so on when we have time to consider.

1.2 Introduction to consensus.go file

This file is mainly divided into 3 parts:

  • pow algorithm entry
  • Consensus common engine interface
  • Part of the interface for reading chain information

1.2.1 Pow algorithm entry

This is an encapsulation of pow,
Let's first look at the code structure:

type PoW interface {
	Engine
	Hashrate() float64 //Returns the computing power of the current node
}

It can be seen from this that the pow algorithm can complete the entire consensus process by itself as long as it satisfies the Engine interface. This also gives us an idea. If we want to achieve consensus by ourselves, we also need to inherit Engine.

1.2.2 Consensus general engine interface Engine

This is also the core of the entire consensus, a general consensus engine interface. If you want to design new consensus rules without changing the overall operation of Ethereum, you must implement the following interfaces. The specific content is indicated in the comments. now:

type Engine interface {
	// Get the Ethereum address of the current mining miner
    Author(header *types.Header) (common.Address, error)
    
    // Check whether the block header information complies with the consensus rules and whether it is sealed
	VerifyHeader(chain ChainReader, header *types.Header, seal bool) error

    // Batch check block header, this method returns an exit signal to terminate the operation, used for asynchronous check.
    VerifyHeaders(chain ChainReader, headers []*types.Header, seals []bool) (chan<- struct{}, <-chan error)
    
    // Check whether the uncle block satisfies the rules
	VerifyUncles(chain ChainReader, block *types.Block) error

	// The VerifySeal() function is based on the exact same algorithm principle as Seal(), and determines whether the block has undergone the Seal operation by verifying whether some properties of the block (Header.Nonce, Header.MixDigest, etc.) are correct.
	VerifySeal(chain ChainReader, header *types.Header) error

	// The consensus field used to initialize the block header is based on the consensus engine. These changes are performed inline.
	Prepare(chain ChainReader, header *types.Header) error

	// All state modifications are done and finally assembled into blocks.
	// Block headers and state databases can be updated to conform to consensus rules at final confirmation.
	// receipts means return to display transaction results
	Finalize(chain ChainReader, header *types.Header, state *state.StateDB, txs []*types.Transaction,
		uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error)

	// The Seal() function can authorize or seal a block that has called Finalize(), and assign some values ​​generated by the sealing process to the remaining unassigned members (Header.Nonce, Header.MixDigest) in the block.  When Seal() succeeds, all members of the returned block are neat and can be regarded as a normal block, which can be broadcast to the entire network, or inserted into the blockchain, etc.
	Seal(chain ChainReader, block *types.Block, results chan<- *types.Block, stop <-chan struct{}) error

	// Returns the hash of the previous block
	SealHash(header *types.Header) common.Hash

	// Calculate the difficulty of the next block
	CalcDifficulty(chain ChainReader, time uint64, parent *types.Header) *big.Int

	// Returns the RPC APIs provided by the consensus engine 
	APIs(chain ChainReader) []rpc.API

	// Closing consensus means closing the thread related to mining
	Close() error
}

Here we have a general understanding of the rules that consensus needs to be implemented. We will not discuss it in detail first. We have a bottom line in our hearts. The specific content will be further analyzed in subsequent articles.

1.2.3 Part of the interface for reading chain information

After all, consensus involves the operation of chain-related content. At this consensus entry, Ethereum provides some interfaces to access blocks or block headers in the local chain.

type ChainReader interface {
	// Get the configuration information of the local chain
	Config() *params.ChainConfig

	// Returns the current block of the local chain
	CurrentHeader() *types.Header

	// Returns a block header from the chain based on the input (block hash and block number)
	GetHeader(hash common.Hash, number uint64) *types.Header

	// Return block from db by block number
	GetHeaderByNumber(number uint64) *types.Header

	// Return block by block hash
	GetHeaderByHash(hash common.Hash) *types.Header

	// Return a block from the db based on the input (block hash and block number)
	GetBlock(hash common.Hash, number uint64) *types.Block
}

1.3 Summary

The consensus.go file tells us that to implement a formula algorithm, we need to implement a specific engine, which provides a better idea for us to design our own consensus algorithm.

Reference article

Interpretation of Ethereum Source Code - Lecture 6.1 - Consensus Module Entry Design

2. Analysis of Ethereum code source: POW(1)

See my blockchain column

3. Analysis of Ethereum code source: POW(2)

See my blockchain column

Tags: Blockchain

Posted by kts on Fri, 06 May 2022 14:04:43 +0300