2 # Copyright (c) 2010 ArtForz -- public domain half-a-node
3 # Copyright (c) 2012 Jeff Garzik
4 # Copyright (c) 2010-2016 The Bitcoin Core developers
5 # Distributed under the MIT software license, see the accompanying
6 # file COPYING or http://www.opensource.org/licenses/mit-license.php.
7 """Bitcoin P2P network half-a-node.
9 This python code was modified from ArtForz' public domain half-a-node, as
10 found in the mini-node branch of http://github.com/jgarzik/pynode.
12 NodeConn: an object which manages p2p connectivity to a bitcoin node
13 NodeConnCB: a base class that describes the interface for receiving
14 callbacks with network messages from a NodeConn
15 CBlock, CTransaction, CBlockHeader, CTxIn, CTxOut, etc....:
16 data structures that should map to corresponding structures in
18 msg_block, msg_tx, msg_headers, etc.:
19 data structures that represent network messages
20 ser_*, deser_*: functions that handle serialization/deserialization
29 from .util
import hex_str_to_bytes
, bytes_to_hex_str
30 from io
import BytesIO
31 from codecs
import encode
33 from threading
import RLock
34 from threading
import Thread
37 from test_framework
.siphash
import siphash256
39 BIP0031_VERSION
= 60000
40 MY_VERSION
= 70014 # past bip-31 for ping/pong
41 MY_SUBVERSION
= b
"/python-mininode-tester:0.0.3/"
42 MY_RELAY
= 1 # from version 70001 onwards, fRelay should be appended to version messages (BIP37)
45 MAX_BLOCK_BASE_SIZE
= 1000000
47 COIN
= 100000000 # 1 btc in satoshis
49 NODE_NETWORK
= (1 << 0)
50 NODE_GETUTXO
= (1 << 1)
52 NODE_WITNESS
= (1 << 3)
54 logger
= logging
.getLogger("TestFramework.mininode")
56 # Keep our own socket map for asyncore, so that we can track disconnects
57 # ourselves (to workaround an issue with closing an asyncore socket when
59 mininode_socket_map
= dict()
61 # One lock for synchronizing all data access between the networking thread (see
62 # NetworkThread below) and the thread running the test logic. For simplicity,
63 # NodeConn acquires this lock whenever delivering a message to to a NodeConnCB,
64 # and whenever adding anything to the send buffer (in send_message()). This
65 # lock should be acquired in the thread running the test logic to synchronize
66 # access to any data shared with the NodeConnCB or NodeConn.
67 mininode_lock
= RLock()
69 # Serialization/deserialization tools
71 return hashlib
.new('sha256', s
).digest()
74 return hashlib
.new('ripemd160', s
).digest()
77 return sha256(sha256(s
))
79 def ser_compact_size(l
):
82 r
= struct
.pack("B", l
)
84 r
= struct
.pack("<BH", 253, l
)
86 r
= struct
.pack("<BI", 254, l
)
88 r
= struct
.pack("<BQ", 255, l
)
91 def deser_compact_size(f
):
92 nit
= struct
.unpack("<B", f
.read(1))[0]
94 nit
= struct
.unpack("<H", f
.read(2))[0]
96 nit
= struct
.unpack("<I", f
.read(4))[0]
98 nit
= struct
.unpack("<Q", f
.read(8))[0]
102 nit
= deser_compact_size(f
)
106 return ser_compact_size(len(s
)) + s
108 def deser_uint256(f
):
111 t
= struct
.unpack("<I", f
.read(4))[0]
119 rs
+= struct
.pack("<I", u
& 0xFFFFFFFF)
124 def uint256_from_str(s
):
126 t
= struct
.unpack("<IIIIIIII", s
[:32])
128 r
+= t
[i
] << (i
* 32)
132 def uint256_from_compact(c
):
133 nbytes
= (c
>> 24) & 0xFF
134 v
= (c
& 0xFFFFFF) << (8 * (nbytes
- 3))
138 def deser_vector(f
, c
):
139 nit
= deser_compact_size(f
)
148 # ser_function_name: Allow for an alternate serialization function on the
149 # entries in the vector (we use this for serializing the vector of transactions
150 # for a witness block).
151 def ser_vector(l
, ser_function_name
=None):
152 r
= ser_compact_size(len(l
))
154 if ser_function_name
:
155 r
+= getattr(i
, ser_function_name
)()
161 def deser_uint256_vector(f
):
162 nit
= deser_compact_size(f
)
170 def ser_uint256_vector(l
):
171 r
= ser_compact_size(len(l
))
177 def deser_string_vector(f
):
178 nit
= deser_compact_size(f
)
186 def ser_string_vector(l
):
187 r
= ser_compact_size(len(l
))
193 def deser_int_vector(f
):
194 nit
= deser_compact_size(f
)
197 t
= struct
.unpack("<i", f
.read(4))[0]
202 def ser_int_vector(l
):
203 r
= ser_compact_size(len(l
))
205 r
+= struct
.pack("<i", i
)
208 # Deserialize from a hex string representation (eg from RPC)
209 def FromHex(obj
, hex_string
):
210 obj
.deserialize(BytesIO(hex_str_to_bytes(hex_string
)))
213 # Convert a binary-serializable object to hex (eg for submission via RPC)
215 return bytes_to_hex_str(obj
.serialize())
217 # Objects that map to bitcoind objects, which can be serialized/deserialized
219 class CAddress(object):
222 self
.pchReserved
= b
"\x00" * 10 + b
"\xff" * 2
226 def deserialize(self
, f
):
227 self
.nServices
= struct
.unpack("<Q", f
.read(8))[0]
228 self
.pchReserved
= f
.read(12)
229 self
.ip
= socket
.inet_ntoa(f
.read(4))
230 self
.port
= struct
.unpack(">H", f
.read(2))[0]
234 r
+= struct
.pack("<Q", self
.nServices
)
235 r
+= self
.pchReserved
236 r
+= socket
.inet_aton(self
.ip
)
237 r
+= struct
.pack(">H", self
.port
)
241 return "CAddress(nServices=%i ip=%s port=%i)" % (self
.nServices
,
244 MSG_WITNESS_FLAG
= 1<<30
251 1|MSG_WITNESS_FLAG
: "WitnessTx",
252 2|MSG_WITNESS_FLAG
: "WitnessBlock",
256 def __init__(self
, t
=0, h
=0):
260 def deserialize(self
, f
):
261 self
.type = struct
.unpack("<i", f
.read(4))[0]
262 self
.hash = deser_uint256(f
)
266 r
+= struct
.pack("<i", self
.type)
267 r
+= ser_uint256(self
.hash)
271 return "CInv(type=%s hash=%064x)" \
272 % (self
.typemap
[self
.type], self
.hash)
275 class CBlockLocator(object):
277 self
.nVersion
= MY_VERSION
280 def deserialize(self
, f
):
281 self
.nVersion
= struct
.unpack("<i", f
.read(4))[0]
282 self
.vHave
= deser_uint256_vector(f
)
286 r
+= struct
.pack("<i", self
.nVersion
)
287 r
+= ser_uint256_vector(self
.vHave
)
291 return "CBlockLocator(nVersion=%i vHave=%s)" \
292 % (self
.nVersion
, repr(self
.vHave
))
295 class COutPoint(object):
296 def __init__(self
, hash=0, n
=0):
300 def deserialize(self
, f
):
301 self
.hash = deser_uint256(f
)
302 self
.n
= struct
.unpack("<I", f
.read(4))[0]
306 r
+= ser_uint256(self
.hash)
307 r
+= struct
.pack("<I", self
.n
)
311 return "COutPoint(hash=%064x n=%i)" % (self
.hash, self
.n
)
315 def __init__(self
, outpoint
=None, scriptSig
=b
"", nSequence
=0):
317 self
.prevout
= COutPoint()
319 self
.prevout
= outpoint
320 self
.scriptSig
= scriptSig
321 self
.nSequence
= nSequence
323 def deserialize(self
, f
):
324 self
.prevout
= COutPoint()
325 self
.prevout
.deserialize(f
)
326 self
.scriptSig
= deser_string(f
)
327 self
.nSequence
= struct
.unpack("<I", f
.read(4))[0]
331 r
+= self
.prevout
.serialize()
332 r
+= ser_string(self
.scriptSig
)
333 r
+= struct
.pack("<I", self
.nSequence
)
337 return "CTxIn(prevout=%s scriptSig=%s nSequence=%i)" \
338 % (repr(self
.prevout
), bytes_to_hex_str(self
.scriptSig
),
342 class CTxOut(object):
343 def __init__(self
, nValue
=0, scriptPubKey
=b
""):
345 self
.scriptPubKey
= scriptPubKey
347 def deserialize(self
, f
):
348 self
.nValue
= struct
.unpack("<q", f
.read(8))[0]
349 self
.scriptPubKey
= deser_string(f
)
353 r
+= struct
.pack("<q", self
.nValue
)
354 r
+= ser_string(self
.scriptPubKey
)
358 return "CTxOut(nValue=%i.%08i scriptPubKey=%s)" \
359 % (self
.nValue
// COIN
, self
.nValue
% COIN
,
360 bytes_to_hex_str(self
.scriptPubKey
))
363 class CScriptWitness(object):
365 # stack is a vector of strings
369 return "CScriptWitness(%s)" % \
370 (",".join([bytes_to_hex_str(x
) for x
in self
.stack
]))
378 class CTxInWitness(object):
380 self
.scriptWitness
= CScriptWitness()
382 def deserialize(self
, f
):
383 self
.scriptWitness
.stack
= deser_string_vector(f
)
386 return ser_string_vector(self
.scriptWitness
.stack
)
389 return repr(self
.scriptWitness
)
392 return self
.scriptWitness
.is_null()
395 class CTxWitness(object):
399 def deserialize(self
, f
):
400 for i
in range(len(self
.vtxinwit
)):
401 self
.vtxinwit
[i
].deserialize(f
)
405 # This is different than the usual vector serialization --
406 # we omit the length of the vector, which is required to be
407 # the same length as the transaction's vin vector.
408 for x
in self
.vtxinwit
:
413 return "CTxWitness(%s)" % \
414 (';'.join([repr(x
) for x
in self
.vtxinwit
]))
417 for x
in self
.vtxinwit
:
423 class CTransaction(object):
424 def __init__(self
, tx
=None):
429 self
.wit
= CTxWitness()
434 self
.nVersion
= tx
.nVersion
435 self
.vin
= copy
.deepcopy(tx
.vin
)
436 self
.vout
= copy
.deepcopy(tx
.vout
)
437 self
.nLockTime
= tx
.nLockTime
438 self
.sha256
= tx
.sha256
440 self
.wit
= copy
.deepcopy(tx
.wit
)
442 def deserialize(self
, f
):
443 self
.nVersion
= struct
.unpack("<i", f
.read(4))[0]
444 self
.vin
= deser_vector(f
, CTxIn
)
446 if len(self
.vin
) == 0:
447 flags
= struct
.unpack("<B", f
.read(1))[0]
448 # Not sure why flags can't be zero, but this
449 # matches the implementation in bitcoind
451 self
.vin
= deser_vector(f
, CTxIn
)
452 self
.vout
= deser_vector(f
, CTxOut
)
454 self
.vout
= deser_vector(f
, CTxOut
)
456 self
.wit
.vtxinwit
= [CTxInWitness() for i
in range(len(self
.vin
))]
457 self
.wit
.deserialize(f
)
458 self
.nLockTime
= struct
.unpack("<I", f
.read(4))[0]
462 def serialize_without_witness(self
):
464 r
+= struct
.pack("<i", self
.nVersion
)
465 r
+= ser_vector(self
.vin
)
466 r
+= ser_vector(self
.vout
)
467 r
+= struct
.pack("<I", self
.nLockTime
)
470 # Only serialize with witness when explicitly called for
471 def serialize_with_witness(self
):
473 if not self
.wit
.is_null():
476 r
+= struct
.pack("<i", self
.nVersion
)
479 r
+= ser_vector(dummy
)
480 r
+= struct
.pack("<B", flags
)
481 r
+= ser_vector(self
.vin
)
482 r
+= ser_vector(self
.vout
)
484 if (len(self
.wit
.vtxinwit
) != len(self
.vin
)):
485 # vtxinwit must have the same length as vin
486 self
.wit
.vtxinwit
= self
.wit
.vtxinwit
[:len(self
.vin
)]
487 for i
in range(len(self
.wit
.vtxinwit
), len(self
.vin
)):
488 self
.wit
.vtxinwit
.append(CTxInWitness())
489 r
+= self
.wit
.serialize()
490 r
+= struct
.pack("<I", self
.nLockTime
)
493 # Regular serialization is without witness -- must explicitly
494 # call serialize_with_witness to include witness data.
496 return self
.serialize_without_witness()
498 # Recalculate the txid (transaction hash without witness)
503 # We will only cache the serialization without witness in
504 # self.sha256 and self.hash -- those are expected to be the txid.
505 def calc_sha256(self
, with_witness
=False):
507 # Don't cache the result, just return it
508 return uint256_from_str(hash256(self
.serialize_with_witness()))
510 if self
.sha256
is None:
511 self
.sha256
= uint256_from_str(hash256(self
.serialize_without_witness()))
512 self
.hash = encode(hash256(self
.serialize())[::-1], 'hex_codec').decode('ascii')
516 for tout
in self
.vout
:
517 if tout
.nValue
< 0 or tout
.nValue
> 21000000 * COIN
:
522 return "CTransaction(nVersion=%i vin=%s vout=%s wit=%s nLockTime=%i)" \
523 % (self
.nVersion
, repr(self
.vin
), repr(self
.vout
), repr(self
.wit
), self
.nLockTime
)
526 class CBlockHeader(object):
527 def __init__(self
, header
=None):
531 self
.nVersion
= header
.nVersion
532 self
.hashPrevBlock
= header
.hashPrevBlock
533 self
.hashMerkleRoot
= header
.hashMerkleRoot
534 self
.nTime
= header
.nTime
535 self
.nBits
= header
.nBits
536 self
.nNonce
= header
.nNonce
537 self
.sha256
= header
.sha256
538 self
.hash = header
.hash
543 self
.hashPrevBlock
= 0
544 self
.hashMerkleRoot
= 0
551 def deserialize(self
, f
):
552 self
.nVersion
= struct
.unpack("<i", f
.read(4))[0]
553 self
.hashPrevBlock
= deser_uint256(f
)
554 self
.hashMerkleRoot
= deser_uint256(f
)
555 self
.nTime
= struct
.unpack("<I", f
.read(4))[0]
556 self
.nBits
= struct
.unpack("<I", f
.read(4))[0]
557 self
.nNonce
= struct
.unpack("<I", f
.read(4))[0]
563 r
+= struct
.pack("<i", self
.nVersion
)
564 r
+= ser_uint256(self
.hashPrevBlock
)
565 r
+= ser_uint256(self
.hashMerkleRoot
)
566 r
+= struct
.pack("<I", self
.nTime
)
567 r
+= struct
.pack("<I", self
.nBits
)
568 r
+= struct
.pack("<I", self
.nNonce
)
571 def calc_sha256(self
):
572 if self
.sha256
is None:
574 r
+= struct
.pack("<i", self
.nVersion
)
575 r
+= ser_uint256(self
.hashPrevBlock
)
576 r
+= ser_uint256(self
.hashMerkleRoot
)
577 r
+= struct
.pack("<I", self
.nTime
)
578 r
+= struct
.pack("<I", self
.nBits
)
579 r
+= struct
.pack("<I", self
.nNonce
)
580 self
.sha256
= uint256_from_str(hash256(r
))
581 self
.hash = encode(hash256(r
)[::-1], 'hex_codec').decode('ascii')
589 return "CBlockHeader(nVersion=%i hashPrevBlock=%064x hashMerkleRoot=%064x nTime=%s nBits=%08x nNonce=%08x)" \
590 % (self
.nVersion
, self
.hashPrevBlock
, self
.hashMerkleRoot
,
591 time
.ctime(self
.nTime
), self
.nBits
, self
.nNonce
)
594 class CBlock(CBlockHeader
):
595 def __init__(self
, header
=None):
596 super(CBlock
, self
).__init
__(header
)
599 def deserialize(self
, f
):
600 super(CBlock
, self
).deserialize(f
)
601 self
.vtx
= deser_vector(f
, CTransaction
)
603 def serialize(self
, with_witness
=False):
605 r
+= super(CBlock
, self
).serialize()
607 r
+= ser_vector(self
.vtx
, "serialize_with_witness")
609 r
+= ser_vector(self
.vtx
)
612 # Calculate the merkle root given a vector of transaction hashes
613 def get_merkle_root(self
, hashes
):
614 while len(hashes
) > 1:
616 for i
in range(0, len(hashes
), 2):
617 i2
= min(i
+1, len(hashes
)-1)
618 newhashes
.append(hash256(hashes
[i
] + hashes
[i2
]))
620 return uint256_from_str(hashes
[0])
622 def calc_merkle_root(self
):
626 hashes
.append(ser_uint256(tx
.sha256
))
627 return self
.get_merkle_root(hashes
)
629 def calc_witness_merkle_root(self
):
630 # For witness root purposes, the hash of the
631 # coinbase, with witness, is defined to be 0...0
632 hashes
= [ser_uint256(0)]
634 for tx
in self
.vtx
[1:]:
635 # Calculate the hashes with witness data
636 hashes
.append(ser_uint256(tx
.calc_sha256(True)))
638 return self
.get_merkle_root(hashes
)
642 target
= uint256_from_compact(self
.nBits
)
643 if self
.sha256
> target
:
646 if not tx
.is_valid():
648 if self
.calc_merkle_root() != self
.hashMerkleRoot
:
654 target
= uint256_from_compact(self
.nBits
)
655 while self
.sha256
> target
:
660 return "CBlock(nVersion=%i hashPrevBlock=%064x hashMerkleRoot=%064x nTime=%s nBits=%08x nNonce=%08x vtx=%s)" \
661 % (self
.nVersion
, self
.hashPrevBlock
, self
.hashMerkleRoot
,
662 time
.ctime(self
.nTime
), self
.nBits
, self
.nNonce
, repr(self
.vtx
))
665 class CUnsignedAlert(object):
677 self
.strComment
= b
""
678 self
.strStatusBar
= b
""
679 self
.strReserved
= b
""
681 def deserialize(self
, f
):
682 self
.nVersion
= struct
.unpack("<i", f
.read(4))[0]
683 self
.nRelayUntil
= struct
.unpack("<q", f
.read(8))[0]
684 self
.nExpiration
= struct
.unpack("<q", f
.read(8))[0]
685 self
.nID
= struct
.unpack("<i", f
.read(4))[0]
686 self
.nCancel
= struct
.unpack("<i", f
.read(4))[0]
687 self
.setCancel
= deser_int_vector(f
)
688 self
.nMinVer
= struct
.unpack("<i", f
.read(4))[0]
689 self
.nMaxVer
= struct
.unpack("<i", f
.read(4))[0]
690 self
.setSubVer
= deser_string_vector(f
)
691 self
.nPriority
= struct
.unpack("<i", f
.read(4))[0]
692 self
.strComment
= deser_string(f
)
693 self
.strStatusBar
= deser_string(f
)
694 self
.strReserved
= deser_string(f
)
698 r
+= struct
.pack("<i", self
.nVersion
)
699 r
+= struct
.pack("<q", self
.nRelayUntil
)
700 r
+= struct
.pack("<q", self
.nExpiration
)
701 r
+= struct
.pack("<i", self
.nID
)
702 r
+= struct
.pack("<i", self
.nCancel
)
703 r
+= ser_int_vector(self
.setCancel
)
704 r
+= struct
.pack("<i", self
.nMinVer
)
705 r
+= struct
.pack("<i", self
.nMaxVer
)
706 r
+= ser_string_vector(self
.setSubVer
)
707 r
+= struct
.pack("<i", self
.nPriority
)
708 r
+= ser_string(self
.strComment
)
709 r
+= ser_string(self
.strStatusBar
)
710 r
+= ser_string(self
.strReserved
)
714 return "CUnsignedAlert(nVersion %d, nRelayUntil %d, nExpiration %d, nID %d, nCancel %d, nMinVer %d, nMaxVer %d, nPriority %d, strComment %s, strStatusBar %s, strReserved %s)" \
715 % (self
.nVersion
, self
.nRelayUntil
, self
.nExpiration
, self
.nID
,
716 self
.nCancel
, self
.nMinVer
, self
.nMaxVer
, self
.nPriority
,
717 self
.strComment
, self
.strStatusBar
, self
.strReserved
)
720 class CAlert(object):
725 def deserialize(self
, f
):
726 self
.vchMsg
= deser_string(f
)
727 self
.vchSig
= deser_string(f
)
731 r
+= ser_string(self
.vchMsg
)
732 r
+= ser_string(self
.vchSig
)
736 return "CAlert(vchMsg.sz %d, vchSig.sz %d)" \
737 % (len(self
.vchMsg
), len(self
.vchSig
))
740 class PrefilledTransaction(object):
741 def __init__(self
, index
=0, tx
= None):
745 def deserialize(self
, f
):
746 self
.index
= deser_compact_size(f
)
747 self
.tx
= CTransaction()
748 self
.tx
.deserialize(f
)
750 def serialize(self
, with_witness
=False):
752 r
+= ser_compact_size(self
.index
)
754 r
+= self
.tx
.serialize_with_witness()
756 r
+= self
.tx
.serialize_without_witness()
759 def serialize_with_witness(self
):
760 return self
.serialize(with_witness
=True)
763 return "PrefilledTransaction(index=%d, tx=%s)" % (self
.index
, repr(self
.tx
))
765 # This is what we send on the wire, in a cmpctblock message.
766 class P2PHeaderAndShortIDs(object):
768 self
.header
= CBlockHeader()
770 self
.shortids_length
= 0
772 self
.prefilled_txn_length
= 0
773 self
.prefilled_txn
= []
775 def deserialize(self
, f
):
776 self
.header
.deserialize(f
)
777 self
.nonce
= struct
.unpack("<Q", f
.read(8))[0]
778 self
.shortids_length
= deser_compact_size(f
)
779 for i
in range(self
.shortids_length
):
780 # shortids are defined to be 6 bytes in the spec, so append
781 # two zero bytes and read it in as an 8-byte number
782 self
.shortids
.append(struct
.unpack("<Q", f
.read(6) + b
'\x00\x00')[0])
783 self
.prefilled_txn
= deser_vector(f
, PrefilledTransaction
)
784 self
.prefilled_txn_length
= len(self
.prefilled_txn
)
786 # When using version 2 compact blocks, we must serialize with_witness.
787 def serialize(self
, with_witness
=False):
789 r
+= self
.header
.serialize()
790 r
+= struct
.pack("<Q", self
.nonce
)
791 r
+= ser_compact_size(self
.shortids_length
)
792 for x
in self
.shortids
:
793 # We only want the first 6 bytes
794 r
+= struct
.pack("<Q", x
)[0:6]
796 r
+= ser_vector(self
.prefilled_txn
, "serialize_with_witness")
798 r
+= ser_vector(self
.prefilled_txn
)
802 return "P2PHeaderAndShortIDs(header=%s, nonce=%d, shortids_length=%d, shortids=%s, prefilled_txn_length=%d, prefilledtxn=%s" % (repr(self
.header
), self
.nonce
, self
.shortids_length
, repr(self
.shortids
), self
.prefilled_txn_length
, repr(self
.prefilled_txn
))
804 # P2P version of the above that will use witness serialization (for compact
806 class P2PHeaderAndShortWitnessIDs(P2PHeaderAndShortIDs
):
808 return super(P2PHeaderAndShortWitnessIDs
, self
).serialize(with_witness
=True)
810 # Calculate the BIP 152-compact blocks shortid for a given transaction hash
811 def calculate_shortid(k0
, k1
, tx_hash
):
812 expected_shortid
= siphash256(k0
, k1
, tx_hash
)
813 expected_shortid
&= 0x0000ffffffffffff
814 return expected_shortid
816 # This version gets rid of the array lengths, and reinterprets the differential
817 # encoding into indices that can be used for lookup.
818 class HeaderAndShortIDs(object):
819 def __init__(self
, p2pheaders_and_shortids
= None):
820 self
.header
= CBlockHeader()
823 self
.prefilled_txn
= []
824 self
.use_witness
= False
826 if p2pheaders_and_shortids
!= None:
827 self
.header
= p2pheaders_and_shortids
.header
828 self
.nonce
= p2pheaders_and_shortids
.nonce
829 self
.shortids
= p2pheaders_and_shortids
.shortids
831 for x
in p2pheaders_and_shortids
.prefilled_txn
:
832 self
.prefilled_txn
.append(PrefilledTransaction(x
.index
+ last_index
+ 1, x
.tx
))
833 last_index
= self
.prefilled_txn
[-1].index
837 ret
= P2PHeaderAndShortWitnessIDs()
839 ret
= P2PHeaderAndShortIDs()
840 ret
.header
= self
.header
841 ret
.nonce
= self
.nonce
842 ret
.shortids_length
= len(self
.shortids
)
843 ret
.shortids
= self
.shortids
844 ret
.prefilled_txn_length
= len(self
.prefilled_txn
)
845 ret
.prefilled_txn
= []
847 for x
in self
.prefilled_txn
:
848 ret
.prefilled_txn
.append(PrefilledTransaction(x
.index
- last_index
- 1, x
.tx
))
852 def get_siphash_keys(self
):
853 header_nonce
= self
.header
.serialize()
854 header_nonce
+= struct
.pack("<Q", self
.nonce
)
855 hash_header_nonce_as_str
= sha256(header_nonce
)
856 key0
= struct
.unpack("<Q", hash_header_nonce_as_str
[0:8])[0]
857 key1
= struct
.unpack("<Q", hash_header_nonce_as_str
[8:16])[0]
858 return [ key0
, key1
]
860 # Version 2 compact blocks use wtxid in shortids (rather than txid)
861 def initialize_from_block(self
, block
, nonce
=0, prefill_list
= [0], use_witness
= False):
862 self
.header
= CBlockHeader(block
)
864 self
.prefilled_txn
= [ PrefilledTransaction(i
, block
.vtx
[i
]) for i
in prefill_list
]
866 self
.use_witness
= use_witness
867 [k0
, k1
] = self
.get_siphash_keys()
868 for i
in range(len(block
.vtx
)):
869 if i
not in prefill_list
:
870 tx_hash
= block
.vtx
[i
].sha256
872 tx_hash
= block
.vtx
[i
].calc_sha256(with_witness
=True)
873 self
.shortids
.append(calculate_shortid(k0
, k1
, tx_hash
))
876 return "HeaderAndShortIDs(header=%s, nonce=%d, shortids=%s, prefilledtxn=%s" % (repr(self
.header
), self
.nonce
, repr(self
.shortids
), repr(self
.prefilled_txn
))
879 class BlockTransactionsRequest(object):
881 def __init__(self
, blockhash
=0, indexes
= None):
882 self
.blockhash
= blockhash
883 self
.indexes
= indexes
if indexes
!= None else []
885 def deserialize(self
, f
):
886 self
.blockhash
= deser_uint256(f
)
887 indexes_length
= deser_compact_size(f
)
888 for i
in range(indexes_length
):
889 self
.indexes
.append(deser_compact_size(f
))
893 r
+= ser_uint256(self
.blockhash
)
894 r
+= ser_compact_size(len(self
.indexes
))
895 for x
in self
.indexes
:
896 r
+= ser_compact_size(x
)
899 # helper to set the differentially encoded indexes from absolute ones
900 def from_absolute(self
, absolute_indexes
):
903 for x
in absolute_indexes
:
904 self
.indexes
.append(x
-last_index
-1)
907 def to_absolute(self
):
908 absolute_indexes
= []
910 for x
in self
.indexes
:
911 absolute_indexes
.append(x
+last_index
+1)
912 last_index
= absolute_indexes
[-1]
913 return absolute_indexes
916 return "BlockTransactionsRequest(hash=%064x indexes=%s)" % (self
.blockhash
, repr(self
.indexes
))
919 class BlockTransactions(object):
921 def __init__(self
, blockhash
=0, transactions
= None):
922 self
.blockhash
= blockhash
923 self
.transactions
= transactions
if transactions
!= None else []
925 def deserialize(self
, f
):
926 self
.blockhash
= deser_uint256(f
)
927 self
.transactions
= deser_vector(f
, CTransaction
)
929 def serialize(self
, with_witness
=False):
931 r
+= ser_uint256(self
.blockhash
)
933 r
+= ser_vector(self
.transactions
, "serialize_with_witness")
935 r
+= ser_vector(self
.transactions
)
939 return "BlockTransactions(hash=%064x transactions=%s)" % (self
.blockhash
, repr(self
.transactions
))
942 # Objects that correspond to messages on the wire
943 class msg_version(object):
947 self
.nVersion
= MY_VERSION
949 self
.nTime
= int(time
.time())
950 self
.addrTo
= CAddress()
951 self
.addrFrom
= CAddress()
952 self
.nNonce
= random
.getrandbits(64)
953 self
.strSubVer
= MY_SUBVERSION
954 self
.nStartingHeight
= -1
955 self
.nRelay
= MY_RELAY
957 def deserialize(self
, f
):
958 self
.nVersion
= struct
.unpack("<i", f
.read(4))[0]
959 if self
.nVersion
== 10300:
961 self
.nServices
= struct
.unpack("<Q", f
.read(8))[0]
962 self
.nTime
= struct
.unpack("<q", f
.read(8))[0]
963 self
.addrTo
= CAddress()
964 self
.addrTo
.deserialize(f
)
966 if self
.nVersion
>= 106:
967 self
.addrFrom
= CAddress()
968 self
.addrFrom
.deserialize(f
)
969 self
.nNonce
= struct
.unpack("<Q", f
.read(8))[0]
970 self
.strSubVer
= deser_string(f
)
974 self
.strSubVer
= None
975 self
.nStartingHeight
= None
977 if self
.nVersion
>= 209:
978 self
.nStartingHeight
= struct
.unpack("<i", f
.read(4))[0]
980 self
.nStartingHeight
= None
982 if self
.nVersion
>= 70001:
983 # Relay field is optional for version 70001 onwards
985 self
.nRelay
= struct
.unpack("<b", f
.read(1))[0]
993 r
+= struct
.pack("<i", self
.nVersion
)
994 r
+= struct
.pack("<Q", self
.nServices
)
995 r
+= struct
.pack("<q", self
.nTime
)
996 r
+= self
.addrTo
.serialize()
997 r
+= self
.addrFrom
.serialize()
998 r
+= struct
.pack("<Q", self
.nNonce
)
999 r
+= ser_string(self
.strSubVer
)
1000 r
+= struct
.pack("<i", self
.nStartingHeight
)
1001 r
+= struct
.pack("<b", self
.nRelay
)
1005 return 'msg_version(nVersion=%i nServices=%i nTime=%s addrTo=%s addrFrom=%s nNonce=0x%016X strSubVer=%s nStartingHeight=%i nRelay=%i)' \
1006 % (self
.nVersion
, self
.nServices
, time
.ctime(self
.nTime
),
1007 repr(self
.addrTo
), repr(self
.addrFrom
), self
.nNonce
,
1008 self
.strSubVer
, self
.nStartingHeight
, self
.nRelay
)
1011 class msg_verack(object):
1017 def deserialize(self
, f
):
1020 def serialize(self
):
1024 return "msg_verack()"
1027 class msg_addr(object):
1033 def deserialize(self
, f
):
1034 self
.addrs
= deser_vector(f
, CAddress
)
1036 def serialize(self
):
1037 return ser_vector(self
.addrs
)
1040 return "msg_addr(addrs=%s)" % (repr(self
.addrs
))
1043 class msg_alert(object):
1047 self
.alert
= CAlert()
1049 def deserialize(self
, f
):
1050 self
.alert
= CAlert()
1051 self
.alert
.deserialize(f
)
1053 def serialize(self
):
1055 r
+= self
.alert
.serialize()
1059 return "msg_alert(alert=%s)" % (repr(self
.alert
), )
1062 class msg_inv(object):
1065 def __init__(self
, inv
=None):
1071 def deserialize(self
, f
):
1072 self
.inv
= deser_vector(f
, CInv
)
1074 def serialize(self
):
1075 return ser_vector(self
.inv
)
1078 return "msg_inv(inv=%s)" % (repr(self
.inv
))
1081 class msg_getdata(object):
1082 command
= b
"getdata"
1084 def __init__(self
, inv
=None):
1085 self
.inv
= inv
if inv
!= None else []
1087 def deserialize(self
, f
):
1088 self
.inv
= deser_vector(f
, CInv
)
1090 def serialize(self
):
1091 return ser_vector(self
.inv
)
1094 return "msg_getdata(inv=%s)" % (repr(self
.inv
))
1097 class msg_getblocks(object):
1098 command
= b
"getblocks"
1101 self
.locator
= CBlockLocator()
1104 def deserialize(self
, f
):
1105 self
.locator
= CBlockLocator()
1106 self
.locator
.deserialize(f
)
1107 self
.hashstop
= deser_uint256(f
)
1109 def serialize(self
):
1111 r
+= self
.locator
.serialize()
1112 r
+= ser_uint256(self
.hashstop
)
1116 return "msg_getblocks(locator=%s hashstop=%064x)" \
1117 % (repr(self
.locator
), self
.hashstop
)
1120 class msg_tx(object):
1123 def __init__(self
, tx
=CTransaction()):
1126 def deserialize(self
, f
):
1127 self
.tx
.deserialize(f
)
1129 def serialize(self
):
1130 return self
.tx
.serialize_without_witness()
1133 return "msg_tx(tx=%s)" % (repr(self
.tx
))
1135 class msg_witness_tx(msg_tx
):
1137 def serialize(self
):
1138 return self
.tx
.serialize_with_witness()
1141 class msg_block(object):
1144 def __init__(self
, block
=None):
1146 self
.block
= CBlock()
1150 def deserialize(self
, f
):
1151 self
.block
.deserialize(f
)
1153 def serialize(self
):
1154 return self
.block
.serialize()
1157 return "msg_block(block=%s)" % (repr(self
.block
))
1159 # for cases where a user needs tighter control over what is sent over the wire
1160 # note that the user must supply the name of the command, and the data
1161 class msg_generic(object):
1162 def __init__(self
, command
, data
=None):
1163 self
.command
= command
1166 def serialize(self
):
1170 return "msg_generic()"
1172 class msg_witness_block(msg_block
):
1174 def serialize(self
):
1175 r
= self
.block
.serialize(with_witness
=True)
1178 class msg_getaddr(object):
1179 command
= b
"getaddr"
1184 def deserialize(self
, f
):
1187 def serialize(self
):
1191 return "msg_getaddr()"
1194 class msg_ping_prebip31(object):
1200 def deserialize(self
, f
):
1203 def serialize(self
):
1207 return "msg_ping() (pre-bip31)"
1210 class msg_ping(object):
1213 def __init__(self
, nonce
=0):
1216 def deserialize(self
, f
):
1217 self
.nonce
= struct
.unpack("<Q", f
.read(8))[0]
1219 def serialize(self
):
1221 r
+= struct
.pack("<Q", self
.nonce
)
1225 return "msg_ping(nonce=%08x)" % self
.nonce
1228 class msg_pong(object):
1231 def __init__(self
, nonce
=0):
1234 def deserialize(self
, f
):
1235 self
.nonce
= struct
.unpack("<Q", f
.read(8))[0]
1237 def serialize(self
):
1239 r
+= struct
.pack("<Q", self
.nonce
)
1243 return "msg_pong(nonce=%08x)" % self
.nonce
1246 class msg_mempool(object):
1247 command
= b
"mempool"
1252 def deserialize(self
, f
):
1255 def serialize(self
):
1259 return "msg_mempool()"
1261 class msg_sendheaders(object):
1262 command
= b
"sendheaders"
1267 def deserialize(self
, f
):
1270 def serialize(self
):
1274 return "msg_sendheaders()"
1277 # getheaders message has
1280 # hash_stop (hash of last desired block header, 0 to get as many as possible)
1281 class msg_getheaders(object):
1282 command
= b
"getheaders"
1285 self
.locator
= CBlockLocator()
1288 def deserialize(self
, f
):
1289 self
.locator
= CBlockLocator()
1290 self
.locator
.deserialize(f
)
1291 self
.hashstop
= deser_uint256(f
)
1293 def serialize(self
):
1295 r
+= self
.locator
.serialize()
1296 r
+= ser_uint256(self
.hashstop
)
1300 return "msg_getheaders(locator=%s, stop=%064x)" \
1301 % (repr(self
.locator
), self
.hashstop
)
1304 # headers message has
1305 # <count> <vector of block headers>
1306 class msg_headers(object):
1307 command
= b
"headers"
1312 def deserialize(self
, f
):
1313 # comment in bitcoind indicates these should be deserialized as blocks
1314 blocks
= deser_vector(f
, CBlock
)
1316 self
.headers
.append(CBlockHeader(x
))
1318 def serialize(self
):
1319 blocks
= [CBlock(x
) for x
in self
.headers
]
1320 return ser_vector(blocks
)
1323 return "msg_headers(headers=%s)" % repr(self
.headers
)
1326 class msg_reject(object):
1328 REJECT_MALFORMED
= 1
1336 def deserialize(self
, f
):
1337 self
.message
= deser_string(f
)
1338 self
.code
= struct
.unpack("<B", f
.read(1))[0]
1339 self
.reason
= deser_string(f
)
1340 if (self
.code
!= self
.REJECT_MALFORMED
and
1341 (self
.message
== b
"block" or self
.message
== b
"tx")):
1342 self
.data
= deser_uint256(f
)
1344 def serialize(self
):
1345 r
= ser_string(self
.message
)
1346 r
+= struct
.pack("<B", self
.code
)
1347 r
+= ser_string(self
.reason
)
1348 if (self
.code
!= self
.REJECT_MALFORMED
and
1349 (self
.message
== b
"block" or self
.message
== b
"tx")):
1350 r
+= ser_uint256(self
.data
)
1354 return "msg_reject: %s %d %s [%064x]" \
1355 % (self
.message
, self
.code
, self
.reason
, self
.data
)
1358 def wait_until(predicate
, *, attempts
=float('inf'), timeout
=float('inf')):
1362 while attempt
< attempts
and elapsed
< timeout
:
1372 class msg_feefilter(object):
1373 command
= b
"feefilter"
1375 def __init__(self
, feerate
=0):
1376 self
.feerate
= feerate
1378 def deserialize(self
, f
):
1379 self
.feerate
= struct
.unpack("<Q", f
.read(8))[0]
1381 def serialize(self
):
1383 r
+= struct
.pack("<Q", self
.feerate
)
1387 return "msg_feefilter(feerate=%08x)" % self
.feerate
1389 class msg_sendcmpct(object):
1390 command
= b
"sendcmpct"
1393 self
.announce
= False
1396 def deserialize(self
, f
):
1397 self
.announce
= struct
.unpack("<?", f
.read(1))[0]
1398 self
.version
= struct
.unpack("<Q", f
.read(8))[0]
1400 def serialize(self
):
1402 r
+= struct
.pack("<?", self
.announce
)
1403 r
+= struct
.pack("<Q", self
.version
)
1407 return "msg_sendcmpct(announce=%s, version=%lu)" % (self
.announce
, self
.version
)
1409 class msg_cmpctblock(object):
1410 command
= b
"cmpctblock"
1412 def __init__(self
, header_and_shortids
= None):
1413 self
.header_and_shortids
= header_and_shortids
1415 def deserialize(self
, f
):
1416 self
.header_and_shortids
= P2PHeaderAndShortIDs()
1417 self
.header_and_shortids
.deserialize(f
)
1419 def serialize(self
):
1421 r
+= self
.header_and_shortids
.serialize()
1425 return "msg_cmpctblock(HeaderAndShortIDs=%s)" % repr(self
.header_and_shortids
)
1427 class msg_getblocktxn(object):
1428 command
= b
"getblocktxn"
1431 self
.block_txn_request
= None
1433 def deserialize(self
, f
):
1434 self
.block_txn_request
= BlockTransactionsRequest()
1435 self
.block_txn_request
.deserialize(f
)
1437 def serialize(self
):
1439 r
+= self
.block_txn_request
.serialize()
1443 return "msg_getblocktxn(block_txn_request=%s)" % (repr(self
.block_txn_request
))
1445 class msg_blocktxn(object):
1446 command
= b
"blocktxn"
1449 self
.block_transactions
= BlockTransactions()
1451 def deserialize(self
, f
):
1452 self
.block_transactions
.deserialize(f
)
1454 def serialize(self
):
1456 r
+= self
.block_transactions
.serialize()
1460 return "msg_blocktxn(block_transactions=%s)" % (repr(self
.block_transactions
))
1462 class msg_witness_blocktxn(msg_blocktxn
):
1463 def serialize(self
):
1465 r
+= self
.block_transactions
.serialize(with_witness
=True)
1468 # This is what a callback should look like for NodeConn
1469 # Reimplement the on_* functions to provide handling for events
1470 class NodeConnCB(object):
1472 self
.verack_received
= False
1473 # deliver_sleep_time is helpful for debugging race conditions in p2p
1474 # tests; it causes message delivery to sleep for the specified time
1475 # before acquiring the global lock and delivering the next message.
1476 self
.deliver_sleep_time
= None
1477 # Remember the services our peer has advertised
1478 self
.peer_services
= None
1479 self
.connection
= None
1480 self
.ping_counter
= 1
1481 self
.last_pong
= msg_pong()
1483 def deliver(self
, conn
, message
):
1484 deliver_sleep
= self
.get_deliver_sleep_time()
1485 if deliver_sleep
is not None:
1486 time
.sleep(deliver_sleep
)
1489 getattr(self
, 'on_' + message
.command
.decode('ascii'))(conn
, message
)
1491 logger
.exception("ERROR delivering %s" % repr(message
))
1493 def set_deliver_sleep_time(self
, value
):
1495 self
.deliver_sleep_time
= value
1497 def get_deliver_sleep_time(self
):
1499 return self
.deliver_sleep_time
1501 # Callbacks which can be overridden by subclasses
1502 #################################################
1504 def on_addr(self
, conn
, message
): pass
1505 def on_alert(self
, conn
, message
): pass
1506 def on_block(self
, conn
, message
): pass
1507 def on_blocktxn(self
, conn
, message
): pass
1508 def on_close(self
, conn
): pass
1509 def on_cmpctblock(self
, conn
, message
): pass
1510 def on_feefilter(self
, conn
, message
): pass
1511 def on_getaddr(self
, conn
, message
): pass
1512 def on_getblocks(self
, conn
, message
): pass
1513 def on_getblocktxn(self
, conn
, message
): pass
1514 def on_getdata(self
, conn
, message
): pass
1515 def on_getheaders(self
, conn
, message
): pass
1516 def on_headers(self
, conn
, message
): pass
1517 def on_mempool(self
, conn
): pass
1518 def on_open(self
, conn
): pass
1519 def on_reject(self
, conn
, message
): pass
1520 def on_sendcmpct(self
, conn
, message
): pass
1521 def on_sendheaders(self
, conn
, message
): pass
1522 def on_tx(self
, conn
, message
): pass
1524 def on_inv(self
, conn
, message
):
1525 want
= msg_getdata()
1526 for i
in message
.inv
:
1530 conn
.send_message(want
)
1532 def on_ping(self
, conn
, message
):
1533 if conn
.ver_send
> BIP0031_VERSION
:
1534 conn
.send_message(msg_pong(message
.nonce
))
1536 def on_pong(self
, conn
, message
):
1537 self
.last_pong
= message
1539 def on_verack(self
, conn
, message
):
1540 conn
.ver_recv
= conn
.ver_send
1541 self
.verack_received
= True
1543 def on_version(self
, conn
, message
):
1544 if message
.nVersion
>= 209:
1545 conn
.send_message(msg_verack())
1546 conn
.ver_send
= min(MY_VERSION
, message
.nVersion
)
1547 if message
.nVersion
< 209:
1548 conn
.ver_recv
= conn
.ver_send
1549 conn
.nServices
= message
.nServices
1554 def add_connection(self
, conn
):
1555 self
.connection
= conn
1557 # Wrapper for the NodeConn's send_message function
1558 def send_message(self
, message
):
1559 self
.connection
.send_message(message
)
1561 def send_and_ping(self
, message
):
1562 self
.send_message(message
)
1563 self
.sync_with_ping()
1565 # Sync up with the node
1566 def sync_with_ping(self
, timeout
=60):
1567 def received_pong():
1568 return (self
.last_pong
.nonce
== self
.ping_counter
)
1569 self
.send_message(msg_ping(nonce
=self
.ping_counter
))
1570 success
= wait_until(received_pong
, timeout
=timeout
)
1572 logger
.error("sync_with_ping failed!")
1573 raise AssertionError("sync_with_ping failed!")
1574 self
.ping_counter
+= 1
1578 # Spin until verack message is received from the node.
1579 # Tests may want to use this as a signal that the test can begin.
1580 # This can be called from the testing thread, so it needs to acquire the
1582 def wait_for_verack(self
):
1585 if self
.verack_received
:
1589 # The actual NodeConn class
1590 # This class provides an interface for a p2p connection to a specified node
1591 class NodeConn(asyncore
.dispatcher
):
1593 b
"version": msg_version
,
1594 b
"verack": msg_verack
,
1596 b
"alert": msg_alert
,
1598 b
"getdata": msg_getdata
,
1599 b
"getblocks": msg_getblocks
,
1601 b
"block": msg_block
,
1602 b
"getaddr": msg_getaddr
,
1605 b
"headers": msg_headers
,
1606 b
"getheaders": msg_getheaders
,
1607 b
"reject": msg_reject
,
1608 b
"mempool": msg_mempool
,
1609 b
"feefilter": msg_feefilter
,
1610 b
"sendheaders": msg_sendheaders
,
1611 b
"sendcmpct": msg_sendcmpct
,
1612 b
"cmpctblock": msg_cmpctblock
,
1613 b
"getblocktxn": msg_getblocktxn
,
1614 b
"blocktxn": msg_blocktxn
1617 "mainnet": b
"\xf9\xbe\xb4\xd9", # mainnet
1618 "testnet3": b
"\x0b\x11\x09\x07", # testnet3
1619 "regtest": b
"\xfa\xbf\xb5\xda", # regtest
1622 def __init__(self
, dstaddr
, dstport
, rpc
, callback
, net
="regtest", services
=NODE_NETWORK
, send_version
=True):
1623 asyncore
.dispatcher
.__init
__(self
, map=mininode_socket_map
)
1624 self
.dstaddr
= dstaddr
1625 self
.dstport
= dstport
1626 self
.create_socket(socket
.AF_INET
, socket
.SOCK_STREAM
)
1632 self
.state
= "connecting"
1635 self
.disconnect
= False
1639 # stuff version msg into sendbuf
1641 vt
.nServices
= services
1642 vt
.addrTo
.ip
= self
.dstaddr
1643 vt
.addrTo
.port
= self
.dstport
1644 vt
.addrFrom
.ip
= "0.0.0.0"
1645 vt
.addrFrom
.port
= 0
1646 self
.send_message(vt
, True)
1648 logger
.info('Connecting to Bitcoin Node: %s:%d' % (self
.dstaddr
, self
.dstport
))
1651 self
.connect((dstaddr
, dstport
))
1656 def handle_connect(self
):
1657 if self
.state
!= "connected":
1658 logger
.debug("Connected & Listening: %s:%d" % (self
.dstaddr
, self
.dstport
))
1659 self
.state
= "connected"
1660 self
.cb
.on_open(self
)
1662 def handle_close(self
):
1663 logger
.debug("Closing connection to: %s:%d" % (self
.dstaddr
, self
.dstport
))
1664 self
.state
= "closed"
1671 self
.cb
.on_close(self
)
1673 def handle_read(self
):
1687 pre_connection
= self
.state
== "connecting"
1688 length
= len(self
.sendbuf
)
1689 return (length
> 0 or pre_connection
)
1691 def handle_write(self
):
1693 # asyncore does not expose socket connection, only the first read/write
1694 # event, thus we must check connection manually here to know when we
1696 if self
.state
== "connecting":
1697 self
.handle_connect()
1698 if not self
.writable():
1702 sent
= self
.send(self
.sendbuf
)
1706 self
.sendbuf
= self
.sendbuf
[sent
:]
1711 if len(self
.recvbuf
) < 4:
1713 if self
.recvbuf
[:4] != self
.MAGIC_BYTES
[self
.network
]:
1714 raise ValueError("got garbage %s" % repr(self
.recvbuf
))
1715 if self
.ver_recv
< 209:
1716 if len(self
.recvbuf
) < 4 + 12 + 4:
1718 command
= self
.recvbuf
[4:4+12].split(b
"\x00", 1)[0]
1719 msglen
= struct
.unpack("<i", self
.recvbuf
[4+12:4+12+4])[0]
1721 if len(self
.recvbuf
) < 4 + 12 + 4 + msglen
:
1723 msg
= self
.recvbuf
[4+12+4:4+12+4+msglen
]
1724 self
.recvbuf
= self
.recvbuf
[4+12+4+msglen
:]
1726 if len(self
.recvbuf
) < 4 + 12 + 4 + 4:
1728 command
= self
.recvbuf
[4:4+12].split(b
"\x00", 1)[0]
1729 msglen
= struct
.unpack("<i", self
.recvbuf
[4+12:4+12+4])[0]
1730 checksum
= self
.recvbuf
[4+12+4:4+12+4+4]
1731 if len(self
.recvbuf
) < 4 + 12 + 4 + 4 + msglen
:
1733 msg
= self
.recvbuf
[4+12+4+4:4+12+4+4+msglen
]
1736 if checksum
!= h
[:4]:
1737 raise ValueError("got bad checksum " + repr(self
.recvbuf
))
1738 self
.recvbuf
= self
.recvbuf
[4+12+4+4+msglen
:]
1739 if command
in self
.messagemap
:
1741 t
= self
.messagemap
[command
]()
1745 logger
.warning("Received unknown command from %s:%d: '%s' %s" % (self
.dstaddr
, self
.dstport
, command
, repr(msg
)))
1746 except Exception as e
:
1747 logger
.exception('got_data:', repr(e
))
1749 def send_message(self
, message
, pushbuf
=False):
1750 if self
.state
!= "connected" and not pushbuf
:
1751 raise IOError('Not connected, no pushbuf')
1752 logger
.debug("Send message to %s:%d: %s" % (self
.dstaddr
, self
.dstport
, repr(message
)))
1753 command
= message
.command
1754 data
= message
.serialize()
1755 tmsg
= self
.MAGIC_BYTES
[self
.network
]
1757 tmsg
+= b
"\x00" * (12 - len(command
))
1758 tmsg
+= struct
.pack("<I", len(data
))
1759 if self
.ver_send
>= 209:
1765 self
.sendbuf
+= tmsg
1766 self
.last_sent
= time
.time()
1768 def got_message(self
, message
):
1769 if message
.command
== b
"version":
1770 if message
.nVersion
<= BIP0031_VERSION
:
1771 self
.messagemap
[b
'ping'] = msg_ping_prebip31
1772 if self
.last_sent
+ 30 * 60 < time
.time():
1773 self
.send_message(self
.messagemap
[b
'ping']())
1774 logger
.debug("Received message from %s:%d: %s" % (self
.dstaddr
, self
.dstport
, repr(message
)))
1775 self
.cb
.deliver(self
, message
)
1777 def disconnect_node(self
):
1778 self
.disconnect
= True
1781 class NetworkThread(Thread
):
1783 while mininode_socket_map
:
1784 # We check for whether to disconnect outside of the asyncore
1785 # loop to workaround the behavior of asyncore when using
1788 for fd
, obj
in mininode_socket_map
.items():
1790 disconnected
.append(obj
)
1791 [ obj
.handle_close() for obj
in disconnected
]
1792 asyncore
.loop(0.1, use_poll
=True, map=mininode_socket_map
, count
=1)
1795 # An exception we can raise if we detect a potential disconnect
1796 # (p2p or rpc) before the test is complete
1797 class EarlyDisconnectError(Exception):
1798 def __init__(self
, value
):
1802 return repr(self
.value
)