什么是比特币协议

荣威财经 | 比特币百科 / 2018-03-12 / 星星 / 150℃

Hashs (散列)

通常情况下,bitcoin在计算散列时会计算2次。大多数情况下,使用SHA-256散列,RIPEMD-160会用于生成较短的散列(例如生成比特币地址的时候)。

对字符串"hello"进行二次-SHA-256散列计算的例子:

hello2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824 (第一轮 sha-256)9595c9df90075148eb06860365df33584b75bff782a510c6cd4883a419833d50 (第二轮 sha-256)

生成比特币地址时(RIPEMD-160)会得到:

hello2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824 (第一轮 使用 sha-256)b6a9c8c230722b7c748331a8b450f05566dc7d0f (第二轮 使用 ripemd-160)Merkle Trees (Merkle树)

Merkle树是散列的二叉树。在bitcoin中,Merkle树使用SHA-256算法,是这样生成的:

sha256(a) sha256(b) sha256(c)sha256(sha256(a)+sha256(b)) sha256(sha256(c)+sha256(c))sha256(sha256(sha256(a)+sha256(b))+sha256(sha256(c)+sha256(c)))

每轮都将上一轮的结果两两相接后计算,若最后剩余单个元素则复制后计算。

Signatures (签名)

Bitcoin使用椭圆曲线数字签名算法(ECDSA)对交易进行签名

ECDSA 使用了 http://www.secg.org/collateral/sec2_final.pdf 中的secp256k1曲线

公钥(in scripts) 以 04 <x> <y>的形式给出,x和y是表示曲线上点的坐标的32字节字符串。签名使用DER 编码 将 r 和 s 写入一个字节流中(因为这是OpenSSL的默认输出).

Transaction Verification (交易认证)

参看: OP_CHECKSIG

一个block的第一笔交易通常是生成比特币的交易,它不包含任何输入交易,而是生成比特币,这些比特币通常被完成这个block的人获得。这样的交易被称作“coinbase交易”。由于每个block只有一个coinbase交易,它无需执行脚本即被bitcoin客户端接受。

如果一笔交易不是coinbase交易,它会引用前一笔交易的散列和其他交易的输出作为这笔交易的输入,执行这笔交易输入部分的脚本。然后引用的交易输出部分的脚本会被执行。如果栈顶的元素为真则交易被认可。

Addresses (地址)

比特币地址(Bitcoin Address)是ECDSA公钥(public key)的散列,它是这样计算出来的:

Version = 1 个字节 0 ; 在测试网络上, 这个值是 1 个字节 111Key hash = Version 与 RIPEMD-160(SHA-256(public key)) 相接Checksum = SHA-256(SHA-256(Key hash))的前4个字节Bitcoin Address = Base58Encode(Key hash 与 Checksum 相接)

Base58编码是专门编写的,(与通用版本)有一些区别。

共用结构编辑本段回目录

绝大多数整数都都使用little endian编码,只有IP地址或端口号使用big endian编码。

Message (消息)字段尺寸描述数据类型说明4magicuint32_t用于识别消息的来源网络,当流状态位置时,它还用于寻找下一条消息12commandchar[12]识别包内容的ASCII字串,用NULL字符补满,(使用非NULL字符填充会被拒绝)4lengthuint32_tpayload的字节数4checksumuint32_tsha256(sha256(payload)) 的前4个字节(不包含在version 或 verack 中) ?payloaduchar[]实际数据

version和verack消息不包含checksum,payload的起始位置提前4个字节

已定义的magic值:

网络Magic 值mainF9BEB4D9testnetFABFB5DAVariable length integer (变长整数)

整数可以根据表达的值进行编码以节省空间。变长整数总是在可变长度数据类型的数组/向量之前出现。

值存储长度格式< 0xfd1uint8_t<= 0xffff30xfd + uint16_t<= 0xffffffff50xfe + uint32_t-90xff + uint64_tVariable length string (变长字符串)

一个变长整数后接字符串构成变长字符串。

字段尺寸描述数据类型说明 ?lengthvar_int字符串长度 ?stringchar[]字符串本身(可为空)Network address (网络地址)

需要网络地址时会用到这个结构。这个协议支持IPv6,但需要注意目前官方客户端仅支持IPv4网络

字段尺寸描述数据类型说明8servicesuint64_t与version 消息中的service(s)相同16IPv6/4char[16]Ipv6地址,以网络字节顺序存储。官方客户端仅支持IPv4,仅读取最后4个字节以获取IPv4地址。IPv4地址以16字节的IPv4映射位址格式写入结构。(12字节 00 00 00 00 00 00 00 00 00 00 FF FF, 后跟4 字节IPv4地址)2portuint16_t端口号,以网络字节顺序存储。

