Grin 中的 Switch Commitment(秘诺切换):Pedersen 承诺的隐私与绑定性安全阀设计解析
区块链Web3【免费下载链接】grinMinimal implementation of the Mimblewimble protocol.项目地址https://gitcode.com/gh_mirrors/gr/grin点击查看免费下载导读本文围绕 GrinMimblewimble 协议的最小化实现文档库中的 doc/switch_commitment.md 展开系统讲解承诺方案Commitment Scheme这一密码学基础概念以及 Grin 如何通过Switch Commitment秘诺切换技术在保持 Pedersen 承诺完美隐匿性的同时为绑定性被意外破解这一极端灾难场景预留一个向后兼容的安全开关。读完本文你将掌握承诺方案的两大核心属性隐匿性与绑定性及其安全权衡、ElGamal 承诺与 Pedersen 承诺的关系并能结合 keychain/src/keychain.rs、core/src/libtx/build.rs 等源码理解 Grin 中秘诺切换的实际实现方式。一、承诺方案把秘密锁进盒子里在密码学中承诺方案Commitment Scheme可以形象地理解为一个带锁的盒子你可以把一样东西放进盒子里例如一张写着秘密数字的纸条锁上锁然后把盒子交给另一个人或公之于众。对方此刻并不知道盒子里的秘密数字是什么而当你日后决定公布这个秘密、并希望证明这确实是我最初想好的那个秘密而不是后来改的时你只需要把盒子的钥匙交给对方即可对方打开盒子将盒内的秘密与你刚刚公布的数字进行比对确认你自锁上盒子以来从未更改过秘密。这就是承诺commit的含义你在事先对秘密数字做出承诺那么在承诺生成与公开揭示之间的任何时间点你都无法再更改它。1.1 哈希承诺最朴素的实现一个简单的承诺方案可以借助密码学哈希函数实现。例如 Alice 和 Bob 要玩猜数字游戏Alice 想好了一个秘密数字29。在游戏开始前Alice 计算hash( 29 r )并把结果公布给 Bob。其中r是一个随机选择的致盲因子Blinding Factor。它之所以必要是因为如果没有rBob 完全可以把游戏中所有可能的数字逐一哈希再与 Alice 公布的哈希值比对从而提前猜出答案。游戏结束时Alice 只需公布秘密数字29和致盲因子rBob 自己重新计算哈希即可验证Alice 在游戏过程中没有偷换数字。1.2 Pedersen 承诺具有同态性的进阶方案更高级的承诺方案可以具备额外性质。例如 Mimblewimble 与机密交易Confidential TransactionsCT大量使用了Pedersen 承诺它是一种同态homomorphic承诺。借用上面盒子的比喻你可以把两个已上锁的盒子盒子1 与 盒子2相加得到一个仍然上锁的新盒子日后打开这个新盒子时里面装着的秘密恰好是盒子1 与盒子2 内秘密的总和。在现实世界中两个盒子相加听起来不可思议但在椭圆曲线上这一性质可以借助运算规则完美实现。关于 Pedersen 承诺在 Grin 中如何使用包括致盲因子、超额值与内核偏移等细节可进一步阅读 doc/intro.md《Introduction to Mimblewimble》。二、承诺方案的两大属性与安全级别无论哪种承诺方案都可以从两个维度衡量其安全性强弱则因方案类型而异隐匿性Hidingness或称机密性 Confidentiality承诺方案对秘密的保护程度。回到盒子比喻攻击者没有钥匙时要打开盒子从而得知秘密数字需要付出多大代价绑定性Bindingness攻击者是否以及有多难能找到另一个不同的秘密使其产生完全相同的承诺。若能做到攻击者日后就能把承诺打开成另一个秘密从而破坏承诺的绑定关系。2.1 两种安全强度计算性 vs 完美性对于上述两个属性可以区分出不同的安全级别。最常见的两种组合是完美绑定perfectly binding 计算隐匿computationally hiding计算绑定computationally binding 完美隐匿perfectly hiding。这里的计算computationally是指该属性由底层数学问题的难度来保障——以现有的计算能力在合理时间内无法求解即今天无法被破解因为现实世界的计算资源是有限的而完美perfectly则是指即使攻击者拥有无限计算能力也不可能破坏该属性。2.2 一个根本性的互斥两者不可兼得需要特别强调的是任何承诺方案都不可能同时做到完美绑定和完美隐匿。这可以用一个思想实验来证明假设攻击者拥有无限计算能力他可以对所有可能的值以及所有可能的致盲因子逐一生成承诺直到找到一个与目标承诺相同输出的输入对。此时若该方案是完美绑定的即不存在两个不同的值产生同一承诺那么这个匹配的输入值就是唯一的——攻击者据此可以直接识别出承诺内的原始值隐匿性随之被破坏反之若方案是完美隐匿的则必然存在多个输入值对应同一个承诺否则无限算力的攻击者只需遍历所有可能值即可破解这又意味着方案不可能完美绑定。结论永远是妥协两个属性不可能同时获得完美安全一个属性若达到完美安全另一个至多只能达到计算安全。2.3 加密货币视角隐匿性与绑定性的不同角色在面向隐私的加密货币如 Grin中这两个属性的意义截然不同隐匿性隐私价值承诺方案被用来保护交易内容。发送方承诺自己要发送的币量但对公众而言具体金额必须保持私密——这依赖承诺方案的隐匿性。绑定性经济价值任何交易创建者都不能在事后把自己的承诺改写成另一个交易金额。如果可能攻击者就能在某个 UTXO未花费交易输出中花费超出先前承诺的金额从而凭空铸造新币更糟的是由于金额本身被隐藏这种通胀行为甚至可能无法被发现。因此加密货币的合理诉求是两个属性都必须在整个生命周期内持续安全。即便如此仍然必须做出选择——到底采用哪种承诺方案。2.4 看似艰难的取舍其实答案清晰如果要二选一哪个属性需要完美安全哪个只需计算安全换句话说假如承诺方案意外被攻破我们更应当优先保住哪一个——经济健全性杜绝隐藏通胀还是隐私保证隐私永不泄露仔细分析会发现答案并不难绑定性只在方案真正被攻破的那一刻才需要是完美的。在此之前即使只是计算绑定也足够安全。而且绑定只影响交易创建时这一时点不会追溯影响过去的交易。隐匿性则必须永远得到保证。因为一旦承诺方案被攻破攻击者可以回溯整条链解除历史交易的致盲从而追溯性地破坏所有过往交易的隐私。也就是说对隐私导向的加密货币而言隐匿性需要永久完美绑定性只需在灾难时刻完美。这正是 Switch Commitment 设计的出发点。三、Pedersen 承诺的属性为什么需要一道安全开关Pedersen 承诺的具体形式为v*H r*G其中v是输入/输出的金额r是致盲因子H与G是椭圆曲线上的两个生成点。Pedersen 承诺是计算绑定且完美隐匿的对于给定的承诺值v*H r*G可能存在另一对不同的r1、v1使得二者之和相同。即使你拥有无限算力、遍历所有可能的取值也无法分辨哪一对才是原始输入因此是完美隐匿。那么问题来了如果 Pedersen 承诺的绑定性被意外破解该怎么办3.1 常规思路的困境换方案意味着全民搬币一般加密货币面对承诺方案被攻破时最直接的反应是更换承诺方案。但这带来一个严峻问题更换方案后必须用新方案重新创建交易输出资金才能重新获得安全保障——也就是说每一位持币者都必须把自己的币转移到新的交易输出。没有转移的币就无法享受新承诺方案的保护。更关键的是这一切必须发生在方案真正被大规模攻破之前否则既有的 UTXO 将无法再被假定为包含正确的金额。3.2 Switch Commitment只换验证方式不换承诺本身针对这一困境《Switch Commitments: A Safety Switch for Confidential Transactions》秘诺切换论文给出了一个精妙的解决方案这类承诺允许仅通过改变揭示/验证流程来改变承诺的属性而完全不需要改变承诺的创建方式。你切换到一套新的验证方案并且它与切换发生之前很久就创建出来的承诺向后兼容。这就是switch切换一词的由来未来可以像拨动开关一样仅仅改变验证程序就能改变承诺在绑定性与隐匿性上的强度而且这种切换对今天创建的承诺依然有效。四、ElGamal 承诺完美绑定的预备方案为了说清楚 Switch Commitment 的原理需要先引入一个新的承诺方案ElGamal 承诺。它与 Pedersen 承诺结构非常相似只是额外增加了一个元素——由致盲因子r与第三个生成点J相乘得到v*H r*G , r*JElGamal 承诺是完美绑定的按照互斥原则它只能做到计算隐匿。关键洞察在于如果我们把额外的r*J字段存储下来但暂时忽略它那么v*H r*G这部分完全可以继续当作普通 Pedersen 承诺使用等到未来某一天我们决定同时验证完整的 ElGamal 承诺就可以立刻获得完美绑定的保护。4.1 早期 Grin 的做法显式存储 switch_commit_hash在主网上线之前的 Grin 早期版本 中正是采用了上述思路将r*J的哈希值即switch_commit_hash附加到交易输出上。这样日后无需改动既有输出即可验证完整的 ElGamal 承诺。但这一方案有一个明显的代价每个交易输出因此增加了 32 字节的体积。对于一条不断累积 UTXO 的公链来说这是一笔不小的存储开销。4.2 Tim Ruffing 的优化把 ElGamal 承诺嵌入致盲因子幸运的是Mimblewimble 邮件列表上的Tim Ruffing最初由Pieter Wuille提出随后给出了一个更漂亮的方案既保留同等优势又无需为每个输出额外存储任何字段。普通的 Pedersen 承诺是v*H r*Gv为输入/输出金额r为真正随机的致盲因子H、G为曲线上的两个生成点。优化思路是让r不再是完全独立的随机数而是由另一个随机数r派生而来——先计算一个 ElGamal 承诺v*H r*G , r*J再将其哈希结果加到r上得到最终致盲因子r r hash( v*H r*G , r*J )其中J是曲线上额外的第三个生成点。这样构造出的r依然是完美有效的致盲因子——因为它仍然随机分布、无法被外界预测。但同时r的构造过程已经内嵌了一个 ElGamal 承诺即哈希括号中的v*H r*G , r*J。未来一旦需要强化绑定性验证方只需校验这个嵌入的关系即可。这个巧妙的想法使得后续 pull requests 得以从交易输出中移除switch_commit_hash将秘诺切换能力折叠进 Pedersen 承诺本身不再占用任何额外字节。五、Grin 中的源码级实现从当前仓库的源码看Switch Commitment 已经贯穿 Grin 交易构建、密钥派生与范围证明rangeproof的各个环节。5.1 SwitchCommitmentType一枚可拨动的开关在 keychain/src/types.rs 中定义了秘诺切换的类型枚举并提供了与u8的双向转换0 对应None1 对应Regularpub enum SwitchCommitmentType { None, Regular, }这正对应文档中当前使用 Pedersen 承诺、但已内嵌 ElGamal 构造的Regular模式以及不启用切换的None模式。Keychaintrait 的derive_key、commit、sign等接口都接收SwitchCommitmentType参数见 keychain/src/keychain.rs。5.2 密钥派生调用底层 blind_switch在 keychain/src/keychain.rs 中derive_key依据切换类型分派match switch { SwitchCommitmentType::Regular { Ok(self.secp.blind_switch(amount, ext_key.secret_key)?) } SwitchCommitmentType::None Ok(ext_key.secret_key), }Regular模式会调用底层secp的blind_switch——这正是文档所述致盲因子由随机r加上 ElGamal 承诺哈希计算得出的落地实现对应 secp256k1-zkp 库commitment/main_impl.h中的blind_switch逻辑。而commit则是先derive_key再secp.commit(amount, key)见 keychain/src/keychain.rs。5.3 交易构建与区块奖励一律使用 Regular在交易构建器 core/src/libtx/build.rs 中无论是普通输入input还是 coinbase 输入coinbase_input都通过SwitchCommitmentType::Regular生成承诺输出构建output同样显式使用Regular见 core/src/libtx/build.rs并配合注释TODO: proper support for different switch commitment schemes——表明当前所有交易输出统一采用内嵌秘诺切换的 Pedersen 承诺。区块奖励输出也不例外core/src/libtx/reward.rs 中计算reward(fees)后同样以SwitchCommitmentType::Regular生成承诺保证 coinbase 输出与其他输出使用同一套安全属性。5.4 范围证明与输出结构不再有 32 字节负担范围证明的创建与回放rewind流程中SwitchCommitmentType也被嵌入证明消息proof message用于钱包找回金额、派生路径与切换类型见 core/src/libtx/proof.rs 的create以及 core/src/libtx/proof.rs 的rewind。同时在 core/src/core/transaction.rs 中Output结构只包含输出标识features commitment与范围证明proof两个字段并不存在独立的switch_commit_hash字段——这正是 Tim Ruffing 方案生效的直接证据秘诺切换能力被压缩进了致盲因子的构造过程每个输出不再承担额外的 32 字节。5.5 测试与佐证仓库中的测试同样印证了上述实现core/tests/transaction.rs 在构建交易测试中显式使用keychain::SwitchCommitmentType::Regular生成承诺与范围证明chain/tests/process_block_cut_through.rs 在区块处理的集成测试中以Regular模式生成 60 亿金额的承诺chain/tests/mine_simple_chain.rs 在挖矿测试中同样使用Regular构建输入输出。这些测试表明从单个输出、到交易、再到区块处理的全链路Grin 都默认采用内嵌秘诺切换的 Pedersen 承诺。六、结论为灾难预留的一层额外保险综上所述Grin 与其他隐私加密货币一样使用 Pedersen 承诺唯一的区别在于随机致盲因子r是通过 ElGamal 承诺方案构造出来的。这个看似微小的改动实际上提供了一项重要的安全措施Pedersen 承诺本身已经是完美隐匿的所以无论发生什么隐私永远不会受到威胁且不需要用户采取任何行动万一承诺方案的绑定性被攻破就可以通过一次软分叉启用秘诺切换要求所有新交易验证完整的 ElGamal 承诺以此证明自己的承诺没有破坏绑定性杜绝凭空铸造。即便如此灾难场景下用户依然保有选择权继续交易用户可以选择继续创建新交易。由于 ElGamal 承诺只是计算隐匿这可能会牺牲隐私且只涉及用户最后的 UTXO但至少用户仍然能够动用自己的币静默离场用户也可以选择不再进行任何交易从而完整保留隐私——因为旧交易只验证过完美隐匿的 Pedersen 承诺过往隐私不受新验证规则影响。现实中隐私泄露对某些人而言可能比损失一笔加密货币更加致命。这是每个用户自己应当做出的判断而秘诺切换恰恰把这种选择权交还给了用户。需要特别澄清的是这是一项专为灾难场景准备的保险措施而不是常态化的机制。如果未来计算能力的进步使离散对数难题的困难性受到质疑那么包括其他加密货币在内的大量加密系统都将急需把底层原语升级到面向未来的方案秘诺切换只是在 Pedersen 承诺的绑定性被意外攻破时为 Grin 额外提供的一层安全纵深。延伸阅读秘诺切换的完整理论出处《Switch Commitments: A Safety Switch for Confidential Transactions》IACR ePrint 2017/237Pedersen 承诺与 Mimblewimble 交易原理doc/intro.md本文中文版对应原文doc/translations/switch_commitment_ZH-CN.md源码入口keychain/src/types.rs、keychain/src/keychain.rs、core/src/libtx/build.rs、core/src/libtx/proof.rs、core/src/core/transaction.rs赞分享区块链Web3【免费下载链接】grinMinimal implementation of the Mimblewimble protocol.项目地址https://gitcode.com/gh_mirrors/gr/grin点击查看免费下载相关推荐FlexPrice 承诺计费Commitment与超额费率Overage Factor实现全解析FlexPrice 承诺计费Commitment与超额费率Overage Factor实现全解析 本文以 FlexPrice 开源仓库中的 docs/pBlitzar核心技术解析GPU加速的零知识证明多标量乘法与Pedersen承诺Blitzar核心技术解析GPU加速的零知识证明多标量乘法与Pedersen承诺 Blitzar 是一个专为加速零知识证明算法的C库通过GPU并行计算实密码学高性能计算FlexPrice 计费引擎Sum with Window 窗口聚合与 Commitment 承诺保底阶梯定价的设计与实现解析FlexPrice 计费引擎Sum with Window 窗口聚合与 Commitment 承诺保底阶梯定价的设计与实现解析 导读 本文基于 FlexPri上一篇godogen 全自动游戏开发流水线演进全记录从 GDScript 生成器到仅文档运行时的架构蜕变下一篇基于 Credential Access Boundaries 的降级凭证Downscoping实战python-docs-samples 中的受限访问令牌实现创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考