GhostPool:加密内存池中的身份元数据隐藏方案

文章提出 GhostPool,用零知识证明、加密绑定和共享 nullifier 命名空间,解决加密 mempool 中 sender 与 nonce 被隐藏后导致的“验证失明”问题。

摘要

Encrypted mempools 在包含前会隐藏交易 内容,但通常不会隐藏身份关键的准入元数据。在许多设计中,准入路径仍然会暴露诸如 sendernonce 之类的字段——或者一个承担相同实际角色的公开 envelope signer——因为这些字段正是实现动态 mempool 检查所必需的。

如果 sender 和 nonce 在没有替代方案的情况下被隐藏,节点就会失去评估 nonce 和偿付能力所需的信息。准入会变成盲目的。

GhostPool 用以下机制替代公开的 (sender, nonce) 准入检查:

  • 一个 root-bound zero-knowledge 准入证明,用于加密交易,
  • 一个 ciphertext-to-payload commitment binding
  • 以及一个覆盖加密交易和明文交易的 shared nullifier namespace

主构造是在标准 account model 中陈述的,在该模型下,nonce 稳定性给出了最清晰的正确性论证,而协议自然支持 head-of-line nonce。GhostPool 保留 network-layer 的来源和经济元数据,例如 gas limits 和 fee parameters 不变。它是一个准入层协议,可与诸如 Shutter-style threshold encryptionmultiparty delay encryption用于 pending-transaction privacy 的 batched threshold encryption 以及近期的 public-envelope encrypted mempool proposals 等 encrypted-mempool 设计组合使用。

1. 引言

1.1 Encrypted mempools 隐藏 payload,不隐藏准入元数据

Encrypted mempools 现在是一个广泛的设计空间,而不是单一提案。示例包括 threshold-encrypted mempoolspublic-envelope encrypted mempools,以及基于 multiparty delay encryptionbatched threshold encryption 的学术提案。

在这些方法中,主要目标通常是在协议定义的解密点之前隐藏 transaction contents。通常仍然暴露的是 admission interface,以及由此带来的身份关键元数据,如 sender 和 nonce。

这正是 GhostPool 所针对的层。

只要 sender 和 nonce 仍然可见,encrypted mempools 就能保留动态准入检查——但同时也保留了 account-level 泄露。当前的 universal enshrined encrypted mempool proposal 例如,保留了一个拥有自己 fee-payment 和 nonce 语义的公开 envelope,并不针对用户隐私。GhostPool 解决的是互补问题:private admission

1.2 Validation blindness

接收交易的节点至少必须检查四件事:

  1. 格式:envelope 结构、字段大小、有效编码
  2. 授权:来自 sender 的有效签名
  3. Nonce:交易指向 sender 的下一个可用 nonce
  4. 偿付能力:账户能够覆盖交易的最坏情况成本

前两项是 static。后两项是 dynamic:它们需要以 sender 为键的账户查询。

这会直接带来一个权衡:

  • 如果 sender 和 nonce 保持可见,节点就能保留动态准入检查,但加密提交仍然会泄露 account-level 活动。
  • 如果 sender 和 nonce 在没有替代方案的情况下被隐藏,节点就再也无法执行 nonce 或偿付能力检查。

我将这种失效模式称为 validation blindness

这与更广为人知的 mempool DoS 文献不同,后者研究的是在交易身份和价格已经可见的情况下的准入、驱逐和锁定攻击。GhostPool 的问题更简单也更根本:在 private admission 下,如果不通过密码学方式替换,动态检查本身就会消失。

1.3 协议陈述

GhostPool 通过将公开的 (sender, nonce) 检查替换为以下机制,来解决 private head-of-line admission 的 validation blindness:

  • 一个 root-bound zero-knowledge admission proof
  • 一个通过 public payload commitment 实现的 ciphertext binding
  • 以及一个跟踪加密和明文交易之间 nonce-slot 占用情况的 shared nullifier namespace

该协议首先在标准 account model 中陈述,在该模型下,nonce-stability 论证最简单,且被跟踪的 slot 是原生 account nonce。在该设置中,可以从明文的 encrypted-admission path 中移除 sender 和 nonce,而不会重新引入 validation blindness。

该协议刻意聚焦于:

  • head-of-line nonce
  • 能够为 ciphertext 认证 payload commitment 的 encrypted-mempool 格式,
  • 以及公开的 fee/gas 元数据。

第 7 节讨论了更广泛的 account model,以及 GhostPool 不隐藏的其余元数据。

2. GhostPool 概览

对于标准 account model,GhostPool 依赖一个简单的单调性事实:

