交易格式详解
目录
交易格式概述
交易的二进制表示
比特币交易在网络中以二进制形式传输和存储。理解这种二进制格式对于开发比特币应用至关重要。
| 层级 | 说明 |
|---|---|
| 逻辑层 | 输入、输出、签名 |
| 序列化层 | 二进制编码格式 |
| 网络层 | P2P 协议传输 |
| 存储层 | 区块链持久化 |
基本结构
交易 (Transaction)
├── 版本号 (4 字节)
├── 输入计数 (1-9 字节,CompactSize)
├── 输入列表 (可变长度)
│ ├── Input 1
│ │ ├── 前一交易 TXID (32 字节)
│ │ ├── 输出索引 (4 字节)
│ │ ├── 脚本长度 (1-9 字节)
│ │ ├── 解锁脚本 (可变长度)
│ │ └── 序列号 (4 字节)
│ ├── Input 2
│ └── ...
├── 输出计数 (1-9 字节,CompactSize)
├── 输出列表 (可变长度)
│ ├── Output 1
│ │ ├── 金额 (8 字节)
│ │ ├── 脚本长度 (1-9 字节)
│ │ └── 锁定脚本 (可变长度)
│ ├── Output 2
│ └── ...
└── 锁定时间 (4 字节)交易序列化
字节顺序(Endianness)
比特币使用小端序(Little Endian)在大多数情况下。
例子:
十六进制值:0x12345678
大端序(网络字节序):12 34 56 78
小端序(Intel 格式):78 56 34 12
比特币中的用法:
- 内存中的整数:通常是本机字节序
- 网络传输:小端序
- TXID 显示:反转字节顺序(大端序显示)
规则:
大多数多字节字段都使用小端序
但某些字段(如脚本)使用大端序序列化过程
序列化步骤:
1. 版本号 → 4 字节小端序
2. 输入计数 → CompactSize
3. 对每个输入:
a. 前一交易 TXID → 32 字节小端序
b. 输出索引 → 4 字节小端序
c. 脚本长度 → CompactSize
d. 脚本数据 → 原始字节
e. 序列号 → 4 字节小端序
4. 输出计数 → CompactSize
5. 对每个输出:
a. 金额 → 8 字节小端序
b. 脚本长度 → CompactSize
c. 脚本数据 → 原始字节
6. 锁定时间 → 4 字节小端序
结果:
连续的字节序列,可以传输或存储紧凑尺寸编码
CompactSize 编码
紧凑尺寸用于编码可变长度的无符号整数。
规则:
如果 n < 253:
编码为 1 字节:0xNN
如果 253 ≤ n < 65536:
编码为 3 字节:0xFD + n (2字节小端序)
如果 65536 ≤ n < 4294967296:
编码为 5 字节:0xFE + n (4字节小端序)
如果 n ≥ 4294967296:
编码为 9 字节:0xFF + n (8字节小端序)
优势:
小值使用少字节
大值才使用多字节
比固定 8 字节更高效编码示例
例子 1:计数为 2 个输入
值:2
编码:0x02(1 字节)
例子 2:计数为 300 个输入
值:300 = 0x012C
编码:0xFD 2C 01(3 字节,小端序)
例子 3:脚本长度为 100 字节
值:100 = 0x64
编码:0x64(1 字节)
例子 4:脚本长度为 50000 字节
值:50000 = 0xC350
编码:0xFE 50 C3 00 00(5 字节,小端序)交易字段详解
1. 版本号(Version)
大小:4 字节小端序
范围:1-4(常见)
版本 1(0x01000000):
标准交易
所有基础功能
版本 2(0x02000000):
支持交易指数的替换(BIP 125)
更灵活的费用替换策略
格式示例:
原始值:1
十六进制:01 00 00 00(小端序)
含义:
版本号向后兼容
节点可识别未来的新版本2. 输入计数
大小:CompactSize
含义:此交易有多少个输入
编码示例:
1 个输入:0x01
2 个输入:0x02
255 个输入:0xFF
256 个输入:0xFD 00 01
理论限制:
无绝对限制
但区块大小限制(1MB)间接限制
实际交易通常 < 100 个输入3. 输出计数
大小:CompactSize
含义:此交易有多少个输出
范围和限制同输入计数4. 锁定时间(Locktime)
大小:4 字节小端序
范围:0 到 4294967295(2^32 - 1)
含义:交易何时能花费
解释规则:
如果 locktime = 0:
交易立即有效
如果 0 < locktime < 500000000:
解释为区块高度
例:locktime = 100000
交易在第 100000 个区块之前无效
如果 locktime ≥ 500000000:
解释为 Unix 时间戳(秒)
例:locktime = 1234567890
交易在 2009-02-13 后有效
应用场景:
1. 时间锁定交易
2. 支付渠道(闪电网络)
3. 原子交换
示例:
locktime = 0x00000000 (立即有效)
locktime = 0x80000000 (2106-02-07 后)交易输入详解
输入结构
每个输入包含:
1. 前一交易 TXID (32 字节)
指向被花费的 UTXO
2. 输出索引 (4 字节)
该 UTXO 在前一交易中的位置
3. 脚本长度 (CompactSize)
解锁脚本的字节长度
4. 解锁脚本 (可变长度)
证明有权花费 UTXO 的脚本
5. 序列号 (4 字节)
用于交易替换和锁定时间前一交易 TXID
大小:32 字节
顺序:小端序
含义:
指向前一个交易的哈希值
该交易包含要花费的输出
显示形式(反转字节顺序):
内存存储:12 34 56 78 ... (小端)
显示: ... 78 56 34 12 (大端)
作用:
1. 唯一标识前一个交易
2. 链接到区块链历史
3. 可验证 UTXO 的存在
双重花费防护:
同一个 TXID + vout 只能被花费一次输出索引(Vout)
大小:4 字节小端序
范围:0 到 2^32 - 1
含义:
在前一交易中,被花费的输出位置
例子:
前一交易有 3 个输出:
Output 0: 1 BTC
Output 1: 2 BTC
Output 2: 3 BTC
如果 vout = 1,则花费 Output 1(2 BTC)
编码:
第 0 个输出:0x00 00 00 00
第 1 个输出:0x01 00 00 00
第 2 个输出:0x02 00 00 00脚本长度
大小:CompactSize
含义:解锁脚本的字节长度
示例:
脚本 47 字节:0x47
脚本 256 字节:0xFD 00 01
作用:
告诉解析器多少字节是脚本
允许不定长的脚本数据解锁脚本(ScriptSig)
大小:可变长度
含义:证明有权花费 UTXO 的脚本
P2PKH (Pay-to-Public-Key-Hash) 脚本:
<signature> <pubkey>
例:
47 30 44...(签名数据)
21 02 79be...(公钥数据)
脚本语言:
基于栈的语言
非图灵完整
串联操作码和数据
作用:
提供解锁证明
通常包含:签名 + 公钥
签名证明有私钥
公钥证明身份序列号(Sequence)
大小:4 字节小端序
范围:0 到 4294967295
含义和用途:
原始意图(不常用):
用于交易替换
值越高,优先级越高
现代用途:
1. 相对锁定时间 (BIP 68)
高位编码锁定时间
序列号 < 0xFFFFFFFF 激活锁定时间
2. 交易替换信号 (BIP 125)
序列号 < 0xFFFFFFFF 允许 RBF
标准值:
0xFFFFFFFF:无限制,立即有效
0xFFFFFFFE:允许 RBF
< 0xFFFFFFFF:启用锁定时间
使用示例:
标准交易:0xFF FF FF FF(允许立即花费)
锁定交易:0xFE FF FF FF(启用锁定时间)交易输出详解
输出结构
每个输出包含:
1. 金额 (8 字节)
聪为单位的金额
2. 脚本长度 (CompactSize)
锁定脚本的字节长度
3. 锁定脚本 (可变长度)
定义谁能花费此输出金额(Value)
大小:8 字节小端序
单位:聪(satoshi)
范围:0 到 2099999997690000
1 BTC = 100,000,000 聪
编码示例:
1 BTC = 100000000 聪
十六进制(小端):00 e1 f5 05 00 00 00 00
0.5 BTC = 50000000 聪
十六进制(小端):80 f0 fa 02 00 00 00 00
特殊值:
-1:未初始化或错误
> 21000000 BTC:无效,超过总供应量
精度:
只能精确到 1 聪
不能表示 0.000000001 BTC 的更小单位锁定脚本(ScriptPubKey)
大小:可变长度
含义:定义谁能花费这个输出
常见脚本类型:
1. P2PKH (Pay-to-Public-Key-Hash)
OP_DUP OP_HASH160 <pubkeyhash> OP_EQUALVERIFY OP_CHECKSIG
格式:0x76 A9 14 <20 bytes hash> 88 AC
总长度:25 字节
2. P2SH (Pay-to-Script-Hash)
OP_HASH160 <scripthash> OP_EQUAL
格式:0xA9 14 <20 bytes hash> 87
总长度:23 字节
3. P2WPKH (Pay-to-Witness-Public-Key-Hash, SegWit)
OP_0 <20 bytes pubkeyhash>
格式:0x00 14 <20 bytes>
总长度:22 字节
4. P2WSH (Pay-to-Witness-Script-Hash, SegWit)
OP_0 <32 bytes scripthash>
格式:0x00 20 <32 bytes>
总长度:34 字节
脚本大小:
P2PKH:25 字节
P2SH:23 字节
P2WPKH:22 字节(最小)脚本序列化
脚本基础
脚本是栈基的:
1. 从左到右读取操作码
2. 操作数压入栈
3. 操作码执行栈操作
4. 最终栈顶必须为真
编码规则:
操作码 0x00-0x4B:数据长度
操作码 0x4C:PUSHDATA1
操作码 0x4D:PUSHDATA2
操作码 0x4E:PUSHDATA4
操作码 0x51-0x60:OP_1 到 OP_16
操作码 0x6B 等:其他操作码常见操作码
OP_DUP (0x76):复制栈顶
OP_HASH160 (0xA9):SHA256 后 RIPEMD160
OP_EQUAL (0x87):比较栈顶两项
OP_EQUALVERIFY (0x88):EQUAL + OP_VERIFY
OP_CHECKSIG (0xAC):验证签名
OP_0 (0x00):压入空值
OP_1 (0x51):压入 1实际交易示例
例子:简单的 P2PKH 交易
场景:Alice 发送 1 BTC 给 Bob
原始十六进制数据(已序列化):
01000000 版本号 (1)
01 输入计数 (1)
86c6047f6f79... 前一交易 TXID (32 字节)
00000000 输出索引 (vout=0)
48 脚本长度 (72 字节)
47304402...86a1 解锁脚本 (72 字节)
ffffffff 序列号 (0xFFFFFFFF)
01 输出计数 (1)
00ca9a3b00000000 金额 (1 BTC = 100000000 聪)
19 脚本长度 (25 字节)
76a91462e907b15cbf...88ac 锁定脚本 (25 字节)
00000000 锁定时间 (0)
大小:约 226 字节交易大小
字节计算
基础开销:
版本号:4 字节
输入计数:1 字节
输出计数:1 字节
锁定时间:4 字节
小计:10 字节
每个输入:
TXID:32 字节
Vout:4 字节
脚本长度:1 字节
脚本:平均 72 字节(签名)+ 33 字节(压缩公钥)
序列:4 字节
小计:约 146 字节
每个输出:
金额:8 字节
脚本长度:1 字节
脚本:25 字节(P2PKH)或更小
小计:约 34 字节
总大小 ≈ 10 + (输入数 × 146) + (输出数 × 34) 字节大小优化
使用 SegWit 可减小交易大小:
传统交易大小 = 1 × vBytes
SegWit 交易大小 = vBytes
vBytes = (基础大小 + 见证数据 × 0.25)
节省约 25-50% 的区块空间常见问题
Q1: 为什么使用小端序?
A: 历史原因和本地处理效率。网络通常使用大端序,但比特币选择小端序作为内部表示。
Q2: 交易最大能有多少个输入?
A: 理论上无限制,但受区块大小限制(1MB,或 SegWit 下 4MB)。实际上,输入越多,费用越高。
Q3: 可以有 0 个输出吗?
A: 可以,但不推荐。这样的交易会烧毁所有输入的比特币。
Q4: 解锁脚本和锁定脚本的作用?
A: 锁定脚本定义条件(出现在前一交易中),解锁脚本提供证明(出现在当前交易中)。
Q5: 序列号为什么总是 0xFFFFFFFF?
A: 因为大多数交易不使用锁定时间。0xFFFFFFFF 表示无锁定限制。
