Skip to content

Commit

Permalink
qa: bitcoind: add a helper for sending a P2P message to bitcoind
Browse files Browse the repository at this point in the history
  • Loading branch information
darosior committed Aug 9, 2023
1 parent df396cc commit c571972
Showing 1 changed file with 48 additions and 1 deletion.
49 changes: 48 additions & 1 deletion tests/test_framework/bitcoind.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import hashlib
import logging
import os
import socket
import time

from decimal import Decimal
from ephemeral_port_reserve import reserve
Expand Down Expand Up @@ -53,11 +56,13 @@ def __init__(self, bitcoin_dir, rpcport=None):
"-datadir={}".format(bitcoin_dir),
"-printtoconsole",
"-server",
"-debug=1",
"-debugexclude=libevent",
"-debugexclude=tor",
]
bitcoind_conf = {
"port": self.p2pport,
"rpcport": rpcport,
"debug": 1,
"fallbackfee": Decimal(1000) / COIN,
"rpcthreads": 32,
}
Expand Down Expand Up @@ -179,6 +184,48 @@ def simple_reorg(self, height, shift=0):
self.generate_block(1 + final_len - (height + shift), memp)
self.wait_for_log(r"UpdateTip: new best=.* height={}".format(final_len))

def send_p2p_message(self, s, command, payload):
magic_bytes = b"\xfa\xbf\xb5\xda"
checksum = hashlib.sha256(hashlib.sha256(payload).digest()).digest()[:4]
payload_len = len(payload).to_bytes(4, "little")
message = magic_bytes + command.encode("ascii") + bytes(12 - len(command)) + payload_len + checksum + payload
s.send(message)
logging.debug(f"Sent message to bitcoind: {command}")

def connect_p2p(self, cur_height):
version = int(70016).to_bytes(4, 'little')
services = int((1 << 0) | (1 << 3)).to_bytes(8, 'little')
timestamp = int(time.time()).to_bytes(8, 'little')
addr_recv = services + bytes(16) + self.p2pport.to_bytes(2, "little")
addr_from = addr_recv
nonce = os.urandom(8)
user_agent = b"\x00"
start_height = cur_height.to_bytes(4, "little")
relay = b"\x00"
ver_payload = version + services + timestamp + addr_recv + addr_from + nonce + user_agent + start_height + relay

logging.debug("Connecting to bitcoind p2p port")
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("127.0.0.1", self.p2pport))
self.send_p2p_message(s, "version", ver_payload)
s.recv(102 + 24) # Recv version
s.recv(0 + 24) # Recv wtxidrelay
s.recv(0 + 24) # Recv sendaddrv2
s.recv(0 + 24) # Recv verack
self.send_p2p_message(s, "verack", b"")
s.recv(9 + 24) # Recv sendcmpct
s.recv(8 + 24) # Recv ping
s.recv(613 + 24) # Recv getheaders (ignore it)
s.recv(8 + 24) # Recv feefilter

logging.debug("Handshake to bitcoind complete")
return s

def submit_block(self, cur_height, block_hex):
"""Submit a block through the P2P interface."""
s = self.connect_p2p(cur_height)
self.send_p2p_message(s, "block", bytes.fromhex(block_hex))

def startup(self):
try:
self.start()
Expand Down

0 comments on commit c571972

Please sign in to comment.