架构
Velum 分为六层。每一层只知道完成自身工作所需的信息,仅此而已。
各层一览
| 层 | 能看到 | 看不到 |
|---|---|---|
| 应用 | 你的明文消息、联系人、助记词 | 其他用户的任何信息 |
| 信封 | 为某台设备加密的一条消息 | 未经拆分不会离开手机 |
| 碎片 | 大小相同的片段,附带回执指纹 | 内容、发件人、真实大小 |
| 节点 | 不透明的碎片、当天的信箱、回执 | 谁发送、谁接收、内容是什么 |
| 入口网关 | 连接以及它转发的 JSON 帧 | 内容;身份从不以明文传输 |
| 区块链 | 转账、代币、订单、回执、奖励 | 消息,以及谁在和谁说话 |
应用
应用生成助记词,派生出各类密钥(身份、钱包、信箱),并创建一把永不离开手机的设备密钥。聊天记录保存在用 SQLCipher 加密的 SQLite 中;密钥以 WHEN_UNLOCKED_THIS_DEVICE_ONLY 存入钥匙串,因此不会随 iCloud 备份传出。
发送消息时,应用会:
- 用设备密钥对内容签名。
- 为收件人的每台设备密封一份,也为你自己的其他设备密封一份(这样所有设备上的记录一致)。
- 把每个信封填充到固定大小,再拆成 5 个碎片。
- 每个碎片经由不同节点,发往收件人当天的信箱。
信封
信封是为一台设备加密的消息。格式如下:
[1 字节版本 = 2][32 B X25519 临时公钥][1088 B ML-KEM-768 密文 kemCt][24 B nonce][密文]
信封外部没有任何能识别发件人的信息(密封发件人)。内部包含由源设备签名的内容、发件人身份,以及把该设备绑定到该身份的签名。详见密码学。
碎片
每个信封先填充到一个档位(2 KB、8 KB、32 KB、128 KB、512 KB、2 MB 或 8 MB),再用 Reed–Solomon 3/5 编码拆分:任意三个碎片即可还原。每个碎片都带有其回执秘密的 SHA-512 指纹。详见碎片与回执。
节点
节点是运行在社区成员电脑上的程序,承担三项工作:
- 打通桥。 桥是节点在发件人与信箱之间打通并维护的一条线路:节点接收碎片(此时它是 carrier),保存下来,等信箱主人打开信箱时投递出去(此时它是 courier)。
- 出块。 全节点轮流打包区块,每个轮次的目标为 2 秒;实际节奏以测量为准。
- 发现 VEL。 每个纪元,节点公布一份其各座桥工作的汇总申报;经过抽样验证后,节点发现本纪元属于自己的那份 VEL。
节点分为全节点(电脑,参与出块)和轻节点(手机应用,只投递碎片)。对每个碎片,一次公开抽签选出 3 个候选节点,应用使用其中最近的一个。参见搭建节点。
入口网关
公共入口网关(wss://velum.consultorabim.com/hub)是汇合点:节点签名问候后接入,应用发送 RPC 请求,浏览器实时接收区块。网关只转发帧,没有任何能读取内容的密钥。
为了抗封锁,入口网关分布在多个启用 ECH 的不同域名上,节点之间可以直接连接(ws://host:7420/ws),每个节点还会把自己的地址公布到链上(endpoint)。参见抗封锁。
应用 ──ws──▶ 网关 /hub?role=client ──▶ 选定的节点(RPC) 或直连:ws://节点:7420/ws?role=client
节点 ──ws──▶ 网关 /hub?role=node ◀─▶ 其他节点 节点之间也可直连:?role=node
网站 ──ws──▶ 网关 /hub?role=watch ◀── 实时区块与统计
区块链
一条独立的区块链,不依赖外部系统。它保存:
- VEL 和各代币的余额,以及每个钱包的 nonce。
- 节点注册信息、等级和投递积分。
- 工作申报(Merkle 根)、抽样验证结果和奖励。
- 每个纪元的预言机价格,以及网络储备的余额。
- 公开别名(
name.register)。 - 代币、给节点的代币奖池、市场订单和成交。
- 已认证的设备(仅其密钥的哈希,不含身份)。
它从不保存消息、联系人、设备列表或聊天身份。参见共识与区块。
分离了什么,为什么
| 分离 | 目的 |
|---|---|
| 身份密钥 ≠ 钱包密钥 | 让任何人都无法把你的聊天和转账联系起来。 |
| 每台设备有自己的设备密钥 | 移除一台设备无需重建账号。 |
| 信箱按天、按设备变化 | 让节点无法长期追踪任何人。 |
| 回执不含签名和地址 | 发现 VEL 不会暴露收件人。 |