精通比特币(75):创币交易

  • A+

创币交易

区块中的第一笔交易是笔特殊交易,称为创币交易或者coinbase交易。这个交易是由挖矿节点构造并用来奖励矿工们所做的贡献的。

与常规交易不同,创币交易没有输入,不消耗UTXO。它只包含一个被称作coinbase的输入,仅仅用来创建新的比特 币。创币交易有一个输出,支付到这个矿工的比特币地址。

Coinbase奖励与矿工费

为了构造创币交易,挖矿节点需要计算矿工费的总额,将已添加到区块交易的输入和输出分别进行求和,然后用输入总额减去输出总额得到矿工费总额,公式如下:
Total Fees = Sum(Inputs) - Sum(Outputs)

紧接着,挖矿节点计算出这个新区块正确的奖励额。奖励额的计算是基于区块高度的,以每个区块50个比特币为开始,每产生210,000个区块减半一次。这个区块高度是277,316,所以正确的奖励额是25个比特币。【详细的计算过程可以参看比特币核心客户端中的GetBlockValue函数。】

计算区块奖励—函数GetBlockValue, Bitcoin Core Client, main.cpp

CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams){
int halvings = nHeight / consensusParams.nSubsidyHalvingInterval;
// Force block reward to zero when right shift is undefined.
if (halvings >= 64)
return 0;

CAmount nSubsidy = 50 * COIN;
// Subsidy is cut in half every 210,000 blocks which will occur approximately every 4 years.
nSubsidy >> = halvings;
return nSubsidy;
}

变量Subsidy表示初始奖励额,值为COIN 常量(100,000,000聪)与50的乘积,也就是说初始奖励额为50亿聪。
紧接着,这个函数用当前区块高度除以减半间隔( SubsidyHalvingInterval 函数)得到减半次数(变量 halvings )。每 210,000个区块为一个减半间隔,对应本例中的区块277316,所以减半次数为1。
变量 halvings 最大值64,如果超出这个值,代码算得的奖励额为0。

然后,这个函数会使用二进制右移操作将奖励额(变量 nSubsidy )右移一位(等同与除以2),每一轮减半右移一次。在这个例子中,对于区块277,316只需要将值为50亿聪的奖励额右移一次,得到25亿聪,也就是25个比特币的奖励额。之所以采用二进制右移操作,是因为相比于整数或浮点数除法,右移操作的效率更高。
​最后,将coinbase奖励额(变量 nSubsidy )与矿工费( nFee )总额求和,并返回这个值。
注意: 如果挖矿节点把coinbase交易写入区块,那么如何防止挖矿奖励自己100甚至1000比特币? 答案是,不正确的奖励将被其他人视为无效,浪费了挖矿节点用于工作证明的投入。 只有这个区块被大家认可,挖矿节点才能得到报酬。

创币交易的结构

创币交易的结构比较特殊,与一般交易输入需要指定一个先前的UTXO不同,它包含一个“coinbase“输 入。

常规交易输入结构

精通比特币(75):创币交易

coinbase交易输入结构

精通比特币(75):创币交易

在Coinbase交易中,“交易哈希”字段32个字节全部填充0,“交易输出索引”字段全部填充0xFF(十进制的255),这两个字段的值表示不引用UTXO。“解锁脚本”由coinbase数据代替,数据可以由矿工自定义。

Coinbase数据

创币交易不包含“解锁脚本“(又称作 scriptSig)字段,这个字段被coinbase数据替代,长度最小2字节,最大100字节。除了开始的几个字节外,矿工可以任意使用coinbase的其他部分,随意填充任何数据。

以创世块为例,中本聪在coinbase中填入了这样的数据“The Times 03/Jan/ 2009 Chancellor on brink of second bailout for banks“(泰晤士报 2009年1月3日 财政大臣将再次对银行施以援手),表示对日期的证明,同时也表达了对银行系统的不信任。现在,矿工使用coinbase数据实现extra nonce功能,并嵌入字符串来标识挖出它的矿池。

coinbase前几个字节也曾是可以任意填写的,不过在后来的第34号比特币改进提议(BIP34)中 规定了版本2的区块(版本字段为2的区块),这个区块的高度必须跟在脚本操作“push“之后,填充在coinbase字段的起始处。

我们以区块277,316为例,coinbase就是交易输入的“解锁脚本“(或scriptSig)字段,这个字段的十六进制值 为03443b0403858402062f503253482f。下面让我们来解码这段数据。
​第一个字节是03,脚本执行引擎执行这个指令将后面3个字节压入脚本栈(见表4-1);紧接着的3个字节——0x443b04, 是以小端格式(最低有效字节在先)编码的区块高度。翻转字节序得到0x043b44,表示为十进制是277,316。
​紧接着的几个十六进制数(03858402062)用于编码extra nonce,或者一个随机值,从而求解一个适当的工作量证明。​
coinbase数据结尾部分(2f503253482f)是ASCII编码字符 /P2SH/,表示挖出这个区块的挖矿节点支持BIP0016所定义的 pay-to-script-hash(P2SH)改进方案。在P2SH功能引入到比特币的时候,曾经有过一场对P2SH不同实现方式的投票, 候选者是BIP0016和BIP0017。支持BIP0016的矿工将/P2SH/放入coinbase数据中,支持BIP0017的矿工将 p2sh/CHV 放入他们的coinbase数据中。最后,BIP0016在选举中胜出,直到现在依然有很多矿工在他们的coinbase中填 入/P2SH/以表示支持这个功能。

可以使用libbitcoin库从创世块中提取coinbase数据,并显示出中本聪留下的信息。libbitcoin库中自带了一份创世块的静态拷贝,所以这段示例代码可以直接取自库中的创世块数据。

发表评论

您必须才能发表评论!