前言
Merkle根是通過將成對的txid散列一起創(chuàng)建的,它為區(qū)塊中的所有事務(wù)提供了一個簡短但唯一的認(rèn)證。
然后將這個merkle根用作于區(qū)塊頭中的字段,這意味著每個區(qū)塊頭將對區(qū)塊內(nèi)的每個事務(wù)都有一個簡潔的表示。
本教程將演示如何計算merkle根字段。
先決條件
本教程將需要訪問比特幣節(jié)點。我們建議以regtest模式配置節(jié)點進(jìn)行,這樣我們就可以自由地玩各種場景,而不必浪費真正的BTC。但是您也可以針對testnet或mainnet配置執(zhí)行這些操作。
在深入到Merkle樹之前,讓我們先了解一下它們的操作所需的專業(yè)術(shù)語,稱為hash函數(shù)或trapdoor函數(shù)。這些函數(shù)在一個方向上很容易計算,但在沒有特殊信息的情況下(稱為“陷阱門”)很難在相反的方向上計算(求逆)。Trapdoor功能廣泛用于密碼學(xué)。散列函數(shù)是可用于將任意大小的數(shù)字?jǐn)?shù)據(jù)映射到固定大小的任何函數(shù),輸入數(shù)據(jù)的細(xì)微差異會導(dǎo)致輸出數(shù)據(jù)的很大差異。
其中一些散列函數(shù)包括md5、sha1和sha256。
使用sha256的示例
gr0kchain@bitcoindev $ echo -en “Hello World” | openssl dgst -sha256
a591a6d40bf420404a011733cfb7b190d62c65bf0bcda32b57b277d9ad9f146e
這里我們提供數(shù)據(jù)Hello World并將其傳遞到opnessl命令,并帶有sha256的摘要標(biāo)志。我們在這里收到的輸出是輸入數(shù)據(jù)的認(rèn)證a591a6d40bf420404a011733cfb7b190d62c65bf0bcda32b57b277d9ad9f146e。任何在相同輸入數(shù)據(jù)上使用sha256的人都會產(chǎn)生相同的哈希值。對數(shù)據(jù)的輕微更改會導(dǎo)致完全不同的哈希值。
gr0kchain@bitcoindev $ echo -en “Hello World.” | openssl dgst -sha256
f4bb1975bf1f81f76ce824f7536c1e101a8060a632a52289d530a6f600d52c92
關(guān)于merkle樹的一些背景
在前面的示例中,我們簡要介紹了如何從任意輸入數(shù)據(jù)生成唯一的認(rèn)證。當(dāng)我們需要為大量數(shù)據(jù)提供加密證明時,這非常有用。這些數(shù)據(jù)可以用所謂的merkle或hash樹表示。Merkle Trees是一種數(shù)據(jù)結(jié)構(gòu),您可以從中派生與前面所指出的相同的哈希。
merkle樹的一個特性是,葉節(jié)點層中的任何更改都將導(dǎo)致完全不同的merkle根散列。因此,我們可以使用這個數(shù)據(jù)結(jié)構(gòu)來驗證一組數(shù)據(jù)的完整性。
從命令行計算merkle根目錄
讓我們完成生成merkle root所需的步驟:
1、生成一個新地址。
gr0kchain@bitcoindev $ bitcoin-cli getnewaddress
mgKkU7NQsDrMZ6uY1J7on9TyKKeH3FNnhH
2、將比特幣發(fā)送到新地址。
gr0kchain@bitcoindev $ bitcoin-cli sendtoaddress mgKkU7NQsDrMZ6uY1J7on9TyKKeH3FNnhH 1
a99011a19e9894753d6c65c8fa412838ea8042886537588e7205734d5de8956d
3、生成新區(qū)塊。
gr0kchain@bitcoindev $ bitcoin-cli generate 1
[
“1e871187ba510207d88f1bb0aa1895fb2420066277fdbba7c857b339810dfcec”
]
4、獲取區(qū)塊的信息。
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”
}
這里我們可以看到該塊的兩個事務(wù)標(biāo)識符為3bd3a1309a518c381248fdc26c3a6bd62c35db7705069f59206684308cc237b3(我們的coinbase)和a99011a19e9894753d6c65c8fa412838ea8042886537588e7205734d5de8956d(我們上面執(zhí)行的事務(wù)的標(biāo)識符)
5、接下來,我們需要將這些字節(jié)順序從大到小顛倒過來(網(wǎng)絡(luò)字節(jié)順序)
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刪除所有本地化設(shè)置。
6、連接這些值并從二進(jìn)制數(shù)據(jù)計算sha256摘要
gr0kchain@bitcoindev $ echo -en “b337c28c30846620599f060577db352
cd66b3a6cc2fd4812388c519a30a1d33b6d95e85d4d7305728e583765884280e
a382841fac8656c3d7594989ea11190a9” | xxd -r -p | sha256
c1f8c1f3b52135cf7f9d0f9422d6d826f4097631615fcc44e3ec70461c27b7b2
7、將此值轉(zhuǎn)換為二進(jìn)制,并在輸出上執(zhí)行另一個sha256操作
gr0kchain@bitcoindev $ echo -en “c1f8c1f3b52135cf7f9d0f9422d6d82
6f4097631615fcc44e3ec70461c27b7b2” | 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
我們現(xiàn)在有來自bitcoin-cli getblock命令的原始merkleroot值! 您可以根據(jù)需要重復(fù)此過程。
只包含coinbase事務(wù)的區(qū)塊的merkle根的異常
上述過程的一個例外是為包含單個事務(wù)的區(qū)塊生成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事務(wù)的事務(wù)id相同。還有另一種情況,如果葉節(jié)點的數(shù)量不均勻,則將現(xiàn)有的tx id附加到葉節(jié)點列表以計算第一級散列對。
結(jié)論
在本教程中,我們研究了hash函數(shù)、merkle樹以及如何計算merkle根。
評論
查看更多