Skip to content

Commit 34318d7

Browse files
gavinandresenTheBlueMatt
authored andcommitted
RPC-test based on invalidateblock for mempool coinbase spends
1 parent 7fd6219 commit 34318d7

File tree

2 files changed

+95
-0
lines changed

2 files changed

+95
-0
lines changed

qa/pull-tester/rpc-tests.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ if [ "x${ENABLE_BITCOIND}${ENABLE_UTILS}${ENABLE_WALLET}" = "x111" ]; then
2525
${BUILDDIR}/qa/rpc-tests/rest.py --srcdir "${BUILDDIR}/src"
2626
${BUILDDIR}/qa/rpc-tests/mempool_spendcoinbase.py --srcdir "${BUILDDIR}/src"
2727
${BUILDDIR}/qa/rpc-tests/httpbasics.py --srcdir "${BUILDDIR}/src"
28+
${BUILDDIR}/qa/rpc-tests/mempool_coinbase_spends.py --srcdir "${BUILDDIR}/src"
2829
#${BUILDDIR}/qa/rpc-tests/forknotify.py --srcdir "${BUILDDIR}/src"
2930
else
3031
echo "No rpc tests to run. Wallet, utils, and bitcoind must all be enabled"
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
#!/usr/bin/env python2
2+
# Copyright (c) 2014 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 re-org scenarios with a mempool that contains transactions
8+
# that spend (directly or indirectly) coinbase transactions.
9+
#
10+
11+
from test_framework import BitcoinTestFramework
12+
from bitcoinrpc.authproxy import AuthServiceProxy, JSONRPCException
13+
from util import *
14+
import os
15+
import shutil
16+
17+
# Create one-input, one-output, no-fee transaction:
18+
class MempoolCoinbaseTest(BitcoinTestFramework):
19+
20+
alert_filename = None # Set by setup_network
21+
22+
def setup_network(self):
23+
args = ["-checkmempool", "-debug=mempool"]
24+
self.nodes = []
25+
self.nodes.append(start_node(0, self.options.tmpdir, args))
26+
self.nodes.append(start_node(1, self.options.tmpdir, args))
27+
connect_nodes(self.nodes[1], 0)
28+
self.is_network_split = False
29+
self.sync_all
30+
31+
def create_tx(self, from_txid, to_address, amount):
32+
inputs = [{ "txid" : from_txid, "vout" : 0}]
33+
outputs = { to_address : amount }
34+
rawtx = self.nodes[0].createrawtransaction(inputs, outputs)
35+
signresult = self.nodes[0].signrawtransaction(rawtx)
36+
assert_equal(signresult["complete"], True)
37+
return signresult["hex"]
38+
39+
def run_test(self):
40+
start_count = self.nodes[0].getblockcount()
41+
42+
# Mine three blocks. After this, nodes[0] blocks
43+
# 101, 102, and 103 are spend-able.
44+
new_blocks = self.nodes[1].setgenerate(True, 4)
45+
self.sync_all()
46+
47+
node0_address = self.nodes[0].getnewaddress()
48+
node1_address = self.nodes[1].getnewaddress()
49+
50+
# Three scenarios for re-orging coinbase spends in the memory pool:
51+
# 1. Direct coinbase spend : spend_101
52+
# 2. Indirect (coinbase spend in chain, child in mempool) : spend_102 and spend_102_1
53+
# 3. Indirect (coinbase and child both in chain) : spend_103 and spend_103_1
54+
# Use invalidatblock to make all of the above coinbase spends invalid (immature coinbase),
55+
# and make sure the mempool code behaves correctly.
56+
b = [ self.nodes[0].getblockhash(n) for n in range(102, 105) ]
57+
coinbase_txids = [ self.nodes[0].getblock(h)['tx'][0] for h in b ]
58+
spend_101_raw = self.create_tx(coinbase_txids[0], node1_address, 50)
59+
spend_102_raw = self.create_tx(coinbase_txids[1], node0_address, 50)
60+
spend_103_raw = self.create_tx(coinbase_txids[2], node0_address, 50)
61+
62+
# Broadcast and mine spend_102 and 103:
63+
spend_102_id = self.nodes[0].sendrawtransaction(spend_102_raw)
64+
spend_103_id = self.nodes[0].sendrawtransaction(spend_103_raw)
65+
self.nodes[0].setgenerate(True, 1)
66+
67+
# Create 102_1 and 103_1:
68+
spend_102_1_raw = self.create_tx(spend_102_id, node1_address, 50)
69+
spend_103_1_raw = self.create_tx(spend_103_id, node1_address, 50)
70+
71+
# Broadcast and mine 103_1:
72+
spend_103_1_id = self.nodes[0].sendrawtransaction(spend_103_1_raw)
73+
self.nodes[0].setgenerate(True, 1)
74+
75+
# ... now put spend_101 and spend_102_1 in memory pools:
76+
spend_101_id = self.nodes[0].sendrawtransaction(spend_101_raw)
77+
spend_102_1_id = self.nodes[0].sendrawtransaction(spend_102_1_raw)
78+
79+
self.sync_all()
80+
81+
assert_equal(set(self.nodes[0].getrawmempool()), set([ spend_101_id, spend_102_1_id ]))
82+
83+
# Use invalidateblock to re-org back and make all those coinbase spends
84+
# immature/invalid:
85+
for node in self.nodes:
86+
node.invalidateblock(new_blocks[0])
87+
88+
self.sync_all()
89+
90+
# mempool should be empty.
91+
assert_equal(set(self.nodes[0].getrawmempool()), set())
92+
93+
if __name__ == '__main__':
94+
MempoolCoinbaseTest().main()

0 commit comments

Comments
 (0)