技术解析如何在 NEAR 中通过 zk-SNARK 实现私密交易

从未花费交易输出、交易、手续费等角度解析 NEAR 中实现隐私交易的方式及提高交易池安全性和使用性的方法。

原文标题:《深度解析 NEAR 的私密交易功能》
撰文:NEAR Protocol

就在不久前,NEAR 宣布与 ZeroPool 建立合作关系,后者将在 NEAR 协议中增加对私密交易功能的支持。目前,在 NEAR 的平台上,所有交易都和比特币和以太坊一样,全部公开可查。也就是说,对于每笔交易,发起方、接收方和交易金额等信息都是对外公开的。采用这种方式能够保证每个人都有权利审计账簿,确认交易的有效性,同时还可以有效杜绝双花现象的发生。

在很多情况下,理想的交易方式是:只有交易的参与者才能看到交易的详细内容。而要满足这一要求,同时保证账簿仍然是可被验证的是一项复杂的工作,需要用到高深的密码学技术。在这篇文章中,笔者将从技术的角度深度解析如何在 NEAR 系统中实现私密交易功能,即在保证验证交易正确性的工作不受到任何损害的情况下,使交易的各个参与方与交易金额等信息处于隐藏状态。下面我们切入主题:

  1. 未经花费的输出
  2. 交易
  3. 通证充提
  4. 交易手续费
  5. 未来发展
  6. 结语

未经花费的输出

在 NEAR 生态里,我们一般使用账户模型作为记账方式,私密交易使用的则是 UTXO (未经花费的输出)模型。每一个 UTXO 都是一个元组,包含数额,接收方,salt 三个元素,其中数额指交易金额,接收方其实是通证接收方的公钥,而「salt」只是一些随机数。

所有的 UTXO 都储存在一个默克尔树上,该默克尔树有一个预设高度,高度值的大小决定了在该默克尔树存在的整个生命周期内,交易池可以处理的交易数量的上限 / 下限。

技术解析如何在 NEAR 中通过 zk-SNARK 实现私密交易图:UTXO 默克尔根

默克尔树上的每一个分支(树叶)或是一个 UTXO,或是 null (空值)。每一个 null 代表一个空位,未来可以填充进一个新的 UTXO。一旦一个空值被填满后,便不可回归到初始状态。所有的分支最初都是空值状态,即都为 null。

除了接收方,真正的 UTXO 不会透露给任何人。因此,默克尔树上的分支实际上是 UTXO 的哈希值,这也是为什么「salt」需要存在的原因。如果没有了它,一旦 Alice 知道了 Bob 的公钥,就可以使用不同的数字,来验证 Bob 的公钥(哈希值)是否出现在了默克尔树上,从而暴力破解交易金额。此时,Bob 的交易也就不再匿名了。

技术解析如何在 NEAR 中通过 zk-SNARK 实现私密交易图: 默克尔根

交易

假设 Alice 想私下里给 Bob 转一些通证。属于 Alice 的通证存放在 UTXO 里,通证的接收者相当于 Alice 的公钥。为了让交易保持私密状态,Alice 用如下形式创建了一次交易:

技术解析如何在 NEAR 中通过 zk-SNARK 实现私密交易

这笔交易有 2 个输入和 2 个输出(输入和输出的确切数量不一定为 2,但是必须要相同——所有交易都是如此),这里的输入是一些既有的 UTXO,对应默克尔树上的分支;输出则是全新的 UTXO,未来将被添加至默克尔树。

当 Alice 发起交易时,如果她发布的恰好是两个正在被花费的 UTXO,就会将该交易链接至生成这两个 UTXO 的交易上。而建立交易池的目的恰恰是为了保证这样的链接不能被建立,以确保输入型 UTXO 不会被发布出去。那么问题来了,如何才能确保在交易的过程中,验证节点可以确认一笔交易花费的是已有的 UTXO,同时又不会对外公布正在被花费的真实的 UTXO 呢?

与众多隐私保护交易引擎一样,ZeroPool 使用了一种非交互性的零知识证明(zk-SNARK)来实现私密交易。针对某种特定计算的零知识证明能够支持以下形式的密码证明:

  • 给定的公开输入 1,公开输入 2…
  • 已知某种私密输入 1,私密输入 2…
  • 可得到【某种结论】

