# 离线重算 Bitcoin Merkle 证明：交易 ID 是否对应给定区块头

整理：链小知（AI 辅助）
资料核对日期：2026-10-12
引用地址：https://lianxiaozhi.com/tools/guides/bitcoin-merkle-proof-header-check
难度：进阶
核验方式：只读核验

读取两个公开浏览器的状态、Merkle 分支和 80 字节区块头，再离线重算。已完成六次公开 GET 和有限样本检查；未验证完整交易、工作量或最佳链。

## 使用工具
- [Blockstream Explorer](https://lianxiaozhi.com/tools/blockstream-explorer) · [官方入口](https://blockstream.info/)
- [mempool.space](https://lianxiaozhi.com/tools/mempool-space) · [官方入口](https://mempool.space/)

## 前置条件
- 准备可读取公开 HTTP 接口的客户端，以及能对二进制字节做 SHA-256 的本地环境；不需要钱包、签名或 API 密钥。
- 只使用 Bitcoin 主网已确认交易。交易 ID、区块哈希和分支哈希为 64 位十六进制字符串，区块头为 160 位十六进制字符串。
- 此任务验证给定交易 ID、分支与给定头之间的哈希关系。区块头和交易 ID 来自公开服务，尚无独立可信链锚点。

## 1. 取得已确认交易的区块身份

分别读取 https://blockstream.info/api/tx/交易ID/status 和 https://mempool.space/api/tx/交易ID/status。保存原始响应、完整 URL 与读取时刻；confirmed 必须为 true，且 block_height、block_hash 存在。未确认、404、429、超时或无法解析时停止，不用其他交易补作成功结果。

本次公开样本 txid 为 e47158e195abcb960741df336d0c39d3b687ddb4edcad9454384dbe519ff2039。两个服务均返回高度 970949、区块哈希 000000000000000000016be5d6cd00660bcbba5b6a55ef74c55af7465d93d5e9。它是历史样本，不是用户转账或平台入账凭据。

核对结果：两个状态响应可复查，网络、交易 ID、确认状态及区块身份一致；未把一致解释成独立节点证明。
依据：[Blockstream Esplora：状态、Merkle proof 与区块头接口](https://raw.githubusercontent.com/Blockstream/esplora/master/API.md)
依据：[实际读取的 Blockstream 已确认样本状态](https://blockstream.info/api/tx/e47158e195abcb960741df336d0c39d3b687ddb4edcad9454384dbe519ff2039/status)
依据：[实际读取的 mempool 已确认样本状态](https://mempool.space/api/tx/e47158e195abcb960741df336d0c39d3b687ddb4edcad9454384dbe519ff2039/status)

## 2. 保存分支与原始区块头

在各服务同一 /api 根路径下读取 /tx/交易ID/merkle-proof，以及 /block/区块哈希/header。前者应有 block_height、pos 和 merkle 数组，后者是 80 字节头的十六进制文本。分支 block_height 与该服务交易状态必须相同；不要把 HTML 错误页、JSON 包装或整个区块正文当作区块头。

样本两服务返回相同的 pos=1 和 13 个分支哈希。pos 从 0 开始，1 表示索引为 1 的叶子；它不是输出编号 vout、当前确认数，也不是区块里只有两笔交易。数组从叶子附近的兄弟节点往根排列，不要排序或逆序。

核对结果：每份分支均配对自己的交易状态与区块头；保留 pos、数组顺序和恰好 80 字节的头。
依据：[Blockstream Esplora：状态、Merkle proof 与区块头接口](https://raw.githubusercontent.com/Blockstream/esplora/master/API.md)
依据：[ElectrumX：get_merkle 的分支顺序与零基索引](https://electrumx.readthedocs.io/en/latest/protocol-methods.html#blockchain-transaction-get-merkle)
依据：[mempool 官方实现：Merkle proof 与区块头请求路径](https://raw.githubusercontent.com/mempool/mempool/master/backend/src/api/bitcoin/esplora-api.ts)
依据：[实际读取的 Blockstream 样本 Merkle 分支](https://blockstream.info/api/tx/e47158e195abcb960741df336d0c39d3b687ddb4edcad9454384dbe519ff2039/merkle-proof)
依据：[实际读取的 mempool 样本 Merkle 分支](https://mempool.space/api/tx/e47158e195abcb960741df336d0c39d3b687ddb4edcad9454384dbe519ff2039/merkle-proof)
依据：[实际读取的 Blockstream 样本原始区块头](https://blockstream.info/api/block/000000000000000000016be5d6cd00660bcbba5b6a55ef74c55af7465d93d5e9/header)
依据：[实际读取的 mempool 样本原始区块头](https://mempool.space/api/block/000000000000000000016be5d6cd00660bcbba5b6a55ef74c55af7465d93d5e9/header)

## 3. 先核对区块头的显示哈希

将头的 160 位十六进制解码为 80 个字节。对这些字节做 SHA-256，再对第一次返回的 32 个原始字节做第二次 SHA-256；把第二次的 32 字节反序后转为十六进制显示，与 status.block_hash 比较。不能哈希十六进制文字的 UTF-8，也不能把第一次哈希转成文字再做第二次。

按从 0 开始的字节偏移，头里的 Merkle root 是 [36,68)，即第 36 至 67 字节；后续比较使用这 32 个内部顺序字节。头哈希相同仅说明这份头的哈希与服务声称的区块 ID 相符，不验证 nBits 难度目标、工作量、前序头链或最佳链。

核对结果：头长度、二次哈希和显示字节顺序分别检查；重算头哈希与状态区块 ID 相同。
依据：[Bitcoin 开发文档：80 字节区块头及 Merkle root 字节顺序](https://developer.bitcoin.org/reference/block_chain.html)
依据：[实际读取的 Blockstream 样本原始区块头](https://blockstream.info/api/block/000000000000000000016be5d6cd00660bcbba5b6a55ef74c55af7465d93d5e9/header)
依据：[实际读取的 mempool 样本原始区块头](https://mempool.space/api/block/000000000000000000016be5d6cd00660bcbba5b6a55ef74c55af7465d93d5e9/header)

## 4. 按索引逐层重算 Merkle root

令 node 为 txid 十六进制解码后的 32 字节反序，index 为 pos。依次把 merkle 中每个哈希解码成 32 字节并反序，得到 sibling。index 为偶数时对 node || sibling 做两次 SHA-256；为奇数时对 sibling || node 做两次 SHA-256。每层用所得原始 32 字节替换 node，并令 index=floor(index÷2)。这里 || 是字节拼接，不是文本连接。

分支处理完后 index 应为 0，node 应与区块头 [36,68) 字节相同。样本按此规则重算的显示根为 29bde428346234017345c4cbd7368acc0aeb100f4694e5b00f5aa60e56c8dd8e；这是最终 node 反序后的十六进制。使用 TXID，不用 WTXID；本文直接采用给定 TXID，没有从原始交易序列化重新计算它，也未做整棵树的重复叶检查。

核对结果：索引奇偶、兄弟节点顺序与内部字节顺序均正确；最终 index=0 且重算根等于头内根。
依据：[ElectrumX：get_merkle 的分支顺序与零基索引](https://electrumx.readthedocs.io/en/latest/protocol-methods.html#blockchain-transaction-get-merkle)
依据：[Bitcoin 开发文档：80 字节区块头及 Merkle root 字节顺序](https://developer.bitcoin.org/reference/block_chain.html)
依据：[Bitcoin Core：交易哈希 Merkle 树及重复叶问题边界](https://raw.githubusercontent.com/bitcoin/bitcoin/master/src/consensus/merkle.cpp)
依据：[实际读取的 Blockstream 样本 Merkle 分支](https://blockstream.info/api/tx/e47158e195abcb960741df336d0c39d3b687ddb4edcad9454384dbe519ff2039/merkle-proof)
依据：[实际读取的 mempool 样本 Merkle 分支](https://mempool.space/api/tx/e47158e195abcb960741df336d0c39d3b687ddb4edcad9454384dbe519ff2039/merkle-proof)

## 5. 用离线负例确认比较确实会失败

保留原文件，另做两份本地副本：一份改变 TXID 的一个十六进制字符，另一份改变第一个分支哈希的一个字符；保持每个哈希仍为 64 位十六进制。分别重复重算，应都与原区块头的根不同。只修改本地输入，不请求服务、不发布交易，也不把坏副本覆盖原始回执。

本次两个服务样本的正确分支均匹配；两个改动副本均不匹配。另用一份独立 Python 离线实现读取保存的公开响应，再次核对两份头哈希、根与最终索引。负例通过说明此样本检查能发现这些改动，不是穷尽攻击场景或证明全部块有效。

核对结果：正确副本通过，两类被改动的副本失败；本地负例与原始公开响应分开保留。
依据：[Bitcoin Core：交易哈希 Merkle 树及重复叶问题边界](https://raw.githubusercontent.com/bitcoin/bitcoin/master/src/consensus/merkle.cpp)
依据：[实际读取的 Blockstream 样本 Merkle 分支](https://blockstream.info/api/tx/e47158e195abcb960741df336d0c39d3b687ddb4edcad9454384dbe519ff2039/merkle-proof)
依据：[实际读取的 mempool 样本 Merkle 分支](https://mempool.space/api/tx/e47158e195abcb960741df336d0c39d3b687ddb4edcad9454384dbe519ff2039/merkle-proof)
依据：[实际读取的 Blockstream 样本原始区块头](https://blockstream.info/api/block/000000000000000000016be5d6cd00660bcbba5b6a55ef74c55af7465d93d5e9/header)
依据：[实际读取的 mempool 样本原始区块头](https://mempool.space/api/block/000000000000000000016be5d6cd00660bcbba5b6a55ef74c55af7465d93d5e9/header)

## 6. 把包含关系与完整验证分开交付

最终记录两个服务各自的状态、分支、原始头、读取时刻、算法、计算根及负例结果。本次六次公开 GET 均返回 HTTP 200，头哈希及分支重算一致。可以说明“给定 TXID 与给定头的 Merkle root 匹配”，不能仅凭服务提供的同一套数据确认它属于独立验证的最佳链。

未取得完整原始交易、完整区块和独立头链，未验证脚本签名、共识规则、累计工作、重组、地址控制或支付用途。两个服务也未证明基础设施独立。交易所是否记账仍需平台自身证据；本教程未连接钱包、转账、广播或进行平台到账测试。

核对结果：报告给定哈希包含关系与实际检查结果，并保留完整交易、链验证、钱包及平台入账的未验证范围。
依据：[Bitcoin 开发文档：80 字节区块头及 Merkle root 字节顺序](https://developer.bitcoin.org/reference/block_chain.html)
依据：[ElectrumX：get_merkle 的分支顺序与零基索引](https://electrumx.readthedocs.io/en/latest/protocol-methods.html#blockchain-transaction-get-merkle)
依据：[Bitcoin Core：交易哈希 Merkle 树及重复叶问题边界](https://raw.githubusercontent.com/bitcoin/bitcoin/master/src/consensus/merkle.cpp)
依据：[实际读取的 Blockstream 已确认样本状态](https://blockstream.info/api/tx/e47158e195abcb960741df336d0c39d3b687ddb4edcad9454384dbe519ff2039/status)
依据：[实际读取的 mempool 已确认样本状态](https://mempool.space/api/tx/e47158e195abcb960741df336d0c39d3b687ddb4edcad9454384dbe519ff2039/status)

## 常见错误
- 把 UTF-8 十六进制文字当原始字节，或每层多做、少做一次哈希。
- TXID 与 WTXID 混用、pos 当作从 1 开始、分支数组被排序或兄弟拼接顺序相反。
- 把服务给出的头哈希和根自洽，当成独立最佳链或完整共识验证。
- 只验一条分支却宣称整棵树无重复叶问题、完整交易有效或平台已经到账。

## 完成检查
- 两份状态、分支和原始 80 字节头均保存，头显示哈希可重算。
- 给定 TXID 的分支根匹配给定头，改动叶子及分支的本地负例失败。
- 输出明确限定为公开历史样本的哈希关系；完整交易、链、钱包和平台到账未验证。

## 相关知识
- [比特币 UTXO 与找零：为什么转一笔账会出现多个输出](https://lianxiaozhi.com/learn/utxo-and-change)
- [区块确认与最终性是什么？交易成功和充值到账为何不同步](https://lianxiaozhi.com/learn/confirmations-and-finality)

## 官方依据
- [Blockstream Esplora：状态、Merkle proof 与区块头接口](https://raw.githubusercontent.com/Blockstream/esplora/master/API.md)
- [Bitcoin 开发文档：80 字节区块头及 Merkle root 字节顺序](https://developer.bitcoin.org/reference/block_chain.html)
- [ElectrumX：get_merkle 的分支顺序与零基索引](https://electrumx.readthedocs.io/en/latest/protocol-methods.html#blockchain-transaction-get-merkle)
- [mempool 官方实现：Merkle proof 与区块头请求路径](https://raw.githubusercontent.com/mempool/mempool/master/backend/src/api/bitcoin/esplora-api.ts)
- [Bitcoin Core：交易哈希 Merkle 树及重复叶问题边界](https://raw.githubusercontent.com/bitcoin/bitcoin/master/src/consensus/merkle.cpp)
- [实际读取的 Blockstream 已确认样本状态](https://blockstream.info/api/tx/e47158e195abcb960741df336d0c39d3b687ddb4edcad9454384dbe519ff2039/status)
- [实际读取的 mempool 已确认样本状态](https://mempool.space/api/tx/e47158e195abcb960741df336d0c39d3b687ddb4edcad9454384dbe519ff2039/status)
- [实际读取的 Blockstream 样本 Merkle 分支](https://blockstream.info/api/tx/e47158e195abcb960741df336d0c39d3b687ddb4edcad9454384dbe519ff2039/merkle-proof)
- [实际读取的 mempool 样本 Merkle 分支](https://mempool.space/api/tx/e47158e195abcb960741df336d0c39d3b687ddb4edcad9454384dbe519ff2039/merkle-proof)
- [实际读取的 Blockstream 样本原始区块头](https://blockstream.info/api/block/000000000000000000016be5d6cd00660bcbba5b6a55ef74c55af7465d93d5e9/header)
- [实际读取的 mempool 样本原始区块头](https://mempool.space/api/block/000000000000000000016be5d6cd00660bcbba5b6a55ef74c55af7465d93d5e9/header)