如果一个账户的 nonce 自证明生成以来没有变化,那么它的 balance 只可能保持不变或增加。

因此,偿付能力证明不需要在每个新区块都重新生成。它只需要保持相关 nonce slot 尚未被占用。

GhostPool 通过为每个 (account, nonce) 对分配一个确定性的 nullifier,而不在加密准入路径中暴露账户,把 stale-proof 问题转化为 slot-tracking 问题。

GhostPool admission flow

图 1。GhostPool 用一个 root-bound proof 加上一个 slot nullifier 替代公开的 (sender, nonce) 准入检查,从而在不重新引入 validation blindness 的情况下,将 sender/nonce 从加密准入路径中移除。

3. 协议

3.1 Envelope 格式

提交的加密交易采用一个 envelope 的形式:

E = (ciphertext, payload_commitment, N, π_leaf, ref_root, public_meta)

其中:

  • ciphertext 是加密后的 payload,
  • payload_commitment 是对隐藏 payload 的公开 commitment,
  • N 是 canonical nullifier,
  • π_leaf 是 leaf proof,
  • ref_root 是证明生成时所依据的确切 state root,
  • public_meta 包含非私密的传输和池管理字段。

在基础构造中,public_meta 还包含为打包和排序而有意保留明文的执行相关字段,例如:

  • gas_limit,
  • max_fee_per_gas,
  • max_priority_fee_per_gas,
  • 以及任何过期或路由提示。

GhostPool 不要求最新 state root。它要求一个确切 root 和一个有界的新鲜度规则。

3.2 Leaf proof

Leaf proof π_leaf 在不泄露 sender 或 nonce 的情况下证明以下内容:

  1. 授权:隐藏交易由对应隐藏账户的有效密钥签名。
  2. Nonce 有效性:链上该账户的 nonce 等于交易中使用的隐藏 nonce。
  3. 偿付能力:账户余额足以覆盖交易声明的最坏情况执行成本,即其 value 加上由公开 gas 和 fee 字段导出的 fee 上界。
  4. 公开字段一致性:任何有意保留在明文中的执行相关字段与隐藏交易中的对应字段一致。
  5. Nullifier 绑定:公开 nullifier N 正确地由同一隐藏密钥和隐藏 nonce 导出。
  6. Payload commitment 绑定:隐藏交易对公开 payload_commitment 做出 commitment。
  7. Anchor 绑定:所有 state witness 都是在确切的 ref_root 上证明的。

该证明在固定 state root 上建立授权、nonce 有效性、偿付能力和 slot 绑定。关于最新 base fee 的新鲜性和当前可包含性仍然是由 proof 之外的 mempool policy 决定的。

对于 Ethereum-style fee semantics,最自然的证明语句是使用交易声明的 fee bound 的 worst-case cost bound,而不是关于最新 base fee 下当前可包含性的断言。

3.3 Ciphertext 绑定

单独的有效证明并不充分。节点还必须知道该证明指向的是与公开 ciphertext 同一个隐藏交易

GhostPool 将这种绑定拆分为两部分:

  • 在 proof 内部:隐藏交易 → payload_commitment
  • 在 encryption layer 内部ciphertextpayload_commitment

因此,外层的 encrypted-mempool 格式必须为 ciphertext 认证一个 payload commitment——例如通过 associated data、authenticated wrapping,或等价机制。GhostPool 不要求某一种特定的加密方案。它要求这个经过认证的 commitment Hook。

这消除了这样一种攻击:用户为一个隐藏交易证明了有效性,却附加了另一个交易的 ciphertext。

3.4 Nullifier

每个 nonce slot 都被分配一个 canonical nullifier:

B_slot = HashToCurve("ghostpool/nullifier/v1" | chainid | address | nonce)

N = sk · B_slot

其中 sk 是 sender secret key,address = Addr(pk)

GhostPool 不使用诸如 H(address | nonce) 的简单 hash,也不使用任何观察者可以从可见状态直接重新计算的确定性公开产物。设计目标是 slot uniqueness without public enumerability from visible state alone

该 nullifier 有四个用途:

  • slot uniqueness:相同的 (account, nonce) 产生相同的 N
  • unforgeability:没有 sender secret key,第三方无法为该 slot 生成有效 nullifier,
  • non-enumerability from public state:即使猜到 (address, nonce),也不足以用观察到的 N 来检验猜测,
  • shared slot semantics:同一个 slot key 同时用于 encrypted 和 plaintext 流程。

