首页 百科知识 整合交易到区块中

整合交易到区块中

时间:2022-07-17 百科知识 版权反馈
【摘要】:验证交易之后,比特币节点会将它们加入内存池中,交易在那里等待着被加入(挖矿)一个区块内,这是比特币共识机制的第二个步骤。当接收到区块277315并验证后,景的节点对内存池中的交易进行检查,剔除那些已被包含进277315区块的交易。仍然留在内存池中的交易都是未确认的交易,它们继续等待被记录到新区块中。

验证交易之后,比特币节点会将它们加入内存池(或交易池)中,交易在那里等待着被加入(挖矿)一个区块内,这是比特币共识机制的第二个步骤。景的节点与其他节点一样,收集、验证并转发交易。与其他节点不同的是,景的节点在完成这些动作后,还要把这些交易整合到一个候选区块(candidate block)中。

我们来跟踪一些区块,这些区块是在爱丽丝从鲍勃咖啡店购买一杯咖啡期间创建的(参见第2章中“购买一杯咖啡”)。爱丽丝的交易被包含进277316号区块。为了演示本章所阐述的概念,我们假设这个区块是被景的挖矿系统挖出来的,我们将在爱丽丝的交易成为新区块的一部分后,继续跟进这笔交易。

景的挖矿节点维护着一份区块链的完整副本,它是所有区块的列表,包含了2009年比特币系统创建以来的所有区块。在爱丽丝购买那杯咖啡前,景的节点已经装配了一条包含277314个区块的链条。景的节点持续监听交易,尝试挖出新的区块;同时,它也监听其他节点发现的区块。当景的节点正在挖矿时,它从比特币网络中接收到277315号区块。这个区块的到达,标志着区块277315的挖矿竞争结束了,而创建区块277316的竞争从此开始。

在之前的10分钟内,景的节点在查找区块255315的解决方案的过程中,也在收集交易,为创建下个区块做准备。此时,它已经收集了几百个交易并保存在内存池中。当接收到区块277315并验证后,景的节点对内存池中的交易进行检查,剔除那些已被包含进277315区块的交易。仍然留在内存池中的交易都是未确认的交易,它们继续等待被记录到新区块中。

完成这些准备工作后,景的节点立即创建一个新的空区块,作为区块277316的候选,这个区块就叫作候选区块,因为它尚未成为有效区块,不包含有效的工作量证明。只有在矿工成功找到一个工作量证明算法的解后,这个区块才会变为有效。

为了构建候选区块,景的比特币节点需要从内存池中选择交易。选择过程首先要对每个交易赋予一个优先级权数,并将最高优先级的交易优先选出。交易基于输入中即将被花费的UTXO的“年龄”进行排序,允许那些较老的、高价值的交易输入比那些较新的、低价值的交易输入拥有更高的优先级。只要区块空间足够,高优先级的交易可以免费发送。

交易优先级是通过输入价值与输入“年龄”乘积的汇总再除以交易总大小后得出的。

在等式中,输入价值的单位是比特币的基础单位,即聪(1比特币的1亿分之一)。UTXO的年龄是自UTXO被记入区块起所经过的区块数量,即这个UTXO在区块链中的深度。交易记录的大小用字节来表示。

对一个被认定为“高优先级”的交易来说,它的优先级必须大于57600000,这相当于一个包含1比特币(1亿聪)、年龄为1天(144区块)、大小为250字节的交易。

区块交易空间的前50KB是保留给高优先级交易的。景的节点将首先填充前50KB,最高优先级的交易优先处理,不管有没有交易费用。即使没有交易费用,高优先级交易也能得到处理。

接着,景的节点继续填充区块的剩余部分,直到达到其大小的上限(代码中设定的MAX_BLOCK_SIZE),这部分交易必须至少包含最低交易费用,并且依据每千字节交易费用的高低进行排序。

如果区块中仍有空间,景的节点可能会选择没有交易费用的交易来填充它。某些矿工基于最大努力原则,将没有交易费用的交易加入区块,而有些矿工则可能选择忽略那些没有交易费的交易。

区块填充后,若还有交易留在内存池中,它们将继续在内存池中等待下个区块的处理。由于交易停留在内存池中,它们的输入“年龄”,即它们花费的UTXO在区块链中的深度将随着新区块的加入而变得更深。因为交易的优先级基于输入年龄,交易保留在内存池中会“变老”,从而优先级得以提高。最终,没有交易费用的交易也有可能拥有足够高的优先级,并被免费添加进区块当中。

比特币的交易并没有超时的设置。一个当前有效的交易也将永久有效。但是,如果一个交易只在网络中传播一次,它只会停留在矿工节点的内存池中。由于内存是一种临时的、非持久化的存储形式,当矿工节点重启后,它的内存池就会被清空。虽然有效交易可能已经被传播到网络上,但是如果它一直未被处理,最终可能从所有挖矿节点的内存池中消失。如果交易未在一定时间内得到处理,钱包软件应该重新发送交易或重新创建包含较高交易费用的交易。

当景的节点汇聚了内存池中的所有交易后,新的候选区块总共填充了418个交易,合计交易费用为0.09094928比特币。你可以利用比特币核心的命令行接口看到区块链中的这个区块,如例8-3所示。

加入区块的第一笔交易是一个特殊交易,叫作铸币交易(generation transaction)币基交易(coinbase transaction)。这个交易由景的节点创建,也是对他挖矿付出努力的报酬。景的节点创建了一笔铸币交易,内容为向其钱包发起支付:“支付25.09094928比特币到景的地址。”景通过挖出一个区块获得的总报酬为币基奖励(25新比特币)与区块中所有交易的交易费用汇总(0.09094928比特币)的和,如例8-4所示。

