6.2 隐私交易与数据隐私:藏得住,也查得了 本节摘要:隐私支付的工程核心是一组看似矛盾的诉求:金额与双方对外隐藏,但"钱没被花两次"必须全网可查。本节拆解承诺树、空值器、花费授权三件套如何化解矛盾,给出元数据泄漏的排查清单,并延伸到私有合约状态与合规接口。承接 6.1,通往 6.3 的身份现场。 别以为隐私只是把数据加密 直觉方案是给交易数据加密——但加密后的账本没法验账:验证者既看不到金额,也就无法确认"支出不超过余额""没有重复花费"。混币类方案(把多笔交易搅在一起)只能提供弱关联保护,金额仍可见,分析技术也一直在进化。隐私池要的是更强的性质:对外不可读,对规则可验证——每个旁观者(包括验证合约)都能确认交易合法,却读不出任何内容。把 4.
本节摘要:隐私支付的工程核心是一组看似矛盾的诉求:金额与双方对外隐藏,但"钱没被花两次"必须全网可查。本节拆解承诺树、空值器、花费授权三件套如何化解矛盾,给出元数据泄漏的排查清单,并延伸到私有合约状态与合规接口。承接 6.1,通往 6.3 的身份现场。
直觉方案是给交易数据加密——但加密后的账本没法验账:验证者既看不到金额,也就无法确认"支出不超过余额""没有重复花费"。混币类方案(把多笔交易搅在一起)只能提供弱关联保护,金额仍可见,分析技术也一直在进化。隐私池要的是更强的性质:对外不可读,对规则可验证——每个旁观者(包括验证合约)都能确认交易合法,却读不出任何内容。把 4.1 的承诺、第 3 章的证明系统组合起来,这个矛盾就有了工程解。
第一件:承诺树。用户存入资产时,系统为这笔"票据"生成秘密随机数,构造承诺值并插入一棵公开的 Merkle 树(4.1 节承诺的批量形态)。树上只有承诺哈希,无任何明文——资产的存在公开,内容与归属隐藏。取款或转账时,用户证明"我知道树中某片叶子的原像"(Merkle 路径加原像知识证明),从而证明自己拥有某笔未花费的资产,但不必指出是哪一笔。
第二件:空值器。新问题来了:不指出花了哪笔资产,怎么防止同一笔被花两次?答案是花费时公开一个空值器——由票据秘密确定性派生的唯一标签(比如秘密与序号的哈希)。合约维护一张已花标签表,标签重复即拒绝;而标签本身与票据的对应关系外界无法推算,这就是"查得了重复、藏得住归属"的钥匙。证明系统把整个逻辑打包:证明者同时证明"树里有我的票据""这个空值器正是它的标签""余额守恒"三件事,验证者一无所见却全部信服。
第三件:花费授权。上述每一步都要求证明者持有完整秘密(票据原像、盲化量),零知识性质保证秘密不出场——这就是授权本身。跑一段玩具演算,把三件套的查重逻辑走通:
# 隐私支付三件套玩具演示:承诺树加空值器防双花 import hashlib, secrets def h(*parts: bytes) -> bytes: return hashlib.sha256(b"|".join(parts)).digest() def merkle_root(leaves): # 极简 Merkle 树根(两两拼接哈希) level = leaves[:] while len(level) > 1: if len(level) % 2: level.append(level[-1]) level = [h(level[i], level[i+1]) for i in range(0, len(level), 2)] return level[0] # —— 存入:为两笔资产生成票据并上树 —— notes = [] for i in range(2): secret = secrets.token_bytes(16) # 票据秘密:仅持有者可见 nonce = secrets.token_bytes(8) # 花费序号 leaf = h(secret) # 叶子 = 秘密的承诺 notes.append({"secret": secret, "nonce": nonce, "leaf": leaf}) root = merkle_root([n["leaf"] for n in notes]) print("公开承诺树根:", root.hex()[:20], "……(对外只看得到这个)") def nullifier(note): # 空值器:秘密与序号的确定性标签 return h(note["secret"], note["nonce"]) spent = set() # 合约维护的已花标签表 def try_spend(note): tag = nullifier(note) if tag in spent: return "拒绝:票据已被花费(双花拦截)" spent.add(tag) return "接受:记账,且外界无法知道是哪一笔" print(try_spend(notes[0])) # 第一次花费 print(try_spend(notes[0])) # 同一笔再花:空值器相同,拒绝 print(try_spend(notes[1])) # 另一笔:标签不同,通过 print("已花标签表(公开):", len(spent), "条,全部不可关联到具体票据")
演算里那张"已花标签表"就是隐私池的公开账本:它记录了花费事实,却抹掉了花费对象——隐私与可验证性的并存点正在于此。真实系统里,"树中有票、标签正确、余额守恒"三件事由一份电路证明打包完成,规模在 5.2 节的账本里已经估算过。
三件套解决内容隐私后,5.3 节的第三问(泄漏在哪)成为最难的部分。高频泄漏点逐条过:时间与金额的粒度——固定面额票据(如等额存款凭证)可消除金额指纹,但混批延迟会泄漏时间行为;空值器时序——标签出现节奏刻画用户活跃规律,对策是延迟队列或批量花费;网络层——广播交易的源地址与中继时序,需要独立的流量混淆层,这是账本密码学管不到的地带。证明的公共输入也要审:树根、标签之外若还传了金额区间或费用,都可能被侧信道利用。一份负责任的隐私方案文档,应当把这张清单连同"接受/缓解"状态一起公布。
隐私交易再往前一步是私有智能合约:合约状态整体加密,每笔调用附带状态转移正确性的证明——执行逻辑公开、数据保密,业务上可用于工资单、供应链定价等敏感场景。证明生成成本目前仍是主要瓶颈(合约逻辑越复杂电路越大),通用方案与专用电路的路线之争与 7.2 节的 ZK 虚拟机一脉相承。合规侧的接口在 5.3 节已经铺过:查看键让授权审计方解密指定票据,选择性披露证明让用户对特定对手方开箱——隐私与监管的工程接口已经存在,剩下的是治理设计而非密码学难题。
票据藏的是钱,身份现场要藏的是人:证明"我年满成年""我持有资格"而不出示证件本体。凭据、谓词与匿名凭据的构造,下一站展开。
**问:普通用户需要理解三件套才能安全使用吗?**理论上不需要,实践上建议至少理解一件——备份。票据秘密(承诺原像)就是资产本身:丢了秘密等于丢了资产,备份泄露等于资产可被冒领。产品设计的功课是把"秘密即资产"翻译成用户能懂的安全提示,工程师的功课是在代码里把秘密的生成、传输、存储全部按最高密级对待。
**问:隐私池能不能被监管接受?**技术接口已经就位——查看键让授权审计方按凭据解密指定票据,选择性披露让用户向指定对手方开箱。监管接受度取决于治理流程(谁有权查看、留痕如何)而非密码学,已有司法辖区在受监管框架内试点。评估隐私方案合规性时,直接问"查看键治理文档在哪",比争论"该不该隐私"更有效率。
**问:把金额藏起来的同时,怎么防洗钱规模化的结构化拆分?**这是隐私系统的经典张力。技术侧的可选对策包括分桶限额、异常模式标记(对承诺树统计特征做链上不可见、监管侧可见的分析)、提款冷却期。每条对策都侵蚀一部分隐私——边界画在哪里是政策问题,工程的任务是让每个选择都可配置、可审计。