主页 > 怎么退出imtoken钱包 > 以太坊源码解读:共识模块入口设计
以太坊源码解读:共识模块入口设计
以太坊源码解读:共识模块入口设计
一、简介
主要是梳理一下共识模块的入口文件consensus.go,它体现了以太坊共识设计的整个设计思路。 为后面进一步分析共识算法做基础工作。
1.1 模块文件结构
先看共识模块的文件目录:
.
|____misc ## 貌似是硬分叉相关的处理,还没研究,先这么认为
| |____forks.go
| |____dao.go
|____consensus.go ## 共识的通用规则设计,pow的入口设计就在这里
|____ethash ## pow共识算法的具体实现
| |____sealer.go
| |____algorithm.go
| |____sealer_test.go
| |____ethash_test.go
| |____consensus.go
| |____algorithm_test.go
| |____api.go
| |____ethash.go
| |____consensus_test.go
|____clique ## poa共识算法的具体实现,这个主要是供私链使用。
| |____clique.go
| |____snapshot_test.go
| |____api.go
| |____snapshot.go
|____errors.go
从这里可以大致看出,以太坊目前实现了两种共识算法,pow和poa。
其中,POA是POW和POS(权益证明)的混合算法,主要用于私有链。 以太坊测试网 (Kovan) 使用 PoA 算法。 看来部署以太坊作为联盟链也是这个共识,没有详细研究过。
这里主要关注一下pow,poa等,以后有空了。
1.2 consensus.go文件介绍
这个文件主要分为3个部分:
1.2.1 Pow算法入门
这是对pow的封装,
先看代码结构:
type PoW interface {
Engine
Hashrate() float64 //返回当前节点的算力
}
由此可见,pow算法只要满足Engine接口就可以自己完成整个共识过程。 这也给了我们一个思路,如果我们要自己达成共识,也需要继承Engine。
1.2.2 共识通用引擎接口Engine
这也是整个共识的核心,一个通用的共识引擎接口。 如果你想在不改变以太坊整体运行的情况下设计新的共识规则,你必须实现以下接口。 具体内容在注释中注明:
type Engine interface {
// 获取当前挖矿矿工的以太坊地址
Author(header *types.Header) (common.Address, error)
// 校验块头部信息是否符合共识规则,是否封印
VerifyHeader(chain ChainReader, header *types.Header, seal bool) error
// 批量校验块头部,这个方法返回一个退出信号用于终止操作,用于异步校验。
VerifyHeaders(chain ChainReader, headers []*types.Header, seals []bool) (chan<- struct{}, <-chan error)
// 较验叔块是否满足规则
VerifyUncles(chain ChainReader, block *types.Block) error
// VerifySeal()函数基于跟Seal()完全一样的算法原理,通过验证区块的某些属性(Header.Nonce,Header.MixDigest等)是否正确,来确定该区块是否已经经过Seal操作。
VerifySeal(chain ChainReader, header *types.Header) error
// 用于初始化区块头的共识字段根据共识引擎。这些改变都是内联执行的。
Prepare(chain ChainReader, header *types.Header) error
// 完成所有的状态修改,并最终组装成块。
// 区块头和状态数据库在最终确认的时候可以被更新使之符合共识规则。
// receipts表示返回显示交易结果
Finalize(chain ChainReader, header *types.Header, state *state.StateDB, txs []*types.Transaction,
uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error)
// Seal()函数可对一个调用过Finalize()的区块进行授权或封印,并将封印过程产生的一些值赋予区块中剩余尚未赋值的成员(Header.Nonce, Header.MixDigest)。Seal()成功时返回的区块全部成员齐整,可视为一个正常区块,可被广播到整个网络中,也可以被插入区块链等。
Seal(chain ChainReader, block *types.Block, results chan<- *types.Block, stop <-chan struct{}) error
// 返回前一个块的hash
SealHash(header *types.Header) common.Hash
// 计算下一个块的难度
CalcDifficulty(chain ChainReader, time uint64, parent *types.Header) *big.Int
// 返回由共识引擎提供的RPC APIs
APIs(chain ChainReader) []rpc.API
// 关闭共识,就是关闭挖矿的线程相关
Close() error
}
到这里我们对共识需要达成的规则有了一个大概的了解。 我们不详细讨论它。 我们有一个底线。 具体内容将在后续文章中进一步分析。
1.2.3 读取链信息的一些接口
毕竟共识涉及链上相关内容的运营。 在这个共识的入口处,以太坊提供了一些接口来访问本地链中的区块或区块头。
type ChainReader interface {
// 获取本地链的配置信息
Config() *params.ChainConfig
// 返回本地链当前块
CurrentHeader() *types.Header
// 根据输入内容(块hash和块号),从链中返回一个块的头部信息
GetHeader(hash common.Hash, number uint64) *types.Header
// 通过块号从db中返回块
GetHeaderByNumber(number uint64) *types.Header
// 通过块hash返回块
GetHeaderByHash(hash common.Hash) *types.Header
// 根据输入内容(块hash和块号),从db中返回一个块
GetBlock(hash common.Hash, number uint64) *types.Block
}
1.3 总结
consensus.go文件告诉我们,要实现一个公式算法以太坊共识算法,需要实现一个具体的引擎以太坊共识算法,这为我们设计自己的共识算法提供了更好的思路。
参考文章
以太坊源码解读——第6.1讲——共识模块入口设计
二、以太坊代码源分析:POW(1)
看我的区块链专栏
3、以太坊代码源分析:POW(2)
看我的区块链专栏