Protocol
在 Python 中建立對等連接
我正在嘗試使用 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("<L",version).encode("hex") payload_hex += struct.pack("<Q",services).encode("hex") payload_hex += struct.pack("<Q",timestamp).encode("hex") payload_hex += struct.pack("<Q",services_u).encode("hex") payload_hex += struct.pack(">16s",adr_u).encode("hex") payload_hex += struct.pack(">H",port_u).encode("hex") payload_hex += struct.pack("<Q",services_me).encode("hex") payload_hex += struct.pack(">16s",adr_me).encode("hex") payload_hex += struct.pack(">H",port_me).encode("hex") payload_hex += struct.pack("<Q",nonce).encode("hex") payload_hex += struct.pack("<B",user_agent_bytes).encode("hex") payload_hex += struct.pack("<L",start_height).encode("hex") payload_hex += struct.pack("<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(">16s",addr_you) payload += struct.pack(">H",port_you) payload += struct.pack("Q",services_me) payload += struct.pack(">16s",addr_me) payload += struct.pack(">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")