|
|
@ -9,10 +9,8 @@ |
|
|
|
This python code was modified from ArtForz' public domain half-a-node, as |
|
|
|
This python code was modified from ArtForz' public domain half-a-node, as |
|
|
|
found in the mini-node branch of http://github.com/jgarzik/pynode. |
|
|
|
found in the mini-node branch of http://github.com/jgarzik/pynode. |
|
|
|
|
|
|
|
|
|
|
|
NodeConn: an object which manages p2p connectivity to a bitcoin node |
|
|
|
P2PConnection: A low-level connection object to a node's P2P interface |
|
|
|
NodeConnCB: a base class that describes the interface for receiving |
|
|
|
P2PInterface: A high-level interface object for communicating to a node over P2P""" |
|
|
|
callbacks with network messages from a NodeConn |
|
|
|
|
|
|
|
""" |
|
|
|
|
|
|
|
import asyncore |
|
|
|
import asyncore |
|
|
|
from collections import defaultdict |
|
|
|
from collections import defaultdict |
|
|
|
from io import BytesIO |
|
|
|
from io import BytesIO |
|
|
@ -57,7 +55,7 @@ MAGIC_BYTES = { |
|
|
|
"regtest": b"\xfa\xbf\xb5\xda", # regtest |
|
|
|
"regtest": b"\xfa\xbf\xb5\xda", # regtest |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
class NodeConn(asyncore.dispatcher): |
|
|
|
class P2PConnection(asyncore.dispatcher): |
|
|
|
"""A low-level connection object to a node's P2P interface. |
|
|
|
"""A low-level connection object to a node's P2P interface. |
|
|
|
|
|
|
|
|
|
|
|
This class is responsible for: |
|
|
|
This class is responsible for: |
|
|
@ -68,9 +66,7 @@ class NodeConn(asyncore.dispatcher): |
|
|
|
- logging messages as they are sent and received |
|
|
|
- logging messages as they are sent and received |
|
|
|
|
|
|
|
|
|
|
|
This class contains no logic for handing the P2P message payloads. It must be |
|
|
|
This class contains no logic for handing the P2P message payloads. It must be |
|
|
|
sub-classed and the on_message() callback overridden. |
|
|
|
sub-classed and the on_message() callback overridden.""" |
|
|
|
|
|
|
|
|
|
|
|
TODO: rename this class P2PConnection.""" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def __init__(self): |
|
|
|
def __init__(self): |
|
|
|
super().__init__(map=mininode_socket_map) |
|
|
|
super().__init__(map=mininode_socket_map) |
|
|
@ -244,7 +240,7 @@ class NodeConn(asyncore.dispatcher): |
|
|
|
logger.debug(log_message) |
|
|
|
logger.debug(log_message) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class NodeConnCB(NodeConn): |
|
|
|
class P2PInterface(P2PConnection): |
|
|
|
"""A high-level P2P interface class for communicating with a Bitcoin node. |
|
|
|
"""A high-level P2P interface class for communicating with a Bitcoin node. |
|
|
|
|
|
|
|
|
|
|
|
This class provides high-level callbacks for processing P2P message |
|
|
|
This class provides high-level callbacks for processing P2P message |
|
|
@ -252,9 +248,7 @@ class NodeConnCB(NodeConn): |
|
|
|
node over P2P. |
|
|
|
node over P2P. |
|
|
|
|
|
|
|
|
|
|
|
Individual testcases should subclass this and override the on_* methods |
|
|
|
Individual testcases should subclass this and override the on_* methods |
|
|
|
if they want to alter message handling behaviour. |
|
|
|
if they want to alter message handling behaviour.""" |
|
|
|
|
|
|
|
|
|
|
|
TODO: rename this class P2PInterface""" |
|
|
|
|
|
|
|
def __init__(self): |
|
|
|
def __init__(self): |
|
|
|
super().__init__() |
|
|
|
super().__init__() |
|
|
|
|
|
|
|
|
|
|
@ -399,10 +393,10 @@ mininode_socket_map = dict() |
|
|
|
|
|
|
|
|
|
|
|
# One lock for synchronizing all data access between the networking thread (see |
|
|
|
# One lock for synchronizing all data access between the networking thread (see |
|
|
|
# NetworkThread below) and the thread running the test logic. For simplicity, |
|
|
|
# NetworkThread below) and the thread running the test logic. For simplicity, |
|
|
|
# NodeConn acquires this lock whenever delivering a message to a NodeConnCB, |
|
|
|
# P2PConnection acquires this lock whenever delivering a message to a P2PInterface, |
|
|
|
# and whenever adding anything to the send buffer (in send_message()). This |
|
|
|
# and whenever adding anything to the send buffer (in send_message()). This |
|
|
|
# lock should be acquired in the thread running the test logic to synchronize |
|
|
|
# lock should be acquired in the thread running the test logic to synchronize |
|
|
|
# access to any data shared with the NodeConnCB or NodeConn. |
|
|
|
# access to any data shared with the P2PInterface or P2PConnection. |
|
|
|
mininode_lock = RLock() |
|
|
|
mininode_lock = RLock() |
|
|
|
|
|
|
|
|
|
|
|
class NetworkThread(Thread): |
|
|
|
class NetworkThread(Thread): |
|
|
|