Changeset View
Changeset View
Standalone View
Standalone View
test/functional/test_framework/mininode.py
Show First 20 Lines • Show All 117 Lines • ▼ Show 20 Lines | class P2PConnection(asyncio.Protocol): | ||||
def peer_connect(self, dstaddr, dstport, net="regtest"): | def peer_connect(self, dstaddr, dstport, net="regtest"): | ||||
assert not self.is_connected | assert not self.is_connected | ||||
self.dstaddr = dstaddr | self.dstaddr = dstaddr | ||||
self.dstport = dstport | self.dstport = dstport | ||||
# The initial message to send after the connection was made: | # The initial message to send after the connection was made: | ||||
self.on_connection_send_msg = None | self.on_connection_send_msg = None | ||||
self.on_connection_send_msg_is_raw = False | self.on_connection_send_msg_is_raw = False | ||||
self.recvbuf = b"" | self.recvbuf = b"" | ||||
self.network = net | self.magic_bytes = MAGIC_BYTES[net] | ||||
logger.debug('Connecting to Bitcoin Node: {}:{}'.format( | logger.debug('Connecting to Bitcoin Node: {}:{}'.format( | ||||
self.dstaddr, self.dstport)) | self.dstaddr, self.dstport)) | ||||
loop = NetworkThread.network_event_loop | loop = NetworkThread.network_event_loop | ||||
conn_gen_unsafe = loop.create_connection( | conn_gen_unsafe = loop.create_connection( | ||||
lambda: self, host=self.dstaddr, port=self.dstport) | lambda: self, host=self.dstaddr, port=self.dstport) | ||||
def conn_gen(): return loop.call_soon_threadsafe( | def conn_gen(): return loop.call_soon_threadsafe( | ||||
▲ Show 20 Lines • Show All 53 Lines • ▼ Show 20 Lines | def _on_data(self): | ||||
This method reads data from the buffer in a loop. It deserializes, | This method reads data from the buffer in a loop. It deserializes, | ||||
parses and verifies the P2P header, then passes the P2P payload to | parses and verifies the P2P header, then passes the P2P payload to | ||||
the on_message callback for processing.""" | the on_message callback for processing.""" | ||||
try: | try: | ||||
with mininode_lock: | with mininode_lock: | ||||
if len(self.recvbuf) < 4: | if len(self.recvbuf) < 4: | ||||
return None | return None | ||||
if self.recvbuf[:4] != MAGIC_BYTES[self.network]: | if self.recvbuf[:4] != self.magic_bytes: | ||||
raise ValueError( | raise ValueError( | ||||
"got garbage {}".format(repr(self.recvbuf))) | "got garbage {}".format(repr(self.recvbuf))) | ||||
if len(self.recvbuf) < 4 + 12 + 4 + 4: | if len(self.recvbuf) < 4 + 12 + 4 + 4: | ||||
return None | return None | ||||
command = self.recvbuf[4:4 + 12].split(b"\x00", 1)[0] | command = self.recvbuf[4:4 + 12].split(b"\x00", 1)[0] | ||||
msglen = struct.unpack( | msglen = struct.unpack( | ||||
"<i", self.recvbuf[4 + 12:4 + 12 + 4])[0] | "<i", self.recvbuf[4 + 12:4 + 12 + 4])[0] | ||||
checksum = self.recvbuf[4 + 12 + 4:4 + 12 + 4 + 4] | checksum = self.recvbuf[4 + 12 + 4:4 + 12 + 4 + 4] | ||||
▲ Show 20 Lines • Show All 50 Lines • ▼ Show 20 Lines | def send_raw_message(self, raw_message_bytes): | ||||
NetworkThread.network_event_loop.call_soon_threadsafe(maybe_write) | NetworkThread.network_event_loop.call_soon_threadsafe(maybe_write) | ||||
# Class utility methods | # Class utility methods | ||||
def build_message(self, message): | def build_message(self, message): | ||||
"""Build a serialized P2P message""" | """Build a serialized P2P message""" | ||||
command = message.command | command = message.command | ||||
data = message.serialize() | data = message.serialize() | ||||
tmsg = MAGIC_BYTES[self.network] | tmsg = self.magic_bytes | ||||
tmsg += command | tmsg += command | ||||
tmsg += b"\x00" * (12 - len(command)) | tmsg += b"\x00" * (12 - len(command)) | ||||
tmsg += struct.pack("<I", len(data)) | tmsg += struct.pack("<I", len(data)) | ||||
th = sha256(data) | th = sha256(data) | ||||
h = sha256(th) | h = sha256(th) | ||||
tmsg += h[:4] | tmsg += h[:4] | ||||
tmsg += data | tmsg += data | ||||
return tmsg | return tmsg | ||||
▲ Show 20 Lines • Show All 392 Lines • Show Last 20 Lines |