Skip to content

Instantly share code, notes, and snippets.

@morcos
Created December 5, 2014 20:14
Show Gist options
  • Save morcos/0ab22140dde800ac70fc to your computer and use it in GitHub Desktop.
Save morcos/0ab22140dde800ac70fc to your computer and use it in GitHub Desktop.
Incorrect balance test for bitcoin-qt
#!/usr/bin/env python
# Copyright (c) 2014 The Bitcoin Core developers
# Distributed under the MIT/X11 software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
from test_framework import BitcoinTestFramework
from util import *
def start_qt_node(i, dirname, extra_args=None, rpchost=None):
"""
Start a bitcoin-qt and return RPC connection to it
"""
os.environ['PATH'] = os.environ['PATH'] +":"+"../../src/qt"
datadir = os.path.join(dirname, "node"+str(i))
args = [ os.getenv("BITCOINQT", "bitcoin-qt"), "-datadir="+datadir, "-keypool=1", "-discover=0", "-rest", "-server" ]
if extra_args is not None: args.extend(extra_args)
bitcoind_processes[i] = subprocess.Popen(args)
devnull = open("/dev/null", "w+")
subprocess.check_call([ os.getenv("BITCOINCLI", "bitcoin-cli"), "-datadir="+datadir] +
["-rpcwait", "getblockcount"], stdout=devnull)
devnull.close()
url = "http://rt:rt@%s:%d" % (rpchost or '127.0.0.1', rpc_port(i))
proxy = AuthServiceProxy(url)
proxy.url = url # store URL on proxy for info
return proxy
class RemoveTest(BitcoinTestFramework):
def setup_chain(self):
print("Initializing test directory "+self.options.tmpdir)
initialize_chain_clean(self.options.tmpdir, 3)
def setup_network(self, split=False):
self.nodes = [start_qt_node(0, self.options.tmpdir, ["-debug"]),
start_node(1, self.options.tmpdir, ["-debug"]),
start_node(2, self.options.tmpdir, ["-debug"])]
connect_nodes_bi(self.nodes, 0, 1)
connect_nodes_bi(self.nodes, 1, 2)
self.is_network_split = split
def run_test (self):
print "Mining blocks..."
self.nodes[0].setgenerate(True, 2)
self.sync_all()
self.nodes[1].setgenerate(True, 101)
self.sync_all()
node0utxos = self.nodes[0].listunspent(1)
assert_equal(len(node0utxos), 2)
inputs = []
outputs = {}
utxo = node0utxos.pop()
inputs.append({ "txid" : utxo["txid"], "vout" : utxo["vout"]})
total = utxo["amount"]
utxo = node0utxos.pop()
inputs.append({ "txid" : utxo["txid"], "vout" : utxo["vout"]})
total += utxo["amount"]
outputs[self.nodes[1].getnewaddress()] = Decimal(70.0)
outputs[self.nodes[0].getnewaddress()] = total - Decimal(70.0)
raw_tx = self.nodes[0].createrawtransaction(inputs, outputs)
raw_sign = self.nodes[0].signrawtransaction(raw_tx)
inputs = []
outputs = {}
#same utxo spent again
inputs.append({ "txid" : utxo["txid"], "vout" : utxo["vout"]})
outputs[self.nodes[2].getnewaddress()] = Decimal(45.0)
outputs[self.nodes[0].getnewaddress()] = Decimal(5.0)
dbl_tx = self.nodes[0].createrawtransaction(inputs, outputs)
dbl_sign = self.nodes[0].signrawtransaction(dbl_tx)
self.sync_all()
print("Stopping node 2")
stop_node(self.nodes[2],2)
print("Restarting node 2")
self.nodes[2] = start_node(2, self.options.tmpdir, ["-debug"])
print("Sending first spend of 70 BTC from node 0")
self.nodes[0].sendrawtransaction(raw_sign["hex"], True)
print("Sending double spend of 45 BTC from node 2")
self.nodes[2].sendrawtransaction(dbl_sign["hex"], True)
print("Reconnecting node 2")
connect_nodes_bi(self.nodes, 1, 2)
print("Mining block from node 2 with the double spend")
self.nodes[2].setgenerate(True, 1)
sync_blocks(self.nodes)
print("Available balance should be 55 BTC")
raw_input("Press Enter to finish test, Available balance should be 55 BTC")
assert_equal(self.nodes[0].getbalance(),55)
if __name__ == '__main__':
RemoveTest().main ()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment