Graphene 源码阅读 - 架构篇 - 节点实例启动流

3년 전

大家好, 本文正式开启架构篇.

如果你还有印象的话, 我们之前在 源码结构 中曾简要的介绍过 bitshares 源码中的每个模块, 这个篇章将会和大家探讨各个模块之间的调用关系, 节点运行时模块之前如何交互, 逐步为大家呈现出一条清晰地脉络.

与整个节点的运行最相关的要数 app 模块了, 所以 app 模块就作为架构篇的第一个模块在本文介绍. 下文中 app 模块我们将其称之为节点实例模块或者直接成为节点实例, 这个名字将更能够表达此模块的含义.

节点实例

节点实例模块在整个系统中无疑是位于顶端的, 系统中各个组件都是由它触发激活并监控他们的状态. 节点在启动时会调用 app::initialize() 以及 app::startup() 方法, app::initialize() 中主要的工作就是注册插件到自己的静态变量中, app::startup() 才包含了节点启动的主要流程.

下面我们就来详细看看节点启动流程.

节点实例启动

genesis 加载进内存

第一步就是加载创世信息 genesis.json, 如果你没指定 —genesis-json (如果你要跑主链的话也不需要指定), egenesis 组件会负责加载默认创世信息 (参见 默认的 Genesis 创世信息), 创世信息加载进内存后会被存储在 genesis_state_type 类对象中, genesis_state_type 类的定义和 genesis.json 中的字段是一一对应的, 只有一个例外是 genesis_state_type 中包含一个 initial_chain_id 字段, 这个字段是在创世信息全加载进内存后对这块内存求哈希算出来的, 所以在 genesis.json 中没有对应.

initial_chain_id 是很重要的字段, 它被用来标识不同节点所运行的是不是同一条链. 所以现在我们知道了, 所以只要不同节点使用相同的创世信息, 它们跑的就一同一条链; 而你如果修改哪怕只是创世信息中的一个微不足道的字段, 其 hash 值都会改变, 你也将不能与其它节点通信 - 实际上这已经创建了一条新链.

数据库打开

如果看过之前的数据库篇, 想必对这个过程会亲切一些, 没错, 这个过程做的就是从磁盘加载对象索引, 打开区块数据文件流, 必要的话还会重建部分对象索引.

另外要注意的是, 如果是节点的第一次启动, 数据库打开这个过程的末尾还会对上面加载的创世信息进行 apply, 这个工作很重要, 创新信息的很多内容和正常链上内容无二, 所以它也要上链, 总不能每次启动节点都将它是放在内存里的. init_genesis() 方法就是做这个工作的.

init_genesis

init_genesis() 在节点第一次启动时被调用, 它读取前面加载到内存中的创世信息并 apply, 这其中包含了大量的工作, 我们选一些主要的说明一下:

创建特殊账户

这个过程会创建区块链上的一些特殊账户对象, 并且是不用走检验直接在索引上创建, 用的是数据库篇说过的 object_database::create() 方法

特殊账户的个数由创世信息的 immutable_parameters.num_special_accounts 字段指定, 对目前的 bitshares 主链来说这个值是 100.

首先创建的是 committee-account, witness_account, relaxed-committee-account, null-account, temp-account, proxy-to-self 这 6 个特殊账户, 这六个账户的 id 依次为 1.2.0 ~ 1.2.5.

实际上目前特殊账户也就这 6 个, 创世信息中指定的 100 个是为了预留以备不时之需. 紧接着要为剩下的 94 个特殊账户预留位置, 预留位置的方式很简单粗暴, 就是创建 94 个账户然后再立马把它们删除, 这样索引结构中 6 ~ 99 号 id 就也被占用了, 新创建的账户将只能从 100 号开始, 如果你用 bitshares 的区块浏览器查看, 就会发现从 1.2.6 ~ 1.2.99 这 94 个账户至今还是空的.

数据库篇 ~ 索引模型 中我们说到过创建对象时有个 set_next_id() 方法可以显式指定要创建的对象的 id, 所以将来要创建 6 ~ 99 号账户的话, 就可以发起一个账户创建交易, 其中指定账户的 id.

创建核心资产与特殊资产

核心资产也就是 BTS 资产, 特殊资产是一些名字以 “SPECIAL_” 打头的资产, 估计也是留作备用. 它们的创建套路和创建初始账户一致, 不再敖述.

创建全局对象

包括全局属性对象 (global_property_object), 动态全局属性对象 (dynamic_global_property_object), 链属性对象 (chain_property_object), 以及区块总结对象 (block_summary_object).

创建初始账户

上面创建的特殊账户是不属于个人的账户, 这里创建的 “初始账户” 实际上都是一些个人账户了, 这些账户可以说是这条链上的 “创世账户”.

不过这些账户毕竟是个人账户, 这些账户都是当初社区最早的那批参与者们, 账户信息也都是他们自己提供的. 既然是人提供的信息, 那就不是 100% 可信的, 所以这些账户的创建不能像特殊账户那样直接创建加索引, 而是要走操作创建, 检验上链的过程, 所以创建这些账户时会看到用的是 apply_operation 方法.

初始账户们由创世信息的 initial_accounts 字段指定, 总共有 90653 个账户.

创建初始资产

和初始账户一样, 初始资产也是一些 “个人” 资产. 创建过程和初始账户一样, 不再敖述.

其它

其它的还有创建初始余额, 初始见证人, 委员会, 提案, 套路和上述一致.

顺便说一句, 初始账户, 初始资产, 初始余额这几个信息几乎是占据了默认创世信息的全部, 默认创世文件 genesis.json 总共 35M 之大, 而其中 99.99% 都是这级部分信息贡献的.

p2p 网络与 rpc 服务初始化

数据库搞好之后, 下一步就是 p2p 网络的建立以及 rpc 服务的启动.

篇幅关系, 这两部分留到后面继续介绍吧, 敬请期待.


Posted from my blog with SteemPress : http://cifer.me/2018/05/01/graphene-%e6%ba%90%e7%a0%81%e9%98%85%e8%af%bb-%e6%9e%b6%e6%9e%84%e7%af%87-%e8%8a%82%e7%82%b9%e5%ae%9e%e4%be%8b%e5%90%af%e5%8a%a8%e6%b5%81/

Authors get paid when people like you upvote their post.
If you enjoyed what you read here, create your account today and start earning FREE STEEM!
STEEMKR.COM IS SPONSORED BY
ADVERTISEMENT
Sort Order:  trending

@cifer, 这是小可可我在steemit最好的邂逅,好喜欢你的编程贴(^∀^)哇~~~ img