一个网络地址结构示例

0000 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................0010 00 00 FF FF 0A 00 00 01 20 8D ........ .Network address: 01 00 00 00 00 00 00 00 - 1 (NODE_NETWORK? see services listed under version command) 00 00 00 00 00 00 00 00 00 00 FF FF 0A 00 00 01 - IPv6: ::ffff:10.0.0.1 or IPv4: 10.0.0.1 20 8D - 端口 8333Inventory Vectors (清单向量)

Inventory vectors 用于告知其他节点本节点拥有的对象或请求的数据

Inventory vectors 由以下数据格式构成

字段尺寸描述数据类型说明4typeuint32_t对象类型标识32hashchar[32]对象散列值

目前对象类型标识已经定义如下3个值

值名称说明0ERROR数据可忽略1MSG_TX散列是关于交易的2MSG_BLOCK散列是关于数据块的

其他数据类型值被保留以便用于将来的实现

Block Headers (Block头部)

回应getheaders消息时,将Block头部放入一个headers packet并发送。

字段尺寸描述数据类型说明4versionuint32_tBlock版本信息,基于创建该block的软件版本32prev_blockchar[32]该block前一block的散列32merkle_rootchar[32]与该block相关的全部交易之散列(Merkle树)4timestampuint32_t记录block创建时间的时间戳4bitsuint32_t创建block的计算难度4nonceuint32_t用于生成block的临时数据1txn_countuint8_t交易数,这个值总是0
消息类型编辑本段回目录
version

一个节点收到连接请求时,它立即宣告其版本。在通信双方都得到对方版本之前,不会有其他通信

结构:

字段尺寸描述数据类型说明4versionuint32_t节点使用的协议版本标识8servicesuint64_t该连接允许的特性(bitfield)8timestampuint64_t以秒计算的标准UNIX时间戳26addr_menet_addr生成此消息的节点的网络地址version >= 10626addr_younet_addr接收此消息的节点的网络地址8nonceuint64_t节点的随机id,用于侦测这个连接 ?sub_version_numvar_str辅助版本信息version >= 2094start_heightuint32_t发送节点接收到的最新block

如果包发送者的版本>=209,而包版本被接受,则需要发送一个"verack"包。

services目前定义如下:

值名称说明1NODE_NETWORK这个节点不仅接受headers请求,还可以接受完整block请求

一个version消息示例(请注意version消息头没有校验和)

0000 F9 BE B4 D9 76 65 72 73 69 6F 6E 00 00 00 00 00 ....version.....0010 55 00 00 00 9C 7C 00 00 01 00 00 00 00 00 00 00 U....|..........0020 E6 15 10 4D 00 00 00 00 01 00 00 00 00 00 00 00 ...M............0030 00 00 00 00 00 00 00 00 00 00 FF FF 0A 00 00 01 ................0040 DA F6 01 00 00 00 00 00 00 00 00 00 00 00 00 00 ................0050 00 00 00 00 FF FF 0A 00 00 02 20 8D DD 9D 20 2C .......... ... ,0060 3A B4 57 13 00 55 81 01 00  :.W..U...Message header: F9 BE B4 D9 - magic: main 网络 76 65 72 73 69 6F 6E 00 00 00 00 00 - command: "version" 55 00 00 00 - Payload 长度为 85 字节 - version 消息中没有校验和Version message: 9C 7C 00 00 - 31900 (版本 0.3.19) 01 00 00 00 00 00 00 00 - 1 (NODE_NETWORK services) E6 15 10 4D 00 00 00 00 - Mon Dec 20 21:50:14 EST 2010 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF 0A 00 00 01 DA F6 - 发送者地址信息 - 见 Network Address 一节 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF 0A 00 00 02 20 8D - 接收者地址信息 - 见 Network Address 一节 DD 9D 20 2C 3A B4 57 13 - 节点的随机唯一 ID 00 - "" 子版本字串 (字串长度为0) 55 81 01 00 - 发送节点拥有的最新block是 #98645verack

版本不低于209的客户端在应答version消息时发送verack消息。这个消息仅包含一个command为"verack"的消息头

verack消息示例:

0000 F9 BE B4 D9 76 65 72 61 63 6B 00 00 00 00 00 00 ....verack......0010 00 00 00 00 ....Message header: F9 BE B4 D9 - magic :main 网络 76 65 72 61 63 6B 00 00 00 00 00 00 - command :"verack" 00 00 00 00 - Payload :长度为0addr

