比特币开发参考

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/weixin_41479993/article/details/79206397

比特币

区块链

区块头

字节 名称 数据类型 描述
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树

Merkle Root是根据这个块中所有交易的TXID生成的:

  • CoinBase的交易排在第一位
  • 该块内的任何输入也可以在输出中出现(假设花费有效)。但是,输出对应的TXID必须放在输入对应的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树的根。

Merkle树构造例子

目标难度nBits

目标阈值是一个无符号的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比特币。)

交易

以下小节将简要介绍核心交易的细节。

操作码

在标准交易中的公有脚本操作码:

  1. 各种数据操作码,从0x00到0x4e(1-78)。
  2. OP_TRUE/OP_1(0x51)和OP_2OP_16(0x52-0x60),表示把1-16压入栈中。
  3. OP_CHECKSIG消费一个签名和一个公钥,如果由SIGHASH标志指定的交易数据被转换为使用生成该公钥的相同ECDSA私钥的签名就压入TRUE, 否则,它会将FALSE压入堆栈。
  4. OP_DUP把栈顶元素复制并压入栈中。
  5. OP_HASH160消费栈顶元素,计算RIPEMD160(SHA256()),并把计算后的值压入栈中。
  6. OP_EQUAL消费栈顶的2个元素,比较,相同压入真,否则压入假。
  7. OP_VERIFY消费栈顶元素,如果是0则终止脚本。
  8. OP_EQUALVERIFY 按顺序运行 OP_EQUALOP_VERIFY
    更多的操作码请看Wiki和其实现script.

地址转换

比特币地址通常用P2PKH和P2SH来进行哈希操作。
首先,获取你的哈希值。对于P2PKH,使用RIPEMD-160(SHA256()) 哈希从你256-bit的ECDSA私钥(随机数)所对应的公钥。对于P2SH,使用RIPEMD-160(SHA256()) 对序列化原始交易通过转化脚本来获得哈希(后续会讲到)。获得哈希结果:
1. 在哈希值前添加一个字节版本

  • 比特币主网络(mainnet)上的P2PKH地址为0x00
  • 比特币测试网络(testnet)上的P2PKH地址0x6f
  • 主网络上的P2SH地址为0x05
  • 测试网络上的P2SH地址的0xc4

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部分中进行了描述。

TxIn: 一个交易输出(非-Coinbase)

每一个非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:特定输出的具体部分

由于一个单一的交易可以包含多个输出,outpoint结构包含一个TXID和一个输出索引号指向一个具体的输出。

字节 名称 数据类型 描述
32 hash char[32] 交易的TXID输出的花费,TXID是以内部字节顺序提供的哈希。
4 index uint32_t 交易中具体花费的具体输出索引号。第一个输出是0x00000000

TxOut: 交易输出

每个输出花费一定数量的聪,任何可以提供满足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。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无符号整数

交易格式和部分点对点网络消息使用一种变长的整数来指示数据中的字节数。比特币核心代码和本文档将这些可变整数称为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。

钱包

确定性钱包格式

类型1:单链钱包

从一个种子创建一个秘钥。它的一个弱点是一旦种子被泄露,钱包将不安全。

类型2:分层确定性(HD)钱包

HD钱包
有关HD钱包的概述,请参阅开发人员指南部分。 详情请参阅BIP32。

P2P网络

这节将会介绍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为空,如verackgetaddr消息,则校验和总是为0x5df6e0e2(SHA256(SHA256(<空字符串>)))。

以下示例是来自没有payload的主网verack消息头的十六进制。

f9beb4d9 ................... Start string: Mainnet
76657261636b000000000000 ... Command name: verack + null padding
00000000 ................... Byte count: 0
5df6e0e2 ................... Checksum: SHA256(SHA256(<empty>))

数据信息

以下网络消息全部是请求或提供与交易和块有关的数据。
P2P
绝大多数数据信息使用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个不同的原因:

  1. 获取数据响应:节点将发送它以响应一个getdata消息,消息为 inventory t的MSG_BLOCK的块(假定该节点具有该块可用于传送)。
  2. Unsolicited(被动获取):一些矿工将发送的挖到新块的信息。

获得区块

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)

Inv

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)

内存池

Merkle块

未找到

Tx

控制信息

地址

警报

费用过滤器

地址过滤器

FilterClear

FilterLoad

获得地址

Ping

Pong

拒绝

发送头

VerAck

版本

比特币核心API

哈希字节顺序

远程过程调用(RPCs)

速览

RPCs

AbandonTransaction
AddMultiSigAddress

HTTP REST

速览

Requests

GET Block

只要思想不滑坡,办法总比困难多。

没有更多推荐了,返回首页