<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Blockchain on 菠萝油与天光墟</title>
    <link>https://ramsayleung.github.io/zh/tags/blockchain/</link>
    <description>Recent content in Blockchain on 菠萝油与天光墟</description>
    <image>
      <title>菠萝油与天光墟</title>
      <url>https://ramsayleung.github.io/%3Clink%20or%20path%20of%20image%20for%20opengraph,%20twitter-cards%3E</url>
      <link>https://ramsayleung.github.io/%3Clink%20or%20path%20of%20image%20for%20opengraph,%20twitter-cards%3E</link>
    </image>
    <generator>Hugo -- 0.146.7</generator>
    <language>zh</language>
    <copyright>See this site&amp;rsquo;s source code here, licensed under GPLv3 ·</copyright>
    <lastBuildDate>Thu, 09 Jan 2025 20:03:58 -0800</lastBuildDate>
    <atom:link href="https://ramsayleung.github.io/zh/tags/blockchain/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>区块链的完整性校验方案: Merkle Tree</title>
      <link>https://ramsayleung.github.io/zh/post/2024/%E5%8C%BA%E5%9D%97%E9%93%BE%E7%9A%84%E5%AE%8C%E6%95%B4%E6%80%A7%E6%A0%A1%E9%AA%8C%E6%96%B9%E6%A1%88_merkle_tree/</link>
      <pubDate>Sat, 12 Oct 2024 18:22:00 -0700</pubDate>
      <guid>https://ramsayleung.github.io/zh/post/2024/%E5%8C%BA%E5%9D%97%E9%93%BE%E7%9A%84%E5%AE%8C%E6%95%B4%E6%80%A7%E6%A0%A1%E9%AA%8C%E6%96%B9%E6%A1%88_merkle_tree/</guid>
      <description>&lt;h2 id=&#34;前言&#34;&gt;&lt;span class=&#34;section-num&#34;&gt;1&lt;/span&gt; 前言&lt;/h2&gt;
&lt;p&gt;最近通过 &lt;a href=&#34;https://www.wtf.academy/docs/solidity-103&#34;&gt;Solidity-103&lt;/a&gt; 课程在学习 Solidity, 看到&lt;a href=&#34;https://www.wtf.academy/docs/solidity-103/MerkleTree/&#34;&gt;第36课&lt;/a&gt; Merkle Tree 的时候着实头疼, 即使我已经了解 Merkle Tree 这数据结构，但是课程还是看得不明所以。 &lt;br/&gt;&lt;/p&gt;
&lt;p&gt;所以写下这篇文章，梳理我所理解的 Merkle Tree 及其用途，既加深自己的理解，又践行了&lt;a href=&#34;https://ramsayleung.github.io/zh/post/2022/feynman_technique/&#34;&gt;费曼学习法&lt;/a&gt; &lt;br/&gt;&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h2 id="前言"><span class="section-num">1</span> 前言</h2>
<p>最近通过 <a href="https://www.wtf.academy/docs/solidity-103">Solidity-103</a> 课程在学习 Solidity, 看到<a href="https://www.wtf.academy/docs/solidity-103/MerkleTree/">第36课</a> Merkle Tree 的时候着实头疼, 即使我已经了解 Merkle Tree 这数据结构，但是课程还是看得不明所以。 <br/></p>
<p>所以写下这篇文章，梳理我所理解的 Merkle Tree 及其用途，既加深自己的理解，又践行了<a href="https://ramsayleung.github.io/zh/post/2022/feynman_technique/">费曼学习法</a> <br/></p>
<h2 id="区块链与交易"><span class="section-num">2</span> 区块链与交易</h2>
<p>关于区块链的资料有非常多，我也不赘述了. <br/></p>
<p>简单理解，区块链是由一个一个区块构成的有序链表，每一个区块都记录了一系列交易，并且，每个区块都指向前一个区块，从而形成一个链条。区块链听起来很高级，其实就是个单链表。 <br/></p>
<p>
<figure>
    
    
    <input type="checkbox" id="zoomCheck-69ce2" hidden>
    <label for="zoomCheck-69ce2">
    
    
    <img class="zoomCheck" loading="lazy" src="/ox-hugo/blockchain.jpg"/> 
    
    
    </label>
</figure>
 <br/></p>
