|
|
@ -20,10 +20,10 @@ |
|
|
|
import struct |
|
|
|
import struct |
|
|
|
import socket |
|
|
|
import socket |
|
|
|
import asyncore |
|
|
|
import asyncore |
|
|
|
import binascii |
|
|
|
|
|
|
|
import time |
|
|
|
import time |
|
|
|
import sys |
|
|
|
import sys |
|
|
|
import random |
|
|
|
import random |
|
|
|
|
|
|
|
from binascii import hexlify, unhexlify |
|
|
|
from io import BytesIO |
|
|
|
from io import BytesIO |
|
|
|
from codecs import encode |
|
|
|
from codecs import encode |
|
|
|
import hashlib |
|
|
|
import hashlib |
|
|
@ -34,7 +34,7 @@ import copy |
|
|
|
|
|
|
|
|
|
|
|
BIP0031_VERSION = 60000 |
|
|
|
BIP0031_VERSION = 60000 |
|
|
|
MY_VERSION = 60001 # past bip-31 for ping/pong |
|
|
|
MY_VERSION = 60001 # past bip-31 for ping/pong |
|
|
|
MY_SUBVERSION = "/python-mininode-tester:0.0.1/" |
|
|
|
MY_SUBVERSION = b"/python-mininode-tester:0.0.2/" |
|
|
|
|
|
|
|
|
|
|
|
MAX_INV_SZ = 50000 |
|
|
|
MAX_INV_SZ = 50000 |
|
|
|
MAX_BLOCK_SIZE = 1000000 |
|
|
|
MAX_BLOCK_SIZE = 1000000 |
|
|
@ -131,7 +131,7 @@ def deser_vector(f, c): |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def ser_vector(l): |
|
|
|
def ser_vector(l): |
|
|
|
r = "" |
|
|
|
r = b"" |
|
|
|
if len(l) < 253: |
|
|
|
if len(l) < 253: |
|
|
|
r = struct.pack("B", len(l)) |
|
|
|
r = struct.pack("B", len(l)) |
|
|
|
elif len(l) < 0x10000: |
|
|
|
elif len(l) < 0x10000: |
|
|
@ -161,7 +161,7 @@ def deser_uint256_vector(f): |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def ser_uint256_vector(l): |
|
|
|
def ser_uint256_vector(l): |
|
|
|
r = "" |
|
|
|
r = b"" |
|
|
|
if len(l) < 253: |
|
|
|
if len(l) < 253: |
|
|
|
r = struct.pack("B", len(l)) |
|
|
|
r = struct.pack("B", len(l)) |
|
|
|
elif len(l) < 0x10000: |
|
|
|
elif len(l) < 0x10000: |
|
|
@ -221,7 +221,7 @@ def deser_int_vector(f): |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def ser_int_vector(l): |
|
|
|
def ser_int_vector(l): |
|
|
|
r = "" |
|
|
|
r = b"" |
|
|
|
if len(l) < 253: |
|
|
|
if len(l) < 253: |
|
|
|
r = struct.pack("B", len(l)) |
|
|
|
r = struct.pack("B", len(l)) |
|
|
|
elif len(l) < 0x10000: |
|
|
|
elif len(l) < 0x10000: |
|
|
@ -236,19 +236,19 @@ def ser_int_vector(l): |
|
|
|
|
|
|
|
|
|
|
|
# Deserialize from a hex string representation (eg from RPC) |
|
|
|
# Deserialize from a hex string representation (eg from RPC) |
|
|
|
def FromHex(obj, hex_string): |
|
|
|
def FromHex(obj, hex_string): |
|
|
|
obj.deserialize(BytesIO(binascii.unhexlify(hex_string))) |
|
|
|
obj.deserialize(BytesIO(unhexlify(hex_string.encode('ascii')))) |
|
|
|
return obj |
|
|
|
return obj |
|
|
|
|
|
|
|
|
|
|
|
# Convert a binary-serializable object to hex (eg for submission via RPC) |
|
|
|
# Convert a binary-serializable object to hex (eg for submission via RPC) |
|
|
|
def ToHex(obj): |
|
|
|
def ToHex(obj): |
|
|
|
return binascii.hexlify(obj.serialize()).decode('utf-8') |
|
|
|
return hexlify(obj.serialize()).decode('ascii') |
|
|
|
|
|
|
|
|
|
|
|
# Objects that map to bitcoind objects, which can be serialized/deserialized |
|
|
|
# Objects that map to bitcoind objects, which can be serialized/deserialized |
|
|
|
|
|
|
|
|
|
|
|
class CAddress(object): |
|
|
|
class CAddress(object): |
|
|
|
def __init__(self): |
|
|
|
def __init__(self): |
|
|
|
self.nServices = 1 |
|
|
|
self.nServices = 1 |
|
|
|
self.pchReserved = "\x00" * 10 + "\xff" * 2 |
|
|
|
self.pchReserved = b"\x00" * 10 + b"\xff" * 2 |
|
|
|
self.ip = "0.0.0.0" |
|
|
|
self.ip = "0.0.0.0" |
|
|
|
self.port = 0 |
|
|
|
self.port = 0 |
|
|
|
|
|
|
|
|
|
|
@ -259,7 +259,7 @@ class CAddress(object): |
|
|
|
self.port = struct.unpack(">H", f.read(2))[0] |
|
|
|
self.port = struct.unpack(">H", f.read(2))[0] |
|
|
|
|
|
|
|
|
|
|
|
def serialize(self): |
|
|
|
def serialize(self): |
|
|
|
r = "" |
|
|
|
r = b"" |
|
|
|
r += struct.pack("<Q", self.nServices) |
|
|
|
r += struct.pack("<Q", self.nServices) |
|
|
|
r += self.pchReserved |
|
|
|
r += self.pchReserved |
|
|
|
r += socket.inet_aton(self.ip) |
|
|
|
r += socket.inet_aton(self.ip) |
|
|
@ -286,7 +286,7 @@ class CInv(object): |
|
|
|
self.hash = deser_uint256(f) |
|
|
|
self.hash = deser_uint256(f) |
|
|
|
|
|
|
|
|
|
|
|
def serialize(self): |
|
|
|
def serialize(self): |
|
|
|
r = "" |
|
|
|
r = b"" |
|
|
|
r += struct.pack("<i", self.type) |
|
|
|
r += struct.pack("<i", self.type) |
|
|
|
r += ser_uint256(self.hash) |
|
|
|
r += ser_uint256(self.hash) |
|
|
|
return r |
|
|
|
return r |
|
|
@ -306,7 +306,7 @@ class CBlockLocator(object): |
|
|
|
self.vHave = deser_uint256_vector(f) |
|
|
|
self.vHave = deser_uint256_vector(f) |
|
|
|
|
|
|
|
|
|
|
|
def serialize(self): |
|
|
|
def serialize(self): |
|
|
|
r = "" |
|
|
|
r = b"" |
|
|
|
r += struct.pack("<i", self.nVersion) |
|
|
|
r += struct.pack("<i", self.nVersion) |
|
|
|
r += ser_uint256_vector(self.vHave) |
|
|
|
r += ser_uint256_vector(self.vHave) |
|
|
|
return r |
|
|
|
return r |
|
|
@ -326,7 +326,7 @@ class COutPoint(object): |
|
|
|
self.n = struct.unpack("<I", f.read(4))[0] |
|
|
|
self.n = struct.unpack("<I", f.read(4))[0] |
|
|
|
|
|
|
|
|
|
|
|
def serialize(self): |
|
|
|
def serialize(self): |
|
|
|
r = "" |
|
|
|
r = b"" |
|
|
|
r += ser_uint256(self.hash) |
|
|
|
r += ser_uint256(self.hash) |
|
|
|
r += struct.pack("<I", self.n) |
|
|
|
r += struct.pack("<I", self.n) |
|
|
|
return r |
|
|
|
return r |
|
|
@ -336,7 +336,7 @@ class COutPoint(object): |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class CTxIn(object): |
|
|
|
class CTxIn(object): |
|
|
|
def __init__(self, outpoint=None, scriptSig="", nSequence=0): |
|
|
|
def __init__(self, outpoint=None, scriptSig=b"", nSequence=0): |
|
|
|
if outpoint is None: |
|
|
|
if outpoint is None: |
|
|
|
self.prevout = COutPoint() |
|
|
|
self.prevout = COutPoint() |
|
|
|
else: |
|
|
|
else: |
|
|
@ -351,7 +351,7 @@ class CTxIn(object): |
|
|
|
self.nSequence = struct.unpack("<I", f.read(4))[0] |
|
|
|
self.nSequence = struct.unpack("<I", f.read(4))[0] |
|
|
|
|
|
|
|
|
|
|
|
def serialize(self): |
|
|
|
def serialize(self): |
|
|
|
r = "" |
|
|
|
r = b"" |
|
|
|
r += self.prevout.serialize() |
|
|
|
r += self.prevout.serialize() |
|
|
|
r += ser_string(self.scriptSig) |
|
|
|
r += ser_string(self.scriptSig) |
|
|
|
r += struct.pack("<I", self.nSequence) |
|
|
|
r += struct.pack("<I", self.nSequence) |
|
|
@ -359,12 +359,12 @@ class CTxIn(object): |
|
|
|
|
|
|
|
|
|
|
|
def __repr__(self): |
|
|
|
def __repr__(self): |
|
|
|
return "CTxIn(prevout=%s scriptSig=%s nSequence=%i)" \ |
|
|
|
return "CTxIn(prevout=%s scriptSig=%s nSequence=%i)" \ |
|
|
|
% (repr(self.prevout), binascii.hexlify(self.scriptSig), |
|
|
|
% (repr(self.prevout), hexlify(self.scriptSig), |
|
|
|
self.nSequence) |
|
|
|
self.nSequence) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class CTxOut(object): |
|
|
|
class CTxOut(object): |
|
|
|
def __init__(self, nValue=0, scriptPubKey=""): |
|
|
|
def __init__(self, nValue=0, scriptPubKey=b""): |
|
|
|
self.nValue = nValue |
|
|
|
self.nValue = nValue |
|
|
|
self.scriptPubKey = scriptPubKey |
|
|
|
self.scriptPubKey = scriptPubKey |
|
|
|
|
|
|
|
|
|
|
@ -373,7 +373,7 @@ class CTxOut(object): |
|
|
|
self.scriptPubKey = deser_string(f) |
|
|
|
self.scriptPubKey = deser_string(f) |
|
|
|
|
|
|
|
|
|
|
|
def serialize(self): |
|
|
|
def serialize(self): |
|
|
|
r = "" |
|
|
|
r = b"" |
|
|
|
r += struct.pack("<q", self.nValue) |
|
|
|
r += struct.pack("<q", self.nValue) |
|
|
|
r += ser_string(self.scriptPubKey) |
|
|
|
r += ser_string(self.scriptPubKey) |
|
|
|
return r |
|
|
|
return r |
|
|
@ -381,7 +381,7 @@ class CTxOut(object): |
|
|
|
def __repr__(self): |
|
|
|
def __repr__(self): |
|
|
|
return "CTxOut(nValue=%i.%08i scriptPubKey=%s)" \ |
|
|
|
return "CTxOut(nValue=%i.%08i scriptPubKey=%s)" \ |
|
|
|
% (self.nValue // COIN, self.nValue % COIN, |
|
|
|
% (self.nValue // COIN, self.nValue % COIN, |
|
|
|
binascii.hexlify(self.scriptPubKey)) |
|
|
|
hexlify(self.scriptPubKey)) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class CTransaction(object): |
|
|
|
class CTransaction(object): |
|
|
@ -410,7 +410,7 @@ class CTransaction(object): |
|
|
|
self.hash = None |
|
|
|
self.hash = None |
|
|
|
|
|
|
|
|
|
|
|
def serialize(self): |
|
|
|
def serialize(self): |
|
|
|
r = "" |
|
|
|
r = b"" |
|
|
|
r += struct.pack("<i", self.nVersion) |
|
|
|
r += struct.pack("<i", self.nVersion) |
|
|
|
r += ser_vector(self.vin) |
|
|
|
r += ser_vector(self.vin) |
|
|
|
r += ser_vector(self.vout) |
|
|
|
r += ser_vector(self.vout) |
|
|
@ -424,7 +424,7 @@ class CTransaction(object): |
|
|
|
def calc_sha256(self): |
|
|
|
def calc_sha256(self): |
|
|
|
if self.sha256 is None: |
|
|
|
if self.sha256 is None: |
|
|
|
self.sha256 = uint256_from_str(hash256(self.serialize())) |
|
|
|
self.sha256 = uint256_from_str(hash256(self.serialize())) |
|
|
|
self.hash = encode(hash256(self.serialize())[::-1], 'hex') |
|
|
|
self.hash = encode(hash256(self.serialize())[::-1], 'hex_codec').decode('ascii') |
|
|
|
|
|
|
|
|
|
|
|
def is_valid(self): |
|
|
|
def is_valid(self): |
|
|
|
self.calc_sha256() |
|
|
|
self.calc_sha256() |
|
|
@ -474,7 +474,7 @@ class CBlockHeader(object): |
|
|
|
self.hash = None |
|
|
|
self.hash = None |
|
|
|
|
|
|
|
|
|
|
|
def serialize(self): |
|
|
|
def serialize(self): |
|
|
|
r = "" |
|
|
|
r = b"" |
|
|
|
r += struct.pack("<i", self.nVersion) |
|
|
|
r += struct.pack("<i", self.nVersion) |
|
|
|
r += ser_uint256(self.hashPrevBlock) |
|
|
|
r += ser_uint256(self.hashPrevBlock) |
|
|
|
r += ser_uint256(self.hashMerkleRoot) |
|
|
|
r += ser_uint256(self.hashMerkleRoot) |
|
|
@ -485,7 +485,7 @@ class CBlockHeader(object): |
|
|
|
|
|
|
|
|
|
|
|
def calc_sha256(self): |
|
|
|
def calc_sha256(self): |
|
|
|
if self.sha256 is None: |
|
|
|
if self.sha256 is None: |
|
|
|
r = "" |
|
|
|
r = b"" |
|
|
|
r += struct.pack("<i", self.nVersion) |
|
|
|
r += struct.pack("<i", self.nVersion) |
|
|
|
r += ser_uint256(self.hashPrevBlock) |
|
|
|
r += ser_uint256(self.hashPrevBlock) |
|
|
|
r += ser_uint256(self.hashMerkleRoot) |
|
|
|
r += ser_uint256(self.hashMerkleRoot) |
|
|
@ -493,7 +493,7 @@ class CBlockHeader(object): |
|
|
|
r += struct.pack("<I", self.nBits) |
|
|
|
r += struct.pack("<I", self.nBits) |
|
|
|
r += struct.pack("<I", self.nNonce) |
|
|
|
r += struct.pack("<I", self.nNonce) |
|
|
|
self.sha256 = uint256_from_str(hash256(r)) |
|
|
|
self.sha256 = uint256_from_str(hash256(r)) |
|
|
|
self.hash = encode(hash256(r)[::-1], 'hex') |
|
|
|
self.hash = encode(hash256(r)[::-1], 'hex_codec').decode('ascii') |
|
|
|
|
|
|
|
|
|
|
|
def rehash(self): |
|
|
|
def rehash(self): |
|
|
|
self.sha256 = None |
|
|
|
self.sha256 = None |
|
|
@ -516,7 +516,7 @@ class CBlock(CBlockHeader): |
|
|
|
self.vtx = deser_vector(f, CTransaction) |
|
|
|
self.vtx = deser_vector(f, CTransaction) |
|
|
|
|
|
|
|
|
|
|
|
def serialize(self): |
|
|
|
def serialize(self): |
|
|
|
r = "" |
|
|
|
r = b"" |
|
|
|
r += super(CBlock, self).serialize() |
|
|
|
r += super(CBlock, self).serialize() |
|
|
|
r += ser_vector(self.vtx) |
|
|
|
r += ser_vector(self.vtx) |
|
|
|
return r |
|
|
|
return r |
|
|
@ -571,9 +571,9 @@ class CUnsignedAlert(object): |
|
|
|
self.nMaxVer = 0 |
|
|
|
self.nMaxVer = 0 |
|
|
|
self.setSubVer = [] |
|
|
|
self.setSubVer = [] |
|
|
|
self.nPriority = 0 |
|
|
|
self.nPriority = 0 |
|
|
|
self.strComment = "" |
|
|
|
self.strComment = b"" |
|
|
|
self.strStatusBar = "" |
|
|
|
self.strStatusBar = b"" |
|
|
|
self.strReserved = "" |
|
|
|
self.strReserved = b"" |
|
|
|
|
|
|
|
|
|
|
|
def deserialize(self, f): |
|
|
|
def deserialize(self, f): |
|
|
|
self.nVersion = struct.unpack("<i", f.read(4))[0] |
|
|
|
self.nVersion = struct.unpack("<i", f.read(4))[0] |
|
|
@ -591,7 +591,7 @@ class CUnsignedAlert(object): |
|
|
|
self.strReserved = deser_string(f) |
|
|
|
self.strReserved = deser_string(f) |
|
|
|
|
|
|
|
|
|
|
|
def serialize(self): |
|
|
|
def serialize(self): |
|
|
|
r = "" |
|
|
|
r = b"" |
|
|
|
r += struct.pack("<i", self.nVersion) |
|
|
|
r += struct.pack("<i", self.nVersion) |
|
|
|
r += struct.pack("<q", self.nRelayUntil) |
|
|
|
r += struct.pack("<q", self.nRelayUntil) |
|
|
|
r += struct.pack("<q", self.nExpiration) |
|
|
|
r += struct.pack("<q", self.nExpiration) |
|
|
@ -616,8 +616,8 @@ class CUnsignedAlert(object): |
|
|
|
|
|
|
|
|
|
|
|
class CAlert(object): |
|
|
|
class CAlert(object): |
|
|
|
def __init__(self): |
|
|
|
def __init__(self): |
|
|
|
self.vchMsg = "" |
|
|
|
self.vchMsg = b"" |
|
|
|
self.vchSig = "" |
|
|
|
self.vchSig = b"" |
|
|
|
|
|
|
|
|
|
|
|
def deserialize(self, f): |
|
|
|
def deserialize(self, f): |
|
|
|
self.vchMsg = deser_string(f) |
|
|
|
self.vchMsg = deser_string(f) |
|
|
@ -636,7 +636,7 @@ class CAlert(object): |
|
|
|
|
|
|
|
|
|
|
|
# Objects that correspond to messages on the wire |
|
|
|
# Objects that correspond to messages on the wire |
|
|
|
class msg_version(object): |
|
|
|
class msg_version(object): |
|
|
|
command = "version" |
|
|
|
command = b"version" |
|
|
|
|
|
|
|
|
|
|
|
def __init__(self): |
|
|
|
def __init__(self): |
|
|
|
self.nVersion = MY_VERSION |
|
|
|
self.nVersion = MY_VERSION |
|
|
@ -672,7 +672,7 @@ class msg_version(object): |
|
|
|
self.nStartingHeight = None |
|
|
|
self.nStartingHeight = None |
|
|
|
|
|
|
|
|
|
|
|
def serialize(self): |
|
|
|
def serialize(self): |
|
|
|
r = "" |
|
|
|
r = b"" |
|
|
|
r += struct.pack("<i", self.nVersion) |
|
|
|
r += struct.pack("<i", self.nVersion) |
|
|
|
r += struct.pack("<Q", self.nServices) |
|
|
|
r += struct.pack("<Q", self.nServices) |
|
|
|
r += struct.pack("<q", self.nTime) |
|
|
|
r += struct.pack("<q", self.nTime) |
|
|
@ -691,7 +691,7 @@ class msg_version(object): |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class msg_verack(object): |
|
|
|
class msg_verack(object): |
|
|
|
command = "verack" |
|
|
|
command = b"verack" |
|
|
|
|
|
|
|
|
|
|
|
def __init__(self): |
|
|
|
def __init__(self): |
|
|
|
pass |
|
|
|
pass |
|
|
@ -700,14 +700,14 @@ class msg_verack(object): |
|
|
|
pass |
|
|
|
pass |
|
|
|
|
|
|
|
|
|
|
|
def serialize(self): |
|
|
|
def serialize(self): |
|
|
|
return "" |
|
|
|
return b"" |
|
|
|
|
|
|
|
|
|
|
|
def __repr__(self): |
|
|
|
def __repr__(self): |
|
|
|
return "msg_verack()" |
|
|
|
return "msg_verack()" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class msg_addr(object): |
|
|
|
class msg_addr(object): |
|
|
|
command = "addr" |
|
|
|
command = b"addr" |
|
|
|
|
|
|
|
|
|
|
|
def __init__(self): |
|
|
|
def __init__(self): |
|
|
|
self.addrs = [] |
|
|
|
self.addrs = [] |
|
|
@ -723,7 +723,7 @@ class msg_addr(object): |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class msg_alert(object): |
|
|
|
class msg_alert(object): |
|
|
|
command = "alert" |
|
|
|
command = b"alert" |
|
|
|
|
|
|
|
|
|
|
|
def __init__(self): |
|
|
|
def __init__(self): |
|
|
|
self.alert = CAlert() |
|
|
|
self.alert = CAlert() |
|
|
@ -733,7 +733,7 @@ class msg_alert(object): |
|
|
|
self.alert.deserialize(f) |
|
|
|
self.alert.deserialize(f) |
|
|
|
|
|
|
|
|
|
|
|
def serialize(self): |
|
|
|
def serialize(self): |
|
|
|
r = "" |
|
|
|
r = b"" |
|
|
|
r += self.alert.serialize() |
|
|
|
r += self.alert.serialize() |
|
|
|
return r |
|
|
|
return r |
|
|
|
|
|
|
|
|
|
|
@ -742,7 +742,7 @@ class msg_alert(object): |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class msg_inv(object): |
|
|
|
class msg_inv(object): |
|
|
|
command = "inv" |
|
|
|
command = b"inv" |
|
|
|
|
|
|
|
|
|
|
|
def __init__(self, inv=None): |
|
|
|
def __init__(self, inv=None): |
|
|
|
if inv is None: |
|
|
|
if inv is None: |
|
|
@ -761,7 +761,7 @@ class msg_inv(object): |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class msg_getdata(object): |
|
|
|
class msg_getdata(object): |
|
|
|
command = "getdata" |
|
|
|
command = b"getdata" |
|
|
|
|
|
|
|
|
|
|
|
def __init__(self, inv=None): |
|
|
|
def __init__(self, inv=None): |
|
|
|
self.inv = inv if inv != None else [] |
|
|
|
self.inv = inv if inv != None else [] |
|
|
@ -777,7 +777,7 @@ class msg_getdata(object): |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class msg_getblocks(object): |
|
|
|
class msg_getblocks(object): |
|
|
|
command = "getblocks" |
|
|
|
command = b"getblocks" |
|
|
|
|
|
|
|
|
|
|
|
def __init__(self): |
|
|
|
def __init__(self): |
|
|
|
self.locator = CBlockLocator() |
|
|
|
self.locator = CBlockLocator() |
|
|
@ -789,7 +789,7 @@ class msg_getblocks(object): |
|
|
|
self.hashstop = deser_uint256(f) |
|
|
|
self.hashstop = deser_uint256(f) |
|
|
|
|
|
|
|
|
|
|
|
def serialize(self): |
|
|
|
def serialize(self): |
|
|
|
r = "" |
|
|
|
r = b"" |
|
|
|
r += self.locator.serialize() |
|
|
|
r += self.locator.serialize() |
|
|
|
r += ser_uint256(self.hashstop) |
|
|
|
r += ser_uint256(self.hashstop) |
|
|
|
return r |
|
|
|
return r |
|
|
@ -800,7 +800,7 @@ class msg_getblocks(object): |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class msg_tx(object): |
|
|
|
class msg_tx(object): |
|
|
|
command = "tx" |
|
|
|
command = b"tx" |
|
|
|
|
|
|
|
|
|
|
|
def __init__(self, tx=CTransaction()): |
|
|
|
def __init__(self, tx=CTransaction()): |
|
|
|
self.tx = tx |
|
|
|
self.tx = tx |
|
|
@ -816,7 +816,7 @@ class msg_tx(object): |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class msg_block(object): |
|
|
|
class msg_block(object): |
|
|
|
command = "block" |
|
|
|
command = b"block" |
|
|
|
|
|
|
|
|
|
|
|
def __init__(self, block=None): |
|
|
|
def __init__(self, block=None): |
|
|
|
if block is None: |
|
|
|
if block is None: |
|
|
@ -835,7 +835,7 @@ class msg_block(object): |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class msg_getaddr(object): |
|
|
|
class msg_getaddr(object): |
|
|
|
command = "getaddr" |
|
|
|
command = b"getaddr" |
|
|
|
|
|
|
|
|
|
|
|
def __init__(self): |
|
|
|
def __init__(self): |
|
|
|
pass |
|
|
|
pass |
|
|
@ -844,14 +844,14 @@ class msg_getaddr(object): |
|
|
|
pass |
|
|
|
pass |
|
|
|
|
|
|
|
|
|
|
|
def serialize(self): |
|
|
|
def serialize(self): |
|
|
|
return "" |
|
|
|
return b"" |
|
|
|
|
|
|
|
|
|
|
|
def __repr__(self): |
|
|
|
def __repr__(self): |
|
|
|
return "msg_getaddr()" |
|
|
|
return "msg_getaddr()" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class msg_ping_prebip31(object): |
|
|
|
class msg_ping_prebip31(object): |
|
|
|
command = "ping" |
|
|
|
command = b"ping" |
|
|
|
|
|
|
|
|
|
|
|
def __init__(self): |
|
|
|
def __init__(self): |
|
|
|
pass |
|
|
|
pass |
|
|
@ -860,14 +860,14 @@ class msg_ping_prebip31(object): |
|
|
|
pass |
|
|
|
pass |
|
|
|
|
|
|
|
|
|
|
|
def serialize(self): |
|
|
|
def serialize(self): |
|
|
|
return "" |
|
|
|
return b"" |
|
|
|
|
|
|
|
|
|
|
|
def __repr__(self): |
|
|
|
def __repr__(self): |
|
|
|
return "msg_ping() (pre-bip31)" |
|
|
|
return "msg_ping() (pre-bip31)" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class msg_ping(object): |
|
|
|
class msg_ping(object): |
|
|
|
command = "ping" |
|
|
|
command = b"ping" |
|
|
|
|
|
|
|
|
|
|
|
def __init__(self, nonce=0L): |
|
|
|
def __init__(self, nonce=0L): |
|
|
|
self.nonce = nonce |
|
|
|
self.nonce = nonce |
|
|
@ -876,7 +876,7 @@ class msg_ping(object): |
|
|
|
self.nonce = struct.unpack("<Q", f.read(8))[0] |
|
|
|
self.nonce = struct.unpack("<Q", f.read(8))[0] |
|
|
|
|
|
|
|
|
|
|
|
def serialize(self): |
|
|
|
def serialize(self): |
|
|
|
r = "" |
|
|
|
r = b"" |
|
|
|
r += struct.pack("<Q", self.nonce) |
|
|
|
r += struct.pack("<Q", self.nonce) |
|
|
|
return r |
|
|
|
return r |
|
|
|
|
|
|
|
|
|
|
@ -885,16 +885,16 @@ class msg_ping(object): |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class msg_pong(object): |
|
|
|
class msg_pong(object): |
|
|
|
command = "pong" |
|
|
|
command = b"pong" |
|
|
|
|
|
|
|
|
|
|
|
def __init__(self, nonce=0L): |
|
|
|
def __init__(self, nonce=0): |
|
|
|
self.nonce = nonce |
|
|
|
self.nonce = nonce |
|
|
|
|
|
|
|
|
|
|
|
def deserialize(self, f): |
|
|
|
def deserialize(self, f): |
|
|
|
self.nonce = struct.unpack("<Q", f.read(8))[0] |
|
|
|
self.nonce = struct.unpack("<Q", f.read(8))[0] |
|
|
|
|
|
|
|
|
|
|
|
def serialize(self): |
|
|
|
def serialize(self): |
|
|
|
r = "" |
|
|
|
r = b"" |
|
|
|
r += struct.pack("<Q", self.nonce) |
|
|
|
r += struct.pack("<Q", self.nonce) |
|
|
|
return r |
|
|
|
return r |
|
|
|
|
|
|
|
|
|
|
@ -903,7 +903,7 @@ class msg_pong(object): |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class msg_mempool(object): |
|
|
|
class msg_mempool(object): |
|
|
|
command = "mempool" |
|
|
|
command = b"mempool" |
|
|
|
|
|
|
|
|
|
|
|
def __init__(self): |
|
|
|
def __init__(self): |
|
|
|
pass |
|
|
|
pass |
|
|
@ -912,13 +912,13 @@ class msg_mempool(object): |
|
|
|
pass |
|
|
|
pass |
|
|
|
|
|
|
|
|
|
|
|
def serialize(self): |
|
|
|
def serialize(self): |
|
|
|
return "" |
|
|
|
return b"" |
|
|
|
|
|
|
|
|
|
|
|
def __repr__(self): |
|
|
|
def __repr__(self): |
|
|
|
return "msg_mempool()" |
|
|
|
return "msg_mempool()" |
|
|
|
|
|
|
|
|
|
|
|
class msg_sendheaders(object): |
|
|
|
class msg_sendheaders(object): |
|
|
|
command = "sendheaders" |
|
|
|
command = b"sendheaders" |
|
|
|
|
|
|
|
|
|
|
|
def __init__(self): |
|
|
|
def __init__(self): |
|
|
|
pass |
|
|
|
pass |
|
|
@ -927,7 +927,7 @@ class msg_sendheaders(object): |
|
|
|
pass |
|
|
|
pass |
|
|
|
|
|
|
|
|
|
|
|
def serialize(self): |
|
|
|
def serialize(self): |
|
|
|
return "" |
|
|
|
return b"" |
|
|
|
|
|
|
|
|
|
|
|
def __repr__(self): |
|
|
|
def __repr__(self): |
|
|
|
return "msg_sendheaders()" |
|
|
|
return "msg_sendheaders()" |
|
|
@ -937,7 +937,7 @@ class msg_sendheaders(object): |
|
|
|
# vector of hashes |
|
|
|
# vector of hashes |
|
|
|
# hash_stop (hash of last desired block header, 0 to get as many as possible) |
|
|
|
# hash_stop (hash of last desired block header, 0 to get as many as possible) |
|
|
|
class msg_getheaders(object): |
|
|
|
class msg_getheaders(object): |
|
|
|
command = "getheaders" |
|
|
|
command = b"getheaders" |
|
|
|
|
|
|
|
|
|
|
|
def __init__(self): |
|
|
|
def __init__(self): |
|
|
|
self.locator = CBlockLocator() |
|
|
|
self.locator = CBlockLocator() |
|
|
@ -949,7 +949,7 @@ class msg_getheaders(object): |
|
|
|
self.hashstop = deser_uint256(f) |
|
|
|
self.hashstop = deser_uint256(f) |
|
|
|
|
|
|
|
|
|
|
|
def serialize(self): |
|
|
|
def serialize(self): |
|
|
|
r = "" |
|
|
|
r = b"" |
|
|
|
r += self.locator.serialize() |
|
|
|
r += self.locator.serialize() |
|
|
|
r += ser_uint256(self.hashstop) |
|
|
|
r += ser_uint256(self.hashstop) |
|
|
|
return r |
|
|
|
return r |
|
|
@ -962,7 +962,7 @@ class msg_getheaders(object): |
|
|
|
# headers message has |
|
|
|
# headers message has |
|
|
|
# <count> <vector of block headers> |
|
|
|
# <count> <vector of block headers> |
|
|
|
class msg_headers(object): |
|
|
|
class msg_headers(object): |
|
|
|
command = "headers" |
|
|
|
command = b"headers" |
|
|
|
|
|
|
|
|
|
|
|
def __init__(self): |
|
|
|
def __init__(self): |
|
|
|
self.headers = [] |
|
|
|
self.headers = [] |
|
|
@ -982,10 +982,10 @@ class msg_headers(object): |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class msg_reject(object): |
|
|
|
class msg_reject(object): |
|
|
|
command = "reject" |
|
|
|
command = b"reject" |
|
|
|
|
|
|
|
|
|
|
|
def __init__(self): |
|
|
|
def __init__(self): |
|
|
|
self.message = "" |
|
|
|
self.message = b"" |
|
|
|
self.code = 0 |
|
|
|
self.code = 0 |
|
|
|
self.reason = "" |
|
|
|
self.reason = "" |
|
|
|
self.data = 0L |
|
|
|
self.data = 0L |
|
|
@ -1025,7 +1025,7 @@ def wait_until(predicate, attempts=float('inf'), timeout=float('inf')): |
|
|
|
return False |
|
|
|
return False |
|
|
|
|
|
|
|
|
|
|
|
class msg_feefilter(object): |
|
|
|
class msg_feefilter(object): |
|
|
|
command = "feefilter" |
|
|
|
command = b"feefilter" |
|
|
|
|
|
|
|
|
|
|
|
def __init__(self, feerate=0L): |
|
|
|
def __init__(self, feerate=0L): |
|
|
|
self.feerate = feerate |
|
|
|
self.feerate = feerate |
|
|
@ -1034,7 +1034,7 @@ class msg_feefilter(object): |
|
|
|
self.feerate = struct.unpack("<Q", f.read(8))[0] |
|
|
|
self.feerate = struct.unpack("<Q", f.read(8))[0] |
|
|
|
|
|
|
|
|
|
|
|
def serialize(self): |
|
|
|
def serialize(self): |
|
|
|
r = "" |
|
|
|
r = b"" |
|
|
|
r += struct.pack("<Q", self.feerate) |
|
|
|
r += struct.pack("<Q", self.feerate) |
|
|
|
return r |
|
|
|
return r |
|
|
|
|
|
|
|
|
|
|
@ -1149,28 +1149,28 @@ class SingleNodeConnCB(NodeConnCB): |
|
|
|
# This class provides an interface for a p2p connection to a specified node |
|
|
|
# This class provides an interface for a p2p connection to a specified node |
|
|
|
class NodeConn(asyncore.dispatcher): |
|
|
|
class NodeConn(asyncore.dispatcher): |
|
|
|
messagemap = { |
|
|
|
messagemap = { |
|
|
|
"version": msg_version, |
|
|
|
b"version": msg_version, |
|
|
|
"verack": msg_verack, |
|
|
|
b"verack": msg_verack, |
|
|
|
"addr": msg_addr, |
|
|
|
b"addr": msg_addr, |
|
|
|
"alert": msg_alert, |
|
|
|
b"alert": msg_alert, |
|
|
|
"inv": msg_inv, |
|
|
|
b"inv": msg_inv, |
|
|
|
"getdata": msg_getdata, |
|
|
|
b"getdata": msg_getdata, |
|
|
|
"getblocks": msg_getblocks, |
|
|
|
b"getblocks": msg_getblocks, |
|
|
|
"tx": msg_tx, |
|
|
|
b"tx": msg_tx, |
|
|
|
"block": msg_block, |
|
|
|
b"block": msg_block, |
|
|
|
"getaddr": msg_getaddr, |
|
|
|
b"getaddr": msg_getaddr, |
|
|
|
"ping": msg_ping, |
|
|
|
b"ping": msg_ping, |
|
|
|
"pong": msg_pong, |
|
|
|
b"pong": msg_pong, |
|
|
|
"headers": msg_headers, |
|
|
|
b"headers": msg_headers, |
|
|
|
"getheaders": msg_getheaders, |
|
|
|
b"getheaders": msg_getheaders, |
|
|
|
"reject": msg_reject, |
|
|
|
b"reject": msg_reject, |
|
|
|
"mempool": msg_mempool, |
|
|
|
b"mempool": msg_mempool, |
|
|
|
"feefilter": msg_feefilter |
|
|
|
b"feefilter": msg_feefilter |
|
|
|
} |
|
|
|
} |
|
|
|
MAGIC_BYTES = { |
|
|
|
MAGIC_BYTES = { |
|
|
|
"mainnet": "\xf9\xbe\xb4\xd9", # mainnet |
|
|
|
"mainnet": b"\xf9\xbe\xb4\xd9", # mainnet |
|
|
|
"testnet3": "\x0b\x11\x09\x07", # testnet3 |
|
|
|
"testnet3": b"\x0b\x11\x09\x07", # testnet3 |
|
|
|
"regtest": "\xfa\xbf\xb5\xda" # regtest |
|
|
|
"regtest": b"\xfa\xbf\xb5\xda" # regtest |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
def __init__(self, dstaddr, dstport, rpc, callback, net="regtest", services=1): |
|
|
|
def __init__(self, dstaddr, dstport, rpc, callback, net="regtest", services=1): |
|
|
@ -1179,8 +1179,8 @@ class NodeConn(asyncore.dispatcher): |
|
|
|
self.dstaddr = dstaddr |
|
|
|
self.dstaddr = dstaddr |
|
|
|
self.dstport = dstport |
|
|
|
self.dstport = dstport |
|
|
|
self.create_socket(socket.AF_INET, socket.SOCK_STREAM) |
|
|
|
self.create_socket(socket.AF_INET, socket.SOCK_STREAM) |
|
|
|
self.sendbuf = "" |
|
|
|
self.sendbuf = b"" |
|
|
|
self.recvbuf = "" |
|
|
|
self.recvbuf = b"" |
|
|
|
self.ver_send = 209 |
|
|
|
self.ver_send = 209 |
|
|
|
self.ver_recv = 209 |
|
|
|
self.ver_recv = 209 |
|
|
|
self.last_sent = 0 |
|
|
|
self.last_sent = 0 |
|
|
@ -1217,8 +1217,8 @@ class NodeConn(asyncore.dispatcher): |
|
|
|
self.show_debug_msg("MiniNode: Closing Connection to %s:%d... " |
|
|
|
self.show_debug_msg("MiniNode: Closing Connection to %s:%d... " |
|
|
|
% (self.dstaddr, self.dstport)) |
|
|
|
% (self.dstaddr, self.dstport)) |
|
|
|
self.state = "closed" |
|
|
|
self.state = "closed" |
|
|
|
self.recvbuf = "" |
|
|
|
self.recvbuf = b"" |
|
|
|
self.sendbuf = "" |
|
|
|
self.sendbuf = b"" |
|
|
|
try: |
|
|
|
try: |
|
|
|
self.close() |
|
|
|
self.close() |
|
|
|
except: |
|
|
|
except: |
|
|
@ -1261,7 +1261,7 @@ class NodeConn(asyncore.dispatcher): |
|
|
|
if self.ver_recv < 209: |
|
|
|
if self.ver_recv < 209: |
|
|
|
if len(self.recvbuf) < 4 + 12 + 4: |
|
|
|
if len(self.recvbuf) < 4 + 12 + 4: |
|
|
|
return |
|
|
|
return |
|
|
|
command = self.recvbuf[4:4+12].split("\x00", 1)[0] |
|
|
|
command = self.recvbuf[4:4+12].split(b"\x00", 1)[0] |
|
|
|
msglen = struct.unpack("<i", self.recvbuf[4+12:4+12+4])[0] |
|
|
|
msglen = struct.unpack("<i", self.recvbuf[4+12:4+12+4])[0] |
|
|
|
checksum = None |
|
|
|
checksum = None |
|
|
|
if len(self.recvbuf) < 4 + 12 + 4 + msglen: |
|
|
|
if len(self.recvbuf) < 4 + 12 + 4 + msglen: |
|
|
@ -1271,7 +1271,7 @@ class NodeConn(asyncore.dispatcher): |
|
|
|
else: |
|
|
|
else: |
|
|
|
if len(self.recvbuf) < 4 + 12 + 4 + 4: |
|
|
|
if len(self.recvbuf) < 4 + 12 + 4 + 4: |
|
|
|
return |
|
|
|
return |
|
|
|
command = self.recvbuf[4:4+12].split("\x00", 1)[0] |
|
|
|
command = self.recvbuf[4:4+12].split(b"\x00", 1)[0] |
|
|
|
msglen = struct.unpack("<i", self.recvbuf[4+12:4+12+4])[0] |
|
|
|
msglen = struct.unpack("<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] |
|
|
|
if len(self.recvbuf) < 4 + 12 + 4 + 4 + msglen: |
|
|
|
if len(self.recvbuf) < 4 + 12 + 4 + 4 + msglen: |
|
|
@ -1301,7 +1301,7 @@ class NodeConn(asyncore.dispatcher): |
|
|
|
data = message.serialize() |
|
|
|
data = message.serialize() |
|
|
|
tmsg = self.MAGIC_BYTES[self.network] |
|
|
|
tmsg = self.MAGIC_BYTES[self.network] |
|
|
|
tmsg += command |
|
|
|
tmsg += command |
|
|
|
tmsg += "\x00" * (12 - len(command)) |
|
|
|
tmsg += b"\x00" * (12 - len(command)) |
|
|
|
tmsg += struct.pack("<I", len(data)) |
|
|
|
tmsg += struct.pack("<I", len(data)) |
|
|
|
if self.ver_send >= 209: |
|
|
|
if self.ver_send >= 209: |
|
|
|
th = sha256(data) |
|
|
|
th = sha256(data) |
|
|
@ -1313,11 +1313,11 @@ class NodeConn(asyncore.dispatcher): |
|
|
|
self.last_sent = time.time() |
|
|
|
self.last_sent = time.time() |
|
|
|
|
|
|
|
|
|
|
|
def got_message(self, message): |
|
|
|
def got_message(self, message): |
|
|
|
if message.command == "version": |
|
|
|
if message.command == b"version": |
|
|
|
if message.nVersion <= BIP0031_VERSION: |
|
|
|
if message.nVersion <= BIP0031_VERSION: |
|
|
|
self.messagemap['ping'] = msg_ping_prebip31 |
|
|
|
self.messagemap[b'ping'] = msg_ping_prebip31 |
|
|
|
if self.last_sent + 30 * 60 < time.time(): |
|
|
|
if self.last_sent + 30 * 60 < time.time(): |
|
|
|
self.send_message(self.messagemap['ping']()) |
|
|
|
self.send_message(self.messagemap[b'ping']()) |
|
|
|
self.show_debug_msg("Recv %s" % repr(message)) |
|
|
|
self.show_debug_msg("Recv %s" % repr(message)) |
|
|
|
self.cb.deliver(self, message) |
|
|
|
self.cb.deliver(self, message) |
|
|
|
|
|
|
|
|
|
|
|