字节 | 名称 | 数据类型 | 描述 |
---|---|---|---|
4 | Veesion | int32_t | 版本号表示所遵循的规则 |
32 | preBlockHeaderHash | char[32] | SHA256(SHA256())前一块头部的哈希 |
32 | MerkleRootHash | char[32] | 这块中所有交易的哈希 |
4 | time | uint32_t | Unix时间戳 |
4 | nbits | uint32_t | 难度系数 |
4 | Nonce | uint32_t | 随机数 |
Merkle Root是根据这个块中所有交易的TXID生成的:
如果一个区块仅有一个CoinBase的交易,这个CoinBase的TXID就被用作Merkle的根哈希。
如果一个区块有一个CoinBase的交易和一个其他交易,那么就排好顺序为64字节然后进行SHA256(SHA256())形成Merkle根哈希。
如果一个区块有3个以上的交易,则形成中间Merkle树。TXID按顺序排列并配对,从CoinBase的TXID开始。每一对都拼接在一起然后进行SHA256(SHA256()),形成第二排散列。如果有一个非偶数(奇数)的TXID个数,则最后一个TXID复制一个自己然后SHA256(SHA256())。如果第二排有超过2个的hashed,则重复上一步的操作。直到只剩2个hashed的时候,再拼接并SHA256(SHA256())形成Merkle树的根。
目标阈值是一个无符号的256-bit整数,头部哈希必须小于等于这个值才能成为区块链的有效部分。
序列化块
按照目前的共识规则,大于1MB的块是无效的。下面介绍的大小全是序列化后的大小。
字节 | 名称 | 数据类型 | 描述 |
---|---|---|---|
80 | block header | block_header | 上面曾描述过的结构 |
Varies | txn_count | compactSizeUnit | 包括CoinBase在内的所有交易数目 |
Varies | txns | raw trasaction | 此块中的每一个交易,一个接一个。 |
块中的第一个交易必须为CoinBase交易,用以收集本块中的交易费用。
所有块高不超过6,930,000的区块都有权获得创建区块的奖励。(区块奖励从50比特币开始,每210,000块减半,大约每四年一次,截至2017年11月,为12.5比特币。)
以下小节将简要介绍核心交易的细节。
在标准交易中的公有脚本操作码:
OP_TRUE
/OP_1
(0x51)和OP_2
到OP_16
(0x52-0x60),表示把1-16压入栈中。OP_CHECKSIG
消费一个签名和一个公钥,如果由SIGHASH标志指定的交易数据被转换为使用生成该公钥的相同ECDSA私钥的签名就压入TRUE, 否则,它会将FALSE压入堆栈。OP_DUP
把栈顶元素复制并压入栈中。OP_HASH160
消费栈顶元素,计算RIPEMD160(SHA256()),并把计算后的值压入栈中。OP_EQUAL
消费栈顶的2个元素,比较,相同压入真,否则压入假。OP_VERIFY
消费栈顶元素,如果是0则终止脚本。OP_EQUALVERIFY
按顺序运行 OP_EQUAL
和 OP_VERIFY
。 比特币地址通常用P2PKH和P2SH来进行哈希操作。
首先,获取你的哈希值。对于P2PKH,使用RIPEMD-160(SHA256()) 哈希从你256-bit的ECDSA私钥(随机数)所对应的公钥。对于P2SH,使用RIPEMD-160(SHA256()) 对序列化原始交易通过转化脚本来获得哈希(后续会讲到)。获得哈希结果:
1. 在哈希值前添加一个字节版本
2.创建一个版本和哈希值得副本,然后进行2次哈希运算SHA256(SHA256(version . hash))
3.从双重哈希副本中提取前四个字节。 这些被用作校验和以确保哈希传输正确。
4.将校验和附加到版本和散列之后,并将其编码为base58字符串:BASE58(version . hash . checksum)
比特币的base58编码称为Base58Check,与其他一般实现不太一样。Wiki
code_string = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
x = convert_bytes_to_big_integer(hash_result)
output_string = ""
while(x > 0)
{
(x, remainder) = divide(x, 58)
output_string.append(code_string[remainder])
}
repeat(number_of_leading_zero_bytes_in_hash)
{
output_string.append(code_string[0]);
}
output_string.reverse();
要将地址转换回哈希值,先base58解码,提取校验和,重复这些步骤以创建校验和,并将其与提取的校验和进行比较,然后删除版本字节。
比特币的交易以序列化的字节格式在点对点之间播发,SHA256(SHA256())
交易去创建TXID,最终是包含交易的块的Mekle树根。
原始交易具有以下格式:
字节 | 名称 | 数据类型 | 描述 |
---|---|---|---|
4 | version | uint32_t | 交易版本号,现在的版本号是1;使用更新的共识规则规则创建的交易可能有更高的版本号。 |
Varies | tx_in count | compactSize uint | 交易输入的数量 |
Varies | tx_in | txIn | 交易输入。 请参阅下面的txIn的描述。 |
Varies | tx_out count | compactSize uint | 交易输出的数量。 |
Varies | tx_out | txOut | 交易输出。 请参阅下面的txOut的描述。 |
4 | local_time | unit32_t | Unix时间或块号,请参阅locktime解析规则。 |
一个交易可能有多笔的输入和输出,所以txIn和txOut结构可能在一个结构中重复出现。CompactSize无符号整数是可变长整数的一种形式; 它们在CompactSize部分中进行了描述。
每一个非CoinBase的输入花费一个outpoint来自之前的交易。(Coinbase输入在下面的示例部分之后单独描述。)
字节 | 名称 | 数据类型 | 描述 |
---|---|---|---|
36 | previous_output | outpoint | 之前被消费的outpoint,请参阅下面的outpoint描述。 |
Varies | script bytes | compactSize uint | 签名脚本中的字节数。 最大值为10,000字节。 |
Varies | signature script | char[] | 一个脚本语言,满足outpoint的pubkey脚本中的条件。 只应该包含数据推送; 请参阅签名脚本修改警告。 |
4 | sequence | uint32_t | 序列号。 比特币核心和几乎所有其他程序的默认值是0xffffffff。 |
由于一个单一的交易可以包含多个输出,outpoint结构包含一个TXID和一个输出索引号指向一个具体的输出。
字节 | 名称 | 数据类型 | 描述 |
---|---|---|---|
32 | hash | char[32] | 交易的TXID输出的花费,TXID是以内部字节顺序提供的哈希。 |
4 | index | uint32_t | 交易中具体花费的具体输出索引号。第一个输出是0x00000000 |
每个输出花费一定数量的聪,任何可以提供满足pubkey script.的人都可以使用它。
字节 | 名称 | 数据类型 | 描述 |
---|---|---|---|
8 | value | int64_t | 花费聪的数量。可能是零;所有输出的总和不得超过以前用于输入部分所提供的聪的总和。 (例外:coinbase交易花费区块奖励和收取的交易费用。) |
1+ | pk_script bytes | compactSize uint | pubkey脚本中的字节数。 最大值是10,000字节。 |
Varies | pk_script | char[] | 定义花费这个输出必须满足的条件。 |
一个交易的例子。
01000000 ................................... Version
01 ......................................... Number of inputs
|
| 7b1eabe0209b1fe794124575ef807057
| c77ada2138ae4fa8d6c4de0398a14f3f ......... Outpoint TXID
| 00000000 ................................. Outpoint index number
|
| 49 ....................................... Bytes in sig. script: 73
| | 48 ..................................... Push 72 bytes as data
| | | 30450221008949f0cb400094ad2b5eb3
| | | 99d59d01c14d73d8fe6e96df1a7150de
| | | b388ab8935022079656090d7f6bac4c9
| | | a94e0aad311a4268e082a725f8aeae05
| | | 73fb12ff866a5f01 ..................... Secp256k1 signature
|
| ffffffff ................................. Sequence number: UINT32_MAX
01 ......................................... Number of outputs
| f0ca052a01000000 ......................... Satoshis (49.99990000 BTC)
|
| 19 ....................................... Bytes in pubkey script: 25
| | 76 ..................................... OP_DUP
| | a9 ..................................... OP_HASH160
| | 14 ..................................... Push 20 bytes as data
| | | cbc20a7664f2f69e5355aa427045bc15
| | | e7c6c772 ............................. PubKey hash
| | 88 ..................................... OP_EQUALVERIFY
| | ac ..................................... OP_CHECKSIG
00000000 ................................... locktime: 0 (a block height)
在区块中的第一个交易,叫做Coinbase交易,有且只有一个输入,叫做Coinbase。Coinbase输入的格式如下:
字节 | 名称 | 数据类型 | 描述 |
---|---|---|---|
32 | hash (null) | char[32] | 一个32字节的null,作为coinbase没有先前的outpoint。 |
4 | index (UINT32_MAX) | uint32_t | 0xffffffff, coinbase 没有先前的outpoint。 |
Varies(4) | script bytes | compactSize uint | coinbase脚本中的字节数,最大为100个字节。 |
Varies | height | script | 块高度。使用脚本语言:从数据压栈操作码开始,该操作码指示将多少字节推送到堆栈,然后将块高度作为小端无符号整数。 该脚本必须尽可能短,否则可能会被拒绝。数据推送操作码将是0x03,大小为四个字节到距离现在约300年的16,777,216块。 |
Varies | coinbase script | None | Coinbase字段:任意数据,不超过100字节减去(4)高度字节。 矿工们通常在这个字段中放置一个额外的随机数,以便在散列期间更新块头merkle根。 |
4 | sequence | uint32_t | 序列号 |
在块高度227,836之前的大多数(但不是全部)块使用1.0版本,其不需要将高度参数作为币基脚本的前缀。 块高度参数现在是必需的。
一个coinbase的交易展示:
01000000 .............................. Version
01 .................................... Number of inputs
| 00000000000000000000000000000000
| 00000000000000000000000000000000 ... Previous outpoint TXID
| ffffffff ............................ Previous outpoint index
|
| 29 .................................. Bytes in coinbase
| |
| | 03 ................................ Bytes in height
| | | 4e0105 .......................... Height: 328014
| |
| | 062f503253482f0472d35454085fffed
| | f2400000f90f54696d65202620486561
| | 6c74682021 ........................ Arbitrary data
| 00000000 ............................ Sequence
01 .................................... Output count
| 2c37449500000000 .................... Satoshis (25.04275756 BTC)
| 1976a914a09be8040cbf399926aeb1f4
| 70c37d1341f3b46588ac ................ P2PKH script
| 00000000 ............................ Locktime
交易格式和部分点对点网络消息使用一种变长的整数来指示数据中的字节数。比特币核心代码和本文档将这些可变整数称为compactSize。
对于从0到252的数字,compactSize无符号整数看起来像普通的无符号整数。 对高于0xffffffffffffffff的其他数字,一个字节以数字为前缀以指示其长度,其余部分数字看起来像小端顺序的常规无符号整数。
值 | 字节使用 | 格式 |
---|---|---|
>= 0 && <= 252 | 1 | uint8_t |
>= 253 && <= 0xffff | 3 | 0xfd followed by the number as uint16_t |
>= 0x10000 && <= 0xffffffff | 5 | 0xfe followed by the number as uint32_t |
>= 0x100000000 && <= 0xffffffffffffffff | 9 | 0xff followed by the number as uint64_t |
例如,515的十六进制为0302,而253的十六进制为fd,所以515表示为0xfd0302。
从一个种子创建一个秘钥。它的一个弱点是一旦种子被泄露,钱包将不安全。
有关HD钱包的概述,请参阅开发人员指南部分。 详情请参阅BIP32。
这节将会介绍P2P网络协议。
所有的点对点通信都是通过TCP完成的。
注意:除非另有说明,否则本节中提到的所有多字节整数均按小端顺序传输。
下面的常量和默认值来自 比特币核心的chainparams.cpp 源代码文件中。
Network | Default Port | Start String | Max nBits |
---|---|---|---|
Mainnet | 8333 | 0xf9beb4d9 | 0x1d00ffff |
Testnet | 18333 | 0x0b110907 | 0x1d00ffff |
Regtest | 18444 | 0xfabfb5da | 0x207fffff |
起始字符串是在比特币网络上发送所有消息开始时出现的硬编码常量; 他们也可能出现在比特币核心的块数据库等数据文件中。 上面显示的nBits是大端顺序的; 他们通过网络以小端的顺序发送。
比特币核心的chainparams.cpp还包括对程序有用的其他常量,例如不同网络的生成块的哈希。
截至比特币核心0.14.2,最新的协议版本是70015。
Version | InitialRelease | Major Changes |
---|---|---|
70015 | Bitcoin Core 0.13.2 (Jan 2017) | • New banning behavior for invalid compact blocks #9026 in v0.14.0, Backported to v0.13.2 in #9048. |
70014 | Bitcoin Core 0.13.0 (Aug 2016) | BIP152: • Added sendcmpct, cmpctblock, getblocktxn, blocktxn messages • Added MSG_CMPCT_BLOCK inventory type to getdata message. |
70013 | Bitcoin Core 0.13.0 (Aug 2016) | BIP133: • Added feefilter message.• Removed alert message system. See Alert System Retirement |
70012 | Bitcoin Core 0.12.0 (Feb 2016) | BIP130: • Added sendheaders message. |
70011 | Bitcoin Core 0.12.0 (Feb 2016) | BIP111: • filter* messages are disabled without NODE_BLOOM after and including this version. |
网络协议中的所有消息使用相同的容器格式。 消息头格式是:
Bytes | Name | Data Type | Description |
---|---|---|---|
4 | start string | char[4] | 魔数 |
12 | command name | char[12] | 标识信息类型,不足的地方以nulls填充(0x00)。 例如: version\0\0\0\0\0 。 |
4 | payload size | uint32_t | payload的字节大小,当前允许的最大字节数 (MAX_SIZE ) 为32MiB。 |
4 | checksum | char[4] | 在协议版本209时被添加。SHA256的前4个字节(SHA256(payload))以内部字节顺序排列。如果payload为空,如verack 和getaddr 消息,则校验和总是为0x5df6e0e2(SHA256(SHA256(<空字符串>)))。 |
以下示例是来自没有payload的主网verack
消息头的十六进制。
f9beb4d9 ................... Start string: Mainnet
76657261636b000000000000 ... Command name: verack + null padding
00000000 ................... Byte count: 0
5df6e0e2 ................... Checksum: SHA256(SHA256(<empty>))
以下网络消息全部是请求或提供与交易和块有关的数据。
绝大多数数据信息使用inventories作为唯一个标识符。blocks. Inventories有一个简单的36-byte结构:
Bytes | Name | Data Type | Description |
---|---|---|---|
4 | type identifier | uint32_t | 对象的哈希值。下面有 identifiers 的类型。 |
32 | hash | char[32] | SHA256(SHA256()) |
类型标识符 (identifiers):
Type Identifier | Name | Description |
---|---|---|
1 | MSG_TX |
TXID |
2 | MSG_BLOCK |
区块头哈希 |
3 | MSG_FILTERED_BLOCK |
仅用于getdata 消息。 |
block
消息以单行序列化发送出去(在serialized blocks一节中讲到)。它可以被发送有2个不同的原因:
getdata
消息,消息为 inventory t的MSG_BLOCK
的块(假定该节点具有该块可用于传送)。getblocks
消息需要一个inv
消息提供所需要的区块散列值。
Bytes | Name | Data Type | Description |
---|---|---|---|
4 | version | uint32_t | 协议版本 |
Varies | hash count | compactSize uint | 提供的头部哈希数量(不包括停止哈希)。 |
Varies | block header hashes | char[32] | 一个或多个块头散列(每个32字节)以内部字节顺序排 |
32 | stop hash | char[32] | 请求最后一个的头部散列; 设置为零以请求包含所有后续头部哈希的inv消息(最多500个;如果您需要超过500个,则需要发送另一个具有更高高度头部的getblocks消息 散列作为块头散列字段中的第一个条目)。 |
例子:
71110100 ........................... Protocol version: 70001
02 ................................. Hash count: 2
d39f608a7775b537729884d4e6633bb2
105e55a16a14d31b0000000000000000 ... Hash #1
5c3e6403d40837110a2e8afb602b1c01
714bda7ce23bea0a0000000000000000 ... Hash #2
00000000000000000000000000000000
00000000000000000000000000000000 ... Stop hash
getdata
消息请求来自另一个节点的一个或多个数据对象。 这些对象是由一个inventory所请求的,请求节点通常通过一个inv消息来接收这个清单。
回复getdata
信息的可以是tx
信息、block
信息、merkleblock
信息或者notfound
信息。
在协议版本31800中添加。
getheaders
消息请求头消息,该消息提供从块链中的特定点开始的块头。 它允许其他人获得它还没有看到的区块头。
getheaders
消息几乎与getblocks
消息相同,只有一点区别:对getblocks
消息的inv
回复将包含不超过500个块头散列; getheaders
消息将包括多达2,000个块头。
头信息可以为空。
Bytes | Name | Data Type | Description |
---|---|---|---|
Varies | count | compactSize uint | 区块头的个数,最多2000。 |
Varies | headers | block_header | 每80-byte的区块头都加上0x00后缀,0x00叫做交易计数,由于区块头不包含交易,所以这里总是0。 |
headers
信息 。(信息头被省略)
01 ................................. Header count: 1
02000000 ........................... Block version: 2
b6ff0b1b1680a2862a30ca44d346d9e8
910d334beb48ca0c0000000000000000 ... Hash of previous blocks header
9d10aa52ee949386ca9385695f04ede2
70dda20810decd12bc9b048aaab31471 ... Merkle root
24d95a54 ........................... Unix time: 1415239972
30c31b18 ........................... Target (bits)
fe9f0864 ........................... Nonce
00 ................................. Transaction count (0x00)
Bytes | Name | Data Type | Description |
---|---|---|---|
Varies | count | compactSize uint | inventory 数目。. |
Varies | inventory | inventory | 最多50,000个。 |
inv
信息包含2个inventory实体 。 (消息头被省略)
02 ................................. Count: 2
01000000 ........................... Type: MSG_TX
de55ffd709ac1f5dc509a0925d0b1fc4
42ca034f224732e429081da1b621f55a ... Hash (TXID)
01000000 ........................... Type: MSG_TX
91d36d997037e08018262978766f24b8
a055aaf1d872e94ae85e9817b2c68dc7 ... Hash (TXID)
只要思想不滑坡,办法总比困难多。