diff options
Diffstat (limited to 'test')
25 files changed, 406 insertions, 99 deletions
diff --git a/test/functional/README.md b/test/functional/README.md index 6be4d9cfab..4d52751b05 100644 --- a/test/functional/README.md +++ b/test/functional/README.md @@ -17,7 +17,7 @@ don't have test cases for. #### Style guidelines -- Where possible, try to adhere to [PEP-8 guidelines]([https://www.python.org/dev/peps/pep-0008/) +- Where possible, try to adhere to [PEP-8 guidelines](https://www.python.org/dev/peps/pep-0008/) - Use a python linter like flake8 before submitting PRs to catch common style nits (eg trailing whitespace, unused imports, etc) - Avoid wildcard imports where possible diff --git a/test/functional/address_types.py b/test/functional/address_types.py new file mode 100755 index 0000000000..cb119c04b0 --- /dev/null +++ b/test/functional/address_types.py @@ -0,0 +1,199 @@ +#!/usr/bin/env python3 +# Copyright (c) 2017 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 that the wallet can send and receive using all combinations of address types. + +There are 4 nodes-under-test: + - node0 uses legacy addresses + - node1 uses p2sh/segwit addresses + - node2 uses p2sh/segwit addresses and bech32 addresses for change + - node3 uses bech32 addresses + +node4 exists to generate new blocks. + +The script is a series of tests, iterating over the 4 nodes. In each iteration +of the test, one node sends: + - 10/101th of its balance to itself (using getrawchangeaddress for single key addresses) + - 20/101th to the next node + - 30/101th to the node after that + - 40/101th to the remaining node + - 1/101th remains as fee+change + +Iterate over each node for single key addresses, and then over each node for +multisig addresses. In a second iteration, the same is done, but with explicit address_type +parameters passed to getnewaddress and getrawchangeaddress. Node0 and node3 send to p2sh, +node 1 sends to bech32, and node2 sends to legacy. As every node sends coins after receiving, +this also verifies that spending coins sent to all these address types works.""" + +from decimal import Decimal +import itertools + +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import assert_equal, assert_greater_than, connect_nodes_bi, sync_blocks, sync_mempools + +class AddressTypeTest(BitcoinTestFramework): + def set_test_params(self): + self.num_nodes = 5 + self.extra_args = [["-addresstype=legacy"], ["-addresstype=p2sh-segwit"], ["-addresstype=p2sh-segwit", "-changetype=bech32"], ["-addresstype=bech32"], []] + + def setup_network(self): + self.setup_nodes() + + # Fully mesh-connect nodes for faster mempool sync + for i, j in itertools.product(range(self.num_nodes), repeat=2): + if i > j: + connect_nodes_bi(self.nodes, i, j) + self.sync_all() + + def get_balances(self, confirmed=True): + """Return a list of confirmed or unconfirmed balances.""" + if confirmed: + return [self.nodes[i].getbalance() for i in range(4)] + else: + return [self.nodes[i].getunconfirmedbalance() for i in range(4)] + + def test_address(self, node, address, multisig, typ): + """Run sanity checks on an address.""" + info = self.nodes[node].validateaddress(address) + assert(info['isvalid']) + if not multisig and typ == 'legacy': + # P2PKH + assert(not info['isscript']) + assert(not info['iswitness']) + assert('pubkey' in info) + elif not multisig and typ == 'p2sh-segwit': + # P2SH-P2WPKH + assert(info['isscript']) + assert(not info['iswitness']) + assert_equal(info['script'], 'witness_v0_keyhash') + assert('pubkey' in info) + elif not multisig and typ == 'bech32': + # P2WPKH + assert(not info['isscript']) + assert(info['iswitness']) + assert_equal(info['witness_version'], 0) + assert_equal(len(info['witness_program']), 40) + assert('pubkey' in info) + elif typ == 'legacy': + # P2SH-multisig + assert(info['isscript']) + assert_equal(info['script'], 'multisig') + assert(not info['iswitness']) + assert('pubkeys' in info) + elif typ == 'p2sh-segwit': + # P2SH-P2WSH-multisig + assert(info['isscript']) + assert_equal(info['script'], 'witness_v0_scripthash') + assert(not info['iswitness']) + assert(info['embedded']['isscript']) + assert_equal(info['embedded']['script'], 'multisig') + assert(info['embedded']['iswitness']) + assert_equal(info['embedded']['witness_version'], 0) + assert_equal(len(info['embedded']['witness_program']), 64) + assert('pubkeys' in info['embedded']) + elif typ == 'bech32': + # P2WSH-multisig + assert(info['isscript']) + assert_equal(info['script'], 'multisig') + assert(info['iswitness']) + assert_equal(info['witness_version'], 0) + assert_equal(len(info['witness_program']), 64) + assert('pubkeys' in info) + else: + # Unknown type + assert(False) + + def run_test(self): + # Mine 101 blocks on node4 to bring nodes out of IBD and make sure that + # no coinbases are maturing for the nodes-under-test during the test + self.nodes[4].generate(101) + sync_blocks(self.nodes) + + uncompressed_1 = "0496b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52da7589379515d4e0a604f8141781e62294721166bf621e73a82cbf2342c858ee" + uncompressed_2 = "047211a824f55b505228e4c3d5194c1fcfaa15a456abdf37f9b9d97a4040afc073dee6c89064984f03385237d92167c13e236446b417ab79a0fcae412ae3316b77" + compressed_1 = "0296b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52" + compressed_2 = "037211a824f55b505228e4c3d5194c1fcfaa15a456abdf37f9b9d97a4040afc073" + + # addmultisigaddress with at least 1 uncompressed key should return a legacy address. + for node in range(4): + self.test_address(node, self.nodes[node].addmultisigaddress(2, [uncompressed_1, uncompressed_2]), True, 'legacy') + self.test_address(node, self.nodes[node].addmultisigaddress(2, [compressed_1, uncompressed_2]), True, 'legacy') + self.test_address(node, self.nodes[node].addmultisigaddress(2, [uncompressed_1, compressed_2]), True, 'legacy') + # addmultisigaddress with all compressed keys should return the appropriate address type (even when the keys are not ours). + self.test_address(0, self.nodes[0].addmultisigaddress(2, [compressed_1, compressed_2]), True, 'legacy') + self.test_address(1, self.nodes[1].addmultisigaddress(2, [compressed_1, compressed_2]), True, 'p2sh-segwit') + self.test_address(2, self.nodes[2].addmultisigaddress(2, [compressed_1, compressed_2]), True, 'p2sh-segwit') + self.test_address(3, self.nodes[3].addmultisigaddress(2, [compressed_1, compressed_2]), True, 'bech32') + + for explicit_type, multisig, from_node in itertools.product([False, True], [False, True], range(4)): + address_type = None + if explicit_type and not multisig: + if from_node == 1: + address_type = 'bech32' + elif from_node == 0 or from_node == 3: + address_type = 'p2sh-segwit' + else: + address_type = 'legacy' + self.log.info("Sending from node {} ({}) with{} multisig using {}".format(from_node, self.extra_args[from_node], "" if multisig else "out", "default" if address_type is None else address_type)) + old_balances = self.get_balances() + self.log.debug("Old balances are {}".format(old_balances)) + to_send = (old_balances[from_node] / 101).quantize(Decimal("0.00000001")) + sends = {} + + self.log.debug("Prepare sends") + for n, to_node in enumerate(range(from_node, from_node + 4)): + to_node %= 4 + change = False + if not multisig: + if from_node == to_node: + # When sending non-multisig to self, use getrawchangeaddress + address = self.nodes[to_node].getrawchangeaddress(address_type=address_type) + change = True + else: + address = self.nodes[to_node].getnewaddress(address_type=address_type) + else: + addr1 = self.nodes[to_node].getnewaddress() + addr2 = self.nodes[to_node].getnewaddress() + address = self.nodes[to_node].addmultisigaddress(2, [addr1, addr2]) + + # Do some sanity checking on the created address + if address_type is not None: + typ = address_type + elif to_node == 0: + typ = 'legacy' + elif to_node == 1 or (to_node == 2 and not change): + typ = 'p2sh-segwit' + else: + typ = 'bech32' + self.test_address(to_node, address, multisig, typ) + + # Output entry + sends[address] = to_send * 10 * (1 + n) + + self.log.debug("Sending: {}".format(sends)) + self.nodes[from_node].sendmany("", sends) + sync_mempools(self.nodes) + + unconf_balances = self.get_balances(False) + self.log.debug("Check unconfirmed balances: {}".format(unconf_balances)) + assert_equal(unconf_balances[from_node], 0) + for n, to_node in enumerate(range(from_node + 1, from_node + 4)): + to_node %= 4 + assert_equal(unconf_balances[to_node], to_send * 10 * (2 + n)) + + # node4 collects fee and block subsidy to keep accounting simple + self.nodes[4].generate(1) + sync_blocks(self.nodes) + + new_balances = self.get_balances() + self.log.debug("Check new balances: {}".format(new_balances)) + # We don't know what fee was set, so we can only check bounds on the balance of the sending node + assert_greater_than(new_balances[from_node], to_send * 10) + assert_greater_than(to_send * 11, new_balances[from_node]) + for n, to_node in enumerate(range(from_node + 1, from_node + 4)): + to_node %= 4 + assert_equal(new_balances[to_node], old_balances[to_node] + to_send * 10 * (2 + n)) + +if __name__ == '__main__': + AddressTypeTest().main() diff --git a/test/functional/bip68-112-113-p2p.py b/test/functional/bip68-112-113-p2p.py index 30ceed3be7..82aa0ff891 100755 --- a/test/functional/bip68-112-113-p2p.py +++ b/test/functional/bip68-112-113-p2p.py @@ -95,7 +95,7 @@ class BIP68_112_113Test(ComparisonTestFramework): def set_test_params(self): self.num_nodes = 1 self.setup_clean_chain = True - self.extra_args = [['-whitelist=127.0.0.1', '-blockversion=4']] + self.extra_args = [['-whitelist=127.0.0.1', '-blockversion=4', '-addresstype=legacy']] def run_test(self): test = TestManager(self, self.options.tmpdir) diff --git a/test/functional/bip68-sequence.py b/test/functional/bip68-sequence.py index 2acdd72aff..94b13653b9 100755 --- a/test/functional/bip68-sequence.py +++ b/test/functional/bip68-sequence.py @@ -362,9 +362,10 @@ class BIP68Test(BitcoinTestFramework): block.vtx.extend([tx1, tx2, tx3]) block.hashMerkleRoot = block.calc_merkle_root() block.rehash() + add_witness_commitment(block) block.solve() - self.nodes[0].submitblock(ToHex(block)) + self.nodes[0].submitblock(bytes_to_hex_str(block.serialize(True))) assert_equal(self.nodes[0].getbestblockhash(), block.hash) def activateCSV(self): diff --git a/test/functional/bumpfee.py b/test/functional/bumpfee.py index ffd5ac197b..5cbd9f5cf7 100755 --- a/test/functional/bumpfee.py +++ b/test/functional/bumpfee.py @@ -194,7 +194,7 @@ def test_settxfee(rbf_node, dest_address): requested_feerate = Decimal("0.00025000") rbf_node.settxfee(requested_feerate) bumped_tx = rbf_node.bumpfee(rbfid) - actual_feerate = bumped_tx["fee"] * 1000 / rbf_node.getrawtransaction(bumped_tx["txid"], True)["size"] + actual_feerate = bumped_tx["fee"] * 1000 / rbf_node.getrawtransaction(bumped_tx["txid"], True)["vsize"] # Assert that the difference between the requested feerate and the actual # feerate of the bumped transaction is small. assert_greater_than(Decimal("0.00001000"), abs(requested_feerate - actual_feerate)) @@ -290,6 +290,7 @@ def submit_block_with_tx(node, tx): block.vtx.append(ctx) block.rehash() block.hashMerkleRoot = block.calc_merkle_root() + blocktools.add_witness_commitment(block) block.solve() node.submitblock(bytes_to_hex_str(block.serialize(True))) return block diff --git a/test/functional/create_cache.py b/test/functional/create_cache.py index 4c79814a26..9665c50a92 100755 --- a/test/functional/create_cache.py +++ b/test/functional/create_cache.py @@ -16,6 +16,7 @@ class CreateCache(BitcoinTestFramework): def set_test_params(self): self.num_nodes = 0 + self.supports_cli = True def setup_network(self): pass diff --git a/test/functional/import-rescan.py b/test/functional/import-rescan.py index 7d5fbb8d65..d193a99d5b 100755 --- a/test/functional/import-rescan.py +++ b/test/functional/import-rescan.py @@ -119,7 +119,7 @@ class ImportRescanTest(BitcoinTestFramework): self.num_nodes = 2 + len(IMPORT_NODES) def setup_network(self): - extra_args = [[] for _ in range(self.num_nodes)] + extra_args = [["-addresstype=legacy"] for _ in range(self.num_nodes)] for i, import_node in enumerate(IMPORT_NODES, 2): if import_node.prune: extra_args[i] += ["-prune=1"] diff --git a/test/functional/importmulti.py b/test/functional/importmulti.py index 35cb5b6768..ab4ca48e48 100755 --- a/test/functional/importmulti.py +++ b/test/functional/importmulti.py @@ -9,6 +9,7 @@ from test_framework.util import * class ImportMultiTest (BitcoinTestFramework): def set_test_params(self): self.num_nodes = 2 + self.extra_args = [["-addresstype=legacy"], ["-addresstype=legacy"]] self.setup_clean_chain = True def setup_network(self): diff --git a/test/functional/mempool_limit.py b/test/functional/mempool_limit.py index b2f718eb01..e7ce3820d2 100755 --- a/test/functional/mempool_limit.py +++ b/test/functional/mempool_limit.py @@ -17,10 +17,14 @@ class MempoolLimitTest(BitcoinTestFramework): txouts = gen_return_txouts() relayfee = self.nodes[0].getnetworkinfo()['relayfee'] + self.log.info('Check that mempoolminfee is minrelytxfee') + assert_equal(self.nodes[0].getmempoolinfo()['minrelaytxfee'], Decimal('0.00001000')) + assert_equal(self.nodes[0].getmempoolinfo()['mempoolminfee'], Decimal('0.00001000')) + txids = [] utxos = create_confirmed_utxos(relayfee, self.nodes[0], 91) - #create a mempool tx that will be evicted + self.log.info('Create a mempool tx that will be evicted') us0 = utxos.pop() inputs = [{ "txid" : us0["txid"], "vout" : us0["vout"]}] outputs = {self.nodes[0].getnewaddress() : 0.0001} @@ -37,10 +41,14 @@ class MempoolLimitTest(BitcoinTestFramework): txids.append([]) txids[i] = create_lots_of_big_transactions(self.nodes[0], txouts, utxos[30*i:30*i+30], 30, (i+1)*base_fee) - # by now, the tx should be evicted, check confirmation state + self.log.info('The tx should be evicted by now') assert(txid not in self.nodes[0].getrawmempool()) txdata = self.nodes[0].gettransaction(txid) assert(txdata['confirmations'] == 0) #confirmation should still be 0 + self.log.info('Check that mempoolminfee is larger than minrelytxfee') + assert_equal(self.nodes[0].getmempoolinfo()['minrelaytxfee'], Decimal('0.00001000')) + assert_greater_than(self.nodes[0].getmempoolinfo()['mempoolminfee'], Decimal('0.00001000')) + if __name__ == '__main__': MempoolLimitTest().main() diff --git a/test/functional/multiwallet.py b/test/functional/multiwallet.py index d0c40e5446..12d9e9f48d 100755 --- a/test/functional/multiwallet.py +++ b/test/functional/multiwallet.py @@ -17,9 +17,16 @@ class MultiWalletTest(BitcoinTestFramework): self.setup_clean_chain = True self.num_nodes = 1 self.extra_args = [['-wallet=w1', '-wallet=w2', '-wallet=w3', '-wallet=w']] + self.supports_cli = True def run_test(self): - assert_equal(set(self.nodes[0].listwallets()), {"w1", "w2", "w3", "w"}) + node = self.nodes[0] + + data_dir = lambda *p: os.path.join(node.datadir, 'regtest', *p) + wallet_dir = lambda *p: data_dir('wallets', *p) + wallet = lambda name: node.get_wallet_rpc(name) + + assert_equal(set(node.listwallets()), {"w1", "w2", "w3", "w"}) self.stop_node(0) @@ -27,39 +34,38 @@ class MultiWalletTest(BitcoinTestFramework): self.assert_start_raises_init_error(0, ['-wallet=w1', '-wallet=w1'], 'Error loading wallet w1. Duplicate -wallet filename specified.') # should not initialize if wallet file is a directory - wallet_dir = os.path.join(self.options.tmpdir, 'node0', 'regtest', 'wallets') - os.mkdir(os.path.join(wallet_dir, 'w11')) + os.mkdir(wallet_dir('w11')) self.assert_start_raises_init_error(0, ['-wallet=w11'], 'Error loading wallet w11. -wallet filename must be a regular file.') # should not initialize if one wallet is a copy of another - shutil.copyfile(os.path.join(wallet_dir, 'w2'), os.path.join(wallet_dir, 'w22')) + shutil.copyfile(wallet_dir('w2'), wallet_dir('w22')) self.assert_start_raises_init_error(0, ['-wallet=w2', '-wallet=w22'], 'duplicates fileid') # should not initialize if wallet file is a symlink - os.symlink(os.path.join(wallet_dir, 'w1'), os.path.join(wallet_dir, 'w12')) + os.symlink(wallet_dir('w1'), wallet_dir('w12')) self.assert_start_raises_init_error(0, ['-wallet=w12'], 'Error loading wallet w12. -wallet filename must be a regular file.') # should not initialize if the specified walletdir does not exist self.assert_start_raises_init_error(0, ['-walletdir=bad'], 'Error: Specified -walletdir "bad" does not exist') # should not initialize if the specified walletdir is not a directory - not_a_dir = os.path.join(wallet_dir, 'notadir') + not_a_dir = wallet_dir('notadir') open(not_a_dir, 'a').close() - self.assert_start_raises_init_error(0, ['-walletdir='+not_a_dir], 'Error: Specified -walletdir "' + not_a_dir + '" is not a directory') + self.assert_start_raises_init_error(0, ['-walletdir=' + not_a_dir], 'Error: Specified -walletdir "' + not_a_dir + '" is not a directory') # if wallets/ doesn't exist, datadir should be the default wallet dir - wallet_dir2 = os.path.join(self.options.tmpdir, 'node0', 'regtest', 'walletdir') - os.rename(wallet_dir, wallet_dir2) + wallet_dir2 = data_dir('walletdir') + os.rename(wallet_dir(), wallet_dir2) self.start_node(0, ['-wallet=w4', '-wallet=w5']) - assert_equal(set(self.nodes[0].listwallets()), {"w4", "w5"}) - w5 = self.nodes[0].get_wallet_rpc("w5") + assert_equal(set(node.listwallets()), {"w4", "w5"}) + w5 = wallet("w5") w5.generate(1) self.stop_node(0) # now if wallets/ exists again, but the rootdir is specified as the walletdir, w4 and w5 should still be loaded - os.rename(wallet_dir2, wallet_dir) - self.start_node(0, ['-wallet=w4', '-wallet=w5', '-walletdir=' + os.path.join(self.options.tmpdir, 'node0', 'regtest')]) - assert_equal(set(self.nodes[0].listwallets()), {"w4", "w5"}) - w5 = self.nodes[0].get_wallet_rpc("w5") + os.rename(wallet_dir2, wallet_dir()) + self.start_node(0, ['-wallet=w4', '-wallet=w5', '-walletdir=' + data_dir()]) + assert_equal(set(node.listwallets()), {"w4", "w5"}) + w5 = wallet("w5") w5_info = w5.getwalletinfo() assert_equal(w5_info['immature_balance'], 50) @@ -67,11 +73,11 @@ class MultiWalletTest(BitcoinTestFramework): self.start_node(0, self.extra_args[0]) - w1 = self.nodes[0].get_wallet_rpc("w1") - w2 = self.nodes[0].get_wallet_rpc("w2") - w3 = self.nodes[0].get_wallet_rpc("w3") - w4 = self.nodes[0].get_wallet_rpc("w") - wallet_bad = self.nodes[0].get_wallet_rpc("bad") + w1 = wallet("w1") + w2 = wallet("w2") + w3 = wallet("w3") + w4 = wallet("w") + wallet_bad = wallet("bad") w1.generate(1) @@ -79,7 +85,7 @@ class MultiWalletTest(BitcoinTestFramework): assert_raises_rpc_error(-18, "Requested wallet does not exist or is not loaded", wallet_bad.getwalletinfo) # accessing wallet RPC without using wallet endpoint fails - assert_raises_rpc_error(-19, "Wallet file not specified", self.nodes[0].getwalletinfo) + assert_raises_rpc_error(-19, "Wallet file not specified", node.getwalletinfo) # check w1 wallet balance w1_info = w1.getwalletinfo() diff --git a/test/functional/nulldummy.py b/test/functional/nulldummy.py index a94fe8204f..110b7a655e 100755 --- a/test/functional/nulldummy.py +++ b/test/functional/nulldummy.py @@ -42,7 +42,7 @@ class NULLDUMMYTest(BitcoinTestFramework): self.setup_clean_chain = True # This script tests NULLDUMMY activation, which is part of the 'segwit' deployment, so we go through # normal segwit activation here (and don't use the default always-on behaviour). - self.extra_args = [['-whitelist=127.0.0.1', '-walletprematurewitness', '-vbparams=segwit:0:999999999999']] + self.extra_args = [['-whitelist=127.0.0.1', '-walletprematurewitness', '-vbparams=segwit:0:999999999999', '-addresstype=legacy']] def run_test(self): self.address = self.nodes[0].getnewaddress() diff --git a/test/functional/p2p-fullblocktest.py b/test/functional/p2p-fullblocktest.py index d08318a96b..fe9bbda14b 100755 --- a/test/functional/p2p-fullblocktest.py +++ b/test/functional/p2p-fullblocktest.py @@ -36,12 +36,15 @@ class CBrokenBlock(CBlock): self.vtx = copy.deepcopy(base_block.vtx) self.hashMerkleRoot = self.calc_merkle_root() - def serialize(self): + def serialize(self, with_witness=False): r = b"" r += super(CBlock, self).serialize() r += struct.pack("<BQ", 255, len(self.vtx)) for tx in self.vtx: - r += tx.serialize() + if with_witness: + r += tx.serialize_with_witness() + else: + r += tx.serialize_without_witness() return r def normal_serialize(self): diff --git a/test/functional/p2p-segwit.py b/test/functional/p2p-segwit.py index 2487fdc239..20e4805df0 100755 --- a/test/functional/p2p-segwit.py +++ b/test/functional/p2p-segwit.py @@ -25,7 +25,7 @@ MAX_SIGOP_COST = 80000 # Calculate the virtual size of a witness block: # (base + witness/4) def get_virtual_size(witness_block): - base_size = len(witness_block.serialize()) + base_size = len(witness_block.serialize(with_witness=False)) total_size = len(witness_block.serialize(with_witness=True)) # the "+3" is so we round up vsize = int((3*base_size + total_size + 3)/4) @@ -1396,18 +1396,20 @@ class SegWitTest(BitcoinTestFramework): temp_utxos.pop(0) - # Update self.utxos for later tests. Just spend everything in - # temp_utxos to a corresponding entry in self.utxos + # Update self.utxos for later tests by creating two outputs + # that consolidate all the coins in temp_utxos. + output_value = sum(i.nValue for i in temp_utxos) // 2 + tx = CTransaction() index = 0 + # Just spend to our usual anyone-can-spend output + tx.vout = [CTxOut(output_value, CScript([OP_TRUE]))] * 2 for i in temp_utxos: - # Just spend to our usual anyone-can-spend output - # Use SIGHASH_SINGLE|SIGHASH_ANYONECANPAY so we can build up + # Use SIGHASH_ALL|SIGHASH_ANYONECANPAY so we can build up # the signatures as we go. tx.vin.append(CTxIn(COutPoint(i.sha256, i.n), b"")) - tx.vout.append(CTxOut(i.nValue, CScript([OP_TRUE]))) tx.wit.vtxinwit.append(CTxInWitness()) - sign_P2PK_witness_input(witness_program, tx, index, SIGHASH_SINGLE|SIGHASH_ANYONECANPAY, i.nValue, key) + sign_P2PK_witness_input(witness_program, tx, index, SIGHASH_ALL|SIGHASH_ANYONECANPAY, i.nValue, key) index += 1 block = self.build_next_block() self.update_witness_block_with_transactions(block, [tx]) diff --git a/test/functional/prioritise_transaction.py b/test/functional/prioritise_transaction.py index c10042ddb2..57954ce321 100755 --- a/test/functional/prioritise_transaction.py +++ b/test/functional/prioritise_transaction.py @@ -15,6 +15,25 @@ class PrioritiseTransactionTest(BitcoinTestFramework): self.extra_args = [["-printpriority=1"], ["-printpriority=1"]] def run_test(self): + # Test `prioritisetransaction` required parameters + assert_raises_rpc_error(-1, "prioritisetransaction", self.nodes[0].prioritisetransaction) + assert_raises_rpc_error(-1, "prioritisetransaction", self.nodes[0].prioritisetransaction, '') + assert_raises_rpc_error(-1, "prioritisetransaction", self.nodes[0].prioritisetransaction, '', 0) + + # Test `prioritisetransaction` invalid extra parameters + assert_raises_rpc_error(-1, "prioritisetransaction", self.nodes[0].prioritisetransaction, '', 0, 0, 0) + + # Test `prioritisetransaction` invalid `txid` + assert_raises_rpc_error(-1, "txid must be hexadecimal string", self.nodes[0].prioritisetransaction, txid='foo', fee_delta=0) + + # Test `prioritisetransaction` invalid `dummy` + txid = '1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000' + assert_raises_rpc_error(-1, "JSON value is not a number as expected", self.nodes[0].prioritisetransaction, txid, 'foo', 0) + assert_raises_rpc_error(-8, "Priority is no longer supported, dummy argument to prioritisetransaction must be 0.", self.nodes[0].prioritisetransaction, txid, 1, 0) + + # Test `prioritisetransaction` invalid `fee_delta` + assert_raises_rpc_error(-1, "JSON value is not an integer as expected", self.nodes[0].prioritisetransaction, txid=txid, fee_delta='foo') + self.txouts = gen_return_txouts() self.relayfee = self.nodes[0].getnetworkinfo()['relayfee'] diff --git a/test/functional/rawtransactions.py b/test/functional/rawtransactions.py index 073ed394c1..fe749adb49 100755 --- a/test/functional/rawtransactions.py +++ b/test/functional/rawtransactions.py @@ -39,6 +39,7 @@ class RawTransactionsTest(BitcoinTestFramework): def set_test_params(self): self.setup_clean_chain = True self.num_nodes = 3 + self.extra_args = [["-addresstype=legacy"], ["-addresstype=legacy"], ["-addresstype=legacy"]] def setup_network(self, split=False): super().setup_network() @@ -189,7 +190,7 @@ class RawTransactionsTest(BitcoinTestFramework): break bal = self.nodes[0].getbalance() - inputs = [{ "txid" : txId, "vout" : vout['n'], "scriptPubKey" : vout['scriptPubKey']['hex']}] + inputs = [{ "txid" : txId, "vout" : vout['n'], "scriptPubKey" : vout['scriptPubKey']['hex'], "amount" : vout['value']}] outputs = { self.nodes[0].getnewaddress() : 2.19 } rawTx = self.nodes[2].createrawtransaction(inputs, outputs) rawTxPartialSigned = self.nodes[1].signrawtransaction(rawTx, inputs) @@ -234,7 +235,7 @@ class RawTransactionsTest(BitcoinTestFramework): break bal = self.nodes[0].getbalance() - inputs = [{ "txid" : txId, "vout" : vout['n'], "scriptPubKey" : vout['scriptPubKey']['hex'], "redeemScript" : mSigObjValid['hex']}] + inputs = [{ "txid" : txId, "vout" : vout['n'], "scriptPubKey" : vout['scriptPubKey']['hex'], "redeemScript" : mSigObjValid['hex'], "amount" : vout['value']}] outputs = { self.nodes[0].getnewaddress() : 2.19 } rawTx2 = self.nodes[2].createrawtransaction(inputs, outputs) rawTxPartialSigned1 = self.nodes[1].signrawtransaction(rawTx2, inputs) diff --git a/test/functional/segwit.py b/test/functional/segwit.py index dbf4a86e38..5a4a7468e5 100755 --- a/test/functional/segwit.py +++ b/test/functional/segwit.py @@ -78,9 +78,9 @@ class SegWitTest(BitcoinTestFramework): self.setup_clean_chain = True self.num_nodes = 3 # This test tests SegWit both pre and post-activation, so use the normal BIP9 activation. - self.extra_args = [["-walletprematurewitness", "-rpcserialversion=0", "-vbparams=segwit:0:999999999999"], - ["-blockversion=4", "-promiscuousmempoolflags=517", "-prematurewitness", "-walletprematurewitness", "-rpcserialversion=1", "-vbparams=segwit:0:999999999999"], - ["-blockversion=536870915", "-promiscuousmempoolflags=517", "-prematurewitness", "-walletprematurewitness", "-vbparams=segwit:0:999999999999"]] + self.extra_args = [["-walletprematurewitness", "-rpcserialversion=0", "-vbparams=segwit:0:999999999999", "-addresstype=legacy"], + ["-blockversion=4", "-promiscuousmempoolflags=517", "-prematurewitness", "-walletprematurewitness", "-rpcserialversion=1", "-vbparams=segwit:0:999999999999", "-addresstype=legacy"], + ["-blockversion=536870915", "-promiscuousmempoolflags=517", "-prematurewitness", "-walletprematurewitness", "-vbparams=segwit:0:999999999999", "-addresstype=legacy"]] def setup_network(self): super().setup_network() @@ -135,9 +135,9 @@ class SegWitTest(BitcoinTestFramework): self.pubkey.append(self.nodes[i].validateaddress(newaddress)["pubkey"]) multiaddress = self.nodes[i].addmultisigaddress(1, [self.pubkey[-1]]) multiscript = CScript([OP_1, hex_str_to_bytes(self.pubkey[-1]), OP_1, OP_CHECKMULTISIG]) - p2sh_addr = self.nodes[i].addwitnessaddress(newaddress, True) + p2sh_addr = self.nodes[i].addwitnessaddress(newaddress) bip173_addr = self.nodes[i].addwitnessaddress(newaddress, False) - p2sh_ms_addr = self.nodes[i].addwitnessaddress(multiaddress, True) + p2sh_ms_addr = self.nodes[i].addwitnessaddress(multiaddress) bip173_ms_addr = self.nodes[i].addwitnessaddress(multiaddress, False) assert_equal(p2sh_addr, key_to_p2sh_p2wpkh(self.pubkey[-1])) assert_equal(bip173_addr, key_to_p2wpkh(self.pubkey[-1])) @@ -356,8 +356,10 @@ class SegWitTest(BitcoinTestFramework): [p2wpkh, p2sh_p2wpkh, p2pk, p2pkh, p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh] = self.p2pkh_address_to_script(v) # normal P2PKH and P2PK with compressed keys should always be spendable spendable_anytime.extend([p2pkh, p2pk]) - # P2SH_P2PK, P2SH_P2PKH, and witness with compressed keys are spendable after direct importaddress - spendable_after_importaddress.extend([p2wpkh, p2sh_p2wpkh, p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh]) + # P2SH_P2PK, P2SH_P2PKH with compressed keys are spendable after direct importaddress + spendable_after_importaddress.extend([p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh]) + # P2WPKH and P2SH_P2WPKH with compressed keys should always be spendable + spendable_anytime.extend([p2wpkh, p2sh_p2wpkh]) for i in uncompressed_spendable_address: v = self.nodes[0].validateaddress(i) @@ -373,7 +375,7 @@ class SegWitTest(BitcoinTestFramework): spendable_anytime.extend([p2pkh, p2pk]) # P2SH_P2PK and P2SH_P2PKH are spendable after direct importaddress spendable_after_importaddress.extend([p2sh_p2pk, p2sh_p2pkh]) - # witness with uncompressed keys are never seen + # Witness output types with uncompressed keys are never seen unseen_anytime.extend([p2wpkh, p2sh_p2wpkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh]) for i in compressed_solvable_address: @@ -384,10 +386,10 @@ class SegWitTest(BitcoinTestFramework): solvable_after_importaddress.extend([bare, p2sh, p2wsh, p2sh_p2wsh]) else: [p2wpkh, p2sh_p2wpkh, p2pk, p2pkh, p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh] = self.p2pkh_address_to_script(v) - # normal P2PKH and P2PK with compressed keys should always be seen - solvable_anytime.extend([p2pkh, p2pk]) - # P2SH_P2PK, P2SH_P2PKH, and witness with compressed keys are seen after direct importaddress - solvable_after_importaddress.extend([p2wpkh, p2sh_p2wpkh, p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh]) + # normal P2PKH, P2PK, P2WPKH and P2SH_P2WPKH with compressed keys should always be seen + solvable_anytime.extend([p2pkh, p2pk, p2wpkh, p2sh_p2wpkh]) + # P2SH_P2PK, P2SH_P2PKH with compressed keys are seen after direct importaddress + solvable_after_importaddress.extend([p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh]) for i in uncompressed_solvable_address: v = self.nodes[0].validateaddress(i) @@ -403,7 +405,7 @@ class SegWitTest(BitcoinTestFramework): solvable_anytime.extend([p2pkh, p2pk]) # P2SH_P2PK, P2SH_P2PKH with uncompressed keys are seen after direct importaddress solvable_after_importaddress.extend([p2sh_p2pk, p2sh_p2pkh]) - # witness with uncompressed keys are never seen + # Witness output types with uncompressed keys are never seen unseen_anytime.extend([p2wpkh, p2sh_p2wpkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh]) op1 = CScript([OP_1]) @@ -496,6 +498,8 @@ class SegWitTest(BitcoinTestFramework): spendable_after_addwitnessaddress = [] # These outputs should be seen after importaddress solvable_after_addwitnessaddress=[] # These outputs should be seen after importaddress but not spendable unseen_anytime = [] # These outputs should never be seen + solvable_anytime = [] # These outputs should be solvable after importpubkey + unseen_anytime = [] # These outputs should never be seen uncompressed_spendable_address.append(self.nodes[0].addmultisigaddress(2, [uncompressed_spendable_address[0], compressed_spendable_address[0]])) uncompressed_spendable_address.append(self.nodes[0].addmultisigaddress(2, [uncompressed_spendable_address[0], uncompressed_spendable_address[0]])) @@ -514,9 +518,8 @@ class SegWitTest(BitcoinTestFramework): premature_witaddress.append(script_to_p2sh(p2wsh)) else: [p2wpkh, p2sh_p2wpkh, p2pk, p2pkh, p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh] = self.p2pkh_address_to_script(v) - # P2WPKH, P2SH_P2WPKH are spendable after addwitnessaddress - spendable_after_addwitnessaddress.extend([p2wpkh, p2sh_p2wpkh]) - premature_witaddress.append(script_to_p2sh(p2wpkh)) + # P2WPKH, P2SH_P2WPKH are always spendable + spendable_anytime.extend([p2wpkh, p2sh_p2wpkh]) for i in uncompressed_spendable_address + uncompressed_solvable_address: v = self.nodes[0].validateaddress(i) @@ -538,10 +541,11 @@ class SegWitTest(BitcoinTestFramework): premature_witaddress.append(script_to_p2sh(p2wsh)) else: [p2wpkh, p2sh_p2wpkh, p2pk, p2pkh, p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh] = self.p2pkh_address_to_script(v) - # P2SH_P2PK, P2SH_P2PKH with compressed keys are seen after addwitnessaddress - solvable_after_addwitnessaddress.extend([p2wpkh, p2sh_p2wpkh]) - premature_witaddress.append(script_to_p2sh(p2wpkh)) + # P2SH_P2PK, P2SH_P2PKH with compressed keys are always solvable + solvable_anytime.extend([p2wpkh, p2sh_p2wpkh]) + self.mine_and_test_listunspent(spendable_anytime, 2) + self.mine_and_test_listunspent(solvable_anytime, 1) self.mine_and_test_listunspent(spendable_after_addwitnessaddress + solvable_after_addwitnessaddress + unseen_anytime, 0) # addwitnessaddress should refuse to return a witness address if an uncompressed key is used @@ -558,8 +562,8 @@ class SegWitTest(BitcoinTestFramework): witaddress = self.nodes[0].addwitnessaddress(i) assert_equal(witaddress, self.nodes[0].addwitnessaddress(witaddress)) - spendable_txid.append(self.mine_and_test_listunspent(spendable_after_addwitnessaddress, 2)) - solvable_txid.append(self.mine_and_test_listunspent(solvable_after_addwitnessaddress, 1)) + spendable_txid.append(self.mine_and_test_listunspent(spendable_after_addwitnessaddress + spendable_anytime, 2)) + solvable_txid.append(self.mine_and_test_listunspent(solvable_after_addwitnessaddress + solvable_anytime, 1)) self.mine_and_test_listunspent(unseen_anytime, 0) # Check that createrawtransaction/decoderawtransaction with non-v0 Bech32 works diff --git a/test/functional/signmessages.py b/test/functional/signmessages.py index c1939b432b..5b6935ceea 100755 --- a/test/functional/signmessages.py +++ b/test/functional/signmessages.py @@ -11,6 +11,7 @@ class SignMessagesTest(BitcoinTestFramework): def set_test_params(self): self.setup_clean_chain = True self.num_nodes = 1 + self.extra_args = [["-addresstype=legacy"]] def run_test(self): message = 'This is just a test message' diff --git a/test/functional/test_framework/messages.py b/test/functional/test_framework/messages.py index d8032e4430..a54a0299c7 100644 --- a/test/functional/test_framework/messages.py +++ b/test/functional/test_framework/messages.py @@ -453,10 +453,10 @@ class CTransaction(): r += struct.pack("<I", self.nLockTime) return r - # Regular serialization is without witness -- must explicitly - # call serialize_with_witness to include witness data. + # Regular serialization is with witness -- must explicitly + # call serialize_without_witness to exclude witness data. def serialize(self): - return self.serialize_without_witness() + return self.serialize_with_witness() # Recalculate the txid (transaction hash without witness) def rehash(self): @@ -472,7 +472,7 @@ class CTransaction(): if self.sha256 is None: self.sha256 = uint256_from_str(hash256(self.serialize_without_witness())) - self.hash = encode(hash256(self.serialize())[::-1], 'hex_codec').decode('ascii') + self.hash = encode(hash256(self.serialize_without_witness())[::-1], 'hex_codec').decode('ascii') def is_valid(self): self.calc_sha256() @@ -569,7 +569,7 @@ class CBlock(CBlockHeader): if with_witness: r += ser_vector(self.vtx, "serialize_with_witness") else: - r += ser_vector(self.vtx) + r += ser_vector(self.vtx, "serialize_without_witness") return r # Calculate the merkle root given a vector of transaction hashes @@ -636,7 +636,7 @@ class PrefilledTransaction(): self.tx = CTransaction() self.tx.deserialize(f) - def serialize(self, with_witness=False): + def serialize(self, with_witness=True): r = b"" r += ser_compact_size(self.index) if with_witness: @@ -645,6 +645,9 @@ class PrefilledTransaction(): r += self.tx.serialize_without_witness() return r + def serialize_without_witness(self): + return self.serialize(with_witness=False) + def serialize_with_witness(self): return self.serialize(with_witness=True) @@ -684,7 +687,7 @@ class P2PHeaderAndShortIDs(): if with_witness: r += ser_vector(self.prefilled_txn, "serialize_with_witness") else: - r += ser_vector(self.prefilled_txn) + r += ser_vector(self.prefilled_txn, "serialize_without_witness") return r def __repr__(self): @@ -815,13 +818,13 @@ class BlockTransactions(): self.blockhash = deser_uint256(f) self.transactions = deser_vector(f, CTransaction) - def serialize(self, with_witness=False): + def serialize(self, with_witness=True): r = b"" r += ser_uint256(self.blockhash) if with_witness: r += ser_vector(self.transactions, "serialize_with_witness") else: - r += ser_vector(self.transactions) + r += ser_vector(self.transactions, "serialize_without_witness") return r def __repr__(self): @@ -1021,7 +1024,7 @@ class msg_block(): self.block.deserialize(f) def serialize(self): - return self.block.serialize() + return self.block.serialize(with_witness=False) def __repr__(self): return "msg_block(block=%s)" % (repr(self.block)) @@ -1292,7 +1295,7 @@ class msg_blocktxn(): def serialize(self): r = b"" - r += self.block_transactions.serialize() + r += self.block_transactions.serialize(with_witness=False) return r def __repr__(self): diff --git a/test/functional/test_framework/script.py b/test/functional/test_framework/script.py index 8429f34c41..dae8a4e569 100644 --- a/test/functional/test_framework/script.py +++ b/test/functional/test_framework/script.py @@ -641,7 +641,7 @@ def SignatureHash(script, txTo, inIdx, hashtype): txtmp.vin = [] txtmp.vin.append(tmp) - s = txtmp.serialize() + s = txtmp.serialize_without_witness() s += struct.pack(b"<I", hashtype) hash = hash256(s) diff --git a/test/functional/test_framework/test_framework.py b/test/functional/test_framework/test_framework.py index e42f3e60c2..5d4f8e6720 100755 --- a/test/functional/test_framework/test_framework.py +++ b/test/functional/test_framework/test_framework.py @@ -62,6 +62,7 @@ class BitcoinTestFramework(): self.setup_clean_chain = False self.nodes = [] self.mocktime = 0 + self.supports_cli = False self.set_test_params() assert hasattr(self, "num_nodes"), "Test must set self.num_nodes in set_test_params()" @@ -91,6 +92,8 @@ class BitcoinTestFramework(): help="Location of the test framework config file") parser.add_option("--pdbonfailure", dest="pdbonfailure", default=False, action="store_true", help="Attach a python debugger if test fails") + parser.add_option("--usecli", dest="usecli", default=False, action="store_true", + help="use bitcoin-cli instead of RPC for all commands") self.add_options(parser) (self.options, self.args) = parser.parse_args() @@ -113,6 +116,8 @@ class BitcoinTestFramework(): success = TestStatus.FAILED try: + if self.options.usecli and not self.supports_cli: + raise SkipTest("--usecli specified but test does not support using CLI") self.setup_chain() self.setup_network() self.run_test() @@ -213,7 +218,7 @@ class BitcoinTestFramework(): assert_equal(len(extra_args), num_nodes) assert_equal(len(binary), num_nodes) for i in range(num_nodes): - self.nodes.append(TestNode(i, self.options.tmpdir, extra_args[i], rpchost, timewait=timewait, binary=binary[i], stderr=None, mocktime=self.mocktime, coverage_dir=self.options.coveragedir)) + self.nodes.append(TestNode(i, self.options.tmpdir, extra_args[i], rpchost, timewait=timewait, binary=binary[i], stderr=None, mocktime=self.mocktime, coverage_dir=self.options.coveragedir, use_cli=self.options.usecli)) def start_node(self, i, extra_args=None, stderr=None): """Start a bitcoind""" diff --git a/test/functional/test_framework/test_node.py b/test/functional/test_framework/test_node.py index a9248c764e..589a8f3969 100755 --- a/test/functional/test_framework/test_node.py +++ b/test/functional/test_framework/test_node.py @@ -10,6 +10,7 @@ import http.client import json import logging import os +import re import subprocess import time @@ -22,6 +23,9 @@ from .util import ( p2p_port, ) +# For Python 3.4 compatibility +JSONDecodeError = getattr(json, "JSONDecodeError", ValueError) + BITCOIND_PROC_WAIT_TIMEOUT = 60 class TestNode(): @@ -38,7 +42,7 @@ class TestNode(): To make things easier for the test writer, any unrecognised messages will be dispatched to the RPC connection.""" - def __init__(self, i, dirname, extra_args, rpchost, timewait, binary, stderr, mocktime, coverage_dir): + def __init__(self, i, dirname, extra_args, rpchost, timewait, binary, stderr, mocktime, coverage_dir, use_cli=False): self.index = i self.datadir = os.path.join(dirname, "node" + str(i)) self.rpchost = rpchost @@ -58,6 +62,7 @@ class TestNode(): self.args = [self.binary, "-datadir=" + self.datadir, "-server", "-keypool=1", "-discover=0", "-rest", "-logtimemicros", "-debug", "-debugexclude=libevent", "-debugexclude=leveldb", "-mocktime=" + str(mocktime), "-uacomment=testnode%d" % i] self.cli = TestNodeCLI(os.getenv("BITCOINCLI", "bitcoin-cli"), self.datadir) + self.use_cli = use_cli self.running = False self.process = None @@ -69,9 +74,12 @@ class TestNode(): self.p2ps = [] def __getattr__(self, name): - """Dispatches any unrecognised messages to the RPC connection.""" - assert self.rpc_connected and self.rpc is not None, "Error: no RPC connection" - return getattr(self.rpc, name) + """Dispatches any unrecognised messages to the RPC connection or a CLI instance.""" + if self.use_cli: + return getattr(self.cli, name) + else: + assert self.rpc_connected and self.rpc is not None, "Error: no RPC connection" + return getattr(self.rpc, name) def start(self, extra_args=None, stderr=None): """Start the node.""" @@ -110,10 +118,13 @@ class TestNode(): raise AssertionError("Unable to connect to bitcoind") def get_wallet_rpc(self, wallet_name): - assert self.rpc_connected - assert self.rpc - wallet_path = "wallet/%s" % wallet_name - return self.rpc / wallet_path + if self.use_cli: + return self.cli("-rpcwallet={}".format(wallet_name)) + else: + assert self.rpc_connected + assert self.rpc + wallet_path = "wallet/%s" % wallet_name + return self.rpc / wallet_path def stop_node(self): """Stop the node.""" @@ -187,6 +198,16 @@ class TestNode(): p.peer_disconnect() del self.p2ps[:] +class TestNodeCLIAttr: + def __init__(self, cli, command): + self.cli = cli + self.command = command + + def __call__(self, *args, **kwargs): + return self.cli.send_cli(self.command, *args, **kwargs) + + def get_request(self, *args, **kwargs): + return lambda: self(*args, **kwargs) class TestNodeCLI(): """Interface to bitcoin-cli for an individual node""" @@ -196,17 +217,26 @@ class TestNodeCLI(): self.binary = binary self.datadir = datadir self.input = None + self.log = logging.getLogger('TestFramework.bitcoincli') def __call__(self, *args, input=None): # TestNodeCLI is callable with bitcoin-cli command-line args - self.args = [str(arg) for arg in args] - self.input = input - return self + cli = TestNodeCLI(self.binary, self.datadir) + cli.args = [str(arg) for arg in args] + cli.input = input + return cli def __getattr__(self, command): - def dispatcher(*args, **kwargs): - return self.send_cli(command, *args, **kwargs) - return dispatcher + return TestNodeCLIAttr(self, command) + + def batch(self, requests): + results = [] + for request in requests: + try: + results.append(dict(result=request())) + except JSONRPCException as e: + results.append(dict(error=e)) + return results def send_cli(self, command, *args, **kwargs): """Run bitcoin-cli command. Deserializes returned string as python object.""" @@ -218,10 +248,18 @@ class TestNodeCLI(): if named_args: p_args += ["-named"] p_args += [command] + pos_args + named_args + self.log.debug("Running bitcoin-cli command: %s" % command) process = subprocess.Popen(p_args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True) cli_stdout, cli_stderr = process.communicate(input=self.input) returncode = process.poll() if returncode: + match = re.match(r'error code: ([-0-9]+)\nerror message:\n(.*)', cli_stderr) + if match: + code, message = match.groups() + raise JSONRPCException(dict(code=int(code), message=message)) # Ignore cli_stdout, raise with cli_stderr raise subprocess.CalledProcessError(returncode, self.binary, output=cli_stderr) - return json.loads(cli_stdout, parse_float=decimal.Decimal) + try: + return json.loads(cli_stdout, parse_float=decimal.Decimal) + except JSONDecodeError: + return cli_stdout.rstrip("\n") diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py index 428a18be86..957a2bc5a7 100755 --- a/test/functional/test_runner.py +++ b/test/functional/test_runner.py @@ -78,6 +78,7 @@ BASE_SCRIPTS= [ 'abandonconflict.py', 'bip68-112-113-p2p.py', 'rawtransactions.py', + 'address_types.py', 'reindex.py', # vv Tests less than 30s vv 'keypool-topup.py', @@ -86,12 +87,14 @@ BASE_SCRIPTS= [ 'mempool_resurrect_test.py', 'txn_doublespend.py --mineblock', 'txn_clone.py', + 'txn_clone.py --segwit', 'getchaintips.py', 'rest.py', 'mempool_spendcoinbase.py', 'mempool_reorg.py', 'mempool_persist.py', 'multiwallet.py', + 'multiwallet.py --usecli', 'httpbasics.py', 'multi_rpc.py', 'proxy_test.py', diff --git a/test/functional/txn_clone.py b/test/functional/txn_clone.py index c50f86341f..ce26d6e0ee 100755 --- a/test/functional/txn_clone.py +++ b/test/functional/txn_clone.py @@ -14,6 +14,8 @@ class TxnMallTest(BitcoinTestFramework): def add_options(self, parser): parser.add_option("--mineblock", dest="mine_block", default=False, action="store_true", help="Test double-spend of 1-confirmed transaction") + parser.add_option("--segwit", dest="segwit", default=False, action="store_true", + help="Test behaviour with SegWit txn (which should fail") def setup_network(self): # Start with split network: @@ -22,6 +24,11 @@ class TxnMallTest(BitcoinTestFramework): disconnect_nodes(self.nodes[2], 1) def run_test(self): + if self.options.segwit: + output_type="p2sh-segwit" + else: + output_type="legacy" + # All nodes should start with 1,250 BTC: starting_balance = 1250 for i in range(4): @@ -31,11 +38,11 @@ class TxnMallTest(BitcoinTestFramework): # Assign coins to foo and bar accounts: self.nodes[0].settxfee(.001) - node0_address_foo = self.nodes[0].getnewaddress("foo") + node0_address_foo = self.nodes[0].getnewaddress("foo", output_type) fund_foo_txid = self.nodes[0].sendfrom("", node0_address_foo, 1219) fund_foo_tx = self.nodes[0].gettransaction(fund_foo_txid) - node0_address_bar = self.nodes[0].getnewaddress("bar") + node0_address_bar = self.nodes[0].getnewaddress("bar", output_type) fund_bar_txid = self.nodes[0].sendfrom("", node0_address_bar, 29) fund_bar_tx = self.nodes[0].gettransaction(fund_bar_txid) @@ -106,6 +113,10 @@ class TxnMallTest(BitcoinTestFramework): # Send clone and its parent to miner self.nodes[2].sendrawtransaction(fund_foo_tx["hex"]) txid1_clone = self.nodes[2].sendrawtransaction(tx1_clone["hex"]) + if self.options.segwit: + assert_equal(txid1, txid1_clone) + return + # ... mine a block... self.nodes[2].generate(1) diff --git a/test/functional/wallet-dump.py b/test/functional/wallet-dump.py index fa51a2e9d7..8b81c81ba8 100755 --- a/test/functional/wallet-dump.py +++ b/test/functional/wallet-dump.py @@ -69,7 +69,7 @@ def read_dump(file_name, addrs, script_addrs, hd_master_addr_old): class WalletDumpTest(BitcoinTestFramework): def set_test_params(self): self.num_nodes = 1 - self.extra_args = [["-keypool=90"]] + self.extra_args = [["-keypool=90", "-addresstype=legacy"]] def setup_network(self, split=False): # Use 1 minute timeout because the initial getnewaddress RPC can take diff --git a/test/functional/wallet.py b/test/functional/wallet.py index 55265d03c6..a90dbc8adf 100755 --- a/test/functional/wallet.py +++ b/test/functional/wallet.py @@ -27,15 +27,15 @@ class WalletTest(BitcoinTestFramework): assert_fee_amount(fee, tx_size, fee_per_byte * 1000) return curr_balance + def get_vsize(self, txn): + return self.nodes[0].decoderawtransaction(txn)['vsize'] + def run_test(self): # Check that there's no UTXO on none of the nodes assert_equal(len(self.nodes[0].listunspent()), 0) assert_equal(len(self.nodes[1].listunspent()), 0) assert_equal(len(self.nodes[2].listunspent()), 0) - self.log.info("Check for mempoolminfee in getmempoolinfo") - assert_equal(self.nodes[0].getmempoolinfo()['mempoolminfee'], Decimal('0.00001000')) - self.log.info("Mining blocks...") self.nodes[0].generate(1) @@ -165,7 +165,7 @@ class WalletTest(BitcoinTestFramework): txid = self.nodes[2].sendtoaddress(address, 10, "", "", False) self.nodes[2].generate(1) self.sync_all([self.nodes[0:3]]) - node_2_bal = self.check_fee_amount(self.nodes[2].getbalance(), Decimal('84'), fee_per_byte, count_bytes(self.nodes[2].getrawtransaction(txid))) + node_2_bal = self.check_fee_amount(self.nodes[2].getbalance(), Decimal('84'), fee_per_byte, self.get_vsize(self.nodes[2].getrawtransaction(txid))) assert_equal(self.nodes[0].getbalance(), Decimal('10')) # Send 10 BTC with subtract fee from amount @@ -174,14 +174,14 @@ class WalletTest(BitcoinTestFramework): self.sync_all([self.nodes[0:3]]) node_2_bal -= Decimal('10') assert_equal(self.nodes[2].getbalance(), node_2_bal) - node_0_bal = self.check_fee_amount(self.nodes[0].getbalance(), Decimal('20'), fee_per_byte, count_bytes(self.nodes[2].getrawtransaction(txid))) + node_0_bal = self.check_fee_amount(self.nodes[0].getbalance(), Decimal('20'), fee_per_byte, self.get_vsize(self.nodes[2].getrawtransaction(txid))) # Sendmany 10 BTC txid = self.nodes[2].sendmany('from1', {address: 10}, 0, "", []) self.nodes[2].generate(1) self.sync_all([self.nodes[0:3]]) node_0_bal += Decimal('10') - node_2_bal = self.check_fee_amount(self.nodes[2].getbalance(), node_2_bal - Decimal('10'), fee_per_byte, count_bytes(self.nodes[2].getrawtransaction(txid))) + node_2_bal = self.check_fee_amount(self.nodes[2].getbalance(), node_2_bal - Decimal('10'), fee_per_byte, self.get_vsize(self.nodes[2].getrawtransaction(txid))) assert_equal(self.nodes[0].getbalance(), node_0_bal) # Sendmany 10 BTC with subtract fee from amount @@ -190,7 +190,7 @@ class WalletTest(BitcoinTestFramework): self.sync_all([self.nodes[0:3]]) node_2_bal -= Decimal('10') assert_equal(self.nodes[2].getbalance(), node_2_bal) - node_0_bal = self.check_fee_amount(self.nodes[0].getbalance(), node_0_bal + Decimal('10'), fee_per_byte, count_bytes(self.nodes[2].getrawtransaction(txid))) + node_0_bal = self.check_fee_amount(self.nodes[0].getbalance(), node_0_bal + Decimal('10'), fee_per_byte, self.get_vsize(self.nodes[2].getrawtransaction(txid))) # Test ResendWalletTransactions: # Create a couple of transactions, then start up a fourth |