Skip to content

交易验证

目录

  1. 验证概述
  2. 交易验证规则
  3. 脚本验证
  4. 双花防护
  5. 共识验证
  6. 交易优先级
  7. 常见错误
  8. 常见问题

验证概述

验证的目的

核心问题:
  如何确保交易合法且不会造成伤害?

验证层级:

1. 语法验证(Syntactic)
  交易格式是否正确
  所有字段是否有效

2. 语义验证(Semantic)
  签名是否有效
  UTXO 是否存在且未被花费

3. 共识验证(Consensus)
  是否符合网络的共识规则
  区块是否有效

目的:
  保护网络安全
  防止双花
  维护系统完整性

谁来验证

全节点:
  下载并验证所有交易
  维护完整的 UTXO 集合

轻客户端:
  只验证与自己相关的交易
  使用 SPV(Merkle 路径验证)

矿工:
  验证交易
  打包到区块

收款人:
  至少要求足够的确认
  如果需要立即验证,运行全节点

交易验证规则

基本验证

1. 大小检查
   ✓ 交易大小 > 0
   ✓ 交易大小 <= 最大大小(4MB SegWit)
   ✓ 交易大小 <= 区块剩余空间

2. 输入/输出检查
   ✓ 至少有 1 个输入
   ✓ 至少有 1 个输出
   ✓ 输入数 < 2^16
   ✓ 输出数 < 2^16

3. 脚本大小
   ✓ 解锁脚本 <= 10,000 字节
   ✓ 锁定脚本 <= 10,000 字节

4. 费用检查
   ✓ 输出总和 <= 输入总和
   ✓ 费用合理(> 最小中继费率)

UTXO 验证

对每个输入进行验证:

1. 前一交易是否存在
   ✓ 前一 TXID 在区块链中
   ✓ 指定的输出索引有效

2. UTXO 是否未被花费
   ✓ 检查 UTXO 集合(utxo_set)
   ✓ 不在已花费列表中

3. 金额是否有效
   ✓ 输出金额 <= 2100 万 BTC
   ✓ 输出金额 > 0

4. Coinbase 特殊规则
   ✓ Coinbase 输出需要 100 个确认才能花费
   ✓ 否则拒绝(BIP 30)

签名验证

关键验证步骤:

1. 签名格式
   ✓ DER 格式有效
   ✓ r 和 s 都在有效范围

2. 公钥格式
   ✓ 压缩格式(33 字节)或未压缩(65 字节)
   ✓ 公钥在椭圆曲线上

3. 签名有效性
   ✓ ECDSA_Verify(hash, sig, pubkey)
   ✗ 失败则交易无效

4. SIGHASH 类型
   ✓ 根据 SIGHASH 类型验证相应字段

脚本验证

脚本执行

比特币脚本是栈基的语言

执行流程:
1. 初始化栈:[]
2. 按顺序读取操作码
3. 压入数据到栈
4. 执行操作码
5. 栈操作:PUSH、DUP、HASH、CHECKSIG 等
6. 最终栈顶必须为真

验证条件:
  脚本执行无错误 AND 栈顶为真 → 有效
  脚本执行错误 OR 栈顶为假 → 无效

P2PKH 验证

锁定脚本:
  OP_DUP OP_HASH160 <pubkey_hash> OP_EQUALVERIFY OP_CHECKSIG

解锁脚本:
  <signature> <pubkey>

完整执行:
1. 执行解锁脚本
   栈:[]
   push sig:[sig]
   push pub:[sig, pub]

2. 执行锁定脚本
   OP_DUP:[sig, pub, pub]
   OP_HASH160:[sig, pub, hash(pub)]
   push hash:[sig, pub, hash(pub), expected_hash]
   OP_EQUALVERIFY:[sig, pub](如果相等)
   OP_CHECKSIG:[] ✅(如果签名有效)

任何步骤失败 → 交易无效

脚本验证的限制

比特币脚本的故意限制:

1. 不是图灵完整的
   没有循环(只有 WHILE 被禁用)
   没有递归
   操作码有限

2. 有执行时间限制
   操作码不能超过 201
   栈大小有限

3. 有内存限制
   避免 DoS 攻击

原因:
  保证脚本快速执行
  防止恶意脚本锁定网络

双花防护

双花的本质

双花问题:
  同一个 UTXO 被两笔交易同时花费

例子:
  UTXO A(5 BTC)
  
  交易 1:A → Bob (5 BTC)
  交易 2:A → Charlie (5 BTC)
  
  问题:A 被花费两次!

解决方案:
  1. UTXO 集合(账本)
  2. 共识机制
  3. 区块链组织

防双花的机制

内存池防护:

1. 交易进入内存池时
   检查输入是否已在内存池中
   如果已存在 → 拒绝(mempool conflict)

