Dash Core  0.12.2.1
P2P Digital Currency
prioritise_transaction.py
Go to the documentation of this file.
1 #!/usr/bin/env python2
2 # Copyright (c) 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 PrioritiseTransaction code
8 #
9 
10 from test_framework.test_framework import BitcoinTestFramework
11 from test_framework.util import *
12 from test_framework.mininode import COIN, MAX_BLOCK_SIZE
13 
15 
16  def __init__(self):
18 
19  def setup_chain(self):
20  print("Initializing test directory "+self.options.tmpdir)
21  initialize_chain_clean(self.options.tmpdir, 1)
22 
23  def setup_network(self):
24  self.nodes = []
25  self.is_network_split = False
26 
27  self.nodes.append(start_node(0, self.options.tmpdir, ["-debug", "-printpriority=1"]))
28  self.relayfee = self.nodes[0].getnetworkinfo()['relayfee']
29 
30  def run_test(self):
31  utxo_count = 90
32  utxos = create_confirmed_utxos(self.relayfee, self.nodes[0], utxo_count)
33  base_fee = self.relayfee*100 # our transactions are smaller than 100kb
34  txids = []
35 
36  # Create 3 batches of transactions at 3 different fee rate levels
37  range_size = utxo_count // 3
38  for i in xrange(3):
39  txids.append([])
40  start_range = i * range_size
41  end_range = start_range + range_size
42  txids[i] = create_lots_of_big_transactions(self.nodes[0], self.txouts, utxos[start_range:end_range], (i+1)*base_fee)
43 
44  # Make sure that the size of each group of transactions exceeds
45  # MAX_BLOCK_SIZE -- otherwise the test needs to be revised to create
46  # more transactions.
47  mempool = self.nodes[0].getrawmempool(True)
48  sizes = [0, 0, 0]
49  for i in xrange(3):
50  for j in txids[i]:
51  assert(j in mempool)
52  sizes[i] += mempool[j]['size']
53  assert(sizes[i] > MAX_BLOCK_SIZE) # Fail => raise utxo_count
54 
55  # add a fee delta to something in the cheapest bucket and make sure it gets mined
56  # also check that a different entry in the cheapest bucket is NOT mined (lower
57  # the priority to ensure its not mined due to priority)
58  self.nodes[0].prioritisetransaction(txids[0][0], 0, int(3*base_fee*COIN))
59  self.nodes[0].prioritisetransaction(txids[0][1], -1e15, 0)
60 
61  self.nodes[0].generate(1)
62 
63  mempool = self.nodes[0].getrawmempool()
64  print "Assert that prioritised transaction was mined"
65  assert(txids[0][0] not in mempool)
66  assert(txids[0][1] in mempool)
67 
68  high_fee_tx = None
69  for x in txids[2]:
70  if x not in mempool:
71  high_fee_tx = x
72 
73  # Something high-fee should have been mined!
74  assert(high_fee_tx != None)
75 
76  # Add a prioritisation before a tx is in the mempool (de-prioritising a
77  # high-fee transaction so that it's now low fee).
78  self.nodes[0].prioritisetransaction(high_fee_tx, -1e15, -int(2*base_fee*COIN))
79 
80  # Add everything back to mempool
81  self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
82 
83  # Check to make sure our high fee rate tx is back in the mempool
84  mempool = self.nodes[0].getrawmempool()
85  assert(high_fee_tx in mempool)
86 
87  # Now verify the modified-high feerate transaction isn't mined before
88  # the other high fee transactions. Keep mining until our mempool has
89  # decreased by all the high fee size that we calculated above.
90  while (self.nodes[0].getmempoolinfo()['bytes'] > sizes[0] + sizes[1]):
91  self.nodes[0].generate(1)
92 
93  # High fee transaction should not have been mined, but other high fee rate
94  # transactions should have been.
95  mempool = self.nodes[0].getrawmempool()
96  print "Assert that de-prioritised transaction is still in mempool"
97  assert(high_fee_tx in mempool)
98  for x in txids[2]:
99  if (x != high_fee_tx):
100  assert(x not in mempool)
101 
102  # Create a free, low priority transaction. Should be rejected.
103  utxo_list = self.nodes[0].listunspent()
104  assert(len(utxo_list) > 0)
105  utxo = utxo_list[0]
106 
107  inputs = []
108  outputs = {}
109  inputs.append({"txid" : utxo["txid"], "vout" : utxo["vout"]})
110  outputs[self.nodes[0].getnewaddress()] = utxo["amount"] - self.relayfee
111  raw_tx = self.nodes[0].createrawtransaction(inputs, outputs)
112  tx_hex = self.nodes[0].signrawtransaction(raw_tx)["hex"]
113  txid = self.nodes[0].sendrawtransaction(tx_hex)
114 
115  # A tx that spends an in-mempool tx has 0 priority, so we can use it to
116  # test the effect of using prioritise transaction for mempool acceptance
117  inputs = []
118  inputs.append({"txid": txid, "vout": 0})
119  outputs = {}
120  outputs[self.nodes[0].getnewaddress()] = utxo["amount"] - self.relayfee
121  raw_tx2 = self.nodes[0].createrawtransaction(inputs, outputs)
122  tx2_hex = self.nodes[0].signrawtransaction(raw_tx2)["hex"]
123  tx2_id = self.nodes[0].decoderawtransaction(tx2_hex)["txid"]
124 
125  try:
126  self.nodes[0].sendrawtransaction(tx2_hex)
127  except JSONRPCException as exp:
128  assert_equal(exp.error['code'], -26) # insufficient fee
129  assert(tx2_id not in self.nodes[0].getrawmempool())
130  else:
131  assert(False)
132 
133  # This is a less than 1000-byte transaction, so just set the fee
134  # to be the minimum for a 1000 byte transaction and check that it is
135  # accepted.
136  self.nodes[0].prioritisetransaction(tx2_id, 0, int(self.relayfee*COIN))
137 
138  print "Assert that prioritised free transaction is accepted to mempool"
139  assert_equal(self.nodes[0].sendrawtransaction(tx2_hex), tx2_id)
140  assert(tx2_id in self.nodes[0].getrawmempool())
141 
142 if __name__ == '__main__':
UniValue prioritisetransaction(const UniValue &params, bool fHelp)
Definition: mining.cpp:279
UniValue listunspent(const UniValue &params, bool fHelp)
Definition: rpcwallet.cpp:2533
UniValue getnewaddress(const UniValue &params, bool fHelp)
Definition: rpcwallet.cpp:113
UniValue getmempoolinfo(const UniValue &params, bool fHelp)
Definition: blockchain.cpp:961
def initialize_chain_clean(test_dir, num_nodes)
Definition: util.py:252
UniValue signrawtransaction(const UniValue &params, bool fHelp)
UniValue createrawtransaction(const UniValue &params, bool fHelp)
UniValue decoderawtransaction(const UniValue &params, bool fHelp)
def gen_return_txouts()
Definition: util.py:559
def start_node(i, dirname, extra_args=None, rpchost=None, timewait=None, binary=None)
Definition: util.py:281
UniValue generate(const UniValue &params, bool fHelp)
Definition: mining.cpp:122
UniValue sendrawtransaction(const UniValue &params, bool fHelp)
UniValue getrawmempool(const UniValue &params, bool fHelp)
Definition: blockchain.cpp:234
def create_confirmed_utxos(fee, node, count)
Definition: util.py:530
UniValue getbestblockhash(const UniValue &params, bool fHelp)
Definition: blockchain.cpp:148
UniValue getnetworkinfo(const UniValue &params, bool fHelp)
Definition: net.cpp:392
def assert_equal(thing1, thing2)
Definition: util.py:461
def create_lots_of_big_transactions(node, txouts, utxos, fee)
Definition: util.py:587