Protocol

在 Python 中建立對等連接

  • September 3, 2016

我正在嘗試使用 Python 建立一個簡單的對等連接。

如果我理解正確,通信開始於向接收節點發送“版本”數據包。然後該節點發回一個“verack”數據包,之後您可以開始查詢數據/推送 txs。

事實證明, Ken Shirriff 的部落格讓我走到了這一步,但我無法讓他的程式碼範例正常工作,可能是因為它們已經過時了?

特別是在執行時:

<https://github.com/shirriff/bitcoin-code/blob/master/minimalPeerConnection.py>

套接字立即關閉。我沒有收到“verack”,也無法繼續推送我的 tx。請注意,我已將他的硬編碼 IP 替換為目前執行的節點 (124.248.237.178:8333)。

我試圖建構一個引用這些文件的更“最新”版本數據包(70002) ,但遇到了同樣的問題:

import struct
import socket
import time
import hashlib
import binascii

magic = 0xd9b4bef9

def makeMessage(magic,command,payload):
   checksum = hashlib.sha256(hashlib.sha256(payload).digest()).digest()[0:4]
   return struct.pack('L12sL4s',magic,command,len(payload),checksum).encode("hex")+payload
def makeVersionPayload():
   version = 70002
   services = 1
   timestamp = int(time.time())

   adr_u = "::ffff:127.0.0.1"
   services_u = 1
   port_u = 8333

   adr_me = "::ffff:127.0.0.1"
   services_me = 1
   port_me = 8333

   nonce = 0

   user_agent_bytes = 0
   start_height = 0
   relay = 0

   #https://bitcoin.org/en/developer-reference#version
   payload_hex = "";
   payload_hex += struct.pack("&lt;L",version).encode("hex")
   payload_hex += struct.pack("&lt;Q",services).encode("hex")
   payload_hex += struct.pack("&lt;Q",timestamp).encode("hex")
   payload_hex += struct.pack("&lt;Q",services_u).encode("hex")
   payload_hex += struct.pack("&gt;16s",adr_u).encode("hex")
   payload_hex += struct.pack("&gt;H",port_u).encode("hex")
   payload_hex += struct.pack("&lt;Q",services_me).encode("hex")
   payload_hex += struct.pack("&gt;16s",adr_me).encode("hex")
   payload_hex += struct.pack("&gt;H",port_me).encode("hex")
   payload_hex += struct.pack("&lt;Q",nonce).encode("hex")
   payload_hex += struct.pack("&lt;B",user_agent_bytes).encode("hex")
   payload_hex += struct.pack("&lt;L",start_height).encode("hex")
   payload_hex += struct.pack("&lt;B",relay).encode("hex")
   return payload_hex

ip = socket.gethostbyname("124.248.237.178")
port = 8333
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print "connected to node..."
sock.connect((ip,port))

hex_msg = makeMessage(magic,"version",makeVersionPayload())
print "sending version packet"
sock.send(binascii.unhexlify(hex_msg))

while 1:
   msg = sock.recv(4096)
   if not msg:
       print "disconnected"
       exit()
   else:
       #expecting verack?
       print "response: ",msg

誰能指出我正確的方向?

得到它的工作。

Ken 的部落格假設是 Windows 環境,在 64 位 Linux 中,某些數據類型的字節數是不同的,所以我不得不更改一些“包”格式。

最後,我一直在用十六進製做所有事情,只為套接字發送轉換為二進制。但是,在計算 sha256(兩次)校驗和時,它必須在 BINARY 有效負載上。

工作程式碼(至少對於 64 位 Linux):

import struct
import socket
import time
import hashlib
import binascii

magic = "f9beb4d9"

def makeMessage(magic,command,payload):
   checksum = hashlib.sha256(hashlib.sha256(payload).digest()).digest()[0:4]
   return magic.decode("hex")+struct.pack('12sI4s',command,len(payload),checksum)+payload
def makeVersionPayload():
   version = 70002
   services = 0
   timestamp = int(time.time())

   addr_you = "127.0.0.1"
   services_you = 0
   port_you = 8333

   addr_me = "127.0.0.1"
   services_me = 0
   port_me = 8333

   nonce = 0

   user_agent_bytes = 0
   start_height = 0
   relay = 1

   #https://bitcoin.org/en/developer-reference#version
   payload = "";
   payload += struct.pack("i",version)
   payload += struct.pack("Q",services)
   payload += struct.pack("q",timestamp)
   payload += struct.pack("Q",services_you)
   payload += struct.pack("&gt;16s",addr_you)
   payload += struct.pack("&gt;H",port_you)
   payload += struct.pack("Q",services_me)
   payload += struct.pack("&gt;16s",addr_me)
   payload += struct.pack("&gt;H",port_me)
   payload += struct.pack("Q",nonce)
   payload += struct.pack("B",user_agent_bytes)
   payload += struct.pack("i",start_height)
   payload += struct.pack("B",relay)
   return payload

ip = socket.gethostbyname("124.248.237.178")
port = 8333
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print "connected to node..."
sock.connect((ip,port))

msg = makeMessage(magic,"version",makeVersionPayload())
print "sending version packet"
sock.send(msg)

while 1:
   msg = sock.recv(2**10)
   if not msg:
       print "done"
       exit()
   else:
       print msg.encode("hex")

引用自:https://bitcoin.stackexchange.com/questions/48350