比特币--交易结构

一个交易的生命周期

  1. 一笔比特币交易从交易被创建开始。
  2. 随后,该笔交易被一个或者多个签名加密,这些签名标志着该交易指向的比特币资金的使用许可。
  3. 接下来,该笔交易被广播到比特币网络中。
  4. 比特币网络中的每个节点接收到该笔交易后,会先验证:根据本笔交易的每个输入的上笔交易哈希和索引,找到对应的上笔交易输出的UTXO,UTXO中包含了锁定脚本,再和本笔交易的每个输入中的解锁脚本结合执行验证交易是否有效。
  5. 节点验证交易通过后放入自己内存交易池、并将交易继续广播,直到被大多数节点接收。
  6. 然后挖矿节点从内存交易池将很多笔交易从组装进区块体,并构造区块头。
  7. 最终,某个挖矿节点计算出了有效哈希值,则将该区块添加到区块链并广播给其他矿工。
  8. 接收到有效区块的矿工会放下正在计算有效哈希的任务,对接收到的有效区块进行验证。
  9. 验证如果通过,更新本地链并帮助广播该有效区块。
  10. 该矿工会将该有效区块中的交易与本地交易池对比,从本地交易池中去除在有效区块中存在的交易。
  11. 然后该矿工会继续从内存交易池将很多笔交易从组装进区块,并继续计算有效哈希。

该笔交易一旦被记录到区块链上并被足够多的后续区块确认,便成为比特币总账本的一部分,并被所有比特币交易参与者认可为有效交易。

于是,被这笔交易分配到新所有者名下的比特币资金可以在新的交易中被使用,这使得所有权链得到延伸且再次开启一个新的比特币交易生命周期。

一个交易的结构

1字节 = 8位二进制数字 = 2位十六进制数字
1byte = 8bit

大小 字段 描述
4字节 协议版本 这笔交易参照的比特币版本
1-9字节 输入数量 被包含的输入数量
不定 输入列表 一个或多个交易输入构成的数组
1-9字节 输出数量 被包含的输出的数量
不定 输出列表 一个或多个交易输出构成的数组
4字节 锁定时间 一个UNIX时间戳或区块号

锁定时间定义了能被加到区块链上的最早的交易时间,大多说被设置为0,表示立即执行。
如果被设置为大于0小于5亿,表示在该区块链高度之前不能被加入区块链上。
如果大于5亿,表示Unix纪元时间(从1970年1月1日开始的秒数),在此时间之前不能被包含到区块链上,即延后交易生效。

UTXO(Unspent Transaction Output, 未花费交易输出)

比特币交易的基本单位是未经使用的一个交易输出,简称UTXO。在比特币世界里既没有账户,也没有余额,只有分散到比特币区块链上的UTXO。比特币钱包通过扫描并聚合比特币网络中分散的UTXO来计算用户的余额。

被交易消耗的UTXO称为交易输入,被交易创建的UTXO称为交易输出。比特币价值通过这种方式在所有者中流通和转移,在交易中消耗和创建UTXO。一笔比特币交易通过使用所有者的私钥签名来解锁UTXO,并使用新的所有者的比特币地址来锁定创建的UTXO,新的所有者可通过自己的私钥来解锁该UTXO进行消费。

UTXO被每个比特币完整客户端存储于内存中的数据库中,称为“UTXO集”或“UTXO池”。

查询某个地址的UTXO: https://blockchain.info/unspent?active=1Dorian4RoXcnBv9hnQ4Y2C1an6NJ4UrjX

交易输出结构

包含两个部分:

  • 一定量的比特币,单位位聪,是比特币的最小单位
  • 一个锁定脚本,也被当作障碍,提出支付输出所必须被满足的条件以锁住这笔金额
尺寸 字段 说明
8个字节 比特币金额 用聪表示的比特币金额,倒序格式
1–9个字节(可变整数) 锁定脚本长度 表示后面锁定脚本的长度
变长 锁定脚步内容 定义了支付输出所需条件的脚本

