首页
/ Bitcoin Core 嵌入式 ASMap 数据:IP 前缀到 ASN 映射的数据来源、协作流程与构建集成

Bitcoin Core 嵌入式 ASMap 数据:IP 前缀到 ASN 映射的数据来源、协作流程与构建集成

2026-09-04 09:01:08作者:宣聪麟

本文以 嵌入式 ASMap 数据说明文档 为核心,系统讲解 Bitcoin Core 中 -asmap 功能背后的 ASMap 数据是如何采集、交叉验证、编码并嵌入发行版二进制的:包括 RPKI/IRR/Routeviews 三类数据源的优先级机制、多人协作的确定性构建与签名流程、asmap-tool.py 编码工具链,以及数据从 src/node/data/ip_asn.dat 经 CMake 编译定义到 NetGroupManager 分桶的完整源码链路。读完后,你可以复现 ASMap 文件的编码与校验步骤,并理解发行版更新内嵌 ASMap 数据的具体操作方式。

背景:为什么需要按 ASN 分桶

ASMap 功能(通过 -asmap 选项启用)允许 Bitcoin Core 在 netgroup 分桶时,使用对等节点自治系统的 ASN(Autonomous System Number,可理解为 ISP/主机商标识),而不是默认的 IP 前缀分桶。默认行为下,分桶依据 IP 前缀划分,但这无法防止一个大型主机商主导连接集合——因为这类公司通常控制着大量互不连续的 IP 段,其不同 IP 段会散落在不同的 IP 前缀桶中。改用 ASN 分桶后,一个节点就不会连接到同一个 AS 下的多个节点,从而提升对等节点集合的多样性。

从源码注释可以进一步确认这一动机:src/netgroup.h 中对 NetGroupManager 的注释明确写道,按 AS 分桶是为了让节点连接到多样化的对等方集合,"This is done in response to Erebus attack, but also to generally diversify the connections every node creates, especially useful when a large fraction of nodes operate under a couple of cloud providers"(这是对 Erebus 攻击的回应,也是在大量节点集中于少数云服务商时的普遍性多样化手段)。

启用 ASMap 的前提是拥有"IP 前缀 → ASN"的映射数据。该数据可以通过外部文件提供,但为了在用户无法自行提供文件时仍可用该功能,Bitcoin Core 还在构建中嵌入了一份默认的映射数据。这就是本文档的主体内容。

数据源与 Kartograf 工具

ASMap 本质上是 IP 前缀到 ASN 的映射,即某一刻互联网路由表的快照。这份文档指出了数据面临的固有难题:

  • 路由表的部分内容波动性极高,且 BGP 协议本身存在已知漏洞,因此采集数据并证明其一致性非常困难;
  • 仅从单一可信来源获取数据同样成问题(单点信任风险)。

为尽可能化解这些不确定性,社区创建了 Kartograf 工具(asmap/kartograf 项目)。Kartograf 的映射数据来自三类来源,且优先级明确:

  1. RPKI 与 IRR:这两者本身就是用于防御 BGP 安全问题的安全机制,因此被认为更安全,其数据优先采用;
  2. Routeviews:一个可信的 BGP 流量收集者,仅用于 RPKI 和 IRR 未覆盖的 IP 地址空间

Kartograf 解析、处理并合并这些数据源的过程是确定性的:给定这些不同来源的原始下载文件,任何人都可以自行构建映射文件,并验证其结果与其他用户一致。而在地图文件被 Bitcoin Core 使用之前,还需要一步编码——这一步使用 contrib/asmap 中的 asmap-tool.py 完成,该步骤同样具有确定性。

多人协作的确定性采集与签名流程

即使处理过程是确定性的,获取初始输入数据时的高波动性依然是挑战:如果用户不想信任 ASMap 文件的单一制作者,怎么办?文档给出的答案是多方同时采集、多数结果共识

  • 多个用户可以在完全相同的时刻启动下载过程,这样他们下载到的数据大概率足够相似,最终会产出相同的输出文件;
  • 这一过程由 asmap-data 项目(asmap/asmap-data 仓库)定期组织协作;
  • 若某个结果哈希被至少 5 位参与者签名确认,则对应的 ASMap 文件会被合入该仓库供公开使用;
  • 合入还要求至少另外 2 位审查者确认上述流程被正确执行、且编码步骤产出的文件哈希一致;
  • 新文件会持续地创建,但没有中央计划或固定时间表。

