diff options
Diffstat (limited to 'test')
-rw-r--r-- | test/README.md | 4 | ||||
-rwxr-xr-x | test/functional/feature_fee_estimation.py | 161 | ||||
-rwxr-xr-x | test/functional/feature_segwit.py | 16 | ||||
-rwxr-xr-x | test/functional/feature_uacomment.py | 2 | ||||
-rwxr-xr-x | test/functional/mempool_persist.py | 9 | ||||
-rwxr-xr-x | test/functional/rpc_blockchain.py | 15 | ||||
-rwxr-xr-x | test/functional/rpc_deprecated.py | 22 | ||||
-rwxr-xr-x | test/functional/rpc_fundrawtransaction.py | 6 | ||||
-rwxr-xr-x | test/functional/rpc_rawtransaction.py | 4 | ||||
-rwxr-xr-x | test/functional/test_framework/mininode.py | 2 | ||||
-rwxr-xr-x | test/functional/test_runner.py | 14 | ||||
-rwxr-xr-x | test/functional/wallet_dump.py | 20 | ||||
-rwxr-xr-x | test/functional/wallet_zapwallettxes.py | 1 |
13 files changed, 136 insertions, 140 deletions
diff --git a/test/README.md b/test/README.md index b59c8db4e5..b522c4469a 100644 --- a/test/README.md +++ b/test/README.md @@ -33,13 +33,13 @@ The ZMQ functional test requires a python ZMQ library. To install it: Individual tests can be run by directly calling the test script, eg: ``` -test/functional/replace-by-fee.py +test/functional/feature_rbf.py ``` or can be run through the test_runner harness, eg: ``` -test/functional/test_runner.py replace-by-fee.py +test/functional/test_runner.py feature_rbf.py ``` You can run any combination (incl. duplicates) of tests by calling: diff --git a/test/functional/feature_fee_estimation.py b/test/functional/feature_fee_estimation.py index 68453e50f4..e1263414bd 100755 --- a/test/functional/feature_fee_estimation.py +++ b/test/functional/feature_fee_estimation.py @@ -3,39 +3,47 @@ # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test fee estimation code.""" +from decimal import Decimal +import random -from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import * -from test_framework.script import CScript, OP_1, OP_DROP, OP_2, OP_HASH160, OP_EQUAL, hash160, OP_TRUE from test_framework.mininode import CTransaction, CTxIn, CTxOut, COutPoint, ToHex, COIN +from test_framework.script import CScript, OP_1, OP_DROP, OP_2, OP_HASH160, OP_EQUAL, hash160, OP_TRUE +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import ( + assert_equal, + assert_greater_than, + assert_greater_than_or_equal, + connect_nodes, + satoshi_round, + sync_blocks, + sync_mempools, +) # Construct 2 trivial P2SH's and the ScriptSigs that spend them # So we can create many transactions without needing to spend # time signing. -redeem_script_1 = CScript([OP_1, OP_DROP]) -redeem_script_2 = CScript([OP_2, OP_DROP]) -P2SH_1 = CScript([OP_HASH160, hash160(redeem_script_1), OP_EQUAL]) -P2SH_2 = CScript([OP_HASH160, hash160(redeem_script_2), OP_EQUAL]) +REDEEM_SCRIPT_1 = CScript([OP_1, OP_DROP]) +REDEEM_SCRIPT_2 = CScript([OP_2, OP_DROP]) +P2SH_1 = CScript([OP_HASH160, hash160(REDEEM_SCRIPT_1), OP_EQUAL]) +P2SH_2 = CScript([OP_HASH160, hash160(REDEEM_SCRIPT_2), OP_EQUAL]) # Associated ScriptSig's to spend satisfy P2SH_1 and P2SH_2 -SCRIPT_SIG = [CScript([OP_TRUE, redeem_script_1]), CScript([OP_TRUE, redeem_script_2])] - -global log +SCRIPT_SIG = [CScript([OP_TRUE, REDEEM_SCRIPT_1]), CScript([OP_TRUE, REDEEM_SCRIPT_2])] def small_txpuzzle_randfee(from_node, conflist, unconflist, amount, min_fee, fee_increment): - """ - Create and send a transaction with a random fee. + """Create and send a transaction with a random fee. + The transaction pays to a trivial P2SH script, and assumes that its inputs are of the same form. The function takes a list of confirmed outputs and unconfirmed outputs and attempts to use the confirmed list first for its inputs. It adds the newly created outputs to the unconfirmed list. - Returns (raw transaction, fee) - """ + Returns (raw transaction, fee).""" + # It's best to exponentially distribute our random fees # because the buckets are exponentially spaced. # Exponentially distributed from 1-128 * fee_increment - rand_fee = float(fee_increment)*(1.1892**random.randint(0,28)) + rand_fee = float(fee_increment) * (1.1892 ** random.randint(0, 28)) # Total fee ranges from min_fee to min_fee + 127*fee_increment fee = min_fee - fee_increment + satoshi_round(rand_fee) tx = CTransaction() @@ -50,95 +58,69 @@ def small_txpuzzle_randfee(from_node, conflist, unconflist, amount, min_fee, fee total_in += t["amount"] tx.vin.append(CTxIn(COutPoint(int(t["txid"], 16), t["vout"]), b"")) if total_in <= amount + fee: - raise RuntimeError("Insufficient funds: need %d, have %d"%(amount+fee, total_in)) - tx.vout.append(CTxOut(int((total_in - amount - fee)*COIN), P2SH_1)) - tx.vout.append(CTxOut(int(amount*COIN), P2SH_2)) + raise RuntimeError("Insufficient funds: need %d, have %d" % (amount + fee, total_in)) + tx.vout.append(CTxOut(int((total_in - amount - fee) * COIN), P2SH_1)) + tx.vout.append(CTxOut(int(amount * COIN), P2SH_2)) # These transactions don't need to be signed, but we still have to insert # the ScriptSig that will satisfy the ScriptPubKey. for inp in tx.vin: inp.scriptSig = SCRIPT_SIG[inp.prevout.n] txid = from_node.sendrawtransaction(ToHex(tx), True) - unconflist.append({ "txid" : txid, "vout" : 0 , "amount" : total_in - amount - fee}) - unconflist.append({ "txid" : txid, "vout" : 1 , "amount" : amount}) + unconflist.append({"txid": txid, "vout": 0, "amount": total_in - amount - fee}) + unconflist.append({"txid": txid, "vout": 1, "amount": amount}) return (ToHex(tx), fee) -def split_inputs(from_node, txins, txouts, initial_split = False): - """ - We need to generate a lot of inputs so we can generate a ton of transactions. +def split_inputs(from_node, txins, txouts, initial_split=False): + """Generate a lot of inputs so we can generate a ton of transactions. + This function takes an input from txins, and creates and sends a transaction which splits the value into 2 outputs which are appended to txouts. Previously this was designed to be small inputs so they wouldn't have - a high coin age when the notion of priority still existed. - """ + a high coin age when the notion of priority still existed.""" + prevtxout = txins.pop() tx = CTransaction() tx.vin.append(CTxIn(COutPoint(int(prevtxout["txid"], 16), prevtxout["vout"]), b"")) - half_change = satoshi_round(prevtxout["amount"]/2) - rem_change = prevtxout["amount"] - half_change - Decimal("0.00001000") - tx.vout.append(CTxOut(int(half_change*COIN), P2SH_1)) - tx.vout.append(CTxOut(int(rem_change*COIN), P2SH_2)) + half_change = satoshi_round(prevtxout["amount"] / 2) + rem_change = prevtxout["amount"] - half_change - Decimal("0.00001000") + tx.vout.append(CTxOut(int(half_change * COIN), P2SH_1)) + tx.vout.append(CTxOut(int(rem_change * COIN), P2SH_2)) # If this is the initial split we actually need to sign the transaction # Otherwise we just need to insert the proper ScriptSig - if (initial_split) : + if (initial_split): completetx = from_node.signrawtransaction(ToHex(tx))["hex"] - else : + else: tx.vin[0].scriptSig = SCRIPT_SIG[prevtxout["vout"]] completetx = ToHex(tx) txid = from_node.sendrawtransaction(completetx, True) - txouts.append({ "txid" : txid, "vout" : 0 , "amount" : half_change}) - txouts.append({ "txid" : txid, "vout" : 1 , "amount" : rem_change}) + txouts.append({"txid": txid, "vout": 0, "amount": half_change}) + txouts.append({"txid": txid, "vout": 1, "amount": rem_change}) -def check_estimates(node, fees_seen, max_invalid, print_estimates = True): - """ - This function calls estimatefee and verifies that the estimates - meet certain invariants. - """ - all_estimates = [ node.estimatefee(i) for i in range(1,26) ] - if print_estimates: - log.info([str(all_estimates[e-1]) for e in [1,2,3,6,15,25]]) - delta = 1.0e-6 # account for rounding error - last_e = max(fees_seen) - for e in [x for x in all_estimates if x >= 0]: - # Estimates should be within the bounds of what transactions fees actually were: - if float(e)+delta < min(fees_seen) or float(e)-delta > max(fees_seen): +def check_estimates(node, fees_seen, max_invalid): + """Call estimatesmartfee and verify that the estimates meet certain invariants.""" + + delta = 1.0e-6 # account for rounding error + last_feerate = float(max(fees_seen)) + all_smart_estimates = [node.estimatesmartfee(i) for i in range(1, 26)] + for i, e in enumerate(all_smart_estimates): # estimate is for i+1 + feerate = float(e["feerate"]) + assert_greater_than(feerate, 0) + + if feerate + delta < min(fees_seen) or feerate - delta > max(fees_seen): raise AssertionError("Estimated fee (%f) out of range (%f,%f)" - %(float(e), min(fees_seen), max(fees_seen))) - # Estimates should be monotonically decreasing - if float(e)-delta > last_e: + % (feerate, min(fees_seen), max(fees_seen))) + if feerate - delta > last_feerate: raise AssertionError("Estimated fee (%f) larger than last fee (%f) for lower number of confirms" - %(float(e),float(last_e))) - last_e = e - valid_estimate = False - invalid_estimates = 0 - for i,e in enumerate(all_estimates): # estimate is for i+1 - if e >= 0: - valid_estimate = True - if i >= 13: # for n>=14 estimatesmartfee(n/2) should be at least as high as estimatefee(n) - assert(node.estimatesmartfee((i+1)//2)["feerate"] > float(e) - delta) + % (feerate, last_feerate)) + last_feerate = feerate + if i == 0: + assert_equal(e["blocks"], 2) else: - invalid_estimates += 1 - - # estimatesmartfee should still be valid - approx_estimate = node.estimatesmartfee(i+1)["feerate"] - answer_found = node.estimatesmartfee(i+1)["blocks"] - assert(approx_estimate > 0) - assert(answer_found > i+1) - - # Once we're at a high enough confirmation count that we can give an estimate - # We should have estimates for all higher confirmation counts - if valid_estimate: - raise AssertionError("Invalid estimate appears at higher confirm count than valid estimate") - - # Check on the expected number of different confirmation counts - # that we might not have valid estimates for - if invalid_estimates > max_invalid: - raise AssertionError("More than (%d) invalid estimates"%(max_invalid)) - return all_estimates - + assert_greater_than_or_equal(i + 1, e["blocks"]) class EstimateFeeTest(BitcoinTestFramework): def set_test_params(self): @@ -151,7 +133,7 @@ class EstimateFeeTest(BitcoinTestFramework): which we will use to generate our transactions. """ self.add_nodes(3, extra_args=[["-maxorphantx=1000", "-whitelist=127.0.0.1"], - ["-blockmaxsize=17000", "-maxorphantx=1000", "-deprecatedrpc=estimatefee"], + ["-blockmaxsize=17000", "-maxorphantx=1000"], ["-blockmaxsize=8000", "-maxorphantx=1000"]]) # Use node0 to mine blocks for input splitting # Node1 mines small blocks but that are bigger than the expected transaction rate. @@ -160,7 +142,6 @@ class EstimateFeeTest(BitcoinTestFramework): # Node2 is a stingy miner, that # produces too small blocks (room for only 55 or so transactions) - def transact_and_mine(self, numblocks, mining_node): min_fee = Decimal("0.00001") # We will now mine numblocks blocks generating on average 100 transactions between each block @@ -169,14 +150,14 @@ class EstimateFeeTest(BitcoinTestFramework): # resorting to tx's that depend on the mempool when those run out for i in range(numblocks): random.shuffle(self.confutxo) - for j in range(random.randrange(100-50,100+50)): - from_index = random.randint(1,2) + for j in range(random.randrange(100 - 50, 100 + 50)): + from_index = random.randint(1, 2) (txhex, fee) = small_txpuzzle_randfee(self.nodes[from_index], self.confutxo, self.memutxo, Decimal("0.005"), min_fee, min_fee) tx_kbytes = (len(txhex) // 2) / 1000.0 - self.fees_per_kb.append(float(fee)/tx_kbytes) + self.fees_per_kb.append(float(fee) / tx_kbytes) sync_mempools(self.nodes[0:3], wait=.1) - mined = mining_node.getblock(mining_node.generate(1)[0],True)["tx"] + mined = mining_node.getblock(mining_node.generate(1)[0], True)["tx"] sync_blocks(self.nodes[0:3], wait=.1) # update which txouts are confirmed newmem = [] @@ -191,10 +172,6 @@ class EstimateFeeTest(BitcoinTestFramework): self.log.info("This test is time consuming, please be patient") self.log.info("Splitting inputs so we can generate tx's") - # Make log handler available to helper functions - global log - log = self.log - # Start node0 self.start_node(0) self.txouts = [] @@ -210,13 +187,13 @@ class EstimateFeeTest(BitcoinTestFramework): # Use txouts to monitor the available utxo, since these won't be tracked in wallet reps = 0 while (reps < 5): - #Double txouts to txouts2 - while (len(self.txouts)>0): + # Double txouts to txouts2 + while (len(self.txouts) > 0): split_inputs(self.nodes[0], self.txouts, self.txouts2) while (len(self.nodes[0].getrawmempool()) > 0): self.nodes[0].generate(1) - #Double txouts2 to txouts - while (len(self.txouts2)>0): + # Double txouts2 to txouts + while (len(self.txouts2) > 0): split_inputs(self.nodes[0], self.txouts2, self.txouts) while (len(self.nodes[0].getrawmempool()) > 0): self.nodes[0].generate(1) @@ -235,7 +212,7 @@ class EstimateFeeTest(BitcoinTestFramework): self.fees_per_kb = [] self.memutxo = [] - self.confutxo = self.txouts # Start with the set of confirmed txouts after splitting + self.confutxo = self.txouts # Start with the set of confirmed txouts after splitting self.log.info("Will output estimates for 1/2/3/6/15/25 blocks") for i in range(2): diff --git a/test/functional/feature_segwit.py b/test/functional/feature_segwit.py index ba6373fa33..7db05077c9 100755 --- a/test/functional/feature_segwit.py +++ b/test/functional/feature_segwit.py @@ -30,11 +30,13 @@ def getutxo(txid): utxo["txid"] = txid return utxo -def find_unspent(node, min_value): - for utxo in node.listunspent(): - if utxo['amount'] >= min_value: +def find_spendable_utxo(node, min_value): + for utxo in node.listunspent(query_options={'minimumAmount': min_value}): + if utxo['spendable']: return utxo + raise AssertionError("Unspent output equal or higher than %s not found" % min_value) + class SegWitTest(BitcoinTestFramework): def set_test_params(self): self.setup_clean_chain = True @@ -113,8 +115,8 @@ class SegWitTest(BitcoinTestFramework): for i in range(5): for n in range(3): for v in range(2): - wit_ids[n][v].append(send_to_witness(v, self.nodes[0], find_unspent(self.nodes[0], 50), self.pubkey[n], False, Decimal("49.999"))) - p2sh_ids[n][v].append(send_to_witness(v, self.nodes[0], find_unspent(self.nodes[0], 50), self.pubkey[n], True, Decimal("49.999"))) + wit_ids[n][v].append(send_to_witness(v, self.nodes[0], find_spendable_utxo(self.nodes[0], 50), self.pubkey[n], False, Decimal("49.999"))) + p2sh_ids[n][v].append(send_to_witness(v, self.nodes[0], find_spendable_utxo(self.nodes[0], 50), self.pubkey[n], True, Decimal("49.999"))) self.nodes[0].generate(1) #block 163 sync_blocks(self.nodes) @@ -209,7 +211,7 @@ class SegWitTest(BitcoinTestFramework): # tx2 (segwit input, paying to a non-segwit output) -> # tx3 (non-segwit input, paying to a non-segwit output). # tx1 is allowed to appear in the block, but no others. - txid1 = send_to_witness(1, self.nodes[0], find_unspent(self.nodes[0], 50), self.pubkey[0], False, Decimal("49.996")) + txid1 = send_to_witness(1, self.nodes[0], find_spendable_utxo(self.nodes[0], 50), self.pubkey[0], False, Decimal("49.996")) hex_tx = self.nodes[0].gettransaction(txid)['hex'] tx = FromHex(CTransaction(), hex_tx) assert(tx.wit.is_null()) # This should not be a segwit input @@ -570,7 +572,7 @@ class SegWitTest(BitcoinTestFramework): assert_equal(self.nodes[1].listtransactions("*", 1, 0, True)[0]["txid"], txid) def mine_and_test_listunspent(self, script_list, ismine): - utxo = find_unspent(self.nodes[0], 50) + utxo = find_spendable_utxo(self.nodes[0], 50) tx = CTransaction() tx.vin.append(CTxIn(COutPoint(int('0x'+utxo['txid'],0), utxo['vout']))) for i in script_list: diff --git a/test/functional/feature_uacomment.py b/test/functional/feature_uacomment.py index 0b2c64ab69..bc3791508a 100755 --- a/test/functional/feature_uacomment.py +++ b/test/functional/feature_uacomment.py @@ -23,7 +23,7 @@ class UacommentTest(BitcoinTestFramework): self.log.info("test -uacomment max length") self.stop_node(0) - expected = "Total length of network version string (286) exceeds maximum length (256). Reduce the number or size of uacomments." + expected = "exceeds maximum length (256). Reduce the number or size of uacomments." self.assert_start_raises_init_error(0, ["-uacomment=" + 'a' * 256], expected) self.log.info("test -uacomment unsafe characters") diff --git a/test/functional/mempool_persist.py b/test/functional/mempool_persist.py index 31a96ec60e..17f0967219 100755 --- a/test/functional/mempool_persist.py +++ b/test/functional/mempool_persist.py @@ -66,16 +66,17 @@ class MempoolPersistTest(BitcoinTestFramework): self.log.debug("Stop-start the nodes. Verify that node0 has the transactions in its mempool and node1 does not. Verify that node2 calculates its balance correctly after loading wallet transactions.") self.stop_nodes() + self.start_node(1) # Give this one a head-start, so we can be "extra-sure" that it didn't load anything later self.start_node(0) - self.start_node(1) self.start_node(2) # Give bitcoind a second to reload the mempool - time.sleep(1) - wait_until(lambda: len(self.nodes[0].getrawmempool()) == 5) - wait_until(lambda: len(self.nodes[2].getrawmempool()) == 5) + wait_until(lambda: len(self.nodes[0].getrawmempool()) == 5, timeout=1) + wait_until(lambda: len(self.nodes[2].getrawmempool()) == 5, timeout=1) + # The others have loaded their mempool. If node_1 loaded anything, we'd probably notice by now: assert_equal(len(self.nodes[1].getrawmempool()), 0) # Verify accounting of mempool transactions after restart is correct + self.nodes[2].syncwithvalidationinterfacequeue() # Flush mempool to wallet assert_equal(node2_balance, self.nodes[2].getbalance()) self.log.debug("Stop-start node0 with -persistmempool=0. Verify that it doesn't load its mempool.dat file.") diff --git a/test/functional/rpc_blockchain.py b/test/functional/rpc_blockchain.py index 11acff4be1..7cf2abe6f0 100755 --- a/test/functional/rpc_blockchain.py +++ b/test/functional/rpc_blockchain.py @@ -100,6 +100,8 @@ class BlockchainTest(BitcoinTestFramework): assert_greater_than(res['size_on_disk'], 0) def _test_getchaintxstats(self): + self.log.info("Test getchaintxstats") + chaintxstats = self.nodes[0].getchaintxstats(1) # 200 txs plus genesis tx assert_equal(chaintxstats['txcount'], 201) @@ -107,21 +109,25 @@ class BlockchainTest(BitcoinTestFramework): # we have to round because of binary math assert_equal(round(chaintxstats['txrate'] * 600, 10), Decimal(1)) - b1 = self.nodes[0].getblock(self.nodes[0].getblockhash(1)) - b200 = self.nodes[0].getblock(self.nodes[0].getblockhash(200)) + b1_hash = self.nodes[0].getblockhash(1) + b1 = self.nodes[0].getblock(b1_hash) + b200_hash = self.nodes[0].getblockhash(200) + b200 = self.nodes[0].getblock(b200_hash) time_diff = b200['mediantime'] - b1['mediantime'] chaintxstats = self.nodes[0].getchaintxstats() assert_equal(chaintxstats['time'], b200['time']) assert_equal(chaintxstats['txcount'], 201) + assert_equal(chaintxstats['window_final_block_hash'], b200_hash) assert_equal(chaintxstats['window_block_count'], 199) assert_equal(chaintxstats['window_tx_count'], 199) assert_equal(chaintxstats['window_interval'], time_diff) assert_equal(round(chaintxstats['txrate'] * time_diff, 10), Decimal(199)) - chaintxstats = self.nodes[0].getchaintxstats(blockhash=b1['hash']) + chaintxstats = self.nodes[0].getchaintxstats(blockhash=b1_hash) assert_equal(chaintxstats['time'], b1['time']) assert_equal(chaintxstats['txcount'], 2) + assert_equal(chaintxstats['window_final_block_hash'], b1_hash) assert_equal(chaintxstats['window_block_count'], 0) assert('window_tx_count' not in chaintxstats) assert('window_interval' not in chaintxstats) @@ -173,8 +179,7 @@ class BlockchainTest(BitcoinTestFramework): def _test_getblockheader(self): node = self.nodes[0] - assert_raises_rpc_error(-5, "Block not found", - node.getblockheader, "nonsense") + assert_raises_rpc_error(-5, "Block not found", node.getblockheader, "nonsense") besthash = node.getbestblockhash() secondbesthash = node.getblockhash(199) diff --git a/test/functional/rpc_deprecated.py b/test/functional/rpc_deprecated.py index d6f25158ef..90183474bb 100755 --- a/test/functional/rpc_deprecated.py +++ b/test/functional/rpc_deprecated.py @@ -4,24 +4,24 @@ # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test deprecation of RPC calls.""" from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import assert_raises_rpc_error class DeprecatedRpcTest(BitcoinTestFramework): def set_test_params(self): self.num_nodes = 2 self.setup_clean_chain = True - self.extra_args = [[], ["-deprecatedrpc=estimatefee", "-deprecatedrpc=createmultisig"]] + self.extra_args = [[], []] def run_test(self): - self.log.info("estimatefee: Shows deprecated message") - assert_raises_rpc_error(-32, 'estimatefee is deprecated', self.nodes[0].estimatefee, 1) - - self.log.info("Using -deprecatedrpc=estimatefee bypasses the error") - self.nodes[1].estimatefee(1) - - self.log.info("Make sure that -deprecatedrpc=createmultisig allows it to take addresses") - assert_raises_rpc_error(-5, "Invalid public key", self.nodes[0].createmultisig, 1, [self.nodes[0].getnewaddress()]) - self.nodes[1].createmultisig(1, [self.nodes[1].getnewaddress()]) + # This test should be used to verify correct behaviour of deprecated + # RPC methods with and without the -deprecatedrpc flags. For example: + # + # self.log.info("Make sure that -deprecatedrpc=createmultisig allows it to take addresses") + # assert_raises_rpc_error(-5, "Invalid public key", self.nodes[0].createmultisig, 1, [self.nodes[0].getnewaddress()]) + # self.nodes[1].createmultisig(1, [self.nodes[1].getnewaddress()]) + # + # There are currently no deprecated RPC methods in master, so this + # test is currently empty. + pass if __name__ == '__main__': DeprecatedRpcTest().main() diff --git a/test/functional/rpc_fundrawtransaction.py b/test/functional/rpc_fundrawtransaction.py index 5f7a0586e0..6b9c9c15b7 100755 --- a/test/functional/rpc_fundrawtransaction.py +++ b/test/functional/rpc_fundrawtransaction.py @@ -223,8 +223,8 @@ class RawTransactionsTest(BitcoinTestFramework): assert_raises_rpc_error(-1, "JSON value is not a string as expected", self.nodes[2].fundrawtransaction, rawtx, {'change_type': None}) assert_raises_rpc_error(-5, "Unknown change type", self.nodes[2].fundrawtransaction, rawtx, {'change_type': ''}) rawtx = self.nodes[2].fundrawtransaction(rawtx, {'change_type': 'bech32'}) - tx = self.nodes[2].decoderawtransaction(rawtx['hex']) - assert_equal('witness_v0_keyhash', tx['vout'][rawtx['changepos']]['scriptPubKey']['type']) + dec_tx = self.nodes[2].decoderawtransaction(rawtx['hex']) + assert_equal('witness_v0_keyhash', dec_tx['vout'][rawtx['changepos']]['scriptPubKey']['type']) ######################################################################### # test a fundrawtransaction with a VIN smaller than the required amount # @@ -676,7 +676,7 @@ class RawTransactionsTest(BitcoinTestFramework): self.nodes[3].fundrawtransaction(rawtx, {"feeRate": 2*min_relay_tx_fee}), self.nodes[3].fundrawtransaction(rawtx, {"feeRate": 2*min_relay_tx_fee, "subtractFeeFromOutputs": [0]})] - dec_tx = [self.nodes[3].decoderawtransaction(tx['hex']) for tx in result] + dec_tx = [self.nodes[3].decoderawtransaction(tx_['hex']) for tx_ in result] output = [d['vout'][1 - r['changepos']]['value'] for d, r in zip(dec_tx, result)] change = [d['vout'][r['changepos']]['value'] for d, r in zip(dec_tx, result)] diff --git a/test/functional/rpc_rawtransaction.py b/test/functional/rpc_rawtransaction.py index d39d86b310..c2ca7c70b8 100755 --- a/test/functional/rpc_rawtransaction.py +++ b/test/functional/rpc_rawtransaction.py @@ -59,6 +59,10 @@ class RawTransactionsTest(BitcoinTestFramework): self.nodes[0].generate(5) self.sync_all() + # Test getrawtransaction on genesis block coinbase returns an error + block = self.nodes[0].getblock(self.nodes[0].getblockhash(0)) + assert_raises_rpc_error(-5, "The genesis block coinbase is not considered an ordinary transaction", self.nodes[0].getrawtransaction, block['merkleroot']) + # Test `createrawtransaction` required parameters assert_raises_rpc_error(-1, "createrawtransaction", self.nodes[0].createrawtransaction) assert_raises_rpc_error(-1, "createrawtransaction", self.nodes[0].createrawtransaction, []) diff --git a/test/functional/test_framework/mininode.py b/test/functional/test_framework/mininode.py index fe14591139..4d9661de37 100755 --- a/test/functional/test_framework/mininode.py +++ b/test/functional/test_framework/mininode.py @@ -6,7 +6,7 @@ # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Bitcoin P2P network half-a-node. -This python code was modified from ArtForz' public domain half-a-node, as +This python code was modified from ArtForz' public domain half-a-node, as found in the mini-node branch of http://github.com/jgarzik/pynode. P2PConnection: A low-level connection object to a node's P2P interface diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py index 98944685e1..c670878d68 100755 --- a/test/functional/test_runner.py +++ b/test/functional/test_runner.py @@ -472,21 +472,15 @@ class TestResult(): def check_script_prefixes(): - """Check that at most a handful of the - test scripts don't start with one of the allowed name prefixes.""" - - # LEEWAY is provided as a transition measure, so that pull-requests - # that introduce new tests that don't conform with the naming - # convention don't immediately cause the tests to fail. - LEEWAY = 10 + """Check that test scripts start with one of the allowed name prefixes.""" good_prefixes_re = re.compile("(example|feature|interface|mempool|mining|p2p|rpc|wallet)_") bad_script_names = [script for script in ALL_SCRIPTS if good_prefixes_re.match(script) is None] - if len(bad_script_names) > 0: - print("INFO: %d tests not meeting naming conventions:" % (len(bad_script_names))) + if bad_script_names: + print("%sERROR:%s %d tests not meeting naming conventions:" % (BOLD[1], BOLD[0], len(bad_script_names))) print(" %s" % ("\n ".join(sorted(bad_script_names)))) - assert len(bad_script_names) <= LEEWAY, "Too many tests not following naming convention! (%d found, maximum: %d)" % (len(bad_script_names), LEEWAY) + raise AssertionError("Some tests are not following naming convention!") def check_script_list(src_dir): diff --git a/test/functional/wallet_dump.py b/test/functional/wallet_dump.py index 77f90ffb81..5e943d048d 100755 --- a/test/functional/wallet_dump.py +++ b/test/functional/wallet_dump.py @@ -20,6 +20,7 @@ def read_dump(file_name, addrs, script_addrs, hd_master_addr_old): found_script_addr = 0 found_addr_chg = 0 found_addr_rsv = 0 + witness_addr_ret = None hd_master_addr_ret = None for line in inputfile: # only read non comment lines @@ -47,7 +48,14 @@ def read_dump(file_name, addrs, script_addrs, hd_master_addr_old): # count key types for addrObj in addrs: - if addrObj['address'] == addr and addrObj['hdkeypath'] == keypath and keytype == "label=": + if addrObj['address'] == addr.split(",")[0] and addrObj['hdkeypath'] == keypath and keytype == "label=": + # a labled entry in the wallet should contain both a native address + # and the p2sh-p2wpkh address that was added at wallet setup + if len(addr.split(",")) == 2: + addr_list = addr.split(",") + # the entry should be of the first key in the wallet + assert_equal(addrs[0]['address'], addr_list[0]) + witness_addr_ret = addr_list[1] found_addr += 1 break elif keytype == "change=1": @@ -63,7 +71,7 @@ def read_dump(file_name, addrs, script_addrs, hd_master_addr_old): found_script_addr += 1 break - return found_addr, found_script_addr, found_addr_chg, found_addr_rsv, hd_master_addr_ret + return found_addr, found_script_addr, found_addr_chg, found_addr_rsv, hd_master_addr_ret, witness_addr_ret class WalletDumpTest(BitcoinTestFramework): @@ -83,6 +91,8 @@ class WalletDumpTest(BitcoinTestFramework): tmpdir = self.options.tmpdir # generate 20 addresses to compare against the dump + # but since we add a p2sh-p2wpkh address for the first pubkey in the + # wallet, we will expect 21 addresses in the dump test_addr_count = 20 addrs = [] for i in range(0,test_addr_count): @@ -101,12 +111,13 @@ class WalletDumpTest(BitcoinTestFramework): result = self.nodes[0].dumpwallet(tmpdir + "/node0/wallet.unencrypted.dump") assert_equal(result['filename'], os.path.abspath(tmpdir + "/node0/wallet.unencrypted.dump")) - found_addr, found_script_addr, found_addr_chg, found_addr_rsv, hd_master_addr_unenc = \ + found_addr, found_script_addr, found_addr_chg, found_addr_rsv, hd_master_addr_unenc, witness_addr_ret = \ read_dump(tmpdir + "/node0/wallet.unencrypted.dump", addrs, script_addrs, None) assert_equal(found_addr, test_addr_count) # all keys must be in the dump assert_equal(found_script_addr, 2) # all scripts must be in the dump assert_equal(found_addr_chg, 50) # 50 blocks where mined assert_equal(found_addr_rsv, 90*2) # 90 keys plus 100% internal keys + assert_equal(witness_addr_ret, witness_addr) # p2sh-p2wsh address added to the first key #encrypt wallet, restart, unlock and dump self.nodes[0].node_encrypt_wallet('test') @@ -116,12 +127,13 @@ class WalletDumpTest(BitcoinTestFramework): self.nodes[0].keypoolrefill() self.nodes[0].dumpwallet(tmpdir + "/node0/wallet.encrypted.dump") - found_addr, found_script_addr, found_addr_chg, found_addr_rsv, _ = \ + found_addr, found_script_addr, found_addr_chg, found_addr_rsv, _, witness_addr_ret = \ read_dump(tmpdir + "/node0/wallet.encrypted.dump", addrs, script_addrs, hd_master_addr_unenc) assert_equal(found_addr, test_addr_count) assert_equal(found_script_addr, 2) assert_equal(found_addr_chg, 90*2 + 50) # old reserve keys are marked as change now assert_equal(found_addr_rsv, 90*2) + assert_equal(witness_addr_ret, witness_addr) # Overwriting should fail assert_raises_rpc_error(-8, "already exists", self.nodes[0].dumpwallet, tmpdir + "/node0/wallet.unencrypted.dump") diff --git a/test/functional/wallet_zapwallettxes.py b/test/functional/wallet_zapwallettxes.py index 08afb87894..87f44b2737 100755 --- a/test/functional/wallet_zapwallettxes.py +++ b/test/functional/wallet_zapwallettxes.py @@ -59,6 +59,7 @@ class ZapWalletTXesTest (BitcoinTestFramework): self.start_node(0, ["-persistmempool=1", "-zapwallettxes=2"]) wait_until(lambda: self.nodes[0].getmempoolinfo()['size'] == 1, timeout=3) + self.nodes[0].syncwithvalidationinterfacequeue() # Flush mempool to wallet assert_equal(self.nodes[0].gettransaction(txid1)['txid'], txid1) assert_equal(self.nodes[0].gettransaction(txid2)['txid'], txid2) |