Skip to content

架构概述

VIZ Ledger 实现为一个模块化的 C++ 守护进程(vizd),由分层库和插件系统组成。本页描述结构层次、设计模式及组件交互方式。


分层结构

┌─────────────────────────────────────────────────────────────────┐
│  程序                                                           │
│  vizd(节点守护进程)         cli_wallet(CLI 钱包)            │
├─────────────────────────────────────────────────────────────────┤
│  插件                                                           │
│  chain │ validator │ p2p │ webserver │ json_rpc │ database_api  │
│  social_network │ snapshot │ committee_api │ invite_api │ ...   │
├─────────────────────────────────────────────────────────────────┤
│  核心库                                                         │
│  libraries/chain     — 区块链状态机,fork 数据库                │
│  libraries/protocol  — 操作类型,交易                           │
│  libraries/network   — P2P 消息传递                             │
│  libraries/api       — 共享 API 属性类型                        │
│  libraries/wallet    — 交易构建辅助工具                         │
│  libraries/time      — NTP 感知时间工具                         │
└─────────────────────────────────────────────────────────────────┘

关键文件用途
libraries/chaindatabase.hpp区块链状态:账户、区块、对象、fork 数据库、共享内存
libraries/protocoloperations.hpp所有 64+ 操作类型的 static_variant 联合
libraries/networknode.hppP2P 引擎:对等连接、同步、消息传播
libraries/apichain_api_properties.hppAPI 插件返回的共享类型
libraries/walletwallet.hpp远程节点 API 调用、交易构建
libraries/timetime.hpp用于区块槽位时序的 NTP 同步

插件

插件在启动时向 AppBase 框架注册,并实现生命周期钩子(plugin_initializeplugin_startupplugin_shutdown)。

插件作用
chain打开数据库,验证并应用区块/交易
validator按计划生产区块(Fair-DPOS),管理 NTP 和看门狗
p2p管理对等连接,同步区块,传播交易
webserverAPI 访问的 HTTP 和 WebSocket 服务器
json_rpc将 JSON-RPC 请求路由到已注册的 API 插件
database_api只读查询:账户、区块、交易、全局数据
social_network索引和查询内容、投票、回复
snapshot创建和恢复状态快照
committee_api委员会工作请求查询
invite_api邀请对象查询
paid_subscription_api付费订阅查询
account_history账户操作历史索引
account_by_key按公钥查找账户
follow关注/屏蔽关系索引
tags基于标签的内容索引
validator_api验证者计划和签名密钥查询
debug_node测试工具:注入区块、设置时间

设计模式

事件驱动的观察者(信号)

链的 Database 在关键点发出 fc::signal 事件。插件订阅这些信号以实现索引、历史记录和通知,而无需与核心链耦合。

push_block() / push_transaction()

    ├── pre_apply_operation  ──► 订阅者插件(前置钩子)
    ├── [evaluator 应用状态变更]
    ├── post_apply_operation ──► 订阅者插件(后置钩子)
    └── applied_block        ──► 订阅者插件(区块已最终确认)

工厂 + 策略(Evaluator 注册表)

每种操作类型都有专用的 evaluator 类。EvaluatorRegistry 将操作类型 ID 映射到 evaluator 实例。应用交易时:

  1. Databasestatic_variant 中提取操作类型标签。
  2. 注册表返回已注册的 evaluator。
  3. Evaluator 的 do_apply(op) 修改数据库状态。

添加新操作只需注册新的 evaluator——无需修改调度循环。

基于插件的架构(AppBase)

vizd/main.cpp 在调用 app().exec() 之前向 AppBase 注册所有插件。每个插件声明其选项和依赖项;AppBase 负责管理顺序和生命周期。

main() ──► register_plugin<chain>()
       ──► register_plugin<validator>()
       ──► register_plugin<p2p>()
       ──► ...
       ──► app().initialize(argc, argv)
       ──► app().startup()
       ──► app().exec()   ← 事件循环运行至 SIGINT/SIGTERM

MVC 分离

组件职责
数据libraries/chain/database状态持久化、验证、信号
控制插件(chainvalidatorp2p生命周期、区块/交易接收、协调
视图API 插件(database_apisocial_network、…)只读查询端点

数据流:传入区块

对等节点(P2P)──► p2p_plugin::handle_block()
                ──► chain_plugin::accept_block()
                    ──► database::push_block()
                        ├── 验证区块头和签名
                        ├── 对每笔交易:
                        │     ├── 验证权限
                        │     └── evaluator->do_apply(operation)
                        ├── 处理虚拟操作(奖励、兑现)
                        ├── 发出 applied_block 信号
                        └── 更新 fork 数据库 / LIB

数据流:API 请求

客户端(HTTP/WS)──► webserver_plugin
                 ──► json_rpc_plugin::call()
                     ──► registry.find_api_method(api, method)
                         ──► database_api / social_network / ...
                             ──► database::get_*(...)
                                 ──► 返回 JSON 结果

并发模型

关注点方法
写操作单一写线程(可选配置 single-write-thread
读操作通过 chainbase 共享内存支持多个并发读取者
P2P I/O专用 boost::asio::io_service 线程池
区块生产计时器验证者插件中独立的 io_service + 线程,防止 P2P 延迟
RPC 服务可配置线程池(rpc-endpoint-thread-pool-size

最重要的不变量:任何时刻只有一个线程可以持有数据库的写锁。 所有 evaluator 和区块处理代码都在该锁下运行。


共享内存数据库

状态存储在由 chainbase 管理的内存映射文件(shared_memory.bin)中。关键属性:

  • 所有对象索引(账户、区块、内容、验证者、…)都存储在该文件中。
  • 当可用空间低于阈值时,文件会增量扩展。
  • 正常关闭后文件保持一致;崩溃可能需要从区块日志重放。
  • 节点可以在区块边界导出共享内存状态的快照——参见快照

源码映射

文件架构中的角色
programs/vizd/main.cpp插件注册和启动
libraries/chain/include/graphene/chain/database.hpp核心数据库接口和信号
libraries/chain/include/graphene/chain/evaluator_registry.hpp操作 evaluator 工厂
libraries/network/include/graphene/network/node.hppP2P 节点委托接口
libraries/protocol/include/graphene/protocol/operations.hpp操作类型联合
plugins/chain/plugin.cpp链插件:区块/交易接收
plugins/json_rpc/plugin.cppJSON-RPC 调度