此类知识证明的工作原理不在本文讨论范围之内。有关此问题的更多信息,可以点击该博客链接查询。如果想以一种最简单的方式达成私密交易,知识论证可以具有以下形式:

  • 给定默克尔根以及两个哈希值 OUT_HASH1 和 OUT_HASH2,
  • 已知有四个这样的 UTXO:IN1,IN2,OUT1,OUT2,两个默克尔证明 P1 和 P2 以及一个私钥 x,
  • OUT1 和 OUT2 对应的哈希值分别为 OUT_HASH1 和 OUT_HASH2;IN1 和 IN2 中的接收者相当于与 x 对应的公钥 X;merkel 证明 P1 和 P2 是在默克尔根已确定的默克尔树中包含 IN1 和 IN2 的有效证明;IN1 和 IN2 中的数量之和等于 OUT1 和 OUT2 中的数量之和。

交易则包含 merkle_root,out_hash1,out_hash2,以及知识证明。交易中的任何内容都不会暴露输出型 UTXO 的接收者,也不会将输出型 UTXO 链接到特定的输入型 UTXO。并且,连交易金额这样的信息也不会在交易过程中对外展示。

技术解析如何在 NEAR 中通过 zk-SNARK 实现私密交易

举例说明:如上图所示,假设该默克尔树的第一个和第三个 UTXO 以 Alice 为接收者,对应的金额分别为 $100 和 $17,Alice 知道这两个 UTXO,但是对树上的其他任何 UTXO 都未知。如果她想向 Bob 发送 $42,通常的做法是她会首先创建一笔交易,这笔交易会使用她的两个 UTXO 作为输入,同时创建两个输出:——一个向 Bob 发送 $42,另一个将剩下的 75$ 返给她自己。她将属于 Bob 的 UTXO 告诉了对方,但是其余的 UTXO 只有她自己知道,旁人无从知晓。并且,甚至连输入型的 UTXO 的哈希值也是保密的。

智能合约负责对交易池进行日常维护,一旦该合约收到了一笔这样的交易,便会对知识证明进行验证。验证无误后,就会将两个新的 UTXO 添加至默克尔树上。

技术解析如何在 NEAR 中通过 zk-SNARK 实现私密交易

Bob 从 Alice 处收到 UTXO 后,会等待一段时间,直到 UTXO 的哈希值被默克尔树收录之后,他才从真正意义上获得了这些通证。

这种方式虽看似简单,但存在一个问题,即相同的 UTXO 可能会被重复使用。由于除了 Alice 没有人知道输入型 UTXO 的哈希值,交易池便无法将已消耗的 UTXO 从默克尔树上移除,因为连它也不知道先从哪个开始移除。

如果 Alice 创建 2 个不同的零知识证明,但是消耗了同样的 2 个输入,每个人都能验证两笔交易消耗了一些原本存在于默克尔树上的 UTXO,但是却无法得知两笔交易中消耗的 UTXO 其实是一样的。为了解决这个问题,我们引入了 nullifier 的概念。简单来说,nullifier 是 UTXO 的哈希值,同时也是 UTXO 接收者的私钥。然后,我们将交易的知识证明更改为以下内容:

  • 给定默克尔根,以及两个哈希值 OUT_HASH1 和 OUT_HASH2,另外两个哈希值 NULLIFIER1 和 NULLIFIER2,
  • 已知有四个这样的 UTXO:IN1,IN2,OUT1,OUT2,两个默克尔证明 P1 和 P2 以及一个私钥 x,
  • OUT1 和 OUT2 对应的哈希分别是 OUT_HASH1 和 OUT_HASH2;IN1 和 IN2 中的接收者相当于与 x 对应的公钥 X;默克尔证明 P1 和 P2 是在有确定的默克尔根的树中包含 IN1 和 IN2 的有效证明;IN1 和 IN2 中的总和等于 OUT1 和 OUT2 中的总和;并且 hash (IN1,x)等于 NULLIFIER1,hash (IN2,x)等于 NULLIFIER2

