比特币核心 v31.0 的发行说明里藏着一个第一次:asmap 数据第一次被直接嵌进官方二进制。在此之前,想用运营商维度给对端分组,你得自己去下载一份 ip_asn.map 文本、转换、放在数据目录里配好路径;现在只要在配置文件里写一行 -asmap=1,节点就用内置的那份映射。内置数据的创建日期是 2026-03-05(对应 PR 34696)。这篇讲清这个”内置版”和”文件版”的行为差异、默认值没变的事实,以及新旧写法迁移时的两个坑。
先回顾 asmap 是干什么的。节点给新连接候选地址分桶(bucketing)时,默认按 IP 前缀划 netgroup——同一台云服务商、同一个大运营商的机器往往落在相邻前缀里。攻击者只要控制某前缀段的地址池,就能用海量”邻居地址”挤满你的地址表,把实际对端聚拢到自己手里。asmap 提供一张 IP 到自治系统号(ASN)的映射,让分桶改按”运营商/托管商”维度进行:同一个 ASN 无论多少地址段,归为同一组,节点的选择器就有了多样性约束的抓手。机制本身早在 0.21 时代就进了核心,卡住普及的一直是那道手工工序:外部映射文件从哪来、多久更新一次、格式对不对。
v31 的变化把工序砍掉了。按 init.cpp 的实现逻辑:官方构建默认开启 WITH_EMBEDDED_ASMAP 编译选项(CMakeLists.txt 中该 option 默认为 ON),二进制里内嵌一份压缩的映射数据;运行时只要 -asmap 以布尔形式给出(写 -asmap 或 -asmap=1),节点就加载内置数据并记录一行日志;只有显式给路径(-asmap=ip_asn.map 这种写法)才走文件读取分支,找不到或解析不了文件仍按原来的错误信息停机。发行说明同时把迁移规则写死:以前裸写 -asmap 不带值会去找数据目录下的 ip_asn.map,现在这种写法等于选内置版——想用外部文件必须明确写出文件名。这是升级排查里最容易踩的语义变化:老配置里裸 -asmap 的节点,升级后悄悄从”读我的文件”变成”用内置数据”,如果你的自定义映射还没备份,行为差异不会有任何报错提示你。
内置版解决了易用性,也带来两个要心里有数的边界。第一是新鲜度:内置数据是构建时刻的快照,而 IP 到 ASN 的归属每月都在变;内置版不会自己更新,发行说明给的就是创建日期而不是”永远新鲜”的承诺。对多样性要求严肃的运维者仍可维持自己的外部文件流程,两分支行为等价,只是来源不同。顺带一个部署细节:官方 CMake 选项 WITH_EMBEDDED_ASMAP 默认 ON,但存在整组功能裁剪的特殊构建路径会显式把它关掉——判断自己的二进制是否带内置数据,看启动配置摘要里 Embedded ASMap 那一行最稳妥。第二是默认值没变:asmap 分桶依旧是关的——发行说明专门强调了”数据虽在,选项依旧 off-by-default”,不显式开 -asmap,节点行为与之前完全一致,不会因为升级就改变对端选择。换句话说,这次嵌入是降低使用门槛,不是改变默认策略。
怎么判断自己开对了?启动日志里会有一行”Opened asmap data … from embedded byte array”,这是内置分支独有的措辞;getnettotals 不显示 asmap 信息,但 getaddrmaninfo 输出的地址表统计能反映 netgroup 聚合效果——启用前后对比,同一个云商的地址不再各算一个组。若日志报的是”Could not find asmap file”,那说明你写成了带文件名的形式而路径不对,两种分支的报错文本在 init.cpp 里是分开的,很好辨认。
版本事实的边界:内置数据存在于官方 v31.0 发行版(自构建若关闭该编译选项则没有内置数据,裸 -asmap 会直接报”Embedded asmap data not available”并停机);-asmap 布尔与文件双形式的规则、外部文件默认文件名行为变化,均以 v31.0 发行说明为准;v30 及更早版本没有内置分支,裸 -asmap 走的是找 ip_asn.map 的老逻辑。
风险提示:对端多样性是节点抗Sybil能力的一环,但任何分桶策略都不是绝对防御;本文描述的是节点配置行为,不构成投资建议。

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