假设实际费率8 sat/vB:140vB为1120sat,280vB为2240sat;钱包构造前显示的只是估算。
假设实际费率8 sat/vB:140vB为1120sat,280vB为2240sat;钱包构造前显示的只是估算。

图片资料:官方来源

查看完整图片 ↗

一笔比特币转账的实际手续费,是这笔交易的输入总额减去输出总额。你设定的费率乘以交易大小,得到的只是估算值。Bitcoin Core 30 文档把相关量写得很清楚:decoderawtransaction 返回的 vsize 是虚拟交易大小,sendtoaddress 的 fee_rate 参数以 sat/vB 为单位。把费率与 vsize 相乘,可以估算手续费,但最终扣费要看输入输出差额。

教学算例:费率不变,大小翻倍

假设一笔交易 vsize 为 140 vB,费率为 8 sat/vB:

  • 估算手续费 = 140 × 8 = 1120 sat
  • 换算成 BTC:1120 ÷ 100,000,000 = 0.00001120 BTC

另一笔交易 vsize 为 280 vB,费率同样是 8 sat/vB:

  • 估算手续费 = 280 × 8 = 2240 sat
  • 即 0.00002240 BTC

费率没变,vsize 翻倍,估算手续费正好翻倍。这组数字是假设算例,不对应任何真实交易,只用来展示乘法关系。看到手续费异常时,先分别核对 vsize 和费率,而不是只看总金额。

vsize 是按权重折算的虚拟字节

vsize 不是交易的原始字节数。隔离见证交易的 witness 数据按较低权重计入,所以 vsize 通常小于序列化后的 size。Bitcoin Core 30 的 decoderawtransaction 会同时返回 size、vsize 和 weight,查手续费时用的是 vsize,不能拿 size 直接乘费率,两者不能混用。

费率由你或钱包设定。sendtoaddress 的 fee_rate 参数单位为 sat/vB;不填时回落到钱包的手续费估计。费率要按 sat/vB 理解,不要和按字节计价的 sat/B 混读,单位对不上,算出来的数就对不上。

什么在影响 vsize

输入数量、输出数量和脚本类型共同决定交易大小。每多一个输入,就多一段引用前序输出的数据和签名数据;每多一个输出,就多一段金额和脚本。输入类型也有差别:传统 P2PKH 输入与原生隔离见证、Taproot 输入占用的 vB 不同,同样转一笔钱,交易大小可能明显不一样。

还有一个容易忽略的点:钱包构造交易时预估的大小,和签名完成后的最终大小可能不一致。预估偏差会体现在实际扣费上。要确认实际手续费,应以最终交易解码后的 vsize 为准。

设定费率与实际手续费不是一回事

这是最容易算错的地方。钱包里设定的 fee_rate 乘以预估 vsize,得到的只是估算手续费;实际网络手续费是这笔交易的输入总额减去输出总额,实际费率则是实际手续费除以最终 vsize。两者接近,但不保证相等。

因此,看到钱包显示“费率 8 sat/vB”,不能直接认定最终扣费就是预估的那个数。判断方法很简单:拿到最终交易,用输入总额减输出总额算出实际手续费,再除以解码得到的 vsize,得到实际 sat/vB,与设定值对照。

几个常见误判

费率不是比特币价格的百分比,币价涨跌不直接改变 sat/vB。也不存在一个固定最低费率能保证交易被确认;确认时间取决于当时的费率市场和矿工打包选择,无法用公式承诺分钟数。

如果钱包显示的金额比预期少,先确认手续费是否被设置为从转账金额中扣除,这会让收款方实际收到的金额低于你填写的数额,而不是额外多收了一笔。

本文的算例仅用于展示 vsize × sat/vB 的乘法关系。实际交易请以最终解码交易的 vsize 和实际输入输出差额为准。

资料来源