初链主网上线技术解读之-PBFT委员会的选举

初链主网采用PBFT与fPOW混合共识,通过PoW选举PBFT节点。本文详细解读白皮书与黄皮书中选举流程,探讨代码中节点门槛、不当行为触发的换届以及选举过程。选举基于随机数种子与节点难度值,候选人需达到水果数量门槛,难度值越大,当选概率越高。选举每隔144个慢链区块进行,同时考虑快链区块高度。
摘要由CSDN通过智能技术生成

从2017年11月启动至今,经过历时近一年的研究、开发与测试,初链主网Beta版于新加坡时间2018年09月28日08:00正式上线,在此之前,07:56分PBFT委员会第一次共识出块和TrueChain fPOW创世区块被挖出。在阅读了一些大神对初链技术的解读之后有一定的了解。本文将对之前白皮书解读黄皮书解读中的一些疑问进行代码的学习。这里主要记录PBFT选举。

白皮书和黄皮书中选举的相关内容及问题

初链白皮书中对PBFT的选举描述如下:

以 PoW 为基础,选举产生 PBFT 节点的混合共识机制设计可以保证 PBFT 节点出现问题时及时进行重新选举,并对PBFT节点进行实时监督。

因此,PBFT节点是从慢链的挖矿节点中选举的。一定程度上讲,PBFT选举也算是双链交互的一个方面。

初链黄皮书中对PBFT的换届描述如下:

PoW协议选择BFT委员会成员的依据是csize(挖出的区块数量)和节点权益的结合。这就提供了一种必要的准入系统,以处理动态的成员以及在许可的环境下切换委员会。

[问题] 这里的csize与节点权益有什么区别?
[解答] 从代码中看到委员会的选举对节点设置了水果数量的门槛,依靠难度值来评估节点选中的概率。这里设置水果的门槛是滤除那些挖出水果少的、性能较差的节点。

另一方面,我们结合了来自Thunderella 的经过认证的投诉的观点,其中慢链可以作为BFT委员会成员不当行为的证据。也就是说,每当委员会的不当行为从慢链中被发现时,第二天的起始点(不一定是第k天)就会触发委员会强制换届。

因此,换届有两种方式:一种固定时间的强制换届(即这里的选举),一种由不当行为触发的特定的换届。
[问题] 不当行为触发的换届是否有在代码中实现?如何进行识别行为不当?
[解答] 在委员会的选举过程的代码中没有体现,可能在其他位置进行设定,还需要学习和追踪。

代码解读

这里在代码中加入一些注释,包含变量的作用、自己的思考与问题,以便更好的理解函数。注释中包含一些关于GO语言语法的学习。

查看了相关代码,对如下一些函数进行细致分析:

getCommittee:获取委员会成员
electCommittee:选举委员会成员
getCandinates:获取候选人
elect:对候选人进行选举

先从选举委员会成员开始。

electCommittee:选举委员会成员

	// electCommittee elect committee members from snail block.
	// go语法:实现接口的方法;(e *Election)为结构体指针;函数作用:选举委员会成员
	func (e *Election) electCommittee(snailBeginNumber *big.Int, snailEndNumber *big.Int) []*types.CommitteeMember {
   
		// 打印LOG:选举范围:慢链开始的区块数、慢链结束的区块数、参与选举慢链节点的水果数量门槛、最大的委员会委员数量
		log.Info("elect new committee..", "begin", snailBeginNumber, "end", snailEndNumber, "threshold", params.ElectionFruitsThreshold, "max", params.MaximumCommitteeNumber)

		// go语法:变量名为committee的CommitteeMember类型的指针切片
		var committee []*types.CommitteeMember
		// singleNode为布尔值,表示是否为单节点;
		if e.singleNode {
   
			// 如果只有一个节点,则直接把创世委员会节点的第一个放入到committee中并返回committee。
			// [问题] 通过genesisCommittee是一个数组(或切片)的形式推断创世委员会成员也不止一个,那么singleNode会在什么时候使用?
			committee = append(committee, e.genesisCommittee[0])
			return committee
		}
		// 将默认的members放到committee里面
		for _, member := range e.defaultMembers {
   
			committee = append(committee, member)
		}
		// 调用getCandinates获取候选人和随机数种子
		seed, candidates := e.getCandinates(snailBeginNumber, snailEndNumber)
		if candidates == nil {
    // 如果没有候选人,则仍然使用目前的委员会成员
			log.Info("can't get new committee, retain current committee")
		} else {
   
			members := e.elect(candidates, seed) // 通过seed来选举候选人

			for _, member := range members {
   
				committee = append(committee, member) // 将选举之后的members放入到committee中。
			}
		}

		return committee // 返回committee:选举完成,返回新的委员会成员(可能没有候选人,仍然是之前的委员会成员)
	}

该函数使用了如下两个函数:获取候选人和对候选人进行选举。这中间通过随机数种子seed进行随机地选举委员会成员。这里随机数种子seed是与选举中选用的慢链区块区间中的区块相关,如果挖矿节点的难度区间越大,其获得选举的可能性越高。且看后面的elect的分析。

getCandinates:获取候选人

	// getCandinates get candinate miners and seed from given snail blocks
	// go语法:实现接口的方法;函数作用:获取候选矿工以及从慢链区块中获取种子。
	func (e *Election) getCandinates(snailBeginNumber *big.Int, snailEndNumber *big.Int) (common.Hash, []*candidateMember) {
   
		// fruitsCount作用:标记每个地址挖出了多少个水果
		var fruitsCount map[common.Address]uint64 = make(map[common.Address]uint64)
		// 候选人的指针切片
		var members []*candidateMember
		var seed []byte
		// get all fruits want to be elected and their pubic key is valid
		// 获取公钥有效且水果表示愿意被选举的节点
		for blockNumber := snailBeginNumber; blockNumber.Cmp(snailEndNumber) <= 0; {
   
			// 通过区块number来获取区块
			block := e.snailchain.GetBlockByNumber(blockNumber.Uint64())
			if block == nil {
   
				return common.Hash{
   }, nil
			}
			// 把区块的哈希按照字节放入到seed切片中
			seed = append(seed, block.Hash().Bytes()...)
			// 获取慢链的水果
			fruits := block.Fruits()
			for _, f := range fruits {
   
				if f.ToElect() {
    // 如果这个水果表示是愿意被选举的
					// 获取public Key
					pubkey, err := f.GetPubKey()
					if err != nil {
    // 异常处理
						continue
					}
					// 通过Public Key 转换成Address
					addr := crypto.PubkeyToAddress(*pubkey)
					// 获取难度值
					act, diff := e.engine.GetDifficulty(f
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值