同步一个巨型区块,或者只想核对某笔交易在原始区块文件里的字节,最费劲的从来不是”要不要下载”,而是”下了用不到的那部分”。Bitcoin Core v31.0 给 REST 接口加了一个新端点 /rest/blockpart/,正好对着这个痛点:按字节范围从指定区块里取数据。这篇讲清它的请求格式、和已有 /rest/block/ 的关系,以及用之前必须先过的两道门。
先交代 REST 本身。比特币核心的节点对外的程序接口有两条:JSON-RPC 和 REST。REST 是更轻的一条,只读、走普通 HTTP GET、不需要 RPC 用户名密码,返回二进制或十六进制。它的开关是 -rest,在 v31.0 源码 init.cpp 里 DEFAULT_REST_ENABLE 为 false——默认关闭,必须显式启动。REST 关掉时什么都不可用;打开后,地址格式统一是 /rest/资源/标识.格式,比如 /rest/block/区块哈希.bin 直接下载整个序列化区块,.hex 则返回十六进制文本。已有的 /rest/headers/、/rest/utxo/ 等端点都遵循这套约定。
v31.0 新增的 /rest/blockpart/ 在这套约定上加了两个查询参数:offset 和 size,含义是从目标区块序列化字节流的第 offset 个字节起取 size 个字节。按 v31.0 源码 rest.cpp 的实现注释,它复用了 rest_block 的主体逻辑,只是把请求区块的哪一段作为参数传下去,并且不支持 JSON 响应——也就是说只能拿 .bin 或 .hex,没有 verbosity 那种结构化输出。从源码读参数的方式也能看出要求:offset 与 size 都必须给且必须是整数,缺一个或写了非数字,请求就不是半块数据而是直接报错。
它解决的具体问题值得说透。序列化区块是一个连续字节流:先是 80 字节区块头,然后是一个表示交易数量的变长整数,之后是一笔接一笔的完整交易。整个区块的序列化长度在一到两 MB 量级(隔离见证数据的折扣决定了实际大小远低于权重上限对应的四百万字节),而你的需求可能只是核对第 N 笔交易的原始字节、拉取 coinbase 的脚本内容、或者比对两份实现产出的某个字节段是否一致。用 /rest/block/ 就得整块传输再本地切片;用 RPC 的 getblock 高 verbosity 模式,节点还要先做一遍反序列化和 JSON 组装。blockpart 把切片挪到了服务端:连接里只走你要的那段字节,带宽和服务端 CPU 都省在刀刃上。对做交叉验证的工具作者——比如用 Rust/Go 独立解析器的审计者——做二分定位坏字节时,这种按范围取数也比反复拉整块快得多。
用法上给一个概念示例(哈希与数值请以你的节点实际数据替换):对区块哈希 H,请求 http://127.0.0.1:8332/rest/blockpart/H.bin?offset=80&size=1024,取回的是跳过 80 字节区块头之后的前 1024 字节,也就是从交易数量字段附近开始的一段原始数据。想验证返回对不对,可以把多段 offset 拼接起来与 /rest/block/ 的整块结果做哈希比对——两者应当逐字节一致,因为走的是同一份磁盘上的区块数据。补一个字节账:80 字节区块头之后,交易数量是变长整数(不超过 253 笔时占 1 字节),第 2 笔到第 N 笔交易的起点等于各前序交易的序列化长度累加,所以先取一小段探明计数与首笔长度,再算出目标交易的 offset,通常两次请求就能定位任意一笔,整块下载在这种工作流里已经完全多余。
边界也要讲明白。第一,这是本地节点的只读接口:REST 由 HTTP 服务在同一台机器(或你显式绑定的地址)上提供,默认没有认证机制,把节点端口暴露到公网前先想清楚隐私与攻击面——这也是文档习惯上建议只对本机或内网开放的原因。第二,它和 RPC 一样受 -rpcworkqueue、线程等资源参数影响,高频范围查询同样是给节点加负载。第三,offset 与 size 是字节而非交易序号,也不做边界补齐:起点落在一笔交易中间、或者超出区块长度,返回的就是对应的原始片段或错误,切分逻辑要调用方自己保证。第四,这个端点自 v31.0 起存在,更早版本没有;如果你管理的节点群里版本混杂,监控脚本应先探测端点是否存在再依赖它。
风险提示:本文描述的是节点软件自带接口的技术用法,开放任何节点接口都存在被滥用的风险,请结合网络环境评估;内容不构成投资建议。

发表评论
还没有评论,来说两句吧。
评论区为展示样式,提交不会被处理。