这个"确定性流程 + 多方独立执行 + 签名与审查"的组合,使得嵌入式 ASMap 数据在不依赖单点信任的前提下具备可验证性。

编码工具链:asmap-tool.py

contrib/asmap/README.md 说明,ASMap 文本文件体积较大,需编码为二进制格式后才能与 -asmap 配合使用。asmap-tool.py 提供四类操作:

python3 asmap-tool.py encode /path/to/input.file /path/to/output.file
python3 asmap-tool.py decode /path/to/input.file /path/to/output.file
python3 asmap-tool.py diff /path/to/first.file /path/to/path/to/second.file
python3 asmap-tool.py diff_addrs /path/to/first.file /path/to/second.file addrs.file

(以上命令按 README 原样整理,diff 一条的第二个参数应为 /path/to/second.file。)各命令要点:

  • encode:将文本 ASMap 编码为二进制。--fill/-f 标志可通过"若相邻网段已有 ASN 分配,则对未映射网段推断分配"进一步压缩输出;但该过程是有损的(丢失哪些网段原本未分配的信息),且仅当输入 ASMap 足够完整、目标是省空间且不打算日后做 diff 时才建议使用;
  • decode:反向解码;--fill 同样会重分配子网以减小体积,--non-overlapping/-n 则输出严格不重叠的网段范围;
  • diff:比较两个 ASMap 文件,输出网段 ASN 分配状态的变化,包括三种状态:重新分配到新 AS(AS26496 # was AS20738)、仅存在于第一个文件(# 220.157.65.0/24 was AS9723)、仅存在于第二个文件(# was unassigned);支持 --ignore-unassigned/-i 忽略新增网段;
  • diff_addrs:结合两个 ASMap 与本机已知节点列表(由 bitcoin-cli getnodeaddresses 导出),只报告本机实际对等方 IP 所经历的 AS 变化,例如:
bitcoin-cli getnodeaddresses 0 > addrs.json
python3 asmap-tool.py diff_addrs path/to/first.file path/to/second.file addrs.json

README 还提示:数据量较大时上述命令可能需要几分钟,建议用 pypy3 加速。

源码链路:嵌入数据如何进入二进制

嵌入过程由构建系统完成。CMakeLists.txt 定义了开关:

option(WITH_EMBEDDED_ASMAP "Embed default ASMap data." ON)

默认开启;仅当启用 BUILD_FOR_FUZZING 时会被强制关闭(见 CMakeLists.txt 附近的 set(WITH_EMBEDDED_ASMAP OFF),该分支同时关闭了钱包、GUI 等目标)。

开启后,src/CMakeLists.txt 中:

if(WITH_EMBEDDED_ASMAP)
  target_compile_definitions(bitcoin_node PRIVATE ENABLE_EMBEDDED_ASMAP=1)
  include(TargetDataSources)
  target_raw_data_sources(bitcoin_node NAMESPACE node::data
    node/data/ip_asn.dat
  )
endif()

即:向 bitcoin_node 目标注入 ENABLE_EMBEDDED_ASMAP=1 编译定义,并把 src/node/data/ip_asn.dat 这份原始数据以 node::data 命名空间生成头文件形式内联进二进制。ip_asn.dat 正是文档"Release process"一节要求替换的那个文件——它位于 src/node/data/ 下。

运行时加载:外部文件与内嵌数据的选择逻辑

启动阶段的加载逻辑在 src/init.cpp 中。-asmap 参数的定义(src/init.cpp)说明了两种用法:

  • -asmap=<file>:指定用于节点分桶的 ASN 映射文件;相对路径会被加上"按网络区分的 datadir 前缀";
  • 若参数为布尔值(-asmap-asmap=1):使用二进制中内嵌的映射数据

加载流程为:参数被设置且未取反时,先判断是否给了具体文件路径——给了则解析路径、检查文件存在(不存在则 Could not find asmap file),调用 DecodeAsmap 读取(解析失败则 Could not parse asmap file),并构建 NetGroupManager::WithLoadedAsmap;未给路径时则走内嵌分支,直接引用编译期生成的 node::data::ip_asn 字节数组,先用 CheckStandardAsmap 做标准数据校验(128 位 IPv6 空间),失败会报 Could not read embedded asmap data,数据不存在则报 Embedded asmap data not available(对应 WITH_EMBEDDED_ASMAP 关闭的构建)。最后,无论哪条路径都会记录 asmap 版本:

LogInfo("Using asmap version %s for IP bucketing", asmap_version.ToString());

这里的 asmap 版本由 src/util/asmap.h 中的 AsmapVersion 计算,是一个标识当前所用映射数据的校验和。同一头文件还声明了 Interpret(从 asmap 字节与 IP 解出 ASN)、SanityCheckAsmap(按位宽做健全性检查)和 DecodeAsmap(读取并校验二进制文件)。

NetGroupManagersrc/netgroup.h)对外提供三个工厂:WithEmbeddedAsmapWithLoadedAsmapNoAsmap;核心接口包括 GetGroup(返回地址的分组标识,保证不会向同一 netgroup 的地址发起两条连接)、GetMappedAS(返回到达该地址 BGP 路径上的 AS)、以及 ASMapHealthCheck(分析并记录基于 ASMap 的桶的健康度)。头文件注释还说明:asmap 以 const 方式在构造时初始化,因而线程安全;m_asmap 可以指向运行时加载的 m_loaded_asmap,也可以指向嵌入数据。

