Bitcoin Block 如何储存 Merkle Tree?

中本聪在Bitcoin P2P Network的论文提到,Merkle TreeSPV Client应用。我们知道,SPV Client不储存所有的Transaction。当它要确认某个Transaction是否在Block里,就去问PeerPeer回传Merkle Path,给SPV Client验证就行了。

本篇提出一些问题给大家深入思考:

  1. Merkle Tree存在何处?
  2. 除了Merkle Tree,还有什么别的方法,可以用在SPV Client上?

问题一:Maerkle Tree存在何处?

我们知道,Merkle Tree是一种Binary Hash Tree。它的用途和原理这里就不多说了,不熟的,请大家自己上网找。为了本文讲解方便,列出相关名词。

Merkle Tree里的Node分为两类,Leaf NodeNon-Leaf NodeNon-Leaf Node里面,还有一个惟一的NodeRoot Node,用来代表整个Merkle Tree

Merkle Tree

  • Leaf Node
  • Non-Leaf Node
    • Root Node

简单来说,每一个TransactionHash值存在Leaf Node,两两Leaf NodeHash值存放在上一层的Node,直到Root Node,其值,就是用来代表Block所包含的所有Transaction

那么,Merkle Tree存在那里?我一直以为是在Block,后来发现,其实Block只存Root Node,连Leaf Node都不存。除了Root Node之外,其它Node都是依照需要,当场计算出来的。我把BlockTransaction的关系,画成下面这张图:

Bitcoin Block 如何储存 Merkle Tree?_第1张图片


从图中,我们可以很清楚的知道,BlockTransaction都不存Merkle Tree,连Leaf Node都无,只有存在Block HeaderMerkle Root,是用来验证它所包含的Transactions完整性的最后一关。

Full Peer会储存完整的BlockBlock Size + Block Header + Transaction Counter + Transactions

SPV (Simplified Payment Verification) Client只存精简的BlockBlock Size + Block Header

Full Peer会储存完整的Transaction,但也没有Merkle Tree,甚至连Transaction Hash也没有。

Transaction InputTransaction Hash指的是关连到上一笔的Transaction,而非这一笔。

由此可知道,整个BlockchainBlock、与Transaction的资料结构,在设计上,是以储存空间最小为考量,而非查询方便为考量。这是因为Blockchain是大家共用的帐本,愈小,愈利于传输。

不管是Full Peer还是SPV ClientTransaction有两项要检查:

  1. Transaction存在性检查 - 检查Transaction是否真的存在Block
  2. Transaction没有被重覆花费 - 检查TransactionInput不是重覆花费

Full PeerSPV Client对这两项的检查方式会有所不同,我将会写另一篇文章探讨。本文拿,SPV ClientTransaction做存在性检查,做为一个例子,解释Merkle Tree在这检查的过程中,起了什么样的做用。

检查Transaction是否真的在某个Block里?我猜想的步骤如下:

  1. SPV Client将这个问题包装成 Q = (Transaction, Block Header) 
  2. SPV Client将问题Q传给Full Peer
  3. Full Peer拆解Q,若发现Transaction属于Block,则建立Merkle Path
  4. Full PeerMerkle Path传给SPV Client
  5. SPV Client拿到Merkle Path,就表示Full Peer回答了Transaction是在Block里。
  6. SPV Client也会对Merkle Path验证Transaction是否真的存在Block,做二次验证。

这里有一个问题:为何不让Full Peer直接给答案就好了?还要丢一个Merkle PathSPV Client,让它做二次验证?

这是因为,SPV Client无法确认Full Peer是否可信的?Bitcoin世界里,Blockchain是惟一可信的,当然里面的BlockMerkle RootTransaction都是可信的。若待验证的Transaction透过Merkle Path,可以接到可信的Merkle Root,那么就可以验证Transaction的存在性。

这种验证Transaction存在性的方法,叫做Merkle Path Proof。再次强调,此法无法验证Transaction的合法性,因为无法证明TransactionInput不是重覆花费。

Full Peer是恶意的,分析一下欺骗SPV Client的可能性如下:

Transaction不属于Block1

Full Peer可以骗SPV Client说:TransactionBlock1里吗?不行,因为很难做出一个假的Merkle Path,因为Merkle Root是一个不断SHA256的值,要造假很困难。(题外话,若是SHA1就很容易造假了,因为Google最近发表,在可接受的时间内,产生相同的SHA1出来)

Transaction属于Block1

Full Peer可以骗SPV Client说:Transaction不在Block1吗?可以。

以后再探讨Bitcoin Network的安全问题。

问题二:除了Merkle Tree,还有什么别的方法,可以用在SPV Client上?

为了建立Merkle PathFull Peer要先从计算所有Leaf Node开始,再往上算出Non-Leaf Node,直到Root Node。为何不用较简单的List资料结构?Hash所有Leaf Node,放到第1Node

List

  • Root Node
  • Leaf Node

List,的确可以减轻Server的运算量,因为不用计算Node。但从Full Peer传给SPV Client的资料量会变很多。原来传给SPV Client的只要Merkle Path,只要Log(2, N),现在要N。想像1Block1024Transaction,其资料量就是 1024 x 36 (SHA256 size) = 36K bytes。如果传的是Merkle Path,其资料量是 Log (2, 1024) x 36 = 360 bytes

由此可见,Merkle Tree虽然会增加Full Peer计算Node的负担,但不会很多。计算Leaf Node运算量会比较大,因为它是Hash两个32 bytesLeaf Node。而传输的资料会少很多。

再来看本文最初提的两个问题:

  1. Merkle Tree存在何处?
  2. 除了Merkle Tree,还有什么别的方法,可以用在SPV Client上。

结论:

  • Blockchain不存放Merkle Tree
  • 但在实作上,Full Peer可以建立一个方便查询或建立Merkle TreeIndex。建Index的方法就有很多了。
  • SPV Client采用Merkle Tree,这是运算量和资料传输量之间的折衷方案。

-Count

你可能感兴趣的:(Bitcoin Block 如何储存 Merkle Tree?)