MerkleTree in BTC
Merkle 树是一种用于高效且安全地验证大数据结构完整性和一致性的哈希树。它在比特币网络中起到至关重要的作用。Merkle 树是一种二叉树结构,其中每个叶子节点包含数据块的哈希值,每个非叶子节点包含其子节点哈希值的组合哈希。
比特币网络中的 Merkle 树
在比特币区块链中,每个区块包含多个交易。为了高效地验证区块内的交易,比特币使用了 Merkle 树。区块头包含一个 Merkle 根(Merkle Root),代表了该区块内所有交易的哈希摘要。
Merkle 树的构建
- 叶子节点:每笔交易的哈希值被用作叶子节点。
- 非叶子节点:每对叶子节点的哈希值被组合并哈希,形成上一级节点。这个过程递归进行,直到形成唯一的根节点,即 Merkle 根。
Merkle 树的生成示例
假设一个区块包含四笔交易 \(T1\)、\(T2\)、\(T3\) 和 \(T4\)。生成 Merkle 树的步骤如下:
计算每笔交易的哈希值 \(H1\)、\(H2\)、\(H3\)、\(H4\):
\[H1 = \text{Hash}(T1)
\]\[H2 = \text{Hash}(T2)
\]\[H3 = \text{Hash}(T3)
\]\[H4 = \text{Hash}(T4)
\]计算相邻交易哈希的组合哈希 \(H12\) 和 \(H34\):
\[H12 = \text{Hash}(H1 || H2)
\]\[H34 = \text{Hash}(H3 || H4)
\]计算根节点哈希 \(H1234\):
\[H1234 = \text{Hash}(H12 || H34)
\]
最终,\(H1234\) 就是包含这四笔交易的 Merkle 根。
Merkle 树的作用
- 验证交易:通过 Merkle 树,可以高效地验证某笔交易是否包含在某个区块中,而不需要检查整个区块。
- 轻客户端(SPV):简化支付验证(SPV)客户端可以通过请求区块头和所需交易的 Merkle 路径来验证交易,而不需要下载整个区块链。
Merkle 路径验证
假设我们要验证交易 \(T3\) 是否在某个区块中:
- 获取交易 \(T3\) 的哈希 \(H3\)。
- 获取 \(H3\) 的相邻哈希 \(H4\)。
- 计算组合哈希 \(H34 = \text{Hash}(H3 || H4)\)。
- 获取 \(H34\) 的相邻哈希 \(H12\)。
- 计算根节点哈希 \(H1234 = \text{Hash}(H12 || H34)\) 并与区块头中的 Merkle 根比较。
如果计算出的根哈希值与区块头中的 Merkle 根匹配,则验证成功,说明交易 \(T3\) 包含在该区块中。
btcd 中的 Merkle 树实现
在 btcd 中,Merkle 树的实现主要在 blockchain/merkle.go 文件中。以下是该文件中关键部分的详细说明:
// HashMerkleBranches 采用两个哈希值,分别视为左树节点和右树节点,并返回它们串联的哈希值。用于帮助生成默克尔树
func HashMerkleBranches(left, right *chainhash.Hash) chainhash.Hash {
// Concatenate the left and right nodes.
var hash [chainhash.HashSize * 2]byte
copy(hash[:chainhash.HashSize], left[:])
copy(hash[chainhash.HashSize:], right[:])
return chainhash.DoubleHashRaw(func(w io.Writer) error {
_, err := w.Write(hash[:])
return err
})
}
// BuildMerkleTreeStore creates a merkle tree from a slice of transactions,
// stores it using a linear array, and returns a slice of the backing array. A
// linear array was chosen as opposed to an actual tree structure since it uses
// about half as much memory. The following describes a merkle tree and how it
// is stored in a linear array.
func BuildMerkleTreeStore(transactions []*btcutil.Tx, witness bool) []*chainhash.Hash {
// Calculate how many entries are required to hold the binary merkle
// tree as a linear array and create an array of that size.
nextPoT := nextPowerOfTwo(len(transactions))
arraySize := nextPoT*2 - 1
merkles := make([]*chainhash.Hash, arraySize)
// Create the base transaction hashes and populate the array with them.
for i, tx := range transactions {
// If we're computing a witness merkle root, instead of the
// regular txid, we use the modified wtxid which includes a
// transaction's witness data within the digest. Additionally,
// the coinbase's wtxid is all zeroes.
switch {
case witness && i == 0:
var zeroHash chainhash.Hash
merkles[i] = &zeroHash
case witness:
wSha := tx.MsgTx().WitnessHash()
merkles[i] = &wSha
default:
merkles[i] = tx.Hash()
}
}
// Start the array offset after the last transaction and adjusted to the
// next power of two.
offset := nextPoT
for i := 0; i < arraySize-1; i += 2 {
switch {
// When there is no left child node, the parent is nil too.
case merkles[i] == nil:
merkles[offset] = nil
// When there is no right child, the parent is generated by
// hashing the concatenation of the left child with itself.
case merkles[i+1] == nil:
newHash := HashMerkleBranches(merkles[i], merkles[i])
merkles[offset] = &newHash
// The normal case sets the parent node to the double sha256
// of the concatenation of the left and right children.
default:
newHash := HashMerkleBranches(merkles[i], merkles[i+1])
merkles[offset] = &newHash
}
offset++
}
return merkles
}
BuildMerkleTreeStore 从交易切片创建默克尔树,使用线性数组存储它,并返回支持数组的切片。选择线性数组而不是实际的树结构,因为它可以节省大约一半的内存。下面描述了merkle树以及它如何存储在线性数组中。
root = h1234 = h(h12 + h34)
/ \
h12 = h(h1 + h2) h34 = h(h3 + h4)
/ \ / \
h1 = h(tx1) h2 = h(tx2) h3 = h(tx3) h4 = h(tx4)
以上存储为线性数组如下:
[h1 h2 h3 h4 h12 h34 root]
如上所示,默克尔根始终是数组中的最后一个元素。
声明:本作品采用署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)进行许可,使用时请注明出处。
Author: mengbin
blog: mengbin
Github: mengbin92
cnblogs: 恋水无意
腾讯云开发者社区:孟斯特
MerkleTree in BTC的更多相关文章
- 区块链基础认识-BTC
1.什么是区块链 a.定义: 从本质上来说区块链就是一种通过将用户的某种特定信息(比如交易信息),通过很多台计算机记录保存并同步的过程,每个区块都记录了对应的交易信息,将这些交易信息串联起来就形成了所 ...
- js 校验 btc eth 地址
NPM 安装 npm install wallet-address-validator Browser <script src="wallet-address-validator.mi ...
- ECC椭圆曲线以及计算出公钥的过程(BTC为例)
ECC概念 全称 “ Ellipse Curve Cryptography ” means “ 椭圆 曲线 密码学 ”. 传统加密方法大多基于大质数因子分解困难性来实现,ECC则是通过椭圆曲线方程式 ...
- [转]BTC RPC API GetTransaction
本文转自: GetTransaction GetTransaction gettransaction调用获取指定钱包内交易的详细信息.该调用需要节点 启用钱包功能. 参数 TXID:要查看详情的交易I ...
- [转]BTC手续费计算,如何设置手续费
本文转自:https://blog.csdn.net/servletcome/article/details/81941334 首先BTC的交易手续费和交易金额是没有关系的.不要误认为交易的金额越大手 ...
- 挖矿程序的工作原理(BTC为例)
Mining时代进化:CPU挖矿 -> GPU挖矿 -> FPGA挖矿 -> ASIC挖矿CPU挖矿时代:SENGENERATEGPU挖矿时代:GETWORK Miner:挖矿的程序 ...
- 区块链区块的生成和链接,比特币btc的产生,UTXO的生成和消耗,比特币系统
区块链区块的生成和链接,比特币btc的产生,UTXO的生成和消耗,比特币系统 区块链区块的生成和链接,比特币btc的产生,UTXO的生成和消耗,比特币系统
- BTC和BCH 区别和联系?
在比特币刚刚出现的时期,中本聪对区块的大小限制在1M.这种限制既保障性能较弱的个人电脑能够参与其中,同时也起到了防止攻击者让比特币网络超载的风险发生,毕竟那时系统还很脆弱.在1M的限制下,10分钟一个 ...
- BTC钱包对接流程
BTC钱包对接流程: 部署钱包节点 分析钱包的API 通过JSON-RPC访问钱包API 部署测试 1.部署钱包节点 虚拟币交易平台对接所有的虚拟币之前,都要在自己的服务器上部署一个钱包节点,首先要找 ...
- 比特币BTC全节点搭建
比特币BTC全节点搭建 #环境 ubuntu 16.4 #硬盘500GB #截止2018-12-31磁盘占用超过230GB #客户端安装 #下载页面 #https://bitcoin.org/zh_C ...
随机推荐
- virtualbox Ubuntn配置多站点
1.编辑站点文件: nano /etc/nginx/sites-available/default cd /etc/nginx/sites-available/ ls2. 把default的设置文件 ...
- HTTP 报文详解
报文的语法 所有的 HTTP 报文都可以分为两类:请求报文和响应报文.请求报文会向 Web 服务器请求一个动作,响应报文会将请求的结果返回给客户端.请求和响应报文的基本报文结构相同 请求报文的格式: ...
- java学习之旅(day.04)
运算符 算术运算符:+ ,- ,* ,/,%(取余或模运算), ++(自增),-- (自减) 赋值运算符:= 关系运算符:>, <,>=, <=, ==, !=(不等于),in ...
- 1 - 香橙派硬件PWM控制sg90舵机
本人机械电子专业的大一学生一枚,这是我在博客园的第一篇随笔 2024年4月份我在二手平台花费300大洋入手了香橙派zero3和3B,买回来后一开始是装上ubuntu跑QQ机器人和minecraft ...
- Java计算百分比保留整数
1.Java计算百分比保留整数的方法步骤 在Java中计算百分比并保留整数,通常涉及以下步骤: (1)计算原始数值与基准数值的百分比(通常使用 (原始数值 / 基准数值) * 100 的公式). (2 ...
- Swoole 源码分析之 Coroutine 协程模块
首发原文链接:Swoole 源码分析之 Coroutine 协程模块 大家好,我是码农先森. 引言 协程又称轻量级线程,但与线程不同的是:协程是用户级线程,不需要操作系统参与.由用户显式控制,可以在需 ...
- 申请并部署免费的 SSL/TLS 证书
对于囊中羞涩的我们来说,只要能白嫖,就绝不乱花钱.惯常申请免费 SSL/TLS 证书的途径有: 各大云服务平台限量提供.比如阿里云会给每个账号每年 20 个证书的申请额度.缺点是不支持泛域名,一年后须 ...
- 阿里云ECS后台CPU占用100%,top却找不到
上周公司阿里云服务器后台报警,CPU占用瞬间飙升到100%: 首先想到使用top命令查询CPU占用详情: 发现进程占用CPU都比较低,在CPU占用一栏发现只有ni的占用比较高. 先了解一下CPU相关监 ...
- LeetCode 692. Top K Frequent Words 前K个高频单词 (Java)
题目: Given a non-empty list of words, return the k most frequent elements. Your answer should be sort ...
- Python + redis操作Redis数据库
Redis redis是一个key-value存储系统.和Memcached类似,它支持存储的value类型相对更多,包括string(字符串).list(链表).set(集合).zset(sorte ...