在直观层面,观察者可以从公开数据推导出 B_slot,但在没有 sender secret key 或有效 public certificate 的情况下,无法判断一个观察到的 N 是否属于该 slot。

HashToCurve 应实现为具有适当 domain separation 的 constant-time hash-to-curve 或 encode-to-curve 方法;见 RFC 9380。协议层面的 nullifier 是 group element N 的 canonical 编码。实现上也可以为了本地索引而额外对其做 hash。

这种构造与 PLUME 等确定性公开产物设计相邻,但 GhostPool 将 nullifier 具体用作 mempool admission 的 nonce-slot key

3.5 明文路径

GhostPool 不强制将明文交易纳入加密准入电路。

明文交易继续使用普通 mempool 路径,sender、nonce 和 fee 字段保持可见。唯一的额外要求是它还必须携带:

  • 其可见 nonce slot 对应的 canonical nullifier N,以及
  • 一个轻量级的 slot certificate π_slot,证明:

pk = sk · GN = sk · B_slot

等价地,

log_G(pk) = log_B_slot(N)

验证者从普通交易签名中恢复 pk,根据 (address, nonce) 计算 B_slot,并将 π_slot 作为 DLEQ / Chaum–Pedersen 关系进行检查。这比完整的 leaf proof 轻得多,并且使用标准机制;见 RFC 9497

这是一条针对同一 nullifier 对象的公开认证路径,而加密交易则在 leaf circuit 内对其进行证明。它也为明文和加密交易提供了一个共享的 slot namespace。

3.6 准入流水线

当节点接收到一个加密 envelope E 时,它按照从最便宜到最昂贵的顺序执行检查:

  1. Envelope sanity:结构有效、必需字段齐全、大小限制被满足。
  2. Nullifier 预过滤:检查 N 是否与现有池条目冲突。
  3. Anchor freshness:验证 ref_root 是否 canonical 且足够新。
  4. Ciphertext commitment 检查:验证 ciphertext 是否认证了声明的 payload_commitment
  5. Leaf proof verification:验证 π_leaf
  6. Replacement finalization:如果 policy 允许,则替换同一 nullifier 的旧条目。

该顺序的选择是为了在进行 proof verification 之前拒绝格式错误或过期对象。

4. Shared nullifier namespace

GhostPool 的架构核心在于:加密明文交易使用不同的准入路径,但在一个共享 slot namespace 上汇合。

Shared nullifier namespace and slot lifecycle

图 2。加密和明文交易使用不同的准入检查,但在一个共享 nullifier namespace 和一个 spent-nullifier 视图上汇合。

正是这个共享 namespace 使 nonce-stability 论证能够在实践中使用。一个 pending 的加密 proof 只要满足以下条件就保持有效:

  • 它的 reference root 仍足够新,
  • 且它的 nullifier 尚未进入 spent set。

在部署中,plaintext nullifier artifacts 必须在 reorg horizon 上可用,以便 spent set 仍然可重建。这些 artifacts 如何持久化是传输或格式选择的问题。准入逻辑本身不变。

5. 池 policy

5.1 要求

进入 mempool 的每笔交易——无论加密还是明文——都必须携带一个 canonical nullifier:

  • 对于 加密交易,nullifier 正确性在 π_leaf 内建立;
  • 对于 明文交易,nullifier 正确性通过普通签名路径加上 π_slot 建立。

因此,GhostPool 依赖一个单一的 slot-tracking 不变量:

任何能够消耗被跟踪 nonce slot 的事件,都必须体现在同一个 slot-consumption 视图中。

在基础构造中,这一点可以直接实现,因为加密和明文交易都参与 shared nullifier namespace。

5.2 新鲜度窗口

GhostPool 只接受 ref_root 仍处于最近 W 个 canonical block roots 之内的加密证明。

概念上,加密条目在以下条件下保持 pending:

  • ref_root 处于窗口内,
  • N ∉ spent

过期仅适用于加密条目。明文条目不携带 root-bound GhostPool leaf proofs。

5.3 替换

替换是定义在 shared nullifier slot 上的,而不是定义在可见 sender 字段上。

如果两个池条目携带相同的 nullifier,它们就竞争同一个底层的 (account, nonce) slot。若本地 policy 允许,新条目可以替换旧条目。

GhostPool 通过 nullifier 标准化 slot equality。它并不在明文和加密流程之间标准化一条统一的 fee-bump 规则。

5.4 Reorgs

当链发生 reorg 时,已包含于回退区块中的交易不再最终确定,因此它们的 nullifier 必须从 spent set 中移回。

