区块链

这个开发者指南的目标是在你开发一个比特币周边应用的时候,给你提供足够的信息。为了更好地使用这个指南,你需要安装最新的bitcoin内核的客户端,可以下载github里面的源码或者官网的预编译版本

一旦安装完毕,你将有以下的三个可执行程序:bitcoind, bitcoin-qt, andbitcoin-cli。 如果你启动的时候没带参数,所有的程序都会默认连接到比特币主网络network(mainnet)。要在网络上创建交易,你就要支付比特币。比特币的最小单位是“聪(satoshis)”,0.00000001 BTC = 1satoshis

但是,为了开发,使用比特币测试网络更为安全和便宜 network (testnet) ,在测试网络中的比特币没有真实世界的价值。 测试网络 对有些限制有所放松,(如对标准交易的检测),它能测试一些在主网络中被禁止的函数,

如果要使用测试网络testnet, 启动的时候需要添加参数 -testnet 或者添加testnet=1到你的bitcoin.conf 文件里面。在Piotr Piasecki’s testnet faucet,你可以获得一些免费的测试比特币。测试网络是社区人员免费提供的公共资源,请不要滥用。

你可以进一步使用regression test mode(回归测试模式)来加快你的开发,这个模式可以在你的电脑上创建一个本地的测试网络。 回归测试模式可以让你通过RPC命令快速创建blocks、获取测试比特币、即刻在block chain上生成交易。

  • bitcoin-qt提供了一个完整的Bitcoin peer 和钱包的前端.在帮助菜单中,你可以找到一个敲RPC 命令的终端

  • bitcoind是个更有用的程序: 它提供了一个完整的 peer(节点) 你可以使用RPCs命令和它交流,正式端口默认8332 (测试网络默认端口18332).

  • bitcoin-cli允许你通过命令行发送 RPC 命令给bitcoind. 举个例子,bitcoin-cli help

    这三个程序都会从Bitcoin程序目录里的bitcoin.conf中读取参数设置:

    • Windows:

      %APPDATA%\Bitcoin\

    • OSX:

      $HOME/Library/Application Support/Bitcoin/

关于比特币开发的问题最好发送到比特币论坛IRC 频道. 对于Bitcoin.org的文档的错误和建议,请以提案的方式提交或者发送到bitcoin-documentation 邮件列表.

在以下的指南里, 某些字符串被缩写成: “[…]” ,表示额外的数据被删除了, 以 “\” 结束的行表明下面还有. 如果你把你的鼠标移动到一个段落,有链接的文字会变成蓝色。如果你移动到有链接的文字上,在工具提示上会出现一个简介。

区块链

区块链提供了比特币的公开总账本, 这个总账本由所有有时序的已确定的交易组成。这个系统被用于防止双花和修改以前的交易记录, 通过被全球P2P网络验证的工作量证明POW来保证全球的一致性。

区块链概览

上面的插图展示了一个简化版本的区块链. 一个包含一个或者多个交易的区块 会被收集到区块的交易数据部分. 每个交易的副本都会被哈希,然后将哈希值进行配对,然后再进行哈希,再配对,再哈系,直到只剩下一个哈希值,这个剩下的哈希值就是Merkle tree(Merkle 树)Merkle root(根节点)

Merkle根节点被存储在区块头。每个区块也会存储上一个区块头的哈希值, 以把所有的区块链接在一起. 这保证了在不修改当前和后面的所有区块的情况下,交易记录是不会被修改的。

交易记录也被链接在一起。比特币钱包软件只记录了比特币的发送接收, 但比特币确实在交易间转移。 每个标准交易花费的satoshis是前一个交易转移过来的币, 所以一个交易的输入是上一个交易的输出

单个比特币交易能把比特币发送到不同的输出中, 就像你把比特币一次发送到不同的地址一样,但是一次输出在区块链中只能使用一次 所有的后续引用都禁止双花—一种把比特币花两次的尝试。

输出不同于比特币 地址。你可以在多个交易中使用同一个地址, 但是输出 只能被使用一次。输出 与交易id(TXIDs)绑定, txid就是签名交易的哈希值

因为每个交易的输出只能被使用一次, 所有在区块链 中的输出能被分类为未使用交易输出Unspent Transaction Outputs (UTXOs)或者已使用输出. 为了让支付有效, 必须使用 未使用输出UTXOs 来作为输入.

比特币在产生交易之后,不能留在UTXO中, 否则这个余额会永久的丢失掉, 所以输入和输出之间的差值就是交易费,都是对把这个交易打包到区块的矿工的奖励。例如,在上面的插图中,每次交易收到的都比发出的会少1000聪, 这10000聪就是交易费

Proof Of Work 工作量证明

区块链是由P2P网络(peer-to-peer network)协作维护的,比特币网络要求在创建区块的时候要提供一定的工作量证明,以保证那些想改变历史区块的不诚实的节点必须付出比那些仅仅想在链上加一个新区块的诚实节点更多的资源。

如果不修改后面所有的区块,修改已经打包到区块中的交易成为一件不可能的事情,这也是把区块链接到一起的用处。 因此,修改一个区块的费用会随着新区块的增加而增加,工作量证明的作用也就随之变大。

