aboutsummaryrefslogtreecommitdiff
path: root/qa/rpc-tests/mempool_limit.py
blob: aeaaa29f32ff87a148794aecf671314d7e326725 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#!/usr/bin/env python2
# Copyright (c) 2014-2015 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.

# Test mempool limiting together/eviction with the wallet

from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import *

class MempoolLimitTest(BitcoinTestFramework):

    def satoshi_round(self, amount):
        return  Decimal(amount).quantize(Decimal('0.00000001'), rounding=ROUND_DOWN)

    def __init__(self):
        # Some pre-processing to create a bunch of OP_RETURN txouts to insert into transactions we create
        # So we have big transactions (and therefore can't fit very many into each block)
        # create one script_pubkey
        script_pubkey = "6a4d0200" #OP_RETURN OP_PUSH2 512 bytes
        for i in xrange (512):
            script_pubkey = script_pubkey + "01"
        # concatenate 128 txouts of above script_pubkey which we'll insert before the txout for change
        self.txouts = "81"
        for k in xrange(128):
            # add txout value
            self.txouts = self.txouts + "0000000000000000"
            # add length of script_pubkey
            self.txouts = self.txouts + "fd0402"
            # add script_pubkey
            self.txouts = self.txouts + script_pubkey

    def create_confirmed_utxos(self, count):
        self.nodes[0].generate(int(0.5*90)+102)
        utxos = self.nodes[0].listunspent()
        iterations = count - len(utxos)
        addr1 = self.nodes[0].getnewaddress()
        addr2 = self.nodes[0].getnewaddress()
        if iterations <= 0:
            return utxos
        for i in xrange(iterations):
            t = utxos.pop()
            fee = self.relayfee
            inputs = []
            inputs.append({ "txid" : t["txid"], "vout" : t["vout"]})
            outputs = {}
            send_value = t['amount'] - fee
            outputs[addr1] = self.satoshi_round(send_value/2)
            outputs[addr2] = self.satoshi_round(send_value/2)
            raw_tx = self.nodes[0].createrawtransaction(inputs, outputs)
            signed_tx = self.nodes[0].signrawtransaction(raw_tx)["hex"]
            txid = self.nodes[0].sendrawtransaction(signed_tx)

        while (self.nodes[0].getmempoolinfo()['size'] > 0):
            self.nodes[0].generate(1)

        utxos = self.nodes[0].listunspent()
        assert(len(utxos) >= count)
        return utxos

    def create_lots_of_big_transactions(self, utxos, fee):
        addr = self.nodes[0].getnewaddress()
        txids = []
        for i in xrange(len(utxos)):
            t = utxos.pop()
            inputs = []
            inputs.append({ "txid" : t["txid"], "vout" : t["vout"]})
            outputs = {}
            send_value = t['amount'] - fee
            outputs[addr] = self.satoshi_round(send_value)
            rawtx = self.nodes[0].createrawtransaction(inputs, outputs)
            newtx = rawtx[0:92]
            newtx = newtx + self.txouts
            newtx = newtx + rawtx[94:]
            signresult = self.nodes[0].signrawtransaction(newtx, None, None, "NONE")
            txid = self.nodes[0].sendrawtransaction(signresult["hex"], True)
            txids.append(txid)
        return txids
                    
    def setup_network(self):
        self.nodes = []
        self.nodes.append(start_node(0, self.options.tmpdir, ["-maxmempool=5", "-spendzeroconfchange=0", "-debug"]))
        self.nodes.append(start_node(1, self.options.tmpdir, []))
        connect_nodes(self.nodes[0], 1)
        self.is_network_split = False
        self.sync_all()
        self.relayfee = self.nodes[0].getnetworkinfo()['relayfee']

    def setup_chain(self):
        print("Initializing test directory "+self.options.tmpdir)
        initialize_chain_clean(self.options.tmpdir, 2)

    def run_test(self):
        txids = []
        utxos = self.create_confirmed_utxos(90)

        #create a mempool tx that will be evicted
        us0 = utxos.pop()
        inputs = [{ "txid" : us0["txid"], "vout" : us0["vout"]}]
        outputs = {self.nodes[1].getnewaddress() : 0.0001}
        tx = self.nodes[0].createrawtransaction(inputs, outputs)
        txF = self.nodes[0].fundrawtransaction(tx)
        txFS = self.nodes[0].signrawtransaction(txF['hex'])
        txid = self.nodes[0].sendrawtransaction(txFS['hex'])
        self.nodes[0].lockunspent(True, [us0])

        relayfee = self.nodes[0].getnetworkinfo()['relayfee']
        base_fee = relayfee*100
        for i in xrange (4):
            txids.append([])
            txids[i] = self.create_lots_of_big_transactions(utxos[30*i:30*i+30], (i+1)*base_fee)

        # by now, the tx should be evicted, check confirmation state
        assert(txid not in self.nodes[0].getrawmempool())
        txdata = self.nodes[0].gettransaction(txid);
        assert(txdata['confirmations'] ==  0) #confirmation should still be 0

if __name__ == '__main__':
    MempoolLimitTest().main()