区块链研究实验室|如何使用Merkle树验证​交易区块

  • 时间:
  • 浏览:71
  • 来源:区块链技术网

前言

本教程旨在简化对比特币如何使用Merkle树验证交易区块的讲解。Merkle根是通过将成对的txid散列一起创建的,它为区块中的所有事务提供了一个简短但唯一的认证。

然后将这个merkle根用作于区块头中的字段,这意味着每个区块头将对区块内的每个事务都有一个简洁的表示。

本教程将演示如何计算merkle根字段。

先决条件

本教程将需要访问比特币节点。我们建议以regtest模式配置节点进行,这样我们就可以自由地玩各种场景,而不必浪费真正的BTC。但是您也可以针对testnet或mainnet配置执行这些操作。

 

在深入到Merkle树之前,让我们先了解一下它们的操作所需的专业术语,称为hash函数或trapdoor函数。这些函数在一个方向上很容易计算,但在没有特殊信息的情况下(称为“陷阱门”)很难在相反的方向上计算(求逆)。Trapdoor功能广泛用于密码学。散列函数是可用于将任意大小的数字数据映射到固定大小的任何函数,输入数据的细微差异会导致输出数据的很大差异。

 

其中一些散列函数包括md5、sha1和sha256。

使用sha256的示例

gr0kchain@bitcoindev $ echo -en "Hello World" | openssl dgst -sha256
a591a6d40bf420404a011733cfb7b190d62c65bf0bcda32b57b277d9ad9f146e

 

这里我们提供数据Hello World并将其传递到opnessl命令,并带有sha256的摘要标志。我们在这里收到的输出是输入数据的认证a591a6d40bf420404a011733cfb7b190d62c65bf0bcda32b57b277d9ad9f146e。任何在相同输入数据上使用sha256的人都会产生相同的哈希值。对数据的轻微更改会导致完全不同的哈希值。

gr0kchain@bitcoindev $ echo -en "Hello World." | openssl dgst -sha256
f4bb1975bf1f81f76ce824f7536c1e101a8060a632a52289d530a6f600d52c92

关于merkle树的一些背景

在前面的示例中,我们简要介绍了如何从任意输入数据生成唯一的认证。当我们需要为大量数据提供加密证明时,这非常有用。这些数据可以用所谓的merkle或hash树表示。Merkle Trees是一种数据结构,您可以从中派生与前面所指出的相同的哈希。

 

merkle树的一个特性是,叶节点层中的任何更改都将导致完全不同的merkle根散列。因此,我们可以使用这个数据结构来验证一组数据的完整性。

从命令行计算merkle根目录

让我们完成生成merkle root所需的步骤:

 

1、生成一个新地址。

 

gr0kchain@bitcoindev $ bitcoin-cli getnewaddress
mgKkU7NQsDrMZ6uY1J7on9TyKKeH3FNnhH

2、将比特币发送到新地址。

 

gr0kchain@bitcoindev $ bitcoin-cli sendtoaddress mgKkU7NQsDrMZ6uY1J7on9TyKKeH3FNnhH 1
a99011a19e9894753d6c65c8fa412838ea8042886537588e7205734d5de8956d

3、生成新区块。

gr0kchain@bitcoindev $ bitcoin-cli generate 1
[
  "1e871187ba510207d88f1bb0aa1895fb2420066277fdbba7c857b339810dfcec"
]

4、获取区块的信息。

gr0kchain@bitcoindev $ bitcoin-cli getblock 

1e871187ba510207d88f1bb0aa1895fb2420066277fdbba7c857b339810dfcec
{
  "hash""1e871187ba510207d88f1bb0aa1895fb2420066277fdbba7c857b

339810dfcec",
  "confirmations"1,
  "size"553,
  "height"132,
  "version"536870912,
  "merkleroot""25c8487847de572c21bff029a95d9a9fecd9f4c2736984b9

79d37258cd47bd1f",
  "tx": [
    "3bd3a1309a518c381248fdc26c3a6bd62c35db7705069f59206684308cc237b3",
    "a99011a19e9894753d6c65c8fa412838ea8042886537588e7205734d5de8956d"
  ],
  "time"1553088284,
  "mediantime"1553087229,
  "nonce"3,
  "bits""207fffff",
  "difficulty"4.656542373906925e-10,
  "chainwork""000000000000000000000000000000000000000000000000000000000000010a",
  "previousblockhash""78c3c76fe213ca9f5a0f616b155341eb12b963ce10107b18c9ff612cfc90843d"
}

这里我们可以看到该块的两个事务标识符为3bd3a1309a518c381248fdc26c3a6bd62c35db7705069f59206684308cc237b3(我们的coinbase)和a99011a19e9894753d6c65c8fa412838ea8042886537588e7205734d5de8956d(我们上面执行的事务的标识符)

 

5、接下来,我们需要将这些字节顺序从大到小颠倒过来(网络字节顺序)

 

gr0kchain@bitcoindev $ (export LC_ALL=C; xxd -revert -plain 

<<< 3bd3a1309a518c381248fdc26c3a6bd62c35db7705069f59206684308cc237b3

 | rev | tr -d '\n' | xxd -plain | tr -d '\n')
