干货 | Grin 中的交易详解

编者注:Grin 是一种基于 MimbleWimble 协议建立的新型密码学货币。本文是一个详细的教程,逐步解释了 MimbleWimble 协议中交易是如何构造出来,又如何运用密码学,在不泄露交易双方地址和交易额的条件下,保证货币没有双花,保证只有货币所有者才能花费货币。

Grin 是一种基于 MimbleWimble 协议建立的新型密码学货币。但是,Grin 的教程又是出了名的晦涩难懂。

本文旨在分享 Grin 交易的运行原理,帮助大家理解 Grin 交易是 如何实际 运行的。

Grin 交易的 输出 是一个 Pederson 承诺 ,采用如下形式:

-一个 Grin 输出就是一个 Pedersen 承诺。-

Perdersen 承诺是一种隐藏信息的好方法。如果你是第一次听到 Perdersen 承诺的概念,那么每当你看到这个词的时候,就想想 “屏蔽值(shielded value)” 的概念(译者注:就是别人都看不见这个值是什么)。

以下这段文字摘自 Grin 的 wiki (了解 Grin 交易运行原理的最佳入门资料)。

假设咱们选择一个非常大的数字 k 当做私钥,将 k * H 作为对应公钥。即便有人知道了公钥 k * H 的值,要据此推导出 k 的值也是近乎不可能的……

• r 是被用作致盲因子的私钥,G 是椭圆曲线上的一个固定点,它们的乘积 r * G 就是 r 在这条曲线上的公钥。

v 是输入值或输出值,H 是椭圆曲线上的另一个固定点……

已知私钥 k 和 私钥 j ,则 (k+j) * H = k * H + j * H ,即两个私钥之和与固定点 H 相乘产生的公钥( (k+j) * H) )等于两个私钥分别与固定点 H 相乘产生的两个公钥之和 k * H + j * H

若想更深入地研究密码学可以阅读 ECC primer 这篇博客。简而言之,要花费一笔 Grin 输出,必须同时知道 致盲因子 (r) 以及 Grin 交易金额 (v) 。这两个值是不可能通过破解承诺倒推得出的。因此,只有提前知道这些数值才能花费 Grin 的输出。

Grin 之所以设置致盲因子,是因为 Grin 的发送者是知道 v 的值的(向你发送的 Grin 数量)。但是该输出的致盲因子只有你知道(连 Grin 的发送者也不知道),因此 只有你 能够花费该输出。

假设这个输出包含 40 Grin,使用的致盲因子为 20 。

插播 :实际发送的 Grin 数量是原子单位 1 NanoGrin 的整数倍。这里为了简单起见,我使用整数个 Grin 来举例):

-在该输出中,致盲因子是 20,Grin 数量是 40。-

Grin 浏览器 上查看 Grin 交易的输出,我们会发现实际的输出并非像上图那样通过清晰的公式呈现。下面才是 Grin 输出真正的样子:

-Grin 输出(位于 “commit” 列)。-

再强调一遍,从该输出推出 “20” (致盲因子)或 “40” (Grin 数量)是不可能的。

花费该输出

假设我们刚才提到的输出属于 Alice。现在,Alice 想要将这些 40 个 Grin 中的 25 个发送给 Bob 。为了简单起见,咱们先忽略给矿工的交易手续费。

如果你有一张 5 美元的钞票,买了 3 美元的东西,会得到 2 美元的找零。比特币系统中的交易就是这样运作的,Grin 也不例外。如果 Alice 想从她的未花费交易输出 40 Grin 中拿出 25 Grin 发送给 Bob ,她在这笔交易中还要创建一个新的未花费交易输出,将余下的 15 Grin (找零)打回自己的地址。

-Alice 知道她发送给 Bob 的 Grin 数量,以及找零数量。-

这笔交易中有 15 Grin 将回到 Alice 手中,意味着只有她能够控制并且再次花费这 15 Grin 。换句话说,必须杜绝 Bob 花费 Alice 零钱的可能性。为此,Alice 必须为她的找零输出创建一个新的致盲因子。假设 Alice 选了 34