交易输出将一定量的以聪位单位的比特币和锁定脚本关联在一起,大多数情况下锁定脚本会将交易输出锁定到一个比特币地址上,从而把一定量的比特币转移到新的所有者上。当新的所有者消费时,通过提供一个包含私钥的解锁脚本来解锁该输出。

交易输入结构

简单说是交易输入是指向UTXO的指针。若想用UTXO来支付,交易输入中需包含一个解锁脚本,用来满足支付条件,即障碍条件。解锁脚本通常是一个私钥签名,用来证明对于锁定脚本中的比特币地址拥有所有权。

选定满足支付金额的UTXO之后,钱包会为每个UTXO生成包含签名的解锁脚本,由此让它们满足锁定脚本的条件以用来被支付。然后钱包把这些UTXO和解锁脚本一起作为交易输入加入到交易结构中。

尺寸 字段 说明
32个字节 交易hash 包含UTXO的交易hash
4个字节 UTXO索引 在父交易输出的UTXO列表中的第几个,从0开始
1–9个字节(可变整数) 解锁脚本尺寸
变长 解锁脚本 通常为私钥签名+公钥
4个字节 序列号 值全部为1,0xFFFFFFFF

交易费

比特币交易的数据结构中没有交易费的定义,比特币采用的是:

交易费 = 所有的交易输入 - 所有的交易输出

另外需注意:UTXO都是整体的、不可分割的,可能某此交易的输入构建的UTXO远大于需支付金额,要注意在交易输出中除了输出给指定的收款人,也要包含找零输出(即再输出给自己),否则的话,多于的会当作交易费给确认该交易的矿工。

比特币交易实例

下面是一个比特币交易的原始数据示例,将原始的二进制数据按字节以十六进制显示,便于分析:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
01000000 02 eb2121e4e727bdb28525e79d39a90bd711b9e8413c054b29ffc4bb
3045022100df82cf6c95b4eb64e4e9cee3af88a94c65fa81650e824d515f0891
d9354755ea815cf714c181b56784b8f98f59f33e977c8939cd6f75db0121022e
fc410343ff373622cca60d3a4c926e58716114b9ffffffffc9f3b07ebfca68fd
095fc93901ea77410103489ab7010000008a47304402206b993231adec55e608
cd60abaff957b1c352b3ef9a022022a22fec37dfa2c646c78d9a0753d56cb439
ef208d0141042ff65bd6b3ef04253225405ccc3ab2dd926ff2ee48aac2108196
1330eb0c76cf49e9e474fb9159ab41653a9c1725c031449d31026affffffff03
022e9f31292873eee495ca9744fc410343ff373622cca60d3a4c926e58716114
506565722d506565722d6e6574776f726b207075626c696352aee07b9a3b0000
a2a3904cda1fd995fb7c4377487ea988ac00000000000000000d6a0b436f6465

0100 0000 //协议版本号,UINT32
03 //Tx输入数量,变长INT。Ox03=3个输入

/** 第1组Input Tx **/
2237b858... // Tx交易的Hash值, 固定为32字节
0100 0000 // 消费的Tx位于前向交易输出的第2个,UINT32,固定4字节
6b // 签名数据的长度,0x6b=107十进制,即107字节长度的签名
// 含有两个部分:私钥签名+公钥。
// 当为00时,则表示为尚未经过签名的原始交易

48 // 对应私钥签名的数据长度,0x48 = 72, 即72字节的私钥签名
3045022... // 私钥签名内容
21 // 对应公钥的数据长度,0x21 = 33, 即33字节的公钥数据
022e9f3... // 对应公钥数据
ffffffff // 序列号,UINT32,固定4字节。
// 该字节是目前未被使用的交易替换功能,默认值为此值。

/** 第2组Input Tx。与上同理 **/
/** 第3组Input Tx。与上同理 **/

03 //Tx输出交易数量,变长INT类型。0x03=3个输出