2. 内存池中的冲突
   两笔交易不能使用相同输入
   第二笔交易被拒绝

区块链防护:

1. 区块确认
   一旦交易进入确认的区块
   输入被标记为已花费(从 UTXO 中移除)

2. UTXO 集合维护
   节点维护所有未花费输出的列表
   任何新交易的输入必须在 UTXO 中
   验证失败 → 拒绝

重组防护:

1. 长链规则(Longest Chain Rule)
   节点接受最长的链
   
2. 确认数
   6 个确认通常被认为"已最终确定"
   极难逆转

3. 51% 攻击
   需要控制多数算力才能重组

交易替换(RBF)

概念:
  使用更高费用的交易替换原交易

机制:

BIP 125 规则:
  信号 RBF:序列号 < 0xFFFFFFFF
  选择 RBF:替代交易支付更高费用
  
替换条件:
  1. 新交易使用相同输入的至少一个
  2. 新交易费用 >= 旧交易费用 + 新增费用
  3. 替代交易不会被拒绝的其他原因

优势:
  交易发送太低费用?可以提高
  避免无限期等待

风险:
  攻击者可能滥用 RBF
  接收者应等待足够确认再视为最终

共识验证

共识规则的必要性

不同节点需要达成一致:
  同一笔交易的有效性
  同一个区块的有效性
  同一条链的有效性

共识规则定义了:
  什么是有效交易
  什么是有效区块
  什么是有效区块链

所有节点遵循相同的规则
→ 全网达成一致
→ 比特币网络正常运行

硬分叉 vs 软分叉

硬分叉(Hard Fork):
  新规则比旧规则更严格
  旧节点无法识别新交易/区块
  导致永久网络分裂

例子:
  增加区块大小限制
  改变 PoW 算法

结果:
  没有升级的旧节点被抛弃
  形成两条独立的区块链

软分叉(Soft Fork):
  新规则比旧规则更严格
  但旧规则仍认为新交易/区块有效
  向后兼容

例子:
  添加新的操作码(旧节点忽略)
  引入新的脚本类型

结果:
  旧节点可继续运行
  但无法完全验证新功能
  通常需要升级获得完整功能

验证的关键区别:
  硬分叉:必须升级或被分叉
  软分叉:旧节点可兼容,但功能受限

交易优先级

优先级计算

公式:
  priority = (sum of input values * input age) / tx_size
  
  优先级 = (输入总值 × 输入年龄) / 交易大小

例子:
  输入 1:2 BTC,100 个确认 → 2 × 100 = 200
  输入 2:3 BTC,50 个确认 → 3 × 50 = 150
  总计:350
  
  交易大小:250 字节
  
  优先级 = 350 / 250 = 1.4

含义:
  高优先级 = 旧的、高价值的 UTXO
  低优先级 = 新的、低价值的 UTXO

优先级对应的费用

费用规则:

1. 高优先级交易
   priority > 57,600,000
   可免费中继(不需要费用)
   矿工优先打包

2. 中等优先级
   57,600,000 > priority > 1,000,000
   需要最小费用或较低费用
   通常会被打包

3. 低优先级
   priority < 1,000,000
   需要更高的费用
   可能等待较长时间

注:规则随时间调整,上述值仅参考

常见错误

交易被拒绝的原因

1. 无效签名
   ECDSA_Verify 失败
   → 拒绝

2. UTXO 不存在
   输入指向不存在的交易
   → 拒绝

3. UTXO 已被花费
   输入已在其他交易中
   → 拒绝(double spend attempt)

4. 费用不足
   对于低优先级交易
   → 拒绝或进入低费内存池

5. 脚本错误
   脚本语法错误
   → 拒绝

6. 大小过大
   超过最大大小限制
   → 拒绝

7. Coinbase 规则
   Coinbase 输出未满足 100 个确认
   → 拒绝

常见问题

Q1: 交易被拒绝后可以重新发送吗?

A:

  • 可以,使用 RBF(Replace-by-Fee)
  • 或等待原交易超时(通常 72 小时)
  • 然后使用新交易重新发送

Q2: 验证一笔交易需要多长时间?

A:

  • 对于简单交易(1 输入 2 输出):几毫秒
  • ECDSA 验证:约 1 毫秒/签名
  • 复杂交易或多重签名:可能 10+ 毫秒

Q3: 交易可以验证但不被打包吗?

A:

  • 可以,如果费用太低
  • 交易有效但在内存池中等待
  • 最终可能因超时被删除

Q4: 一个交易可以有多个签名吗?

A:

  • 可以,使用多重签名或多输入交易
  • 每个输入都需要对应的签名
  • 所有签名都必须有效

Q5: 何时可以认为交易"最终"?

A:

  • 进入一个确认的区块:基本安全
  • 6 个确认:标准安全
  • 100+ 确认:极其安全