大家好, 本文正式开启架构篇.
<p dir="auto">如果你还有印象的话, 我们之前在 <a href="https://steemit.com/bitshares/@cifer/4fxtit-graphene" target="_blank" rel="noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">源码结构 中曾简要的介绍过 bitshares 源码中的每个模块, 这个篇章将会和大家探讨各个模块之间的调用关系, 节点运行时模块之前如何交互, 逐步为大家呈现出一条清晰地脉络. <p dir="auto">与整个节点的运行最相关的要数 app 模块了, 所以 app 模块就作为架构篇的第一个模块在本文介绍. 下文中 app 模块我们将其称之为节点实例模块或者直接成为节点实例, 这个名字将更能够表达此模块的含义. <p dir="auto"><h2>节点实例<p> <p dir="auto">节点实例模块在整个系统中无疑是位于顶端的, 系统中各个组件都是由它触发激活并监控他们的状态. 节点在启动时会调用 <code>app::initialize() 以及 <code>app::startup() 方法, <code>app::initialize() 中主要的工作就是注册插件到自己的静态变量中, <code>app::startup() 才包含了节点启动的主要流程. <p dir="auto">下面我们就来详细看看节点启动流程. <p dir="auto"><h2>节点实例启动<p> <p dir="auto"><h3>genesis 加载进内存<p> <p dir="auto">第一步就是加载创世信息 genesis.json, 如果你没指定 <code>—genesis-json (如果你要跑主链的话也不需要指定), egenesis 组件会负责加载默认创世信息 (参见 <a href="https://steemit.com/bitshares/@cifer/graphene-genesis" target="_blank" rel="noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">默认的 Genesis 创世信息), 创世信息加载进内存后会被存储在 <code>genesis_state_type 类对象中, <code>genesis_state_type 类的定义和 genesis.json 中的字段是一一对应的, 只有一个例外是 <code>genesis_state_type 中包含一个 <code>initial_chain_id 字段, 这个字段是在创世信息全加载进内存后对这块内存求哈希算出来的, 所以在 genesis.json 中没有对应. <p dir="auto"><code>initial_chain_id 是很重要的字段, 它被用来标识不同节点所运行的是不是同一条链. 所以现在我们知道了, 所以只要不同节点使用相同的创世信息, 它们跑的就一同一条链; 而你如果修改哪怕只是创世信息中的一个微不足道的字段, 其 hash 值都会改变, 你也将不能与其它节点通信 - 实际上这已经创建了一条新链. <p dir="auto"><h3>数据库打开<p> <p dir="auto">如果看过之前的数据库篇, 想必对这个过程会亲切一些, 没错, 这个过程做的就是从磁盘加载对象索引, 打开区块数据文件流, 必要的话还会重建部分对象索引. <p dir="auto">另外要注意的是, 如果是节点的第一次启动, 数据库打开这个过程的末尾还会对上面加载的创世信息进行 apply, 这个工作很重要, 创新信息的很多内容和正常链上内容无二, 所以它也要上链, 总不能每次启动节点都将它是放在内存里的. <code>init_genesis() 方法就是做这个工作的. <p dir="auto"><h3>init_genesis<p> <p dir="auto"><code>init_genesis() 在节点第一次启动时被调用, 它读取前面加载到内存中的创世信息并 apply, 这其中包含了大量的工作, 我们选一些主要的说明一下: <p dir="auto"><h4>创建特殊账户<p> <p dir="auto">这个过程会创建区块链上的一些特殊账户对象, 并且是不用走检验直接在索引上创建, 用的是数据库篇说过的 <code>object_database::create() 方法 <p dir="auto">特殊账户的个数由创世信息的 <code>immutable_parameters.num_special_accounts 字段指定, 对目前的 bitshares 主链来说这个值是 100. <p dir="auto">首先创建的是 committee-account, witness_account, relaxed-committee-account, null-account, temp-account, proxy-to-self 这 6 个特殊账户, 这六个账户的 id 依次为 1.2.0 ~ 1.2.5. <p dir="auto">实际上目前特殊账户也就这 6 个, 创世信息中指定的 100 个是为了预留以备不时之需. 紧接着要为剩下的 94 个特殊账户预留位置, 预留位置的方式很简单粗暴, 就是创建 94 个账户然后再立马把它们删除, 这样索引结构中 6 ~ 99 号 id 就也被占用了, 新创建的账户将只能从 100 号开始, 如果你用 bitshares 的区块浏览器查看, 就会发现从 1.2.6 ~ 1.2.99 这 94 个账户至今还是空的. <p dir="auto">在 <a href="https://steemit.com/bitshares/@cifer/7c8spa-graphene" target="_blank" rel="noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">数据库篇 ~ 索引模型 中我们说到过创建对象时有个 <code>set_next_id() 方法可以显式指定要创建的对象的 id, 所以将来要创建 6 ~ 99 号账户的话, 就可以发起一个账户创建交易, 其中指定账户的 id. <p dir="auto"><h4>创建核心资产与特殊资产<p> <p dir="auto">核心资产也就是 BTS 资产, 特殊资产是一些名字以 “SPECIAL_” 打头的资产, 估计也是留作备用. 它们的创建套路和创建初始账户一致, 不再敖述. <p dir="auto"><h4>创建全局对象<p> <p dir="auto">包括全局属性对象 (global_property_object), 动态全局属性对象 (dynamic_global_property_object), 链属性对象 (chain_property_object), 以及区块总结对象 (block_summary_object). <p dir="auto"><h4>创建初始账户<p> <p dir="auto">上面创建的特殊账户是不属于个人的账户, 这里创建的 “初始账户” 实际上都是一些个人账户了, 这些账户可以说是这条链上的 “创世账户”. <p dir="auto">不过这些账户毕竟是个人账户, 这些账户都是当初社区最早的那批参与者们, 账户信息也都是他们自己提供的. 既然是人提供的信息, 那就不是 100% 可信的, 所以这些账户的创建不能像特殊账户那样直接创建加索引, 而是要走操作创建, 检验上链的过程, 所以创建这些账户时会看到用的是 <code>apply_operation 方法. <p dir="auto">初始账户们由创世信息的 <code>initial_accounts 字段指定, 总共有 90653 个账户. <p dir="auto"><h4>创建初始资产<p> <p dir="auto">和初始账户一样, 初始资产也是一些 “个人” 资产. 创建过程和初始账户一样, 不再敖述. <p dir="auto"><h4>其它<p> <p dir="auto">其它的还有创建初始余额, 初始见证人, 委员会, 提案, 套路和上述一致. <p dir="auto">顺便说一句, 初始账户, 初始资产, 初始余额这几个信息几乎是占据了默认创世信息的全部, 默认创世文件 genesis.json 总共 35M 之大, 而其中 99.99% 都是这级部分信息贡献的. <p dir="auto"><h3>p2p 网络与 rpc 服务初始化<p> <p dir="auto">数据库搞好之后, 下一步就是 p2p 网络的建立以及 rpc 服务的启动. <p dir="auto">篇幅关系, 这两部分留到后面继续介绍吧, 敬请期待.<br /><center><hr /><em>Posted from my blog with <a href="https://wordpress.org/plugins/steempress/" target="_blank" rel="noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">SteemPress<span> : <a href="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/" target="_blank" rel="noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">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/<hr />Graphene 源码阅读 - 架构篇 - 节点实例启动流
7 years ago in #bitshares by cifer (60)
$89.67
- Past Payouts $89.67
- - Author $68.29
- - Curators & beneficiaries $21.38
- > fredrikaa: $2.24
- > howo: $2.24
@cifer, 这是小可可我在steemit最好的邂逅,好喜欢你的编程贴(^∀^)哇~~~