<p>每个区块都会保存对应的交易信息，也会包含元数据信息在头部，包括前一个区块的 hash, 包含的交易数，merkle tree 的根节点 hash,时间戳等信息. <br/>
<img loading="lazy" src="/ox-hugo/block_detail.jpg"> <br/></p>
<p>我们总说区块链是不可窜改，那么它究竟是怎么不可窜改的? <br/></p>
<p>如果用户想要验证某个区块的某笔交易是否被窜改，他要怎么做？ <br/>
最简单的方式自然是把整个区块的交易都下载下来，平均每个区块有1M的数据，验证起来肯定很费时间. <br/></p>
<p>是否有一个验证方案，可以使用很小的数据集就完成验证? <br/></p>
<p>有的，那就是 Merkle Tree. <br/></p>
<h2 id="merkle-tree"><span class="section-num">3</span> Merkle Tree</h2>
<p>那什么是 Merkle Tree? <br/></p>
<p>假如我们有8笔交易被包含在区块中, 每笔交易都可以通过 hash 函数计算出一个 hash 值: <br/></p>
<p>
<figure>
    
    
    <input type="checkbox" id="zoomCheck-681ec" hidden>
    <label for="zoomCheck-681ec">
    
    
    <img class="zoomCheck" loading="lazy" src="/ox-hugo/8transactions.jpg"/> 
    
    
    </label>
</figure>
 <br/></p>
<p>哈希值也可以看做数据，所以可以把 <code>h1</code> 和 <code>h2</code> 拼起来， <code>h3</code> 和 <code>h4</code> 拼起来, 依此类推，再计算出哈希值 <code>b1</code> 和 <code>b2</code> <br/></p>
<p>
<figure>
    
    
    <input type="checkbox" id="zoomCheck-025de" hidden>
    <label for="zoomCheck-025de">
    
    
    <img class="zoomCheck" loading="lazy" src="/ox-hugo/merkle_tree_layer_two.jpg"/> 
    
    
    </label>
</figure>
 <br/></p>
<p>递归计算下去，直到计算结果只有一个 hash 值，这个就是所谓的 merkle root, 而 h1-h8 就是所谓的 <code>leaf node</code>, 两者之间的就是 <code>non-leaf node</code>. <br/></p>
<p>交易数量恰好是偶数能这么算，如果是奇数，那要怎么算呢？这个时侯，只需要把最后一个 hash 值复制一份，也能算出最终的 merkle root： <br/></p>
<p>
<figure>
    
    
    <input type="checkbox" id="zoomCheck-d8759" hidden>
    <label for="zoomCheck-d8759">
    
    
    <img class="zoomCheck" loading="lazy" src="/ox-hugo/odd_leaf_merkle_tree.jpg"/> 
    
    
    </label>
</figure>
 <br/></p>
<h2 id="merkle-tree-validation"><span class="section-num">4</span> Merkle tree validation</h2>
<p>现在有了 Merkle Tree, 如果我们要验证区块中的交易是否被修改，要怎么算呢？ <br/></p>
<p>最简单粗暴的方式肯定是把区块所有的交易下载下来，从头重组整棵 Merkle Tree, 8笔交易计算起来还可以，如果是几千笔呢？几百万笔呢？甚至几亿笔交易呢？ <br/></p>
<p>重组 Merkle Tree 的时间复杂度是 O(N), 如果是1亿笔交易，这意味着你要计算1亿次，太慢了。 <br/></p>
<p>但是，如果我们利用 Merkle Tree 的特性，从数学的角度，我们只需要少量的Merkle Proof(你可以理解成需要提供的验证数据集), 就可以完成验证. <br/></p>
<p>回到上文的 Merkle Tree, 假如我们要验证 <code>tx2</code> 是否被窜改，我们需要有 Merkle Tree Root 和 Merkle Proof: <br/></p>
<p>
<figure>
    
    
    <input type="checkbox" id="zoomCheck-1cbbe" hidden>
    <label for="zoomCheck-1cbbe">
    
    
    <img class="zoomCheck" loading="lazy" src="/ox-hugo/merkle_proof.jpg"/> 
    
    
    </label>
</figure>
 <br/></p>
