内存池替换:避免把多次花费尝试算多笔付款
内存池数据流可能出现多个交易标识,竞争花费同一个比特币旧输出。如果把它们的金额全部累计为付款,就会高估在同一选定链上能够结算的价值。研究应保留每次尝试,同时分开统计已确认结果和未解决的花费尝试族。
BIP 125描述了主动选择替换的信号与策略。它不能保证当前所有节点采用完全相同的转发行为。应记录实际节点软件和观测条件,不能用单个数据流代表整个网络。
用输入冲突定义计数对象
每次尝试保留首次看到时间、交易标识、输入旧输出引用、输出金额、手续费和后续状态。旧输出引用由上一交易标识加输出序号构成。共享输入的竞争交易,不能在同一有效链历史中同时花费该输入。
把共享输入的尝试连接成冲突图。连通部分可以作为调查族,但不一定代表完全相同的付款意图:替换版本可以改金额或收款人,还可能新增输入,把之前独立的组连接起来。因此要保存图,也保存每个版本的输出。
至少分三列:看到的尝试数、冲突族数、确认交易数。内存池记录消失可能来自替换、驱逐、重启或观测缺口。仅凭后续快照里找不到,不能确定是哪种原因;证据不足就保留未解决状态。
假设案例:三个版本、一笔结果
假设虚构钱包广播A、B、C,都花费同一个1 BTC旧输出。A拟向收款人付0.8 BTC,手续费0.0001 BTC;B保留付款,把费提高到0.0002;C再提高到0.0003。各版本找零相应减少,以满足输入输出守恒。
| 观察阶段 | 已看到尝试 | 冲突族 | 确认付款 |
|---|---|---|---|
| A进入数据流 | 1 | 1 | 0 |
| 又看到B和C | 3 | 1 | 0 |
| C被确认 | 3 | 1 | 1 |
如果C按上述收款金额确认,结算付款为0.8 BTC,而不是把三个拟付款相加的2.4 BTC。已结算手续费也是C的费用,不能加总三个版本。但“看到三次尝试”依然是该数据流中有效的运行统计。
如果B换了收款人,就不能把整个族说成同一指令的三次加费。研究付款意图时需要区分改变意图与单纯调费,或者承认意图未知。共享输入只证明竞争关系,不证明动机。
分开转发证据与链上证据
保存各节点何时看到哪个版本,以及是否获得移除原因。不同节点可能看不到同样的替换版本或后代交易。声称全网首次看到,需要超出单节点的覆盖;数据流断线期间不能当成零尝试。
确认后检查实际区块以及被消耗输入。选定链后续改变时,按公开的链口径修订结果,同时保留旧观察历史。没有找到确认成员的族仍是未解决,不能直接写成放弃、欺诈或需求失败。
统计替换率时对齐群体。当天收到的尝试除以当天确认交易,会把确认有延迟的两个群体混在一起。更合适的是追踪同一首次出现群体直到指定截止点,列出待定和跟踪不完整比例。
交付物是尝试到结果的调节账,不是替换付款的操作指南。它可以解释内存池计数为何上升但结算付款未同比增加,不能单凭哈希确定全网需求、客户或动机。
冲突关系还应与后代关系分开。某交易花费未确认父交易新建的输出,是依赖子交易,不一定是竞争替换。若把两者都当冲突,会误合并本来可以依次有效的付款链。建图前检查到底是共享同一个旧输出,还是先创建再消耗不同输出,并把依赖边与冲突边分别保存。
常见问题
三个交易标识一定代表三笔付款吗?
不是。若竞争同一输入,同一选定链上最多一个版本花费它,尝试数与结算数必须分开。
从节点消失就证明被替换吗?
不能。驱逐、重启、确认或观测缺失也可能造成消失,有明确证据才能指定原因。