Skip to content
zhiwei edited this page Oct 14, 2020 · 2 revisions

Welcome to the controller_poc wiki!

概述

Controller是整个区块链系统的中枢,负责所有核心流程(出块,同步等)。基本只有Controller会主动发起流程和相关的接口调用,相比之下,其他微服务都处于被调用的位置。

各模块介绍

genesis

创世块本质是一个配置文件,里面配置了高度为0的创世块的内容。因为目前版本没有智能合约的功能,系统配置有另外单独的配置文件,因此创世块里只有timestampprevhash两项内容。

初始化的时候会读取配置文件,然后生成相应的块结构。

utxo_set

本实现的区块链系统同时支持accountutxo两种类型的交易。但是utxo类型的交易只用于系统配置管理。

初始化时需要一个单独的初始系统配置,给系统配置项赋予初值。

在一个块确认之后,如果发现有utxo类型的交易,会调用本模块的update函数更新系统配置。

pool

交易池负责维护尚未确认的交易。本实现就简单的使用HashSet来保存这些交易的hash,另外有一个HashMap给每笔交易赋予一个序号。

因为要支持pow之类没有最终确定性的共识算法,交易池直到块最终确认(后面累计block_delay_number个后续块),才会将交易从交易池中删除。

为了尽量避免打包重复的交易,打包交易的时候是随机选择交易的。具体做法是随机选择一个开始的序号,然后往后顺序扫描,直到没有交易,或者交易数量达到打包上限。

auth

auth主要负责检查交易的合法性,包括交易中每个字段的合法性,以及与历史交易是否重复。同现在的cita一样,auth会保存最近100个历史块中的交易hash

对于utxo类型的交易的交易,还要校验prevhash是否正确。

chain

chain主要是维护了一个管理未最终确认块的fork_tree。因为链的未确认部分长度是确定的(block_delay_number),因此fork_tree是一个HashMap,以index(块高-已经确认的最高块高)为key。其总长度为block_delay_number * 2 + 2,主要是考虑节点落后的情况下,可以尽量多的同步未来的候选块,加快同步的速度。

本实现比较简单,并没有分叉链之间切换的逻辑。而是在一个块得到确认之后,按照prevhash临时找出对应的分叉链。如果该分叉链比之前的主链要长,则进行替换,并更新一些相关的状态。

如果新的主链长度大于block_delay_number,则多出的部分最老的块得到最终确认,会将相关信息写入storage,并更新当前块高/块hash等信息。

新确认的块有两个来源:一个是共识微服务通过commit_block提交的块,另外一个是同步过来的块。只不过共识提交的确认块在未最终确认的区域,而同步过来的块是已经最终确认的。同步块的处理基本与上述相同,额外的会清理掉当前的主链,因为最新的当前块变化之后,原来的主链肯定跟它连不上了。

候选块除了刚启动初始化时会主动增加,后续是每次有新的块最终确认才会增加新的候选块。同步块的处理没有这个操作,因为处于同步状态意味着本节点落后了,那么主链和候选块很可能是没有意义的。

sync

本实现没有自己实现同步协议,而是使用了一个成熟的文件同步工具(syncthing)。针对要同步的内容(txproposalblock)分别创建了同步文件夹。

将要同步的内容写入对应的文件夹,就会自动同步到其他节点。接受方使用inotify监控文件变化,有新的文件之后会生成通知事件。

有一个单独的任务,定时拉取通知事件,根据事件类型的不同,分别调用不同的处理函数。

核心流程和数据结构

区块链的核心流程有同步和出块。

同步在本地实现里面使用了已有的软件,大致情况前面已经讲过,这里略过不谈。

出块其实就是将用户提交的原始交易数据,组装成共识模块需要的提案,经过共识并最终确认之后,写入storage持久化的过程。

为了减少共识过程中带宽的消耗,最终共识的提案只是一个哈希值。从用户提交的原始交易数据到提案,经过了两次处理。即原始交易数据到compact block,和compact block到提案。

用户通过rpc接口提交原始交易数据,经过auth进行合法性验证,进入pool。需要提案的时候,从pool中打包一批交易,compact block中存放交易的哈希。

本实现中,block header中并没有proofexecuted block hash字段。而是在由compact block形成提案的时候,将上一个块的proofexecuted block hash计算在内。

这些过程可以随着具体设计的不同而变化,但是整个过程要保证是可验证的,以便其他节点收到候选块的时候可以验证。

Clone this wiki locally