不像普通交易,铸币交易并不需要消耗(花费)UTXO。实际上,它只有一个输入,叫作币基(coinbase),这个交易从无到有生成了比特币。铸币交易有一个输出,支付到矿工的比特币地址。铸币交易的输出将25.09094928比特币发送到矿工的比特币地址。在本例中,地址为:1MxTkeEP2PmHSMze5tUZ1hAV3YTKu2Gh1N。

首先,为了构建一笔铸币交易,景的节点对所有加入区块的418个交易的输入和输出进行汇总轧差,计算得出交易费用。计算公式如下。

在区块277316中,总的交易费用是0.09094928比特币。

接着,景的节点需要计算新区块的准确奖励金额。奖励金额的计算基于区块高度,从每区块50比特币开始,每210000个区块减半。当前的区块高度是277316,因此正确的奖励是25比特币。

计算过程可以在比特币核心客户端的函数GetBlockValue中查到,如例8-5所示。

初始奖励是以聪为单位进行计算的,其值为50与COIN常量(100000000聪)的乘积。即初始的奖励金(nSubsidy)为50亿聪。

接下来,计算已经发生的减半(halvings)次数:将当前的区块高度除以减半间隔(SubsidyHalvingInterval)。对区块277316来说,除以210000的减半间隔,其结果为1,即1个减半。

可允许的最大的减半次数为64次,所以在代码中,如果减半次数超出了64,就将奖励金设置为0(只返回交易费用)。

再接下来,函数采用右移操作符对奖励金(nSubsidy)进行除以2的操作,每次减半右移一位,即除以2。对于区块277316,由于减半次数为1次,则对奖励金(50亿聪)右移操作一次,得到的结果是25亿聪,或者25比特币。之所以使用右移操作符,是因为它做除以2的操作效率比整数除法或浮点型除法高得多。

最后,函数将币基奖励(nSubsidy)与交易费用(nFees)相加,将两者总和返回。

通过以上计算,景的节点创建了一个铸币交易,向他自己支付了25.09094928比特币。

从例8-4可以看到,铸币交易使用了一种特殊的格式。相对普通交易的输入需要指定用于花费的前序UTXO,铸币交易只有一个“币基”输入。我们曾在表5.3中考察了普通交易的输入。现在我们将普通交易的输入与铸币交易的输入做个对比。表8.1显示的是普通交易输入的数据结构,表8.2显示的是铸币交易输入的数据结构。

表8.1 “普通”交易的输入结构

表8.2 铸币交易的输入结构

在铸币交易中,前两个字段设置为与UTXO引用无关的值。第一个字段是32字节的“0”,而不是“交易哈希”。“输出索引”用4字节0xFF填充(十进制255)。“解锁脚本”被替换为币基数据,一个可由矿工自由定义的数据。

铸币交易没有解锁脚本(scriptSig)字段。相反,这个字段被替换为币基数据,长度限定在2到100字节之间。除了前面几个字节,币基数据的剩余部分可被矿工用于其自主的任何用途,填充任意数据。

举例来说,在创世区块中,中本聪在币基数据中加了这段话:“The Times 03/Jan/2009 Chancellor on brink of second bailout for banks”(《泰晤士报》,2009年1月3日,财政大臣正处于实施第二轮银行紧急援助的边缘)用以证明比特币的发明日期并传达一条信息。当前,矿工们通常使用币基数据包含额外的随机数,并附上标识其矿池信息的字符串,我们将在接下来的几个章节继续讨论。

币基的前几个字节曾经也是可以任意安排的,但是现在不再这样了。依据比特币改进提案34号(BIP0034),版本2区块(版本字段设置为2的区块)必须在币基字段的最前面附加区块高度索引,作为脚本的“压栈”操作。

在区块277316中,我们看到币基(参看例8-4),也就是交易输入的“解锁脚本”或scriptSig字段,包含一段十六进制数据03443b0403858402062f503253482f。我们将其解码,看看其内容。

第1个字节,03,指示脚本执行引擎将后续3个字节压入脚本堆栈中(参见附录A表A.1)。接下来的3个字节,0x443b04,以小字节序(little endian)格式编码的区块高度。将其字节序翻转,结果就是0x043b44,对应的十进制就是277316。

紧接着的几个十六进制数字(03858402062)用于编码额外随机数(参看本章中“扩展随机数方案”),以用于找到合适的工作量证明的解。

最后部分(2f503253482f)是ASCII编码的字符串(“/P2SH/”),提示本区块的挖矿节点支持BIP0016定义的“支付到脚本哈希(P2SH)”。P2SH能力引入的时候曾要求矿工“投票”,从BIP0016和BIP0017中间选择一个。那些选择了BIP0016实现的矿工会将“/P2SH/”加进币基数据,而那些选择了BIP0017的P2SH实现的矿工则在币基数据中加入字符串“p2sh/CHV”。最终BIP0016成了赢家,但是很多矿工依然将字符串/P2SH/加入币基中,表明其支持这个特性的态度。

例8-6使用libbitcoin库(参见第3章“替代客户端、库、工具集”)从创世区块中提取币基数据,并显示中本聪在区块中留下的信息。需要注意的是,libbitcoin内嵌了创世区块的静态复制,所以示例代码可以直接从库中提取创世区块。

使用GNU C++编译这段代码,运行所生成的可执行程序,结果如例8-7所示。

免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。

我要反馈