Alice 同时知道 r (她的找零输出的致盲因子)和 v (找零的 Grin 数量),就拥有了创建零钱输出( co )所需的一切信息,而且将作为一个输出记录在区块链上。Alice 即将向 Bob 发送 的 25 Grin 输出也是如此。

-Alice 的找零输出。-

正如我前面所提到的,只有知道了输出使用的致盲因子,才能花费这个输出。Alice 知道她想花费的输出的致盲因子 (20) ,但是她需要通过一种方式向 Grin 系统中的其他人证明她知道。

这就是为什么她需要创建一个完全独立的计算,求解 她的致盲因子总数 。这就要把 Alice 刚刚为她的找零输出创建的致盲因子(34),减去她想要花费的输出的致盲因子 (20)。

-Alice 的致盲因子总数。-

rs(s 表示发送者,即 Alice )代表 Alice 的致盲因子总数,在这个例子里是 14 。( 插播 :我有意忽略了内核偏移量(kernel offset)。)

最后,Alice 需要创建一个随机 nonce ks (s 同样表示 发送者 Alice )。她将使用该随机 nonce 值,帮助她对这个交易进行签名(见下文)。Alice 不会将实际的 nonce 值发送给 Bob ,而是发送 ks·G (该 nonce 对应的 Pedersen 承诺)。如前所述,通过将该 nonce 值乘以生成点 G ,Alice 隐藏了实际的 nonce 值。

Alice 将以下信息发送给 Bob 。实际上,Grin 数据并不会被分为 “元数据(Metadata)” 和 "数据(Data)”字段,但是为了清晰起见,本文特意将二者区分开来。

Alice 在 Grin 交易第一步需要发送给 Bob 的所有信息。

元数据(Metadata)字段:

  • 发送数量(Amount to send): Alice 想要发送给 Bob 的 Grin 数量(这个例子里是 25 )。
  • 交易唯一 ID (TX UUID): Alice 和 Bob 在来回发送数据时使用的唯一标识符,用于标识此交易。
  • 交易费(TX fee): 交易费(在本教程中咱不讨论了)。
  • 锁定高度(lock_height) :交易生效的区块号。

数据(Data)字段:

  • 交易输入(TX Inputs): Alice 将单个或多个未花费输出用作发送给 Bob 的交易的输入。
  • 找零输出(co) : Alice 的找零输出
  • ks • G : Alice 的 nonce ks 与生成点 G 相乘,得到的值就是这个 nonce 的 Pedersen 承诺
  • rs • G : Alice 的致盲因子总数 rs 与生成点 G 相乘,得到的值就是这个 rsPedersen 承诺

Alice 将以上信息发送给 Bob,由 Bob 来完成下一步操作。

Bob 的操作

当接收到 Alice 发送的信息后,Bob 将 TX feelock_height 这两个变量连起来产生 M (即交易的 “消息(Message)”)。

-交易 “消息”。-

Bob 为他将要从 Alice 处接收的 25 Grin 选择一个致盲因子 rr (r 代表 接收者 ,即 Bob)。假设他选择了 11 。与此同时,他也选择了自己的随机 nonce kr (r 代表 接收者 )。

与 Alice 的操作相同,Bob 将 rr 和 kr 两个值分别与生成点 G 相乘,创建了一个 Pedersen 承诺 。有了这些数据之后,Bob 就可以生成本交易对应的 Schnorr 挑战 ,用变量 e 表示:

-交易的 Schnorr 挑战。-

Schnorr 挑战按照顺序对以下信息进行了 SHA256 哈希运算:

  • 交易消息。
  • Alice 和 Bob 所选的 nonce 对应的 Pedersen 承诺之和。
  • Bob (为他的 25 Grin 输出所选)的致盲因子对应的承诺与 Alice 的致盲因子总数对应的承诺之和。

Bob 通过 e 为该交易生成自己的 Schnoor 签名 ,即 srr 代表 接收者 )。虽然 sr 是 Bob 的完整签名,但是我们称其为 Bob 的 部分签名 ,因为该签名最终要与 Alice 的 部分签名 一同创建整个交易的 签名。

