Grin交易原理详解

By Brandon Arvanaghi

Updated on March 08, 2019, 17:49 PM

grinbetter.jpg


本文由Gemini的安全工程师Brandon Arvanaghi撰写。 LongHash的翻译是本文作者授权的唯一中文翻译,网络流传所有其他中文翻译版本均未经授权。阅读原英文文章,请访问:Medium.



Grin,一种使用MimbleWimble协议的新型加密货币,连日来让整个市场为之兴奋。但其相关教程却乏善可陈。


本文就旨在阐明Grin交易的具体原理。


Grin输出采用了Pedersen Commitment。输出形式如下:


1-qHqYcOzxKeA7aQBUGPykvA.png

Grin输出——Pedersen Commitment方案。


Pedersen Commitment是一种隐藏信息的巧妙方式。如果这是你第一次听到Commitment,那么再看到这个词语的时候你就可以将其理解为“隐藏价值”。


以下内容摘自Grin wiki,很好地初步阐明了Grin交易原理。


如果我们选择一个非常大的数字 k 作为私钥,则k * H被认为是相应的公钥。即知道公钥k * H的值,要推导出 k 的值也几乎是不可能的...

• r 是私钥,用作盲因子, G 是椭圆曲线上的不动点,他们的乘积 r*G 是曲线上r的公钥。

• v 是输入或输出值,H 是椭圆曲线上的另一个不动点。

在公式(k + j)* H = k * H + j * H中, k 和 j 都是私钥,说明两个私钥和获取的公钥(k + j)* H,等于每个私钥的对应公钥和(k * H + j * H)。


ECC入门中有对密码学更深入的研究,但简而言之,要花费Grin,就必须要知道盲因子(r)和Grin的数量(v)。而要解构commitment来推断这些值是不可能的。我们必须提前知道这些值。


盲因子之所以存在是因为向你支付Grin的人也知道v的值是多少(他们向你发送了多少Grin)。但只有你(而非Grin的发出方)知道该输出的盲因子,因此,只有你能够花掉这笔输出。


假设该笔输出使用的盲因子为20,且该笔输出包括40个Grin。(注:Grin的数量实际上是以原子单位1 NanoGrin的倍数发送的。简单起见,这里我们使用“Grin”来表示。):


1-jGRqzEHHHlB14D4aHbV6dA.png

该笔输出中,盲因子为20,Grin数量为40.



若查看Grin的区块链浏览器,你会发现这笔输出不会如上所述整齐地分解。以下为真正的Grin输出,与我们所创建的一样:


1-kqUap2txRfj-ta27wITygg.png

Grin输出形式(在Commit列下)



同样,要从该输出中推导出“20”(盲因子)或“40”(Grin数量)是不可能的。


花费输出


假设我们展示的输出属于Alice。现在,Alice希望将40个Grin中的25个发送给Bob。为方便说明,我们将忽略矿工费。


如果你用一张5美元的钞票买了一件3美元的东西,那么你会得到2美元的找零(余额)。比特币交易方式亦是如此,Grin也不例外。如果Alice想要从她未使用的40个Grin输出中发送25个Grin给Bob,她也会在同样一笔交易中创建一个输出,这笔输出会将余下的15个Grin(找零)返还给她自己。


1-dIVmDE4RcDyOA2ZHZmmErA.png

Alice确定想要发送给Bob的Grin数量,及其余额。



这15个Grin将回到Alice的账户中,这就意味着,只有她能够控制并再次花费。换言之,Bob无法花费Alice的这15个找零。为此,Alice必须为这15个找零创建一个新的盲因子。假设Alice选择34作为盲因子。


Alice既知道r值(找零输出的盲因子),也知道v值(余下Grin数量)。这样,她就拥有了创建找零输出(co)所需的一切信息。这也将作为一笔输出记录在区块链上,就像Alice很快生成的、将25个Grin发送给Bob的输出一样。


1-nLlF8tpmjoywDYmEGJjt8A.png

Alice的余额输出。



如前所述,要花费任何一笔输出,必须知道输出中所使用的盲因子。Alice知道她想要花费的输出中所使用的盲因子(20),但她需要一种方式向所有人证明她知道。


为此,她需要创建一个完全独立的计算方法——盲因子总和。这里需要Alice用她刚刚为自己的余额输出创建的盲因子(34),减去她希望花费的输出的盲因子(20)。


1-MaLQ4m5yG_66RYvlv4Uhtw.png

Alice的盲因子总和。



s(s代表发送方,即Alice)是Alice所有盲因子的总和,本例中总和为14。(注:本文中我有意忽略了内核偏移)。