比特币网络中的工作量证明利用了密码学哈希算法的伪随机性。一个好的密码学哈希可以把任意的数据转换成一个看起来随机的数字。如果这个原始数据的任何地方被更改,然后重新计算哈希,将会生成一个完全不同的新的哈希结果。所以修改数据以预知哈希的结果是不可能的。 为了证明你已经做了一些创建区块的工作,你需要计算出一个不大于某个特定值的块头的哈希值。举个例子: 如果这个最大哈希值是22562^{256} − 1,你只要证明你做了两次组合就可以使哈希值小于22562^{256} − 1。

在上面的例子中,你很有可能在第一次尝试的时候就生成了一个成功的哈希值。你甚至可以估算你要达到的某个阈值所需要的尝试的次数。比特币本身并不能控制这个可能性,但是单纯假设这个阈值越小需要尝试的次数越多,平均下来也就是个平均数(这个是概率平均)。

只有当哈系值至少跟P2P网络预期的难度值难度相当的时候,新的区块才会被加到区块链上。比特币网络使用储存在2016个区块头的时间戳的差值来计算下一轮的难度。这个差值的理想的间隔是1,209,600秒(两周)。

  • 如果产生2016个区块的时间小于两周,预期的难度将成比例地提高(大约300%)以便于下一个块能够准确地在两周生成,前提是保证在当前的HASH在同一算力.

  • 如果产生2016个块的时间超过两周,同样地,预期难度将降低(75%左右)。

(注意: 比特币内核实现的一个差一错误,导致每到2016区块的时候,因为使用了第2015块的时间戳,难度就会更新,这导致了轻微的偏差。

由于每一块头的哈希值必须小于某个阈值,每一区块也必须链接到它前面的一个区块。要在原始区块生成到当前这段时间里传送一个已修改的区块,(一般来说)需要消耗和整个比特币网络消耗的算力一样多的哈系算力。只有你掌握了全网大多数哈希算力,你才能有效地实现对交易历史进行51%的攻击。

区块头提供了一些容易改的字段,例如dedicated nonce field,所以获取新块的哈希不需要等新的交易的到来。同样,只有80字节的区块头会被计算到POW的哈希中,因此添加更多的交易信息不会降低伴有额外I/O的哈希计算速度.

区块高度及分叉

任何成功计算出小于阈值的哈系值的矿工可以把整个区块加到区块链中(假设这个区块是有效的)。这些区块被标记为当前区块的高度--就是当前区块到第一个块(genesis block)的差值. 比如,第2016块是第一个调整难度的块。

多个区块可以有同样的区块高度,这在两个或两个以上的矿工几乎在同一时间创建了一个区块的情况下是很常见的。正如上图所示,区块链上出现了显然的分叉。

当矿工同时在区块链的末端生成区块的时候,每个节点都独立地选择相信哪个区块。(在没有其他考虑的情况下,节点通常选择相信他们接收到的第一个块)。

最终,矿工会创建一个新块,这个区块附在其中一个竞争的并行区块。这会使这个分支比别的分支更长。假设一个分支只包括有效的区块,正常的节点将选择最长的那个分支(最难创建的一个链),然后抛弃比它短的分支。

长期的分叉是可能的,如果这些矿工有其他意图,比如一些矿工在分叉之后的一条分支上奋力计算,尝试51%攻击去修改交易历史。

由于很多区块在分叉的时候会有同样的高度,所以高度不能作为唯一的区分。通常,都用它的SHA256的哈希值来表示这个区块。

交易数据

每个区块必须包含一个或者多个交易记录,第一个交易记录必须是coinbase(币基)记录,这个记录包含了区块奖励和本区块的所有的交易费。

由挖矿出来的币有一个特殊的使用条件,就是在此后的100块只能不能使用。这个可以部分防止有的矿工花费可能以后被抛弃的区块奖励(分叉之后,这个矿工的这条链被抛弃)。

区块不是必须包含所有的非-coinbase的交易,但是矿工们通常会为了他们的交易费把这些交易记录给收录进来。

所有的交易记录,包含coinbase记录,会在前面加上交易队列的编报,并被编码为rawtransaction格式的二进制进行存储。

rawtransaction 格式是由txid哈希而来. 这些txids组成了一个Merkle树。Merkle树是一个层级hash树,如果叶节点有两个叶子,节点的值就是这两个值的哈希,如果叶节点只有一个节点,节点的值就是这一个叶节点的哈希值。

如果有并排节点的,就和并排节点一起哈希;所有没有并排节点的节点都自己计算哈希,这样一层一层计算,就计算出Merkle根节点的哈希。

举个例子,这些节点仅仅是组合在一起(并未计算哈希), 五层的交易记录Merkle 树就是像下图这样

       ABCDEEEE .......Merkle root
      /        \
   ABCD        EEEE
  /    \      /
 AB    CD    EE .......E is paired with itself
/  \  /  \  /
A  B  C  D  E .........Transactions

在简单支付验证(SPV)部分,这个Merkle树允许客户端验证他们的在某个块中的交易记录,通过从Merkle根节点进行遍历。所有的节点不用被信任:在区块头作假是一件很昂贵的事情,中间的哈希结果不能被伪造,否则这个认证将失败。

举个例子, 为了证明D交易被添加到这个区块中,一个SPV客户端只需要拷贝C、AB和EEEE 哈希到Merkle根节点;客户端不需要知道其他的交易的任何信息。如果这5个交易都达到了最大的大小,下载整个区块将需要500,0000 字节,但是下载这3个哈希值加上头部只需要140字节。

Last updated