-该交易中 Bob 的部分签名。-

当 Alice 最终收到 sr 时,是无法倒推出 krrr 的实际数值的。Bob 将以下内容发送给 Alice:

- Bob 将自己的部分签名、nonce 对应的承诺,以及 25 Grin 的致盲因子对应的承诺发送给 Alice。-

按照顺序,发送的内容包括:

  • sr: Bob 的部分签名。
  • kr • G : Bob 所选的 nonce 对应的承诺。
  • rr • G : Bob 即将收到的 25 Grin 的致盲因子所对应的承诺。

最后一步:发送回 Alice

Alice 现在有了计算 e 以及该交易的 Schnorr 挑战所需的一切信息。在本地计算完 e 之后,Alice 就能够 验证 Bob 的部分签名

相信你还记得,Bob 的部分签名 sr 包括以下内容:

-该交易中 Bob 的部分签名。-

基于我们先前描述的椭圆曲线的性质,Alice 在等式两边同时乘以生成点 G 后,该等式依旧成立。

- Alice 在等式两边同时乘以生成点 G。-

因为 Alice 等于已经从 Bob 处收到了 kr • G (Bob 所选的 nonce 对应的承诺)与 rr • G (Bob 即将收到的 25 Grin 的致盲因子所对应的承诺),并且已经在本地计算出了 e ,她只需要简单地将 sr 乘以生成点 G ,确保与等式右边的值相等,就能够验证 Bob 的部分签名了。

通过完成以上操作,Alice 能够证明:

  1. Bob 知道他将收到的 Grin 数量(25)。
  2. Bob 知道他的 nonce 值。
  3. Bob 知道他为这 25 Grin 选取的致盲因子。

……至此,Alice 在不知道 Bob 选择的 nonce 和致盲因子的情况下验证了 Bob 的部分签名。

之后,Alice 生成她自己的部分签名:

-该交易中 Alice 的部分签名。-

Alice 现在可以生成该交易的 签名 ,其中包含她和 Bob 的 部分签名:

交易签名由 Alice 和 Bob 的部分签名之和以及他们各自的 nonce 所对应的承诺之和组成。

按照顺序, 签名 包含:

  • Alice 和 Bob 的部分签名之和。
  • Alice 和 Bob 的 nonce 所对应的承诺之和 (他们彼此都不知道对方的 nonce 值)。

合并之后,交易签名可以表示成如下形式:

-交易签名-

其中,s = ss + sr,k = ks + kr。

记住这个签名 —— 你很快就知道它的意义了。

交易完成

数字货币需要 “记忆” —— 也就是说,当你向某个人发送一笔钱的时候,你不能把同一笔钱发送给其他人。通过使用 Grin,我们隐藏了 Grin 的发送数量以及接收方。那么,我们怎么证明这笔钱没有被 “双花” 或凭空造出来的呢?

在一笔 Grin 交易中,从输入中减去所有输出之后,剩余 Grin 的数量应该等于 0。再以 5 美元钞票举例:

3 美元给收银员(输出)+ 2 美元找零返还给我(输出)- 5 美元钞票(输入) = 0

同理,一笔合法的 Grin 交易也符合上述等式。那么,在不暴露具体值的情况下,我们可以如何验证呢?来了解一下 Alice 和 Bob 之间交易的输入和输出情况:

(34•G) + (15•H) + (11•G) + (25•H) - (20•G) - (40•H) = (25•G) + (0•H)

这里的巧妙之处在于,当 Grin 数量抵消时(没有多余的 Grin 凭空产生),用输入减去输出后剩余的是 “ 过剩致盲因子 ” 或 “ 过剩内核 ” 所对应的承诺。在我们现在的例子中,过剩致盲因子对应的承诺为 25•G ,即 椭圆曲线上的一个公钥

如果一笔 Grin 交易的输出之和减去输入之和后能够产生一个有效的椭圆曲线公钥,那么你就能知道 v 值一定被抵消了。如果等式右侧不是某些已知数值 n 的 n•G + 0•H 形式,你就能知道这笔交易是非法的了。这意味着,要么输出总量大于输入总量(例如,你支付了 5 美元,收银员收取了 3 美元,却倒找了你 10 美元),要么输入总量大于输出总量(例如,你支付了 5 美元,收银员收了 3 美元,但是没有找你钱)。

