config的配置项中大量使用到了一个容器:flat_set。这是一个使用键存储对象,且经过排序的容器,同时它是一个去重容器,也就是说容器中不会包含两个相同的元素。
其中被序列化公开的属性有:
FC_REFLECT( eosio::chain::controller::config, (actor_whitelist) // 账户集合,作为actor白名单 (actor_blacklist) // 账户集合,作为actor黑名单 (contract_whitelist) // 账户集合,作为合约白名单 (contract_blacklist) // 账户集合,作为合约黑名单 (blocks_dir) // 存储区块数据的目录名字,有默认值为"blocks" (state_dir) // 存储状态数据的目录名字,有默认值为"state" (state_size) // 状态数据的大小,有默认值为1GB (reversible_cache_size) // 可逆去快数据的缓存大小,有默认值为340MB (read_only) // 是否只读,默认为false。 (force_all_checks) // 是否强制执行所有检查,默认为false。 (disable_replay_opts) // 是否禁止重播参数,默认为false。 (contracts_console) // 是否允许合约输出到控制台,一般为了调试合约使用,默认为false。 (genesis) // eosio::chain::genesis_state结构体的实例,包含了创世块的初始化配置内容。 (wasm_runtime) // 运行时webassembly虚拟机的类型,默认值为eosio::chain::wasm_interface::vm_type::wabt (resource_greylist) // 账户集合,是资源灰名单。 (trusted_producers) // 账户集合,为可信生产者。 )未包含在内的属性有:
flat_set< pair<account_name, action_name> > action_blacklist; // 账户和action组成一个二元组作为元素的集合,储存了action的黑名单 flat_set<public_key_type> key_blacklist; // 公钥集合,公钥黑名单 uint64_t state_guard_size = chain::config::default_state_guard_size; // 状态守卫大小,默认为128MB uint64_t reversible_guard_size = chain::config::default_reversible_guard_size; // 可逆区块守卫大小,默认为2MB bool allow_ram_billing_in_notify = false; // 是否允许内存账单通知,默认为false。 db_read_mode read_mode = db_read_mode::SPECULATIVE; // db只读模式,默认为SPECULATIVE validation_mode block_validation_mode = validation_mode::FULL; // 区块校验模式,默认为FULLcontroller::block_status,区块状态枚举类,包括:
irreversible = 0,该区块已经被当前节点应用,并且被认为是不可逆的。
validated = 1,这是由一个有效生产者签名的完整区块,并且之前已经被当前节点应用,因此该区块已被验证但未成为不可逆。
complete = 2,这是一个由有效生产者签名的完整区块,但是还没有成为不可逆,也没有被当前节点应用。
incomplete = 3,这是一个未完成的区块,未被生产者签名也没有被某个节点生产。
接下来,查看controller的私有成员:
apply_context类对象,处理节点应用区块的上下文环境。其中包含了迭代器缓存、二级索引管理、通用索引管理、构造器等内容。
transaction_context类对象,事务上下文环境。包含了构造器,转型,事务的生命周期(包括初始化、执行、完成、刷入磁盘、撤销操作),事务资源管理、分发action、定时事务、资源账单等内容。
mutable_db(),返回一个可变db,类型与正常db相同,都是chainbase::database,但这个函数返回的是一个常量引用。
controller_impl结构体的实例的唯一指针my。这是整个controller的环境对象,controller_impl结构体包含了众多controller功能的实现。通过my都可以缓存在同一个环境下使用。
controller类的共有成员属性以及私有成员介绍完了,还剩下公有成员函数,这部分内容非常多,几乎包含了整个链运行所涉及到的出块流程相关的一切内容,从区块本地组装、校验签名,到本地节点应用入状态库,经过多节点共识成为不可逆区块等函数。其中每个阶段都有对应的信号,信号功能使用了boost::signals2::signal库。controller维护了这些信号内容:
signal<void(const signed_block_ptr&)> pre_accepted_block; // 预承认区块(承认其他节点广播过来的区块是正确的)
signal<void(const block_state_ptr&)> accepted_block_header; // 承认区块头(对区块头做过校验)
signal<void(const block_state_ptr&)> accepted_block; // 承认区块
signal<void(const block_state_ptr&)> irreversible_block; // 不可逆区块
signal<void(const transaction_metadata_ptr&)> accepted_transaction; // 承认事务
signal<void(const transaction_trace_ptr&)> applied_transaction; // 应用事务(承认其他节点数据要先校验,通过以后可以应用在本地节点)
signal<void(const header_confirmation&)> accepted_confirmation; // 承认确认
signal<void(const int&)> bad_alloc; // 内存分配错误信号
controller的具体实现