@@ -41,6 +41,20 @@ def wait_until(predicate, attempts=float('inf'), timeout=float('inf')):
4141
4242 return False
4343
44+ class RejectResult (object ):
45+ '''
46+ Outcome that expects rejection of a transaction or block.
47+ '''
48+ def __init__ (self , code , reason = '' ):
49+ self .code = code
50+ self .reason = reason
51+ def match (self , other ):
52+ if self .code != other .code :
53+ return False
54+ return other .reason .startswith (self .reason )
55+ def __repr__ (self ):
56+ return '%i:%s' % (self .code ,self .reason or '*' )
57+
4458class TestNode (NodeConnCB ):
4559
4660 def __init__ (self , block_store , tx_store ):
@@ -51,6 +65,8 @@ def __init__(self, block_store, tx_store):
5165 self .block_request_map = {}
5266 self .tx_store = tx_store
5367 self .tx_request_map = {}
68+ self .block_reject_map = {}
69+ self .tx_reject_map = {}
5470
5571 # When the pingmap is non-empty we're waiting for
5672 # a response
@@ -94,6 +110,12 @@ def on_pong(self, conn, message):
94110 except KeyError :
95111 raise AssertionError ("Got pong for unknown ping [%s]" % repr (message ))
96112
113+ def on_reject (self , conn , message ):
114+ if message .message == 'tx' :
115+ self .tx_reject_map [message .data ] = RejectResult (message .code , message .reason )
116+ if message .message == 'block' :
117+ self .block_reject_map [message .data ] = RejectResult (message .code , message .reason )
118+
97119 def send_inv (self , obj ):
98120 mtype = 2 if isinstance (obj , CBlock ) else 1
99121 self .conn .send_message (msg_inv ([CInv (mtype , obj .sha256 )]))
@@ -243,6 +265,15 @@ def check_results(self, blockhash, outcome):
243265 if outcome is None :
244266 if c .cb .bestblockhash != self .connections [0 ].cb .bestblockhash :
245267 return False
268+ elif isinstance (outcome , RejectResult ): # Check that block was rejected w/ code
269+ if c .cb .bestblockhash == blockhash :
270+ return False
271+ if blockhash not in c .cb .block_reject_map :
272+ print 'Block not in reject map: %064x' % (blockhash )
273+ return False
274+ if not outcome .match (c .cb .block_reject_map [blockhash ]):
275+ print 'Block rejected with %s instead of expected %s: %064x' % (c .cb .block_reject_map [blockhash ], outcome , blockhash )
276+ return False
246277 elif ((c .cb .bestblockhash == blockhash ) != outcome ):
247278 # print c.cb.bestblockhash, blockhash, outcome
248279 return False
@@ -262,6 +293,15 @@ def check_mempool(self, txhash, outcome):
262293 if c .cb .lastInv != self .connections [0 ].cb .lastInv :
263294 # print c.rpc.getrawmempool()
264295 return False
296+ elif isinstance (outcome , RejectResult ): # Check that tx was rejected w/ code
297+ if txhash in c .cb .lastInv :
298+ return False
299+ if txhash not in c .cb .tx_reject_map :
300+ print 'Tx not in reject map: %064x' % (txhash )
301+ return False
302+ if not outcome .match (c .cb .tx_reject_map [txhash ]):
303+ print 'Tx rejected with %s instead of expected %s: %064x' % (c .cb .tx_reject_map [txhash ], outcome , txhash )
304+ return False
265305 elif ((txhash in c .cb .lastInv ) != outcome ):
266306 # print c.rpc.getrawmempool(), c.cb.lastInv
267307 return False
0 commit comments