节点维护一个按区块划分的 nullifier 更新日志。发生 reorg 时:

  1. 逆序回放被回退的区块,
  2. 正向应用新的 canonical blocks,
  3. 重新评估其新鲜度或 spentness 发生变化的 pending 加密条目。

6. 聚合与传播

当 leaf proofs 很大时,递归 STARK 聚合是 GhostPool 的自然传播层。

如果加密 envelope 与其 leaf proofs 一起被天真地传播,那么 proof 带宽和全网验证工作都会随着吞吐量快速增长。 Recursive-STARK-based bandwidth-efficient mempool 中提出的递归传播模式适用于这种场景:节点先验证新对象一次,然后定期对它们当前已知的有效对象发布递归证明。

GhostPool 在 加密路径 上使用该模式。

一个首次接收加密 envelope 的节点只验证一次其 leaf proof。随后,在每个 tick,它生成一个覆盖本地视图中所有仍然有效的加密 envelope 的 recursive STARK,并将该递归证明与该 peer 尚未见过的任何加密 envelope 一起转发给 peers,但不包含它们原始的 leaf proofs。

递归证明的 public input 是被覆盖的加密 envelope 的一个集合描述符——例如 bitfield 或 envelope hashes 列表。递归 circuit 随后接收:

  • 零个或多个带 leaf proofs 的加密 envelope,
  • 零个或多个同类型的其他 recursive STARK,
  • 以及一个 discard set,

并证明所有直接提供的 envelope 以及所有递归导入集合的并集,在减去被丢弃的 envelope 后,都是有效的。

这种“union minus discard”结构与 GhostPool 非常契合。它允许 aggregate 随着 mempool 演化:

  • ref_root 已经落出新鲜度窗口的 envelope 可以被丢弃,
  • 其 nullifier 已进入 spent set 的 envelope 可以被丢弃,
  • 被同一 slot 的更新交易替换的 envelope 可以被丢弃。

如果一个节点当前有 {Tx1, Tx2, Tx3},另一个节点有 {Tx2, Tx3, Tx4},那么它们的递归证明可以合并成一个更大的证明,覆盖并集 {Tx1, Tx2, Tx3, Tx4}。接收多个部分重叠 aggregate 的 builder 也可以完全以相同方式进行组合。

Recursive aggregation on the encrypted path

图 3。递归聚合将重叠的加密交易集合合并为一个关于其并集的单一证明,并通过 discard set 移除失效对象。

这使 GhostPool 在加密路径上具有两个具体优势。

首先,它减少了 全网验证工作。一个新的加密 envelope 在首次进入网络时仍然需要被检查一次,但下游节点越来越多地验证的是覆盖 envelopes 集合的递归 coverage proofs,而不是独立地重新验证每个 leaf proof。

其次,它减少了 proof 传播开销。每个加密 envelope 的主体仍然需要在网络中传播,但 proof 流量变成了 按 tick、按 peer,而不是 按 envelope。这就是递归构造的主要带宽收益:对象数据随 envelope 数量扩展,而 proof 开销随 tick rate 和 peer 数量扩展。

7. 讨论

7.1 更广泛的 account model

nonce-stability 论证在标准 account model 中最简单,因为外发交易既是消耗 nonce 又是减少 balance 的机制。

EIP-7702 说明,一旦引入 delegated execution paths,这种简单性就不再保持不变。在这些场景中,仅凭 nonce 稳定性就无法再推断原生 balance,而被跟踪的 slot 可能会通过非普通 GhostPool-tracked transactions 的 authorization paths 被消耗。

这改变了协议需要跟踪的对象。一个自然的恢复方向是将 native-balance solvency 替换为 escrow-style solvency object,并相应扩展 slot-consumption tracking。准入架构本身不变。

7.2 Transaction chains

基础协议仅支持 head-of-line nonce

如果用户想为 nonce nn+1n+2 排队 private transactions,则后面的交易无法独立地针对当前链上状态进行证明。从 n+1n 的 nullifier 的一个天真的依赖指针会重新引入 linkage。

因此,private queued transaction chains 需要另一层机制,最可能的是对可接受的 parent nullifier 做 set-membership 或 dependency proof。

7.3 经济元数据与 fingerprinting

GhostPool 在加密准入路径中隐藏 sender 和 nonce,但 经济元数据 仍然是一个显著的隐私风险。Fee parameters 和 gas limits 可以作为强统计指纹,并且当它们与 ciphertext size、timing 以及应用特定行为等其他可观察特征结合时,会变得更加暴露。

