diff options
Diffstat (limited to 'test')
26 files changed, 184 insertions, 133 deletions
diff --git a/test/functional/feature_cltv.py b/test/functional/feature_cltv.py index dc5bffe33e..3438027db6 100755 --- a/test/functional/feature_cltv.py +++ b/test/functional/feature_cltv.py @@ -4,8 +4,7 @@ # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test BIP65 (CHECKLOCKTIMEVERIFY). -Test that the CHECKLOCKTIMEVERIFY soft-fork activates at (regtest) block height -1351. +Test that the CHECKLOCKTIMEVERIFY soft-fork activates. """ from test_framework.blocktools import ( @@ -62,9 +61,9 @@ def cltv_invalidate(tx, failure_reason): # +-------------------------------------------------+------------+--------------+ [[OP_CHECKLOCKTIMEVERIFY], None, None], [[OP_1NEGATE, OP_CHECKLOCKTIMEVERIFY, OP_DROP], None, None], - [[CScriptNum(1000), OP_CHECKLOCKTIMEVERIFY, OP_DROP], 0, 1296688602], # timestamp of genesis block - [[CScriptNum(1000), OP_CHECKLOCKTIMEVERIFY, OP_DROP], 0, 500], - [[CScriptNum(500), OP_CHECKLOCKTIMEVERIFY, OP_DROP], 0xffffffff, 500], + [[CScriptNum(100), OP_CHECKLOCKTIMEVERIFY, OP_DROP], 0, 1296688602], # timestamp of genesis block + [[CScriptNum(100), OP_CHECKLOCKTIMEVERIFY, OP_DROP], 0, 50], + [[CScriptNum(50), OP_CHECKLOCKTIMEVERIFY, OP_DROP], 0xffffffff, 50], ][failure_reason] cltv_modify_tx(tx, prepend_scriptsig=scheme[0], nsequence=scheme[1], nlocktime=scheme[2]) @@ -105,6 +104,7 @@ class BIP65Test(BitcoinTestFramework): self.log.info("Mining %d blocks", CLTV_HEIGHT - 2) wallet.generate(10) self.nodes[0].generate(CLTV_HEIGHT - 2 - 10) + assert_equal(self.nodes[0].getblockcount(), CLTV_HEIGHT - 2) self.log.info("Test that invalid-according-to-CLTV transactions can still appear in a block") diff --git a/test/functional/feature_config_args.py b/test/functional/feature_config_args.py index d5f0ae480b..0daa0ba3d8 100755 --- a/test/functional/feature_config_args.py +++ b/test/functional/feature_config_args.py @@ -248,6 +248,10 @@ class ConfArgsTest(BitcoinTestFramework): self.nodes[0].assert_start_raises_init_error([f'-conf={conf_file}'], f'Error: Error reading configuration file: specified data directory "{new_data_dir}" does not exist.') + # Check that an explicitly specified config file that cannot be opened fails + none_existent_conf_file = os.path.join(default_data_dir, "none_existent_bitcoin.conf") + self.nodes[0].assert_start_raises_init_error(['-conf=' + none_existent_conf_file], 'Error: Error reading configuration file: specified config file "' + none_existent_conf_file + '" could not be opened.') + # Create the directory and ensure the config file now works os.mkdir(new_data_dir) self.start_node(0, [f'-conf={conf_file}']) diff --git a/test/functional/feature_dbcrash.py b/test/functional/feature_dbcrash.py index 5bbcd20016..f0766ca7c2 100755 --- a/test/functional/feature_dbcrash.py +++ b/test/functional/feature_dbcrash.py @@ -217,7 +217,7 @@ class ChainstateWriteCrashTest(BitcoinTestFramework): # Start by creating a lot of utxos on node3 initial_height = self.nodes[3].getblockcount() - utxo_list = create_confirmed_utxos(self.nodes[3].getnetworkinfo()['relayfee'], self.nodes[3], 5000) + utxo_list = create_confirmed_utxos(self, self.nodes[3].getnetworkinfo()['relayfee'], self.nodes[3], 5000) self.log.info(f"Prepped {len(utxo_list)} utxo entries") # Sync these blocks with the other nodes @@ -253,7 +253,8 @@ class ChainstateWriteCrashTest(BitcoinTestFramework): self.log.debug("Mining longer tip") block_hashes = [] while current_height + 1 > self.nodes[3].getblockcount(): - block_hashes.extend(self.nodes[3].generatetoaddress( + block_hashes.extend(self.generatetoaddress( + self.nodes[3], nblocks=min(10, current_height + 1 - self.nodes[3].getblockcount()), # new address to avoid mining a block that has just been invalidated address=self.nodes[3].getnewaddress(), diff --git a/test/functional/feature_maxuploadtarget.py b/test/functional/feature_maxuploadtarget.py index d0a94658ff..bd615997cb 100755 --- a/test/functional/feature_maxuploadtarget.py +++ b/test/functional/feature_maxuploadtarget.py @@ -67,7 +67,7 @@ class MaxUploadTest(BitcoinTestFramework): p2p_conns.append(self.nodes[0].add_p2p_connection(TestP2PConn())) # Now mine a big block - mine_large_block(self.nodes[0], self.utxo_cache) + mine_large_block(self, self.nodes[0], self.utxo_cache) # Store the hash; we'll request this later big_old_block = self.nodes[0].getbestblockhash() @@ -78,7 +78,7 @@ class MaxUploadTest(BitcoinTestFramework): self.nodes[0].setmocktime(int(time.time()) - 2*60*60*24) # Mine one more block, so that the prior block looks old - mine_large_block(self.nodes[0], self.utxo_cache) + mine_large_block(self, self.nodes[0], self.utxo_cache) # We'll be requesting this new block too big_new_block = self.nodes[0].getbestblockhash() diff --git a/test/functional/feature_nulldummy.py b/test/functional/feature_nulldummy.py index f467626801..678e103e5f 100755 --- a/test/functional/feature_nulldummy.py +++ b/test/functional/feature_nulldummy.py @@ -24,7 +24,10 @@ from test_framework.blocktools import ( from test_framework.messages import CTransaction from test_framework.script import CScript from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import assert_equal, assert_raises_rpc_error +from test_framework.util import ( + assert_equal, + assert_raises_rpc_error, +) NULLDUMMY_ERROR = "non-mandatory-script-verify-flag (Dummy CHECKMULTISIG argument must be zero)" @@ -51,6 +54,7 @@ class NULLDUMMYTest(BitcoinTestFramework): self.extra_args = [[ f'-segwitheight={COINBASE_MATURITY + 5}', '-addresstype=legacy', + '-par=1', # Use only one script thread to get the exact reject reason for testing ]] def skip_test_if_missing_module(self): @@ -86,7 +90,7 @@ class NULLDUMMYTest(BitcoinTestFramework): txid2 = self.nodes[0].sendrawtransaction(test1txs[1].serialize_with_witness().hex(), 0) test1txs.append(create_transaction(self.nodes[0], coinbase_txid[1], self.wit_ms_address, amount=49)) txid3 = self.nodes[0].sendrawtransaction(test1txs[2].serialize_with_witness().hex(), 0) - self.block_submit(self.nodes[0], test1txs, False, True) + self.block_submit(self.nodes[0], test1txs, accept=True) self.log.info("Test 2: Non-NULLDUMMY base multisig transaction should not be accepted to mempool before activation") test2tx = create_transaction(self.nodes[0], txid2, self.ms_address, amount=47) @@ -94,28 +98,28 @@ class NULLDUMMYTest(BitcoinTestFramework): assert_raises_rpc_error(-26, NULLDUMMY_ERROR, self.nodes[0].sendrawtransaction, test2tx.serialize_with_witness().hex(), 0) self.log.info(f"Test 3: Non-NULLDUMMY base transactions should be accepted in a block before activation [{COINBASE_MATURITY + 4}]") - self.block_submit(self.nodes[0], [test2tx], False, True) + self.block_submit(self.nodes[0], [test2tx], accept=True) self.log.info("Test 4: Non-NULLDUMMY base multisig transaction is invalid after activation") test4tx = create_transaction(self.nodes[0], test2tx.hash, self.address, amount=46) test6txs = [CTransaction(test4tx)] trueDummy(test4tx) assert_raises_rpc_error(-26, NULLDUMMY_ERROR, self.nodes[0].sendrawtransaction, test4tx.serialize_with_witness().hex(), 0) - self.block_submit(self.nodes[0], [test4tx]) + self.block_submit(self.nodes[0], [test4tx], accept=False) self.log.info("Test 5: Non-NULLDUMMY P2WSH multisig transaction invalid after activation") test5tx = create_transaction(self.nodes[0], txid3, self.wit_address, amount=48) test6txs.append(CTransaction(test5tx)) test5tx.wit.vtxinwit[0].scriptWitness.stack[0] = b'\x01' assert_raises_rpc_error(-26, NULLDUMMY_ERROR, self.nodes[0].sendrawtransaction, test5tx.serialize_with_witness().hex(), 0) - self.block_submit(self.nodes[0], [test5tx], True) + self.block_submit(self.nodes[0], [test5tx], with_witness=True, accept=False) self.log.info(f"Test 6: NULLDUMMY compliant base/witness transactions should be accepted to mempool and in block after activation [{COINBASE_MATURITY + 5}]") for i in test6txs: self.nodes[0].sendrawtransaction(i.serialize_with_witness().hex(), 0) - self.block_submit(self.nodes[0], test6txs, True, True) + self.block_submit(self.nodes[0], test6txs, with_witness=True, accept=True) - def block_submit(self, node, txs, witness=False, accept=False): + def block_submit(self, node, txs, *, with_witness=False, accept): tmpl = node.getblocktemplate(NORMAL_GBT_REQUEST_PARAMS) assert_equal(tmpl['previousblockhash'], self.lastblockhash) assert_equal(tmpl['height'], self.lastblockheight + 1) @@ -124,11 +128,12 @@ class NULLDUMMYTest(BitcoinTestFramework): tx.rehash() block.vtx.append(tx) block.hashMerkleRoot = block.calc_merkle_root() - witness and add_witness_commitment(block) + if with_witness: + add_witness_commitment(block) block.rehash() block.solve() - assert_equal(None if accept else 'block-validation-failed', node.submitblock(block.serialize().hex())) - if (accept): + assert_equal(None if accept else NULLDUMMY_ERROR, node.submitblock(block.serialize().hex())) + if accept: assert_equal(node.getbestblockhash(), block.hash) self.lastblockhash = block.hash self.lastblocktime += 1 diff --git a/test/functional/feature_rbf.py b/test/functional/feature_rbf.py index 65929704eb..694cca15fd 100755 --- a/test/functional/feature_rbf.py +++ b/test/functional/feature_rbf.py @@ -23,49 +23,6 @@ from test_framework.script_util import DUMMY_P2WPKH_SCRIPT, DUMMY_2_P2WPKH_SCRIP from test_framework.wallet import MiniWallet MAX_REPLACEMENT_LIMIT = 100 - - -def make_utxo(node, amount, confirmed=True, scriptPubKey=DUMMY_P2WPKH_SCRIPT): - """Create a txout with a given amount and scriptPubKey - - Mines coins as needed. - - confirmed - txouts created will be confirmed in the blockchain; - unconfirmed otherwise. - """ - fee = 1 * COIN - while node.getbalance() < satoshi_round((amount + fee) / COIN): - node.generate(COINBASE_MATURITY) - - new_addr = node.getnewaddress() - txid = node.sendtoaddress(new_addr, satoshi_round((amount + fee) / COIN)) - tx1 = node.getrawtransaction(txid, 1) - txid = int(txid, 16) - i, _ = next(filter(lambda vout: new_addr == vout[1]['scriptPubKey']['address'], enumerate(tx1['vout']))) - - tx2 = CTransaction() - tx2.vin = [CTxIn(COutPoint(txid, i))] - tx2.vout = [CTxOut(amount, scriptPubKey)] - tx2.rehash() - - signed_tx = node.signrawtransactionwithwallet(tx2.serialize().hex()) - - txid = node.sendrawtransaction(signed_tx['hex'], 0) - - # If requested, ensure txouts are confirmed. - if confirmed: - mempool_size = len(node.getrawmempool()) - while mempool_size > 0: - node.generate(1) - new_size = len(node.getrawmempool()) - # Error out if we have something stuck in the mempool, as this - # would likely be a bug. - assert new_size < mempool_size - mempool_size = new_size - - return COutPoint(int(txid, 16), 0) - - class ReplaceByFeeTest(BitcoinTestFramework): def set_test_params(self): self.num_nodes = 1 @@ -129,6 +86,46 @@ class ReplaceByFeeTest(BitcoinTestFramework): self.log.info("Passed") + def make_utxo(self, node, amount, confirmed=True, scriptPubKey=DUMMY_P2WPKH_SCRIPT): + """Create a txout with a given amount and scriptPubKey + + Mines coins as needed. + + confirmed - txouts created will be confirmed in the blockchain; + unconfirmed otherwise. + """ + fee = 1 * COIN + while node.getbalance() < satoshi_round((amount + fee) / COIN): + self.generate(node, COINBASE_MATURITY) + + new_addr = node.getnewaddress() + txid = node.sendtoaddress(new_addr, satoshi_round((amount + fee) / COIN)) + tx1 = node.getrawtransaction(txid, 1) + txid = int(txid, 16) + i, _ = next(filter(lambda vout: new_addr == vout[1]['scriptPubKey']['address'], enumerate(tx1['vout']))) + + tx2 = CTransaction() + tx2.vin = [CTxIn(COutPoint(txid, i))] + tx2.vout = [CTxOut(amount, scriptPubKey)] + tx2.rehash() + + signed_tx = node.signrawtransactionwithwallet(tx2.serialize().hex()) + + txid = node.sendrawtransaction(signed_tx['hex'], 0) + + # If requested, ensure txouts are confirmed. + if confirmed: + mempool_size = len(node.getrawmempool()) + while mempool_size > 0: + self.generate(node, 1) + new_size = len(node.getrawmempool()) + # Error out if we have something stuck in the mempool, as this + # would likely be a bug. + assert new_size < mempool_size + mempool_size = new_size + + return COutPoint(int(txid, 16), 0) + def test_simple_doublespend(self): """Simple doublespend""" # we use MiniWallet to create a transaction template with inputs correctly set, @@ -165,7 +162,7 @@ class ReplaceByFeeTest(BitcoinTestFramework): """Doublespend of a long chain""" initial_nValue = 50 * COIN - tx0_outpoint = make_utxo(self.nodes[0], initial_nValue) + tx0_outpoint = self.make_utxo(self.nodes[0], initial_nValue) prevout = tx0_outpoint remaining_value = initial_nValue @@ -205,7 +202,7 @@ class ReplaceByFeeTest(BitcoinTestFramework): """Doublespend of a big tree of transactions""" initial_nValue = 50 * COIN - tx0_outpoint = make_utxo(self.nodes[0], initial_nValue) + tx0_outpoint = self.make_utxo(self.nodes[0], initial_nValue) def branch(prevout, initial_value, max_txs, tree_width=5, fee=0.0001 * COIN, _total_txs=None): if _total_txs is None: @@ -268,7 +265,7 @@ class ReplaceByFeeTest(BitcoinTestFramework): # double-spent at once" anti-DoS limit. for n in (MAX_REPLACEMENT_LIMIT + 1, MAX_REPLACEMENT_LIMIT * 2): fee = int(0.0001 * COIN) - tx0_outpoint = make_utxo(self.nodes[0], initial_nValue) + tx0_outpoint = self.make_utxo(self.nodes[0], initial_nValue) tree_txs = list(branch(tx0_outpoint, initial_nValue, n, fee=fee)) assert_equal(len(tree_txs), n) @@ -285,7 +282,7 @@ class ReplaceByFeeTest(BitcoinTestFramework): def test_replacement_feeperkb(self): """Replacement requires fee-per-KB to be higher""" - tx0_outpoint = make_utxo(self.nodes[0], int(1.1 * COIN)) + tx0_outpoint = self.make_utxo(self.nodes[0], int(1.1 * COIN)) tx1a = CTransaction() tx1a.vin = [CTxIn(tx0_outpoint, nSequence=0)] @@ -305,8 +302,8 @@ class ReplaceByFeeTest(BitcoinTestFramework): def test_spends_of_conflicting_outputs(self): """Replacements that spend conflicting tx outputs are rejected""" - utxo1 = make_utxo(self.nodes[0], int(1.2 * COIN)) - utxo2 = make_utxo(self.nodes[0], 3 * COIN) + utxo1 = self.make_utxo(self.nodes[0], int(1.2 * COIN)) + utxo2 = self.make_utxo(self.nodes[0], 3 * COIN) tx1a = CTransaction() tx1a.vin = [CTxIn(utxo1, nSequence=0)] @@ -345,8 +342,8 @@ class ReplaceByFeeTest(BitcoinTestFramework): def test_new_unconfirmed_inputs(self): """Replacements that add new unconfirmed inputs are rejected""" - confirmed_utxo = make_utxo(self.nodes[0], int(1.1 * COIN)) - unconfirmed_utxo = make_utxo(self.nodes[0], int(0.1 * COIN), False) + confirmed_utxo = self.make_utxo(self.nodes[0], int(1.1 * COIN)) + unconfirmed_utxo = self.make_utxo(self.nodes[0], int(0.1 * COIN), False) tx1 = CTransaction() tx1.vin = [CTxIn(confirmed_utxo)] @@ -369,7 +366,7 @@ class ReplaceByFeeTest(BitcoinTestFramework): # Start by creating a single transaction with many outputs initial_nValue = 10 * COIN - utxo = make_utxo(self.nodes[0], initial_nValue) + utxo = self.make_utxo(self.nodes[0], initial_nValue) fee = int(0.0001 * COIN) split_value = int((initial_nValue - fee) / (MAX_REPLACEMENT_LIMIT + 1)) @@ -417,7 +414,7 @@ class ReplaceByFeeTest(BitcoinTestFramework): def test_opt_in(self): """Replacing should only work if orig tx opted in""" - tx0_outpoint = make_utxo(self.nodes[0], int(1.1 * COIN)) + tx0_outpoint = self.make_utxo(self.nodes[0], int(1.1 * COIN)) # Create a non-opting in transaction tx1a = CTransaction() @@ -438,7 +435,7 @@ class ReplaceByFeeTest(BitcoinTestFramework): # This will raise an exception assert_raises_rpc_error(-26, "txn-mempool-conflict", self.nodes[0].sendrawtransaction, tx1b_hex, 0) - tx1_outpoint = make_utxo(self.nodes[0], int(1.1 * COIN)) + tx1_outpoint = self.make_utxo(self.nodes[0], int(1.1 * COIN)) # Create a different non-opting in transaction tx2a = CTransaction() @@ -494,7 +491,7 @@ class ReplaceByFeeTest(BitcoinTestFramework): # correctly used by replacement logic # 1. Check that feeperkb uses modified fees - tx0_outpoint = make_utxo(self.nodes[0], int(1.1 * COIN)) + tx0_outpoint = self.make_utxo(self.nodes[0], int(1.1 * COIN)) tx1a = CTransaction() tx1a.vin = [CTxIn(tx0_outpoint, nSequence=0)] @@ -520,7 +517,7 @@ class ReplaceByFeeTest(BitcoinTestFramework): assert tx1b_txid in self.nodes[0].getrawmempool() # 2. Check that absolute fee checks use modified fee. - tx1_outpoint = make_utxo(self.nodes[0], int(1.1 * COIN)) + tx1_outpoint = self.make_utxo(self.nodes[0], int(1.1 * COIN)) tx2a = CTransaction() tx2a.vin = [CTxIn(tx1_outpoint, nSequence=0)] diff --git a/test/functional/interface_zmq.py b/test/functional/interface_zmq.py index 61b96a8250..6686f77a44 100755 --- a/test/functional/interface_zmq.py +++ b/test/functional/interface_zmq.py @@ -82,8 +82,8 @@ class ZMQTestSetupBlock: raw transaction data. """ - def __init__(self, node): - self.block_hash = node.generate(1)[0] + def __init__(self, test_framework, node): + self.block_hash = test_framework.generate(node, 1)[0] coinbase = node.getblock(self.block_hash, 2)['tx'][0] self.tx_hash = coinbase['txid'] self.raw_tx = coinbase['hex'] @@ -147,7 +147,7 @@ class ZMQTest (BitcoinTestFramework): for sub in subscribers: sub.socket.set(zmq.RCVTIMEO, 1000) while True: - test_block = ZMQTestSetupBlock(self.nodes[0]) + test_block = ZMQTestSetupBlock(self, self.nodes[0]) recv_failed = False for sub in subscribers: try: diff --git a/test/functional/mempool_limit.py b/test/functional/mempool_limit.py index 39035f7cb1..1b1ac23024 100755 --- a/test/functional/mempool_limit.py +++ b/test/functional/mempool_limit.py @@ -32,7 +32,7 @@ class MempoolLimitTest(BitcoinTestFramework): assert_equal(self.nodes[0].getmempoolinfo()['mempoolminfee'], Decimal('0.00001000')) txids = [] - utxos = create_confirmed_utxos(relayfee, self.nodes[0], 91) + utxos = create_confirmed_utxos(self, relayfee, self.nodes[0], 91) self.log.info('Create a mempool tx that will be evicted') us0 = utxos.pop() diff --git a/test/functional/mempool_unbroadcast.py b/test/functional/mempool_unbroadcast.py index 5fe20ea9e1..d10b510c6a 100755 --- a/test/functional/mempool_unbroadcast.py +++ b/test/functional/mempool_unbroadcast.py @@ -32,7 +32,7 @@ class MempoolUnbroadcastTest(BitcoinTestFramework): node = self.nodes[0] min_relay_fee = node.getnetworkinfo()["relayfee"] - utxos = create_confirmed_utxos(min_relay_fee, node, 10) + utxos = create_confirmed_utxos(self, min_relay_fee, node, 10) self.disconnect_nodes(0, 1) diff --git a/test/functional/mining_getblocktemplate_longpoll.py b/test/functional/mining_getblocktemplate_longpoll.py index 715b68e04c..3003627778 100755 --- a/test/functional/mining_getblocktemplate_longpoll.py +++ b/test/functional/mining_getblocktemplate_longpoll.py @@ -48,9 +48,9 @@ class GetBlockTemplateLPTest(BitcoinTestFramework): thr.join(5) # wait 5 seconds or until thread exits assert thr.is_alive() - miniwallets = [ MiniWallet(node) for node in self.nodes ] + miniwallets = [MiniWallet(node) for node in self.nodes] self.log.info("Test that longpoll will terminate if another node generates a block") - miniwallets[1].generate(1) # generate a block on another node + self.generate(miniwallets[1], 1) # generate a block on another node # check that thread will exit now that new transaction entered mempool thr.join(5) # wait 5 seconds or until thread exits assert not thr.is_alive() @@ -58,7 +58,7 @@ class GetBlockTemplateLPTest(BitcoinTestFramework): self.log.info("Test that longpoll will terminate if we generate a block ourselves") thr = LongpollThread(self.nodes[0]) thr.start() - miniwallets[0].generate(1) # generate a block on own node + self.generate(miniwallets[0], 1) # generate a block on own node thr.join(5) # wait 5 seconds or until thread exits assert not thr.is_alive() diff --git a/test/functional/mining_prioritisetransaction.py b/test/functional/mining_prioritisetransaction.py index 9fc38ebf53..d357e2ed47 100755 --- a/test/functional/mining_prioritisetransaction.py +++ b/test/functional/mining_prioritisetransaction.py @@ -48,7 +48,7 @@ class PrioritiseTransactionTest(BitcoinTestFramework): self.relayfee = self.nodes[0].getnetworkinfo()['relayfee'] utxo_count = 90 - utxos = create_confirmed_utxos(self.relayfee, self.nodes[0], utxo_count) + utxos = create_confirmed_utxos(self, self.relayfee, self.nodes[0], utxo_count) base_fee = self.relayfee*100 # our transactions are smaller than 100kb txids = [] diff --git a/test/functional/p2p_invalid_tx.py b/test/functional/p2p_invalid_tx.py index 8783c244c3..8fef2d173f 100755 --- a/test/functional/p2p_invalid_tx.py +++ b/test/functional/p2p_invalid_tx.py @@ -141,9 +141,9 @@ class InvalidTxRequestTest(BitcoinTestFramework): tx_orphan_2_valid, # The valid transaction (with sufficient fee) ] } - # Transactions that do not end up in the mempool - # tx_orphan_no_fee, because it has too low fee (p2ps[0] is not disconnected for relaying that tx) - # tx_orphan_invalid, because it has negative fee (p2ps[1] is disconnected for relaying that tx) + # Transactions that do not end up in the mempool: + # tx_orphan_2_no_fee, because it has too low fee (p2ps[0] is not disconnected for relaying that tx) + # tx_orphan_2_invalid, because it has negative fee (p2ps[1] is disconnected for relaying that tx) self.wait_until(lambda: 1 == len(node.getpeerinfo()), timeout=12) # p2ps[1] is no longer connected assert_equal(expected_mempool, set(node.getrawmempool())) diff --git a/test/functional/p2p_unrequested_blocks.py b/test/functional/p2p_unrequested_blocks.py index e7a05d8547..a9d5ed970a 100755 --- a/test/functional/p2p_unrequested_blocks.py +++ b/test/functional/p2p_unrequested_blocks.py @@ -77,7 +77,7 @@ class AcceptBlockTest(BitcoinTestFramework): min_work_node = self.nodes[1].add_p2p_connection(P2PInterface()) # 1. Have nodes mine a block (leave IBD) - [n.generatetoaddress(1, n.get_deterministic_priv_key().address) for n in self.nodes] + [self.generatetoaddress(n, 1, n.get_deterministic_priv_key().address) for n in self.nodes] tips = [int("0x" + n.getbestblockhash(), 0) for n in self.nodes] # 2. Send one block that builds on each tip. diff --git a/test/functional/rpc_blockchain.py b/test/functional/rpc_blockchain.py index 1e73dcf5cd..2ee5c7ee0a 100755 --- a/test/functional/rpc_blockchain.py +++ b/test/functional/rpc_blockchain.py @@ -27,6 +27,7 @@ import subprocess from test_framework.address import ADDRESS_BCRT1_P2WSH_OP_TRUE from test_framework.blocktools import ( + CLTV_HEIGHT, DERSIG_HEIGHT, create_block, create_coinbase, @@ -143,7 +144,7 @@ class BlockchainTest(BitcoinTestFramework): assert_equal(res['softforks'], { 'bip34': {'type': 'buried', 'active': True, 'height': 2}, 'bip66': {'type': 'buried', 'active': True, 'height': DERSIG_HEIGHT}, - 'bip65': {'type': 'buried', 'active': False, 'height': 1351}, + 'bip65': {'type': 'buried', 'active': True, 'height': CLTV_HEIGHT}, 'csv': {'type': 'buried', 'active': False, 'height': 432}, 'segwit': {'type': 'buried', 'active': True, 'height': 0}, 'testdummy': { diff --git a/test/functional/rpc_signmessage.py b/test/functional/rpc_signmessagewithprivkey.py index 1c71732a61..95beba8730 100755 --- a/test/functional/rpc_signmessage.py +++ b/test/functional/rpc_signmessagewithprivkey.py @@ -2,7 +2,7 @@ # Copyright (c) 2016-2019 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 RPC commands for signing and verifying messages.""" +"""Test RPC commands for signing messages with private key.""" from test_framework.test_framework import BitcoinTestFramework from test_framework.util import ( @@ -10,14 +10,10 @@ from test_framework.util import ( assert_raises_rpc_error, ) -class SignMessagesTest(BitcoinTestFramework): +class SignMessagesWithPrivTest(BitcoinTestFramework): def set_test_params(self): self.setup_clean_chain = True self.num_nodes = 1 - self.extra_args = [["-addresstype=legacy"]] - - def skip_test_if_missing_module(self): - self.skip_if_no_wallet() def run_test(self): message = 'This is just a test message' @@ -30,33 +26,20 @@ class SignMessagesTest(BitcoinTestFramework): assert_equal(expected_signature, signature) assert self.nodes[0].verifymessage(address, signature, message) - self.log.info('test signing with an address with wallet') - address = self.nodes[0].getnewaddress() - signature = self.nodes[0].signmessage(address, message) - assert self.nodes[0].verifymessage(address, signature, message) - - self.log.info('test verifying with another address should not work') - other_address = self.nodes[0].getnewaddress() - other_signature = self.nodes[0].signmessage(other_address, message) - assert not self.nodes[0].verifymessage(other_address, signature, message) - assert not self.nodes[0].verifymessage(address, other_signature, message) - self.log.info('test parameter validity and error codes') - # signmessage(withprivkey) have two required parameters + # signmessagewithprivkey has two required parameters for num_params in [0, 1, 3, 4, 5]: param_list = ["dummy"]*num_params assert_raises_rpc_error(-1, "signmessagewithprivkey", self.nodes[0].signmessagewithprivkey, *param_list) - assert_raises_rpc_error(-1, "signmessage", self.nodes[0].signmessage, *param_list) # verifymessage has three required parameters for num_params in [0, 1, 2, 4, 5]: param_list = ["dummy"]*num_params assert_raises_rpc_error(-1, "verifymessage", self.nodes[0].verifymessage, *param_list) # invalid key or address provided assert_raises_rpc_error(-5, "Invalid private key", self.nodes[0].signmessagewithprivkey, "invalid_key", message) - assert_raises_rpc_error(-5, "Invalid address", self.nodes[0].signmessage, "invalid_addr", message) assert_raises_rpc_error(-5, "Invalid address", self.nodes[0].verifymessage, "invalid_addr", signature, message) # malformed signature provided - assert_raises_rpc_error(-3, "Malformed base64 encoding", self.nodes[0].verifymessage, self.nodes[0].getnewaddress(), "invalid_sig", message) + assert_raises_rpc_error(-3, "Malformed base64 encoding", self.nodes[0].verifymessage, 'mpLQjfK79b7CCV4VMJWEWAj5Mpx8Up5zxB', "invalid_sig", message) if __name__ == '__main__': - SignMessagesTest().main() + SignMessagesWithPrivTest().main() diff --git a/test/functional/rpc_signrawtransaction.py b/test/functional/rpc_signrawtransaction.py index 312a4abbc3..e6fef7e838 100755 --- a/test/functional/rpc_signrawtransaction.py +++ b/test/functional/rpc_signrawtransaction.py @@ -5,7 +5,6 @@ """Test transaction signing using the signrawtransaction* RPCs.""" from test_framework.blocktools import ( - CLTV_HEIGHT, COINBASE_MATURITY, CSV_ACTIVATION_HEIGHT, ) @@ -274,7 +273,7 @@ class SignRawTransactionsTest(BitcoinTestFramework): getcontext().prec = 8 # Make sure CSV is active - generate_to_height(self.nodes[0], CSV_ACTIVATION_HEIGHT) + generate_to_height(self, self.nodes[0], CSV_ACTIVATION_HEIGHT) assert self.nodes[0].getblockchaininfo()['softforks']['csv']['active'] # Create a P2WSH script with CSV @@ -310,11 +309,10 @@ class SignRawTransactionsTest(BitcoinTestFramework): getcontext().prec = 8 # Make sure CLTV is active - generate_to_height(self.nodes[0], CLTV_HEIGHT) assert self.nodes[0].getblockchaininfo()['softforks']['bip65']['active'] # Create a P2WSH script with CLTV - script = CScript([1000, OP_CHECKLOCKTIMEVERIFY, OP_DROP]) + script = CScript([100, OP_CHECKLOCKTIMEVERIFY, OP_DROP]) address = script_to_p2wsh(script) # Fund that address and make the spend diff --git a/test/functional/test_framework/blocktools.py b/test/functional/test_framework/blocktools.py index 11d0ab40d5..25b36b6a91 100644 --- a/test/functional/test_framework/blocktools.py +++ b/test/functional/test_framework/blocktools.py @@ -55,7 +55,7 @@ COINBASE_MATURITY = 100 # Soft-fork activation heights DERSIG_HEIGHT = 102 # BIP 66 -CLTV_HEIGHT = 1351 +CLTV_HEIGHT = 111 # BIP 65 CSV_ACTIVATION_HEIGHT = 432 # From BIP141 diff --git a/test/functional/test_framework/messages.py b/test/functional/test_framework/messages.py index 6e57107f86..65d90f8448 100755 --- a/test/functional/test_framework/messages.py +++ b/test/functional/test_framework/messages.py @@ -19,7 +19,6 @@ Classes use __slots__ to ensure extraneous attributes aren't accidentally added by tests, compromising their intended effect. """ from base64 import b32decode, b32encode -from codecs import encode import copy import hashlib from io import BytesIO @@ -681,7 +680,7 @@ class CBlockHeader: r += struct.pack("<I", self.nBits) r += struct.pack("<I", self.nNonce) self.sha256 = uint256_from_str(hash256(r)) - self.hash = encode(hash256(r)[::-1], 'hex_codec').decode('ascii') + self.hash = hash256(r)[::-1].hex() def rehash(self): self.sha256 = None diff --git a/test/functional/test_framework/test_framework.py b/test/functional/test_framework/test_framework.py index 6d8e6ef45c..f382e0fdb3 100755 --- a/test/functional/test_framework/test_framework.py +++ b/test/functional/test_framework/test_framework.py @@ -410,7 +410,7 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass): # To ensure that all nodes are out of IBD, the most recent block # must have a timestamp not too old (see IsInitialBlockDownload()). self.log.debug('Generate a block with current time') - block_hash = self.nodes[0].generate(1)[0] + block_hash = self.generate(self.nodes[0], 1)[0] block = self.nodes[0].getblock(blockhash=block_hash, verbosity=0) for n in self.nodes: n.submitblock(block) @@ -619,6 +619,22 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass): self.connect_nodes(1, 2) self.sync_all() + def generate(self, generator, *args, **kwargs): + blocks = generator.generate(*args, **kwargs) + return blocks + + def generateblock(self, generator, *args, **kwargs): + blocks = generator.generateblock(*args, **kwargs) + return blocks + + def generatetoaddress(self, generator, *args, **kwargs): + blocks = generator.generatetoaddress(*args, **kwargs) + return blocks + + def generatetodescriptor(self, generator, *args, **kwargs): + blocks = generator.generatetodescriptor(*args, **kwargs) + return blocks + def sync_blocks(self, nodes=None, wait=1, timeout=60): """ Wait until everybody has the same tip. @@ -749,7 +765,8 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass): gen_addresses = [k.address for k in TestNode.PRIV_KEYS][:3] + [ADDRESS_BCRT1_P2WSH_OP_TRUE] assert_equal(len(gen_addresses), 4) for i in range(8): - cache_node.generatetoaddress( + self.generatetoaddress( + cache_node, nblocks=25 if i != 7 else 24, address=gen_addresses[i % len(gen_addresses)], ) diff --git a/test/functional/test_framework/util.py b/test/functional/test_framework/util.py index 54f2fdee21..ec27fd7f85 100644 --- a/test/functional/test_framework/util.py +++ b/test/functional/test_framework/util.py @@ -445,10 +445,10 @@ def find_output(node, txid, amount, *, blockhash=None): # Helper to create at least "count" utxos # Pass in a fee that is sufficient for relay and mining new transactions. -def create_confirmed_utxos(fee, node, count): +def create_confirmed_utxos(test_framework, fee, node, count): to_generate = int(0.5 * count) + 101 while to_generate > 0: - node.generate(min(25, to_generate)) + test_framework.generate(node, min(25, to_generate)) to_generate -= 25 utxos = node.listunspent() iterations = count - len(utxos) @@ -469,7 +469,7 @@ def create_confirmed_utxos(fee, node, count): node.sendrawtransaction(signed_tx) while (node.getmempoolinfo()['size'] > 0): - node.generate(1) + test_framework.generate(node, 1) utxos = node.listunspent() assert len(utxos) >= count @@ -541,7 +541,7 @@ def create_lots_of_big_transactions(node, txouts, utxos, num, fee): return txids -def mine_large_block(node, utxos=None): +def mine_large_block(test_framework, node, utxos=None): # generate a 66k transaction, # and 14 of them is close to the 1MB block limit num = 14 @@ -552,17 +552,17 @@ def mine_large_block(node, utxos=None): utxos.extend(node.listunspent()) fee = 100 * node.getnetworkinfo()["relayfee"] create_lots_of_big_transactions(node, txouts, utxos, num, fee=fee) - node.generate(1) + test_framework.generate(node, 1) -def generate_to_height(node, target_height): +def generate_to_height(test_framework, node, target_height): """Generates blocks until a given target block height has been reached. To prevent timeouts, only up to 200 blocks are generated per RPC call. Can be used to activate certain soft-forks (e.g. CSV, CLTV).""" current_height = node.getblockcount() while current_height < target_height: nblocks = min(200, target_height - current_height) - current_height += len(node.generate(nblocks)) + current_height += len(test_framework.generate(node, nblocks)) assert_equal(node.getblockcount(), target_height) diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py index 1a1a6a263a..d6d676da1f 100755 --- a/test/functional/test_runner.py +++ b/test/functional/test_runner.py @@ -225,7 +225,8 @@ BASE_SCRIPTS = [ 'wallet_importprunedfunds.py --descriptors', 'p2p_leak_tx.py', 'p2p_eviction.py', - 'rpc_signmessage.py', + 'wallet_signmessagewithaddress.py', + 'rpc_signmessagewithprivkey.py', 'rpc_generateblock.py', 'rpc_generate.py', 'wallet_balance.py --legacy-wallet', diff --git a/test/functional/wallet_descriptor.py b/test/functional/wallet_descriptor.py index c6f5d334f8..17a4c79da3 100755 --- a/test/functional/wallet_descriptor.py +++ b/test/functional/wallet_descriptor.py @@ -84,7 +84,7 @@ class WalletDescriptorTest(BitcoinTestFramework): send_wrpc = self.nodes[0].get_wallet_rpc("desc1") # Generate some coins - send_wrpc.generatetoaddress(COINBASE_MATURITY + 1, send_wrpc.getnewaddress()) + self.generatetoaddress(send_wrpc, COINBASE_MATURITY + 1, send_wrpc.getnewaddress()) # Make transactions self.log.info("Test sending and receiving") diff --git a/test/functional/wallet_importdescriptors.py b/test/functional/wallet_importdescriptors.py index 262175c789..4cb311983c 100755 --- a/test/functional/wallet_importdescriptors.py +++ b/test/functional/wallet_importdescriptors.py @@ -74,7 +74,7 @@ class ImportDescriptorsTest(BitcoinTestFramework): assert_equal(wpriv.getwalletinfo()['keypoolsize'], 0) self.log.info('Mining coins') - w0.generatetoaddress(COINBASE_MATURITY + 1, w0.getnewaddress()) + self.generatetoaddress(w0, COINBASE_MATURITY + 1, w0.getnewaddress()) # RPC importdescriptors ----------------------------------------------- @@ -405,7 +405,7 @@ class ImportDescriptorsTest(BitcoinTestFramework): solvable=True, ismine=True) txid = w0.sendtoaddress(address, 49.99995540) - w0.generatetoaddress(6, w0.getnewaddress()) + self.generatetoaddress(w0, 6, w0.getnewaddress()) self.sync_blocks() tx = wpriv.createrawtransaction([{"txid": txid, "vout": 0}], {w0.getnewaddress(): 49.999}) signed_tx = wpriv.signrawtransactionwithwallet(tx) diff --git a/test/functional/wallet_signmessagewithaddress.py b/test/functional/wallet_signmessagewithaddress.py new file mode 100755 index 0000000000..bf6f95e3f1 --- /dev/null +++ b/test/functional/wallet_signmessagewithaddress.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +# Copyright (c) 2016-2019 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 Wallet commands for signing and verifying messages.""" + +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import ( + assert_raises_rpc_error, +) + +class SignMessagesWithAddressTest(BitcoinTestFramework): + def set_test_params(self): + self.setup_clean_chain = True + self.num_nodes = 1 + self.extra_args = [["-addresstype=legacy"]] + + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + + def run_test(self): + message = 'This is just a test message' + + self.log.info('test signing with an address with wallet') + address = self.nodes[0].getnewaddress() + signature = self.nodes[0].signmessage(address, message) + assert self.nodes[0].verifymessage(address, signature, message) + + self.log.info('test verifying with another address should not work') + other_address = self.nodes[0].getnewaddress() + other_signature = self.nodes[0].signmessage(other_address, message) + assert not self.nodes[0].verifymessage(other_address, signature, message) + assert not self.nodes[0].verifymessage(address, other_signature, message) + + self.log.info('test parameter validity and error codes') + # signmessage has two required parameters + for num_params in [0, 1, 3, 4, 5]: + param_list = ["dummy"]*num_params + assert_raises_rpc_error(-1, "signmessage", self.nodes[0].signmessage, *param_list) + # invalid key or address provided + assert_raises_rpc_error(-5, "Invalid address", self.nodes[0].signmessage, "invalid_addr", message) + + +if __name__ == '__main__': + SignMessagesWithAddressTest().main() diff --git a/test/lint/lint-circular-dependencies.sh b/test/lint/lint-circular-dependencies.sh index df5051720b..233381f2d9 100755 --- a/test/lint/lint-circular-dependencies.sh +++ b/test/lint/lint-circular-dependencies.sh @@ -15,6 +15,7 @@ EXPECTED_CIRCULAR_DEPENDENCIES=( "index/base -> validation -> index/blockfilterindex -> index/base" "index/coinstatsindex -> node/coinstats -> index/coinstatsindex" "policy/fees -> txmempool -> policy/fees" + "policy/rbf -> txmempool -> validation -> policy/rbf" "qt/addresstablemodel -> qt/walletmodel -> qt/addresstablemodel" "qt/recentrequeststablemodel -> qt/walletmodel -> qt/recentrequeststablemodel" "qt/sendcoinsdialog -> qt/walletmodel -> qt/sendcoinsdialog" diff --git a/test/util/bitcoin-util-test.py b/test/util/bitcoin-util-test.py index 7b1cc2b031..aa8fd6eee5 100755 --- a/test/util/bitcoin-util-test.py +++ b/test/util/bitcoin-util-test.py @@ -10,7 +10,6 @@ Runs automatically during `make check`. Can also be run manually.""" import argparse -import binascii import configparser import difflib import json @@ -167,7 +166,7 @@ def parse_output(a, fmt): if fmt == 'json': # json: compare parsed data return json.loads(a) elif fmt == 'hex': # hex: parse and compare binary data - return binascii.a2b_hex(a.strip()) + return bytes.fromhex(a.strip()) else: raise NotImplementedError("Don't know how to compare %s" % fmt) |