请注意,任何花费特定 UTXO 的交易计算的都是相同的 NULLIFIER 值,因为 NULLIFIER 仅取决于 UTXO 的哈希值和 UTXO 中公钥对应的私钥。由于上述知识证明中的 NULLIFIER 是在公开的「给定」语句(Clause)中,因此如果曾经发布过使用相同 UTXO 的两笔交易,每个人都可以得知它们具有相同的 NULLIFIER,并舍弃后出现的那笔交易。同样值得注意的是,只要用于计算它的哈希是抗原像攻击的,NULLIFIER 就不会显示有关输入型 UTXO 或接收方私钥的任何信息。

通证充提

上述类型的交易可用于池内资产的转移,但对于一个功能完善的交易池来说,必须同时支持池内外的资金转移。因此,我们在私密交易的格式中加入了一个额外的字段,称为 delta,如此一来,输入型 UTXO 的总量就等于输出型 UTXO 数量+delta。

  • 给定默克尔树,两个哈希值 OUT_HASH1 和 OUT_HASH2,另外两个哈希值 NULLIFIER1 和 NULLIFIER2,以及一个 delta 值。
  • 已知对于 IN1,IN2,OUT1,OUT2 计 4 个 UTXO,两个默克尔证明 P1 和P2,还有一个私钥 x,
  • 则 OUT1 与 OUT2 对应的哈希值分别为 OUT_HASH1 和 OUT_HASH2;IN1 和 IN2 中的交易接收方相当于与私钥 x 对应的公钥 X;默克尔证明P1 和 P2 是有给定哈希根的包含 IN1 和 IN2 的 merkel 树的有效证明;IN1 和 IN2 数量等于 OUT1,OUT2 数量总和再加上 delta 值;hash (IN1,x)等于 NULLIFIER1;hash (IN2,x)等于 NULLIFIE2R。

需要注意的是,delta 在给定语句中,因此是公开的。NEAR 在处理上述类型的交易时,若 delta 值为负(即一笔私密交易中输入通证比输出通证少),多出来的通证会存入交易发起方的账户中;若 delta 值为正(即一笔私密交易中输入通证比输出通证多),则只有在剩余通证被补足时交易才有效。

交易手续费

私密交易禁止在新创建的 UTXO 和曾被用作交易输入的 UTXO 之间建立联系。不过对于任何将被记录在 NEAR 链上的交易而言,交易的发出者都必须支付 gas 费。也正是因为这个原因,该发出者的账户中必须有一定数量的 NEAR 通证。该账户可能不知通过什么手段获得了一些 NEAR 通证,从而在上文提到的两种 UTXO 之间创建了某种联系,私密交易的目的会因此大为受挫。

为了解决这个问题,我们在系统中引入了中继者(Relayer)的概念。假设 Alice 想给 Bob 发送一笔交易,并打算让 Ryan 充当中继者。这笔交易的 gas 费用小于Ⓝ1,而 Alice 愿意支付给 RyanⓃ1,让 Ryan 帮他把交易上链。

Alice 甚至可能都没有 NEAR 账户,此时的她创建了一笔私密交易。在这笔交易中,作为交易输入的两个 UTXO 的资金总额比作为交易输出的 UTXO 的资金总额正好少Ⓝ1。剩余的Ⓝ1 被提取至交易提交方的账户中。Ryan 从 Alice 处收集到这笔交易信息,验证其有效性,并用自己的账户提交交易。整个过程消耗的 gas 费小于Ⓝ1,但是他最后却得到了Ⓝ1 的酬劳 。

Alice 最终在没有暴露自己身份的情况下提交了一笔交易,Ryan 则获得了一笔小额的回报。请注意在交互中,任何一方都无需取得他人的信任:Ryan 不能以任何形式篡改交易,留给他的只有两个选择:要么提交,要么放弃。因此,对于 Alice 来说最大的风险就是她的交易可能没有被提交(这种情况下她可以请另一个中继人)。由于 Ryan 在交易提交之前就验证了交易,因此除非另一个中继人捷足先登,否则 Ryan 便不会有花费了 gas 却得不到回报的风险。