隐藏经济元数据要困难得多,因为 builders 在排序和打包时需要它们。更重要的是,像 OREHE 这样的标准密码学思想在公开提交场景下并不能解决这个问题。如果任何人都可以生成加密或与 comparison interface 交互,那么小域元数据仍可能通过探测被恢复:加密猜测、比较结果,并推断底层值。

设计一种既能支持公开提交、builder incentives 和 block construction 的 fee 和 gas 保密性,仍然是一个开放问题。GhostPool 将其视为单独的工作。

8. 结论

Encrypted mempools 已经有了可信的设计,可以在 inclusion order 固定之前隐藏交易 内容。它们通常尚未提供的是一种私密方式,来决定一个加密交易是否首先是 admissible,而不重新引入 validation blindness。

GhostPool 填补了这一空白。

在其基础范围内——标准 account model 下的 head-of-line nonce admission,并且位于认证 payload commitment 的 encrypted 格式中——GhostPool 用一个 root-bound ZK proof 加上一个覆盖加密和明文交易的共享 nullifier namespace,替代公开的 (sender, nonce) 准入检查。这在保留语义准入检查的同时,将身份关键的准入元数据从明文加密准入路径中移除。

附录

以下内容均为可选。它使提案更易于实现和审阅,但删除后不会改变核心叙述。

附录 A. 记号与参数

  • h:节点观察到的当前头部区块高度
  • W:新鲜度窗口(按区块计)
  • R_h:窗口内 canonical block roots 的集合,例如 {root[h-W], ..., root[h]}
  • ref_root:在 π_leaf 内使用的确切 root
  • payload_commitment:对隐藏交易 payload 的公开 commitment
  • sk, pk:签名私钥/公钥
  • address = Addr(pk):账户地址
  • nonce:账户 nonce
  • HashToCurve(·):带 domain separation 的 hash-to-curve 或 encode-to-curve 函数

B_slot 的推荐 domain separation 输入:

  • protocol domain string,例如 "ghostpool/nullifier/v1"
  • chainid
  • address
  • nonce

附录 B. 非正式证明陈述

B.1 加密 leaf proof 关系

Public inputs

  • payload_commitment
  • N
  • ref_root
  • 来自 public_meta 的公开 fee 和 packing 字段

Witness

  • sk, pk, address, nonce
  • 隐藏交易字段(to, value, gas_limit, max_fee_per_gas, max_priority_fee_per_gas, calldata 等)
  • 签名材料
  • 位于 ref_root 下的账户和 state witness

Statement

证明者展示一个 witness 的存在,使得:

  1. address = Addr(pk)
  2. 隐藏交易签名在 pk 下可验证
  3. nonce(address; ref_root) = nonce
  4. balance(address; ref_root) ≥ worst_case_cost(hidden_tx)
  5. 公开 gas 和 fee 字段等于隐藏交易中的对应字段
  6. payload_commitment = Commit(hidden_tx)
  7. B_slot = HashToCurve("dst" | chainid | address | nonce)
  8. N = sk · B_slot

B.2 明文 slot certificate 关系

Public inputs

  • pk(从普通交易签名中恢复)
  • B_slot(根据可见 (address, nonce) 计算)
  • N

Witness

  • sk

Statement

证明:

log_G(pk) = log_B_slot(N)

这是一个标准的 DLEQ / Chaum–Pedersen 语句;见 RFC 9497

附录 C. Slot certificate 细节

在素数阶群上,标准的 Chaum–Pedersen 证明可按如下方式证明离散对数相等:

  • 证明者知道 sk,使得 pk = sk · GN = sk · B
  • 证明者采样随机数 r 并计算承诺:

a_1 = r · G, a_2 = r · B

  • 验证者给出挑战 c
  • 证明者响应:

z = r + c · sk

  • 验证者检查:

z · G = a_1 + c · pk

以及

z · B = a_2 + c · N

Fiat–Shamir 变换可使其非交互化。

附录 D. 实践说明

  • 一个自然的起点是 W ∈ [32, 128] 个区块。
  • 存储开销主要是:
    • pending_map,受 mempool 大小限制
    • spent_set,受为恢复和 reorg 安全而跟踪的近期链跨度限制
  • 最昂贵的工程点很可能是加密 leaf proof,尤其当实现将 secp256k1-style authorization relations 保留在 proof system 内时。
  • 钱包支持可能需要暴露以下之一:
    • 直接的 nullifier-generation 支持,
    • 或者与所选 DLEQ 实现兼容的通用“prove slot certificate”路径。
  • 原文链接: ethresear.ch/t/ghostpool...
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
以太坊中文
以太坊中文
以太坊中文, 用中文传播以太坊的最新进展