还记得上文得出的签名么?

-交易签名-

该签名实际上 签署 了我刚才提到过的 过剩致盲因子对应的承诺 ,下面我们来解释一下。

还记得吧,当你把 Bob 的部分签名的等式两边同时乘以 G 后,会得到如下等式。

-等式两边同时乘以生成点 G 后 Bob 的部分签名-

同样,当你把 Alice 的部分签名的等式两边同时乘以 G 后,会得到如下等式。

-等式两边同时乘以生成点 G 后 Alice 的部分签名。-

如果把两个等式相加会发生什么呢?你将得到:

sr•G + ss•G = (kr • G) + (ks • G) + (e • (rr•G + rs•G))

其中, rr 是 Bob 的致盲因子, rs 是 Alice 的 致盲因子总数 , rr•G + rs•G 等于 (rr + rs)•G 。

Bob 的致盲因子对应的承诺是 11•G 。Alice 的致盲因子总数对应的承诺是 14•G ,两者相加之后得到 25•G (代表整个交易的过剩致盲因子的承诺)。因此, sr (Bob 的部分签名) 和 ss (Alice 的部分签名) 相加之和若等于过剩致盲因子对应的承诺,即可 证明整个交易是合法的。

进一步简化这个等式,我们会得到:

sr•G + ss•G = (k•G) + (e • (r•G))

或:

sr•G + ss•G = (k•G) + (e • (25•G))

那么接下来只需检验等式两边是否相等就行了。

记住,等式中的所有变量(部分签名之和、 e 中各部分、过剩致盲因子所对应的承诺、nonce 之和对应的承诺)对于所有人都是可见的,因此任何人都能进行验证。我们可以在既不知道 Alice 的致盲因子也不知道 Bob 的致盲因子的情况下验证该交易。通过将他们的部分签名相加,并验证其总和是否等于过剩致盲因子对应的承诺,我们能够证明:

  1. Alice 花费的输入中没有凭空产生多余的 Grin 。
  2. Alice 和 Bob 在创建该交易的时候,都知道各自输出的致盲因子。这意味着新他们能够花费交易产生的新输出,使得该输出不被锁定。

刚才我们用来验证交易的信息被放在 交易内核 当中。

交易内核

除了输出, 交易内核 是 Grin 交易生成的另一部分信息。每笔交易生成一个交易内核,但是无法通过查询 Grin 区块链上的某一输出找到与之关联的交易内核。每笔 Grin 交易都包含一个交易内核,以及没有凭空产生多余 Grin 的证明。

以下信息将存储在交易内核中:

  • 交易 签名 (s, k • G)。
  • 与 “ 过剩致盲因子 ” 关联的公钥(本例中为 25•G )。如上所述,该公钥可以用于验证 s
  • 该交易的 交易费(transaction fee)锁定高度(lock_height)。(插播: 如果是 Coinbase 交易,不会包含这两部分信息 )。

总结

在完成所有这些操作之后,只有如下交易相关信息会广播到网络中:

  • 所花费的输入。
  • 新产生的输出。
  • 交易内核。
  • 内核偏移(我在这里没有描述)。

上文所述的交易元数据不会被广播。更好的是,其中一些信息也可以丢弃 —— 我们将在另一篇博客中讲述。

希望本文能对了解 Grin 交易工作原理有所帮助。我刻意略去了范围证明(range proof)、内核偏移以及交易费的内容。更多信息请阅读有关 Grin 中交易合并机制(cut-through)工作原理、多方参与交易原理以及一些实验性的博客。

原文链接: https://medium.com/@brandonarvanaghi/grin-transactions-explained-step-by-step-fdceb905a853

作者:Brandon Arvanaghi

翻译&校对:stormpang & 闵敏

本文由作者授权 EthFans 翻译及再出版。

我来评几句
登录后评论

已发表评论数()

相关站点

+订阅
热门文章