未来发展

上文描述的这种模型已经是一个可以完全满足私密交易的交易池了。接下来,笔者会从几个方面简要描述一下如何提高交易池的安全性或使用性。

支付

在我们描述如上交易的过程中,笔者曾提到当 Alice 悄悄将通证发给 Bob 的同时,也将新创建的 UTXO 分享给了对方。这一过程的实现需要 Alice 与 Bob 在链下交流,而这是我们不希望看到的。为了解决这一问题,我们可以对交易池进行扩展,使其可以存储所有的用交易接收方的公钥加密的 UTXO。当 Alice 将资产转给 Bob 并创建 2 个新的 UTXO 后,Bob 作为接收方,其公钥会被 Alice 用来对 UTXO 加密。

再来看 Bob,他监控着所有新创建的 UTXO,并试着用自己的私钥对其逐个解密。一旦他试到 Alice 创建的 UTXO,则解密成功——这样,Bob 就完全通过 NEAR 特有的链上沟通的方式发现了他们的 UTXO。

解耦签名与证明

当 Alice 创建一笔交易后,她需要使用自己的私钥信息,设计一个复杂的证明。因此,计算该证明的机器需要获取她的私钥,而这是我们不愿意看到的。总的来说,私钥最好用某些外部的硬件设备加以存储,这类硬件的功能通常会比较单一,比如有些产品只有消息签名这一个功能。对于这种硬件来说,运算知识证明通常在他们的功能之外。

为了适配这些硬件,我们生成 3 个密钥,而不是传统的公私钥对:私钥,解译钥和公钥。在这种情况下,用公钥加密的某条信息可以使用解译钥来解密。同理,私钥签名可以通过解译钥来验证。只有公钥是大家都能看到的。解译钥被储存在一个运算交易证明的设备上,而私钥被储存在外接设备中,该设备只能对信息进行签名。我们可以使用以下方式对知识证明做一些修改:

  • 给定默克尔根,两个哈希值 OUT_HASH1 和 OUT_HASH2,以及另外两个哈希值 NULLIFIER1 和 NULLIFIER2
  • 已知有 IN1,IN2,OUT1,OUT2 四个 UTXO,两个默克尔证明 P1 和 P2,一个解译钥 d 和一个签名 s。
  • OUT1,OUT2 对应的哈希值为 OUT_HASH1 和 OUT_HASH2;IN1 和 IN2 中的接收方相当于和 d 对应的公钥 X;默克尔证明 P1 和 P2 是给定哈希根的默克尔树包含 IN1,IN2 的有效证明;IN1 与 IN2 数量之和等于 OUT1 与 OUT2 的数量之和;hash (IN1,d)等于 NULLIFIER1;hash (IN2,d)等于 NULLIFIER2,s 是 message (IN1,IN2,OUT1,OUT2)的签名、并对于 d 有效。

当 Alice 想要创建一笔交易时,她会使用硬件设备签名(IN1,IN2,OUT1,OUT2),然后使用签名 s 在只能获取解译钥的机器上生成证明。需要注意的是,如果无法使用硬件设备,Alice 就无法生成签名 s,也就不能花出这笔钱——即使获取了用于生成证明的机器的使用权限也不行。

支持更多通证

私密交易并不仅仅局限于 NEAR 通证。开发人员只需作轻微调整,便可让交易池可以支持任何发行在 NEAR 平台上的通证。具体的实现方式本文不再赘述。

结语

除了与 NEAR 合作之外,ZeroPool 也在为以太坊搭建私密交易功能。目前团队发展所需的资金主要来自于社区,热心的读者可以在 Gitcoin 上支持他们。

来源链接:mp.weixin.qq.com

>>> 【买币首选】DragonEx龙网交易所,买比特币和以太坊等币简单快捷,现在注册交易手续费终身4折,每天现金分红 + 30%年化理财收益,注册并中级认证即可获得抽DT奖励(100%中奖),1小时内极速出入资金。

...

...

>>【8年老牌】现在注册Gateio比特儿交易所,即可享受一年内交易手续费9折优惠+糖果空投。

...

...

相关推荐

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址