/** 第1组输出 **/
7d16000000000000 // 输出的比特币数量,UINT64,8个字节。字节顺序需翻转得到
// 0x000000000000167d = 5757 satoshi = 0.00005757 BTC
19 // 输出描述脚本字节数,0x19 = 25字节,由一些操作码与数值构成
76 // 脚本起始操作,0x76代表OP_DUP复制栈顶元素
a9 // 地址类型,0xa9代表OP_HASH160即栈顶项进行两次HASH,先用SHA-256,再用RIPEMD-160
14 // 地址长度,0x14 = 20字节
51a09... // 对应ODIN标识拥有者地址的HASH160值,20字节
88 // 代表OP_EQUALVERIFY 运行脚本的二进制算数和条件
// 如结果为0,之后运行OP_VERIFY
ac // 代表OP_CHECKSIG交易所用的签名必须是哈希值和公钥的有效签名,
// 如果为真,则返回1

/** 第2组输出 **/
/** 第3组输出 **/

00000000 // 锁定时间,UINT32, 固定4字节,0表示立即执行

内存交易池

比特币网络中几乎每个节点都会维护一份未确认交易的临时列表,被称为内存池或交易池。节点们利用这个池来追踪记录那些被网络所知晓、但还未被区块链所包含的交易。例如,保存用户钱包的节点会利用这个交易池来记录那些网络已经接收但还未被确认的、属于该用户钱包的预支付信息。

随着交易被接收和验证,它们被添加到交易池并通知到相邻节点处,从而传播到网络中。

交易链条

一笔交易是使用了先前的交易(父交易)的输出,而同时为随后的交易(子交易)创建了输出,这样就形成了交易链条。

孤立交易池

有些节点的实现还维护一个单独的孤立交易池。如果一个交易的输入与某未知的交易有关,如与缺失的父交易相关,该孤立交易就会被暂时储存在孤立交易池中直到父交易的信息到达。

当交易链在网络中被传送时,不能保证每个交易到达的顺序一致,这就导致一个比特币节点收到子交易可能在父交易之前到达,此时节点不能找到子交易的父交易做参考,无法进行确认。

当一个交易被添加到交易池中,会同时检查孤立交易池,看是否有某个孤立交易引用了此交易的输出(子交易)。任何匹配的孤立交易会被进行验证。如果验证有效,它们会从孤立交易池中删除,并添加到交易池中,使以其父交易开始的链变得完整。对新加入交易池的交易来说,它不再是孤立交易。前述过程重复递归寻找进一步的后代,直至所有的后代都被找到。通过这一过程,一个父交易的到达把整条链中的孤立交易和它们的父级交易重新结合在一起,从而触发了整条独立交易链进行级联重构。

内存中存放孤立交易的数量中有限,为了防止针对比特币节点的拒绝服务攻击(DoS).

交易池和孤立交易池(如有实施)都是存储在本地内存中,并不是存储在永久性存储设备(如硬盘)里。更准确的说,它们是随网络传入的消息动态填充的。节点启动时,两个池都是空闲的;随着网络中新交易不断被接收,两个池逐渐被填充。

UTXO池

有些比特币客户端的实现还维护一个UTXO数据库,也称UTXO池,是区块链中所有未支付交易输出的集合。“UTXO池”的名字听上去与交易池相似,但它代表了不同的数据集。UTXO池不同于交易池和孤立交易池的地方在于,它在初始化时不为空,而是包含了数以百万计的未支付交易输出条目,有些条目的历史甚至可以追溯至2009年。UTXO池可能会被安置在本地内存,或者作为一个包含索引的数据库表安置在永久性存储设备中。

交易池和孤立交易池代表的是单个节点的本地视角。取决于节点的启动时间或重启时间,不同节点的两池内容可能有很大差别。相反地,UTXO池代表的是网络的突显共识,因此,不同节点间UTXO池的内容差别不大。此外,交易池和孤立交易池只包含未确认交易,而UTXO池之只包含已确认交易。