Skip to content

Instantly share code, notes, and snippets.

@xgess
Last active February 25, 2018 14:19
Show Gist options
  • Save xgess/1424fef719247651a6d5ba8f03b9e085 to your computer and use it in GitHub Desktop.
Save xgess/1424fef719247651a6d5ba8f03b9e085 to your computer and use it in GitHub Desktop.
the simplest bitcoin node
from binascii import hexlify, unhexlify
from hashlib import sha256
from io import BytesIO
import random
import socket
import struct
import time
user_agent_to_send = 'agentalex'
version = struct.pack("i", 70015) # corresponds to 0.15
services = struct.pack("Q", 0) # this "node" does nothing
timestamp = struct.pack("Q", (int(time.time())))
addr_recv_services = struct.pack("q", 0)
addr_recv_ip = struct.pack(">16s", b'127.0.0.1')
addr_recv_port = struct.pack(">H", 8333)
addr_trans_services = struct.pack("Q", 0)
addr_trans_ip = struct.pack(">16s", b'127.0.0.1')
addr_trans_port = struct.pack(">H", 8333)
nonce = struct.pack("Q", random.getrandbits(64))
user_agent_bytes = struct.pack("<B", len(user_agent_to_send))
user_agent = user_agent_to_send.encode()
starting_height = struct.pack("i", 0)
relay = struct.pack("?", False)
payload = version + services + timestamp + addr_recv_services + \
addr_recv_ip + addr_recv_port + addr_trans_services + \
addr_trans_ip + addr_trans_port + nonce + user_agent_bytes + \
user_agent + starting_height + relay
network = unhexlify("F9BEB4D9") #mainnet
command = str.encode('version'.ljust(12, '\00'))
payload_size = struct.pack("I", len(payload))
checksum = sha256(sha256(payload).digest()).digest()[:4]
full_version_message = network + command + payload_size + checksum + payload
def read_a_message(sock):
header = BytesIO(sock.recv(24))
version = hexlify(header.read(4))
command = header.read(12).decode().replace('\x00', '').upper()
payload_size = struct.unpack("I", header.read(4))[0]
checksum = hexlify(header.read(4))
payload = sock.recv(payload_size)
return {'message_type': command, 'payload': payload}
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
some_existing_bitcoin_nodes = ["108.184.197.47", "87.140.70.14", "5.9.66.210"]
sock.connect((random.choice(some_existing_bitcoin_nodes), 8333))
sock.sendall(full_version_message)
first_received_message = read_a_message(sock)
print(f"omg you got a response from that node: {first_received_message}")
finally:
sock.close()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment