Dash Core  0.12.2.1
P2P Digital Currency
mininode.py
Go to the documentation of this file.
1 # mininode.py - Dash P2P network half-a-node
2 #
3 # Distributed under the MIT/X11 software license, see the accompanying
4 # file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 #
6 # This python code was modified from ArtForz' public domain half-a-node, as
7 # found in the mini-node branch of http://github.com/jgarzik/pynode.
8 #
9 # NodeConn: an object which manages p2p connectivity to a dash node
10 # NodeConnCB: a base class that describes the interface for receiving
11 # callbacks with network messages from a NodeConn
12 # CBlock, CTransaction, CBlockHeader, CTxIn, CTxOut, etc....:
13 # data structures that should map to corresponding structures in
14 # dash/primitives
15 # msg_block, msg_tx, msg_headers, etc.:
16 # data structures that represent network messages
17 # ser_*, deser_*: functions that handle serialization/deserialization
18 
19 
20 import struct
21 import socket
22 import asyncore
23 import time
24 import sys
25 import random
26 from binascii import hexlify, unhexlify
27 from io import BytesIO
28 from codecs import encode
29 import hashlib
30 from threading import RLock
31 from threading import Thread
32 import logging
33 import copy
34 
35 import dash_hash
36 
37 BIP0031_VERSION = 60000
38 MY_VERSION = 70206 # current MIN_PEER_PROTO_VERSION
39 MY_SUBVERSION = b"/python-mininode-tester:0.0.2/"
40 
41 MAX_INV_SZ = 50000
42 MAX_BLOCK_SIZE = 1000000
43 
44 COIN = 100000000L # 1 btc in satoshis
45 
46 # Keep our own socket map for asyncore, so that we can track disconnects
47 # ourselves (to workaround an issue with closing an asyncore socket when
48 # using select)
49 mininode_socket_map = dict()
50 
51 # One lock for synchronizing all data access between the networking thread (see
52 # NetworkThread below) and the thread running the test logic. For simplicity,
53 # NodeConn acquires this lock whenever delivering a message to to a NodeConnCB,
54 # and whenever adding anything to the send buffer (in send_message()). This
55 # lock should be acquired in the thread running the test logic to synchronize
56 # access to any data shared with the NodeConnCB or NodeConn.
57 mininode_lock = RLock()
58 
59 # Serialization/deserialization tools
60 def sha256(s):
61  return hashlib.new('sha256', s).digest()
62 
63 
64 def hash256(s):
65  return sha256(sha256(s))
66 
67 def dashhash(s):
68  return dash_hash.getPoWHash(s)
69 
70 def deser_string(f):
71  nit = struct.unpack("<B", f.read(1))[0]
72  if nit == 253:
73  nit = struct.unpack("<H", f.read(2))[0]
74  elif nit == 254:
75  nit = struct.unpack("<I", f.read(4))[0]
76  elif nit == 255:
77  nit = struct.unpack("<Q", f.read(8))[0]
78  return f.read(nit)
79 
80 
81 def ser_string(s):
82  if len(s) < 253:
83  return struct.pack("B", len(s)) + s
84  elif len(s) < 0x10000:
85  return struct.pack("<BH", 253, len(s)) + s
86  elif len(s) < 0x100000000L:
87  return struct.pack("<BI", 254, len(s)) + s
88  return struct.pack("<BQ", 255, len(s)) + s
89 
90 
92  r = 0L
93  for i in xrange(8):
94  t = struct.unpack("<I", f.read(4))[0]
95  r += t << (i * 32)
96  return r
97 
98 
99 def ser_uint256(u):
100  rs = b""
101  for i in xrange(8):
102  rs += struct.pack("<I", u & 0xFFFFFFFFL)
103  u >>= 32
104  return rs
105 
106 
108  r = 0L
109  t = struct.unpack("<IIIIIIII", s[:32])
110  for i in xrange(8):
111  r += t[i] << (i * 32)
112  return r
113 
114 
116  nbytes = (c >> 24) & 0xFF
117  v = (c & 0xFFFFFFL) << (8 * (nbytes - 3))
118  return v
119 
120 
121 def deser_vector(f, c):
122  nit = struct.unpack("<B", f.read(1))[0]
123  if nit == 253:
124  nit = struct.unpack("<H", f.read(2))[0]
125  elif nit == 254:
126  nit = struct.unpack("<I", f.read(4))[0]
127  elif nit == 255:
128  nit = struct.unpack("<Q", f.read(8))[0]
129  r = []
130  for i in xrange(nit):
131  t = c()
132  t.deserialize(f)
133  r.append(t)
134  return r
135 
136 
137 def ser_vector(l):
138  r = b""
139  if len(l) < 253:
140  r = struct.pack("B", len(l))
141  elif len(l) < 0x10000:
142  r = struct.pack("<BH", 253, len(l))
143  elif len(l) < 0x100000000L:
144  r = struct.pack("<BI", 254, len(l))
145  else:
146  r = struct.pack("<BQ", 255, len(l))
147  for i in l:
148  r += i.serialize()
149  return r
150 
151 
153  nit = struct.unpack("<B", f.read(1))[0]
154  if nit == 253:
155  nit = struct.unpack("<H", f.read(2))[0]
156  elif nit == 254:
157  nit = struct.unpack("<I", f.read(4))[0]
158  elif nit == 255:
159  nit = struct.unpack("<Q", f.read(8))[0]
160  r = []
161  for i in xrange(nit):
162  t = deser_uint256(f)
163  r.append(t)
164  return r
165 
166 
168  r = b""
169  if len(l) < 253:
170  r = struct.pack("B", len(l))
171  elif len(l) < 0x10000:
172  r = struct.pack("<BH", 253, len(l))
173  elif len(l) < 0x100000000L:
174  r = struct.pack("<BI", 254, len(l))
175  else:
176  r = struct.pack("<BQ", 255, len(l))
177  for i in l:
178  r += ser_uint256(i)
179  return r
180 
181 
183  nit = struct.unpack("<B", f.read(1))[0]
184  if nit == 253:
185  nit = struct.unpack("<H", f.read(2))[0]
186  elif nit == 254:
187  nit = struct.unpack("<I", f.read(4))[0]
188  elif nit == 255:
189  nit = struct.unpack("<Q", f.read(8))[0]
190  r = []
191  for i in xrange(nit):
192  t = deser_string(f)
193  r.append(t)
194  return r
195 
196 
198  r = b""
199  if len(l) < 253:
200  r = struct.pack("B", len(l))
201  elif len(l) < 0x10000:
202  r = struct.pack("<BH", 253, len(l))
203  elif len(l) < 0x100000000L:
204  r = struct.pack("<BI", 254, len(l))
205  else:
206  r = struct.pack("<BQ", 255, len(l))
207  for sv in l:
208  r += ser_string(sv)
209  return r
210 
211 
213  nit = struct.unpack("<B", f.read(1))[0]
214  if nit == 253:
215  nit = struct.unpack("<H", f.read(2))[0]
216  elif nit == 254:
217  nit = struct.unpack("<I", f.read(4))[0]
218  elif nit == 255:
219  nit = struct.unpack("<Q", f.read(8))[0]
220  r = []
221  for i in xrange(nit):
222  t = struct.unpack("<i", f.read(4))[0]
223  r.append(t)
224  return r
225 
226 
228  r = b""
229  if len(l) < 253:
230  r = struct.pack("B", len(l))
231  elif len(l) < 0x10000:
232  r = struct.pack("<BH", 253, len(l))
233  elif len(l) < 0x100000000L:
234  r = struct.pack("<BI", 254, len(l))
235  else:
236  r = struct.pack("<BQ", 255, len(l))
237  for i in l:
238  r += struct.pack("<i", i)
239  return r
240 
241 # Deserialize from a hex string representation (eg from RPC)
242 def FromHex(obj, hex_string):
243  obj.deserialize(BytesIO(unhexlify(hex_string.encode('ascii'))))
244  return obj
245 
246 # Convert a binary-serializable object to hex (eg for submission via RPC)
247 def ToHex(obj):
248  return hexlify(obj.serialize()).decode('ascii')
249 
250 # Objects that map to dashd objects, which can be serialized/deserialized
251 
252 class CAddress(object):
253  def __init__(self):
254  self.nServices = 1
255  self.pchReserved = b"\x00" * 10 + b"\xff" * 2
256  self.ip = "0.0.0.0"
257  self.port = 0
258 
259  def deserialize(self, f):
260  self.nServices = struct.unpack("<Q", f.read(8))[0]
261  self.pchReserved = f.read(12)
262  self.ip = socket.inet_ntoa(f.read(4))
263  self.port = struct.unpack(">H", f.read(2))[0]
264 
265  def serialize(self):
266  r = b""
267  r += struct.pack("<Q", self.nServices)
268  r += self.pchReserved
269  r += socket.inet_aton(self.ip)
270  r += struct.pack(">H", self.port)
271  return r
272 
273  def __repr__(self):
274  return "CAddress(nServices=%i ip=%s port=%i)" % (self.nServices,
275  self.ip, self.port)
276 
277 
278 class CInv(object):
279  typemap = {
280  0: "Error",
281  1: "TX",
282  2: "Block"}
283 
284  def __init__(self, t=0, h=0L):
285  self.type = t
286  self.hash = h
287 
288  def deserialize(self, f):
289  self.type = struct.unpack("<i", f.read(4))[0]
290  self.hash = deser_uint256(f)
291 
292  def serialize(self):
293  r = b""
294  r += struct.pack("<i", self.type)
295  r += ser_uint256(self.hash)
296  return r
297 
298  def __repr__(self):
299  return "CInv(type=%s hash=%064x)" \
300  % (self.typemap[self.type], self.hash)
301 
302 
303 class CBlockLocator(object):
304  def __init__(self):
305  self.nVersion = MY_VERSION
306  self.vHave = []
307 
308  def deserialize(self, f):
309  self.nVersion = struct.unpack("<i", f.read(4))[0]
310  self.vHave = deser_uint256_vector(f)
311 
312  def serialize(self):
313  r = b""
314  r += struct.pack("<i", self.nVersion)
315  r += ser_uint256_vector(self.vHave)
316  return r
317 
318  def __repr__(self):
319  return "CBlockLocator(nVersion=%i vHave=%s)" \
320  % (self.nVersion, repr(self.vHave))
321 
322 
323 class COutPoint(object):
324  def __init__(self, hash=0, n=0):
325  self.hash = hash
326  self.n = n
327 
328  def deserialize(self, f):
329  self.hash = deser_uint256(f)
330  self.n = struct.unpack("<I", f.read(4))[0]
331 
332  def serialize(self):
333  r = b""
334  r += ser_uint256(self.hash)
335  r += struct.pack("<I", self.n)
336  return r
337 
338  def __repr__(self):
339  return "COutPoint(hash=%064x n=%i)" % (self.hash, self.n)
340 
341 
342 class CTxIn(object):
343  def __init__(self, outpoint=None, scriptSig=b"", nSequence=0):
344  if outpoint is None:
346  else:
347  self.prevout = outpoint
348  self.scriptSig = scriptSig
349  self.nSequence = nSequence
350 
351  def deserialize(self, f):
352  self.prevout = COutPoint()
353  self.prevout.deserialize(f)
354  self.scriptSig = deser_string(f)
355  self.nSequence = struct.unpack("<I", f.read(4))[0]
356 
357  def serialize(self):
358  r = b""
359  r += self.prevout.serialize()
360  r += ser_string(self.scriptSig)
361  r += struct.pack("<I", self.nSequence)
362  return r
363 
364  def __repr__(self):
365  return "CTxIn(prevout=%s scriptSig=%s nSequence=%i)" \
366  % (repr(self.prevout), hexlify(self.scriptSig),
367  self.nSequence)
368 
369 
370 class CTxOut(object):
371  def __init__(self, nValue=0, scriptPubKey=b""):
372  self.nValue = nValue
373  self.scriptPubKey = scriptPubKey
374 
375  def deserialize(self, f):
376  self.nValue = struct.unpack("<q", f.read(8))[0]
377  self.scriptPubKey = deser_string(f)
378 
379  def serialize(self):
380  r = b""
381  r += struct.pack("<q", self.nValue)
382  r += ser_string(self.scriptPubKey)
383  return r
384 
385  def __repr__(self):
386  return "CTxOut(nValue=%i.%08i scriptPubKey=%s)" \
387  % (self.nValue // COIN, self.nValue % COIN,
388  hexlify(self.scriptPubKey))
389 
390 
391 class CTransaction(object):
392  def __init__(self, tx=None):
393  if tx is None:
394  self.nVersion = 1
395  self.vin = []
396  self.vout = []
397  self.nLockTime = 0
398  self.sha256 = None
399  self.hash = None
400  else:
401  self.nVersion = tx.nVersion
402  self.vin = copy.deepcopy(tx.vin)
403  self.vout = copy.deepcopy(tx.vout)
404  self.nLockTime = tx.nLockTime
405  self.sha256 = None
406  self.hash = None
407 
408  def deserialize(self, f):
409  self.nVersion = struct.unpack("<i", f.read(4))[0]
410  self.vin = deser_vector(f, CTxIn)
411  self.vout = deser_vector(f, CTxOut)
412  self.nLockTime = struct.unpack("<I", f.read(4))[0]
413  self.sha256 = None
414  self.hash = None
415 
416  def serialize(self):
417  r = b""
418  r += struct.pack("<i", self.nVersion)
419  r += ser_vector(self.vin)
420  r += ser_vector(self.vout)
421  r += struct.pack("<I", self.nLockTime)
422  return r
423 
424  def rehash(self):
425  self.sha256 = None
426  self.calc_sha256()
427 
428  def calc_sha256(self):
429  if self.sha256 is None:
430  self.sha256 = uint256_from_str(hash256(self.serialize()))
431  self.hash = encode(hash256(self.serialize())[::-1], 'hex_codec').decode('ascii')
432 
433  def is_valid(self):
434  self.calc_sha256()
435  for tout in self.vout:
436  if tout.nValue < 0 or tout.nValue > 21000000 * COIN:
437  return False
438  return True
439 
440  def __repr__(self):
441  return "CTransaction(nVersion=%i vin=%s vout=%s nLockTime=%i)" \
442  % (self.nVersion, repr(self.vin), repr(self.vout), self.nLockTime)
443 
444 
445 class CBlockHeader(object):
446  def __init__(self, header=None):
447  if header is None:
448  self.set_null()
449  else:
450  self.nVersion = header.nVersion
451  self.hashPrevBlock = header.hashPrevBlock
452  self.hashMerkleRoot = header.hashMerkleRoot
453  self.nTime = header.nTime
454  self.nBits = header.nBits
455  self.nNonce = header.nNonce
456  self.sha256 = header.sha256
457  self.hash = header.hash
458  self.calc_sha256()
459 
460  def set_null(self):
461  self.nVersion = 1
462  self.hashPrevBlock = 0
463  self.hashMerkleRoot = 0
464  self.nTime = 0
465  self.nBits = 0
466  self.nNonce = 0
467  self.sha256 = None
468  self.hash = None
469 
470  def deserialize(self, f):
471  self.nVersion = struct.unpack("<i", f.read(4))[0]
472  self.hashPrevBlock = deser_uint256(f)
473  self.hashMerkleRoot = deser_uint256(f)
474  self.nTime = struct.unpack("<I", f.read(4))[0]
475  self.nBits = struct.unpack("<I", f.read(4))[0]
476  self.nNonce = struct.unpack("<I", f.read(4))[0]
477  self.sha256 = None
478  self.hash = None
479 
480  def serialize(self):
481  r = b""
482  r += struct.pack("<i", self.nVersion)
483  r += ser_uint256(self.hashPrevBlock)
484  r += ser_uint256(self.hashMerkleRoot)
485  r += struct.pack("<I", self.nTime)
486  r += struct.pack("<I", self.nBits)
487  r += struct.pack("<I", self.nNonce)
488  return r
489 
490  def calc_sha256(self):
491  if self.sha256 is None:
492  r = b""
493  r += struct.pack("<i", self.nVersion)
494  r += ser_uint256(self.hashPrevBlock)
495  r += ser_uint256(self.hashMerkleRoot)
496  r += struct.pack("<I", self.nTime)
497  r += struct.pack("<I", self.nBits)
498  r += struct.pack("<I", self.nNonce)
499  self.sha256 = uint256_from_str(dashhash(r))
500  self.hash = encode(dashhash(r)[::-1], 'hex_codec').decode('ascii')
501 
502  def rehash(self):
503  self.sha256 = None
504  self.calc_sha256()
505  return self.sha256
506 
507  def __repr__(self):
508  return "CBlockHeader(nVersion=%i hashPrevBlock=%064x hashMerkleRoot=%064x nTime=%s nBits=%08x nNonce=%08x)" \
509  % (self.nVersion, self.hashPrevBlock, self.hashMerkleRoot,
510  time.ctime(self.nTime), self.nBits, self.nNonce)
511 
512 
514  def __init__(self, header=None):
515  super(CBlock, self).__init__(header)
516  self.vtx = []
517 
518  def deserialize(self, f):
519  super(CBlock, self).deserialize(f)
520  self.vtx = deser_vector(f, CTransaction)
521 
522  def serialize(self):
523  r = b""
524  r += super(CBlock, self).serialize()
525  r += ser_vector(self.vtx)
526  return r
527 
528  def calc_merkle_root(self):
529  hashes = []
530  for tx in self.vtx:
531  tx.calc_sha256()
532  hashes.append(ser_uint256(tx.sha256))
533  while len(hashes) > 1:
534  newhashes = []
535  for i in xrange(0, len(hashes), 2):
536  i2 = min(i+1, len(hashes)-1)
537  newhashes.append(hash256(hashes[i] + hashes[i2]))
538  hashes = newhashes
539  return uint256_from_str(hashes[0])
540 
541  def is_valid(self):
542  self.calc_sha256()
543  target = uint256_from_compact(self.nBits)
544  if self.sha256 > target:
545  return False
546  for tx in self.vtx:
547  if not tx.is_valid():
548  return False
549  if self.calc_merkle_root() != self.hashMerkleRoot:
550  return False
551  return True
552 
553  def solve(self):
554  self.rehash()
555  target = uint256_from_compact(self.nBits)
556  while self.sha256 > target:
557  self.nNonce += 1
558  self.rehash()
559 
560  def __repr__(self):
561  return "CBlock(nVersion=%i hashPrevBlock=%064x hashMerkleRoot=%064x nTime=%s nBits=%08x nNonce=%08x vtx=%s)" \
562  % (self.nVersion, self.hashPrevBlock, self.hashMerkleRoot,
563  time.ctime(self.nTime), self.nBits, self.nNonce, repr(self.vtx))
564 
565 
566 class CUnsignedAlert(object):
567  def __init__(self):
568  self.nVersion = 1
569  self.nRelayUntil = 0
570  self.nExpiration = 0
571  self.nID = 0
572  self.nCancel = 0
573  self.setCancel = []
574  self.nMinVer = 0
575  self.nMaxVer = 0
576  self.setSubVer = []
577  self.nPriority = 0
578  self.strComment = b""
579  self.strStatusBar = b""
580  self.strReserved = b""
581 
582  def deserialize(self, f):
583  self.nVersion = struct.unpack("<i", f.read(4))[0]
584  self.nRelayUntil = struct.unpack("<q", f.read(8))[0]
585  self.nExpiration = struct.unpack("<q", f.read(8))[0]
586  self.nID = struct.unpack("<i", f.read(4))[0]
587  self.nCancel = struct.unpack("<i", f.read(4))[0]
588  self.setCancel = deser_int_vector(f)
589  self.nMinVer = struct.unpack("<i", f.read(4))[0]
590  self.nMaxVer = struct.unpack("<i", f.read(4))[0]
592  self.nPriority = struct.unpack("<i", f.read(4))[0]
593  self.strComment = deser_string(f)
594  self.strStatusBar = deser_string(f)
595  self.strReserved = deser_string(f)
596 
597  def serialize(self):
598  r = b""
599  r += struct.pack("<i", self.nVersion)
600  r += struct.pack("<q", self.nRelayUntil)
601  r += struct.pack("<q", self.nExpiration)
602  r += struct.pack("<i", self.nID)
603  r += struct.pack("<i", self.nCancel)
604  r += ser_int_vector(self.setCancel)
605  r += struct.pack("<i", self.nMinVer)
606  r += struct.pack("<i", self.nMaxVer)
607  r += ser_string_vector(self.setSubVer)
608  r += struct.pack("<i", self.nPriority)
609  r += ser_string(self.strComment)
610  r += ser_string(self.strStatusBar)
611  r += ser_string(self.strReserved)
612  return r
613 
614  def __repr__(self):
615  return "CUnsignedAlert(nVersion %d, nRelayUntil %d, nExpiration %d, nID %d, nCancel %d, nMinVer %d, nMaxVer %d, nPriority %d, strComment %s, strStatusBar %s, strReserved %s)" \
616  % (self.nVersion, self.nRelayUntil, self.nExpiration, self.nID,
617  self.nCancel, self.nMinVer, self.nMaxVer, self.nPriority,
618  self.strComment, self.strStatusBar, self.strReserved)
619 
620 
621 class CAlert(object):
622  def __init__(self):
623  self.vchMsg = b""
624  self.vchSig = b""
625 
626  def deserialize(self, f):
627  self.vchMsg = deser_string(f)
628  self.vchSig = deser_string(f)
629 
630  def serialize(self):
631  r = b""
632  r += ser_string(self.vchMsg)
633  r += ser_string(self.vchSig)
634  return r
635 
636  def __repr__(self):
637  return "CAlert(vchMsg.sz %d, vchSig.sz %d)" \
638  % (len(self.vchMsg), len(self.vchSig))
639 
640 
641 # Objects that correspond to messages on the wire
642 class msg_version(object):
643  command = b"version"
644 
645  def __init__(self):
646  self.nVersion = MY_VERSION
647  self.nServices = 1
648  self.nTime = int(time.time())
649  self.addrTo = CAddress()
651  self.nNonce = random.getrandbits(64)
652  self.strSubVer = MY_SUBVERSION
653  self.nStartingHeight = -1
654 
655  def deserialize(self, f):
656  self.nVersion = struct.unpack("<i", f.read(4))[0]
657  if self.nVersion == 10300:
658  self.nVersion = 300
659  self.nServices = struct.unpack("<Q", f.read(8))[0]
660  self.nTime = struct.unpack("<q", f.read(8))[0]
661  self.addrTo = CAddress()
662  self.addrTo.deserialize(f)
663  if self.nVersion >= 106:
664  self.addrFrom = CAddress()
665  self.addrFrom.deserialize(f)
666  self.nNonce = struct.unpack("<Q", f.read(8))[0]
667  self.strSubVer = deser_string(f)
668  if self.nVersion >= 209:
669  self.nStartingHeight = struct.unpack("<i", f.read(4))[0]
670  else:
671  self.nStartingHeight = None
672  else:
673  self.addrFrom = None
674  self.nNonce = None
675  self.strSubVer = None
676  self.nStartingHeight = None
677 
678  def serialize(self):
679  r = b""
680  r += struct.pack("<i", self.nVersion)
681  r += struct.pack("<Q", self.nServices)
682  r += struct.pack("<q", self.nTime)
683  r += self.addrTo.serialize()
684  r += self.addrFrom.serialize()
685  r += struct.pack("<Q", self.nNonce)
686  r += ser_string(self.strSubVer)
687  r += struct.pack("<i", self.nStartingHeight)
688  return r
689 
690  def __repr__(self):
691  return 'msg_version(nVersion=%i nServices=%i nTime=%s addrTo=%s addrFrom=%s nNonce=0x%016X strSubVer=%s nStartingHeight=%i)' \
692  % (self.nVersion, self.nServices, time.ctime(self.nTime),
693  repr(self.addrTo), repr(self.addrFrom), self.nNonce,
694  self.strSubVer, self.nStartingHeight)
695 
696 
697 class msg_verack(object):
698  command = b"verack"
699 
700  def __init__(self):
701  pass
702 
703  def deserialize(self, f):
704  pass
705 
706  def serialize(self):
707  return b""
708 
709  def __repr__(self):
710  return "msg_verack()"
711 
712 
713 class msg_addr(object):
714  command = b"addr"
715 
716  def __init__(self):
717  self.addrs = []
718 
719  def deserialize(self, f):
720  self.addrs = deser_vector(f, CAddress)
721 
722  def serialize(self):
723  return ser_vector(self.addrs)
724 
725  def __repr__(self):
726  return "msg_addr(addrs=%s)" % (repr(self.addrs))
727 
728 
729 class msg_alert(object):
730  command = b"alert"
731 
732  def __init__(self):
733  self.alert = CAlert()
734 
735  def deserialize(self, f):
736  self.alert = CAlert()
737  self.alert.deserialize(f)
738 
739  def serialize(self):
740  r = b""
741  r += self.alert.serialize()
742  return r
743 
744  def __repr__(self):
745  return "msg_alert(alert=%s)" % (repr(self.alert), )
746 
747 
748 class msg_inv(object):
749  command = b"inv"
750 
751  def __init__(self, inv=None):
752  if inv is None:
753  self.inv = []
754  else:
755  self.inv = inv
756 
757  def deserialize(self, f):
758  self.inv = deser_vector(f, CInv)
759 
760  def serialize(self):
761  return ser_vector(self.inv)
762 
763  def __repr__(self):
764  return "msg_inv(inv=%s)" % (repr(self.inv))
765 
766 
767 class msg_getdata(object):
768  command = b"getdata"
769 
770  def __init__(self, inv=None):
771  self.inv = inv if inv != None else []
772 
773  def deserialize(self, f):
774  self.inv = deser_vector(f, CInv)
775 
776  def serialize(self):
777  return ser_vector(self.inv)
778 
779  def __repr__(self):
780  return "msg_getdata(inv=%s)" % (repr(self.inv))
781 
782 
783 class msg_getblocks(object):
784  command = b"getblocks"
785 
786  def __init__(self):
788  self.hashstop = 0L
789 
790  def deserialize(self, f):
791  self.locator = CBlockLocator()
792  self.locator.deserialize(f)
793  self.hashstop = deser_uint256(f)
794 
795  def serialize(self):
796  r = b""
797  r += self.locator.serialize()
798  r += ser_uint256(self.hashstop)
799  return r
800 
801  def __repr__(self):
802  return "msg_getblocks(locator=%s hashstop=%064x)" \
803  % (repr(self.locator), self.hashstop)
804 
805 
806 class msg_tx(object):
807  command = b"tx"
808 
809  def __init__(self, tx=CTransaction()):
810  self.tx = tx
811 
812  def deserialize(self, f):
813  self.tx.deserialize(f)
814 
815  def serialize(self):
816  return self.tx.serialize()
817 
818  def __repr__(self):
819  return "msg_tx(tx=%s)" % (repr(self.tx))
820 
821 
822 class msg_block(object):
823  command = b"block"
824 
825  def __init__(self, block=None):
826  if block is None:
827  self.block = CBlock()
828  else:
829  self.block = block
830 
831  def deserialize(self, f):
832  self.block.deserialize(f)
833 
834  def serialize(self):
835  return self.block.serialize()
836 
837  def __repr__(self):
838  return "msg_block(block=%s)" % (repr(self.block))
839 
840 
841 class msg_getaddr(object):
842  command = b"getaddr"
843 
844  def __init__(self):
845  pass
846 
847  def deserialize(self, f):
848  pass
849 
850  def serialize(self):
851  return b""
852 
853  def __repr__(self):
854  return "msg_getaddr()"
855 
856 
857 class msg_ping_prebip31(object):
858  command = b"ping"
859 
860  def __init__(self):
861  pass
862 
863  def deserialize(self, f):
864  pass
865 
866  def serialize(self):
867  return b""
868 
869  def __repr__(self):
870  return "msg_ping() (pre-bip31)"
871 
872 
873 class msg_ping(object):
874  command = b"ping"
875 
876  def __init__(self, nonce=0L):
877  self.nonce = nonce
878 
879  def deserialize(self, f):
880  self.nonce = struct.unpack("<Q", f.read(8))[0]
881 
882  def serialize(self):
883  r = b""
884  r += struct.pack("<Q", self.nonce)
885  return r
886 
887  def __repr__(self):
888  return "msg_ping(nonce=%08x)" % self.nonce
889 
890 
891 class msg_pong(object):
892  command = b"pong"
893 
894  def __init__(self, nonce=0):
895  self.nonce = nonce
896 
897  def deserialize(self, f):
898  self.nonce = struct.unpack("<Q", f.read(8))[0]
899 
900  def serialize(self):
901  r = b""
902  r += struct.pack("<Q", self.nonce)
903  return r
904 
905  def __repr__(self):
906  return "msg_pong(nonce=%08x)" % self.nonce
907 
908 
909 class msg_mempool(object):
910  command = b"mempool"
911 
912  def __init__(self):
913  pass
914 
915  def deserialize(self, f):
916  pass
917 
918  def serialize(self):
919  return b""
920 
921  def __repr__(self):
922  return "msg_mempool()"
923 
924 class msg_sendheaders(object):
925  command = b"sendheaders"
926 
927  def __init__(self):
928  pass
929 
930  def deserialize(self, f):
931  pass
932 
933  def serialize(self):
934  return b""
935 
936  def __repr__(self):
937  return "msg_sendheaders()"
938 
939 # getheaders message has
940 # number of entries
941 # vector of hashes
942 # hash_stop (hash of last desired block header, 0 to get as many as possible)
943 class msg_getheaders(object):
944  command = b"getheaders"
945 
946  def __init__(self):
948  self.hashstop = 0L
949 
950  def deserialize(self, f):
951  self.locator = CBlockLocator()
952  self.locator.deserialize(f)
953  self.hashstop = deser_uint256(f)
954 
955  def serialize(self):
956  r = b""
957  r += self.locator.serialize()
958  r += ser_uint256(self.hashstop)
959  return r
960 
961  def __repr__(self):
962  return "msg_getheaders(locator=%s, stop=%064x)" \
963  % (repr(self.locator), self.hashstop)
964 
965 
966 # headers message has
967 # <count> <vector of block headers>
968 class msg_headers(object):
969  command = b"headers"
970 
971  def __init__(self):
972  self.headers = []
973 
974  def deserialize(self, f):
975  # comment in dashd indicates these should be deserialized as blocks
976  blocks = deser_vector(f, CBlock)
977  for x in blocks:
978  self.headers.append(CBlockHeader(x))
979 
980  def serialize(self):
981  blocks = [CBlock(x) for x in self.headers]
982  return ser_vector(blocks)
983 
984  def __repr__(self):
985  return "msg_headers(headers=%s)" % repr(self.headers)
986 
987 
988 class msg_reject(object):
989  command = b"reject"
990  REJECT_MALFORMED = 1
991 
992  def __init__(self):
993  self.message = b""
994  self.code = 0
995  self.reason = b""
996  self.data = 0L
997 
998  def deserialize(self, f):
999  self.message = deser_string(f)
1000  self.code = struct.unpack("<B", f.read(1))[0]
1001  self.reason = deser_string(f)
1002  if (self.code != self.REJECT_MALFORMED and
1003  (self.message == b"block" or self.message == b"tx")):
1004  self.data = deser_uint256(f)
1005 
1006  def serialize(self):
1007  r = ser_string(self.message)
1008  r += struct.pack("<B", self.code)
1009  r += ser_string(self.reason)
1010  if (self.code != self.REJECT_MALFORMED and
1011  (self.message == b"block" or self.message == b"tx")):
1012  r += ser_uint256(self.data)
1013  return r
1014 
1015  def __repr__(self):
1016  return "msg_reject: %s %d %s [%064x]" \
1017  % (self.message, self.code, self.reason, self.data)
1018 
1019 # Helper function
1020 def wait_until(predicate, attempts=float('inf'), timeout=float('inf')):
1021  attempt = 0
1022  elapsed = 0
1023 
1024  while attempt < attempts and elapsed < timeout:
1025  with mininode_lock:
1026  if predicate():
1027  return True
1028  attempt += 1
1029  elapsed += 0.05
1030  time.sleep(0.05)
1031 
1032  return False
1033 
1034 # This is what a callback should look like for NodeConn
1035 # Reimplement the on_* functions to provide handling for events
1036 class NodeConnCB(object):
1037  def __init__(self):
1038  self.verack_received = False
1039  # deliver_sleep_time is helpful for debugging race conditions in p2p
1040  # tests; it causes message delivery to sleep for the specified time
1041  # before acquiring the global lock and delivering the next message.
1043 
1044  def set_deliver_sleep_time(self, value):
1045  with mininode_lock:
1046  self.deliver_sleep_time = value
1047 
1049  with mininode_lock:
1050  return self.deliver_sleep_time
1051 
1052  # Spin until verack message is received from the node.
1053  # Tests may want to use this as a signal that the test can begin.
1054  # This can be called from the testing thread, so it needs to acquire the
1055  # global lock.
1056  def wait_for_verack(self):
1057  while True:
1058  with mininode_lock:
1059  if self.verack_received:
1060  return
1061  time.sleep(0.05)
1062 
1063  def deliver(self, conn, message):
1064  deliver_sleep = self.get_deliver_sleep_time()
1065  if deliver_sleep is not None:
1066  time.sleep(deliver_sleep)
1067  with mininode_lock:
1068  try:
1069  getattr(self, 'on_' + message.command)(conn, message)
1070  except:
1071  print "ERROR delivering %s (%s)" % (repr(message),
1072  sys.exc_info()[0])
1073 
1074  def on_version(self, conn, message):
1075  if message.nVersion >= 209:
1076  conn.send_message(msg_verack())
1077  conn.ver_send = min(MY_VERSION, message.nVersion)
1078  if message.nVersion < 209:
1079  conn.ver_recv = conn.ver_send
1080 
1081  def on_verack(self, conn, message):
1082  conn.ver_recv = conn.ver_send
1083  self.verack_received = True
1084 
1085  def on_inv(self, conn, message):
1086  want = msg_getdata()
1087  for i in message.inv:
1088  if i.type != 0:
1089  want.inv.append(i)
1090  if len(want.inv):
1091  conn.send_message(want)
1092 
1093  def on_addr(self, conn, message): pass
1094  def on_alert(self, conn, message): pass
1095  def on_getdata(self, conn, message): pass
1096  def on_getblocks(self, conn, message): pass
1097  def on_tx(self, conn, message): pass
1098  def on_block(self, conn, message): pass
1099  def on_getaddr(self, conn, message): pass
1100  def on_headers(self, conn, message): pass
1101  def on_getheaders(self, conn, message): pass
1102  def on_ping(self, conn, message):
1103  if conn.ver_send > BIP0031_VERSION:
1104  conn.send_message(msg_pong(message.nonce))
1105  def on_reject(self, conn, message): pass
1106  def on_close(self, conn): pass
1107  def on_mempool(self, conn): pass
1108  def on_pong(self, conn, message): pass
1109 
1110 # More useful callbacks and functions for NodeConnCB's which have a single NodeConn
1112  def __init__(self):
1113  NodeConnCB.__init__(self)
1114  self.connection = None
1115  self.ping_counter = 1
1117 
1118  def add_connection(self, conn):
1119  self.connection = conn
1120 
1121  # Wrapper for the NodeConn's send_message function
1122  def send_message(self, message):
1123  self.connection.send_message(message)
1124 
1125  def on_pong(self, conn, message):
1126  self.last_pong = message
1127 
1128  # Sync up with the node
1129  def sync_with_ping(self, timeout=30):
1130  def received_pong():
1131  return (self.last_pong.nonce == self.ping_counter)
1132  self.send_message(msg_ping(nonce=self.ping_counter))
1133  success = wait_until(received_pong, timeout)
1134  self.ping_counter += 1
1135  return success
1136 
1137 # The actual NodeConn class
1138 # This class provides an interface for a p2p connection to a specified node
1139 class NodeConn(asyncore.dispatcher):
1140  messagemap = {
1141  b"version": msg_version,
1142  b"verack": msg_verack,
1143  b"addr": msg_addr,
1144  b"alert": msg_alert,
1145  b"inv": msg_inv,
1146  b"getdata": msg_getdata,
1147  b"getblocks": msg_getblocks,
1148  b"tx": msg_tx,
1149  b"block": msg_block,
1150  b"getaddr": msg_getaddr,
1151  b"ping": msg_ping,
1152  b"pong": msg_pong,
1153  b"headers": msg_headers,
1154  b"getheaders": msg_getheaders,
1155  b"reject": msg_reject,
1156  b"mempool": msg_mempool,
1157  }
1158  MAGIC_BYTES = {
1159  "mainnet": b"\xbf\x0c\x6b\xbd", # mainnet
1160  "testnet3": b"\xce\xe2\xca\xff", # testnet3
1161  "regtest": b"\xfc\xc1\xb7\xdc" # regtest
1162  }
1163 
1164  def __init__(self, dstaddr, dstport, rpc, callback, net="regtest", services=1):
1165  asyncore.dispatcher.__init__(self, map=mininode_socket_map)
1166  self.log = logging.getLogger("NodeConn(%s:%d)" % (dstaddr, dstport))
1167  self.dstaddr = dstaddr
1168  self.dstport = dstport
1169  self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
1170  self.sendbuf = b""
1171  self.recvbuf = b""
1172  self.ver_send = 209
1173  self.ver_recv = 209
1174  self.last_sent = 0
1175  self.state = "connecting"
1176  self.network = net
1177  self.cb = callback
1178  self.disconnect = False
1179 
1180  # stuff version msg into sendbuf
1181  vt = msg_version()
1182  vt.nServices = services
1183  vt.addrTo.ip = self.dstaddr
1184  vt.addrTo.port = self.dstport
1185  vt.addrFrom.ip = "0.0.0.0"
1186  vt.addrFrom.port = 0
1187  self.send_message(vt, True)
1188  print 'MiniNode: Connecting to Dash Node IP # ' + dstaddr + ':' \
1189  + str(dstport)
1190 
1191  try:
1192  self.connect((dstaddr, dstport))
1193  except:
1194  self.handle_close()
1195  self.rpc = rpc
1196 
1197  def show_debug_msg(self, msg):
1198  self.log.debug(msg)
1199 
1200  def handle_connect(self):
1201  self.show_debug_msg("MiniNode: Connected & Listening: \n")
1202  self.state = "connected"
1203 
1204  def handle_close(self):
1205  self.show_debug_msg("MiniNode: Closing Connection to %s:%d... "
1206  % (self.dstaddr, self.dstport))
1207  self.state = "closed"
1208  self.recvbuf = b""
1209  self.sendbuf = b""
1210  try:
1211  self.close()
1212  except:
1213  pass
1214  self.cb.on_close(self)
1215 
1216  def handle_read(self):
1217  try:
1218  t = self.recv(8192)
1219  if len(t) > 0:
1220  self.recvbuf += t
1221  self.got_data()
1222  except:
1223  pass
1224 
1225  def readable(self):
1226  return True
1227 
1228  def writable(self):
1229  with mininode_lock:
1230  length = len(self.sendbuf)
1231  return (length > 0)
1232 
1233  def handle_write(self):
1234  with mininode_lock:
1235  try:
1236  sent = self.send(self.sendbuf)
1237  except:
1238  self.handle_close()
1239  return
1240  self.sendbuf = self.sendbuf[sent:]
1241 
1242  def got_data(self):
1243  try:
1244  while True:
1245  if len(self.recvbuf) < 4:
1246  return
1247  if self.recvbuf[:4] != self.MAGIC_BYTES[self.network]:
1248  raise ValueError("got garbage %s" % repr(self.recvbuf))
1249  if self.ver_recv < 209:
1250  if len(self.recvbuf) < 4 + 12 + 4:
1251  return
1252  command = self.recvbuf[4:4+12].split(b"\x00", 1)[0]
1253  msglen = struct.unpack("<i", self.recvbuf[4+12:4+12+4])[0]
1254  checksum = None
1255  if len(self.recvbuf) < 4 + 12 + 4 + msglen:
1256  return
1257  msg = self.recvbuf[4+12+4:4+12+4+msglen]
1258  self.recvbuf = self.recvbuf[4+12+4+msglen:]
1259  else:
1260  if len(self.recvbuf) < 4 + 12 + 4 + 4:
1261  return
1262  command = self.recvbuf[4:4+12].split(b"\x00", 1)[0]
1263  msglen = struct.unpack("<i", self.recvbuf[4+12:4+12+4])[0]
1264  checksum = self.recvbuf[4+12+4:4+12+4+4]
1265  if len(self.recvbuf) < 4 + 12 + 4 + 4 + msglen:
1266  return
1267  msg = self.recvbuf[4+12+4+4:4+12+4+4+msglen]
1268  th = sha256(msg)
1269  h = sha256(th)
1270  if checksum != h[:4]:
1271  raise ValueError("got bad checksum " + repr(self.recvbuf))
1272  self.recvbuf = self.recvbuf[4+12+4+4+msglen:]
1273  if command in self.messagemap:
1274  f = BytesIO(msg)
1275  t = self.messagemap[command]()
1276  t.deserialize(f)
1277  self.got_message(t)
1278  else:
1279  self.show_debug_msg("Unknown command: '" + command + "' " +
1280  repr(msg))
1281  except Exception as e:
1282  print 'got_data:', repr(e)
1283 
1284  def send_message(self, message, pushbuf=False):
1285  if self.state != "connected" and not pushbuf:
1286  return
1287  self.show_debug_msg("Send %s" % repr(message))
1288  command = message.command
1289  data = message.serialize()
1290  tmsg = self.MAGIC_BYTES[self.network]
1291  tmsg += command
1292  tmsg += b"\x00" * (12 - len(command))
1293  tmsg += struct.pack("<I", len(data))
1294  if self.ver_send >= 209:
1295  th = sha256(data)
1296  h = sha256(th)
1297  tmsg += h[:4]
1298  tmsg += data
1299  with mininode_lock:
1300  self.sendbuf += tmsg
1301  self.last_sent = time.time()
1302 
1303  def got_message(self, message):
1304  if message.command == b"version":
1305  if message.nVersion <= BIP0031_VERSION:
1306  self.messagemap[b'ping'] = msg_ping_prebip31
1307  if self.last_sent + 30 * 60 < time.time():
1308  self.send_message(self.messagemap[b'ping']())
1309  self.show_debug_msg("Recv %s" % repr(message))
1310  self.cb.deliver(self, message)
1311 
1312  def disconnect_node(self):
1313  self.disconnect = True
1314 
1315 
1316 class NetworkThread(Thread):
1317  def run(self):
1318  while mininode_socket_map:
1319  # We check for whether to disconnect outside of the asyncore
1320  # loop to workaround the behavior of asyncore when using
1321  # select
1322  disconnected = []
1323  for fd, obj in mininode_socket_map.items():
1324  if obj.disconnect:
1325  disconnected.append(obj)
1326  [ obj.handle_close() for obj in disconnected ]
1327  asyncore.loop(0.1, use_poll=True, map=mininode_socket_map, count=1)
1328 
1329 
1330 # An exception we can raise if we detect a potential disconnect
1331 # (p2p or rpc) before the test is complete
1332 class EarlyDisconnectError(Exception):
1333  def __init__(self, value):
1334  self.value = value
1335 
1336  def __str__(self):
1337  return repr(self.value)
def __init__(self, inv=None)
Definition: mininode.py:770
def deser_vector(f, c)
Definition: mininode.py:121
def __init__(self, tx=CTransaction())
Definition: mininode.py:809
def __init__(self, nonce=0L)
Definition: mininode.py:876
def deliver(self, conn, message)
Definition: mininode.py:1063
def on_getblocks(self, conn, message)
Definition: mininode.py:1096
def on_headers(self, conn, message)
Definition: mininode.py:1100
def FromHex(obj, hex_string)
Definition: mininode.py:242
def on_alert(self, conn, message)
Definition: mininode.py:1094
def on_getaddr(self, conn, message)
Definition: mininode.py:1099
def on_getheaders(self, conn, message)
Definition: mininode.py:1101
def __init__(self, outpoint=None, scriptSig=b"", nSequence=0)
Definition: mininode.py:343
def __init__(self, dstaddr, dstport, rpc, callback, net="regtest", services=1)
Definition: mininode.py:1164
def on_ping(self, conn, message)
Definition: mininode.py:1102
def on_verack(self, conn, message)
Definition: mininode.py:1081
def on_getdata(self, conn, message)
Definition: mininode.py:1095
def __init__(self, t=0, h=0L)
Definition: mininode.py:284
def wait_until(predicate, attempts=float('inf'), timeout=float('inf'))
Definition: mininode.py:1020
def __init__(self, inv=None)
Definition: mininode.py:751
def sync_with_ping(self, timeout=30)
Definition: mininode.py:1129
def on_addr(self, conn, message)
Definition: mininode.py:1093
def on_tx(self, conn, message)
Definition: mininode.py:1097
def on_pong(self, conn, message)
Definition: mininode.py:1108
def __init__(self, nValue=0, scriptPubKey=b"")
Definition: mininode.py:371
def on_pong(self, conn, message)
Definition: mininode.py:1125
def __init__(self, header=None)
Definition: mininode.py:514
def __init__(self, nonce=0)
Definition: mininode.py:894
def on_reject(self, conn, message)
Definition: mininode.py:1105
def send_message(self, message, pushbuf=False)
Definition: mininode.py:1284
def on_inv(self, conn, message)
Definition: mininode.py:1085
def on_version(self, conn, message)
Definition: mininode.py:1074
def set_deliver_sleep_time(self, value)
Definition: mininode.py:1044
def got_message(self, message)
Definition: mininode.py:1303
Internal SHA-256 implementation.
Definition: sha256.cpp:15
def __init__(self, block=None)
Definition: mininode.py:825
UniValue debug(const UniValue &params, bool fHelp)
Definition: misc.cpp:119
def __init__(self, header=None)
Definition: mininode.py:446
def __init__(self, hash=0, n=0)
Definition: mininode.py:324
def on_block(self, conn, message)
Definition: mininode.py:1098