Dash Core  0.12.2.1
P2P Digital Currency
replace-by-fee.py
Go to the documentation of this file.
1 #!/usr/bin/env python2
2 # Copyright (c) 2014-2015 The Bitcoin Core developers
3 # Distributed under the MIT software license, see the accompanying
4 # file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 
6 #
7 # Test replace by fee code
8 #
9 
10 from test_framework.test_framework import BitcoinTestFramework
11 from test_framework.util import *
12 from test_framework.script import *
13 from test_framework.mininode import *
14 
15 MAX_REPLACEMENT_LIMIT = 100
16 
17 def txToHex(tx):
18  return bytes_to_hex_str(tx.serialize())
19 
20 def make_utxo(node, amount, confirmed=True, scriptPubKey=CScript([1])):
21  """Create a txout with a given amount and scriptPubKey
22 
23  Mines coins as needed.
24 
25  confirmed - txouts created will be confirmed in the blockchain;
26  unconfirmed otherwise.
27  """
28  fee = 1*COIN
29  while node.getbalance() < satoshi_round((amount + fee)/COIN):
30  node.generate(100)
31  #print (node.getbalance(), amount, fee)
32 
33  new_addr = node.getnewaddress()
34  #print new_addr
35  txid = node.sendtoaddress(new_addr, satoshi_round((amount+fee)/COIN))
36  tx1 = node.getrawtransaction(txid, 1)
37  txid = int(txid, 16)
38  i = None
39 
40  for i, txout in enumerate(tx1['vout']):
41  #print i, txout['scriptPubKey']['addresses']
42  if txout['scriptPubKey']['addresses'] == [new_addr]:
43  #print i
44  break
45  assert i is not None
46 
47  tx2 = CTransaction()
48  tx2.vin = [CTxIn(COutPoint(txid, i))]
49  tx2.vout = [CTxOut(amount, scriptPubKey)]
50  tx2.rehash()
51 
52  signed_tx = node.signrawtransaction(txToHex(tx2))
53 
54  txid = node.sendrawtransaction(signed_tx['hex'], True)
55 
56  # If requested, ensure txouts are confirmed.
57  if confirmed:
58  mempool_size = len(node.getrawmempool())
59  while mempool_size > 0:
60  node.generate(1)
61  new_size = len(node.getrawmempool())
62  # Error out if we have something stuck in the mempool, as this
63  # would likely be a bug.
64  assert(new_size < mempool_size)
65  mempool_size = new_size
66 
67  return COutPoint(int(txid, 16), 0)
68 
70 
71  def setup_network(self):
72  self.nodes = []
73  self.nodes.append(start_node(0, self.options.tmpdir, ["-maxorphantx=1000", "-debug",
74  "-relaypriority=0", "-whitelist=127.0.0.1",
75  "-limitancestorcount=50",
76  "-limitancestorsize=101",
77  "-limitdescendantcount=200",
78  "-limitdescendantsize=101"
79  ]))
80  self.is_network_split = False
81 
82  def run_test(self):
83  make_utxo(self.nodes[0], 1*COIN)
84 
85  print "Running test simple doublespend..."
87 
88  print "Running test doublespend chain..."
90 
91  print "Running test doublespend tree..."
93 
94  print "Running test replacement feeperkb..."
96 
97  print "Running test spends of conflicting outputs..."
99 
100  print "Running test new unconfirmed inputs..."
102 
103  print "Running test too many replacements..."
105 
106  print "Running test opt-in..."
107  self.test_opt_in()
108 
109  print "Running test prioritised transactions..."
111 
112  print "Passed\n"
113 
115  """Simple doublespend"""
116  tx0_outpoint = make_utxo(self.nodes[0], int(1.1*COIN))
117 
118  tx1a = CTransaction()
119  tx1a.vin = [CTxIn(tx0_outpoint, nSequence=0)]
120  tx1a.vout = [CTxOut(1*COIN, CScript([b'a']))]
121  tx1a_hex = txToHex(tx1a)
122  tx1a_txid = self.nodes[0].sendrawtransaction(tx1a_hex, True)
123 
124  # Should fail because we haven't changed the fee
125  tx1b = CTransaction()
126  tx1b.vin = [CTxIn(tx0_outpoint, nSequence=0)]
127  tx1b.vout = [CTxOut(1*COIN, CScript([b'b']))]
128  tx1b_hex = txToHex(tx1b)
129 
130  try:
131  tx1b_txid = self.nodes[0].sendrawtransaction(tx1b_hex, True)
132  except JSONRPCException as exp:
133  assert_equal(exp.error['code'], -26) # insufficient fee
134  else:
135  assert(False)
136 
137  # Extra 0.1 BTC fee
138  tx1b = CTransaction()
139  tx1b.vin = [CTxIn(tx0_outpoint, nSequence=0)]
140  tx1b.vout = [CTxOut(int(0.9*COIN), CScript([b'b']))]
141  tx1b_hex = txToHex(tx1b)
142  tx1b_txid = self.nodes[0].sendrawtransaction(tx1b_hex, True)
143 
144  mempool = self.nodes[0].getrawmempool()
145 
146  assert (tx1a_txid not in mempool)
147  assert (tx1b_txid in mempool)
148 
149  assert_equal(tx1b_hex, self.nodes[0].getrawtransaction(tx1b_txid))
150 
152  """Doublespend of a long chain"""
153 
154  initial_nValue = 50*COIN
155  tx0_outpoint = make_utxo(self.nodes[0], initial_nValue)
156 
157  prevout = tx0_outpoint
158  remaining_value = initial_nValue
159  chain_txids = []
160  while remaining_value > 10*COIN:
161  remaining_value -= 1*COIN
162  tx = CTransaction()
163  tx.vin = [CTxIn(prevout, nSequence=0)]
164  tx.vout = [CTxOut(remaining_value, CScript([1]))]
165  tx_hex = txToHex(tx)
166  txid = self.nodes[0].sendrawtransaction(tx_hex, True)
167  chain_txids.append(txid)
168  prevout = COutPoint(int(txid, 16), 0)
169 
170  # Whether the double-spend is allowed is evaluated by including all
171  # child fees - 40 BTC - so this attempt is rejected.
172  dbl_tx = CTransaction()
173  dbl_tx.vin = [CTxIn(tx0_outpoint, nSequence=0)]
174  dbl_tx.vout = [CTxOut(initial_nValue - 30*COIN, CScript([1]))]
175  dbl_tx_hex = txToHex(dbl_tx)
176 
177  try:
178  self.nodes[0].sendrawtransaction(dbl_tx_hex, True)
179  except JSONRPCException as exp:
180  assert_equal(exp.error['code'], -26) # insufficient fee
181  else:
182  assert(False) # transaction mistakenly accepted!
183 
184  # Accepted with sufficient fee
185  dbl_tx = CTransaction()
186  dbl_tx.vin = [CTxIn(tx0_outpoint, nSequence=0)]
187  dbl_tx.vout = [CTxOut(1*COIN, CScript([1]))]
188  dbl_tx_hex = txToHex(dbl_tx)
189  self.nodes[0].sendrawtransaction(dbl_tx_hex, True)
190 
191  mempool = self.nodes[0].getrawmempool()
192  for doublespent_txid in chain_txids:
193  assert(doublespent_txid not in mempool)
194 
196  """Doublespend of a big tree of transactions"""
197 
198  initial_nValue = 50*COIN
199  tx0_outpoint = make_utxo(self.nodes[0], initial_nValue)
200 
201  def branch(prevout, initial_value, max_txs, tree_width=5, fee=0.0001*COIN, _total_txs=None):
202  if _total_txs is None:
203  _total_txs = [0]
204  if _total_txs[0] >= max_txs:
205  return
206 
207  txout_value = (initial_value - fee) // tree_width
208  if txout_value < fee:
209  return
210 
211  vout = [CTxOut(txout_value, CScript([i+1]))
212  for i in range(tree_width)]
213  tx = CTransaction()
214  tx.vin = [CTxIn(prevout, nSequence=0)]
215  tx.vout = vout
216  tx_hex = txToHex(tx)
217 
218  assert(len(tx.serialize()) < 100000)
219  txid = self.nodes[0].sendrawtransaction(tx_hex, True)
220  yield tx
221  _total_txs[0] += 1
222 
223  txid = int(txid, 16)
224 
225  for i, txout in enumerate(tx.vout):
226  for x in branch(COutPoint(txid, i), txout_value,
227  max_txs,
228  tree_width=tree_width, fee=fee,
229  _total_txs=_total_txs):
230  yield x
231 
232  fee = int(0.0001*COIN)
233  n = MAX_REPLACEMENT_LIMIT
234  tree_txs = list(branch(tx0_outpoint, initial_nValue, n, fee=fee))
235  assert_equal(len(tree_txs), n)
236 
237  # Attempt double-spend, will fail because too little fee paid
238  dbl_tx = CTransaction()
239  dbl_tx.vin = [CTxIn(tx0_outpoint, nSequence=0)]
240  dbl_tx.vout = [CTxOut(initial_nValue - fee*n, CScript([1]))]
241  dbl_tx_hex = txToHex(dbl_tx)
242  try:
243  self.nodes[0].sendrawtransaction(dbl_tx_hex, True)
244  except JSONRPCException as exp:
245  assert_equal(exp.error['code'], -26) # insufficient fee
246  else:
247  assert(False)
248 
249  # 1 BTC fee is enough
250  dbl_tx = CTransaction()
251  dbl_tx.vin = [CTxIn(tx0_outpoint, nSequence=0)]
252  dbl_tx.vout = [CTxOut(initial_nValue - fee*n - 1*COIN, CScript([1]))]
253  dbl_tx_hex = txToHex(dbl_tx)
254  self.nodes[0].sendrawtransaction(dbl_tx_hex, True)
255 
256  mempool = self.nodes[0].getrawmempool()
257 
258  for tx in tree_txs:
259  tx.rehash()
260  assert (tx.hash not in mempool)
261 
262  # Try again, but with more total transactions than the "max txs
263  # double-spent at once" anti-DoS limit.
264  for n in (MAX_REPLACEMENT_LIMIT+1, MAX_REPLACEMENT_LIMIT*2):
265  fee = int(0.0001*COIN)
266  tx0_outpoint = make_utxo(self.nodes[0], initial_nValue)
267  tree_txs = list(branch(tx0_outpoint, initial_nValue, n, fee=fee))
268  assert_equal(len(tree_txs), n)
269 
270  dbl_tx = CTransaction()
271  dbl_tx.vin = [CTxIn(tx0_outpoint, nSequence=0)]
272  dbl_tx.vout = [CTxOut(initial_nValue - 2*fee*n, CScript([1]))]
273  dbl_tx_hex = txToHex(dbl_tx)
274  try:
275  self.nodes[0].sendrawtransaction(dbl_tx_hex, True)
276  except JSONRPCException as exp:
277  assert_equal(exp.error['code'], -26)
278  assert_equal("too many potential replacements" in exp.error['message'], True)
279  else:
280  assert(False)
281 
282  for tx in tree_txs:
283  tx.rehash()
284  self.nodes[0].getrawtransaction(tx.hash)
285 
287  """Replacement requires fee-per-KB to be higher"""
288  tx0_outpoint = make_utxo(self.nodes[0], int(1.1*COIN))
289 
290  tx1a = CTransaction()
291  tx1a.vin = [CTxIn(tx0_outpoint, nSequence=0)]
292  tx1a.vout = [CTxOut(1*COIN, CScript([b'a']))]
293  tx1a_hex = txToHex(tx1a)
294  tx1a_txid = self.nodes[0].sendrawtransaction(tx1a_hex, True)
295 
296  # Higher fee, but the fee per KB is much lower, so the replacement is
297  # rejected.
298  tx1b = CTransaction()
299  tx1b.vin = [CTxIn(tx0_outpoint, nSequence=0)]
300  tx1b.vout = [CTxOut(int(0.001*COIN), CScript([b'a'*999000]))]
301  tx1b_hex = txToHex(tx1b)
302 
303  try:
304  tx1b_txid = self.nodes[0].sendrawtransaction(tx1b_hex, True)
305  except JSONRPCException as exp:
306  assert_equal(exp.error['code'], -26) # insufficient fee
307  else:
308  assert(False)
309 
311  """Replacements that spend conflicting tx outputs are rejected"""
312  utxo1 = make_utxo(self.nodes[0], int(1.2*COIN))
313  utxo2 = make_utxo(self.nodes[0], 3*COIN)
314 
315  tx1a = CTransaction()
316  tx1a.vin = [CTxIn(utxo1, nSequence=0)]
317  tx1a.vout = [CTxOut(int(1.1*COIN), CScript([b'a']))]
318  tx1a_hex = txToHex(tx1a)
319  tx1a_txid = self.nodes[0].sendrawtransaction(tx1a_hex, True)
320 
321  tx1a_txid = int(tx1a_txid, 16)
322 
323  # Direct spend an output of the transaction we're replacing.
324  tx2 = CTransaction()
325  tx2.vin = [CTxIn(utxo1, nSequence=0), CTxIn(utxo2, nSequence=0)]
326  tx2.vin.append(CTxIn(COutPoint(tx1a_txid, 0), nSequence=0))
327  tx2.vout = tx1a.vout
328  tx2_hex = txToHex(tx2)
329 
330  try:
331  tx2_txid = self.nodes[0].sendrawtransaction(tx2_hex, True)
332  except JSONRPCException as exp:
333  assert_equal(exp.error['code'], -26)
334  else:
335  assert(False)
336 
337  # Spend tx1a's output to test the indirect case.
338  tx1b = CTransaction()
339  tx1b.vin = [CTxIn(COutPoint(tx1a_txid, 0), nSequence=0)]
340  tx1b.vout = [CTxOut(1*COIN, CScript([b'a']))]
341  tx1b_hex = txToHex(tx1b)
342  tx1b_txid = self.nodes[0].sendrawtransaction(tx1b_hex, True)
343  tx1b_txid = int(tx1b_txid, 16)
344 
345  tx2 = CTransaction()
346  tx2.vin = [CTxIn(utxo1, nSequence=0), CTxIn(utxo2, nSequence=0),
347  CTxIn(COutPoint(tx1b_txid, 0))]
348  tx2.vout = tx1a.vout
349  tx2_hex = txToHex(tx2)
350 
351  try:
352  tx2_txid = self.nodes[0].sendrawtransaction(tx2_hex, True)
353  except JSONRPCException as exp:
354  assert_equal(exp.error['code'], -26)
355  else:
356  assert(False)
357 
359  """Replacements that add new unconfirmed inputs are rejected"""
360  confirmed_utxo = make_utxo(self.nodes[0], int(1.1*COIN))
361  unconfirmed_utxo = make_utxo(self.nodes[0], int(0.1*COIN), False)
362 
363  tx1 = CTransaction()
364  tx1.vin = [CTxIn(confirmed_utxo)]
365  tx1.vout = [CTxOut(1*COIN, CScript([b'a']))]
366  tx1_hex = txToHex(tx1)
367  tx1_txid = self.nodes[0].sendrawtransaction(tx1_hex, True)
368 
369  tx2 = CTransaction()
370  tx2.vin = [CTxIn(confirmed_utxo), CTxIn(unconfirmed_utxo)]
371  tx2.vout = tx1.vout
372  tx2_hex = txToHex(tx2)
373 
374  try:
375  tx2_txid = self.nodes[0].sendrawtransaction(tx2_hex, True)
376  except JSONRPCException as exp:
377  assert_equal(exp.error['code'], -26)
378  else:
379  assert(False)
380 
382  """Replacements that evict too many transactions are rejected"""
383  # Try directly replacing more than MAX_REPLACEMENT_LIMIT
384  # transactions
385 
386  # Start by creating a single transaction with many outputs
387  initial_nValue = 10*COIN
388  utxo = make_utxo(self.nodes[0], initial_nValue)
389  fee = int(0.0001*COIN)
390  split_value = int((initial_nValue-fee)/(MAX_REPLACEMENT_LIMIT+1))
391  actual_fee = initial_nValue - split_value*(MAX_REPLACEMENT_LIMIT+1)
392 
393  outputs = []
394  for i in range(MAX_REPLACEMENT_LIMIT+1):
395  outputs.append(CTxOut(split_value, CScript([1])))
396 
397  splitting_tx = CTransaction()
398  splitting_tx.vin = [CTxIn(utxo, nSequence=0)]
399  splitting_tx.vout = outputs
400  splitting_tx_hex = txToHex(splitting_tx)
401 
402  txid = self.nodes[0].sendrawtransaction(splitting_tx_hex, True)
403  txid = int(txid, 16)
404 
405  # Now spend each of those outputs individually
406  for i in range(MAX_REPLACEMENT_LIMIT+1):
407  tx_i = CTransaction()
408  tx_i.vin = [CTxIn(COutPoint(txid, i), nSequence=0)]
409  tx_i.vout = [CTxOut(split_value-fee, CScript([b'a']))]
410  tx_i_hex = txToHex(tx_i)
411  self.nodes[0].sendrawtransaction(tx_i_hex, True)
412 
413  # Now create doublespend of the whole lot; should fail.
414  # Need a big enough fee to cover all spending transactions and have
415  # a higher fee rate
416  double_spend_value = (split_value-100*fee)*(MAX_REPLACEMENT_LIMIT+1)
417  inputs = []
418  for i in range(MAX_REPLACEMENT_LIMIT+1):
419  inputs.append(CTxIn(COutPoint(txid, i), nSequence=0))
420  double_tx = CTransaction()
421  double_tx.vin = inputs
422  double_tx.vout = [CTxOut(double_spend_value, CScript([b'a']))]
423  double_tx_hex = txToHex(double_tx)
424 
425  try:
426  self.nodes[0].sendrawtransaction(double_tx_hex, True)
427  except JSONRPCException as exp:
428  assert_equal(exp.error['code'], -26)
429  assert_equal("too many potential replacements" in exp.error['message'], True)
430  else:
431  assert(False)
432 
433  # If we remove an input, it should pass
434  double_tx = CTransaction()
435  double_tx.vin = inputs[0:-1]
436  double_tx.vout = [CTxOut(double_spend_value, CScript([b'a']))]
437  double_tx_hex = txToHex(double_tx)
438  self.nodes[0].sendrawtransaction(double_tx_hex, True)
439 
440  def test_opt_in(self):
441  """ Replacing should only work if orig tx opted in """
442  tx0_outpoint = make_utxo(self.nodes[0], int(1.1*COIN))
443 
444  # Create a non-opting in transaction
445  tx1a = CTransaction()
446  tx1a.vin = [CTxIn(tx0_outpoint, nSequence=0xffffffff)]
447  tx1a.vout = [CTxOut(1*COIN, CScript([b'a']))]
448  tx1a_hex = txToHex(tx1a)
449  tx1a_txid = self.nodes[0].sendrawtransaction(tx1a_hex, True)
450 
451  # Shouldn't be able to double-spend
452  tx1b = CTransaction()
453  tx1b.vin = [CTxIn(tx0_outpoint, nSequence=0)]
454  tx1b.vout = [CTxOut(int(0.9*COIN), CScript([b'b']))]
455  tx1b_hex = txToHex(tx1b)
456 
457  try:
458  tx1b_txid = self.nodes[0].sendrawtransaction(tx1b_hex, True)
459  except JSONRPCException as exp:
460  assert_equal(exp.error['code'], -26)
461  else:
462  print tx1b_txid
463  assert(False)
464 
465  tx1_outpoint = make_utxo(self.nodes[0], int(1.1*COIN))
466 
467  # Create a different non-opting in transaction
468  tx2a = CTransaction()
469  tx2a.vin = [CTxIn(tx1_outpoint, nSequence=0xfffffffe)]
470  tx2a.vout = [CTxOut(1*COIN, CScript([b'a']))]
471  tx2a_hex = txToHex(tx2a)
472  tx2a_txid = self.nodes[0].sendrawtransaction(tx2a_hex, True)
473 
474  # Still shouldn't be able to double-spend
475  tx2b = CTransaction()
476  tx2b.vin = [CTxIn(tx1_outpoint, nSequence=0)]
477  tx2b.vout = [CTxOut(int(0.9*COIN), CScript([b'b']))]
478  tx2b_hex = txToHex(tx2b)
479 
480  try:
481  tx2b_txid = self.nodes[0].sendrawtransaction(tx2b_hex, True)
482  except JSONRPCException as exp:
483  assert_equal(exp.error['code'], -26)
484  else:
485  assert(False)
486 
487  # Now create a new transaction that spends from tx1a and tx2a
488  # opt-in on one of the inputs
489  # Transaction should be replaceable on either input
490 
491  tx1a_txid = int(tx1a_txid, 16)
492  tx2a_txid = int(tx2a_txid, 16)
493 
494  tx3a = CTransaction()
495  tx3a.vin = [CTxIn(COutPoint(tx1a_txid, 0), nSequence=0xffffffff),
496  CTxIn(COutPoint(tx2a_txid, 0), nSequence=0xfffffffd)]
497  tx3a.vout = [CTxOut(int(0.9*COIN), CScript([b'c'])), CTxOut(int(0.9*COIN), CScript([b'd']))]
498  tx3a_hex = txToHex(tx3a)
499 
500  self.nodes[0].sendrawtransaction(tx3a_hex, True)
501 
502  tx3b = CTransaction()
503  tx3b.vin = [CTxIn(COutPoint(tx1a_txid, 0), nSequence=0)]
504  tx3b.vout = [CTxOut(int(0.5*COIN), CScript([b'e']))]
505  tx3b_hex = txToHex(tx3b)
506 
507  tx3c = CTransaction()
508  tx3c.vin = [CTxIn(COutPoint(tx2a_txid, 0), nSequence=0)]
509  tx3c.vout = [CTxOut(int(0.5*COIN), CScript([b'f']))]
510  tx3c_hex = txToHex(tx3c)
511 
512  self.nodes[0].sendrawtransaction(tx3b_hex, True)
513  # If tx3b was accepted, tx3c won't look like a replacement,
514  # but make sure it is accepted anyway
515  self.nodes[0].sendrawtransaction(tx3c_hex, True)
516 
518  # Ensure that fee deltas used via prioritisetransaction are
519  # correctly used by replacement logic
520 
521  # 1. Check that feeperkb uses modified fees
522  tx0_outpoint = make_utxo(self.nodes[0], int(1.1*COIN))
523 
524  tx1a = CTransaction()
525  tx1a.vin = [CTxIn(tx0_outpoint, nSequence=0)]
526  tx1a.vout = [CTxOut(1*COIN, CScript([b'a']))]
527  tx1a_hex = txToHex(tx1a)
528  tx1a_txid = self.nodes[0].sendrawtransaction(tx1a_hex, True)
529 
530  # Higher fee, but the actual fee per KB is much lower.
531  tx1b = CTransaction()
532  tx1b.vin = [CTxIn(tx0_outpoint, nSequence=0)]
533  tx1b.vout = [CTxOut(int(0.001*COIN), CScript([b'a'*740000]))]
534  tx1b_hex = txToHex(tx1b)
535 
536  # Verify tx1b cannot replace tx1a.
537  try:
538  tx1b_txid = self.nodes[0].sendrawtransaction(tx1b_hex, True)
539  except JSONRPCException as exp:
540  assert_equal(exp.error['code'], -26)
541  else:
542  assert(False)
543 
544  # Use prioritisetransaction to set tx1a's fee to 0.
545  self.nodes[0].prioritisetransaction(tx1a_txid, 0, int(-0.1*COIN))
546 
547  # Now tx1b should be able to replace tx1a
548  tx1b_txid = self.nodes[0].sendrawtransaction(tx1b_hex, True)
549 
550  assert(tx1b_txid in self.nodes[0].getrawmempool())
551 
552  # 2. Check that absolute fee checks use modified fee.
553  tx1_outpoint = make_utxo(self.nodes[0], int(1.1*COIN))
554 
555  tx2a = CTransaction()
556  tx2a.vin = [CTxIn(tx1_outpoint, nSequence=0)]
557  tx2a.vout = [CTxOut(1*COIN, CScript([b'a']))]
558  tx2a_hex = txToHex(tx2a)
559  tx2a_txid = self.nodes[0].sendrawtransaction(tx2a_hex, True)
560 
561  # Lower fee, but we'll prioritise it
562  tx2b = CTransaction()
563  tx2b.vin = [CTxIn(tx1_outpoint, nSequence=0)]
564  tx2b.vout = [CTxOut(int(1.01*COIN), CScript([b'a']))]
565  tx2b.rehash()
566  tx2b_hex = txToHex(tx2b)
567 
568  # Verify tx2b cannot replace tx2a.
569  try:
570  tx2b_txid = self.nodes[0].sendrawtransaction(tx2b_hex, True)
571  except JSONRPCException as exp:
572  assert_equal(exp.error['code'], -26)
573  else:
574  assert(False)
575 
576  # Now prioritise tx2b to have a higher modified fee
577  self.nodes[0].prioritisetransaction(tx2b.hash, 0, int(0.1*COIN))
578 
579  # tx2b should now be accepted
580  tx2b_txid = self.nodes[0].sendrawtransaction(tx2b_hex, True)
581 
582  assert(tx2b_txid in self.nodes[0].getrawmempool())
583 
584 if __name__ == '__main__':
UniValue prioritisetransaction(const UniValue &params, bool fHelp)
Definition: mining.cpp:279
def make_utxo(node, amount, confirmed=True, scriptPubKey=CScript([1]))
UniValue getrawtransaction(const UniValue &params, bool fHelp)
def satoshi_round(amount)
Definition: util.py:525
def start_node(i, dirname, extra_args=None, rpchost=None, timewait=None, binary=None)
Definition: util.py:281
UniValue sendrawtransaction(const UniValue &params, bool fHelp)
UniValue getrawmempool(const UniValue &params, bool fHelp)
Definition: blockchain.cpp:234
def assert_equal(thing1, thing2)
Definition: util.py:461
def bytes_to_hex_str(byte_str)
Definition: util.py:108