b337c28c30846620599f060577db352cd66b3a6cc2fd4812388c519a30a1d33b
gr0kchain@bitcoindev $ (export LC_ALL=C; xxd -revert -plain 

<<< a99011a19e9894753d6c65c8fa412838ea8042886537588e7205734d5de8956d 

| rev | tr -d '\n' | xxd -plain | tr -d '\n')
6d95e85d4d7305728e583765884280ea382841fac8656c3d7594989ea11190a9

注意:此处使用LC_ALL = C删除所有本地化设置。

 

6、连接这些值并从二进制数据计算sha256摘要

 

gr0kchain@bitcoindev $ echo -en "b337c28c30846620599f060577db352cd66b3a6cc2fd4812388c519a30a1d33b6d95e85d4d7305728e583765884280ea382841fac8656c3d7594989ea11190a9" | xxd -r -p | sha256
c1f8c1f3b52135cf7f9d0f9422d6d826f4097631615fcc44e3ec70461c27b7b2

7、将此值转换为二进制,并在输出上执行另一个sha256操作

 

gr0kchain@bitcoindev $ echo -en "c1f8c1f3b52135cf7f9d0f9422d6d826f4097631615fcc44e3ec70461c27b7b2" | xxd -r -p | sha256
1fbd47cd5872d379b9846973c2f4d9ec9f9a5da929f0bf212c57de477848c825

8、最后,颠倒顺序从小到大。

 

gr0kchain@bitcoindev $ (export LC_ALL=C; xxd -revert -plain <<< 1fbd47cd5872d379b9846973c2f4d9ec9f9a5da929f0bf212c57de477848c825 | rev | tr -d '\n' | xxd -plain | tr -d '\n')
25c8487847de572c21bff029a95d9a9fecd9f4c2736984b979d37258cd47bd1f

我们现在有来自bitcoin-cli getblock命令的原始merkleroot值! 您可以根据需要重复此过程。

只包含coinbase事务的区块的merkle根的异常

 

上述过程的一个例外是为包含单个事务的区块生成merkle根。

 

gr0kchain@bitcoindev $ bitcoin-cli generate 1
[
  "78c3c76fe213ca9f5a0f616b155341eb12b963ce10107b18c9ff612cfc90843d"
]
gr0kchain@bitcoindev $ bitcoin-cli getblock 78c3c76fe213ca9f5a0f616b155341eb12b963ce10107b18c9ff612cfc90843d
{
  "hash""78c3c76fe213ca9f5a0f616b155341eb12b963ce10107b18c9ff612cfc90843d",
  "confirmations"1,
  "size"181,
  "height"131,
  "version"536870912,
  "merkleroot""4415425121d3e80d3d733323ecdc981d43b6888241b99c0217a6b7184b021f5e",
  "tx": [
    "4415425121d3e80d3d733323ecdc981d43b6888241b99c0217a6b7184b021f5e"
  ],
  "time"1553088104,
  "mediantime"1553087066,
  "nonce"0,
  "bits""207fffff",
  "difficulty"4.656542373906925e-10,
  "chainwork""0000000000000000000000000000000000000000000000000000000000000108",
  "previousblockhash""0d0c6c9b2c5b48451832c15cf6e8856772df2a0760f8614dbc0734e1e9d7171a"
}

在这里我们可以看到merkle root与coinbase事务的事务id相同。还有另一种情况,如果叶节点的数量不均匀,则将现有的tx id附加到叶节点列表以计算第一级散列对。

结论

猜你喜欢

区块链骗局曝光骗局,看看你上过当没有?

区块链骗局曝光骗局,看看你上过当没有? 随着这一波的下跌,很多人怕是过不好这个年了。 其实按道理说,从6万上方跌到5万,和从43000跌到35000跌幅差不多,但为什么大家的感受如此截然不同?

2022-01-24

从零开发区块链应用(一)-golang配置文件管理工具viper

理解 HTTP 构建的网络应用只要关注两个端--客户端(client)和服务端(server),两个端的交互来自 client 的 request,以及 server 端的 response。所谓的 http 服务器,主要在于如何接受 client 的 request,并向 client 返回 response

2022-01-20

从零开发区块链应用(二)--mysql安装及数据库表的安装创建

varchar 类型的长度是可变的,在创建表时指定了最大长度。定义时,其最大值可以取 0~~65525 之间的任意值。指定了 varchar 类型的最大值以后,其长度可以在 o 到最大长度之间。

2022-01-20

从零开发区块链应用(三)--mysql初始化及gorm框架使用

Gorm 是 golang 的一个 orm 框架,它提供了对数据库操作的封装,使用起来相当便利。所以如果对 mysql 使用操作不熟悉,建议也可以使用 gorm 框架操作 mysql 数据库。

2022-01-20

从零开发区块链应用(四)--自定义业务错误信息

在实际业务开发中,一个条错误信息需要包含两部分内容:直接展示给用户的 message 和用于开发人员 debug 的 error 。message 可能会直接展示给用户,error 是用于 debug 的错误信息,可能包含敏感/内部信息,不宜对外展示

2022-01-20