发行版更新流程(Release Process)

文档最后一节给出了嵌入式 ASMap 数据在版本发布时的更新规程:

  1. 临近新版本发布时,应当用 asmap-data 仓库中更新的 ASMap 文件替换 ip_asn.dat(当前仓库中该文件位于 src/node/data/ip_asn.dat),使新数据被嵌入发行版;
  2. 优先选择现成的近期文件:理想情况下应已存在最近构建的文件可直接选用;
  3. 必要时发起新一轮构建:若没有合适文件,可按前文描述的协作流程启动一次新的创建过程,以获取用于该版本的新鲜地图。

由于 Kartograf 处理与 asmap-tool.py 编码都是确定性的,且合入 asmap-data 仓库需要多方签名与审查,因此替换 ip_asn.dat 这一动作本身的风险是受控的——开发者只需确认所选文件的哈希与 asmap-data 仓库中已验证的文件一致。

验证与测试支撑

仓库中围绕 asmap 的验证手段与上述文档流程相互印证:

小结

doc/asmap-data.md 描述的是一条"数据可信度"链路:RPKI/IRR 优先 + Routeviews 兜底的采集、Kartograf 确定性处理、多方同时下载与 5 签 2 审的共识机制、asmap-tool.py 确定性编码,最终落到 src/node/data/ip_asn.dat 并由 WITH_EMBEDDED_ASMAP(默认 ON)嵌入发行版;运行期则通过 -asmap 参数在"外部文件"与"内嵌数据"之间切换,并以 AsmapVersion 校验和对外标识当前使用的映射。对运维者而言,日常只需关注 -asmap 的使用与 diff_addrs 对现有对等方影响面的评估;对版本发布者而言,则按 Release process 一节在发布前更新内嵌文件即可。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.12 K
2.72 K
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
904
1.82 K
docsdocs
暂无描述
Markdown
889
5.78 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
854
1.34 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
527
590
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.52 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.33 K
1.45 K
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
540
384
flutter_flutterflutter_flutter
本仓库是 Flutter SDK 与 Flutter Engine 的 OpenHarmony 适配版本,由 CPF-Flutter 团队维护。开发者可使用熟悉的 Flutter 技术栈开发 OpenHarmony 应用,3.35.7 及以后的适配版本可基于本仓库源码构建支持 OpenHarmony 的 Flutter Engine。
Dart
1.17 K
341