本文个人博客地址:http://www.huweihuang.com/article/blockchain/blockchain-transactions/
比特币交易是比特币系统最重要的部分,本质是数据结构
,数据结构中含有比特币交易参与者价值转移
的相关信息。比特币区块链是一本全球复制记账总账簿
,每个比特币交易
即账簿上公开的一页转账记录
。
签名
标志了该比特币的使用许可。一个交易如果被记录到区块链上并被足够多的后续区块确认,便成为比特币总账簿的一部分,并被所有比特币交易参与者认可为有效交易。
比特币交易类似纸质支票
,比特币交易带有货币转移
的目的,交易可以被任何人在线上或线下创建,但是交易的发起人并不一定是签署该笔交易的人,比如一个负责应付账款的柜员发起交易,但需要CEO进行签名才有效。比特币交易的资金来源是以往的某笔交易输入,而不是一个特定账户。
一笔比特币交易被创建,会被所有资金所有者签名,如果是合法创建和签名,则该交易是有效的。
一笔交易需要传递到比特币网络中,才能被传播也才能加入区块链中。本质上比特币交易是一份数据,并且需要被发送到比特币节点的任何一个。该交易经过签名但不含任何机密信息、私钥等,因此可以被公开传播。
比特币交易被发送到比特币网络的任一节点,该节点将会验证该笔交易。具体如下:
比特币网络是个点对点网络
,每个比特币节点都可以连接其他节点。整个比特币网络形成松散连接,没有固定拓扑的网状结构,所以节点地位同等
。一笔有效的交易被验证后会被传播到其他节点,以此类推,交易会被迅速扩散式传播,直到所有节点都接收到它。
每个节点在传播每笔交易前均进行独立验证,因此比特币网络可以抵御入侵,拒绝服务式攻击等。
一笔比特币交易是一个包含输入值
和输出值
的数据结构,该数据结构植入了将一笔资金从起始点(输入值)转移至目标地址(输出值)的代码信息。比特币交易的输入值和输出值与账户或身份信息无关。
交易结构
大小 | 字段 | 描述 |
---|---|---|
4字节 | 版本 | 明确这笔交易参照的规则 |
1-9字节 | 输入数量 | 被包含的输入的数量 |
不定 | 输入 | 一个或多个交易输入 |
1-9字节 | 输出数量 | 被包含的输出的数量 |
不定 | 输出 | 一个或多个交易输出 |
4字节 | 时钟时间 | 一个UNIX时间戳或区块号 |
比特币交易的基本单位是一个未花费的输出
(UTXO),UTXO
是不能分割,被记录于区块链中并被整个网络识别成货币单位的一定量的比特币货币。比特币没有账户和余额的概念,只有分散到区块链中的UTXO
。比特币的余额是比特币钱包通过扫描区块链并聚合所有属于该用户的UTXO来计算该用户余额。
比特币可以分成表示八位小数的聪
,一个UTXO可以是一“聪”的任意倍,UTXO虽然可以是任意值但一旦被创造出来就不能被切分。就好比,用5元纸币支付2元的商品,不能将5元撕成一半支付,而是支付5元,找零3元。比特币钱包可以自动通过组合若干UTXO来准确支付或找零。
被交易消耗的UTXO被称为交易输入
,被交易创建的UTXO称为交易输出
。通过不断在交易链中消耗和创建UTXO,实现比特币价值在不同所有者之间转移。一笔比特币交易通过使用所有者的签名来解锁UTXO,通过新的使用者的比特币地址来锁定并创建UTXO。
每一笔比特币交易创造输出,输出都会被比特币账簿记录下来。几乎所有的输出都能创造一定数量的可用于支付的比特币,也就是UTXO。这些UTXO被整个网络识别,并且所有者可在未来的交易中使用它们。给某人发送比特币实际上是创造新的UTXO,注册到那个人的地址,并且能被他用于新的支付。
UTXO被每一个全节点比特币客户端在一个储存于内存中的数据库所追踪,该数据库也被称为“UTXO集
”或者“UTXO池
”。新的交易从UTXO集中消耗(支付)一个或多个输出。
交易输出包含两部分:
交易输出结构
尺寸 | 字段 | 说明 |
---|---|---|
8个字节 | 总量 | 用聪表示的比特币值(10-8比特币) |
1–9个字节(可变整数) | 锁定脚本尺寸 | 用字节表示的后面的锁定脚本长度 |
变长 | 锁定脚本 | 一个定义了支付输出所需条件的脚本 |
支付条件(障碍)
交易输出把用聪表示的一定数量的比特币,和特定的定义了支付输出所必须被满足的条件的障碍,或者叫锁定脚本,关联到了一起。在大多数情况下,锁定脚本会把输出锁在一个特定的比特币地址上,从而把一定数量的比特币的所有权转移到新的所有者上。
交易输入是指向UTXO的指针。它们指向特定的UTXO,并被交易哈希和在区块链中记录UTXO的序列号作为参考。若想支付UTXO,一个交易的输入也需要包含一个解锁脚本,用来满足UTXO的支付条件。解锁脚本通常是一个签名,用来证明对于在锁定脚本中的比特币地址拥有所有权。
当用户付款时,他的钱包通过选择可用的UTXO来构造一笔交易。比如说,要支付0.015比特币,钱包应用会选择一个0.01 UTXO和一个0.005 UTXO,使用它们加在一起来得到想要的付款额。
一旦UTXO被选中,钱包会为每个UTXO生成包含签名的解锁脚本,由此让它们变得可以通过满足锁定脚本的条件来被支付。钱包把这些UTXO作为参考,并且连同解锁脚本一起作为输入加到交易中。
交易输入的结构
尺寸 | 字段 | 说明 |
---|---|---|
32个字节 | 交易 | 指向交易包含的被花费的UTXO的哈希指针 |
4个字节 | 输出索引 | 被花费的UTXO的索引号,第一个是0 |
1–9个字节(可变整数) | 解锁脚本尺寸 | 用字节表示的后面的解锁脚本长度 |
变长 | 解锁脚本 | 一个达到UTXO锁定脚本中的条件的脚本 |
4个字节 | 序列号 | 目前未被使用的交易替换功能,设成0xFFFFFFFF |
交易费可当作是为了包含(挖矿)一笔交易到下一个区块中的一种鼓励,也可当作是对于欺诈交易和任何种类的系统滥用,在每一笔交易上通过征收一笔小成本的税而造成的一种妨碍。交易费被挖出这个区块的矿工得到,并且记录在这个交易的区块链中。
交易费基于交易的尺寸,用千字节来计算,与参加交易的比特币值无关。总的来说,交易费基于市场所设置,生效于比特币网络中。
交易费的高低影响交易被处理的优先级
,即交易费高的交易可以被优先处理,交易费低的交易被延迟处理,甚至不被处理。
交易的数据结构没有交易费的字段,而是输入总额与输出总额之间的差来表示。
交易费 = 求和(所有输入) - 求和(所有输出)
当一笔交易需要找零时,交易费 = 付款金额 - 收款金额 - 找零金额
。
交易形成一条链,这条链的形式是一笔交易消耗了先前的交易(父交易)的输出,并为随后的交易(子交易)创造了输出。
有的时候组成整个链条的所有交易依赖于他们自己——比如父交易、子交易和孙交易——而他们又被同时创造出来,来满足复杂交易的工作流程。这需要在一个交易的父交易被签名之前,有一个合法的子交易被签名。
当父交易和子交易同时被创建的时候,如果子交易比父交易先到达目的地,验证的时候找不到父交易,此时子交易会被放到临时池中(没有父交易的交易池称为孤立交易池
),一旦接收到父交易,孤立池的子交易就会被释放出来,递归重新验证。
内存中储存的孤立交易数量是有限制的,避免拒绝服务攻击(DoS)。最大值为MAX_ORPHAN_TRANSACTIONS
,如果超过该值,会随机选出一个或多个孤立交易丢弃,直到交易数低于该值。
比特币客户端通过执行一个用类Forth脚本语言编写的脚本验证比特币交易。锁定脚本被写入UTXO,同时它往往包含一个用同种脚本语言编写的签名。当一笔比特币交易被验证时,每一个输入值中的解锁脚本被与其对应的锁定脚本同时(互不干扰地)执行,从而查看这笔交易是否满足使用条件。
比特币的交易验证引擎依赖于两类脚本来验证比特币交易:一个锁定脚本
和一个解锁脚本
。
锁定脚本
是一个放在一个输出值上的“障碍”,同时它明确了今后花费这笔输出的条件。由于锁定脚本往往含有一个公钥
(即比特币地址)。解锁脚本
是一个“解决”或满足被锁定脚本在一个输出上设定的花费条件的脚本,同时它将允许输出被消费。解锁脚本是每一笔比特币交易输出的一部分,而且往往含有一个被用户的比特币钱包(通过用户的私钥
)生成的数字签名
。由于解锁脚本常常包含一个数字签名,因此它曾被称作ScriptSig
。每一个比特币客户端会通过同时执行锁定和解锁脚本来验证一笔交易。对于比特币交易中的每一个输入,验证软件会先检索输入所指向的UTXO。这个UTXO包含一个定义了花费条件的锁定脚本。接下来,验证软件会读取试图花费这个UTXO的输入中所包含的解锁脚本,并执行这两个脚本。
使用堆栈执行引擎执行解锁脚本。如果解锁脚本在执行过程中未报错(没有悬空操作符),主堆栈(非其它堆栈)将被复制,然后脚本将被执行。如果采用从解锁脚本处复制而来的数据执行锁定脚本的结果为真,那么解锁脚本就成功地满足了锁定脚本所设置的条件,因而,该输入是一个能使用该UTXO的有效授权。如果在执行完组合脚本后的结果不是真,那么输入就不是有效的,因为它并未能满足UTXO中所设置的使用该笔资金的条件。
UTXO是永久性地记录在区块链中的,因此它不会因一笔新交易所发起的无效尝试而变化或受影响。只有一笔有效的能准确满足UTXO条件的交易才会导致UTXO被标记为“已使用”,然后从有效的(未使用)UTXO集中所移除。
解锁和锁定脚本样本
比特币脚本语言被称为基于栈语言,因为它使用的数据结构被称为栈。脚本语言通过从左至右地处理每个项目的方式执行脚本。数字(常数)被推送至堆栈,操作符向堆栈推送(或移除)一个或多个参数,对它们进行处理,甚至可能会向堆栈推送一个结果。
比特币脚本语言没有循环
或者复杂流控制功能以外的其他条件的流控制。即图灵非完备性
,这意味着脚本的复杂性有限,交易可执行的次数有限。这种限制避免受到拒绝服务攻击。
比特币交易脚本语言是无国家主权
的,一个脚本能在任何系统上以相同的方式执行。如果你的系统对一个脚本进行验证,可以确信的是每一个比特币网络中的其他系统也将对其进行验证,这意味着一个有效的交易对每个人而言都是有效的。
比特币发展中,开发者对可以经由客户端进行操作的脚本类型设置了一些限制。这些限制被编译为一个Standard()函数,该函数定义了五种类型的标准交易。五大标准脚本分别为P2PKH
、P2PK
、MS(限15个密钥)[多重签名]
、P2SH
和OP_Return
。
多重签名
脚本设置了这样一个条件,假如记录在脚本中的公钥个数为N,则至少需提供其中的M个公钥才可以解锁。这也被称为M-N组合
,其中,N
是记录在脚本中的公钥总个数
,M
是使得多重签名生效的公钥数阀值
(最少数目)。
参考:
Mastering Bitcoin
https://github.com/bitcoinbook/bitcoinbook/blob/develop/ch06.asciidoc