精力有限,后期修订以github为主,建议大家移步github链接阅读更新版本,感谢理解:
https://github.com/tianmingyun/MasterBitcoin2CN
本文约5300字。
6.1 简介
比特币交易是比特币系统中最重要的部分。根据比特币系统的设计原理,系统中任何其他的部分都是为了确保比特币交 易可以被生成、能在比特币网络中得以传播和通过验证,并最终添加入全球比特币交易总账簿(比特币区块链)。比特 币交易的本质是数据结构,这些数据结构中含有比特币交易参与者价值转移的相关信息。比特币区块链是全球复式记账 总账簿,每个比特币交易都是在比特币区块链上的一个公开记录。
在这一章,我们将会剖析比特币交易的多种形式、所包含的信息、如何被创建、如何被验证以及如何成为所有比特币交 易永久记录的一部分。当我们在本章中使用术语“钱包”时,我们指的是构建交易的软件,而不仅仅是密钥的数据库。
6.2交易细节
在[第二章比特币概述]中,我们查看了Alice曾经在Bob的咖啡店使用区块浏览器(Alice与Bob's Cafe的交易)支付咖啡的交易。
区块浏览器应用程序显示从Alice的“地址”到Bob的“地址”的交易。 这是一个非常简化的交易中包含的内容。 实际上,正如我们将在本章中看到的,所显示的大部分信息都是由区块浏览器构建的,实际上并不在交易中。
图6-1Alice与Bob的咖啡交易6.2.1交易 - 幕后细节
在幕后,实际的交易看起来与典型的区块浏览器提供的交易非常不同。 事实上,我们在各种比特币应用程序用户界面中看到的大多数高级结构实际上并不存在于比特币系统中。
我们可以使用Bitcoin Core的命令行界面(getrawtransaction和decodeawtransaction)来检索Alice的“原始”事务,对其进行解码,并查看它包含的内容。 结果如下:
Alice的交易被解码后是这个样子:
{
"version": 1,
"locktime": 0,
"vin": [
{
"txid": "7957a35fe64f80d234d76d83a2a8f1a0d8149a41d81de548f0a65a8a999f6f18",
"vout": 0,
"scriptSig" : "3045022100884d142d86652a3f47ba4746ec719bbfbd040a570b1deccbb6498c75c4ae24cb02204b9f039ff08df09cbe9f6addac960298cad530a863ea8f53982c09db8f6e3813[ALL] 0484ecc0d46f1918b30928fa0e4ed99f16a0fb4fde0735e7ade8416ab9fe423cc5412336376789d172787ec3457eee41c04f4938de5cc17b4a10fa336a8d752adf",
"sequence": 4294967295
}
],
"vout": [
{
"value": 0.01500000,
"scriptPubKey": "OP_DUP OP_HASH160 ab68025513c3dbd2f7b92a94e0581f5d50f654e7 OP_EQUALVERIFY OP_CHECKSIG"
},
{
"value": 0.08450000,
"scriptPubKey": "OP_DUP OP_HASH160 7f9b1a7fb68d60c536c2fd8aeaa53a8f3cc025a8 OP_EQUALVERIFY OP_CHECKSIG",
}
]
}
您可能会注意到有关此交易的一些事情,主要是缺少的事情! Alice的地址在哪里?Bob的地址在哪里? Alice“0.1”输入在哪里? 在比特币,没有硬币,没有发件人,没有收件人,没有余额,没有帐户,没有地址。 所有这些东西都是在更高层次上构建的,为了使用者的利益,使事情更容易理解。
你可能还会注意到很多奇怪和不可破译的字段和十六进制字符串。 不必担心,本章将详细介绍这里所示的各个字段。
6.3交易的输入输出
比特币交易中组成区块链的基础是交易输出。 交易输出是不可分割的比特币货币块,记录在块上,并被整个网络识别为有效。 比特币完整节点跟踪所有可用的和可花费的输出,称为未用量的交易输出,或UTXO。 所有UTXO的集合被称为UTXO集,目前有数百万个UTXO。 当新的UTXO的创建,UTXO集就会变大,当UTXO被消耗时,UTXO集会随着而缩小。 在UTXO集中,每个交易代表的一个变化(状态转换)。
当我们说用户的钱包已经“收到”比特币时,我们的意思是,钱包已经检测到可以使用的UTXO,而且这些UTXO是被该钱包密钥控制的。
因此,用户的比特币“余额”是用户钱包可以花费的所有UTXO和可能分散在数百个交易和数百个块中的总和。 “一个用户的比特币余额”,这个概念是一个通过比特币钱包应用创建的派生之物。比特币钱包通过扫描区块链并 聚合所有属于该用户的UTXO来计算该用户的余额。大多数钱包维护着数据库或使用数据库服务来存储所有UTXO的快速参考集,这些UTXO由用户所有的密钥进行控制花费行为。
一个UTXO可以是一“聪”的任意倍(整数倍)。就像美元可以被分割成表示两位小数的“分”一样,比特币可以被分割成表示八位小数 的“聪”。尽管UTXO可以是任意值,但只要它被创造出来了,就像不能被切成两半的硬币一样不可再分了。
如果一个 UTXO比一笔交易所需量大,它仍会被当作一个整体而消耗掉,但同时会在交易中生成零头。例如,你有20比特币的 UTXO并且想支付1比特币,那么你的交易必须消耗掉整个20比特币的UTXO并且产生两个输出:一个是支付了1比特币 给接收人,另一个是支付19比特币的找零到你的钱包。这样的话,大部分比特币交易都会产生找零。
想象一下,一位顾客要买1.5元的饮料。她掏出她的钱包并努力从所有硬币和钞票中找出一种组合来凑齐她要支付的1.5 元。如果可能的话,她会选刚刚好的零钱(比如一张1元纸币和5个一毛硬币)或者是小面额的组合(比如3个五毛硬 币)。如果都不行的话,她会用一张大面额的钞票,比如5元纸币。如果她把过多的钱,比如5元,给了商店老板,她会 拿到3.5元的找零,并把找零放回她的钱包以供未来使用。
类似的,一笔比特币交易可以有任意数值,但必须从用户可用的UTXO中创建出来。用户不能再把UTXO进一步细分,就 像不能把一元纸币撕开而继续当货币使用一样。用户的钱包应用通常会从用户可用的UTXO中选取多个可用的个体来拼 凑出一个大于或等于一笔交易所需的比特币量。
就像现实生活中一样,比特币应用可以使用一些策略来满足付款需要:组合若干小的个体,算出准确的找零;或者使用 一个比交易值大的个体然后进行找零。所有这些复杂的、由可支付的UTXO完成的组合,都是由用户的钱包自动完成, 并不为用户所见。只有当你以编程方式用UTXO来构建原始交易时,这些才与你有关。
被交易消耗的UTXO被称为交易输入,由交易创建的UTXO被称为交易输出。通过这种方式,一定量的比特币价值在不同 所有者之间转移,并在交易链中消耗和创建UTXO。一笔比特币交易通过使用所有者的签名来解锁UTXO,并通过使用新 的所有者的比特币地址来锁定并创建UTXO。
对于输出和输入链来说,有一个例外,它是一种特殊的交易类型,称为Coinbase交易。这是每个区块中的首个交易。 这种交易存在的原因是作为对挖矿的奖励而产生全新的可用于支付的比特币给“赢家”矿工。这也就是为什么比特币可以 在挖矿过程中被创造出来,我们将在挖矿这一章进行详述。
提示输入和输出,哪一个是先产生的呢?先有鸡还是先有蛋呢?严格来讲,先产生输出,因为可以创造新比特币的 coinbase交易没有输入,但它可以无中生有地产生输出。
6.3.1 交易输出
每一笔比特币交易创造输出,输出都会被比特币账簿记录下来。除特例之外(见“数据输出(OP_RETURN操作 符)”),几乎所有的输出都能创造一定数量的可用于支付的比特币,也就是UTXO。这些UTXO被整个网络识别,并且 所有者可在未来的交易中使用它们。
追踪UTXO的方式是通过UTXO集(UTXOset)中的每一个全节点比特币客户端实现的。 新的交易从UTXO集中消耗(支付)一个或多个输出。
交易输出包含两部分:
▷ 一定量的比特币,被命名为“聪”,是最小的比特币单位; ▷ 确定花费输出所需条件的加密难题(cryptographic puzzle)
这个加密难题也被称为锁定脚本(locking script), 见证脚本(witness script),脚本公钥 (scriptPubKey)。
个交易脚本语言会在后面121页的“交易脚本和脚本语言”一节中详细讨论。
现在,我们来看看Alice的交易(之前的章节“交易 - 幕后”),看看我们是否可以找到并识别输出。 在JSON编码中,输出位于名为vout的数组(列表)中:
"vout": [
{
"value": 0.01500000,
"scriptPubKey": "OP_DUP OP_HASH160 ab68025513c3dbd2f7b92a94e0581f5d50f654e7 OP_EQUALVERIFY
OP_CHECKSIG"
},
{
"value": 0.08450000,
"scriptPubKey": "OP_DUP OP_HASH160 7f9b1a7fb68d60c536c2fd8aeaa53a8f3cc025a8 OP_EQUALVERIFY OP_CHECKSIG",
}
]
如您所见,交易包含两个输出。 每个输出都由一个值和一个加密难题来定义。 在Bitcoin Core显示的编码中,该值显示在以bitcoin为单位,但在交易本身中,它被记录为以satoshis为单位的整数。 每个输出的第二部分是设定支出条件的加密难题。 Bitcoin Core将其显示为scriptPubKey,并向我们展示了一个人性化的脚本表示。
稍后将在脚本构造(Lock + Unlock)中讨论锁定和解锁UTXO的主题。 在ScriptPubKey中用于编辑脚本的脚本语言在Transaction Scripts和Script Language中讨论。 但在我们深入研究这些话题之前,我们需要了解交易投入和产出的整体结构。
6.3.1.1交易序列化 - 输出
当交易通过网络传输或在应用程序之间交换时,它们被序列化。 序列化是将数据结构的内部表示转换为可以一次发送一个字节的格式(也称为字节流)的过程。 序列化最常用于编码通过网络传输或用于文件中存储的数据结构。 交易输出的序列化格式显示在下表中。
表6-1交易输出序列化格式
大多数比特币库和框架不会在内部将交易存储为字节流,因为每次需要访问单个字段时,都需要复杂的解析。为了方便和可读性,比特币库将交易内部存储在数据结构(通常是面向对象的结构)中。
从交易的字节流表示转换为库的内部数据结构表示的过程称为反序列化或交易解析。转换回到字节流以通过网络传输,用于散列或存储在磁盘上的过程称为序列化。大多数比特币库具有用于交易序列化和反序列化的内置函数。
看看是否可以从序列化的十六进制形式手动解码Alice的交易,找到我们以前看到的一些元素。包含两个输出的部分在下面中会突出显示:
例6-1Alice的交易,序列化并以十六进制表示
这里有一些提示:
突出显示的部分有两个输出,每个序列化本节之前所述。
0.015比特币的价值是1,500,000 satoshis。 这是十六进制的16 e3 60。
在串行化交易中,值16 e3 60以小端(最低有效字节优先)字节顺序进行编码,所以它看起来像60 e3 16。
scriptPubKey的长度为25个字节,以十六进制为19。
6.3.2交易输入
交易输入将UTXO(通过参考)标记为将被消费,并通过解锁脚本提供所有权证明。
要构建一个交易,一个钱包从它控制的UTXO中选择足够的价值来进行请求的付款。 有时一个UTXO是足够的,其他时候不止一个。 对于将用于进行此付款的每个UTXO,钱包将创建一个指向UTXO的输入,并使用解锁脚本解锁它。
让我们更详细地看一下输入的组件。 输入的第一部分是通过参考在块链中记录UTXO的交易散列和序列号来指向UTXO的指针。 第二部分是解锁脚本,钱包构造以满足在UTXO中设置的支出条件。 大多数情况下,解锁脚本是一个数字签名和公钥,证明了比特币的所有权。 但是并不是所有的解锁脚本都包含签名。 第三部分是序列号,稍后再讨论。
考虑我们在之前章节交易幕后提到的例子。 交易输入是一个名为vin的数组(列表):
"vin": [
{
"txid": "7957a35fe64f80d234d76d83a2a8f1a0d8149a41d81de548f0a65a8a999f6f18",
"vout": 0,
"scriptSig" : "3045022100884d142d86652a3f47ba4746ec719bbfbd040a570b1deccbb6498c75c4ae24cb02204b9f039ff08df09cbe9f6addac960298cad530a863ea8f53982c09db8f6e3813[ALL] 0484ecc0d46f1918b30928fa0e4ed99f16a0fb4fde0735e7ade8416ab9fe423cc5412336376789d172787ec3457eee41c04f4938de5cc17b4a10fa336a8d752adf",
"sequence": 4294967295
}
]
如您所见,列表中只有一个输入(因为一个UTXO包含足够的值来进行此付款)。 输入包含四个元素:
引用包含正在使用的UTXO的交易的交易ID
一个输出索引(vout),用于标识来自该交易的哪个UTXO被引用(第一个为零)
一个scriptSig,满足UTXO上的条件,解锁它用于支出
序列号(稍后讨论)
在Alice的交易中,交易ID是:
7957a35fe64f80d234d76d83a2a8f1a0d8149a41d81de548f0a65a8a999f6f18
输出索引0(即由该交易创建的第一个UTXO)。解锁脚本由Alice的钱包构建,首先检索引用的UTXO,检查其锁定脚本,然后使用它来构建必要的解锁脚本以满足此要求。
看一下输入,你可能已经注意到,除了对包含它的交易的引用之外,我们不了解这个UTXO的任何内容。我们不知道它的价值(多少satoshi金额),我们不知道锁定脚本设置支出的条件。要查找此信息,我们必须通过检索基础交易来检索引用的UTXO。请注意,由于输入值未明确说明,因此我们还必须使用引用的UTXO来计算在此交易中支付的费用(参见后面交易费用章节)。
这不仅仅是Alice的钱包需要检索输入中引用的UTXO。一旦将该交易广播到网络,每个验证节点也将需要检索交易输入中引用的UTXO,以验证该交易。
交易本身似乎不完整,因为它们缺乏语境。他们在输入中引用UTXO,但是没有检索到UTXO,我们无法知道输入的值或其锁定条件。当编写比特币软件时,无论何时解码交易以验证它或计算费用或检查解锁脚本,您的代码首先必须从块链中检索引用的UTXO,以构建上下文隐含但不存在于输入的UTXO引用。例如,要计算费用支付的金额,您必须知道输入和输出值的总和。但是,如果不检索输入中引用的UTXO,则不知道它们的值。因此,在单个交易中计算费用的简单操作实际上涉及多个交易的多个步骤和数据。
我们可以使用与比特币核心相同的命令序列,就像我们在检索Alice的事务(getrawtransaction和decodeawtransaction)时一样。因此,我们可以在前面的输入中引用UTXO,并查看:
Alice的UTXO从以前的交易中引用的输入
"vout": [
{
"value": 0.10000000,
"scriptPubKey": "OP_DUP OP_HASH160 7f9b1a7fb68d60c536c2fd8aeaa53a8f3cc025a8 OP_EQUALVERIFY OP_CHECKSIG"
}
]
我们看到这个UTXO的值为0.1BTC,并且它具有包含“OP_DUP OP_HASH160 ...”的锁定脚本(scriptPubKey)。
提示为了充分了解Alice的交易,我们必须检索引用以前的交易作为输入。 检索以前的交易和未花费的交易输出的函数是非常普遍的,并且存在于几乎每个比特币库和API中。
6.3.2.1交易序列化--交易输入
当交易被序列化以在网络上传输时,它们的输入被编码成字节流,如下表所示
表6-2交易输入序列化与输出一样,我们来看看我们是否可以从序列化格式的Alice的交易中找到输入。 首先,输入解码:
"vin": [
{
"txid": "7957a35fe64f80d234d76d83a2a8f1a0d8149a41d81de548f0a65a8a999f6f18",
"vout": 0,
"scriptSig" : "3045022100884d142d86652a3f47ba4746ec719bbfbd040a570b1deccbb6498c75c4ae24cb02204b9f039ff08df09cbe9f6addac960298cad530a863ea8f53982c09db8f6e3813[ALL] 0484ecc0d46f1918b30928fa0e4ed99f16a0fb4fde0735e7ade8416ab9fe423cc5412336376789d172787ec3457eee41c04f4938de5cc17b4a10fa336a8d752adf",
"sequence": 4294967295
}
]
现在,我们来看看我们是否可以在下面中识别这些字段,并以十六进制表示法表示:
提示:
交易ID以反转字节顺序序列化,因此以(十六进制)18开头,以79结尾
输出索引为4字节组,容易识别
scriptSig的长度为139个字节,或8b为十六进制
序列号设置为FFFFFFFF,便于识别。
本章未完。待续。
参考内容:
1、本文部分内容摘自《精通比特币》第一版中译本,特此说明并致谢。
我正在发起“和我一起阅读《精通比特币第二版》”活动。
我把这作为一次认知学习法的实践。
我希望将认知学习法与《精通比特币第二版》的研读结合起来,尝试总结出一套可行的区块链知识技能快速入门的方法。
这也将成为我们大家一起合作编写的一本书《认知学习比特币》的雏形(所有有价值的讨论都将成为这本书的素材)。
而且我更希望通过本次认知学习方法论的实践以及迭代,将这种经过实践的学习方法迁移到更多领域的学习中。
所以我们会有第二季,第三季......
欢迎扫描二维码加入。
欲知详情请扫描二维码
网友评论