最后,Alice要创建一个随机数ks(s同样代表发送方)。她将使用该随机数为这笔交易构建签名,我们将在稍后展示签名的构建过程。Alice不会将实际随机数发送给Bob。相反,她发送的是ks • G,这是对该随机数的承诺(commitment)。如前所述,Alice将随机数与生成点G相乘,从而隐藏了实际随机数的值。


Alice会将以下信息发送给Bob。但实际上,Grin数据并未被分为“元数据(Metadata)”和“数据(Data)”字段。而为了清晰起见,我们在这里会按照如下形式表示。


1-wIubZAkZHgPCEFp2_Yiv5w.png

Alice在本次Grin交易的第一步中发送给Bob的所有信息。



元数据字段包括:


1. 发送数量:Alice想要发送给Bob的Grin数量(本例中为25)。

2. TX UUID:Alice和Bob在来回发送数据时用于标识此交易的唯一标识符。

3. TX fee: 交易费用(本教程中将不予讨论)。

4. 区块高度(lock_height):该笔交易生效时的区块编号。


数据字段包括:


1. TX输入:未花费的输出,Alice用作与Bob进行交易的输入。

2. co: Alice的余额输出。

3. ks • G: Alice的随机数ks乘以生成点G,成为对该随机数的承诺。

4. rs • G: Alice所有盲因子rs的总和乘以生成点G,成为对该值的承诺。


Alice将以上全部数据发送给Bob,Bob继续下一步操作。


轮到Bob


Bob在接收到Alice发来的数据后,将交易费用(TX fee)和区块高度(lock_height)变量联系起来以创建M,我们称之为该笔交易的“信息(Message)”。


1-g2agNid3qDrVlQH01L1PKw.png

该笔交易的“信息”



Bob为他想要从Alice那里收到的25个Grin选择一个盲因子rr(r代表接收方,在本例中为Bob)。假设他选择11作为盲因子rr,同时还选择了自己的随机数kr(r同样代表接收方)。


正如Alice所做的,Bob也分别将这两个值乘以生成点G,创建对这两个值的承诺。接着Bob利用这些数值,为该笔交易生成Schnorr challenge,由变量e表示:


1-Fhh761YDI3u2vQfza4UyzA.png

该笔交易的Schnorr challenge。



Schnorr challenge按顺序包含以下内容的SHA256哈希:


1. 交易信息。

2. Alice和Bob使用随机数的承诺总和。

3. Bob(25个Grin输出)的盲因子承诺总和,和Alice所有的盲因子总和。


Bob使用e为交易生成他的Schnorr签名,sr(r代表接收方)。虽然这是Bob签名的全部内容,但我们称之为Bob的部分签名,因为它最终将与Alice的部分签名相加,从而得到整个交易的签名。


1-RKFMVC6KUjztDUfKwaarFw.png

该笔交易Bob的部分签名



当Alice最终收到sr时,她是无法从中得知kr或rr的值的。


Bob将以下内容发回给Alice:


1-Ez6bwxanfmqfD9HyY5KgsA.png

Bob将他的部分签名、随机数承诺以及对输出盲因子的承诺发回给Alice。



这些内容按顺序包括:


1. sr: Bob的部分签名。

2. kr • G: Bob的随机数承诺

3. rr • G: Bob对他想要得到的25个Grin的盲因子承诺


最后一步:回到Alice


Alice现在拥有所需一切信息,可以在本地计算e,即该笔交易的Schnorr challenge。在本地计算了e之后,Alice可以验证Bob的部分签名。


Bob的部分签名sr包含以下内容:

1-RKFMVC6KUjztDUfKwaarFw.png

该笔交易Bob的部分签名


基于我们前面描述的椭圆曲线的性质,Alice可将生成点G引入方程式两边,等式仍然成立。


1-OnlvcHKk_MAGwbDnst6TqA.png

Alice将等式两边分别乘以生成点G。



由于Alice收到了Bob的kr•G(Bob的随机数承诺)和rr•G(Bob的盲因子承诺,他将使用该盲因子来获得他将收到的那25个Grin),同时由于已经在本地计算了e,Alice可以简单地乘以生成点G,并确保等式的右边等于这个值,从而验证Bob的部分签名sr。


如此,Alice便证明了:


1. Bob知道他会收到多少Grin(25个)。

2. Bob知道其随机数.

3. Bob知道他想要得到的25个Grin的盲因子。


而Alice不会知道Bob选择的随机数或者盲因子。


接着,Alice生成自己的部分签名:


1-HTLqp3Oa6f2N5EbI7dpzPw.png