提供网络上已知节点的信息。一般来说3小时不进行宣告(advertise)的节点会被网络遗忘

Payload (maximum payload length: 1000 bytes):

字段尺寸描述数据类型说明1+countvar_int地址数30x?addr_list(uint32_t + net_addr)[]网络上其他节点的地址,版本低于209时仅读取第一条

注意:从31402版本开始,地址前都会附加一个时间戳。如果没有这个时间戳,除非它被确认有效,否则这个地址不会发送到其他节点

addr消息示例

0000 F9 BE B4 D9 61 64 64 72 00 00 00 00 00 00 00 00 ....addr........0010 1F 00 00 00 7F 85 39 C2 01 E2 15 10 4D 01 00 00 ......9.....M...0020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF ................0030 FF 0A 00 00 01 20 8D .D(.. .Message Header: F9 BE B4 D9 - magic :main 网络 61 64 64 72 00 00 00 00 00 00 00 00 - "addr" 1F 00 00 00 - payload 长度31字节 7F 85 39 C2 - payload 校验和Payload: 01 - count : 1 消息中有1条地址Address: E2 15 10 4D - Mon Dec 20 21:50:10 EST 2010 (only when version is >= 31402) 01 00 00 00 00 00 00 00 - 1 (NODE_NETWORK service - 见 [[#version]]) 00 00 00 00 00 00 00 00 00 00 FF FF 0A 00 00 01 - IPv4: 10.0.0.1, IPv6: ::ffff:10.0.0.1 (IPv4-mapped IPv6 address) 20 8D - 端口 8333inv

节点通过此消息可以宣告(advertise)它又拥有的对象信息。这个消息可以主动发送,也可以用于应答getbloks消息

Payload (payload 最大长度 50000 字节):

字段尺寸描述数据类型说明 ?countvar_int清单(inventory)数量36x?inventoryinv_vect[]清单(inventory)数据getdata

getdata用于应答inv消息来获取指定对象,它通常在接收到inv包并滤去已知元素后发送

Payload (payload 最大长度为 50000 字节):

字段尺寸描述数据类型说明 ?countvar_int清单(inventory)数量36x?inventoryinv_vect[]清单(inventory)数据getblocks

发送此消息以期返回一个包含编号从hash_start到hash_stop的block列表的inv消息。若hash_start到hash_stop的block数超过500,则在500处截止。欲获取后面的block散列,需要重新发送getblocks消息。

Payload:

字段尺寸描述数据类型说明1+start countvar_inthash_start 的数量32+hash_startchar[32]发送节点已知的最新block散列32hash_stopchar[32]请求的最后一个block的散列,若要获得尽可能多的block则设为0getheaders

获取包含编号hash_star到hash_stop的至多2000个block的header包。要获取之后的block散列,需要重新发送getheaders消息。这个消息用于快速下载不包含相关交易的blockchain。

Payload:

字段尺寸描述数据类型说明1+start countvar_inthash_start 的数量32+hash_startchar[32]发送节点已知的最新block散列32hash_stopchar[32]请求的最后一个block的散列,若要获得尽可能多的block则设为0tx

tx消息描述一笔比特币交易,用于应答getdata消息

字段尺寸描述数据类型说明4versionuint32_t交易数据格式版本1+tx_in countvar_int交易的输入数41+tx_intx_in[]交易输入或比特币来源列表1+tx_out countvar_int交易的输出数8+tx_outtx_out[]交易输出或比特币去向列表4lock_timeuint32_t锁定交易的期限或block数目。如果为0则交易一直被锁定。未锁定的交易不可包含在block中,并可以在过期前修改(目前bitcon不允许更改交易,所以没有用)

tx_in的构成:

字段尺寸描述数据类型说明36previous_outputoutpoint对前一输出的引用1+script lengthvar_intsignature script 的长度 ?signature scriptuchar[]用于确认交易授权的计算脚本4sequenceuint32_t发送者定义的交易版本,用于在交易被写入block之前更改交易

OutPoint结构的构成:

字段尺寸描述数据类型说明32hashchar[32]引用的交易的散列4indexuint32_t指定输出的索引,第一笔输出的索引是0,以此类推

script由一系列与交易相关的信息和操作组成 详情请参考script.h 和 script.cpp

tx_out的构成:

字段尺寸描述数据类型说明8valueuint64_t交易的比特币数量(单位是0.00000001)1+pk_script lengthvar_intpk_script的长度 ?pk_scriptuchar[]Usually contains the public key as a Bitcoin script setting up conditions to claim this output.

tx消息示例:

000000F9 BE B4 D9 74 78 00 00 00 00 00 00 00 00 00 00 ....tx..........00001002 01 00 00 E2 93 CD BE 01 00 00 00 01 6D BD DB .............m..00002008 5B 1D 8A F7 51 84 F0 BC 01 FA D5 8D 12 66 E9 .[...Q........f.000030B6 3B 50 88 19 90 E4 B4 0D 6A EE 36 29 00 00 00 .;P......j.6)...00004000 8B 48 30 45 02 21 00 F3 58 1E 19 72 AE 8A C7 ..H0E.!..X..r...000050C7 36 7A 7A 25 3B C1 13 52 23 AD B9 A4 68 BB 3A .6zz%;..R#...h.:00006059 23 3F 45 BC 57 83 80 02 20 59 AF 01 CA 17 D0 Y#?E.W... Y.....0000700E 41 83 7A 1D 58 E9 7A A3 1B AE 58 4E DE C2 8D .A.z.X.z...XN...00008035 BD 96 92 36 90 91 3B AE 9A 01 41 04 9C 02 BF 5...6..;...A....000090C9 7E F2 36 CE 6D 8F E5 D9 40 13 C7 21 E9 15 98 .~.6.m...@..!...0000A02A CD 2B 12 B6 5D 9B 7D 59 E2 0A 84 20 05 F8 FC *.+..].}Y... ...0000B04E 02 53 2E 87 3D 37 B9 6F 09 D6 D4 51 1A DA 8F N.S..=7.o...Q...0000C014 04 2F 46 61 4A 4C 70 C0 F1 4B EF F5 FF FF FF ../FaJLp..K.....0000D0FF 02 40 4B 4C 00 00 00 00 00 19 76 A9 14 1A A0 ..@KL......v....0000E0CD 1C BE A6 E7 45 8A 7A BA D5 12 A9 D9 EA 1A FB .....E.z........0000F022 5E 88 AC 80 FA E9 C7 00 00 00 00 19 76 A9 14 "^...........v..0001000E AB 5B EA 43 6A 04 84 CF AB 12 48 5E FD A0 B7 ..[.Cj.....H^...0001108B 4E CC 52 88 AC 00 00 00 00 .N.R......Message header: F9 BE B4 D9 - magic: main 网络 74 78 00 00 00 00 00 00 00 00 00 00 - command:"tx" command 02 01 00 00 - payload 长度: 258字节 E2 93 CD BE - payload 校验和Transaction: 01 00 00 00 - versionInputs: 01 - 交易的输入数:1Input 1: 6D BD DB 08 5B 1D 8A F7 51 84 F0 BC 01 FA D5 8D - 前一输出(outpoint) 12 66 E9 B6 3B 50 88 19 90 E4 B4 0D 6A EE 36 29 00 00 00 00 8B - signature script 长度:139字节 48 30 45 02 21 00 F3 58 1E 19 72 AE 8A C7 C7 36 - signature script (scriptSig) 7A 7A 25 3B C1 13 52 23 AD B9 A4 68 BB 3A 59 23 3F 45 BC 57 83 80 02 20 59 AF 01 CA 17 D0 0E 41 83 7A 1D 58 E9 7A A3 1B AE 58 4E DE C2 8D 35 BD 96 92 36 90 91 3B AE 9A 01 41 04 9C 02 BF C9 7E F2 36 CE 6D 8F E5 D9 40 13 C7 21 E9 15 98 2A CD 2B 12 B6 5D 9B 7D 59 E2 0A 84 20 05 F8 FC 4E 02 53 2E 87 3D 37 B9 6F 09 D6 D4 51 1A DA 8F 14 04 2F 46 61 4A 4C 70 C0 F1 4B EF F5 FF FF FF FF - sequenceOutputs: 02 - 交易的输出数:2Output 1: 40 4B 4C 00 00 00 00 00 - 0.05 BTC (5000000) 19 - pk_script 长度:25字节 76 A9 14 1A A0 CD 1C BE A6 E7 45 8A 7A BA D5 12 - pk_script A9 D9 EA 1A FB 22 5E 88 ACOutput 2: 80 FA E9 C7 00 00 00 00 - 33.54 BTC (3354000000) 19 - pk_script 长度:25字节 76 A9 14 0E AB 5B EA 43 6A 04 84 CF AB 12 48 5E - pk_script FD A0 B7 8B 4E CC 52 88 ACLocktime: 00 00 00 00 - lock timeblock

block消息用于响应请求交易信息的getdata消息

字段尺寸描述数据类型说明4versionuint32_tblock版本信息,基于生成block的软件版本32prev_blockchar[32]这一block引用的前一block之散列32merkle_rootchar[32]与这一block相关的全部交易之散列(Merkle树)4timestampuint32_t记录block创建时间的时间戳4bitsuint32_t这一block的计算难度4nonceuint32_t用于生成这一block的nonce值 ?txn_countvar_int交易数量 ?txnstx[]交易,以tx格式存储

用于识别每个block的SHA256散列使用这个结构的前6个字段计算(version, prev_block, merkle_root, timestamp, bits, nonce, 后接标准 SHA256 填充, 共2个64字节块)而非整个block。计算散列是SHA256算法只需要处理2个块。由于nonce字段在第二个块里,在开采过程中,第一个块保持不变。因此只需要处理第二个块。但是bitcoin散列是二次散列,每个开采循环需要2轮SHA256计算。

headers

headers消息返回block的头部以应答getheaders

Payload:

字段尺寸描述数据类型说明 ?countvar_intblock头数量77x?headersblock_header[]block头getaddr

getaddr消息向一个节点发送获取已知活动端的请求,以识别网络中的节点。回应这个消息的方法是发送包含已知活动端信息的addr消息。一般的,一个3小时内发送过消息的节点被认为是活动的。

这个消息没有附加数据

checkorder

此消息用于IP Transactions,以询问对方是否接受交易并允许查看order内容。

它包含一个CWalletTx对象

Payload:

字段尺寸描述数据类型说明Fields from CMerkleTx ?hashBlock ?vMerkleBranch ?nIndexFields from CWalletTx ?vtxPrev ?mapValue ?vOrderForm ?fTimeReceivedIsTxTime ?nTimeReceived ?fFromMe ?fSpentsubmitorder

确认一个order已经被提交

Payload:

字段尺寸描述数据类型说明32hashchar[32]交易散列 ?wallet_entryCWalletTx与checkorder的payload相同reply

IP Transactions的一般应答

Payload:

字段尺寸描述数据类型说明4replyuint32_t应答代码

可能值:

值名称说明0SUCCESSIP Transaction可以执行(回应checkorder)或已经被接受(回应submitorder)1WALLET_ERRORAcceptWalletTransaction()失败2DENIED此节点不接受IP Transactionsping

ping消息主要用于确认TCP/IP连接的可用性。

alert

alert消息用于在节点间发送通知使其传遍整个网络。如果签名验证这个alert来自Bitcoin的核心开发组,建议将这条消息显示给终端用户。交易尝试,尤其是客户端间的自动交易则建议停止。消息文字应当记入记录文件并传到每个用户。

Payload:

字段尺寸描述数据类型说明 ?messagevar_str向网络中所有节点发出的系统消息 ?signaturevar_str可由公钥验证Satoshi授权或创建了此信息的签名

签名将用下面的ECDSA公钥做比对:

04fc9702847840aaf195de8442ebecedf5b095cdbb9bc716bda9110971b28a49e0ead8564ff0db22209e0374782c093bb899692d524e9d6a6956e7c5ecbcd68284(hash) 1AGRxqDa5WjUKBwHB9XYEjmkv1ucoUUy1s
→ 肉丁网微信公众号:【肉丁网】 ←
上一篇:
下一篇:
创意有趣的人民币花样折纸 戴帽子
真皮迷你手工DIY小零钱包硬币包
王颢科学小实验大全之让硬币浮现在
王颢科学小实验 硬币对对碰—适合
王颢:硬币水上漂科学小实验的做法
王颢科学小实验:找准重心硬币也能
史上最难被杀死的8个人 希特勒曾
手工DIY纸币折纸鲁班锁的做法实
手工DIY最新版520爱心纸币折
揭秘老版人民币上出现过的人物原型
穿梭钱币魔术秘籍:硬币逃脱术近景
硬币奇迹魔术秘籍:独一无二的硬币
教你用彩色铅笔手绘百元人民币详细
故事轮盘、拉比盒子的做法 3-7
妈妈,我把咱家的钥匙和硬币熔到一

作者

名字:花香调

来自:陕西 汉中

微信:1795648562

QQ:1795648562

邮箱:1795648562@qq.com

大家好,我是花香调,希望肉丝们喜欢我的作品,欢迎加我QQ一起交流。


花香调的其它作品

假“Telegram(电报)”ICO网
万向肖风再话区块链:区块链与加密经济学
重磅监管箭在弦上,合规或成区块链行业唯
ICO已达300万美元的WAVES宣布
数字货币(区块链)创新与资本之间,依然
区块链初创公司Colu整合彩色币和闪电

最热

什么是比特币协议