# 分布式数据链路 · 详细方案与逻辑推演 > 📌 术语:本文以「分布式」指代本项目(2026-09-19 由「去中心化」更名);引用原文、DAO 专有名词与行业泛指保留原措辞。 > 版本 v1.7 | 2026-09-19 | 状态:**推演完成 · 待评审** > 主文档:`分布式数据存储与查询-架构设计与隐私保护方案_20260919.md`(v1.2 · md5 `788f2a3a574733eae35cea3404550a7f`) > 推演基准:`分布式数据链路-技术方案与落地路线_20260919.md` | 前身(存档):`面向公众资产平台与隐私金库-落地方案_20260919.md` > 本文做九件事:**(一) 8 场景推演(§2)** + **(二) 多用户与规模量级(§3)** + **(三) 能力层密钥与核验(§3.6)** + **(四) 中继 / 节点信誉分层(§3.7)** + **(五) 目标形态 3 骨干 + 1,000 节点 + 50 万终端(§3.8)** + **(六) 终端升格子节点(§3.9)** + **(七) 依赖顺序裁决(§3.10)** + **(八) 账号密码与 1000 万并发登录(§3.11,v1.6 新增)** + **(九) 链上 / 链下边界与链的引入时机(§3.12,v1.7 新增)** > ⛔ 本文**不改动**上述三份文档;对主文档的修订建议集中写在 §5,须拍板后才回填。 ### 📌 v1.1 修订记录(依据用户 2026-09-19 三条拍板) | # | 用户拍板(原话要点) | 本文落点 | |---|---|---| | 1 | 「**现在不做,预留扩展空间(这是面向全球的开源项目)**」 | §2.9 场景 8 第 7 步 + §3.6 V1 扩展点 + §5 已拍板段 —— 开源主仓**默认不含任何价值凭证能力** | | 2 | 「**平台只做互联和项目协作的作用:能力共创、能力共享、能力使用分发**」 | §2.9 前置澄清(平台范围收窄)+ §4 判据 22(平台不经手资金与内容) | | 3 | 「**预留扩展空间,先用最低成本的方式生成密钥与核验**」 | **§3.6(新增整节)** —— V0 = WebCrypto/Passkey + Merkle 包含证明 + Ed25519 签名,零额外基础设施;V1 = ZK 只留接口 | ### 📌 v1.2 修订记录(依据用户 2026-09-19 19:30 提问与 19:31 认可) | # | 用户输入(原话要点) | 本文落点 | |---|---|---| | 1 | 提问:「**🛡️ 可信中继网络 … 节点信任:将中继节点的历史表现(延迟、成功率)记录在链上,用智能合约自动筛选可靠节点**」+ 认可:「**分层方案和建议不错 可以记录下来**」 | **§3.7(新增整节)** + §0 第 8 条 + §4 判据 25 / 26 + §5.0 第 4 行 + §1.2 新增 `OBS` 代号 + §5 第 14 项(由步 ① 引出) | ### 📌 v1.3 修订记录(依据用户 2026-09-19 规模提问 + 本轮核算发现) | # | 触发 | 本文落点 | |---|---|---| | 1 | 用户提问:「**假设要部署3台骨干服务器 和1000台节点 以及500000个终端设备**…」 | **§3.8(新增整节)** + §0 第 9 条 + §4 判据 27 / 28 + §5 第 15 / 16 项 | | 2 | **本轮核算发现的既有算错**(§3.4.2「峰值 TPS」行) | **已更正 §3.4.2 表格两行 + 计算示例第 7 条 + §3.4.3 判断 3 + §0 第 5 条**:年→秒除数须为 `365×86400`;100 万用户正确值 **95 TPS**(读 **951 TPS**),原值偏大 **3.65×** | ### 📌 v1.4 修订记录(依据用户 2026-09-19 子节点提问) | # | 触发 | 本文落点 | |---|---|---| | 1 | 用户提问:「**假设50W终端之间有公网IP的设备也能升级为子节点呢,现有方案支持这样的情况吗**」 | **§3.9(新增整节)** + §0 第 10 条 + §4 判据 29 / 30 + §5 第 17 项 | ### 📌 v1.5 修订记录(依据用户 2026-09-19 依赖顺序提问) | # | 触发 | 本文落点 | |---|---|---| | 1 | 用户提问:「**现在有必要优化吗,不优化后续做链会有影响吗,先做链后续在优化网络是不是会返工**」 | **§3.10(新增整节)** + §0 第 11 条 + §4 判据 31 | ### 📌 v1.6 修订记录(依据用户 2026-09-19 账号密码 / 并发登录提问) | # | 触发 | 本文落点 | |---|---|---| | 1 | 用户提问:「**链上存 用户账号密码等信息,1000万用户 1000万同时登录 能支持并发吗,是不是无法像数据库那样做分布式 主从库那样容易扩展性能**」 | **§3.11(新增整节)** + §0 第 12 条 + §4 判据 32 | ### 📌 v1.7 修订记录(依据用户 2026-09-19 拍板:链的引入时机) | # | 用户拍板(原话) | 本文落点 | |---|---|---| | 1 | 「**还是区分链上和链下的数据是对的,后续做DAO和在线游戏时在考虑链**」 | **§3.12(新增整节)** + §0 第 13 条 + §4 判据 33 + §5.0 第 5 行 + §6 自查 1 行 + §7 判断 1 条 | --- ## 0. 本文结论(十三条) 1. **架构在 7 个场景下逻辑自洽,但有 3 处真实的冲突点必须在 S0 解决**:① B 层"链上不可删" vs PIPL 47 条删除权(§2.4)② 内容哈希的"公开可验证" vs "删除后不可枚举关联"(§2.4)③ zkVM 盲验证与 B 层"平台授权可解"的边界(§2.5)。 2. **2-of-3 门限只防"单方",不防"平台 + 第三方串谋"**(§2.3 / §2.5)。这是全架构**比桥表更危险的残余风险**——桥表泄露泄露身份,双片串谋直接泄露全部数据明文。必须如实写进安全声明。 3. **最现实的攻击不是密码学被破,而是前端投毒**(§2.7):平台控制客户端下发通道 ⇒ 可窃取用户 MK。所有"平台不可解"的承诺都建立在这条之上,必须用可验证构建 + 透明日志登记来收窄。 4. **多租户密钥的分水岭只有一条判据:「平台是否需要解」**(§3.1)。需要解 ⇒ 由租户级 KEK_t 派生(平台侧);不需要解 ⇒ 由用户级 KEK_u 派生(用户侧,平台不可计算)。**不是"每租户一把 DEK"**。 5. **百万用户在写入量级上是单链可承载的**(§3.4:峰值约 95 TPS),真正的门槛在三处:**盲索引条目(约 10 GB,且是查询热路径)· 审计日志增速(约 10 GB/年,只增不减)· 读流量(约为写的 10 倍 ⇒ 约 951 TPS)**。⇒ 查询必须走只读副本 + 索引层缓存,**不得穿过共识层**。 6. **统计攻击无法消除,只能压到"需要外部辅助信息 + 大量观测"才成立**(§3.5)。这是验收判据 10 的落点,也是"号称加密但被流量分析打穿"的分水岭。 7. **DAO 是第 8 个场景,且它的前置条件是"平台承担备案与实名"**(§2.9)—— 🔴 律所口径:未登记为法人/合伙的 DAO **无法合规从事区块链信息服务**,所以 DAO 自己备案做不到,**只能是平台上的组织形态**。本轮三条拍板(价值凭证现在不做但预留 · 平台只做互联与协作 · 先上最低成本密钥与核验)已落地为 §2.9 + §3.6。 8. **「把中继节点表现记在链上、用合约自动筛选」这个形态不成立,正确形态是四层分工**(§3.7):合约不会观测(要人喂数 ⇒ 中心只是换了位置)· 当前真正缺的是 **≥3 个独立观测者**(不是链)· 逐条上链在 1,000 节点时 ≈ 33 TPS 而 99% 样本无人读 · 共识秒级 vs 选路毫秒级差 3–4 个数量级 ⇒ **链只做「周期性信任锚」,实时选路留在链下**。上链成立的唯一判据 = **观测者与被观测者互不信任 且 筛选结果需对外举证**(§3.7.4)。 9. **3 骨干 + 1,000 节点 + 50 万终端的形态推演**(§3.8):数据面不成问题(元数据 12.8 GB/年 · 密文 blob 323 GB · 每节点 0.97 GB/年);两处**形态硬伤** —— 3 台骨干 BFT `f = 0`(容 1 台作恶须 **4 台**)、1,000 节点跑经典 PBFT 是 `O(n²)` 不可行(须抽样委员会 / 分层锚定);覆盖网络**撑得住 1,000 节点(占用 13.3%)撑不住 50 万终端**(需 17–67 台中继,而目录硬上限只有 8 个地址)。 10. **终端升格为子节点:①② 已支持、③ 只到设计**(§3.9):"子节点"是**三档不同能力** —— **① 被连方**(声明端口 + 回环监听 + 一机一钥,已支持,但**纯浏览器终端做不到**)· **② 内容子节点**(peer 声明 + 分组隔离 + 取回复算,已支持)· **③ 中继子节点**(公网入向可达 + 控制面登记 + 目录下发,**无自动升格代码路径**,106 升格是人工)。五条硬门里最前置的是**目录 8 地址上限**(升格出 2.5 万台也发现不了)与**"有公网 IP"≠"入向可达"**。 11. **依赖顺序:不必先优化网络,先做链也不返工**(§3.10):判据是**「返工来自同一件事被定义两遍,不来自晚做优化」** —— 网络侧 6 项里只有**目录协议**会变兼容债,其余 5 项全是加法、后置不触碰链的数据模型;现在必须定死的是**三条复用点**(节点身份、寻址与会合、锚定落点)+**两个口径**(命名空间、世代),⛔ 不写死则返工点恰好落在「身份 / 寻址」。 12. **账号密码不上链、登录事件不上链;1000 万并发登录的瓶颈是 KDF 不是存储**(§3.11):密码摘要留在链下应用侧(链上最多存匿名锚);"链 vs 库"在登录并发上**不是变量**(同样的 KDF 账);用户的判断**正确** —— 链的**写**扩展只能分片、片内不能像主从那样加写节点,**但读的扩展与库相同**。1000 万用户在 B 层必须**分片**(峰值写 951 TPS 已抵单链下沿 ⇒ 8 片 / 每片 119 TPS)。 13. **链上 / 链下分离定为原则;链的引入时机 = 做 DAO 与在线游戏时**(§3.12):链对外提供的三样能力 —— **时序不可否认 · 多方一致性 · 防篡改日志** —— 在 V0 全都有链下等价物(**Merkle 根 + 可信时间戳锚** / **多方各留副本 + 摘要互签对账** / **哈希链**),且三者的升级动作**一律是「把单方改成多方」** ⇒ ⛔ 不触碰数据结构、密钥分层与 API 形状,**不返工**(与第 11 条同一判据)。V0 唯一硬约束:对外「**不可篡改**」必须由**用户自行举证**(Merkle 根 + 签名 + 自留副本),⛔ 不得表述为"平台保证"—— 前者在引入链后自动升级为可举证真命题,后者届时是**推翻承诺**。落层:DAO → **A 层**;在线游戏 → **B 层 + 链下执行、链上结算**(与 §3.7「链只做周期锚」同构)。 --- ## 1. 推演口径与分层记号 ### 1.1 三层落点记号(本文全文统一) | 记号 | 含义 | 平台能否解密 | |---|---|---| | **A** | A 层分布式存储与查询层(可公开 / 半公开);密文 blob + 盲索引 token + 匿名 ID + 内容哈希 | ⛔ **永不** | | **B** | B 层隐私金库(私有共识链,不公开但多节点共识);KV 结构 | ✅ **授权下可**(受审计约束) | | **桥** | 窄桥匿名 ID 映射表(HMAC,独立加密、双人授权、每次留痕) | ✅ 可(最高保护级) | | **链下** | 云对象存储(密文 blob 本体)/ 关系库 / 备份 | 视封装密钥而定 | | **设备** | 用户侧(安全芯片 / Keychain / 原生客户端) | ⛔ 永不 | ### 1.2 参与方代号 `U`=用户设备 | `GW`=接入网关 | `BR`=桥服务 | `B`=B 层节点群 | `A`=A 层链 | `OSS`=云对象存储 | `KMS`=密钥管理(HSM) | `T3`=用户指定的第三方托管方 | `ZK`=证明层 | `LOG`=只追加审计日志 | `ADM`=平台管理员 | `OBS`=信誉观测者(多方独立,§3.7) ### 1.3 密钥分层记号(§3.1 详述) `MK` 用户主密钥(设备生成,Shamir 分片)→ `KEK_t` 租户级 KEK(KMS 持有)→ `KEK_u`=HKDF(MK,…) 用户级 → 域密钥 `DK_idx`/`DK_kv_key`/`DEK_kv`/`DEK_data` → 记录级 `rk` > **全文默认前提**:密码学原语一律用成熟库(libsodium / OpenSSL / 国密 SDK)或硬件模块,⛔ 不自研(主文档 §3.2 红线 1)。 > **全文默认取舍**:任何一步"是否引入新组件 / 是否花钱 / 是否触碰合规口径"都**不在本文自决**,统一收进 §5 待拍板。 --- ## 2. 多场景推演 > 每个场景统一五段:**参与方 → 时序步骤(含落层与安全属性)→ 该场景的数据落点汇总 → 失败模式与处置 → 本场景的结论/遗留**。 ### 2.1 场景 1 · 新用户注册与首份数据上传 **参与方**:U · GW · BR · B · A · OSS · KMS · T3 · LOG **时序步骤** | 步 | 动作(参与方) | 落层 | 该步的安全属性 | |---|---|---|---| | 1 | 提交注册:手机号 + 邮箱验证码 + 实名信息(U→GW) | 桥(凭据校验)+ B(实名落库) | 传输层 TLS;验证码一次性;⛔ 实名**绝不进 A 层** | | 2 | 实名 KV 写入:`key=HMAC(DK_kv_key, normalize(uid))`,`value=AES-256-GCM(DEK_kv_pii, 实名)`(GW→B) | B | key 为盲索引 token ⇒ 链上节点看不出"同属一人";value 密文;全程审计 | | 3 | 生成 MK(32 B,设备 CSPRNG)(U) | 设备 | MK 由设备 CSPRNG 生成,**从不上传明文** | | 4 | Shamir 2-of-3 分片:Sh1→设备安全芯片、Sh2→B 层、Sh3→T3(U→B/T3) | 设备 / B / T3 | 单方仅持 1 片 ⇒ **信息论上无法重建**(非"计算困难",是"信息不足") | | 5 | 分片封装:Sh2 落 B 层前用 `KEK_t` 封装(B/KMS) | B | 拿到节点磁盘 ≠ 拿到可用分片;解封需 KMS 凭据 + 门限授权 | | 6 | 生成匿名 ID:`anon_id = HMAC(DK_bridge, tenant‖user_id)`(BR) | 桥 | 裸哈希会被彩虹表/枚举反推(手机号空间极小)⇒ 必须 HMAC + 域密钥 | | 7 | 首份数据加密:生成 `DEK_data(u, ds1)`;`rk=HKDF(DEK_data,"rec",rec_id,v1)`;`C=AES-GCM(rk, pt, AAD={anon_id,rec_id,v1})`(U) | 设备 | AAD 绑定归属与版本 ⇒ 防跨记录密文替换 | | 8 | 上传密文:GW 转存 `C` 到 OSS(路径含 `content_hash`)(U→GW→OSS) | 链下 | 平台只见密文;OSS 凭证由 GW 持有,**不暴露给 A 层** | | 9 | A 层链写:`{anon_id, content_hash, rec_id, v1, index_token[], blob_ptr, ts}`(GW→A) | A | ⛔ 链上**无任何明文**;仅有匿名 ID、哈希、token | | 10 | 盲索引写入:`index_token = truncate(HMAC(DK_idx, normalize(field)‖value), b)`(GW→A) | A | 只见 token 不见明文;截断位数 b 由总量算出(§3.4) | | 11 | DEK_data 信封备份:`wrap(DEK_data, MK)` 随数据写 A 层(U→A) | A | 🔴 **必须用 MK 包裹**——若用平台 KEK 包裹 ⇒ A 层零知识当场失效 | | 12 | 确认返回:anon_id + content_hash + 版本号(GW→U) | — | 客户端可独立复算 content_hash 校验 | | 13 | 审计锚定:本次全部操作事件写只追加日志并定期锚定(LOG) | 链下 + 锚 | 篡改可检测(主文档判据 9) | **数据落点汇总**:实名/联系方式 → **B**|密文 blob → **链下 OSS**|索引与内容哈希与匿名 ID → **A**|`anon_id↔user_id` 映射 → **桥**|MK 分片 → **设备 + B + T3**|DEK_data 包裹体 → **A** **失败模式与处置** | 失败 | 后果 | 处置 | |---|---|---| | OSS 成功、A 层链写失败 | **孤儿 blob**(有密文无索引,查不到) | 客户端持 rec_id 重试链写;后台对账清理 N 天无引用的 blob(⚠️ 需并入删除权流程) | | A 层链写成功、OSS 失败 | **悬空指针**(索引指向不存在的 blob) | 链上记录标 `pending`;客户端重传(密文是确定输入,可重算);超时未补 ⇒ 标记废弃 | | 分片只落 2 处(Sh2 写失败) | 用户仅剩 Sh1+Sh3,仍可恢复但冗余耗尽 | 🔴 **顺序纪律:三分片全部确认落位后,才允许上传首份数据** | | 实名 KV 写失败 | 注册未完成 | **阻断注册**——《区块链信息服务管理规定》第 8 条:未实名不得提供服务 | | 客户端时钟漂移 | 审计时间戳不可信 | 时间戳以**服务端签注**为准,客户端时间仅作提示 | **结论/遗留**:本场景的核心风险不在密码学,在**两步写(OSS + A 层)没有分布式事务** ⇒ 设计上接受最终一致,用对账 + 幂等补偿。⚠️ 幂等键 = `(anon_id, rec_id, version)`,重复写入必须去重(A 层链天然按 txid 去重)。 --- ### 2.2 场景 2 · 用户跨设备登录与查询 **参与方**:U2(新设备)· GW · 认证服务 · B · A · OSS · T3 · LOG **时序步骤** | 步 | 动作(参与方) | 落层 | 该步的安全属性 | |---|---|---|---| | 1 | 登录:账号 + 二次认证(U2→GW) | B(凭据哈希校验) | 密码走 Argon2id;二次认证防凭据单点 | | 2 | 设备绑定校验:新设备指纹/设备证书(U2→GW) | B | 🔴 **这是场景 3 之外唯一能阻止"平台+攻击者合谋取片"的闸门** | | 3 | 取回 Sh2:平台侧交出,需**双人授权 + 风控判定**(B/KMS→U2) | B | 平台持有 Sh2 ≠ 可随意使用;每次交出留痕(谁批、何因) | | 4 | (可选)取回 Sh3(T3→U2) | T3 | 第三方须**独立于平台**验证,否则两片同源 | | 5 | 重建 MK:Shamir 组合(U2 本地) | 设备 | MK 只在设备内存中存在;用后**显式清零**(mlock + 擦除 + 禁 core dump) | | 6 | 派生 `DK_idx`:`HKDF(KEK_u,"dk-index")`(U2 本地) | 设备 | ✅ **用户侧派生** ⇒ 平台无法替用户构造 token(防平台做访问模式画像) | | 7 | 构造查询 token:`token = truncate(HMAC(DK_idx, field‖value), b)`(U2) | 设备 | 查询条件明文不出设备 | | 8 | 提交 token 到查询接口(U2→GW→A) | A | 索引层只见 token;无法反解明文 | | 9 | 返回匹配指针列表(A→U2) | A | 只返回 blob 指针与内容哈希,不含数据 | | 10 | 取回密文:预签名 URL 或 anon_id 签名能力(U2→OSS) | 链下 | 预签名 URL 短期有效 + 绑定 anon_id + 单次使用 | | 11 | 取回 `wrap(DEK_data, MK)` 并用 MK 解出 DEK_data(U2→A→设备) | A→设备 | 平台全程不接触可用密钥 | | 12 | 本地解密:`rk=HKDF(DEK_data,"rec",rec_id,v)` → 解出明文(U2) | 设备 | 校验 AAD 与 content_hash ⇒ 防替换/降级攻击 | | 13 | 查询事件:`{anon_id, token 摘要, ts}` 写只追加日志(GW→LOG) | LOG | ⚠️ **这一步本身就是访问模式泄露面**(§3.5) | **数据落点汇总**:MK 分片 → **设备/B/T3**|查询条件明文 → **仅设备**|token → **A**|密文 blob → **链下 OSS**|查询审计 → **LOG** **失败模式与处置** | 失败 | 后果 | 处置 | |---|---|---| | 新设备未绑定即请求分片 | 攻击者冒充用户取 Sh2 | 阻断 + 强认证 + 告警;新设备首次取片后 N 小时内限制批量拉取(冷却期) | | Shamir 组合失败(分片损坏/版本不符) | 无法重建 MK | 分片带 checksum + 版本;回退 `Sh1+Sh3` 或 `Sh2+Sh3` 路径 | | 设备内存被 dump(恶意软件/调试器) | MK 泄露 | TEE 隔离(L3)+ 用后清零 + 禁 core dump + 原生客户端加固 | | token 截断过短 | 单次查询返回大量记录 | 应用层解密过滤兜底 + **单次返回行数硬上限**(判据 5 的落点) | | 预签名 URL 被转发 | 密文被未授权者下载 | 短期(分钟级)+ 绑定 anon_id + 单次使用;⚠️ 密文即使被下载也不可解,风险等级中等 | | **平台选择"服务端代理查询"模式** | 平台可任意扫描用户 token ⇒ 访问模式全暴露 | ⛔ 默认**不做**代理;若为体验引入,必须限定"只转发 token、不落盘、不聚合" | **结论/遗留**:本场景的设计选择是 **`DK_idx` 由用户侧派生**。若改为平台侧持有,可支持"服务端代理查询"(体验好、离线可查),代价是平台获得完整的访问模式可见性。这是**真取舍**(各有优劣)⇒ 收进 §5。 --- ### 2.3 场景 3 · 丢失密钥/设备 → 2-of-3 门限恢复 **参与方**:U3(新设备)· 恢复服务 · B · T3 · 可选守护人 · LOG · ADM **前置状态**:用户丢失设备(Sh1 丢失),仍可登录账号,但无 MK。 **时序步骤** | 步 | 动作(参与方) | 落层 | 该步的安全属性 | |---|---|---|---| | 1 | 发起恢复:新设备登录 + 触发恢复(U3→恢复服务) | B | 加强认证(实名 + 手机 + 活体/人工审核,按风险分级) | | 2 | 交付 Sh2:需**双人授权 + 事由登记**(ADM/B→U3) | B | 场景中**唯一**允许平台单独交出一片的路径;全程留痕 | | 3 | 交付 Sh3:第三方独立验证(向注册手机发挑战 / 守护人多签)(U3↔T3) | T3 | 🔴 第三方验证**不得依赖平台提供的凭据**,否则两片同源 | | 4 | 重建 MK:`Sh2 + Sh3`(2-of-3 已满足)(U3 本地) | 设备 | 平台 + 第三方各自单独都无效 | | 5 | **重新分片**:生成 Sh1'→U3、Sh2'→B、Sh3'→T3(U3→B/T3) | 设备/B/T3 | 旧分片作废(靠 B/T3 侧删除实现) | | 6 | **轮换 MK**(安全增强):生成 MK',重新 `wrap(DEK_data, MK')`(U3→A) | A/设备 | 🔴 旧分片即使被攻击者复制也失效(它只能重建已作废的 MK) | | 7 | (按损失面决定)**轮换 DEK_data + 全量重加密** | A/链下 | 仅在"设备可能被解锁"时执行;代价为全量重加密 | | 8 | 恢复后校验:抽样拉取 → 校验 content_hash → 试解密 → 试查询(U3) | 设备 | 端到端验证,避免"看起来恢复了但数据不可用" | | 9 | 审计:完整恢复轨迹(授权人、时间、第三方验证凭据)写只追加日志 | LOG | 不可抵赖 | **数据落点汇总**:分片三分位(设备/B/T3)|MK 只在设备内存|MK' 包裹体 → **A**|恢复审计 → **LOG** **失败模式与处置** | 失败 | 后果 | 处置 | |---|---|---| | 用户同时丢分片 + T3 不可用 | 🔴 **数据永久丢失**(架构固有代价) | 注册时强提示;可选升 3-of-5 增加冗余(⚠️ 但串谋门槛随之下降 ⇒ 真取舍) | | 攻击者同时控制平台 + T3(串谋) | 🔴 **全部用户 MK 可重建 ⇒ A 层数据全解** | 见下方"残余风险",这是架构最高风险点 | | 恢复流程被社工(冒充用户) | 攻击者拿到分片 | 强认证 + 冷却期 + 恢复后通知(邮件/短信)+ 恢复期禁止批量导出 | | T3 托管商倒闭 | 无法取 Sh3 | 分片本身可迁移(只是数据,无密码学障碍);需在 SLA 中约定数据可导出 | | 设备被找到但已被解锁过 | 攻击者已复制 Sh1 + 可能已 dump MK | 走步骤 7(轮换 MK + DEK_data 全量重加密)——**只轮换 MK 不够** | | 只轮换 MK 不轮换 DEK_data | 若攻击者已持有 MK,轮换 MK 无效 | 判据:**攻击者是否曾获得过完整 MK** ⇒ 是 ⇒ 必须连 DEK_data 一起换 | **🔴 本场景最重要的判断:2-of-3 的安全性上限 = "平台与第三方不串谋"这条假设** - 门限分片的数学保证只针对**少于 2 片**的情况;2 片到手即可重建,与"谁持有"无关。 - ⇒ 因此 **`平台 + T3` 在合法程序下协同即可解开全部用户数据**(场景 5 会用到这一点)。 - ⇒ 这不是设计缺陷,但**必须如实写进安全声明**,⛔ 不能对外宣称"任何人都无法解密"。 - 缓解手段(三层叠加,缺一层则风险显著上升): 1. **T3 必须为独立法人 / 独立管理域**(最好独立司法辖区)——同一实控人手中 ⇒ 等同单点; 2. **T3 的片用 T3 独立 KEK 保护** ⇒ 平台侧即使拿到 T3 的存储也无用; 3. **取 Sh2 / Sh3 均需多角色授权 + 全量审计 + 异常告警**(单次请求量、非工作时间、跨租户批量)。 - **若"连串谋也必须不可解"是硬需求** ⇒ 唯一办法是让平台**不参与**分片,即 2-of-3 改为"用户设备片 + 用户密码派生片 + T3 片"。代价:平台彻底无恢复能力,用户丢设备 + 忘密码 ⇒ 永久丢失(回到 V3 硬代价)。⇒ **真取舍,收进 §5**。 --- ### 2.4 场景 4 · 用户行使删除权(PIPL 47 条)—— 链上不可删 vs 删除义务 **参与方**:U · 平台合规 · A · B · 桥 · OSS · LOG **核心拆解(本文的关键推演)**:删除义务要落在"四类真实副本"上,而不是落在一个"删除按钮"上。 | 副本类别 | 内容 | 能否真删 | 处置 | |---|---|---|---| | ① 数据本体(密文 blob) | OSS 中的密文 | ✅ 能 | 调 API **彻底删除**(含多版本/软删除/回收站),并回读验证 | | ② 密钥材料 | `wrap(DEK_data, MK)`、DEK_data 副本 | ✅ 能 | 删除包裹体 ⇒ **加密粉碎(crypto-shredding)**作为加固(⛔ 主文档负面清单:不可作为唯一手段) | | ③ 索引 | A 层 `index_token` 条目 | ⚠️ 部分 | 见下方"链上处理" | | ④ 身份映射 | 桥表 `anon_id ↔ user_id` | ✅ 能 | 删除映射 ⇒ 旧链上记录变为"无主哈希" | | ⑤ 备份 / 快照 | OSS 备份、B 层快照、LOG 备份 | ⚠️ 有窗口 | 备份保留期 ≤ 合规窗口;**宣称删除效力的最坏时延 = 备份保留期** | **时序步骤** | 步 | 动作(参与方) | 落层 | 该步的安全属性 | |---|---|---|---| | 1 | 提交删除请求(指定数据集 / 全账号)(U→平台合规) | B(工单审计) | 请求本身走 B 层审计,不落 A | | 2 | 定位全部引用:按 anon_id 枚举 A 层记录 + B 层 KV + 桥映射 + OSS blob(平台) | 桥→A/B/OSS | 🔴 这一步需要**桥的映射能力** ⇒ 双人授权 + 留痕 | | 3 | 删除本体:OSS 彻底删除(含版本/回收站) | 链下 | 回读验证(删除后拉取必须 404) | | 4 | 销毁密钥:删除 `wrap(DEK_data, MK)` + DEK_data 所有副本 | A/链下 | 即使 blob 因备份残留也不可解(加固,非主手段) | | 5 | A 层处理:链上记录**保留**,但断开关联 | A | 见下方"两处冲突" | | 6 | 桥表处理:删除 `anon_id ↔ user_id` 映射 | 桥 | 旧 anon_id 成为无法映射到任何现实身份的字符串 | | 7 | B 层处理:写**墓碑记录**(tombstone)+ 真删 value 密文 | B | 墓碑 = "曾存在且已删除"的不可篡改事实,**不含任何个人信息** | | 8 | 分片处理:若为全账号删除 ⇒ 删除 Sh2(B 层)+ 通知 T3 删除 Sh3 | B/T3 | ⚠️ 必须警告:删除后用户若再丢设备 ⇒ 永久无法恢复 | | 9 | 生成删除证明:`commit = HMAC(DK_hash, 删除范围描述 ‖ ts)`(平台→U) | — | 用户可验证"删除已执行",⛔ 证明本身不含数据内容 | | 10 | 审计锚定:删除事件写只追加日志 + 锚定 | LOG | 不可抵赖 | **🔴 冲突一:B 层也是链 ⇒ 链上不可删与删除权在 B 层同样成立** 主文档说"B 层 = 私有共识链上的加密 KV 金库"。但链的特性是**不可删除** ⇒ 若 value 密文直接落链,B 层将**同样无法履行删除义务**(这与 A 层的问题一模一样,此前只在 A 层讨论过)。 **推演出的三种解法(含取舍)** | 解法 | 做法 | 优点 | 缺点 | |---|---|---|---| | **b1 状态裁剪 + 历史归档** | 链上语义只保证"最新状态";状态库支持删除;老区块靠"密文 + 销毁 DEK"变成不可解 | 改动最小;保留链式结构 | ⚠️ "不可解" ≠ "已删除"(PIPL 要求删除,不是加密丢弃);老区块仍是永久密文 | | **b2 链上只存锚 + 链下存密文**(本文推荐) | 链上存 `key_token → {value_hash, version, DEK_id, tombstone}`;value 密文本体存链下受控加密存储 | ✅ 删除权真满足(真删链下);链条不可篡改语义保留(墓碑也是不可篡改的事实) | ⚠️ B 层不再是"纯 KV 链"(value 在链下),与 v1.1 需求表述有落差;需处理备份中的影子副本 | | **b3 可裁剪历史的许可链** | 定期状态快照后裁剪旧区块 | 能满足删除 | 🔴 削弱"历史不可篡改"的可验证性(历史没了)⇒ B 层不可篡改性只能保证"自上次 checkpoint 以来" | **我的建议(须拍板后回填主文档)**:采用 **b2 变体** —— > B 层链上 = `key_token → {value_hash, version, DEK_id, status}`,其中 `status ∈ {active, tombstone}`;value 密文在链下受控加密存储;删除 = 链上写 tombstone + 链下真删密文 + 销毁 DEK。 > ✅ 删除权满足(真删)+ 不可篡改语义保留(墓碑不可撤)+ **删除可证明**(墓碑是公开可验证的"已删"事实,不含内容)。 > ⚠️ 代价:B 层形态从"纯 KV 链"变为"KV 索引链 + 链下密文库";必须处理备份/快照中的影子副本(保留期 ≤ 合规窗口)。 **🔴 冲突二:内容哈希的"公开可验证" vs "删除后不可枚举关联"** - A 层链上存 `content_hash` ⇒ 若明文集合可枚举(证件号、已知文件、公开文档),攻击者**枚举比对哈希**即可反查"某人是否上传过 X" ⇒ 删除后依然可关联。 - 但加盐哈希(`HMAC(DK_hash, content)`)会**摧毁跨用户去重与第三方独立验证能力**(同内容在不同用户下产生不同哈希)。 - ⇒ **真取舍**,两条路各有优劣: - **全局哈希**:保留公开可验证 + 去重;代价是存在枚举关联风险; - **加盐哈希**:删除后真正不可关联;代价是失去第三方独立验证(须降级为"凭平台签发的凭证号 + 可吊销")。 **失败模式与处置** | 失败 | 后果 | 处置 | |---|---|---| | OSS 开了版本化/软删除 | "删了"其实只剩标记 | 必须调用彻底删除 API 并**回读验证 404** | | 备份/快照仍含密文 | 删除效力存在窗口 | 备份保留期 ≤ 合规窗口;最坏时延 = 保留期,须在用户协议中写明 | | 用户要求删"链上哈希" | ⛔ 技术上不可行 | 提前在协议写明"链上仅存匿名化哈希、不含个人信息"(⚠️ 合规口径 ⇒ §5) | | 只删某条记录 | 部分删除 | 逐条走 3–6 步;不得因"只删一条"而跳过密钥销毁 | | 全账号删除后用户又丢设备 | 永久无法恢复 | 删除确认页**显式警告** + 二次确认 | | 缓存/CDN 残留密文 | 密文可被再次下载 | 短期签名 URL + 防盗链;⚠️ 密文不可解 ⇒ 风险等级中等 | **结论/遗留**:删除权的技术实现是**可以做到的**,但成立条件有两个**前置定性**(⛔ 均属合规口径 ⇒ §5 待拍板):① 链上"匿名化哈希 + 去映射 anon_id"是否构成 PIPL 意义上的"非个人信息";② 用户协议中"链上不可删"的告知是否足以豁免。 --- ### 2.5 场景 5 · 平台受司法/监管配合请求 —— B 层可解 vs A 层不可解的边界 **参与方**:司法机关 · 平台合规/法务 · ADM · B · A · 桥 · LOG **边界表(能配合什么 / 不能配合什么)** | 请求内容 | 平台能否配合 | 依据 | 落层 | |---|---|---|---| | 用户实名信息(姓名/证件号) | ✅ 能 | B 层平台可解(授权下) | B | | 联系方式(手机/邮箱) | ✅ 能 | 同上 | B | | 登录与风控日志(时间/IP/设备) | ✅ 能 | 同上(⚠️ IP 亦属个人信息,仅按法定范围提供) | B | | 账号 ↔ 匿名 ID 的映射 | ✅ 能 | **桥表存在的目的之一**;需双人授权 + 合法性审查 | 桥 | | 链上交易流水(时间/哈希/token 结构) | ✅ 能(且本已公开) | 公开数据 | A | | 支付信息 | ⚠️ 只能给 Token | Token 本身无意义,须向支付网关另行调取 | B | | **用户数据本体明文(文件/内容)** | ❌ **不能** | 平台只有 MK 的 1 片,无 DEK_data | A | | **用户私钥 / 助记词** | ❌ **不能** | 从不出设备 | 设备 | | **批量解密全部用户** | ❌ **不能(架构级不存在此接口)** | 🔴 技术上**不提供**批量解密能力 ⇒ 这是设计上的合规保障 | — | | 平台 + T3 在合法程序下协同重建指定用户 MK | ⚠️ **理论上可** | 2 片即可重建 ⇒ **必须如实告知这一事实** | B/T3 | **时序步骤(配合流程)** | 步 | 动作(参与方) | 落层 | 该步的安全属性 | |---|---|---|---| | 1 | 受理法律文书 → 法务审查(主体、范围、合法性、案号)(合规) | — | ⛔ 技术层不得自行判断合法性,必须法务前置 | | 2 | **双人授权**:两名授权人独立签署导出审批(ADM) | B(+LOG) | 防单人滥用;授权链不可抵赖 | | 3 | 在受控环境执行范围内查询(TEE 隔离区,若有)(ADM→B) | B | 只输出请求范围内的字段;输出受限(行数上限、字段白名单) | | 4 | 导出留痕:对导出内容计算哈希并登记(ADM→LOG) | LOG | 可证明"交付了什么、多少条、何时" | | 5 | 通知用户(若法律允许 / 有约定) | — | 透明性 | | 6 | 事后审计:异常检测(单次请求量、非工作时间、跨租户批量)(审计) | LOG | 内部人滥用是主要风险面 | **失败模式与处置** | 失败 | 后果 | 处置 | |---|---|---| | 请求内容超出平台技术能力(要 A 层明文) | 无法满足 | 书面回复"技术上不可行"并说明密钥架构(⚠️ **是否构成拒不配合责任 ⇒ 法律定性 ⇒ §5 待拍板**) | | 内部人滥用配合通道 | 数据泄露 | 双人 + 范围限制 + 行数上限 + 告警 + 权限分离(申请人与执行人分离) | | 收到"解密全部用户"的泛化请求 | 架构不支持 | 技术层**不存在**此接口;须由法务界定可执行范围 | | 请求方要求"静默配合" | 审计与通知被绕过 | ⛔ 不允许绕过审计;"静默"只能体现在"不通知用户",⛔ 不能体现在"不记录" | **结论/遗留(本场景最重要的坦白)**:**"平台不可解"在本架构中准确表述是"平台单方不可解"**。司法程序下平台 + T3 协同是**可解**的;若某类数据连这一点都不能接受,唯一办法是让平台完全退出分片(§2.3 的真取舍)。⇒ 这条必须写进对外的安全声明与用户协议,⛔ 不能含糊。 --- ### 2.6 场景 6 · B 层单节点宕机 / 节点被攻破 **参与方**:B 层节点 N1..N4(PBFT 类,N=3f+1,f=1)· 运维 · KMS · LOG #### 6a · 单节点宕机(崩溃容错) | 步 | 动作 | 落层 | 安全属性 | |---|---|---|---| | 1 | 心跳超时检测 | B | 3 个节点仍在 quorum(N=4 ⇒ quorum=2f+1=3)⇒ **可用性不降** | | 2 | 剔除节点,共识继续 | B | 视图切换;已提交数据不丢(其余节点有副本) | | 3 | 节点恢复 → 从快照 + 区块追赶 | B | 必须**校验状态根**(防被喂假状态) | | 4 | 重新准入(需授权) | B | 新/恢复节点须授权准入(判据 12) | **失败模式**:同时宕 2 个节点(N=4)⇒ 只剩 2 个 < quorum ⇒ **停止出块**,但**不产生错误数据**——这是 BFT"安全性优先于活跃性"的正常行为。处置:只读降级 + 告警 + 尽快恢复(⛔ 不得为了"保持写入"而降 quorum,那正是"悄悄削共识假设")。 **部署建议**:至少 4 节点(容 1 故障),推荐 7 节点(容 2 故障);**跨机架/跨可用区**部署;⚠️ 全部节点在同一云账号 ⇒ 账号失陷 = 全网失陷(与项目"跨云为目标生产形态"的基调一致)。 #### 6b · 单节点被攻破(拜占庭容错) **攻击者拿到 1 个节点的完全控制 + 该节点磁盘(含全量状态与历史)。** | 攻击者能做什么 | 后果 | |---|---| | 读取全部 `key_token` 与 value 密文 | 只有密文 ⇒ 无明文泄露;但**获得完整的访问模式与改查分布** | | 读取该节点上的 Sh2 分片(封装态) | ⚠️ 需 KMS 凭据解封;且**只有 1 片 ⇒ 信息论上不足以重建 MK** | | 发起恶意提案 | 被其余诚实节点拒绝(f=1 在容错范围内) | | 选择性拒绝服务 | liveness 攻击 ⇒ 超时 + 视图切换 + 审计告警 | | 攻击者**不能**做什么(关键安全属性) | 原因 | |---|---| | ❌ 解密 B 层 value | 派生密钥在 KMS/HSM,节点只有密文 | | ❌ 重建任何用户的 MK | 只有 1 片 ⇒ 少于门限的片数**不含任何信息** | | ❌ 篡改历史 | 其余节点拒绝 ⇒ 篡改可检测 | | ❌ 推导 A 层数据 | A 层用 `DEK_data`(用户侧密钥),B 层从未持有 | **🔴 但必须点明的组合风险**:**若攻击者同时攻破 B 层节点 + T3 ⇒ 2 片到手 ⇒ 全部用户 MK 可重建 ⇒ A 层数据全解。** > 这比桥表泄露更危险:桥表泄露泄露**身份**,双片串谋泄露**数据明文**。 > 缓解三层:① T3 片用 T3 独立 KEK 保护;② Sh2 在 B 层**必须封装存放**(拿到节点磁盘 ≠ 拿到可用分片);③ **分片的解封只在 TEE 内进行,且需多角色授权**(L3 + L4 组合)——即"平台持有 Sh2 ≠ 平台可随意使用 Sh2"。 **处置时序**:检测(共识行为异常/审计告警)→ 隔离(剔除)→ **凭据轮换**(该节点所有凭据)→ 评估是否需轮换数据密钥(⚡ 判据:若该节点运行时可解 `DEK_kv` ⇒ 必须轮换 KEK_t + 重加密 B 层 value;若只拿到 Sh2 ⇒ 无需轮换用户密钥)→ 取证(链上记录攻击者全部提案)→ 恢复(从快照重建,**不信任节点本地数据**) **失败模式** | 失败 | 后果 | 处置 | |---|---|---| | 控制 f+1 个节点(N=4 时控制 2 个) | **可破坏安全性**(可写入错误数据,但 value 仍不可解) | 跨管理域部署 + 准入证书 + 监控(⚠️ 4 节点全在同一台机器 ⇒ 容错形同虚设) | | 快照/备份被投毒 | 恢复时喂假状态 | 恢复必须校验状态根 + **多节点交叉校验** | | 全部节点丢失(灾难) | 服务中断 | 从备份恢复;⚠️ **备份是信任的根** ⇒ 加密 + 分离保管 + **真跑一次恢复演练** | --- ### 2.7 场景 7 · 管理员越权尝试解密 A 层数据(应失败 + 留痕) **前提**:攻击者拥有**平台全部权限**(DBA + KMS 管理员 + 链节点管理员 + 桥管理员),但**没有用户设备**。 **攻击路径矩阵与结果** | # | 路径 | 结果 | |---|---|---| | 1 | 直读 A 层链上数据 | ❌ **失败**——只有密文、匿名 ID、哈希、token | | 2 | 从 OSS 下 blob,用 KMS 的 KEK 解密 | ❌ **失败**——`DEK_data` 由**用户 MK** 包裹,平台 KEK 对其无效(🔴 前提:绝不用平台 KEK 加密 A 层数据) | | 3 | 从 B 层取 Sh2 尝试重建 MK | ❌ **失败**——只有 1 片,Shamir 信息论上不可重建 | | 4 | 伪造用户身份走恢复流程取 Sh3 | ❌ **失败**——T3 独立验证,不依赖平台提供的凭据 | | 5 | 攻破 T3(平台运营方实施) | ⚠️ **成功**——2 片到手 ⇒ 这是架构残余风险,必须承认(§2.3 / §2.6b) | | 6 | 走 TEE 隔离区 | ⚪ 不算"越权成功"——只能在授权 + 范围内运行,输出受限、全程留痕(**受控通道**,而非绕过) | | 7 | 🔴 **改代码 / 向下发恶意客户端 JS 窃取 MK** | ⚠️ **这才是最现实的攻击**——平台控制前端下发通道 ⇒ 可窃取 MK ⇒ 直接击穿"平台不可解"承诺 | **关于路径 7(必须写进安全声明的软肋)** > **对"平台不可信"模型,客户端加密是唯一防线,而前端投毒可击穿它。** 缓解手段(按强度递增): 1. CSP + SRI(子资源完整性)+ 禁止动态注入脚本; 2. **可验证构建**:发布物带签名,构建哈希登记到**只追加透明日志**(用户可校验"我运行的代码 = 已登记的代码",类比 Certificate Transparency); 3. 原生客户端 + 代码签名 + 系统级校验; 4. 开放客户端源码(⚠️ 商业权衡,需拍板); 5. 最彻底:本机应用 + **可复现构建**。 ⚠️ **诚实结论**:前端投毒属于**不可完全防住**的一类攻击,只能降低概率 + 提高可检测性。这是所有"零知识"平台共同的软肋,⛔ 不能对外声称"绝对不可解"。 **审计留痕设计(三平面分离)** | 平面 | 内容 | 存储 | 权限 | 保留 | |---|---|---|---|---| | 业务日志 | 业务操作 | 常规存储 | 运维可读 | 常规 | | **密钥使用日志** | 谁、何时、对哪个 DEK/分片、用途、授权链 | 独立存储 | 仅密钥管理员 + 审计 | 长 | | **管理操作日志** | 授权审批、恢复操作、桥表访问 | 独立存储 | 仅审计 | 长 | **关键要求**: - 🔴 **审计日志必须只追加(Merkle 日志)+ 定期锚定** ⇒ 管理员无法悄悄删; - ⚠️ 但若管理员同时控制日志存储 + 锚定通道 ⇒ 可停掉锚定 ⇒ **必须有外部监督者**(判据 7 同款:没人验证的透明日志 = 没有); - **异常检测**:解密量突增、非工作时间、跨租户批量、同一管理员重复失败("尝试重建"信号)。 **判据 2 的可执行测试(本轮细化)** | 测试 | 期望 | |---|---| | T1 用 A 层全量数据 + 全部 KEK 尝试解密 | **0 条成功** | | T2 用 B 层全量分片 + 全部权限尝试重建任一用户 MK | **失败**(判据 14) | | T3 全库扫描"能解 A 层"的密钥路径 | **0 命中** | | T4 越权/超范围查询 | **告警必触发** | | T5 前端下发通道注入检测(可验证构建比对) | **比对不一致必告警**(本轮新增,见 §4) | --- ### 2.8 八场景横向对照(一页速查) | 场景 | 平台可见明文 | 平台不可见 | 主要风险 | 是否已可落地 | |---|---|---|---|---| | 1 注册与首传 | 实名、联系方式 | 数据本体、MK | 两步写不一致(孤儿/悬空) | ✅ 可(需补对账) | | 2 跨设备查询 | 无(token 摘要除外) | 查询条件、数据本体 | 访问模式泄露;平台代理查询的选择 | ✅ 可 | | 3 门限恢复 | 无 | MK、Sh1 | **平台+T3 串谋** | ⚠️ 待拍板(分片参数) | | 4 删除权 | 无 | — | B 层链上删除;哈希可枚举关联 | ⚠️ 待拍板(B 层形态 + 哈希策略) | | 5 司法配合 | 实名、日志、映射 | 数据本体、私钥 | 单方 vs 合谋的表述 | ⚠️ 待拍板(合规口径) | | 6 节点故障/被破 | 无 | 分片、value 明文 | 双片串谋;quorum 部署 | ✅ 可(需部署纪律) | | 7 管理员越权 | 无 | 数据本体 | **前端投毒**;审计可被停锚 | ⚠️ 待拍板(客户端策略) | | 8 DAO 协作网络 | 实名、成员表(V0) | 数据本体、私钥 | **备案主体缺位**;贡献值无法链上度量 | ✅ 可(V0 零新增基础设施) | --- ### 2.9 场景 8 · DAO 协作网络(能力共创 / 能力共享 / 能力使用分发) > **场景来源**:用户 2026-09-19 定义「A 网络的一个重要场景是 DAO」,并给出三条拍板 —— ① **价值凭证现在不做、预留扩展空间**(本项目是**面向全球的开源项目**)② **平台只做互联和项目协作**:能力共创、能力共享、能力使用分发 ③ **预留扩展空间,先用最低成本的方式生成密钥与核验**。 **参与方**:`U`(OPC 个体)· `平台`(互联层 + 协作层)· `A` · `B` · `桥` · `目录`(能力目录)· `LOG` #### 2.9.1 前置澄清(两条,缺一则本场景不成立) 1. 🔴 **DAO 自己无法完成区块链信息服务备案** —— 备案第 8 条要求真实身份认证(组织机构代码 / 身份证号),而 DAO 既非法人、通常也未登记为合伙。律所口径:「未注册为法人、合伙企业的 DAO……**无法合规从事区块链信息服务**」。⇒ **平台必须是已登记主体并承担备案与实名,DAO 只作为平台上的组织形态存在**。 2. ⛔ **平台范围收窄(本轮拍板)** —— 平台只做两件事:**① 互联**(身份、寻址、桥、网络)**② 项目协作**(能力注册 / 匹配 / 调用授权 / 分发路由 / 贡献记录)。⛔ **不做**:资金、代币、法律主体代持、内容运营、撮合定价。 #### 2.9.2 时序步骤 | 步 | 动作(参与方) | 落层 | 该步的安全属性 | |---|---|---|---| | 1 | **能力注册**:提交能力描述 → 生成 `cap_id`(内容寻址)+ `meta_hash`(U→平台→A) | A | ✅ 能力可公开发现、不可篡改;⛔ 价格与结算方式**不上链**(避免落入"定价服务"定性) | | 2 | **协作组织创建**:定义成员集合 → 计算**成员资格树根**(Merkle root)→ 上链 `root + 治理规则哈希`(平台→A) | A | ✅ 只公开 root ⇒ **成员名单不公开**(最低成本的成员隐私) | | 3 | **成员加入**:生成身份密钥(**V0 最低成本,见 §3.6**)→ 提交公钥 → 平台签发**可验证凭据(VC)** → 入树、链上只更新 root(U↔平台) | 设备/B/A | 私钥不出设备;✅ 成员表加密存 B,链上只有 root | | 4 | **项目立项**:任一提案 → 提案内容哈希 + 截止块高上链(U→A) | A | ✅ 提案可验证、不可改 | | 5 | **治理表决**:用身份密钥**签名投票**;提交时附 **Merkle 包含证明**证明"我在成员集合内"(U→A) | A | ✅ 投票权可验证、**身份不公开**;⚠️ V0 不隐藏"投票权大小"(V1 由 ZK 补) | | 6 | **贡献记录**:成果内容哈希上链 + 相关成员**签名确认**(谁认领 / 谁验收)(U→A) | A | ✅ 贡献可追溯、不可抵赖;⚠️ **不产生"贡献值多少"**(见 2.9.4 硬伤 3) | | 7 | **分账登记**:**规则哈希**上链(比例、里程碑判定条件)+ 成员签名确认;**资金由付款方链下直接付给各方**(U→A,资金**不经平台**) | A / 链下 | 🔴 规则可验证但**钱不走链、不过平台**(§2.9.1 范围收窄 + 237 口径) | | 8 | **能力分发(调用)**:查目录 → 请求调用 → 能力方签发**调用凭据**(V0 = 签名 token,含 scope/过期/被调用方 `anon_id`)→ 平台**只做路由与分发** | A / 平台 | ✅ 平台不经手内容明文与资金;凭据可离线验证、短 TTL 可即时撤销 | | 9 | **退出 / 解散**:退出 ⇒ 链上 root 更新 + 桥映射删除 + B 层个人信息删除(PIPL 47);解散 ⇒ 链上写"已解散"墓碑,规则哈希保留 | A/B/桥 | ⚠️ 链上匿名记录保留(账本即资产);🔴 **技术解散 ≠ 义务终止**(质保 / IP / PIPL / 税务) | | 10 | **审计**:全部治理与协作事件写只追加日志 + 锚定(LOG) | LOG | 不可抵赖;⚠️ 需独立锚定方(判据 19) | #### 2.9.3 数据落点汇总 | 内容 | 落层 | |---|---| | 能力元数据哈希 / 成员资格树 root / 提案 / 投票承诺 / 贡献哈希 / 分账**规则**哈希 / 解散墓碑 | **A 层** | | 成员实名 / 联系方式 / 对公主体 / 成员表 / 调用凭据索引 / 退出与删除义务 | **B 层** | | `anon_id ↔ user_id` 映射 | **桥** | | ⛔ 代币 / 铸币权 / 余额 / 分红 / 抵押兑换 / 对外签约主体 / 成员真实身份 | **不上链** | #### 2.9.4 五处硬伤(对"OPC + DAO"叙事的批判,必须如实写明) 1. **代币抵押 + 自动分账 = 银发〔2021〕237 号红线** —— 律所口径:DAO「因其作为基础建设的代币工具的广泛使用,**目前在中国尚无合法的立足之处**」。⇒ 本轮拍板:**现在不做**。 2. **资金腿不在链上** —— OPC 收入来自法币客户;"自动分账"要资金上链 ⇒ 法币通道被禁、稳定币被禁 ⇒ **境内不可实现**,只能"链上记账 + 链下付款"(步 7 即此形态)。 3. **贡献度不可链上验证** —— 合约能执行"按约定比例分",算不出"谁的贡献是多少"。⇒ 链只解决**规则不可篡改**,不解决**输入数据真实性**(garbage in, garbage out)。 4. **法律主体缺位** —— 无主体 ⇒ 不能签约 / 收费 / 开票 / 应诉;实务上**高概率被认定合伙 ⇒ 无限连带责任**(《合伙企业法》第 2 条);**成员退出后仍可能因链上记录被追责**;**税盾缺失**。⇒ "项目结束即可解散"只解散技术实体,义务不终止。 5. **治理现实被美化** —— 一币一票 = 财阀制(与"贡献可验证"的取向相反);投票率长期个位数;"临时组 DAO"冷启动无信用。⇒ 需设**法定人数(quorum)** + 委托投票,⛔ 不得用"沉默即同意"。 #### 2.9.5 失败模式与处置 | 失败 | 后果 | 处置 | |---|---|---| | 成员身份私钥丢失 | 无法投票 / 签名 / 被授权 | 用 §3.6 的设备密钥 + Passkey 生物解锁;⛔ **不得用数据侧 MK 分片替代**(职责分离) | | 成员表泄露(平台侧) | 匿名性局部失效 | 成员表加密存 B 层 + 访问双人授权;V1 迁 ZK 后**平台也不再需要成员表** | | 投票率过低 | 治理形同虚设 | 法定人数 + 委托投票 + 未达标即"未通过"(⛔ 无"沉默即同意") | | 能力描述与实际交付不符 | 交付争议 | 链上只有哈希 ⇒ **争议靠线下 + 平台仲裁规则**,⛔ 链不解决 | | 被要求平台代收代付 / 代为分账 | 越出平台范围且触发 237 风险 | **直接拒绝**;平台只提供"规则与履约凭证登记" | | 项目解散后仍被追责 | 责任落回成员个人 | 协议中明确责任主体 = 成员个人或其登记主体;不承诺"解散即免责" | | 贡献记录因成员退出被删 | 账本失去意义 | 链上只留**匿名化**记录(去映射 anon_id)⇒ ⚠️ 定性须法律意见(§5 第 1 项) | #### 2.9.6 结论 **A 网络对 DAO 的定位 = 可验证的协作与能力分发账本;⛔ 不是自治的金融组织。** 本场景的全部价值在于"**跨 OPC 协作的信任与可验证性**",而**不需要**任何价值凭证 —— 这也正是"现在不做、预留扩展"可以成立的原因。 --- ## 3. 多用户逻辑推演 ### 3.1 多租户 key/DEK 隔离模型 **先给唯一的判据**(其余全由此推出): > **「平台是否需要解这条数据?」——需要 ⇒ 密钥由租户级 `KEK_t` 派生(平台侧,KMS 持有);不需要 ⇒ 密钥由用户级 `KEK_u` 派生(用户侧,平台不可计算)。** **分层模型** | 层 | 密钥 | 生成/持有 | 用途 | 平台可否计算 | |---|---|---|---|---| | **L0 根** | `MK`(32 B) | 用户设备 CSPRNG;Shamir 2-of-3 分片(设备 / B / T3) | 用户密钥树的根;包裹 DEK_data | ⛔ 不可(仅 1 片) | | **L1 租户** | `KEK_t` | KMS/HSM 持有;每租户一把 | 封装 B 层 value 的 DEK;封装用户分片 Sh2 | ✅ 可(KMS 内) | | **L2 用户** | `KEK_u = HKDF(MK, "kek-u", tenant_id, user_id)` | 用户侧派生 | 派生全部域密钥 | ⛔ 不可 | | **L3 域** | `DK_idx = HKDF(KEK_u,"dk-index")` | 用户侧派生(**不存储**) | 盲索引 token 的域密钥 | ⛔ 不可 | | L3 | `DK_kv_key = HKDF(KEK_u,"dk-kv-key")` | 用户侧派生 | B 层 KV 的 key_token(防节点看出同属一人) | ⛔ 不可 | | L3 | `DEK_kv(u, cls)` | 由 `KEK_t` 包裹的独立 DEK(按字段类:实名/联系方式/支付/风控) | B 层 value 加密(**平台授权下可解**) | ✅ 可(授权 + 审计) | | L3 | `DEK_data(u, ds)` | 用户侧生成;用 `MK` 包裹后存 A 层 | A 层数据本体加密 | ⛔ 不可 | | L3 | `DK_hash(u)`(可选) | 用户侧派生 | 加盐内容哈希(§2.4 冲突二) | ⛔ 不可 | | L3 | `DK_bridge` | 平台侧,独立存储(⛔ 不在 KMS 常规域) | 生成 `anon_id` | ✅ 可(双人授权) | | **L4 记录** | `rk = HKDF(DEK_data,"rec",rec_id,version)` | 派生,不存储 | 单条/单版本加密 | ⛔ 不可 | **⛔ 域分离硬约束**(主文档 §4.2 约束 3 的展开):每一次派生**必须带唯一 label**(`"dk-index"` / `"dk-kv-key"` / `"rec"` / …)+ 唯一 ID(tenant_id / user_id / rec_id / version)。**禁止任何密钥跨域复用** —— 攻破 key 空间不得推出 value 密钥。 **「每租户一 DEK」的判定:❌ 不是** | 候选 | 优点 | 缺点 | |---|---|---| | 每租户一把 DEK | 密钥数量最少、管理简单 | 🔴 一把被破 ⇒ 整租户全解(爆炸半径 = 整租户);无法按用户轮换;租户内用户间**可以互相解密**(越权) | | **租户 KEK(仅封装)+ 用户级密钥**(推荐) | 爆炸半径 = 单用户;可单用户轮换;用户间天然隔离 | 密钥对象数 ∝ 用户数(但见下方"KMS 对象数"的化解) | **🔴 一处必须澄清的成本误区**:有人担心"每用户密钥 ⇒ KMS 对象数爆炸"。实际上: - **MK 不进 KMS**(用户生成,平台只有分片); - 分片由**租户级 `KEK_t`** 封装 ⇒ **KMS 里的对象数 ∝ 租户数,不是用户数**; - `KEK_u`/域密钥是 **HKDF 派生**(不存储、不进 KMS); - `DEK_data` 用 MK 包裹后存 A 层 ⇒ **平台侧零 KMS 依赖**; - 只有 `DEK_kv`(B 层 value)需要平台可解 ⇒ 由 `KEK_t` 包裹(密文存普通加密存储,**只有 KEK_t 本身在 KMS**)。 - ⇒ **KMS 对象数 = 租户数**(如 1,000)—— 这是完全可运营的量级。✅ **租户隔离的第二个必要件:每租户独立 salt** - 盲索引域密钥已按用户区分,但仍需**每租户独立 salt** 参与 token 派生,否则同一标识(如邮箱)在**不同租户**下产生**相同 token** ⇒ 可跨租户判定"这两个账号是同一人"。 - 代价:**零存储增量**(token 长度不变),只多一次 HKDF。⇒ 无理由不做。 ### 3.2 并发写入:B 层私有链的共识与冲突处理 **结论先行**:**跨用户无冲突(密钥空间天然不相交);同 key 冲突必须走"乐观并发控制 + 版本号",⛔ 禁止 last-write-wins。** | 冲突类型 | 是否发生 | 机制 | |---|---|---| | 不同用户并发写 | ❌ 不冲突 | 域密钥不同 ⇒ `key_token` 空间不相交;共识负责**定序**,天然串行化 | | 同一用户不同 key 并发写 | ❌ 不冲突 | 同上 | | **同一 key 并发写**(同用户两设备改同一条) | ✅ 会 | **乐观并发控制(CAS)**:交易声明 `expected_version`,不匹配即拒绝;冲突返回客户端 rebase(类 git) | | **热点 key**(计数器 / 配额 / 全局配置) | ✅ 会 | 分片计数器 / CRDT 计数器 / 预分配号段(⚠️ 见下方 CRDT 判据) | | 跨 shard 原子事务 | ⚠️ 设计上应避免 | 两阶段提交代价高 ⇒ **把强不变量收敛到单 shard** | **⛔ 明确禁止的做法** - **last-write-wins 用于用户数据** ⇒ 静默丢数据(用户会认为"我明明改了"); - **CRDT 用于金额/配额等有不变量的数据** ⇒ CRDT 只在**可交换、可幂等**时才安全。判据:**这个操作交换后结果是否相同?** 集合类(标签、收藏)可用 OR-Set / LWW-Register;金额必须强一致。 **幂等与去重**:客户端重试必须带 `request_id`;A/B 两层链**天然按 txid 去重**,重复提交不会重复生效。 **最终性与体验的取舍(必须写进产品设计)** - 用户数据的写入**必须等共识确认**(⛔ 不做"乐观确认")——因为丢数据的代价远高于多等 1–2 秒; - ⇒ 写入延迟 = 共识延迟(秒级)⇒ 前端须用**异步确认模式**(提交后显示"处理中",确认后变"已保存"),而不是假装立刻成功。 **性能上限**:共识决定 TPS 上限(自研链要优化的正是这一点,主文档 §3.4.6);**热 key 会成为首个瓶颈** ⇒ 先分区、再考虑提高共识吞吐。 ### 3.3 跨用户数据共享/授权("平台不可解"前提下) **核心判断**:平台的零知识使得"平台代转授权"**不成立** ⇒ 授权必须发生在**密钥层**,而不是 ACL 层。 | 候选 | 做法 | 优点 | 缺点 | |---|---|---|---| | **A 数据集级密钥 + 逐接收者包裹**(本文推荐) | 共享数据集用独立 `DEK_g`;授权 = 用接收者公钥 `wrap(DEK_g, PK_B)`;平台只搬运密文包 | ✅ 平台零知识保持;粒度到数据集;撤销可做(换版本 + 重包裹);实现成熟 | 撤销需重加密受影响数据;大量接收者时 wrap 数量 ∝ 接收者数 | | B 代理重加密(PRE) | 平台代理把 A 的公钥密文转成 B 可解的密文,代理不看明文 | 数据所有者可离线 | ⚠️ 代理自身是信任点(需 PRE 方案的安全性证明);实现库少 | | C 属性基加密(ABE / KP-ABE) | 策略写在密文里,凭属性密钥解密 | 一对多共享天然、粒度好 | 🔴 撤销困难、密钥管理复杂、性能开销大、生产级实现少 ⇒ **当前成熟度不足以作主方案** | | D 平台代转(ACL 层) | 平台持密钥代解密再转给接收者 | 实现最简单 | ⛔ **破坏平台零知识**(平台必须持可用密钥) ⇒ 与架构前提矛盾,不采用 | **推荐形态(A 的工程细化)** - **共享数据集的 DEK 版本化**:`DEK_g_v1 → DEK_g_v2`; - **撤销一个成员** = 生成 `DEK_g_v2`、对**剩余成员**重新 wrap、存量数据**惰性重加密**(读时重加密 + 写时强制 v2); - **平台可见的部分**:授权图(谁授权了谁、某数据集有几个授权)⇒ ⚠️ **这本身是元数据泄露面**;缓解:授权记录放 B 层且 value 加密,key 为 `HMAC(DK_kv_key, receiver‖dataset)`,进一步可用**匿名授权槽位**(平台只见"数据集有 N 个授权",不见身份对应)。 - **⚠️ 不可逆性提醒**:授权一旦给出且数据已被 wrap,**已复制的明文无法收回**。撤销只影响未来访问,⛔ 不能让用户误以为"撤销 = 收回"。 - **平台零知识是否被削弱?** 不 —— 平台仍不可解。被削弱的是**用户之间的私密性**(B 能读 A 的数据),而这正是用户主动授权的。 ### 3.4 规模推演:10 / 1 万 / 100 万用户 #### 3.4.1 基准画像(先固定假设,否则量级不可比) | 参数 | 取值 | 说明 | |---|---|---| | `R` 记录数/用户/年 | **100** 条 | 轻量口径(结构化记录为主) | | `s` 平均记录明文 | **2 KB** | ⚠️ 若含媒体则按 50 KB 另算(见 3.4.4) | | `F` 每个记录的可查字段数 | **5** | 决定索引条目数 | | `m` 链上每条记录元数据 | **256 B** | 含 anon_id(32) + content_hash(32) + rec_id(16) + version(4) + token 列表(20) + blob_ptr(64) + ts(8) + 对齐 | | `e` 密文膨胀 | **1.05×** | AES-GCM + 封装 + 版本头 | | `V` 版本保留数 | **3** | 保留 3 个历史版本 | | `W` B 层写入放大 | **3 笔/记录** | KV 写 + 索引更新 + 审计锚 | #### 3.4.2 主表(含计算过程) | 项目 | 计算式 | 10 用户 | 1 万用户 | 100 万用户 | |---|---|---|---|---| | 记录数 | `N_u × R` | 1×10³ | 1×10⁶ | 1×10⁸ | | **盲索引条目** | `记录数 × F` | 5×10³ | 5×10⁶ | **5×10⁸** | | 截断位数 `b`(目标平均 3 行/查询) | `⌈log₂(条目数/3)⌉` | 11 bit | 21 bit | **28 bit** | | 索引存储 | `条目数 × (16 B 引用 + ⌈b/8⌉)` | 5×10³×18 B ≈ **90 KB** | 5×10⁶×19 B ≈ **95 MB** | 5×10⁸×20 B ≈ **10 GB** | | A 层链上元数据 | `记录数 × m` | 256 KB | 256 MB | **25.6 GB** | | 密文 blob(明文) | `记录数 × s` | 2 MB | 2 GB | 200 GB | | 密文 blob(密文) | `× e` | 2.1 MB | 2.1 GB | **210 GB** | | 含版本保留 | `× V` | 6.3 MB | 6.3 GB | 630 GB | | B 层 KV(实名等) | `N_u × 2.2 KB` | 22 KB | 22 MB | **2.2 GB** | | 用户分片存储 | `N_u × 200 B` | 2 KB | 2 MB | **200 MB** | | B 层写入笔数/年 | `记录数 × W` | 3×10³ | 3×10⁶ | **3×10⁸** | | 峰值写入 TPS | `笔数 × 10 ÷ (365 × 86400)` | 0.001 | 0.95 | **95** | | 峰值读 TPS(读:写=10:1) | `× 10` | 0.01 | 9.5 | **951** | | KMS 对象数 | `= 租户数`(非用户数) | 1 | 10 | 1,000 | **计算示例(100 万用户,逐步展开以便复核)** 1. 记录数 = 1,000,000 × 100 = **1×10⁸** 条/年; 2. 索引条目 = 1×10⁸ × 5 = **5×10⁸** 条; 3. 截断位数 = ⌈log₂(5×10⁸ / 3)⌉ = ⌈log₂(1.667×10⁸)⌉ = ⌈27.32⌉ = **28 bit**(占 4 B); 4. 索引存储 = 5×10⁸ × (16 B + 4 B) = 5×10⁸ × 20 B = **10 GB**; 5. 链上元数据 = 1×10⁸ × 256 B = 2.56×10¹⁰ B = **25.6 GB**; 6. 密文 blob = 1×10⁸ × 2 KB = 2×10¹¹ B = 200 GB;×1.05 = **210 GB**;×3 版本 = **630 GB**; 7. B 层写入 = 1×10⁸ × 3 = 3×10⁸ 笔/年;峰值 = 3×10⁸ × 10 ÷ (365 × 86,400) = 3×10⁹ ÷ 3.1536×10⁷ ≈ **95 TPS**。 > ⚠️ **v1.3 更正(本轮核算发现)**:本行原为 `笔数 × 10 / 86400`,且 1 万 / 100 万两格按「×10」递推(3.5 / 347)——**两处都不对**:`笔数` 是**笔/年** ⇒ 除数须为 **365 × 86400 = 3.1536×10⁷**;且用户数 ×1000 ⇒ TPS 亦 ×1000。**正确值:100 万用户 ≈ 95 TPS(读 951 TPS)、10 用户 ≈ 0.001 TPS**。方向性结论(写可承载、读不可穿共识层)不变,原数值偏大 **3.65×**。 #### 3.4.3 三条从量级里读出来的判断 1. **截断位数必须随总量对数增长**:`b = ⌈log₂(N/3)⌉` ⇒ 每 ×10 数据量,`b` 只增加 **3.32 bit**(约 0.4 B/条目)。⇒ 这是**可运营的**,不是膨胀问题。**但前提是被索引字段基数足够高**——低基数字段无论截断多少位都无法控制返回行数(每桶天然超大)。这正是"⛔ 不给低熵字段建盲索引"的**第二重理由**(第一重是频率还原)。 2. **KMS 不是瓶颈,索引与审计才是**:KMS 对象数 ∝ 租户数(1,000 级);而**索引 10 GB 是查询热路径**(需内存/SSD + 分片),**审计日志是增速最快的项**——按每用户每月 20 次操作 × 500 B ≈ **10 KB/年/用户 ⇒ 100 万用户 = 10 GB/年**,且**只增不减**(判据:审计保留策略必须定)。 3. **写入可承载,读不可直打共识层**:峰值写 95 TPS 落在私有共识链(PBFT 类 1,000–3,000 TPS 口径)能力内;但**读 ≈ 951 TPS** 已抵到该口径**下沿** ⇒ 查询路径**必须走只读副本 + 索引层缓存**,不得穿过共识。 #### 3.4.4 含媒体内容的口径(另一条曲线) 若 `s = 50 KB`(含图片/短视频封面等): | 用户数 | 明文 | 密文(×1.05) | 含 3 版本 | |---|---|---|---| | 10 | 50 MB | 52.5 MB | 158 MB | | 1 万 | 50 GB | 52.5 GB | 158 GB | | 100 万 | **5 TB** | 5.25 TB | **15.75 TB** | ⇒ 此时**对象存储成本与带宽成为主要成本项**,链上部分(元数据)不变。⚠️ 具体存储费用属"花钱"项 ⇒ §5。 #### 3.4.5 规模增长的非线性风险(必须提前设计) | 风险 | 何时出现 | 处置 | |---|---|---| | 索引条目超过单分片容量 | 千万级 → 亿级条目 | 按 `token` 前缀预分片;查询扇出控制 | | 链上状态库膨胀 | 亿级记录 | 状态快照 + 冷数据归档(⚠️ 与删除权/不可篡改性联动) | | 审计日志无界增长 | 从第一天起 | 定保留策略 + 分层(热/冷)+ 定期锚定后归档 | | 单 key 热区(计数器) | 十万级并发 | 分片计数器 | | 租户数量增长 | 1,000 → 10,000 | 租户 KEK 数量增长,KMS 扩容(仍是低量级) | ### 3.5 多用户下的元数据泄露面与缓解 #### 3.5.1 可见面清单(谁在什么位置能看到什么) | 泄露面 | 可见者 | 内容 | 危害 | |---|---|---|---| | **访问模式** | 链节点 / 平台 | `anon_id` + 何时查了哪个 token | 推断作息、活跃度、兴趣 | | **搜索模式** | 链节点 / 平台 | 相同 token 反复出现 | **同 token = 同值**(等值泄露);聚类"同一查询对象" | | **频率分布** | 链节点 | 各桶/各 token 的出现次数 | 低基数字段可**频率还原**明文类别 | | **规模与节奏** | 全网(A 层公开) | 每用户记录数、更新频率、增长曲线 | 商业情报 / 用户画像 | | **授权图** | 平台 | 谁授权给谁、共享数据集有几人 | 社交关系泄露 | | **时间关联** | 平台 | 注册时间与首次写入的间隔 | 可辅助识别真人/机器人 | | **分片请求日志** | 平台 | 谁在何时请求了 Sh2 | 可识别"正在恢复/换设备"的用户 | #### 3.5.2 攻击模型(四种必须防的) | 攻击 | 机制 | 关键前提 | |---|---|---| | **频率分析** | 若攻击者知道总体分布(如"18–25 岁占 30%"),可把 token 频率映射回明文类别 | 需外部辅助分布 ⇒ **低基数字段致命** | | **计数攻击** | 已知"有 N 个用户属于某组",从桶大小反推 | 需外部计数信息 | | **链接攻击** | 桥表泄露 ⇒ 全部 token 历史**立即实名化**,且不可撤回 | 需拿到桥表 | | **差分/注入探测** | 攻击者可控地插入一条已知记录,观察是否产生相同 token,反推他人值 | ✅ **截断 HMAC 部分缓解**:截断后新记录会与既有记录碰撞,无法精确反推(这正是"截断还能防试探性写入"的原理) | #### 3.5.3 缓解矩阵(本文新增三条,与主文档 §5.6 合并) | 手段 | 防哪个 | 代价 | |---|---|---| | 查询填充(定长响应 + 假记录填到固定行数) | 访问模式、规模泄露 | 带宽/存储开销 | | 批处理 + 延迟随机化(时间粒度粗化到窗口,如 5 min 桶) | 时间关联、搜索模式 | 查询延迟上升 | | 门限解密策略(查询解密需 N-of-M 授权) | 内鬼批量抓取 | 协作成本、延迟 | | 输出过滤(单次返回行数硬上限) | 批量抓取 | 大结果集需分页(⚠️ 分页本身又泄露查询次数 ⇒ 需合并计费/配额) | | 索引槽位混淆(每条记录建固定 K 个槽,部分为随机假槽) | 字段数与真实基数 | 索引膨胀 K 倍(K=2 即 +100%) | | **匿名 ID 轮换**(每会话/每周期换 `DK_idx`) | 长期访问模式关联 | ⚠️ **索引需重建** ⇒ 仅在"轮换周期 ≥ 数据更新周期"时可行 ⇒ 高风险场景才做 | | **查询配额 + 行为基线告警** | 慢速批量抓取 | 需运维投入 | | 只读副本隔离(读流量不经过共识节点) | 节点侧访问模式聚合 | 副本一致性窗口 | #### 3.5.4 诚实的结论 > **统计攻击无法完全消除**,只能压到"攻击者需要**外部辅助信息 + 大量观测**才成立"的水平。 > ⇒ 这条是验收判据 10(元数据泄露已评估)的落点,也是"**号称加密但被流量分析打穿**"的分水岭。 > ⇒ ⛔ 因此对外表述**不能用**"加密后无法分析",准确表述是"**内容不可解,模式被最小化**"。 ### 3.6 能力层:密钥生成与核验的最低成本实现(v1.1 新增 · 依据用户拍板) > 用户拍板:「**预留扩展空间,先用最低成本的方式生成密钥与核验**」。⇒ 本节按"**V0 零新增基础设施 → V1 只留接口**"两段写。 #### 3.6.1 V0 · 最低成本(零额外基础设施,全部浏览器原生能力) | 用途 | 最低成本做法 | 成本 | 安全属性 | |---|---|---|---| | **身份密钥生成** | 设备 **WebCrypto**(Ed25519 / P-256,`extractable: false`)或 **Passkey / WebAuthn**(私钥进设备安全芯片) | **0**(浏览器原生,无服务器组件) | 私钥不出设备;Passkey 另得生物识别解锁与跨设备同步 | | **成员资格核验** | **Merkle 包含证明**(成员集合 root 上链,成员只提交 path) | **0**(一次哈希链计算) | 证明"我在集合内"而**不公开成员表**;⚠️ 不隐藏"我参与了"这一事实 | | **投票 / 贡献确认** | **Ed25519 签名** `sign(vote‖attestation, 身份私钥)` | **0** | 不可抵赖;可离线签、可批量验 | | **治理规则完整性** | 规则文档哈希上链(版本化) | **0** | 规则不可篡改、可追溯变更 | | **能力调用授权** | 能力方签发**签名 token**(scope + 过期 + 被调用方 `anon_id`) | **0** | 可离线验证;短 TTL ⇒ 可即时撤销 | | **密钥恢复(轻量)** | 设备密钥 + 平台签发的**恢复凭据**(需实名 + 二次认证 + 冷却期) | 0(复用 §2.2 认证链路) | 不引入新组件;⚠️ 平台可协助恢复 ⇒ 属"受限信任",须审计 | **🔴 V0 明确不做**:ZK 证明 · TEE · 门限签名 · 链上代币 · 链上余额 · 链上定价。 **🔴 V0 全部为"证明后端可替换"设计**:接口按 `prove(claim) → proof` / `verify(proof, claim) → bool` 抽象,V1 只换实现,⛔ 不动上层调用方。 #### 3.6.2 V1 · 预留扩展点(现在只留接口,⛔ 不实现、不排期) | 扩展点 | 升级方向 | 触发条件(⛔ 不预设时间) | |---|---|---| | 匿名投票 | Merkle 包含证明 → **ZK 成员资格证明**(SP1 / RISC Zero / OpenVM,或 circom + Groth16) | 出现"连投票权大小也不能暴露"的需求 | | 节点盲验证 | 无 → **有效性证明**(主文档 §3.4.2 的死结解) | B 层节点数上升、需要不看数据即验状态 | | 价值凭证 | 无 → 可选**非转让、非兑换**的贡献积分 | ⚠️ 合规口径未定(§5 第 1 项),且**仅限境外部署形态** | | 身份密钥 | 设备密钥 → 门限签名 / 社交恢复 | 出现"身份密钥丢失"的量级问题 | #### 3.6.3 三条设计纪律 1. 🔴 **身份密钥与数据密钥职责分离** —— 身份密钥(签名 / 投票 / 授权)在设备上,**不参与 A 层数据的加解密**;数据侧仍走 `MK` + Shamir 2-of-3(§3.1)。⛔ 不得用同一把密钥既签名又解密。 2. 🔴 **扩展点是"接口预留",不是"功能占位"** —— V0 走纯签名 + Merkle;代码里⛔ 不得出现"等 ZK 上线再说"的空实现、半成品开关或死代码分支(否则等于埋一条假路径)。 3. 🔴 **面向全球开源 ⇒ 分层合规**(本轮拍板的关键推论)—— 开源主仓**默认不含任何价值凭证能力**;代币 / 积分类扩展**只能作为独立可选插件存在,且仅用于境外部署形态**,⛔ 不进主仓默认路径、⛔ 不在境内部署中出现。 ⇒ **这是"现在不做"与"预留扩展空间"两句话能同时成立的唯一方式**:底座中性、扩展外挂、地域可分。 --- ### 3.7 中继 / 节点信誉:分层方案与落地建议(v1.2 新增 · 依据用户提问) > 用户提问(原话要点):「**🛡️ 可信中继网络 … 节点信任:将中继节点的历史表现(延迟、成功率)记录在链上,用智能合约自动筛选可靠节点。**」 > **一句话判定**:方向对(信誉应当客观化、可举证),但「**逐条记在链上 + 合约自动筛选**」这个形态**在当前乃至全球开放初期都不成立**;正确形态是**四层分工** —— 链**只做「周期性信任锚」**,实时选路必须留在链下。 #### 3.7.1 四条技术判断(为什么「逐条上链 + 合约筛选」做不成) **判断 1 · 智能合约不会观测,只会读别人喂进去的数** - 合约的执行环境决定它无法主动测量网络延迟 / 连通率;这类量必须由**合约之外**的某一方测量后再写进去。 - ⇒ **谁是喂数方,谁就掌握了「判定谁可靠」的实质权力** —— 把筛选搬到链上并不自动去中心化,只是把中心从「选路代码」挪到「喂数者」(与 §2.4 桥表同理:**链不消除信任点,只移动信任点**)。 - 判据:链保证 **完整性**(写进去的改不了),⛔ **不保证真实性**(写进去的本身可能就是假的)。 **判断 2 · 真正缺的不是「链」,而是「多方独立观测」** - 现状(源码取证):延迟来自 **PONG 的 rtt**、成功率来自**注册 / 心跳结果** —— **全部由被观测者自己那条链路采集** ⇒ 节点可以对自身坏表现「少报」。这是**自证**,不是**他证**。 - 补法不是上链,而是:**同一台 relay 由 ≥3 个互不信任的观测者分别测量,聚合取中位数** —— 单点撒谎(或单点网络抖动误判)不改变结论。 - ⇒ 这一步**不需要链**,却能直接把「输入可信」提升一档,**是当前唯一真缺口**。 **判断 3 · 量级上「逐条上链」不可行** - 设每条信誉样本上链一次:**100 节点 × 每 30 s 一条 ≈ 3.3 TPS**(单链勉强)→ **1,000 节点 ≈ 33 TPS**(已吃掉单链很大一块)→ 若按「**每次转接都记**」(转接量 ≫ 节点数,约 ×100 量级)⇒ **数千 TPS**,**超出单链能力**。 - 而且这类样本 **99% 永远无人读取** ⇒ 等于为极小概率的争议场景**支付常态成本**。 - 正确做法:**高频样本落链下**(可聚合、可滚动窗口、可丢弃),**只有聚合摘要周期上链**。 **判断 4 · 时间尺度不匹配:共识秒级 vs 选路毫秒级** - 选路必须在**毫秒**内出决定;链的最终性是**秒级**(跨地域更慢)—— 差 **3–4 个数量级**。 - ⇒ **链不能当实时筛选器**。链上能承担的只有「**周期性信任锚**」:把某时刻的信誉快照钉住,供事后争议 / 申诉举证。 #### 3.7.2 分层方案(四层各归其位) | 层 | 回答什么问题 | 现在的实现 | 现状 | |---|---|---|---| | ① 准入 / 身份 | 「**这台机器是不是我们信任的?**」—— 一机一钥 + 离线信任根 + 本地校验 + 单台吊销 | 覆盖网络 `identity.ts`(四层密钥模型;离线信任根照抄 Tailscale Tailnet Lock 思路) | ✅ **已有** | | ② **观测**(本方案核心缺口) | 「**它的表现(延迟 / 成功率)是谁测的?**」—— ≥3 个**互不信任**的观测者分别测,聚合取中位数 | 现为**自采**(PONG 的 rtt + 注册 / 心跳结果) | ⚠️ **缺** | | ③ 信誉载体 | 「**凭什么相信这个结论没被事后改过?**」—— 高频样本**链下**累积 + **周期性把聚合摘要锚定到 A 层** | 无 | 未做(**不急**) | | ④ 选路决策 | 「**这次选谁?**」—— **毫秒级、读本地缓存快照**,⛔ 不查链 | 覆盖网络 `placement.ts`:`score = w(0.55·speed + 0.45·load) − failurePenalty × recentFailures`,满载为唯一硬门 | ✅ **已有** | > **一句话记法**:**身份在准入层 · 真值在观测层 · 证据在信誉层 · 决定在选路层**。 > 🔴 **信誉不能当安全边界**:某节点「是否可信」由**准入层身份**判定(层 ①);信誉只回答「**这次选谁更快**」。⛔ 不得用「信誉低」代替「吊销密钥」。 #### 3.7.3 三步落地建议(严格按序,⛔ 不可跳步) | 步 | 做什么 | 为什么这一步先做 | 前置依赖 | 成本量级 | |---|---|---|---|---| | **①** | **补「多方观测」**:同一 relay 由 **≥3 个独立观测者**分别测延迟 / 成功率,聚合取中位数;观测者**不共享**测量口径 | **不需要链**就能把「输入可信」从**自证**提到**他证** —— 当前**唯一真缺口** | 无(复用现有 relay 链路) | 低 | | **②** | **信誉快照锚定**:周期性(如每 10 min 或每小时)把聚合摘要写入 A 层 | 用途明确且**有限** —— 争议 / 节点申诉时**可举证**、**不可事后篡改**;⛔ 不承担实时功能 | ① 必须已成立(否则锚上去的是假数据) | 低(一次哈希上链) | | **③** | **链上规则重排**(**仅周期性**) | 只有当**第三方节点可自主加入、选点规则需要公开裁决**时才值 | ① + ② 均成立 | 中(合约 + 治理) | ⛔ **明确不做**:**「每笔转接上链」** · **「合约实时筛选节点」** · **「用链上延迟数据作为选路输入」**。 #### 3.7.4 判据:什么时候「把信誉放上链」才值 > **须同时满足两条**: > ① **观测者与被观测者互不信任**(数据来源天然不可信 ⇒ 必须多方独立); > ② **筛选结果需要对外举证**(争议裁决 / 准入决定 / 对外审计)。 > > **现状**(节点全部自运维、同属一个运营主体)⇒ **两条都不满足** ⇒ **现在不需要链**,缺的是**多方观测**。 > **全球开放后**(第三方节点自主加入)⇒ **只有第 ② 条成立,且只成立于「周期摘要」这一小块** ⇒ ⛔ **不是「每笔上链 + 合约筛选」**。 #### 3.7.5 与既有设计的衔接(⛔ 不另起炉灶) - **复用,不新建**:准入层直接复用 `identity.ts`(一机一钥 + 离线信任根 + 本地校验 + 单台吊销);选路层直接复用 `placement.ts`(毫秒级本地打分,**天生不依赖链**)。**本方案只新增「层 ② 观测」这一块**。 - **上链量对比**:本方案 = **每小时 1 条摘要**,与节点数**无关**(O(1));「逐条上链」= O(节点数 × 采样频率 × 转接次数) ⇒ **两者差 3 个数量级以上**(推导见 §3.7.1 判断 3)。 - **可分段交付**:即使将来完全不做第 ② / ③ 步,**只做 ① 也能独立交付价值**(选路更稳、少被单点坏数据带偏);反之若先上链却没有 ①,锚的是一堆自证数据 —— **方向反了**。 - **未验证项(须实测,⛔ 不猜)**:① 单 relay 的连接 / 内存上限(现仅有 `relay-mem-calibrate.mjs` **单机标定**,**无规模曲线**)② 控制面(47)的 `hostId` 命名空间与 DB 登记在 100 节点时**是否成单点** ③ 候选链目录变更流程(删 `/var/lib/dshs/overlay/directory.json` + 二次重启控制面)在加节点时的**运维瓶颈**。 #### 3.7.6 结论 让「选谁」这件事(a)**输入可信**、(b)**结论可举证**,才是目的;**「上链」只是(b)的一种手段**。 ⇒ 当前(自运维)只缺 **(a)的实现 = 多方观测**,**不需要链**;全球开放后需要的是 **(b)的一小块 = 周期摘要锚定**。 ⇒ ⛔ 完整形态**永远不是**「每次转接写链 + 合约实时筛选」,而是**四层分工 + 链只做周期性信任锚**。 --- ### 3.8 目标形态推演:3 台骨干 + 1,000 节点 + 50 万终端(v1.3 新增 · 依据用户提问) > 用户提问(原话):「**假设要部署3台骨干服务器 和1000台节点 以及500000个终端设备,这A B两层链如何运行,普通服务器能否运行需要什么配置,现在的覆盖网络能否支撑运行**」 > 本节全部数值沿用 §3.4.1 基准画像(`R=100` / `s=2 KB` / `F=5` / `m=256 B` / `e=1.05` / `V=3` / `W=3`),与 §3.4.2 同口径。 #### 3.8.1 一句话结论(三条) 1. **数据面完全不是瓶颈**:50 万终端全年只产生 A 层链上元数据 **12.8 GB**、密文 blob **323 GB**(含 3 版本),摊到 1,000 节点每台每年 **0.97 GB**。 2. **两处形态级硬伤**(不是容量问题,是设计问题):① **3 台骨干做 B 层共识 ⇒ 拜占庭容错 `f = 0`**(只防宕机,不防作恶)② **1,000 节点跑经典 PBFT ⇒ `O(n²)` = 每轮约 10⁶ 条消息**,不可行。 3. **现有覆盖网络撑得住 1,000 节点(单台中继容量 7,515,占用 13.3%),撑不住 50 万终端**:终端全挂中继需 **67 台**(2C2G 口径)或 **17 台**(4 GB 专用口径);且 **目录结构硬上限 = 8 个中继地址 / 一份目录**(`directory.ts:70`),现有机制**下发不了**这么多中继。 #### 3.8.2 规模账(50 万终端) | 项目 | 计算式 | 50 万终端 | 100 万对比 | |---|---|---|---| | 记录数 / 年 | `N_u × 100` | 5×10⁷ | 1×10⁸ | | 盲索引条目 | `× 5` | 2.5×10⁸ | 5×10⁸ | | 截断位数 `b` | `⌈log₂(条目/3)⌉` | **27 bit**(4 B) | 28 bit | | 索引存储 | `条目 × (16 B + 4 B)` | **5 GB** | 10 GB | | A 层链上元数据 / 年 | `记录数 × 256 B` | **12.8 GB** | 25.6 GB | | 密文 blob(含 3 版本) | `记录数 × 2 KB × 1.05 × 3` | **323 GB** | 630 GB | | 媒体口径(`s=50 KB`,含 3 版本) | `× 50 KB × 1.05 × 3` | **8.06 TB/年** | 15.75 TB | | B 层 KV | `N_u × 2.2 KB` | **1.1 GB** | 2.2 GB | | 用户分片 | `N_u × 200 B` | **100 MB** | 200 MB | | **峰值写 TPS** | `笔数 × 10 ÷ (365 × 86400)` | **≈ 48** | 95 | | **峰值读 TPS** | `× 10` | **≈ 476** | 951 | | KMS 对象数 | `= 租户数` | ≤ 1,000 | 1,000 | **每台节点(1,000 台均摊)**:非媒体 **0.97 GB/年**;媒体口径 **24.2 GB/年**(均已含 3 副本)。⇒ **普通 100 GB 盘即可(媒体口径建议 1 TB)**。 #### 3.8.3 A / B 两层怎么跑(角色分配) | 层 | 谁在跑 | 做什么 | 50 万终端下的量 | |---|---|---|---| | **A 层**(公开链 + 云对象存储) | 1,000 节点 + 3 台骨干 | 链上元数据 12.8 GB/年;blob 走对象存储(**不进链**);1,000 节点做**分片持有 + 可验证** | 每台 0.97 GB/年(非媒体)/ 24.2 GB/年(媒体) | | **B 层**(私有共识链) | **3 台骨干**(本文建议 4 台) | KV 全量 1.1 GB(实名 / 密钥分片 / 桥表);峰值写 ≈ 48 TPS | 单台常驻 1.1 GB 状态 + 索引热路径 | | 覆盖网络(互联层) | 3 台骨干 + 1,000 节点(有公网 IP 者可升格中继) | 信令、打洞协调、兜底转发 | 1,000 节点在册仅占单台中继 **13.3%** | | 终端(50 万) | 用户设备 | 只拨出;客户端加密;盲索引 token 在设备侧算 | **零平台侧成本**(§3.6 V0 全浏览器原生) | **A 层共识形态(现在是空白,必须定)** - ⛔ **1,000 节点不能跑经典 PBFT**:消息量 `O(n²)` ⇒ `n=100` 时 10⁴ 条、`n=1,000` 时 **10⁶ 条/轮**(每轮按 500 B 计 ≈ 500 MB),带宽与 CPU 都不成立。 - ✅ 三条可行路(代价由低到高):① **周期 Merkle root 多签锚定**(最省,与 §3.7「链只做周期性信任锚」同一结论)② **抽样委员会**(VRF 选 100–200 节点轮值出块)③ **分层共识**(1,000 台分 33 组 × 30 台 ⇒ 组内选代表 ⇒ 33 节点代表层)。 **B 层共识形态(硬伤,必须二选一)** - BFT 门槛 `n ≥ 3f+1`:**3 台 ⇒ `f = 0`**;容 1 台作恶需 **4 台**,容 2 台需 **7 台**。 - ⇒ 3 台只能做 **CFT(Raft 类)**:可容 1 台**宕机**,**不能容 1 台作恶**(无法区分"宕机"与"撒谎")。这与 §2.6 用的 `N=4 / f=1` 口径**不一致** ⇒ 要么改 4 台,要么在安全声明里如实写"3 节点仅崩溃容错",且 §2.6b(节点被攻破)在 B 层**无解**。 #### 3.8.4 普通服务器能不能跑 / 配置单 **结论:能跑,但"角色"决定档位 —— 2C2G 能当节点或中继,当不了骨干。** | 角色 | 数量 | CPU | 内存 | 磁盘 | 带宽 | 依据(实测口径) | |---|---|---|---|---|---|---| | **骨干**(B 层共识 + 控制面 + 桥) | 3(建议 **4**) | **8 核** | **32 GB** | NVMe 1 TB | 200 Mbps–1 Gbps | B 层状态 1.1 GB + 索引 5 GB 热路径 + 共识验签(CPU 密)+ 45% 余量 | | 中继(**2C2G 云轻量**,可用内存 ≈1 GB) | **67** | 2 核 | 4 GB | 40 GB | 100 Mbps | `MEM_PER_HOST` 0.06 MB ⇒ `C_MEM` 16,700 ⇒ `MAX_HOSTS` **7,515** | | 中继(**4 GB 专用**,裸机给 relay) | **17** | 2–4 核 | 4–8 GB | 40 GB | 100 Mbps | `C_FD` 65,536 成新上限 ⇒ `MAX_HOSTS` **29,491** | | **普通节点**(A 层分片) | 1,000 | **2 核** | **4 GB** | **100 GB**(含媒体 ⇒ 1 TB) | 10 Mbps | 0.97 GB/年(非媒体)/ 24.2 GB/年(媒体,含 3 副本) | | 终端 | 500,000 | 用户设备 | — | — | — | 只拨出;WebCrypto / Passkey(§3.6 V0) | **两条"没配就崩"的配置项** 1. 🔴 **中继 fd 上限必须拉起**:`FD_PER_HOST = 4` ⇒ fd 还是默认 1024 时**单台只能装 256 台**(不是 7,515)。必须 `LimitNOFILE = 262144`(47 实测值)。 2. 🔴 **`--max-hosts` 必须显式下发**:默认 `0` = **不限**(`main.ts:70`)⇒ 不限等于既无硬门也无软门,超载时表现为"**静默变慢**"而非"明确拒绝"。按 §5.2 公式下发(47 / 106 现为 7,515)。 #### 3.8.5 现有覆盖网络能不能支撑(逐项判定) | 维度 | 现有能力(实测 / 取证) | 判定 | |---|---|---| | 1,000 节点在册 | 单台中继 7,515 ⇒ 1,000 = **13.3%** | ✅ **够**(且只用得上 1 台;第 2 台今天是容灾不是容量) | | 50 万终端挂中继 | 7,515 / 29,491 每台 ⇒ 需 **67 / 17 台** | ❌ **现有 2 台远远不够** | | 目录下发 | `MAX_ENTRIES = 8`(`directory.ts:70`,防放大设计) | ❌ **硬上限**:一份目录最多 8 个地址 ⇒ 下发不了 17–67 台 ⇒ 必须改目录结构(分片 / 二级目录) | | 控制面带宽 | 心跳 `6.7 B/s × 50 万 = 26.8 Mbps` | ✅ 3 台骨干(各 100 Mbps)可承载,约占 9% | | 数据面 | 峰值读 476 TPS × 2 KB ≈ **0.95 MB/s** | ✅ 可忽略 | | **带流量 per-host 内存** | 0.06 MB/台是**空闲会话**实测;每流高水位 **256 KB**(`server.ts:101`)+队列上限 **1 MB**(`:98`) | ⚠️ **最大不确定项**:终端满流时 per-host 是 MB 级 ⇒ **7,515 只在"以空闲会话为主"时成立**(未测已登记) | | 1,000 节点共识 | 经典 BFT 为 `O(n²)` | ❌ 需抽样委员会 / 分层(§3.8.3) | | 3 台骨干 BFT | `n ≥ 3f+1` ⇒ `f = 0` | ❌ 须 4 台,或如实降级为 CFT | | 加中继的运维 | 目录变更需"删 `directory.json` + 二次重启控制面" | ⚠️ 加 17–67 台时是瓶颈 ⇒ 需先做**目录热更新** | > **净判定**:覆盖网络在「**1,000 节点**」这一维上已经够用(7.5× 余量);在「**50 万终端**」这一维上不够,而**缺的不是机器、是两处机制** —— ① 目录只能下发 8 个中继地址 ② per-host 内存只有空闲会话实测值。 #### 3.8.6 按序要补的三件事 1. **量测"带流量 per-host 内存"** —— 唯一还没量的关键口径;它同时决定"17 台还是 67 台"与"终端能不能挂中继"。 2. **改目录结构** —— 支持 ≥64 个中继地址 + **热更新**(取消二次重启控制面)。 3. **定 A 层共识形态(§3.8.3 三选一)+ 把骨干改为 4 台**(两处形态硬伤)。 --- ### 3.9 终端升格为子节点:现有方案支持到哪一步(v1.4 新增 · 依据用户提问) > 用户提问(原话):「**假设50W终端之间有公网IP的设备也能升级为子节点呢,现有方案支持这样的情况吗**」 > 判据先行:**"子节点"是三个不同的档位,能力与成本差一个量级** —— 必须分开判,不能笼统答"支持/不支持"。 #### 3.9.1 先分档(三档"子节点") | 档 | 能力 | 门槛 | 代价 | |---|---|---|---| | **① 被连方** | 别人能连到它(host↔host 流) | 在册 host + **声明端口** + 回环监听 + 一机一钥 | 需**原生客户端/守护进程** | | **② 内容子节点** | 帮同组 peer 取块 / 持有块 | peer 声明 + 分组隔离 + 读侧复算 | 块缓存配额(默认 **64 MiB**) | | **③ 中继子节点** | 帮别人转发与会合 | **公网入向可达** + 控制面登记 + 目录下发 | 凭据运维面(万级) | #### 3.9.2 判定:①② **已支持**,③ **只到设计、未到实现** - **① 已支持**:`server.ts:153` —— relay 侧密钥表为空 ⇒ **所有 `HELLO` 被拒(默认拒绝)**;`:1176` —— worker「注册即开回环监听、**必须声明端口**」;`keys.ts` 每 host 一密钥(爆炸半径 = 那一台)。 - **② 已支持**:`content/peer.ts:31` 的 `PeerDeclaration{name, network, group, holds, epoch}` + 分组键 `|` + **跨组显式拒绝并计数**;发现源**就是 relay 的在册会话表**(`peer.ts:24`,⛔ 不新开公网口);取块走 `source.ts:57` 五档链,`peer` 档已在装配点接线并**复算块 id**(不符即丢弃、不算命中)。 - **③ 未实现**:`接续入口` 已定「**有公网 IP 的节点升格为中继候选**」(清单 §3 关键决定),但**目录里的 `relays` 由签发的目录文档给出**(`directory.ts:305`,`slice(0, MAX_ENTRIES)`)⇒ **代码里没有"自动升格"路径**;现有第二台中继(106)的升格是**人工执行**(T19 / S8)。 #### 3.9.3 五条硬门(代码级,决定"能不能做到") 1. 🔴 **纯浏览器终端做不了 ①** —— 要当被连方就得**声明端口 + 开回环监听**,而 relay 默认且建议只绑 `127.0.0.1`(`server.ts:150`)、`no-ports` 一律拒绝 ⇒ **Web 终端只能"拨出+取块",不能"被连"**。要当子节点必须是**原生客户端/桌面守护进程**。 2. 🔴 **升格必须由控制面登记并下发密钥** —— **"自动升格" ≠ "自动生效"**;没有凭据那一步,HELLO 直接被拒。 3. 🔴 **目录是比机器数量更前置的墙** —— `MAX_ENTRIES = 8`(`directory.ts:70`)⇒ 即便升格出 2.5 万台子节点,**新终端也发现不了它们**(见 §3.8.5 同一堵墙)。 4. ⚠️ **"有公网 IP" ≠ "入向可达"** —— `directory.ts:435 isPublicHost` 只剔除回环与私网;**家宽 NAT / 运营商 CGNAT 下"本机看到公网 IP"与"外部能连进来"是两件事** ⇒ 升格判据必须是**入向可达实测**,⛔ 不是"我拿到一个公网地址"。 5. ⚠️ **打洞能力不能当既成事实** —— `direct/punch.ts:23` 原文已留档:机器断言证明的是"**这段打洞逻辑**在 NAT 穿透场景下成立",⛔ **不是**"公网一定能打洞"。 #### 3.9.4 升格后能省多少(容量口径) - **约束是出带宽,不是内存**:47 的 352 KB/s 是**云轻量出带宽封顶**,不是 relay 栈上限(上行方向实测 12,213 KB/s)⇒ **一台上行 100 Mbps 的家宽子节点,可承接流量是同档云轻量的数十倍**;但全网必须按**最慢的那台**兜底 ⇒ **中继仍需保留**(设计本就是 45% 余量 + 443/TCP 兜底)。 - **每端口 64 条并发流**(`MAX_STREAMS_PER_PORT = 64`,实测)⇒ **内容子节点单端口只能同时服务 64 个取块请求**;热门块会立刻打满 ⇒ 必须多端口/多子节点分散(Delivery Optimization 式多源)。 - **每节点块缓存默认 64 MiB**(`CONTENT_STORE_MAX_BYTES = 67,108,864 B`,与 relay 的 `MEM_PER_HOST_MB` 预算**独立**)⇒ 真要当内容子节点,须上调该值并固化进参数表,否则命中率极低。 - **净收益**:若 **5% 终端可升格**(2.5 万台)⇒ 中继容量需求从 17–67 台降到「**只需兜底数台**」(信令 + NAT 严格者);且子节点之间可直连 ⇒ 目录只需下发**会合点**,不必下发全部子节点。 - ⚠️ **前置条件**:必须先有 §3.7 步 ① 的**多方观测**,否则节点质量参差会直接拖垮选路(`placement.ts` 的分数只对"输入可信"负责)。 #### 3.9.5 按序要补的五件事 1. **定档位**(①②③ 是三种能力):先做 ①②(代码已就绪),③ 走「**候选池 + 半自动升格**」而非全自动。 2. **控制面凭据的批量登记/吊销**(万级量级)—— 复用 `identity.ts` 的一机一钥 + 单台吊销;这是真正的运维面瓶颈。 3. **改目录结构**(≥64 地址 + 热更新,§3.8.6 第 2 条同一件事)。 4. **补"入向可达"探测** —— 把"有公网 IP"与"外部真能连进来"分开判定(硬门 4)。 5. **参数表固化子节点档位值**:`CONTENT_STORE_MAX_BYTES`(现 64 MiB)、`MAX_STREAMS_PER_PORT`(现 64 条)。 --- ### 3.10 依赖顺序裁决:要不要先优化网络、先做链会不会返工(v1.5 新增 · 依据用户提问) > 用户提问(原话):「**现在有必要优化吗,不优化后续做链会有影响吗,先做链后续在优化网络是不是会返工**」 > **裁决:不必现在做容量类优化;先做链也不会返工 —— 但前提是现在把「三条复用点 + 两个口径」写死(成本 = 写文档,不是写代码)。** 真正会返工的只有一类情形:**链另起一套身份或寻址**。 #### 3.10.1 判据:返工从哪来 **返工来自「同一件事被定义两遍」,不来自「晚做优化」。** - **优化** = 在既有接口**内部加东西**(可叠加、可回滚、幂等)⇒ 后置**不产生返工**; - **口径 / 协议分叉** = 把**同一个概念定义两次**(不可叠加,必有一方被重写)⇒ 这一类**必须现在定**。 ⇒ 逐项只问一句:**这个动作会不会产生「第二套定义」?** #### 3.10.2 逐项裁决(§3.8.6 三件 + §3.9.5 五件) | 项 | 性质 | 后置的后果 | |---|---|---| | 带流量 per-host 内存量测 | 量测 | ⛔ 不返工(只改参数值与台数) | | 多方观测(≥3 观测者) | 新增一层 | ⛔ 不返工;**选路质量**依赖它,但不阻塞链 | | 入向可达探测 | 量测 | ⛔ 不返工 | | 控制面凭据批量登记 / 吊销 | 运维工具 | ⛔ 不返工 | | 参数表固化(64 MiB / 64 条流) | 参数 | ⛔ 不返工 | | **目录结构(≥64 地址 + 热更新)** | **协议**(客户端要长期兼容) | ⚠️ **会变兼容债**:能改,但存量终端升不动 | | A 层共识形态 / 骨干 3 → 4 台 | **链自身的设计与部署** | — 不属"网络优化",是链的开工前置 | ⇒ **网络侧 6 项里只有"目录协议"一项会变成兼容债**,其余 5 项全是加法,后置做**不触碰链的数据模型**。 #### 3.10.3 现在就要定死的五条(成本 = 写文档,不是写代码) 1. **节点身份**:链上任何「节点 / 验证者 / 存储持有者」的资格判定,**唯一口径 = `identity.ts`**(一机一钥 + 离线信任根 + 本地校验 + 单台吊销)⇒ ⛔ 链自建第二套身份 = **必返工**。 2. **寻址与会合**:链节点之间怎么找到彼此,**唯一口径 = 覆盖网络**(`placement.ts` 选路 + 目录会合)⇒ ⛔ 链自建第二套寻址 = **必返工**。 3. **锚定落点**:链要锚定就**锚到 A 层**(§3.7 结论),⛔ 不新建第三条链。 4. **口径一 · 命名空间**:`network_id`(`ops` / `u:`)与 hostId 逻辑名(`/`)—— 链上锚定数据**一旦以某个 id 方案为依据,改口径就要迁数据**。 5. **口径二 · 世代**:沿用既有 `epoch` 思路(`content/peer.ts` 已用「epoch 不一致 ⇒ 不作为候选」)⇒ 链的版本 / 世代走同一套,⛔ 另立一套版本号。 (注:`identity.ts` 的**离线信任根**是整条线的信任锚 —— 它一旦上链参与资格判定,就是全链的信任起点,改它的代价最高。) #### 3.10.4 一句话回答三问 - **现在有必要优化吗** ⇒ **不必** —— 逐项核对后,**没有一项构成链的阻塞**。 - **不优化对做链有影响吗** ⇒ **有且只有一处**:目录若先按「≤8 地址」上线,客户端会按这个格式解析 ⇒ 后期改结构要付**兼容成本**(不是返工,是存量设备升不动)。 - **先做链再优化网络会返工吗** ⇒ **不会**,前提是 §3.10.3 那五条现在写死;**若不写死,返工点恰好落在「身份 / 寻址」这一处**,而非网络优化的其他方面。 #### 3.10.5 建议的执行顺序 | 序 | 动作 | 性质 | 能否后置 | |---|---|---|---| | 1 | 冻结 §3.10.3 五条(写进主文档 / 接口注释) | 口径 | ⛔ **现在做**(零代码) | | 2 | 定链的两处形态(A 层共识三选一、骨干改 4 台) | 链的设计 | ⛔ 链开工前 | | 3 | 做链(复用覆盖网络的身份与寻址) | 建设 | — | | 4 | 目录协议改造(≥64 地址 + 热更新) | 协议 | ⚠️ 与链**同期或紧随**(越晚越贵) | | 5 | 其余优化(带流量内存量测 / 多方观测 / 凭据工具 / 参数固化 / 入向探测) | 加法 | ✅ 任意时点,**不返工** | --- ### 3.11 账号密码能否上链 · 1000 万用户与 1000 万并发登录(v1.6 新增 · 依据用户提问) > 用户提问(原话):「**链上存 用户账号密码等信息,1000万用户 1000万同时登录 能支持并发吗,是不是无法像数据库那样做分布式 主从库那样容易扩展性能**」 > **两句话判定**:① **账号密码不该上链**(不是性能问题,是设计错误)② **"1000 万同时登录"的瓶颈是 KDF,与"链 or 库"无关** —— 换数据库一样要付这笔账。用户关于**写扩展性**的判断是**对的**。 #### 3.11.1 账号密码为什么不该上链(三条判据) **数据该放链上的判据(三条须同时满足)**:① 需要多方对**同一份状态**达成不可篡改的共识;② **写入低频**;③ **公开可验证**有实际收益。 **账号密码与登录三条全不满足**,且另撞两条硬冲突: - ⛔ **链上区块对全部节点可见且永久** —— 即使只存**摘要**,它也是"全网可见 + 攻击者拥有**无限时间**"的离线爆破目标。方案红线只是"A 层永不出现明文",**摘要仍须按高价值资产对待**。 - ⛔ **链只能追加、不可删改** —— 改密码 / 注销都会在链上留下**旧摘要**,攻击面**永久累积**(与 §2.4 冲突一同一个病)。 - ⛔ **认证是高频读 + 高频写** —— 而链的每一笔写都要走共识(见 §3.11.3)。 ⇒ **正确落点**:密码摘要(Argon2id / bcrypt)留在**链下应用侧**;链上最多存"身份存在性"的**匿名锚**(HMAC token,与 §2.4 / §3.1 匿名 ID 同口径),且低频。**B 层只存实名与密钥分片(§2.3 已定),⛔ 不存密码。** #### 3.11.2 「1000 万同时登录」的真实瓶颈 = KDF(与链/库无关) | 登录窗口 | 请求率 | KDF 参数 | 需要的核 | 需要的内存 | |---|---|---|---|---| | 1 分钟 | 166,667 req/s | 75 ms / 64 MiB | 12,500 核 | **781 GB** | | 5 分钟 | 33,333 req/s | 75 ms / 64 MiB | 2,500 核 | 156 GB | | 5 分钟 | 33,333 req/s | 75 ms / **19 MiB** | 2,500 核 | **46 GB** | | 30 分钟 | 5,556 req/s | 75 ms / 19 MiB | 417 核 | 7.7 GB | ⇒ **这张表在数据库方案下一模一样** —— 瓶颈是 `KDF 参数 × 并发数`,不是存储选型。 ⇒ 结论:**"1000 万同时登录"只能靠"会话复用 + 排队限流 + 参数标定"化解**,⛔ 不能靠换存储化解: ① 登录成功签发**长 TTL 会话令牌**(后续请求**不再算 KDF**);② 登录入口**令牌桶限流 + 排队**;③ KDF 参数按"可接受延迟"标定(19 MiB 档位内存降 3.4×)。 #### 3.11.3 用户的判断是对的:链的**写**扩展性确实不如库(但要分清读/写) | 能力 | 关系库主从 | 链 | 差别 | |---|---|---|---| | 加**只读**副本 | ✅ 线性 | ✅ **一样**(只读副本 + 索引层缓存) | ⛔ 无差别 | | 加**写入**能力 | ✅ 分库分表(改路由即可) | ⚠️ **只能分片链**(每片独立共识,**跨片无原子性**) | 🔴 **真正差别** | | 扩容粒度 | 表 / 库 / 实例 | **链**(整片) | 粒度粗 | | 改历史 | ✅ UPDATE / DELETE | ⛔ **只能追加** | 与删除权冲突(§2.4) | | 成员变更 | 加从库即可 | ⚠️ 需**共识成员变更协议** | 比"加从库"重 | | 写延迟 | 毫秒 | **共识秒级** | 差 3 个数量级(§3.7 判断 4) | ⇒ 一句话:**「读」像库一样好扩;「写」只能分片,且片内不能像主从那样自由加写节点。** #### 3.11.4 本方案在 1000 万用户下的两处硬结论 - 🔴 **B 层必须分片**:1000 万用户 ⇒ B 层峰值写 **951 TPS**,已抵 PBFT 类单链上限(1,000–3,000 TPS 口径)**下沿** ⇒ 建议 **8 片**(每片 125 万用户 / 119 TPS),16 片更稳(每片 62 万 / 60 TPS)。⚠️ 分片后**跨片无原子事务** ⇒ 跨片操作要走两阶段 / 补偿,设计上应避开。 - 🔴 **登录事件不上链**:每天 3 次/用户 ⇒ 日均 347 TPS、**峰值 3,472 TPS**(**超单链能力**);每天 1 次 ⇒ 峰值 1,157 TPS 亦在临界 ⇒ 登录只上"**日聚合摘要**"(1 条/天),与 §3.7「链只做周期性信任锚」**同构**。 #### 3.11.5 与既有结论的一致性 - 与 §3.7(链只做周期锚定)/§3.10(不产生第二套定义)一致:KDF 用成熟库,⛔ 不自研密码学。 - 与主文档红线一致:A 层永不出现明文;B 层只存密钥**分片**;链上不设密码字段。 --- ### 3.12 链上 / 链下边界与链的引入时机(v1.7 新增 · 依据用户拍板) > 用户拍板原话:「**还是区分链上和链下的数据是对的,后续做DAO和在线游戏时在考虑链**」 #### 3.12.1 这条拍板定了两件事 | # | 定了什么 | 性质 | |---|---|---| | 1 | **链上 / 链下分离**是正确设计,继续执行 | **确认既有原则**(与 §2.4 / §3.7 / §3.11 同向) | | 2 | **链的引入时机 = 后续做 DAO 与在线游戏时再考虑** | **排期决策**(⛔ 不是架构变更) | **一句话判定**:这是**排期决策,不是架构变更** —— 它不推翻 §3.6 的 V0 / V1 两段式,而是把「链能力」整体归入 **V1+**,并要求 V0 里每一处「本该由链提供的能力」都先有**链下等价物**。 #### 3.12.2 为什么"链"在 V0 可以被拿掉而不塌(三项链下等价物) 链对外提供的其实是三样东西,三样都能先用链下方式做到 —— 区别只在「**谁来保证**」: | 链提供的能力 | V0 链下等价物 | 升级为链时改什么 | |---|---|---| | **① 时序不可否认**("这条记录在 T 时刻已存在") | **Merkle 根 + 可信时间戳锚**(§3.6.1 已定),锚可由**用户自留副本** | **只换锚的存放处**,数据模型不变 | | **② 多方一致性**(互不信任的几方对同一状态达成一致) | **多方各留一份 + 摘要互签 + 定期对账** | **只换仲裁方**("对账" → "共识") | | **③ 防篡改日志**(只能追加、不能改历史) | **哈希链**(每块含前块哈希)—— 它本身就是"单方链" | **只换写入权归属**("平台写" → "多方写") | **关键**:三项的升级动作全都是「**把单方改成多方**」,⛔ 不动数据结构、⛔ 不动密钥分层、⛔ 不动 API 形状。⇒ 与 §3.10 判据一致:**链的引入不产生返工**。 #### 3.12.3 V0 唯一需要定死的硬约束 > 🔴 **凡对外宣称「不可篡改」的地方,必须能由用户自己举证,⛔ 不得表述为「平台保证不可篡改」。** - **做法**:一律用「**Merkle 根 + 签名 + 由用户自己留存副本**」实现;平台只提供"把根再签一次"的便利,⛔ 不把"信任平台"当作唯一凭据。 - **理由**:这句话在 V0 是**诚实的**(平台确实能改),引入链后**自动变成可举证的真命题**(根已上链)⇒ **文案与接口都不用重写**。反之,V0 若写"平台保证不可篡改",链引入时不是升级,而是**推翻既有承诺**。 #### 3.12.4 为什么 DAO 与在线游戏恰好"需要用链" 两者都**同时命中 §3.7.4 的上链判据**(观测者与被观测者互不信任 **且** 结果需对外举证): | 场景 | 为什么链下不够 | 落层 | |---|---|---| | **DAO**(§2.9) | 治理结果必须"**任何单方**都改不了",且要对**非成员**举证 ⇒ 中心化对账天然不被采信 | **A 层**(公开可验证的锚 + 规则哈希) | | **在线游戏** | 跨服 / 跨运营方的物品与状态要互认,且要**防内部私改**(运营方本身就是参与者之一)⇒ 与被审计方同侧的数据库不能作凭据 | **B 层**(私有共识链)+ 高频状态走链下 | ⚠️ **在线游戏的额外约束**:游戏是**高 TPS + 低延迟**负载,⛔ 不可能逐笔上链 ⇒ 只能「**链下执行 + 链上结算**」(批量结算 / 定期锚定)。这与 §3.7 的结论**同构**(链做周期性信任锚、实时留在链下)⇒ **同一个模式复用两次**,不需要为游戏另立一套。 #### 3.12.5 边界与交付 - ✅ **已按此拍板落地**:§3.6(V0 能力层)不变 | §3.7(链只做周期锚)不变 | §3.11(认证与链解耦)不变 —— **三处方向一致,本轮无冲突需裁决**。 - ⛔ **本文未做**:不预估 DAO / 游戏的排期,⛔ 不预设链选型(上链判据已给出,选型留到触发时再定)。 - ⏳ **触发条件(写明用法)**:出现「**多互不信任方 + 需对外举证**」的需求即为触发点;届时按 §3.7.4 判据 + 本节 §3.12.2 的「换锚 / 换仲裁方 / 换写入权」三处替换点逐项对齐。 --- ## 4. 本文新增的验收判据建议(15–33,须并入主文档 §6) | # | 判据 | 通过标准 | 由来 | |---|---|---|---| | 15 | **删除真效力可验证** | 删除后:① OSS 回读 404(含版本/回收站)② 密钥副本零残留 ③ 桥映射已清除 ④ 抽样备份命中 0 | 场景 4 | | 16 | **并发写入不丢数据** | 两设备并发改同一条 ⇒ 后提交者被拒绝并收到冲突提示(⛔ 无静默覆盖) | §3.2 | | 17 | **恢复演练含密钥轮换** | 模拟"设备丢失且可能被解锁" ⇒ MK + 全部 DEK_data 轮换成功,旧分片失效 | 场景 3 | | 18 | **客户端可验证性** | 用户侧可校验"运行的客户端 = 已登记构建";比对不一致必告警 | 场景 7 路径 7 | | 19 | **审计不可停锚** | 存在**独立于平台**的锚定/验证方;停锚 N 小时内必有外部告警 | 场景 7 | | 20 | **分片不可单点取用** | 解封 Sh2 需多角色授权;单管理员全权限操作**无法**单独取到可用分片 | 场景 6b | | 21 | **治理可验证且成员不公开** | 仅凭公开数据可验证"某票有效",但**无法反推投票人身份或成员表** | 场景 8 | | 22 | **平台不经手资金与内容** | 全量清点平台接口:**无**收款 / 付款 / 分账执行接口;能力调用路径不落地内容明文 | 场景 8 + 拍板 2 | | 23 | **可替换证明后端** | 身份 / 成员资格核验走统一 `prove/verify` 抽象;V0(签名 + Merkle)与 V1(ZK)**可互换而不改上层** | §3.6 | | 24 | **主仓无价值凭证** | 开源主仓全量检索:**零**代币 / 积分 / 余额相关能力;相关能力仅以独立插件形式存在于境外部署 | §3.6.3 + 拍板 1 | | 25 | **观测非自证** | 同一 relay 的延迟 / 成功率由 **≥3 个互不信任的观测者**分别采集,聚合取中位数;单点撒谎不改变结论 | §3.7 | | 26 | **信誉锚定可举证且不拖累实时** | 周期摘要可在 A 层被第三方复核;**选路路径不含链调用**(实测选路延迟不受上链影响) | §3.7 | | 27 | **带流量容量口径已实测** | 存在"每 host 有活跃流"时的 per-host 内存实测值(⛔ 不用空闲会话外推);据此重算并下发 `RELAY_MAX_HOSTS` | §3.8.5 | | 28 | **目录可承载多中继且热更新** | 单份目录可下发 ≥64 个中继地址(或分层目录);**新增中继无需重启控制面**即生效 | §3.8.5 | | 29 | **入向可达是实测值而非推断值** | 子节点资格判定取自**外部入向连通实测**;⛔ 不接受"本机看到公网地址"作为判据(区分 NAT / CGNAT) | §3.9.3 | | 30 | **子节点可批量登记与吊销** | 万级子节点凭据可批量下发与**单台吊销**;吊销后台账与在册会话**同时**消失(⛔ 不残留可用凭据) | §3.9.5 | | 31 | **链侧无第二套身份与寻址** | 全量检索链侧代码与配置:**不存在**独立于覆盖网络的密钥表 / 在册表 / 目录表;链上资格判定与寻址**均引用** `identity.ts` / `placement.ts` 同一份口径 | §3.10.3 | | 32 | **认证与链解耦** | 全量检查登录路径:**无链调用**、链上**无密码摘要字段**;登录只以**日聚合摘要**形式上链;并发登录经会话复用 + 限流后**不再触发 KDF** | §3.11 | | 33 | **「不可篡改」可由用户自证** | 全量检索对外文案与 API:**无**"平台保证不可篡改"表述;所有此类承诺均可由用户用「Merkle 根 + 签名 + 自留副本」**独立复核** | §3.12.3 | --- ## 5. 待拍板(⛔ 本文不自决,需你定夺后再回填主文档) ### 5.0 已拍板(2026-09-19 19:0x · 用户三条 · 本文已按此落地) | # | 拍板(原话要点) | 落点 | 对下方待拍板项的影响 | |---|---|---|---| | 1 | 「**现在不做,预留扩展空间(这是面向全球的开源项目)**」 | §2.9 步 7 · §3.6.2 · §3.6.3 · 判据 24 | 底座保持中性(主仓零价值凭证能力) | | 2 | 「**平台只做互联和项目协作的作用:能力共创、能力共享、能力使用分发**」 | §2.9.1 · §2.9.3 · 判据 22 | **平台范围定项**:⛔ 不引入资金与法律主体职能 ⇒ 下方第 9 / 10 项仍待拍板,但已被此条收窄 | | 3 | 「**预留扩展空间,先用最低成本的方式生成密钥与核验**」 | **§3.6(V0 = 设备密钥 + Merkle 包含证明 + Ed25519 签名,零新增基础设施)** | **第 6 项(zkVM 资源来源)降级为"预留、不进当前排期"** ⇒ 当前**不需要** GPU 与证明运维线 | | 4 | 「**分层方案和建议不错 可以记录下来**」(对 19:30 提问「节点信任:把中继节点历史表现记在链上、用智能合约自动筛选可靠节点」的回应) | **§3.7(新增整节)** + §0 第 8 条 + 判据 25 / 26 | **记录性拍板**(认可分层方案)⇒ 下方第 14 项(多方观测者由谁承担)成为**步 ① 的真实前置** | | 5 | 「**还是区分链上和链下的数据是对的,后续做DAO和在线游戏时在考虑链**」 | **§3.12(新增整节)** + §0 第 13 条 + 判据 33 | **排期性拍板**:链能力整体归入 **V1+**,V0 取链下等价物 ⇒ 下方第 6 项(zkVM 资源来源)与第 16 项(A 层共识三选一)**均不进当前排期**,保持"预留"状态 | > 排序:先合规口径(决定架构底线),再成本(决定排期),最后产品/安全策略(各有优劣的真取舍)。 **1. 合规口径 —— 链上"匿名化哈希 + 去映射 anon_id"是否构成 PIPL 意义上的"非个人信息"(含 DAO 场景的贡献 / 投票记录)** - 这是**删除权能否成立的前提**,未经法律意见不能写进方案。 - 候选 A:直接采信"匿名化后不属个人信息",据此设计删除流程。 - 优点:架构不需要为删除权做额外妥协;实现最直接。 - 缺点:若定性被推翻,链上将出现无法删除的个人信息 ⇒ 需重做架构。 - 候选 B:先取执业法律意见,再定架构细则(本文默认按此挂起)。 - 优点:风险最低;口径可写进用户协议与监管沟通材料。 - 缺点:需要外部成本与时间,S0 排期被拉长。 - 候选 C:不依赖定性 —— 直接按最保守口径设计(链上只存加盐哈希,彻底放弃第三方独立验证)。 - 优点:无论定性如何都站得住。 - 缺点:牺牲公开可验证性(产品的对外卖点之一)。 **2. 合规口径 —— 司法配合请求在"A 层技术上不可解"时的定性** - 问题:平台无法提供 A 层明文,**是否构成"拒不配合"**?须法律意见。 - 候选 A:按"技术上不可行"书面回复并说明密钥架构。 - 优点:符合架构现状,无需改动。 - 缺点:责任边界未定,存在被认定不配合的风险。 - 候选 B:预先与主管部门沟通备案(说明"单方不可解、合谋可解"的事实)。 - 优点:把不确定性前置解决。 - 缺点:可能引出新的监管要求(如被要求保留可解密通道)⇒ 反过来冲击架构。 **3. 影响面 —— 2-of-3 中是否保留"平台片"** - 候选 A:保留平台片(本文默认沿用主文档)。 - 优点:丢设备可恢复;合规配合作业有技术通道。 - 缺点:**平台 + T3 串谋即可解开全部用户数据**,对外不能宣称"任何人不可解"。 - 候选 B:去掉平台片(2-of-3 = 用户设备片 + 用户密码派生片 + T3 片)。 - 优点:平台彻底退出 ⇒ "连串谋也不可解"成立。 - 缺点:丢设备 + 忘密码 = **永久丢失**;司法配合彻底无通道。 **4. 影响面 —— B 层形态:value 落链 vs 链下存密文(本文 §2.4 的 b2 建议)** - 候选 A(本文建议):链上只存锚 + 墓碑,value 密文在链下受控存储。 - 优点:删除权真满足;不可篡改语义保留;删除可证明。 - 缺点:与 v1.1 已表述的"KV 链"形态有落差;需处理备份影子副本。 - 候选 B:维持 value 直接落链,用"状态裁剪 + 销毁 DEK"应对删除。 - 优点:形态符合原表述;链条完整。 - 缺点:**"不可解" ≠ "已删除"** ⇒ 删除权可能不被认定为已履行(⚠️ 又回到合规口径 1)。 **5. 成本 —— 自研链的团队与预算(20 人以上 / 年 500 万量级口径)** - 候选 A:按主文档分阶段(FISCO BCOS 先行,逐步替换)。 - 优点:业务未验证前不投重资产。 - 缺点:两次建设、迁移成本。 - 候选 B:直接组建自研团队。 - 优点:一步到位。 - 缺点:业务未验证即投重资产;招聘周期长。 **6. 成本 —— zkVM 证明层的资源来源(自购 GPU vs 证明外包)** - 候选 A:批量证明 + 自购 GPU($24–48K 量级硬件)。 - 优点:成本可控、数据不出域。 - 缺点:需新增 GPU 运维线;低延迟能力受限。 - 候选 B:证明外包(证明市场)。 - 优点:无需资产、弹性。 - 缺点:引入第三方依赖;证明输入数据的信任边界需重新论证。 - 候选 C:暂不引入(B 层先不做盲验证)。 - 优点:省一条运维线。 - 缺点:B 层节点要验状态就得看数据 ⇒ 与"加密安全优先"冲突(主文档 §3.4.2 的死结 unresolved)。 **7. 产品策略 —— 前端投毒防护做到哪一档** - 候选 A:CSP + SRI(最低档)。 - 优点:零额外成本。 - 缺点:几乎挡不住有平台权限的攻击者。 - 候选 B:可验证构建 + 透明日志登记(推荐起点)。 - 优点:可检测、可举证;对用户可展示。 - 缺点:需建立构建流水线与发布流程。 - 候选 C:原生客户端 + 代码签名(或开源客户端)。 - 优点:防护最强。 - 缺点:开发与分发成本最高;开源涉及商业权衡。 **8. 安全可用性 —— 门限参数 2-of-3 与 3-of-5** - 候选 A:2-of-3(沿用)。 - 优点:协调成本低;用户少找一方。 - 缺点:容错差(同时丢 2 方即永久丢失)。 - 候选 B:3-of-5。 - 优点:恢复概率显著提升。 - 缺点:**任 3 片串谋的门槛更低**(风险面扩大);用户需维护更多托管关系。 **9. 影响面 —— 第三方托管方(T3)由谁承担** - 需具备:独立法人 / 独立管理域(最好独立司法辖区)、SLA 约定分片可导出、独立验证能力。 - 候选 A:引入专业托管机构。 - 优点:独立性容易满足;有合规资质。 - 缺点:持续成本;引入对外依赖与合同约束。 - 候选 B:自建第二个平台(同实控人)。 - 优点:成本低、可控。 - 缺点:**独立性不成立 ⇒ 门限安全性退化为"单方持有 2 片"**,架构承诺失效(本文明确不推荐)。 **10. 影响面 —— 数据出境:链节点与对象存储的地域** - 需定:A 层公开链节点、B 层私有链节点、对象存储区域。 - 候选 A:全境内。 - 优点:出境合规最简单。 - 缺点:跨云/跨地域容灾能力受限;成本可能更高。 - 候选 B:境内外混合(冗余更强)。 - 优点:容灾更好。 - 缺点:触发数据出境评估(⚠️ 且"密文出境 + 密钥不出境"的定性需专业意见)。 **11. 真取舍 —— `DK_idx` 由用户侧派生(默认)还是平台侧持有** - 候选 A:用户侧派生(本文默认)。 - 优点:平台无法替用户构造 token ⇒ 访问模式不能被平台任意扫描。 - 缺点:查询需用户设备在线;服务端代理能力弱(离线/搜索体验受限)。 - 候选 B:平台侧持有。 - 优点:支持服务端代理查询,体验好。 - 缺点:平台获得完整访问模式可见性(虽仍不可解密内容)。 **12. 合规口径 —— 用户协议中"链上不可删"的告知是否足以豁免** - 候选 A:以显著方式告知并取得单独同意。 - 优点:成本最低。 - 缺点:PIPL 47 条属法定义务,**同意未必能豁免**(须法律意见)。 - 候选 B:按最保守口径设计(见第 1 项候选 C)。 **13. 对外承诺 —— 开源许可证选择与"境外价值凭证插件"的分发方式**(**由拍板 1「面向全球的开源项目」直接引出**) - 候选 A:主仓用宽松许可(Apache-2.0 / MIT),价值凭证类扩展另仓另许可。 - 优点:全球采用门槛最低,生态最容易起量;与"底座中性"的定位一致。 - 缺点:无法阻止他人(含境内主体)自行加上代币层 ⇒ 平台对"被用于 237 禁止用途"的控制力弱。 - 候选 B:主仓用 AGPL-3.0,商业使用走双轨授权。 - 优点:可对商用施加约束,保留商业授权空间。 - 缺点:企业采用意愿显著下降;AGPL 的网络服务条款常被大厂直接排除。 - 候选 C:主仓宽松许可 + 单独的**可接受使用政策(AUP)**明文禁止代币化用途。 - 优点:兼顾采用率与合规姿态;不靠许可证而靠政策表达边界。 - 缺点:政策无强制力,只具声明与事后追责依据的价值。 **14. 影响面 —— 步 ① 的「多方观测者」(≥3)由谁承担**(**由 §3.7 三步建议第 ① 步直接引出**) - 需具备:观测者之间**互不信任**、网络位置不同(不同云 / 不同地域)、口径一致但**各自独立上报**。 - 候选 A:平台自建 3 个观测点(不同云厂商 + 不同地域)。 - 优点:立刻可做,无需第三方协调;测量口径完全一致。 - 缺点:**同属一个主体 ⇒ 严格说仍是「自证」**,只消掉「单机抖动误判」,没解决「观测者与被观测者同主体」。 - 候选 B:现有 relay 节点互测(每台观测其余节点)。 - 优点:零新增资源;规模越大观测面越广。 - 缺点:**互相观测的流量随节点数 O(n²) 增长**;节点同属一个运营主体时,同样不解决「独立」问题。 - 候选 C:引入独立第三方观测(外部探针 / 节点运营方互测 + 公开口径)。 - 优点:**唯一真正满足「互不信任」的做法**;结果可对外举证(对齐 §3.7.4 第 ② 条)。 - 缺点:引入对外依赖与成本;口径对齐与数据回传需设计。 - 👉 **本文倾向**:现在走 **A**(先把「单点误判」消掉,成本近零),把 **C** 作为全球开放后的目标形态;**B** 只作补充探针,⛔ 不当作「独立观测」。 **15. 成本 / 形态 —— 骨干服务器 3 台还是 4 台**(**由 §3.8.3 引出**) - 事实:BFT 门槛 `n ≥ 3f+1` ⇒ **3 台 `f = 0`**(只容崩溃、不容作恶);容 1 台作恶需 **4 台**,容 2 台需 7 台。 - 候选 A:维持 3 台,并在安全声明里如实写"仅崩溃容错"。 - 优点:省一台机器与一份运维;与当前预算一致。 - 缺点:**无法区分"宕机"与"作恶"**;与 §2.6 的 `N=4 / f=1` 口径冲突 ⇒ §2.6b(节点被攻破)在 B 层**无解**。 - 候选 B:改 4 台,`f = 1`(本文建议)。 - 优点:与 §2.6 口径一致;能容 1 台拜占庭,"多节点共识"的对外表述站得住。 - 缺点:多一台成本与运维。 - 👉 **本文倾向 B**:一台机器的成本远低于"安全声明降级"的代价;4 节点 PBFT 每轮仅 16 条消息,**无性能代价**。 **16. 影响面 / 复杂度 —— A 层共识形态三选一**(**由 §3.8.3 引出**) - 前提:1,000 节点跑经典 PBFT 不可行(`O(n²)` ⇒ 10⁶ 消息/轮)。 - 候选 A:**周期 Merkle root 多签锚定**(骨干多签,1,000 节点可自验)。 - 优点:最省,与 §3.7「链只做周期性信任锚」同一结论;节点零共识开销。 - 缺点:**不是"节点共识"** ⇒ 对外不能说"A 层由 1,000 节点共同出块";信任集中在骨干多签。 - 候选 B:**抽样委员会**(VRF 选 100–200 节点轮值)。 - 优点:兼顾参与度与可跑性;被选中节点数可控。 - 缺点:需实现 VRF 与轮值治理;委员会成员可能被定向攻击。 - 候选 C:**分层共识**(1,000 台分 33 组 × 30 台 ⇒ 组内选代表 ⇒ 33 节点代表层)。 - 优点:语义最接近"全网参与";可随规模扩展。 - 缺点:最复杂;两层共识的最终性延迟叠加;组划分与代表选举需治理规则。 - 👉 **本文倾向 A(先上)→ B(第三方节点起来后)**;C 仅在"必须有全网共识语义"时考虑。 **17. 形态 / 成本 —— 子节点的升格方式三选一**(**由 §3.9 引出**;档位 ①② 已就绪,此处只问 ③ 的升格路径) - 候选 A:**全自动升格**(节点自测入向可达即自动成为中继候选)。 - 优点:零人工、规模越大越省事;天然贴合"全球开放、节点自主加入"。 - 缺点:**自测可被伪造**(节点自称"我可达"即可进候选)⇒ 必须先有 §3.7 的多方观测才能防;且**目录 8 地址上限**不解决就仍然下发不出去。 - 候选 B:**半自动升格**(候选池 + 控制面登记,凭据与目录由控制面下发)——本文建议。 - 优点:与现有"一机一钥 + 单台吊销"体系一致;凭据可控、可回滚;不需要先解决自测可信问题。 - 缺点:有一个人工/审批环节 ⇒ 规模上去后运维成本随候选数线性增长(万级时需批量工具)。 - 候选 C:**第三方节点运营方自行接入**(外部主体带资质接入,签合同与 SLA)。 - 优点:把运维面外移;适合全球开放后的骨干层。 - 缺点:引入对外依赖与合同约束;质量与响应不可控;**影响面超出本平台**。 - 👉 **本文倾向 B(先上)→ A(多方观测落地后放开)**;C 只在"骨干层需要外部主体"时才考虑。 --- ## 6. 与主文档的一致性自查 | 主文档纪律 | 本文推演是否遵守 | 说明 | |---|---|---| | A 层永不出现明文隐私 | ✅ | 场景 1–7 全部路径复核;实名只落 B | | B 层不公开但多节点共识 | ✅ | 场景 6 按 N=4 / f=1 推演容错 | | 窄桥独立加密 + 双人授权 + 留痕 | ✅ | 场景 4 步 6、场景 5 步 2、场景 3 步 2 | | ⛔ 不给低熵字段建盲索引 | ✅ 并补强 | §3.4.3 给出**第二重理由**(截断对低基数字段无效) | | ⛔ 不用 OPE | ✅ | 范围查询走 bucket 化 + 应用层过滤 | | ⛔ 不长期加密上链 | ⚠️ **发现一处张力** | §2.4 冲突一:B 层本身是链 ⇒ 需 §5 第 4 项拍板 | | ⛔ 不自研密码学 | ✅ | 全文以 `HKDF/HMAC/AES-GCM/Shamir` 成熟库为前提 | | ⛔ B 层不整钥存放 | ✅ 并补强 | §3.1 分层 + 场景 6b 组合风险 | | ⛔ key 不用裸明文 | ✅ | 全部 `key_token = HMAC(DK_kv_key, …)` | | ⛔ key/value 域分离 | ✅ | §3.1 域分离硬约束 | | ⛔ 不做代币 / 发行(银发〔2021〕237 号) | ✅ **并已拍板强化** | §2.9 步 7 + §3.6.3:**开源主仓默认零价值凭证能力**,代币/积分类扩展只作境外可选插件 | | **平台范围收窄**(拍板 2) | ✅ | §2.9.1 + 判据 22:平台只做互联与协作,⛔ 不经手资金、内容、法律主体 | | 判据 2 平台不可解 | ⚠️ **表述需修正** | 准确表述是"**平台单方**不可解";2 片串谋可解(§2.3 / §2.5) | | **⛔ 不为了「看起来更去中心」而把功能搬上链**(由拍板 1「现在不做、预留扩展」延伸) | ✅ | §3.7:信誉**只做周期摘要锚定**,实时选路留在链下;⛔ 不逐条上链、⛔ 合约不做实时筛选 | | **链上 / 链下边界**(拍板 5:链的引入时机 = DAO 与在线游戏) | ✅ | §3.12:链的三样能力在 V0 **均有链下等价物**;升级只换「锚落点 / 仲裁方 / 写入权」三处,⛔ 不动数据模型 | --- ## 7. 来源 **本文为推演性内容,不引入新外部事实**;所依赖的事实、条文、实测数据全部来自三份既有文档(主文档 §9 已列全部来源),此处不重复。 **本文新增的判断(自研推演,非搜索所得)** - 7 场景的时序拆解与失败模式矩阵(§2); - **B 层链上删除权的三种解法**(含 b2 变体建议)与**内容哈希可枚举关联**冲突的识别(§2.4); - **"平台不可解"的准确表述 = "平台单方不可解"**,2-of-3 的安全性上限 = "平台与第三方不串谋"(§2.3 / §2.5); - **前端投毒是"平台不可解"体系的第一现实威胁**(§2.7 路径 7); - **密钥分层唯一判据 =「平台是否需要解」**,以及"KMS 对象数 ∝ 租户数(非用户数)"的成本化解(§3.1); - **截断位数与总量的对数关系** `b = ⌈log₂(N/3)⌉`,及"低基数字段截断无效"(§3.4.3); - 规模主表的计算式与 10 / 1 万 / 100 万三档量级(§3.4); - 元数据泄露的**四种攻击模型 + 缓解矩阵**(含匿名 ID 轮换的可行性边界)(§3.5); - **新增 19 条验收判据建议**(判据 15–33,§4); - **中继 / 节点信誉的四条技术判断 + 四层分层方案 + 三步落地建议**(合约不观测 · 缺口是多方观测 · 逐条上链的量级否决 · 共识秒级 vs 选路毫秒级,§3.7); - **覆盖网络多节点身份 / 选路体系的只读取证**(v1.2 新增,⛔ **未改动任何文件**):`src/net/relay/identity.ts`(685 行 · 四层密钥模型 + 离线信任根)· `placement.ts`(210 行 · 毫秒级本地打分)· `network.ts`(289 行 · `network_id` 命名空间)· `join.ts`(435 行 · 一键加入四步)—— 用于支撑 §3.7 判断 2 与 §3.7.5 的「复用而非新建」结论。 - **3 骨干 + 1,000 节点 + 50 万终端的形态推演**(规模账 · 角色分配 · 两处形态硬伤 · 覆盖网络逐项判定,§3.8); - **终端升格为子节点的支持度判定**(三档能力拆分 · 五条代码级硬门 · 容量口径 · 按序要补的五件事,§3.9); - **依赖顺序裁决(优化 vs 做链)**:判据「返工来自同一件事被定义两遍,不来自晚做优化」+ 三条复用点 / 两个口径(§3.10)。 - **账号密码 / 并发登录的落点判定**:密码摘要不上链、登录只上日聚合摘要;1000 万并发登录的瓶颈是 KDF(表见 §3.11.2);链的"写"扩展只能分片、"读"扩展与库相同(§3.11)。 - **纠正 §3.4.2「峰值 TPS」行的换算错误**(年→秒除数须为 `365×86400`;100 万用户正确值为 **95 TPS / 读 951 TPS**,原值偏大 3.65×)。 - **链上 / 链下边界的可替换性证明**(§3.12):链的三样能力 → V0 链下等价物 → 升级时「只换锚落点 / 只换仲裁方 / 只换写入权」;**在线游戏的"链下执行 + 链上结算"与 §3.7 的"链只做周期锚"同构**,同一模式复用(§3.12.2 / §3.12.4)。 **DAO / OPC 场景(v1.1 新增,均为可溯源事实)** - **WOPC(世界 OPC 生态联盟)**:2026-05-28 于厦门国际会展中心成立(金砖国家新工业革命展览会核心配套活动),使命「**建立全球 OPC+DAO 连接协议标准**」;四层星云架构中**连接层**以「TOKEN 经济(连接权凭证)+ 智能合约(全自动价值分配)+ 声誉系统(链上信用凭证)」为核心 —— 来源:海峡导报 / 新浪新闻 / 中国报业网(2026-05) - **DAO 在中国的法律定性与责任**:北京国枫律师事务所《浅谈去中心化自治组织(DAO)的基本概念及其合规监管》—— 「DAO 因代币工具的广泛使用,**目前在中国尚无合法的立足之处**」;与**合伙企业**高度类似(《合伙企业法》第 2 / 6 / 26 条:普通合伙人**无限连带责任**、合伙人**分别缴纳所得税**) - 天元律师事务所《DAO 亦有道》—— 「一旦被认定为合伙(**而这是高概率的**,除非另有架构安排),builder 须就其他 builder 的行为承担**无限连带责任**」;未注册为法人 / 合伙企业的 DAO「**无法合规从事区块链信息服务**」经营;成员**即使已退出**仍可能因链上记录承担责任;**税盾缺失**;中国公民 builder 可能被认定**共同犯罪** - 学术参照:张志坚、何艺华《去中心化自治组织的法律性质及归责路径》,《天府新论》2024 年第 6 期 —— DAO = **新型非法人组织**;「**去中心化理念的再中心化事实**」(矿池 / 发起人 / 漏洞修补三重再中心化);归责采**二分**(实控人员无限连带、一般投资者有限) **⚠️ 提示**:§5 第 1、2、12 项属合规口径问题、**第 13 项属对外承诺**,建议取得执业法律意见后定案。本文为技术推演,不构成法律意见。 --- *相关文档:`分布式数据存储与查询-架构设计与隐私保护方案_20260919.md`(主文档 v1.2)|`分布式数据链路-技术方案与落地路线_20260919.md`(通用判定与三档路线)|`面向公众资产平台与隐私金库-落地方案_20260919.md`(仅存档)*