记录黑客技术中优秀的内容,传播黑客文化,分享黑客技术精华

比特币区块链哈希树(MerkleRoot)的计算方法

2021-01-30 23:48

比特币区块链哈希树(MerkleRoot)的计算方法

在比特币代码里 block.h 头文件里声明区块头的结构,有下面几个字段,其中有一个叫哈希树(MerkleRoot) 的字段,它的作用是可以校验当前区块里所有的交易记录。

class CBlockHeader
{
public:
    // header
    int32_t nVersion;
    uint256 hashPrevBlock;
    uint256 hashMerkleRoot;
    uint32_t nTime;
    uint32_t nBits;
    uint32_t nNonce;
        //...
};

MerkleRoot 是将当前区块里的所有交易记录的 Hash 使用二叉树的方式,层层相加并计算出新的 Hash,直到最后一个节点 Hash 就是MerkleRoot,这样只要有一笔交易出现被篡改,很容易定位到这笔交易。比如一个区块里有 4 条交易记录,每条交易记录的 Hash 我们分别定义成 H1、H2、H3、H4 变量,计算 MerkleRoot 的方法是下面这样的步骤。

(1) H1 和 H2 做一次大小端反转,然后相加计算出一个Hash,生成一个节点叫 H12。

(2) H3 和 H4 做一次大小端反转,然后相加计算出一个Hash,生成一个节点叫 H34。

(3) H12 和 H34 相加计算出一个Hash,最后的节点得到的 Hash 还需要做一次大小端反转,得到的结果就是 MerkleRoot。

步骤如下图所示:

每一次计算 Hash 是通过两次 sha256,最终得到计算 MaerkleRoot 的计算公式是:

sha256(sha256(sha256(sha256(H1+H2))+sha256(sha256(H3+H4))))

上面我们看到是交易数量是双数,如果交易数量是单数该怎么处理?比如只有 3 个交易,H1 和 H2 的处理没有变化,只是处理的过程会把 H3+H3 计算出一个 Hash 做为上层节点,如下图所示:

还有一种情况,如果交易数量只有一个呢?只有一个交易数量,不需要进行任何计算,直接将第一笔的交易 Hash 做为 MerkleRoot,比如区块高度是 0,也就是第一个区块,看到它的 MerkleRoot 和第一笔交易的 Hash 是完全一样的。如果区块里有两笔交易,H1+H2 计算 Hash 得到的 H12 节点是最后的根节点,也就是 MaerkleRoot。下面我们尝试在本地验证 MerkleRoot 计算的过程,比如找到区块高度 181,这个区块里有两笔交易,第一笔交易的 Hash 是8347cee4a1cb5ad1bb0d92e86e6612dbf6cfc7649c9964f210d4069b426e720a,大小端转换反转过后的十六进制数据是:

0a 72 6e 42 9b 06 d4 10 f2 64 99 9c 64 c7 cf f6 db 12 66 6e e8 92 0d bb d1 5a cb a1 e4 ce 47 83

第二笔交易的 Hash 是 a16f3ce4dd5deb92d98ef5cf8afeaf0775ebca408f708b2146c4fb42b41e14be 大小端转换反转过后的十六进制数据是:

be 14 1e b4 42 fb c4 46 21 8b 70 8f 40 ca eb 75 07 af fe 8a cf f5 8e d9 92 eb 5d dd e4 3c 6f a1

将两个交易记录的 Hash 大小端反转后再相加在一起,组合的结果如下:

0a726e429b06d410f264999c64c7cff6db12666ee8920dbbd15acba1e4ce4783be141eb442fbc446218b708f40caeb7507affe8acff58ed992eb5ddde43c6fa1

然后计算 sha256,第一次计算的结果是 4bb234b71d205dba7936c5e6241e1666479e56f0e370e7725de2c99e6cf5de81,如下图所示:

第二次计算的 sha256 的结果是 366c2a0915f05db4b450c050ce7165acd55f823fee51430a8c993e0bdbb192ed,最后得到的 Hash 需要做一次大小端转换,得到的 merkleRoot 是 ed92b1db0b3e998c0a4351ee3f825fd5ac6571ce50c050b4b45df015092a6c36。

还可以编写 010editor 脚本来实现,具体代码如下:

uchar sha256[32];
int count=ChecksumAlgBytes(CHECKSUM_SHA256,sha256,0,0,"",-1,-1);
Printf("sha256: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n", 
sha256[0], sha256[1],sha256[2], sha256[3],sha256[4], sha256[5], sha256[6], sha256[7],sha256[8], 
sha256[9],sha256[10], sha256[11],sha256[12], sha256[13], sha256[14], sha256[15], sha256[16],
sha256[17],sha256[18], sha256[19], sha256[20], sha256[21], sha256[22], sha256[23], sha256[24],
sha256[25], sha256[26], sha256[27], sha256[28], sha256[29], sha256[30], sha256[31]);

uchar H12[32];
count=ChecksumAlgArrayBytes(CHECKSUM_SHA256,H12,sha256,32,"",-1,-1);

//大小端转换反转
Printf("merkleRoot: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n", 
H12[31], H12[30], H12[29], H12[28], H12[27], H12[26], H12[25], H12[24],
H12[23], H12[22], H12[21], H12[20], H12[19], H12[18], H12[17], H12[16], 
H12[15], H12[14], H12[13], H12[12], H12[11], H12[10], H12[9], H12[8], 
H12[7], H12[6], H12[5], H12[4], H12[3], H12[2], H12[1], H12[0]);

输出的结果和我们手动用 010editor 验证的是一样的。

sha256: 4bb234b71d205dba7936c5e6241e1666479e56f0e370e7725de2c99e6cf5de81
merkleRoot: ed92b1db0b3e998c0a4351ee3f825fd5ac6571ce50c050b4b45df015092a6c36

转载请注明:exchen's blog » 比特币区块链哈希树(MerkleRoot)的计算方法


知识来源: https://www.exchen.net/bitcoin-blockchain-merkleroot.html

阅读:189385 | 评论:0 | 标签:区块链/比特币 区块链 比特币

想收藏或者和大家分享这篇好文章→复制链接地址

“比特币区块链哈希树(MerkleRoot)的计算方法”共有0条留言

发表评论

姓名:

邮箱:

网址:

验证码:

黑帝公告 📢

永久免费持续更新精选优质黑客技术文章Hackdig,帮你成为掌握黑客技术的英雄

广而告之 💖

标签云 ☁