<p>假设现在我们有 <code>tx2</code> 的交易数据，我们只需要 Merkle Proof 提供3个hash 值(图中的绿色部分)，然后我们只计算4次（橙色部分），就会算出 Merkle Root Tree 的值，用来和区块头部的 Merkle root 值进行比对。 <br/></p>
<p>通过 Merkle Proof 提供的数据集，我们就可以把下载8笔交易，计算15次hash，优化成只需3个 hash 值，以及计算4次hash，需要的 Merkle Proof 数量等于Merkle Tree的高度，而Merkle Tree就是一棵完美的平衡二叉树, 树的高度就是 <code>log₂(N)</code>, 所以时间复杂度从O(N)降低成O(logN). <br/></p>
<p>这个比对似乎不明显，但是以1亿交易为例的话，log(1_000_000_000) ~= 27, 也就是只需要 Merkle Proof 提供27个 hash 值即可, 巨大的性能提升. <br/></p>
<h2 id="区块链的不可窜改性"><span class="section-num">5</span> 区块链的不可窜改性</h2>
<p>通过Merkle tree root可以保证交易的不可窜改性，而区块 hash 又能保证区块头部的元数据不被窜改. <br/></p>
<p>因为每个区块都有区块 hash, 区块hash是通过计算头部元数据信息计算出来的: <br/></p>
<p>
<figure>
    
    
    <input type="checkbox" id="zoomCheck-21472" hidden>
    <label for="zoomCheck-21472">
    
    
    <img class="zoomCheck" loading="lazy" src="/ox-hugo/block_hash.jpg"/> 
    
    
    </label>
</figure>
 <br/></p>
<p>只要修改了其中一个元数据值，那么 block hash 就会发生变化，而区块链就是一个单链表，通过后一个区块通过 <code>prev_hash</code> 指向前一个区块，如果 block hash 发生变化，那么后一个区块就无法正确指向前一个区块了，这个链就断了. <br/></p>
<p>如果一个恶意的攻击者修改了一个区块中的某个交易，那么Merkle Hash验证就不会通过。 <br/></p>
<p>所以，他只能重新计算Merkle Hash，然后把区块头的Merkle Hash也修改了。 <br/></p>
<p>这时，我们就会发现，这个区块本身的Block Hash就变了，所以，下一个区块指向它的链接就断掉了, 他就要把后续所有区块全部重新计算并且伪造出来，才能够修改整个区块链； <br/></p>
<p>而要修改后续所有区块，这个攻击者必须掌握全网51%以上的算力才行。 <br/></p>
<p>理论上可行，但是实操难度非常非常非常大. <br/></p>
<h2 id="merkle-tree-版本管理中的应用"><span class="section-num">6</span> Merkle Tree 版本管理中的应用</h2>
<p>除去区块链，Merkle Tree还被应用于类似 Git 和 Mercurial 这样的版本管理系统中，以Git为例, 假如我们Git项目内有4个文件: <br/></p>
<p>
<figure>
    
    
    <input type="checkbox" id="zoomCheck-d3fa3" hidden>
    <label for="zoomCheck-d3fa3">
    
    
    <img class="zoomCheck" loading="lazy" src="/ox-hugo/git_merkle_tree.jpg"/> 
    
    
    </label>
</figure>
 <br/></p>
<p>当你push 代码到远程分支或者从远程分支 pull 代码的时候，Git就计算你的Merkle Tree Root 的值, 比较远程分支的Merkle Tree Root和本地分支的Merkle Tree Root 是否相同: <br/></p>
<p>如果相同，那就不用更新了；如果不同的话它就会检查左节点或者右节点，并且递归下去， <br/>
直到找到是哪些文件发生了修改，只通过网络传输修改部分的内容, 以提高传输效率. <br/></p>
<p>不过Git实际用的是Merkle Tree的变体，并不是直接使用Merkle Tree. <br/></p>
<p>除些之外, Merkle Tree 还在 Cassandra, DynamoDB 这样的NoSQL数据库中被用于检查不同节点数据的一致性, 细节可以看下这个 <a href="https://stackoverflow.com/questions/5486304/explain-merkle-trees-for-use-in-eventual-consistency">Stackoverflow 问题</a>。 <br/></p>
<h2 id="参考"><span class="section-num">7</span> 参考</h2>
<ul>
<li><a href="https://alexromanov.github.io/2022/06/19/bchain-test-7-merkle-tree/">Blockchain for Test Engineers: Merkle Trees</a> <br/></li>
<li><a href="https://medium.com/geekculture/understanding-merkle-trees-f48732772199">Understanding Merkle Trees</a> <br/></li>
<li><a href="https://stackoverflow.com/questions/5486304/explain-merkle-trees-for-use-in-eventual-consistency">Explain Merkle Trees for use in Eventual Consistency</a> <br/></li>
</ul>
<div center class="qr-container">
<img src="/ox-hugo/qrcode_gh_e06d750e626f_1.jpg" alt="qrcode_gh_e06d750e626f_1.jpg" width="160px" height="160px" center="t" class="qr-container" />
公号同步更新，欢迎关注👻
</div>
]]></content:encoded>
    </item>
  </channel>
</rss>