Alice为该笔交易生成部分签名。


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


1-1i9Rgo2Qwvxp0E49sNHuNg.png

交易签名,包括Alice和Bob部分签名的总和以及对其随机数的承诺。



签名按顺序包括:


1. Alice和Bob部分签名的总和。

2. Alice和Bob的随机数承诺的总和(他们彼此互不知道对方的真实随机数)。


简化后该签名表现为:


1-9cQZq336fQNSJgqr82a0sg.png

该交易的签名



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



记住这个签名,很快你就会理解它的意义。


完成交易


数字货币需要“记忆”——也就是说,当你将一笔钱发送给某一个人的时候,你就不能将它再发送给另一个人。而Grin的运作方式隐藏了发送的Grin数量和接收方。那么,我们怎么能证明一笔钱没有被重复支付或凭空创造出来呢?


在一笔Grin交易中,当从输入中减去所有输出时,剩余Grin的数量应该等于0。那么回到之前的5美元例子:


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


在Grin的交易中,当一笔交易合法时,相同的求和使得v值总和为零。但我们如何在不展示这些数值的情况下证明这一点呢?让我们看看从Alice到Bob的交易中使用的输入和输出:



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


这里的巧妙之处在于,当Grin的数量抵消时(不存在凭空创造的情况下应该得到的结果),从输入减去输出所剩下的就是“过多盲因子(the excess blinding factor)”的承诺,或“kernel excess”。本文例子中,盲因子的承诺是25•G,是曲线上的公钥。


如果一笔Grin交易的输出总和减去输入总和会在曲线上产生一个有效公钥,那么你就会知道,v值一定已经被抵消了。如果对于某个已知的n值,等式的右边不是n•G + 0•H的形式,那么该笔交易无效。这意味着要么花费的金额大于输入的总和(就好比你拿出5美元纸钞,向收银员支付3美,却得到找零10美元),要么输入大于输出(就好比你拿出5美元纸钞,向收银员支付3美元,却没有找零)。


还记得这个签名吗?


image.png

该交易的签名



这个签名实际上已经对我刚刚提到的过多盲因子签署了承诺。以下对此进行了阐释。


如果你还记得的话,这就是当你在等式两边同时乘以生成点G时,Bob的部分签名。


1--Aa86Dh4S8PWptBK2HR0dg.png

当两边同时乘以生成点G时,Bob的部分签名。


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


1-x6SkY2yOLEWg5bc9GHIjjg.png

等式两边同时乘以生成点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和ss (Bob和Alice各自的部分签名)就证明了整个交易的有效性,因为它们加起来就等于对过多盲因子的承诺。


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


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


或:


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



接下来就要检查左右两边是否相等。


记住,这个等式中的所有内容(部分签名的总和,e中的所有内容,对过多盲因子的承诺,对随机数总和的承诺)都是公开可见的,因此任何人都可以对此进行验证。我们既不需要Alice也不需要Bob的盲因子来验证交易。加上他们的部分签名,并验证他们对过多盲因子的承诺进行了求和,我们就证明了:


1. 在花费Alice之前的输入时,没有凭空创造新的资金。

2. Alice和Bob在创建该笔交易时都知道其输出的盲因子。这意味着他们可以花费新的输出,不会出现问题。


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


交易内核


除输出外,交易内核是从Grin交易输出中得到的另一条信息。每笔交易都会生成一个交易内核,但是Grin区块链是无法查看的,也无法将一笔输出与交易内核相关联。每笔Grin交易都存在一个交易内核,其中包含了“没有凭空创造新的资金”的证明。

交易内核中存储信息如下:


1. 交易的签名(s, k • G).

2. 与“过多盲因子”相关的公钥(在本例中为25•G)。如上所述,可用其验证s。

3. 交易费和交易的区块高度。(注:如果是Coinbase交易,则这两者均不存在)。


总结


完成以上操作后,从该笔交易向网络中广播的信息仅包括:


1. 使用的输入。

2. 新的输出。

3. 交易内核。

4. 内核偏移(本文中未作介绍)。


此前交易的元数据皆不会被转发。更棒的是,其中一些信息可能也会被丢弃,关于这方面内容,我们将在另一篇文章中进行介绍。

希望这篇文章能够进一步阐明Grin交易的操作原理。本文中,我有意省略了范围证明、内核偏移和矿工费。请留意更多有关Grin中核销(cut-through)的工作原理、多人参与交易的形式和一些实验功能的文章。



邮件订阅

LongHash 通过强大的数据分析为您解读真实的区块链,发现隐藏在数据背后的投资价值

MORE NEWS