aboutsummaryrefslogtreecommitdiff
path: root/test/functional
diff options
context:
space:
mode:
Diffstat (limited to 'test/functional')
-rwxr-xr-xtest/functional/feature_assumevalid.py9
-rwxr-xr-xtest/functional/feature_backwards_compatibility.py5
-rwxr-xr-xtest/functional/feature_blockfilterindex_prune.py8
-rwxr-xr-xtest/functional/feature_cltv.py30
-rwxr-xr-xtest/functional/feature_coinstatsindex.py3
-rwxr-xr-xtest/functional/feature_csv_activation.py213
-rwxr-xr-xtest/functional/feature_dersig.py26
-rwxr-xr-xtest/functional/feature_includeconf.py9
-rwxr-xr-xtest/functional/feature_loadblock.py3
-rwxr-xr-xtest/functional/feature_nulldummy.py9
-rwxr-xr-xtest/functional/feature_rbf.py3
-rwxr-xr-xtest/functional/feature_taproot.py3
-rwxr-xr-xtest/functional/interface_bitcoin_cli.py4
-rwxr-xr-xtest/functional/mempool_accept.py3
-rwxr-xr-xtest/functional/mempool_compatibility.py3
-rwxr-xr-xtest/functional/mempool_expiry.py3
-rwxr-xr-xtest/functional/mempool_package_onemore.py3
-rwxr-xr-xtest/functional/mempool_packages.py3
-rwxr-xr-xtest/functional/mempool_reorg.py109
-rwxr-xr-xtest/functional/mempool_resurrect.py3
-rwxr-xr-xtest/functional/mining_getblocktemplate_longpoll.py3
-rwxr-xr-xtest/functional/p2p_blocksonly.py3
-rwxr-xr-xtest/functional/p2p_compactblocks.py13
-rwxr-xr-xtest/functional/p2p_eviction.py8
-rwxr-xr-xtest/functional/p2p_feefilter.py3
-rwxr-xr-xtest/functional/p2p_leak_tx.py3
-rwxr-xr-xtest/functional/rpc_createmultisig.py3
-rwxr-xr-xtest/functional/rpc_dumptxoutset.py4
-rwxr-xr-xtest/functional/rpc_getblockstats.py4
-rwxr-xr-xtest/functional/rpc_net.py77
-rwxr-xr-xtest/functional/rpc_packages.py362
-rwxr-xr-xtest/functional/rpc_rawtransaction.py4
-rwxr-xr-xtest/functional/rpc_signrawtransaction.py5
-rwxr-xr-xtest/functional/rpc_txoutproof.py3
-rw-r--r--test/functional/test_framework/blocktools.py3
-rw-r--r--test/functional/test_framework/netutil.py2
-rw-r--r--test/functional/test_framework/wallet.py76
-rwxr-xr-xtest/functional/test_runner.py1
-rwxr-xr-xtest/functional/wallet_abandonconflict.py3
-rwxr-xr-xtest/functional/wallet_address_types.py5
-rwxr-xr-xtest/functional/wallet_avoidreuse.py46
-rwxr-xr-xtest/functional/wallet_backup.py5
-rwxr-xr-xtest/functional/wallet_balance.py3
-rwxr-xr-xtest/functional/wallet_basic.py5
-rwxr-xr-xtest/functional/wallet_bumpfee.py3
-rwxr-xr-xtest/functional/wallet_descriptor.py3
-rwxr-xr-xtest/functional/wallet_fallbackfee.py4
-rwxr-xr-xtest/functional/wallet_groups.py3
-rwxr-xr-xtest/functional/wallet_hd.py3
-rwxr-xr-xtest/functional/wallet_importdescriptors.py3
-rwxr-xr-xtest/functional/wallet_importmulti.py9
-rwxr-xr-xtest/functional/wallet_importprunedfunds.py5
-rwxr-xr-xtest/functional/wallet_keypool_topup.py3
-rwxr-xr-xtest/functional/wallet_labels.py7
-rwxr-xr-xtest/functional/wallet_listsinceblock.py3
-rwxr-xr-xtest/functional/wallet_multiwallet.py3
-rwxr-xr-xtest/functional/wallet_upgradewallet.py7
-rwxr-xr-xtest/functional/wallet_watchonly.py3
58 files changed, 850 insertions, 305 deletions
diff --git a/test/functional/feature_assumevalid.py b/test/functional/feature_assumevalid.py
index 1a148f04f4..a4480307a7 100755
--- a/test/functional/feature_assumevalid.py
+++ b/test/functional/feature_assumevalid.py
@@ -31,6 +31,7 @@ Start three nodes:
"""
from test_framework.blocktools import (
+ COINBASE_MATURITY,
create_block,
create_coinbase,
)
@@ -161,8 +162,8 @@ class AssumeValidTest(BitcoinTestFramework):
# Send blocks to node0. Block 102 will be rejected.
self.send_blocks_until_disconnected(p2p0)
- self.wait_until(lambda: self.nodes[0].getblockcount() >= 101)
- assert_equal(self.nodes[0].getblockcount(), 101)
+ self.wait_until(lambda: self.nodes[0].getblockcount() >= COINBASE_MATURITY + 1)
+ assert_equal(self.nodes[0].getblockcount(), COINBASE_MATURITY + 1)
# Send all blocks to node1. All blocks will be accepted.
for i in range(2202):
@@ -173,8 +174,8 @@ class AssumeValidTest(BitcoinTestFramework):
# Send blocks to node2. Block 102 will be rejected.
self.send_blocks_until_disconnected(p2p2)
- self.wait_until(lambda: self.nodes[2].getblockcount() >= 101)
- assert_equal(self.nodes[2].getblockcount(), 101)
+ self.wait_until(lambda: self.nodes[2].getblockcount() >= COINBASE_MATURITY + 1)
+ assert_equal(self.nodes[2].getblockcount(), COINBASE_MATURITY + 1)
if __name__ == '__main__':
diff --git a/test/functional/feature_backwards_compatibility.py b/test/functional/feature_backwards_compatibility.py
index e6a53b52db..c712f7141c 100755
--- a/test/functional/feature_backwards_compatibility.py
+++ b/test/functional/feature_backwards_compatibility.py
@@ -22,6 +22,7 @@ needs an older patch version.
import os
import shutil
+from test_framework.blocktools import COINBASE_MATURITY
from test_framework.test_framework import BitcoinTestFramework
from test_framework.descriptors import descsum_create
@@ -64,13 +65,13 @@ class BackwardsCompatibilityTest(BitcoinTestFramework):
self.import_deterministic_coinbase_privkeys()
def run_test(self):
- self.nodes[0].generatetoaddress(101, self.nodes[0].getnewaddress())
+ self.nodes[0].generatetoaddress(COINBASE_MATURITY + 1, self.nodes[0].getnewaddress())
self.sync_blocks()
# Sanity check the test framework:
res = self.nodes[self.num_nodes - 1].getblockchaininfo()
- assert_equal(res['blocks'], 101)
+ assert_equal(res['blocks'], COINBASE_MATURITY + 1)
node_master = self.nodes[self.num_nodes - 5]
node_v19 = self.nodes[self.num_nodes - 4]
diff --git a/test/functional/feature_blockfilterindex_prune.py b/test/functional/feature_blockfilterindex_prune.py
index bada791fba..28d8f2fbbc 100755
--- a/test/functional/feature_blockfilterindex_prune.py
+++ b/test/functional/feature_blockfilterindex_prune.py
@@ -54,11 +54,13 @@ class FeatureBlockfilterindexPruneTest(BitcoinTestFramework):
self.stop_node(0)
self.log.info("make sure we get an init error when starting the node again with block filters")
- with self.nodes[0].assert_debug_log(["basic block filter index best block of the index goes beyond pruned data. Please disable the index or reindex (which will download the whole blockchain again)"]):
- self.nodes[0].assert_start_raises_init_error(extra_args=["-fastprune", "-prune=1", "-blockfilterindex=1"])
+ self.nodes[0].assert_start_raises_init_error(
+ extra_args=["-fastprune", "-prune=1", "-blockfilterindex=1"],
+ expected_msg="Error: basic block filter index best block of the index goes beyond pruned data. Please disable the index or reindex (which will download the whole blockchain again)",
+ )
self.log.info("make sure the node starts again with the -reindex arg")
- self.start_node(0, extra_args = ["-fastprune", "-prune=1", "-blockfilterindex", "-reindex"])
+ self.start_node(0, extra_args=["-fastprune", "-prune=1", "-blockfilterindex", "-reindex"])
if __name__ == '__main__':
diff --git a/test/functional/feature_cltv.py b/test/functional/feature_cltv.py
index 6c51944d81..10d2072dba 100755
--- a/test/functional/feature_cltv.py
+++ b/test/functional/feature_cltv.py
@@ -26,7 +26,10 @@ from test_framework.script import (
)
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import assert_equal
-from test_framework.wallet import MiniWallet
+from test_framework.wallet import (
+ MiniWallet,
+ MiniWalletMode,
+)
CLTV_HEIGHT = 1351
@@ -34,7 +37,7 @@ CLTV_HEIGHT = 1351
# Helper function to modify a transaction by
# 1) prepending a given script to the scriptSig of vin 0 and
# 2) (optionally) modify the nSequence of vin 0 and the tx's nLockTime
-def cltv_modify_tx(node, tx, prepend_scriptsig, nsequence=None, nlocktime=None):
+def cltv_modify_tx(tx, prepend_scriptsig, nsequence=None, nlocktime=None):
assert_equal(len(tx.vin), 1)
if nsequence is not None:
tx.vin[0].nSequence = nsequence
@@ -42,10 +45,9 @@ def cltv_modify_tx(node, tx, prepend_scriptsig, nsequence=None, nlocktime=None):
tx.vin[0].scriptSig = CScript(prepend_scriptsig + list(CScript(tx.vin[0].scriptSig)))
tx.rehash()
- return tx
-def cltv_invalidate(node, tx, failure_reason):
+def cltv_invalidate(tx, failure_reason):
# Modify the signature in vin 0 and nSequence/nLockTime of the tx to fail CLTV
#
# According to BIP65, OP_CHECKLOCKTIMEVERIFY can fail due the following reasons:
@@ -66,14 +68,14 @@ def cltv_invalidate(node, tx, failure_reason):
[[CScriptNum(500), OP_CHECKLOCKTIMEVERIFY, OP_DROP], 0xffffffff, 500],
][failure_reason]
- return cltv_modify_tx(node, tx, prepend_scriptsig=scheme[0], nsequence=scheme[1], nlocktime=scheme[2])
+ cltv_modify_tx(tx, prepend_scriptsig=scheme[0], nsequence=scheme[1], nlocktime=scheme[2])
-def cltv_validate(node, tx, height):
+def cltv_validate(tx, height):
# Modify the signature in vin 0 and nSequence/nLockTime of the tx to pass CLTV
scheme = [[CScriptNum(height), OP_CHECKLOCKTIMEVERIFY, OP_DROP], 0, height]
- return cltv_modify_tx(node, tx, prepend_scriptsig=scheme[0], nsequence=scheme[1], nlocktime=scheme[2])
+ cltv_modify_tx(tx, prepend_scriptsig=scheme[0], nsequence=scheme[1], nlocktime=scheme[2])
class BIP65Test(BitcoinTestFramework):
@@ -97,7 +99,7 @@ class BIP65Test(BitcoinTestFramework):
def run_test(self):
peer = self.nodes[0].add_p2p_connection(P2PInterface())
- wallet = MiniWallet(self.nodes[0], raw_script=True)
+ wallet = MiniWallet(self.nodes[0], mode=MiniWalletMode.RAW_OP_TRUE)
self.test_cltv_info(is_active=False)
@@ -108,17 +110,17 @@ class BIP65Test(BitcoinTestFramework):
self.log.info("Test that invalid-according-to-CLTV transactions can still appear in a block")
# create one invalid tx per CLTV failure reason (5 in total) and collect them
- invalid_ctlv_txs = []
+ invalid_cltv_txs = []
for i in range(5):
spendtx = wallet.create_self_transfer(from_node=self.nodes[0])['tx']
- spendtx = cltv_invalidate(self.nodes[0], spendtx, i)
- invalid_ctlv_txs.append(spendtx)
+ cltv_invalidate(spendtx, i)
+ invalid_cltv_txs.append(spendtx)
tip = self.nodes[0].getbestblockhash()
block_time = self.nodes[0].getblockheader(tip)['mediantime'] + 1
block = create_block(int(tip, 16), create_coinbase(CLTV_HEIGHT - 1), block_time)
block.nVersion = 3
- block.vtx.extend(invalid_ctlv_txs)
+ block.vtx.extend(invalid_cltv_txs)
block.hashMerkleRoot = block.calc_merkle_root()
block.solve()
@@ -146,7 +148,7 @@ class BIP65Test(BitcoinTestFramework):
# create and test one invalid tx per CLTV failure reason (5 in total)
for i in range(5):
spendtx = wallet.create_self_transfer(from_node=self.nodes[0])['tx']
- spendtx = cltv_invalidate(self.nodes[0], spendtx, i)
+ cltv_invalidate(spendtx, i)
expected_cltv_reject_reason = [
"non-mandatory-script-verify-flag (Operation not valid with the current stack size)",
@@ -179,7 +181,7 @@ class BIP65Test(BitcoinTestFramework):
peer.sync_with_ping()
self.log.info("Test that a version 4 block with a valid-according-to-CLTV transaction is accepted")
- spendtx = cltv_validate(self.nodes[0], spendtx, CLTV_HEIGHT - 1)
+ cltv_validate(spendtx, CLTV_HEIGHT - 1)
block.vtx.pop(1)
block.vtx.append(spendtx)
diff --git a/test/functional/feature_coinstatsindex.py b/test/functional/feature_coinstatsindex.py
index d3adde5cc5..cf270b25ee 100755
--- a/test/functional/feature_coinstatsindex.py
+++ b/test/functional/feature_coinstatsindex.py
@@ -12,6 +12,7 @@ the index.
from decimal import Decimal
from test_framework.blocktools import (
+ COINBASE_MATURITY,
create_block,
create_coinbase,
)
@@ -68,7 +69,7 @@ class CoinStatsIndexTest(BitcoinTestFramework):
index_hash_options = ['none', 'muhash']
# Generate a normal transaction and mine it
- node.generate(101)
+ node.generate(COINBASE_MATURITY + 1)
address = self.nodes[0].get_deterministic_priv_key().address
node.sendtoaddress(address=address, amount=10, subtractfeefromamount=True)
node.generate(1)
diff --git a/test/functional/feature_csv_activation.py b/test/functional/feature_csv_activation.py
index 8fa3f52de8..5081867319 100755
--- a/test/functional/feature_csv_activation.py
+++ b/test/functional/feature_csv_activation.py
@@ -37,13 +37,13 @@ bip112txs_vary_OP_CSV_9 - 16 txs with nSequence = 9 evaluated against varying {r
bip112tx_special - test negative argument to OP_CSV
bip112tx_emptystack - test empty stack (= no argument) OP_CSV
"""
-from decimal import Decimal
from itertools import product
-from io import BytesIO
import time
-from test_framework.blocktools import create_coinbase, create_block, create_transaction
-from test_framework.messages import ToHex, CTransaction
+from test_framework.blocktools import (
+ create_block,
+ create_coinbase,
+)
from test_framework.p2p import P2PDataStore
from test_framework.script import (
CScript,
@@ -53,9 +53,12 @@ from test_framework.script import (
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
assert_equal,
- hex_str_to_bytes,
softfork_active,
)
+from test_framework.wallet import (
+ MiniWallet,
+ MiniWalletMode,
+)
TESTING_TX_COUNT = 83 # Number of testing transactions: 1 BIP113 tx, 16 BIP68 txs, 66 BIP112 txs (see comments above)
COINBASE_BLOCK_COUNT = TESTING_TX_COUNT # Number of coinbase blocks we need to generate as inputs for our txs
@@ -83,66 +86,6 @@ def relative_locktime(sdf, srhb, stf, srlb):
def all_rlt_txs(txs):
return [tx['tx'] for tx in txs]
-def sign_transaction(node, unsignedtx):
- rawtx = ToHex(unsignedtx)
- signresult = node.signrawtransactionwithwallet(rawtx)
- tx = CTransaction()
- f = BytesIO(hex_str_to_bytes(signresult['hex']))
- tx.deserialize(f)
- return tx
-
-def create_bip112special(node, input, txversion, address):
- tx = create_transaction(node, input, address, amount=Decimal("49.98"))
- tx.nVersion = txversion
- signtx = sign_transaction(node, tx)
- signtx.vin[0].scriptSig = CScript([-1, OP_CHECKSEQUENCEVERIFY, OP_DROP] + list(CScript(signtx.vin[0].scriptSig)))
- return signtx
-
-def create_bip112emptystack(node, input, txversion, address):
- tx = create_transaction(node, input, address, amount=Decimal("49.98"))
- tx.nVersion = txversion
- signtx = sign_transaction(node, tx)
- signtx.vin[0].scriptSig = CScript([OP_CHECKSEQUENCEVERIFY] + list(CScript(signtx.vin[0].scriptSig)))
- return signtx
-
-def send_generic_input_tx(node, coinbases, address):
- return node.sendrawtransaction(ToHex(sign_transaction(node, create_transaction(node, node.getblock(coinbases.pop())['tx'][0], address, amount=Decimal("49.99")))))
-
-def create_bip68txs(node, bip68inputs, txversion, address, locktime_delta=0):
- """Returns a list of bip68 transactions with different bits set."""
- txs = []
- assert len(bip68inputs) >= 16
- for i, (sdf, srhb, stf, srlb) in enumerate(product(*[[True, False]] * 4)):
- locktime = relative_locktime(sdf, srhb, stf, srlb)
- tx = create_transaction(node, bip68inputs[i], address, amount=Decimal("49.98"))
- tx.nVersion = txversion
- tx.vin[0].nSequence = locktime + locktime_delta
- tx = sign_transaction(node, tx)
- tx.rehash()
- txs.append({'tx': tx, 'sdf': sdf, 'stf': stf})
-
- return txs
-
-def create_bip112txs(node, bip112inputs, varyOP_CSV, txversion, address, locktime_delta=0):
- """Returns a list of bip68 transactions with different bits set."""
- txs = []
- assert len(bip112inputs) >= 16
- for i, (sdf, srhb, stf, srlb) in enumerate(product(*[[True, False]] * 4)):
- locktime = relative_locktime(sdf, srhb, stf, srlb)
- tx = create_transaction(node, bip112inputs[i], address, amount=Decimal("49.98"))
- if (varyOP_CSV): # if varying OP_CSV, nSequence is fixed
- tx.vin[0].nSequence = BASE_RELATIVE_LOCKTIME + locktime_delta
- else: # vary nSequence instead, OP_CSV is fixed
- tx.vin[0].nSequence = locktime + locktime_delta
- tx.nVersion = txversion
- signtx = sign_transaction(node, tx)
- if (varyOP_CSV):
- signtx.vin[0].scriptSig = CScript([locktime, OP_CHECKSEQUENCEVERIFY, OP_DROP] + list(CScript(signtx.vin[0].scriptSig)))
- else:
- signtx.vin[0].scriptSig = CScript([BASE_RELATIVE_LOCKTIME, OP_CHECKSEQUENCEVERIFY, OP_DROP] + list(CScript(signtx.vin[0].scriptSig)))
- tx.rehash()
- txs.append({'tx': signtx, 'sdf': sdf, 'stf': stf})
- return txs
class BIP68_112_113Test(BitcoinTestFramework):
def set_test_params(self):
@@ -150,13 +93,69 @@ class BIP68_112_113Test(BitcoinTestFramework):
self.setup_clean_chain = True
self.extra_args = [[
'-whitelist=noban@127.0.0.1',
- '-addresstype=legacy',
'-par=1', # Use only one script thread to get the exact reject reason for testing
]]
self.supports_cli = False
- def skip_test_if_missing_module(self):
- self.skip_if_no_wallet()
+ def create_self_transfer_from_utxo(self, input_tx):
+ utxo = self.miniwallet.get_utxo(txid=input_tx.rehash(), mark_as_spent=False)
+ tx = self.miniwallet.create_self_transfer(from_node=self.nodes[0], utxo_to_spend=utxo)['tx']
+ return tx
+
+ def create_bip112special(self, input, txversion):
+ tx = self.create_self_transfer_from_utxo(input)
+ tx.nVersion = txversion
+ self.miniwallet.sign_tx(tx)
+ tx.vin[0].scriptSig = CScript([-1, OP_CHECKSEQUENCEVERIFY, OP_DROP] + list(CScript(tx.vin[0].scriptSig)))
+ return tx
+
+ def create_bip112emptystack(self, input, txversion):
+ tx = self.create_self_transfer_from_utxo(input)
+ tx.nVersion = txversion
+ self.miniwallet.sign_tx(tx)
+ tx.vin[0].scriptSig = CScript([OP_CHECKSEQUENCEVERIFY] + list(CScript(tx.vin[0].scriptSig)))
+ return tx
+
+ def send_generic_input_tx(self, coinbases):
+ input_txid = self.nodes[0].getblock(coinbases.pop(), 2)['tx'][0]['txid']
+ utxo_to_spend = self.miniwallet.get_utxo(txid=input_txid)
+ return self.miniwallet.send_self_transfer(from_node=self.nodes[0], utxo_to_spend=utxo_to_spend)['tx']
+
+ def create_bip68txs(self, bip68inputs, txversion, locktime_delta=0):
+ """Returns a list of bip68 transactions with different bits set."""
+ txs = []
+ assert len(bip68inputs) >= 16
+ for i, (sdf, srhb, stf, srlb) in enumerate(product(*[[True, False]] * 4)):
+ locktime = relative_locktime(sdf, srhb, stf, srlb)
+ tx = self.create_self_transfer_from_utxo(bip68inputs[i])
+ tx.nVersion = txversion
+ tx.vin[0].nSequence = locktime + locktime_delta
+ self.miniwallet.sign_tx(tx)
+ tx.rehash()
+ txs.append({'tx': tx, 'sdf': sdf, 'stf': stf})
+
+ return txs
+
+ def create_bip112txs(self, bip112inputs, varyOP_CSV, txversion, locktime_delta=0):
+ """Returns a list of bip68 transactions with different bits set."""
+ txs = []
+ assert len(bip112inputs) >= 16
+ for i, (sdf, srhb, stf, srlb) in enumerate(product(*[[True, False]] * 4)):
+ locktime = relative_locktime(sdf, srhb, stf, srlb)
+ tx = self.create_self_transfer_from_utxo(bip112inputs[i])
+ if (varyOP_CSV): # if varying OP_CSV, nSequence is fixed
+ tx.vin[0].nSequence = BASE_RELATIVE_LOCKTIME + locktime_delta
+ else: # vary nSequence instead, OP_CSV is fixed
+ tx.vin[0].nSequence = locktime + locktime_delta
+ tx.nVersion = txversion
+ self.miniwallet.sign_tx(tx)
+ if (varyOP_CSV):
+ tx.vin[0].scriptSig = CScript([locktime, OP_CHECKSEQUENCEVERIFY, OP_DROP] + list(CScript(tx.vin[0].scriptSig)))
+ else:
+ tx.vin[0].scriptSig = CScript([BASE_RELATIVE_LOCKTIME, OP_CHECKSEQUENCEVERIFY, OP_DROP] + list(CScript(tx.vin[0].scriptSig)))
+ tx.rehash()
+ txs.append({'tx': tx, 'sdf': sdf, 'stf': stf})
+ return txs
def generate_blocks(self, number):
test_blocks = []
@@ -185,16 +184,16 @@ class BIP68_112_113Test(BitcoinTestFramework):
def run_test(self):
self.helper_peer = self.nodes[0].add_p2p_connection(P2PDataStore())
+ self.miniwallet = MiniWallet(self.nodes[0], mode=MiniWalletMode.RAW_P2PK)
self.log.info("Generate blocks in the past for coinbase outputs.")
long_past_time = int(time.time()) - 600 * 1000 # enough to build up to 1000 blocks 10 minutes apart without worrying about getting into the future
self.nodes[0].setmocktime(long_past_time - 100) # enough so that the generated blocks will still all be before long_past_time
- self.coinbase_blocks = self.nodes[0].generate(COINBASE_BLOCK_COUNT) # blocks generated for inputs
+ self.coinbase_blocks = self.miniwallet.generate(COINBASE_BLOCK_COUNT) # blocks generated for inputs
self.nodes[0].setmocktime(0) # set time back to present so yielded blocks aren't in the future as we advance last_block_time
self.tipheight = COINBASE_BLOCK_COUNT # height of the next block to build
self.last_block_time = long_past_time
self.tip = int(self.nodes[0].getbestblockhash(), 16)
- self.nodeaddress = self.nodes[0].getnewaddress()
# Activation height is hardcoded
# We advance to block height five below BIP112 activation for the following tests
@@ -209,14 +208,14 @@ class BIP68_112_113Test(BitcoinTestFramework):
# 16 normal inputs
bip68inputs = []
for _ in range(16):
- bip68inputs.append(send_generic_input_tx(self.nodes[0], self.coinbase_blocks, self.nodeaddress))
+ bip68inputs.append(self.send_generic_input_tx(self.coinbase_blocks))
# 2 sets of 16 inputs with 10 OP_CSV OP_DROP (actually will be prepended to spending scriptSig)
bip112basicinputs = []
for _ in range(2):
inputs = []
for _ in range(16):
- inputs.append(send_generic_input_tx(self.nodes[0], self.coinbase_blocks, self.nodeaddress))
+ inputs.append(self.send_generic_input_tx(self.coinbase_blocks))
bip112basicinputs.append(inputs)
# 2 sets of 16 varied inputs with (relative_lock_time) OP_CSV OP_DROP (actually will be prepended to spending scriptSig)
@@ -224,16 +223,16 @@ class BIP68_112_113Test(BitcoinTestFramework):
for _ in range(2):
inputs = []
for _ in range(16):
- inputs.append(send_generic_input_tx(self.nodes[0], self.coinbase_blocks, self.nodeaddress))
+ inputs.append(self.send_generic_input_tx(self.coinbase_blocks))
bip112diverseinputs.append(inputs)
# 1 special input with -1 OP_CSV OP_DROP (actually will be prepended to spending scriptSig)
- bip112specialinput = send_generic_input_tx(self.nodes[0], self.coinbase_blocks, self.nodeaddress)
+ bip112specialinput = self.send_generic_input_tx(self.coinbase_blocks)
# 1 special input with (empty stack) OP_CSV (actually will be prepended to spending scriptSig)
- bip112emptystackinput = send_generic_input_tx(self.nodes[0],self.coinbase_blocks, self.nodeaddress)
+ bip112emptystackinput = self.send_generic_input_tx(self.coinbase_blocks)
# 1 normal input
- bip113input = send_generic_input_tx(self.nodes[0], self.coinbase_blocks, self.nodeaddress)
+ bip113input = self.send_generic_input_tx(self.coinbase_blocks)
self.nodes[0].setmocktime(self.last_block_time + 600)
inputblockhash = self.nodes[0].generate(1)[0] # 1 block generated for inputs to be in chain at height 431
@@ -253,36 +252,36 @@ class BIP68_112_113Test(BitcoinTestFramework):
# Test both version 1 and version 2 transactions for all tests
# BIP113 test transaction will be modified before each use to put in appropriate block time
- bip113tx_v1 = create_transaction(self.nodes[0], bip113input, self.nodeaddress, amount=Decimal("49.98"))
+ bip113tx_v1 = self.create_self_transfer_from_utxo(bip113input)
bip113tx_v1.vin[0].nSequence = 0xFFFFFFFE
bip113tx_v1.nVersion = 1
- bip113tx_v2 = create_transaction(self.nodes[0], bip113input, self.nodeaddress, amount=Decimal("49.98"))
+ bip113tx_v2 = self.create_self_transfer_from_utxo(bip113input)
bip113tx_v2.vin[0].nSequence = 0xFFFFFFFE
bip113tx_v2.nVersion = 2
# For BIP68 test all 16 relative sequence locktimes
- bip68txs_v1 = create_bip68txs(self.nodes[0], bip68inputs, 1, self.nodeaddress)
- bip68txs_v2 = create_bip68txs(self.nodes[0], bip68inputs, 2, self.nodeaddress)
+ bip68txs_v1 = self.create_bip68txs(bip68inputs, 1)
+ bip68txs_v2 = self.create_bip68txs(bip68inputs, 2)
# For BIP112 test:
# 16 relative sequence locktimes of 10 against 10 OP_CSV OP_DROP inputs
- bip112txs_vary_nSequence_v1 = create_bip112txs(self.nodes[0], bip112basicinputs[0], False, 1, self.nodeaddress)
- bip112txs_vary_nSequence_v2 = create_bip112txs(self.nodes[0], bip112basicinputs[0], False, 2, self.nodeaddress)
+ bip112txs_vary_nSequence_v1 = self.create_bip112txs(bip112basicinputs[0], False, 1)
+ bip112txs_vary_nSequence_v2 = self.create_bip112txs(bip112basicinputs[0], False, 2)
# 16 relative sequence locktimes of 9 against 10 OP_CSV OP_DROP inputs
- bip112txs_vary_nSequence_9_v1 = create_bip112txs(self.nodes[0], bip112basicinputs[1], False, 1, self.nodeaddress, -1)
- bip112txs_vary_nSequence_9_v2 = create_bip112txs(self.nodes[0], bip112basicinputs[1], False, 2, self.nodeaddress, -1)
+ bip112txs_vary_nSequence_9_v1 = self.create_bip112txs(bip112basicinputs[1], False, 1, -1)
+ bip112txs_vary_nSequence_9_v2 = self.create_bip112txs(bip112basicinputs[1], False, 2, -1)
# sequence lock time of 10 against 16 (relative_lock_time) OP_CSV OP_DROP inputs
- bip112txs_vary_OP_CSV_v1 = create_bip112txs(self.nodes[0], bip112diverseinputs[0], True, 1, self.nodeaddress)
- bip112txs_vary_OP_CSV_v2 = create_bip112txs(self.nodes[0], bip112diverseinputs[0], True, 2, self.nodeaddress)
+ bip112txs_vary_OP_CSV_v1 = self.create_bip112txs(bip112diverseinputs[0], True, 1)
+ bip112txs_vary_OP_CSV_v2 = self.create_bip112txs(bip112diverseinputs[0], True, 2)
# sequence lock time of 9 against 16 (relative_lock_time) OP_CSV OP_DROP inputs
- bip112txs_vary_OP_CSV_9_v1 = create_bip112txs(self.nodes[0], bip112diverseinputs[1], True, 1, self.nodeaddress, -1)
- bip112txs_vary_OP_CSV_9_v2 = create_bip112txs(self.nodes[0], bip112diverseinputs[1], True, 2, self.nodeaddress, -1)
+ bip112txs_vary_OP_CSV_9_v1 = self.create_bip112txs(bip112diverseinputs[1], True, 1, -1)
+ bip112txs_vary_OP_CSV_9_v2 = self.create_bip112txs(bip112diverseinputs[1], True, 2, -1)
# -1 OP_CSV OP_DROP input
- bip112tx_special_v1 = create_bip112special(self.nodes[0], bip112specialinput, 1, self.nodeaddress)
- bip112tx_special_v2 = create_bip112special(self.nodes[0], bip112specialinput, 2, self.nodeaddress)
+ bip112tx_special_v1 = self.create_bip112special(bip112specialinput, 1)
+ bip112tx_special_v2 = self.create_bip112special(bip112specialinput, 2)
# (empty stack) OP_CSV input
- bip112tx_emptystack_v1 = create_bip112emptystack(self.nodes[0], bip112emptystackinput, 1, self.nodeaddress)
- bip112tx_emptystack_v2 = create_bip112emptystack(self.nodes[0], bip112emptystackinput, 2, self.nodeaddress)
+ bip112tx_emptystack_v1 = self.create_bip112emptystack(bip112emptystackinput, 1)
+ bip112tx_emptystack_v2 = self.create_bip112emptystack(bip112emptystackinput, 2)
self.log.info("TESTING")
@@ -292,8 +291,8 @@ class BIP68_112_113Test(BitcoinTestFramework):
success_txs = []
# BIP113 tx, -1 CSV tx and empty stack CSV tx should succeed
bip113tx_v1.nLockTime = self.last_block_time - 600 * 5 # = MTP of prior block (not <) but < time put on current block
- bip113signed1 = sign_transaction(self.nodes[0], bip113tx_v1)
- success_txs.append(bip113signed1)
+ self.miniwallet.sign_tx(bip113tx_v1)
+ success_txs.append(bip113tx_v1)
success_txs.append(bip112tx_special_v1)
success_txs.append(bip112tx_emptystack_v1)
# add BIP 68 txs
@@ -312,8 +311,8 @@ class BIP68_112_113Test(BitcoinTestFramework):
success_txs = []
# BIP113 tx, -1 CSV tx and empty stack CSV tx should succeed
bip113tx_v2.nLockTime = self.last_block_time - 600 * 5 # = MTP of prior block (not <) but < time put on current block
- bip113signed2 = sign_transaction(self.nodes[0], bip113tx_v2)
- success_txs.append(bip113signed2)
+ self.miniwallet.sign_tx(bip113tx_v2)
+ success_txs.append(bip113tx_v2)
success_txs.append(bip112tx_special_v2)
success_txs.append(bip112tx_emptystack_v2)
# add BIP 68 txs
@@ -338,17 +337,22 @@ class BIP68_112_113Test(BitcoinTestFramework):
self.log.info("BIP 113 tests")
# BIP 113 tests should now fail regardless of version number if nLockTime isn't satisfied by new rules
bip113tx_v1.nLockTime = self.last_block_time - 600 * 5 # = MTP of prior block (not <) but < time put on current block
- bip113signed1 = sign_transaction(self.nodes[0], bip113tx_v1)
+ self.miniwallet.sign_tx(bip113tx_v1)
+ bip113tx_v1.rehash()
bip113tx_v2.nLockTime = self.last_block_time - 600 * 5 # = MTP of prior block (not <) but < time put on current block
- bip113signed2 = sign_transaction(self.nodes[0], bip113tx_v2)
- for bip113tx in [bip113signed1, bip113signed2]:
+ self.miniwallet.sign_tx(bip113tx_v2)
+ bip113tx_v2.rehash()
+ for bip113tx in [bip113tx_v1, bip113tx_v2]:
self.send_blocks([self.create_test_block([bip113tx])], success=False, reject_reason='bad-txns-nonfinal')
+
# BIP 113 tests should now pass if the locktime is < MTP
bip113tx_v1.nLockTime = self.last_block_time - 600 * 5 - 1 # < MTP of prior block
- bip113signed1 = sign_transaction(self.nodes[0], bip113tx_v1)
+ self.miniwallet.sign_tx(bip113tx_v1)
+ bip113tx_v1.rehash()
bip113tx_v2.nLockTime = self.last_block_time - 600 * 5 - 1 # < MTP of prior block
- bip113signed2 = sign_transaction(self.nodes[0], bip113tx_v2)
- for bip113tx in [bip113signed1, bip113signed2]:
+ self.miniwallet.sign_tx(bip113tx_v2)
+ bip113tx_v2.rehash()
+ for bip113tx in [bip113tx_v1, bip113tx_v2]:
self.send_blocks([self.create_test_block([bip113tx])])
self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
@@ -471,8 +475,9 @@ class BIP68_112_113Test(BitcoinTestFramework):
time_txs = []
for tx in [tx['tx'] for tx in bip112txs_vary_OP_CSV_v2 if not tx['sdf'] and tx['stf']]:
tx.vin[0].nSequence = BASE_RELATIVE_LOCKTIME | SEQ_TYPE_FLAG
- signtx = sign_transaction(self.nodes[0], tx)
- time_txs.append(signtx)
+ self.miniwallet.sign_tx(tx)
+ tx.rehash()
+ time_txs.append(tx)
self.send_blocks([self.create_test_block(time_txs)])
self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
diff --git a/test/functional/feature_dersig.py b/test/functional/feature_dersig.py
index 3b430139b1..eb027c554a 100755
--- a/test/functional/feature_dersig.py
+++ b/test/functional/feature_dersig.py
@@ -7,7 +7,10 @@
Test that the DERSIG soft-fork activates at (regtest) height 1251.
"""
-from test_framework.blocktools import create_coinbase, create_block, create_transaction
+from test_framework.blocktools import (
+ create_block,
+ create_coinbase,
+)
from test_framework.messages import msg_block
from test_framework.p2p import P2PInterface
from test_framework.script import CScript
@@ -15,6 +18,10 @@ from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
assert_equal,
)
+from test_framework.wallet import (
+ MiniWallet,
+ MiniWalletMode,
+)
DERSIG_HEIGHT = 1251
@@ -46,8 +53,9 @@ class BIP66Test(BitcoinTestFramework):
self.setup_clean_chain = True
self.rpc_timeout = 240
- def skip_test_if_missing_module(self):
- self.skip_if_no_wallet()
+ def create_tx(self, input_txid):
+ utxo_to_spend = self.miniwallet.get_utxo(txid=input_txid, mark_as_spent=False)
+ return self.miniwallet.create_self_transfer(from_node=self.nodes[0], utxo_to_spend=utxo_to_spend)['tx']
def test_dersig_info(self, *, is_active):
assert_equal(self.nodes[0].getblockchaininfo()['softforks']['bip66'],
@@ -60,17 +68,16 @@ class BIP66Test(BitcoinTestFramework):
def run_test(self):
peer = self.nodes[0].add_p2p_connection(P2PInterface())
+ self.miniwallet = MiniWallet(self.nodes[0], mode=MiniWalletMode.RAW_P2PK)
self.test_dersig_info(is_active=False)
self.log.info("Mining %d blocks", DERSIG_HEIGHT - 2)
- self.coinbase_txids = [self.nodes[0].getblock(b)['tx'][0] for b in self.nodes[0].generate(DERSIG_HEIGHT - 2)]
- self.nodeaddress = self.nodes[0].getnewaddress()
+ self.coinbase_txids = [self.nodes[0].getblock(b)['tx'][0] for b in self.miniwallet.generate(DERSIG_HEIGHT - 2)]
self.log.info("Test that a transaction with non-DER signature can still appear in a block")
- spendtx = create_transaction(self.nodes[0], self.coinbase_txids[0],
- self.nodeaddress, amount=1.0)
+ spendtx = self.create_tx(self.coinbase_txids[0])
unDERify(spendtx)
spendtx.rehash()
@@ -104,8 +111,7 @@ class BIP66Test(BitcoinTestFramework):
self.log.info("Test that transactions with non-DER signatures cannot appear in a block")
block.nVersion = 3
- spendtx = create_transaction(self.nodes[0], self.coinbase_txids[1],
- self.nodeaddress, amount=1.0)
+ spendtx = self.create_tx(self.coinbase_txids[1])
unDERify(spendtx)
spendtx.rehash()
@@ -133,7 +139,7 @@ class BIP66Test(BitcoinTestFramework):
peer.sync_with_ping()
self.log.info("Test that a version 3 block with a DERSIG-compliant transaction is accepted")
- block.vtx[1] = create_transaction(self.nodes[0], self.coinbase_txids[1], self.nodeaddress, amount=1.0)
+ block.vtx[1] = self.create_tx(self.coinbase_txids[1])
block.hashMerkleRoot = block.calc_merkle_root()
block.rehash()
block.solve()
diff --git a/test/functional/feature_includeconf.py b/test/functional/feature_includeconf.py
index f22b7f266a..448182eded 100755
--- a/test/functional/feature_includeconf.py
+++ b/test/functional/feature_includeconf.py
@@ -42,7 +42,14 @@ class IncludeConfTest(BitcoinTestFramework):
self.log.info("-includeconf cannot be used as command-line arg")
self.stop_node(0)
- self.nodes[0].assert_start_raises_init_error(extra_args=["-includeconf=relative2.conf"], expected_msg="Error: Error parsing command line arguments: -includeconf cannot be used from commandline; -includeconf=relative2.conf")
+ self.nodes[0].assert_start_raises_init_error(
+ extra_args=['-noincludeconf=0'],
+ expected_msg='Error: Error parsing command line arguments: -includeconf cannot be used from commandline; -includeconf=true',
+ )
+ self.nodes[0].assert_start_raises_init_error(
+ extra_args=['-includeconf=relative2.conf', '-includeconf=no_warn.conf'],
+ expected_msg='Error: Error parsing command line arguments: -includeconf cannot be used from commandline; -includeconf="relative2.conf"',
+ )
self.log.info("-includeconf cannot be used recursively. subversion should end with 'main; relative)/'")
with open(os.path.join(self.options.tmpdir, "node0", "relative.conf"), "a", encoding="utf8") as f:
diff --git a/test/functional/feature_loadblock.py b/test/functional/feature_loadblock.py
index 0a457ca17f..14f64d63a2 100755
--- a/test/functional/feature_loadblock.py
+++ b/test/functional/feature_loadblock.py
@@ -16,6 +16,7 @@ import sys
import tempfile
import urllib
+from test_framework.blocktools import COINBASE_MATURITY
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import assert_equal
@@ -28,7 +29,7 @@ class LoadblockTest(BitcoinTestFramework):
def run_test(self):
self.nodes[1].setnetworkactive(state=False)
- self.nodes[0].generate(100)
+ self.nodes[0].generate(COINBASE_MATURITY)
# Parsing the url of our node to get settings for config file
data_dir = self.nodes[0].datadir
diff --git a/test/functional/feature_nulldummy.py b/test/functional/feature_nulldummy.py
index c7981d31dc..02e387c7ee 100755
--- a/test/functional/feature_nulldummy.py
+++ b/test/functional/feature_nulldummy.py
@@ -14,13 +14,18 @@ Generate COINBASE_MATURITY (CB) more blocks to ensure the coinbases are mature.
"""
import time
-from test_framework.blocktools import NORMAL_GBT_REQUEST_PARAMS, create_block, create_transaction, add_witness_commitment
+from test_framework.blocktools import (
+ COINBASE_MATURITY,
+ NORMAL_GBT_REQUEST_PARAMS,
+ add_witness_commitment,
+ create_block,
+ create_transaction,
+)
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
-COINBASE_MATURITY = 100
NULLDUMMY_ERROR = "non-mandatory-script-verify-flag (Dummy CHECKMULTISIG argument must be zero)"
def trueDummy(tx):
diff --git a/test/functional/feature_rbf.py b/test/functional/feature_rbf.py
index 945880cc3b..344db5f652 100755
--- a/test/functional/feature_rbf.py
+++ b/test/functional/feature_rbf.py
@@ -6,6 +6,7 @@
from decimal import Decimal
+from test_framework.blocktools import COINBASE_MATURITY
from test_framework.messages import COIN, COutPoint, CTransaction, CTxIn, CTxOut
from test_framework.script import CScript, OP_DROP
from test_framework.test_framework import BitcoinTestFramework
@@ -27,7 +28,7 @@ def make_utxo(node, amount, confirmed=True, scriptPubKey=DUMMY_P2WPKH_SCRIPT):
"""
fee = 1*COIN
while node.getbalance() < satoshi_round((amount + fee)/COIN):
- node.generate(100)
+ node.generate(COINBASE_MATURITY)
new_addr = node.getnewaddress()
txid = node.sendtoaddress(new_addr, satoshi_round((amount+fee)/COIN))
diff --git a/test/functional/feature_taproot.py b/test/functional/feature_taproot.py
index 183a43abd4..fc04853199 100755
--- a/test/functional/feature_taproot.py
+++ b/test/functional/feature_taproot.py
@@ -5,6 +5,7 @@
# Test Taproot softfork (BIPs 340-342)
from test_framework.blocktools import (
+ COINBASE_MATURITY,
create_coinbase,
create_block,
add_witness_commitment,
@@ -1440,7 +1441,7 @@ class TaprootTest(BitcoinTestFramework):
def run_test(self):
# Post-taproot activation tests go first (pre-taproot tests' blocks are invalid post-taproot).
self.log.info("Post-activation tests...")
- self.nodes[1].generate(101)
+ self.nodes[1].generate(COINBASE_MATURITY + 1)
self.test_spenders(self.nodes[1], spenders_taproot_active(), input_counts=[1, 2, 2, 2, 2, 3])
# Re-connect nodes in case they have been disconnected
diff --git a/test/functional/interface_bitcoin_cli.py b/test/functional/interface_bitcoin_cli.py
index b5ce18a48b..30cd499b3f 100755
--- a/test/functional/interface_bitcoin_cli.py
+++ b/test/functional/interface_bitcoin_cli.py
@@ -5,6 +5,8 @@
"""Test bitcoin-cli"""
from decimal import Decimal
+
+from test_framework.blocktools import COINBASE_MATURITY
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
assert_equal,
@@ -16,7 +18,7 @@ from test_framework.util import (
# The block reward of coinbaseoutput.nValue (50) BTC/block matures after
# COINBASE_MATURITY (100) blocks. Therefore, after mining 101 blocks we expect
# node 0 to have a balance of (BLOCKS - COINBASE_MATURITY) * 50 BTC/block.
-BLOCKS = 101
+BLOCKS = COINBASE_MATURITY + 1
BALANCE = (BLOCKS - 100) * 50
JSON_PARSING_ERROR = 'error: Error parsing JSON: foo'
diff --git a/test/functional/mempool_accept.py b/test/functional/mempool_accept.py
index c4002f524a..12aac3ab65 100755
--- a/test/functional/mempool_accept.py
+++ b/test/functional/mempool_accept.py
@@ -67,7 +67,8 @@ class MempoolAcceptanceTest(BitcoinTestFramework):
self.log.info('Should not accept garbage to testmempoolaccept')
assert_raises_rpc_error(-3, 'Expected type array, got string', lambda: node.testmempoolaccept(rawtxs='ff00baar'))
- assert_raises_rpc_error(-8, 'Array must contain exactly one raw transaction for now', lambda: node.testmempoolaccept(rawtxs=['ff00baar', 'ff22']))
+ assert_raises_rpc_error(-8, 'Array must contain between 1 and 25 transactions.', lambda: node.testmempoolaccept(rawtxs=['ff22']*26))
+ assert_raises_rpc_error(-8, 'Array must contain between 1 and 25 transactions.', lambda: node.testmempoolaccept(rawtxs=[]))
assert_raises_rpc_error(-22, 'TX decode failed', lambda: node.testmempoolaccept(rawtxs=['ff00baar']))
self.log.info('A transaction already in the blockchain')
diff --git a/test/functional/mempool_compatibility.py b/test/functional/mempool_compatibility.py
index eb08765ebf..6de6778909 100755
--- a/test/functional/mempool_compatibility.py
+++ b/test/functional/mempool_compatibility.py
@@ -15,6 +15,7 @@ Only v0.15.2 is required by this test. The rest is used in other backwards compa
import os
+from test_framework.blocktools import COINBASE_MATURITY
from test_framework.test_framework import BitcoinTestFramework
from test_framework.wallet import MiniWallet
@@ -41,7 +42,7 @@ class MempoolCompatibilityTest(BitcoinTestFramework):
old_node, new_node = self.nodes
new_wallet = MiniWallet(new_node)
new_wallet.generate(1)
- new_node.generate(100)
+ new_node.generate(COINBASE_MATURITY)
# Sync the nodes to ensure old_node has the block that contains the coinbase that new_wallet will spend.
# Otherwise, because coinbases are only valid in a block and not as loose txns, if the nodes aren't synced
# unbroadcasted_tx won't pass old_node's `MemPoolAccept::PreChecks`.
diff --git a/test/functional/mempool_expiry.py b/test/functional/mempool_expiry.py
index 4c46075ae9..7d1bfef333 100755
--- a/test/functional/mempool_expiry.py
+++ b/test/functional/mempool_expiry.py
@@ -12,6 +12,7 @@ definable expiry timeout via the '-mempoolexpiry=<n>' command line argument
from datetime import timedelta
+from test_framework.blocktools import COINBASE_MATURITY
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
assert_equal,
@@ -36,7 +37,7 @@ class MempoolExpiryTest(BitcoinTestFramework):
# Add enough mature utxos to the wallet so that all txs spend confirmed coins.
self.wallet.generate(4)
- node.generate(100)
+ node.generate(COINBASE_MATURITY)
# Send a parent transaction that will expire.
parent_txid = self.wallet.send_self_transfer(from_node=node)['txid']
diff --git a/test/functional/mempool_package_onemore.py b/test/functional/mempool_package_onemore.py
index 884a2fef11..1e9895e621 100755
--- a/test/functional/mempool_package_onemore.py
+++ b/test/functional/mempool_package_onemore.py
@@ -9,6 +9,7 @@
from decimal import Decimal
+from test_framework.blocktools import COINBASE_MATURITY
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import assert_equal, assert_raises_rpc_error, satoshi_round
@@ -42,7 +43,7 @@ class MempoolPackagesTest(BitcoinTestFramework):
def run_test(self):
# Mine some blocks and have them mature.
- self.nodes[0].generate(101)
+ self.nodes[0].generate(COINBASE_MATURITY + 1)
utxo = self.nodes[0].listunspent(10)
txid = utxo[0]['txid']
vout = utxo[0]['vout']
diff --git a/test/functional/mempool_packages.py b/test/functional/mempool_packages.py
index 461f9237ff..606717d890 100755
--- a/test/functional/mempool_packages.py
+++ b/test/functional/mempool_packages.py
@@ -6,6 +6,7 @@
from decimal import Decimal
+from test_framework.blocktools import COINBASE_MATURITY
from test_framework.messages import COIN
from test_framework.p2p import P2PTxInvStore
from test_framework.test_framework import BitcoinTestFramework
@@ -59,7 +60,7 @@ class MempoolPackagesTest(BitcoinTestFramework):
def run_test(self):
# Mine some blocks and have them mature.
peer_inv_store = self.nodes[0].add_p2p_connection(P2PTxInvStore()) # keep track of invs
- self.nodes[0].generate(101)
+ self.nodes[0].generate(COINBASE_MATURITY + 1)
utxo = self.nodes[0].listunspent(10)
txid = utxo[0]['txid']
vout = utxo[0]['vout']
diff --git a/test/functional/mempool_reorg.py b/test/functional/mempool_reorg.py
index 8e1f87e42c..bcc6aa7bcc 100755
--- a/test/functional/mempool_reorg.py
+++ b/test/functional/mempool_reorg.py
@@ -8,10 +8,9 @@ Test re-org scenarios with a mempool that contains transactions
that spend (directly or indirectly) coinbase transactions.
"""
-from test_framework.blocktools import create_raw_transaction
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import assert_equal, assert_raises_rpc_error
-
+from test_framework.wallet import MiniWallet
class MempoolCoinbaseTest(BitcoinTestFramework):
def set_test_params(self):
@@ -23,86 +22,90 @@ class MempoolCoinbaseTest(BitcoinTestFramework):
[]
]
- def skip_test_if_missing_module(self):
- self.skip_if_no_wallet()
-
def run_test(self):
+ wallet = MiniWallet(self.nodes[0])
+
# Start with a 200 block chain
assert_equal(self.nodes[0].getblockcount(), 200)
- # Mine four blocks. After this, nodes[0] blocks
- # 101, 102, and 103 are spend-able.
- new_blocks = self.nodes[1].generate(4)
- self.sync_all()
-
- node0_address = self.nodes[0].getnewaddress()
- node1_address = self.nodes[1].getnewaddress()
+ self.log.info("Add 4 coinbase utxos to the miniwallet")
+ # Block 76 contains the first spendable coinbase txs.
+ first_block = 76
+ wallet.scan_blocks(start=first_block, num=4)
# Three scenarios for re-orging coinbase spends in the memory pool:
- # 1. Direct coinbase spend : spend_101
- # 2. Indirect (coinbase spend in chain, child in mempool) : spend_102 and spend_102_1
- # 3. Indirect (coinbase and child both in chain) : spend_103 and spend_103_1
- # Use invalidatblock to make all of the above coinbase spends invalid (immature coinbase),
+ # 1. Direct coinbase spend : spend_1
+ # 2. Indirect (coinbase spend in chain, child in mempool) : spend_2 and spend_2_1
+ # 3. Indirect (coinbase and child both in chain) : spend_3 and spend_3_1
+ # Use invalidateblock to make all of the above coinbase spends invalid (immature coinbase),
# and make sure the mempool code behaves correctly.
- b = [self.nodes[0].getblockhash(n) for n in range(101, 105)]
+ b = [self.nodes[0].getblockhash(n) for n in range(first_block, first_block+4)]
coinbase_txids = [self.nodes[0].getblock(h)['tx'][0] for h in b]
- spend_101_raw = create_raw_transaction(self.nodes[0], coinbase_txids[1], node1_address, amount=49.99)
- spend_102_raw = create_raw_transaction(self.nodes[0], coinbase_txids[2], node0_address, amount=49.99)
- spend_103_raw = create_raw_transaction(self.nodes[0], coinbase_txids[3], node0_address, amount=49.99)
-
- # Create a transaction which is time-locked to two blocks in the future
- timelock_tx = self.nodes[0].createrawtransaction(
- inputs=[{
- "txid": coinbase_txids[0],
- "vout": 0,
- }],
- outputs={node0_address: 49.99},
- locktime=self.nodes[0].getblockcount() + 2,
- )
- timelock_tx = self.nodes[0].signrawtransactionwithwallet(timelock_tx)["hex"]
- # This will raise an exception because the timelock transaction is too immature to spend
+ utxo_1 = wallet.get_utxo(txid=coinbase_txids[1])
+ utxo_2 = wallet.get_utxo(txid=coinbase_txids[2])
+ utxo_3 = wallet.get_utxo(txid=coinbase_txids[3])
+ self.log.info("Create three transactions spending from coinbase utxos: spend_1, spend_2, spend_3")
+ spend_1 = wallet.create_self_transfer(from_node=self.nodes[0], utxo_to_spend=utxo_1)
+ spend_2 = wallet.create_self_transfer(from_node=self.nodes[0], utxo_to_spend=utxo_2)
+ spend_3 = wallet.create_self_transfer(from_node=self.nodes[0], utxo_to_spend=utxo_3)
+
+ self.log.info("Create another transaction which is time-locked to two blocks in the future")
+ utxo = wallet.get_utxo(txid=coinbase_txids[0])
+ timelock_tx = wallet.create_self_transfer(
+ from_node=self.nodes[0],
+ utxo_to_spend=utxo,
+ mempool_valid=False,
+ locktime=self.nodes[0].getblockcount() + 2
+ )['hex']
+
+ self.log.info("Check that the time-locked transaction is too immature to spend")
assert_raises_rpc_error(-26, "non-final", self.nodes[0].sendrawtransaction, timelock_tx)
- # Broadcast and mine spend_102 and 103:
- spend_102_id = self.nodes[0].sendrawtransaction(spend_102_raw)
- spend_103_id = self.nodes[0].sendrawtransaction(spend_103_raw)
+ self.log.info("Broadcast and mine spend_2 and spend_3")
+ wallet.sendrawtransaction(from_node=self.nodes[0], tx_hex=spend_2['hex'])
+ wallet.sendrawtransaction(from_node=self.nodes[0], tx_hex=spend_3['hex'])
+ self.log.info("Generate a block")
self.nodes[0].generate(1)
- # Time-locked transaction is still too immature to spend
+ self.log.info("Check that time-locked transaction is still too immature to spend")
assert_raises_rpc_error(-26, 'non-final', self.nodes[0].sendrawtransaction, timelock_tx)
- # Create 102_1 and 103_1:
- spend_102_1_raw = create_raw_transaction(self.nodes[0], spend_102_id, node1_address, amount=49.98)
- spend_103_1_raw = create_raw_transaction(self.nodes[0], spend_103_id, node1_address, amount=49.98)
+ self.log.info("Create spend_2_1 and spend_3_1")
+ spend_2_utxo = wallet.get_utxo(txid=spend_2['txid'])
+ spend_2_1 = wallet.create_self_transfer(from_node=self.nodes[0], utxo_to_spend=spend_2_utxo)
+ spend_3_utxo = wallet.get_utxo(txid=spend_3['txid'])
+ spend_3_1 = wallet.create_self_transfer(from_node=self.nodes[0], utxo_to_spend=spend_3_utxo)
- # Broadcast and mine 103_1:
- spend_103_1_id = self.nodes[0].sendrawtransaction(spend_103_1_raw)
+ self.log.info("Broadcast and mine spend_3_1")
+ spend_3_1_id = self.nodes[0].sendrawtransaction(spend_3_1['hex'])
+ self.log.info("Generate a block")
last_block = self.nodes[0].generate(1)
# Sync blocks, so that peer 1 gets the block before timelock_tx
# Otherwise, peer 1 would put the timelock_tx in recentRejects
self.sync_all()
- # Time-locked transaction can now be spent
+ self.log.info("The time-locked transaction can now be spent")
timelock_tx_id = self.nodes[0].sendrawtransaction(timelock_tx)
- # ... now put spend_101 and spend_102_1 in memory pools:
- spend_101_id = self.nodes[0].sendrawtransaction(spend_101_raw)
- spend_102_1_id = self.nodes[0].sendrawtransaction(spend_102_1_raw)
+ self.log.info("Add spend_1 and spend_2_1 to the mempool")
+ spend_1_id = self.nodes[0].sendrawtransaction(spend_1['hex'])
+ spend_2_1_id = self.nodes[0].sendrawtransaction(spend_2_1['hex'])
- assert_equal(set(self.nodes[0].getrawmempool()), {spend_101_id, spend_102_1_id, timelock_tx_id})
+ assert_equal(set(self.nodes[0].getrawmempool()), {spend_1_id, spend_2_1_id, timelock_tx_id})
self.sync_all()
+ self.log.info("invalidate the last block")
for node in self.nodes:
node.invalidateblock(last_block[0])
- # Time-locked transaction is now too immature and has been removed from the mempool
- # spend_103_1 has been re-orged out of the chain and is back in the mempool
- assert_equal(set(self.nodes[0].getrawmempool()), {spend_101_id, spend_102_1_id, spend_103_1_id})
+ self.log.info("The time-locked transaction is now too immature and has been removed from the mempool")
+ self.log.info("spend_3_1 has been re-orged out of the chain and is back in the mempool")
+ assert_equal(set(self.nodes[0].getrawmempool()), {spend_1_id, spend_2_1_id, spend_3_1_id})
- # Use invalidateblock to re-org back and make all those coinbase spends
- # immature/invalid:
+ self.log.info("Use invalidateblock to re-org back and make all those coinbase spends immature/invalid")
+ b = self.nodes[0].getblockhash(first_block + 100)
for node in self.nodes:
- node.invalidateblock(new_blocks[0])
+ node.invalidateblock(b)
- # mempool should be empty.
+ self.log.info("Check that the mempool is empty")
assert_equal(set(self.nodes[0].getrawmempool()), set())
self.sync_all()
diff --git a/test/functional/mempool_resurrect.py b/test/functional/mempool_resurrect.py
index 4aa58270b6..1b5ca7e15a 100755
--- a/test/functional/mempool_resurrect.py
+++ b/test/functional/mempool_resurrect.py
@@ -4,6 +4,7 @@
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Test resurrection of mined transactions when the blockchain is re-organized."""
+from test_framework.blocktools import COINBASE_MATURITY
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import assert_equal
from test_framework.wallet import MiniWallet
@@ -20,7 +21,7 @@ class MempoolCoinbaseTest(BitcoinTestFramework):
# Add enough mature utxos to the wallet so that all txs spend confirmed coins
wallet.generate(3)
- node.generate(100)
+ node.generate(COINBASE_MATURITY)
# Spend block 1/2/3's coinbase transactions
# Mine a block
diff --git a/test/functional/mining_getblocktemplate_longpoll.py b/test/functional/mining_getblocktemplate_longpoll.py
index cc32f78e2e..715b68e04c 100755
--- a/test/functional/mining_getblocktemplate_longpoll.py
+++ b/test/functional/mining_getblocktemplate_longpoll.py
@@ -8,6 +8,7 @@ from decimal import Decimal
import random
import threading
+from test_framework.blocktools import COINBASE_MATURITY
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import get_rpc_proxy
from test_framework.wallet import MiniWallet
@@ -62,7 +63,7 @@ class GetBlockTemplateLPTest(BitcoinTestFramework):
assert not thr.is_alive()
# Add enough mature utxos to the wallets, so that all txs spend confirmed coins
- self.nodes[0].generate(100)
+ self.nodes[0].generate(COINBASE_MATURITY)
self.sync_blocks()
self.log.info("Test that introducing a new transaction into the mempool will terminate the longpoll")
diff --git a/test/functional/p2p_blocksonly.py b/test/functional/p2p_blocksonly.py
index ab2556cd72..6409d4ea82 100755
--- a/test/functional/p2p_blocksonly.py
+++ b/test/functional/p2p_blocksonly.py
@@ -6,6 +6,7 @@
import time
+from test_framework.blocktools import COINBASE_MATURITY
from test_framework.messages import msg_tx
from test_framework.p2p import P2PInterface, P2PTxInvStore
from test_framework.test_framework import BitcoinTestFramework
@@ -23,7 +24,7 @@ class P2PBlocksOnly(BitcoinTestFramework):
self.miniwallet = MiniWallet(self.nodes[0])
# Add enough mature utxos to the wallet, so that all txs spend confirmed coins
self.miniwallet.generate(2)
- self.nodes[0].generate(100)
+ self.nodes[0].generate(COINBASE_MATURITY)
self.blocksonly_mode_tests()
self.blocks_relay_conn_tests()
diff --git a/test/functional/p2p_compactblocks.py b/test/functional/p2p_compactblocks.py
index 55573efc06..3e4f2f974d 100755
--- a/test/functional/p2p_compactblocks.py
+++ b/test/functional/p2p_compactblocks.py
@@ -9,7 +9,12 @@ Version 2 compact blocks are post-segwit (wtxids)
"""
import random
-from test_framework.blocktools import create_block, NORMAL_GBT_REQUEST_PARAMS, add_witness_commitment
+from test_framework.blocktools import (
+ COINBASE_MATURITY,
+ NORMAL_GBT_REQUEST_PARAMS,
+ add_witness_commitment,
+ create_block,
+)
from test_framework.messages import BlockTransactions, BlockTransactionsRequest, calculate_shortid, CBlock, CBlockHeader, CInv, COutPoint, CTransaction, CTxIn, CTxInWitness, CTxOut, FromHex, HeaderAndShortIDs, msg_no_witness_block, msg_no_witness_blocktxn, msg_cmpctblock, msg_getblocktxn, msg_getdata, msg_getheaders, msg_headers, msg_inv, msg_sendcmpct, msg_sendheaders, msg_tx, msg_block, msg_blocktxn, MSG_BLOCK, MSG_CMPCT_BLOCK, MSG_WITNESS_FLAG, NODE_NETWORK, P2PHeaderAndShortIDs, PrefilledTransaction, ser_uint256, ToHex
from test_framework.p2p import p2p_lock, P2PInterface
from test_framework.script import CScript, OP_TRUE, OP_DROP
@@ -115,7 +120,7 @@ class CompactBlocksTest(BitcoinTestFramework):
block = self.build_block_on_tip(self.nodes[0])
self.segwit_node.send_and_ping(msg_no_witness_block(block))
assert int(self.nodes[0].getbestblockhash(), 16) == block.sha256
- self.nodes[0].generatetoaddress(100, self.nodes[0].getnewaddress(address_type="bech32"))
+ self.nodes[0].generatetoaddress(COINBASE_MATURITY, self.nodes[0].getnewaddress(address_type="bech32"))
total_value = block.vtx[0].vout[0].nValue
out_value = total_value // 10
@@ -226,7 +231,7 @@ class CompactBlocksTest(BitcoinTestFramework):
# This test actually causes bitcoind to (reasonably!) disconnect us, so do this last.
def test_invalid_cmpctblock_message(self):
- self.nodes[0].generate(101)
+ self.nodes[0].generate(COINBASE_MATURITY + 1)
block = self.build_block_on_tip(self.nodes[0])
cmpct_block = P2PHeaderAndShortIDs()
@@ -244,7 +249,7 @@ class CompactBlocksTest(BitcoinTestFramework):
version = test_node.cmpct_version
node = self.nodes[0]
# Generate a bunch of transactions.
- node.generate(101)
+ node.generate(COINBASE_MATURITY + 1)
num_transactions = 25
address = node.getnewaddress()
diff --git a/test/functional/p2p_eviction.py b/test/functional/p2p_eviction.py
index d60aa5b383..a525996493 100755
--- a/test/functional/p2p_eviction.py
+++ b/test/functional/p2p_eviction.py
@@ -15,7 +15,11 @@ Therefore, this test is limited to the remaining protection criteria.
import time
-from test_framework.blocktools import create_block, create_coinbase
+from test_framework.blocktools import (
+ COINBASE_MATURITY,
+ create_block,
+ create_coinbase,
+)
from test_framework.messages import CTransaction, FromHex, msg_pong, msg_tx
from test_framework.p2p import P2PDataStore, P2PInterface
from test_framework.test_framework import BitcoinTestFramework
@@ -45,7 +49,7 @@ class P2PEvict(BitcoinTestFramework):
protected_peers = set() # peers that we expect to be protected from eviction
current_peer = -1
node = self.nodes[0]
- node.generatetoaddress(101, node.get_deterministic_priv_key().address)
+ node.generatetoaddress(COINBASE_MATURITY + 1, node.get_deterministic_priv_key().address)
self.log.info("Create 4 peers and protect them from eviction by sending us a block")
for _ in range(4):
diff --git a/test/functional/p2p_feefilter.py b/test/functional/p2p_feefilter.py
index 52dc4de3bd..0175b9f6c0 100755
--- a/test/functional/p2p_feefilter.py
+++ b/test/functional/p2p_feefilter.py
@@ -6,6 +6,7 @@
from decimal import Decimal
+from test_framework.blocktools import COINBASE_MATURITY
from test_framework.messages import MSG_TX, MSG_WTX, msg_feefilter
from test_framework.p2p import P2PInterface, p2p_lock
from test_framework.test_framework import BitcoinTestFramework
@@ -81,7 +82,7 @@ class FeeFilterTest(BitcoinTestFramework):
miniwallet = MiniWallet(node1)
# Add enough mature utxos to the wallet, so that all txs spend confirmed coins
miniwallet.generate(5)
- node1.generate(100)
+ node1.generate(COINBASE_MATURITY)
conn = self.nodes[0].add_p2p_connection(TestP2PConn())
diff --git a/test/functional/p2p_leak_tx.py b/test/functional/p2p_leak_tx.py
index a45f792e81..9a4ceb86ae 100755
--- a/test/functional/p2p_leak_tx.py
+++ b/test/functional/p2p_leak_tx.py
@@ -4,6 +4,7 @@
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Test that we don't leak txs to inbound peers that we haven't yet announced to"""
+from test_framework.blocktools import COINBASE_MATURITY
from test_framework.messages import msg_getdata, CInv, MSG_TX
from test_framework.p2p import p2p_lock, P2PDataStore
from test_framework.test_framework import BitcoinTestFramework
@@ -27,7 +28,7 @@ class P2PLeakTxTest(BitcoinTestFramework):
miniwallet = MiniWallet(gen_node)
# Add enough mature utxos to the wallet, so that all txs spend confirmed coins
miniwallet.generate(1)
- gen_node.generate(100)
+ gen_node.generate(COINBASE_MATURITY)
inbound_peer = self.nodes[0].add_p2p_connection(P2PNode()) # An "attacking" inbound peer
diff --git a/test/functional/rpc_createmultisig.py b/test/functional/rpc_createmultisig.py
index 19f0d5765a..af515f3a27 100755
--- a/test/functional/rpc_createmultisig.py
+++ b/test/functional/rpc_createmultisig.py
@@ -9,6 +9,7 @@ import itertools
import json
import os
+from test_framework.blocktools import COINBASE_MATURITY
from test_framework.authproxy import JSONRPCException
from test_framework.descriptors import descsum_create, drop_origins
from test_framework.key import ECPubKey, ECKey
@@ -109,7 +110,7 @@ class RpcCreateMultiSigTest(BitcoinTestFramework):
def checkbalances(self):
node0, node1, node2 = self.nodes
- node0.generate(100)
+ node0.generate(COINBASE_MATURITY)
self.sync_all()
bal0 = node0.getbalance()
diff --git a/test/functional/rpc_dumptxoutset.py b/test/functional/rpc_dumptxoutset.py
index dc469ba552..3efbdab013 100755
--- a/test/functional/rpc_dumptxoutset.py
+++ b/test/functional/rpc_dumptxoutset.py
@@ -4,6 +4,8 @@
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Test the generation of UTXO snapshots using `dumptxoutset`.
"""
+
+from test_framework.blocktools import COINBASE_MATURITY
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import assert_equal, assert_raises_rpc_error
@@ -21,7 +23,7 @@ class DumptxoutsetTest(BitcoinTestFramework):
node = self.nodes[0]
mocktime = node.getblockheader(node.getblockhash(0))['time'] + 1
node.setmocktime(mocktime)
- node.generate(100)
+ node.generate(COINBASE_MATURITY)
FILENAME = 'txoutset.dat'
out = node.dumptxoutset(FILENAME)
diff --git a/test/functional/rpc_getblockstats.py b/test/functional/rpc_getblockstats.py
index 57794ae973..4af518c870 100755
--- a/test/functional/rpc_getblockstats.py
+++ b/test/functional/rpc_getblockstats.py
@@ -6,6 +6,8 @@
#
# Test getblockstats rpc call
#
+
+from test_framework.blocktools import COINBASE_MATURITY
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
assert_equal,
@@ -41,7 +43,7 @@ class GetblockstatsTest(BitcoinTestFramework):
def generate_test_data(self, filename):
mocktime = 1525107225
self.nodes[0].setmocktime(mocktime)
- self.nodes[0].generate(101)
+ self.nodes[0].generate(COINBASE_MATURITY + 1)
address = self.nodes[0].get_deterministic_priv_key().address
self.nodes[0].sendtoaddress(address=address, amount=10, subtractfeefromamount=True)
diff --git a/test/functional/rpc_net.py b/test/functional/rpc_net.py
index 16d7958712..6e5ef770d1 100755
--- a/test/functional/rpc_net.py
+++ b/test/functional/rpc_net.py
@@ -11,6 +11,7 @@ from decimal import Decimal
from itertools import product
import time
+from test_framework.blocktools import COINBASE_MATURITY
from test_framework.p2p import P2PInterface
import test_framework.messages
from test_framework.messages import (
@@ -53,7 +54,7 @@ class NetTest(BitcoinTestFramework):
self.wallet = MiniWallet(self.nodes[0])
self.wallet.generate(1)
# Get out of IBD for the minfeefilter and getpeerinfo tests.
- self.nodes[0].generate(101)
+ self.nodes[0].generate(COINBASE_MATURITY + 1)
# By default, the test framework sets up an addnode connection from
# node 1 --> node0. By connecting node0 --> node 1, we're left with
@@ -69,6 +70,7 @@ class NetTest(BitcoinTestFramework):
self.test_getaddednodeinfo()
self.test_service_flags()
self.test_getnodeaddresses()
+ self.test_addpeeraddress()
def test_connection_count(self):
self.log.info("Test getconnectioncount")
@@ -187,43 +189,78 @@ class NetTest(BitcoinTestFramework):
def test_getnodeaddresses(self):
self.log.info("Test getnodeaddresses")
self.nodes[0].add_p2p_connection(P2PInterface())
+ services = NODE_NETWORK | NODE_WITNESS
- # Add some addresses to the Address Manager over RPC. Due to the way
- # bucket and bucket position are calculated, some of these addresses
- # will collide.
+ # Add an IPv6 address to the address manager.
+ ipv6_addr = "1233:3432:2434:2343:3234:2345:6546:4534"
+ self.nodes[0].addpeeraddress(address=ipv6_addr, port=8333)
+
+ # Add 10,000 IPv4 addresses to the address manager. Due to the way bucket
+ # and bucket positions are calculated, some of these addresses will collide.
imported_addrs = []
for i in range(10000):
first_octet = i >> 8
second_octet = i % 256
- a = "{}.{}.1.1".format(first_octet, second_octet) # IPV4
+ a = f"{first_octet}.{second_octet}.1.1"
imported_addrs.append(a)
self.nodes[0].addpeeraddress(a, 8333)
- # Obtain addresses via rpc call and check they were ones sent in before.
- #
- # Maximum possible addresses in addrman is 10000, although actual
- # number will usually be less due to bucket and bucket position
- # collisions.
- node_addresses = self.nodes[0].getnodeaddresses(0)
+ # Fetch the addresses via the RPC and test the results.
+ assert_equal(len(self.nodes[0].getnodeaddresses()), 1) # default count is 1
+ assert_equal(len(self.nodes[0].getnodeaddresses(count=2)), 2)
+ assert_equal(len(self.nodes[0].getnodeaddresses(network="ipv4", count=8)), 8)
+
+ # Maximum possible addresses in AddrMan is 10000. The actual number will
+ # usually be less due to bucket and bucket position collisions.
+ node_addresses = self.nodes[0].getnodeaddresses(0, "ipv4")
assert_greater_than(len(node_addresses), 5000)
assert_greater_than(10000, len(node_addresses))
for a in node_addresses:
assert_greater_than(a["time"], 1527811200) # 1st June 2018
- assert_equal(a["services"], NODE_NETWORK | NODE_WITNESS)
+ assert_equal(a["services"], services)
assert a["address"] in imported_addrs
assert_equal(a["port"], 8333)
assert_equal(a["network"], "ipv4")
- node_addresses = self.nodes[0].getnodeaddresses(1)
- assert_equal(len(node_addresses), 1)
+ # Test the IPv6 address.
+ res = self.nodes[0].getnodeaddresses(0, "ipv6")
+ assert_equal(len(res), 1)
+ assert_equal(res[0]["address"], ipv6_addr)
+ assert_equal(res[0]["network"], "ipv6")
+ assert_equal(res[0]["port"], 8333)
+ assert_equal(res[0]["services"], services)
- assert_raises_rpc_error(-8, "Address count out of range", self.nodes[0].getnodeaddresses, -1)
+ # Test for the absence of onion and I2P addresses.
+ for network in ["onion", "i2p"]:
+ assert_equal(self.nodes[0].getnodeaddresses(0, network), [])
- # addrman's size cannot be known reliably after insertion, as hash collisions may occur
- # so only test that requesting a large number of addresses returns less than that
- LARGE_REQUEST_COUNT = 10000
- node_addresses = self.nodes[0].getnodeaddresses(LARGE_REQUEST_COUNT)
- assert_greater_than(LARGE_REQUEST_COUNT, len(node_addresses))
+ # Test invalid arguments.
+ assert_raises_rpc_error(-8, "Address count out of range", self.nodes[0].getnodeaddresses, -1)
+ assert_raises_rpc_error(-8, "Network not recognized: Foo", self.nodes[0].getnodeaddresses, 1, "Foo")
+
+ def test_addpeeraddress(self):
+ self.log.info("Test addpeeraddress")
+ node = self.nodes[1]
+
+ self.log.debug("Test that addpeerinfo is a hidden RPC")
+ # It is hidden from general help, but its detailed help may be called directly.
+ assert "addpeerinfo" not in node.help()
+ assert "addpeerinfo" in node.help("addpeerinfo")
+
+ self.log.debug("Test that adding an empty address fails")
+ assert_equal(node.addpeeraddress(address="", port=8333), {"success": False})
+ assert_equal(node.getnodeaddresses(count=0), [])
+
+ self.log.debug("Test that adding a valid address succeeds")
+ assert_equal(node.addpeeraddress(address="1.2.3.4", port=8333), {"success": True})
+ addrs = node.getnodeaddresses(count=0)
+ assert_equal(len(addrs), 1)
+ assert_equal(addrs[0]["address"], "1.2.3.4")
+ assert_equal(addrs[0]["port"], 8333)
+
+ self.log.debug("Test that adding the same address again when already present fails")
+ assert_equal(node.addpeeraddress(address="1.2.3.4", port=8333), {"success": False})
+ assert_equal(len(node.getnodeaddresses(count=0)), 1)
if __name__ == '__main__':
diff --git a/test/functional/rpc_packages.py b/test/functional/rpc_packages.py
new file mode 100755
index 0000000000..3d8d81d6b8
--- /dev/null
+++ b/test/functional/rpc_packages.py
@@ -0,0 +1,362 @@
+#!/usr/bin/env python3
+# Copyright (c) 2021 The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+"""RPCs that handle raw transaction packages."""
+
+from decimal import Decimal
+from io import BytesIO
+import random
+
+from test_framework.address import ADDRESS_BCRT1_P2WSH_OP_TRUE
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.messages import (
+ BIP125_SEQUENCE_NUMBER,
+ COIN,
+ CTransaction,
+ CTxInWitness,
+)
+from test_framework.script import (
+ CScript,
+ OP_TRUE,
+)
+from test_framework.util import (
+ assert_equal,
+ hex_str_to_bytes,
+)
+
+class RPCPackagesTest(BitcoinTestFramework):
+ def set_test_params(self):
+ self.num_nodes = 1
+ self.setup_clean_chain = True
+
+ def assert_testres_equal(self, package_hex, testres_expected):
+ """Shuffle package_hex and assert that the testmempoolaccept result matches testres_expected. This should only
+ be used to test packages where the order does not matter. The ordering of transactions in package_hex and
+ testres_expected must match.
+ """
+ shuffled_indeces = list(range(len(package_hex)))
+ random.shuffle(shuffled_indeces)
+ shuffled_package = [package_hex[i] for i in shuffled_indeces]
+ shuffled_testres = [testres_expected[i] for i in shuffled_indeces]
+ assert_equal(shuffled_testres, self.nodes[0].testmempoolaccept(shuffled_package))
+
+ def run_test(self):
+ self.log.info("Generate blocks to create UTXOs")
+ node = self.nodes[0]
+ self.privkeys = [node.get_deterministic_priv_key().key]
+ self.address = node.get_deterministic_priv_key().address
+ self.coins = []
+ # The last 100 coinbase transactions are premature
+ for b in node.generatetoaddress(200, self.address)[:100]:
+ coinbase = node.getblock(blockhash=b, verbosity=2)["tx"][0]
+ self.coins.append({
+ "txid": coinbase["txid"],
+ "amount": coinbase["vout"][0]["value"],
+ "scriptPubKey": coinbase["vout"][0]["scriptPubKey"],
+ })
+
+ # Create some transactions that can be reused throughout the test. Never submit these to mempool.
+ self.independent_txns_hex = []
+ self.independent_txns_testres = []
+ for _ in range(3):
+ coin = self.coins.pop()
+ rawtx = node.createrawtransaction([{"txid": coin["txid"], "vout": 0}],
+ {self.address : coin["amount"] - Decimal("0.0001")})
+ signedtx = node.signrawtransactionwithkey(hexstring=rawtx, privkeys=self.privkeys)
+ assert signedtx["complete"]
+ testres = node.testmempoolaccept([signedtx["hex"]])
+ assert testres[0]["allowed"]
+ self.independent_txns_hex.append(signedtx["hex"])
+ # testmempoolaccept returns a list of length one, avoid creating a 2D list
+ self.independent_txns_testres.append(testres[0])
+ self.independent_txns_testres_blank = [{
+ "txid": res["txid"], "wtxid": res["wtxid"]} for res in self.independent_txns_testres]
+
+ self.test_independent()
+ self.test_chain()
+ self.test_multiple_children()
+ self.test_multiple_parents()
+ self.test_conflicting()
+ self.test_rbf()
+
+ def chain_transaction(self, parent_txid, parent_value, n=0, parent_locking_script=None):
+ """Build a transaction that spends parent_txid.vout[n] and produces one output with
+ amount = parent_value with a fee deducted.
+ Return tuple (CTransaction object, raw hex, nValue, scriptPubKey of the output created).
+ """
+ node = self.nodes[0]
+ inputs = [{"txid": parent_txid, "vout": n}]
+ my_value = parent_value - Decimal("0.0001")
+ outputs = {self.address : my_value}
+ rawtx = node.createrawtransaction(inputs, outputs)
+ prevtxs = [{
+ "txid": parent_txid,
+ "vout": n,
+ "scriptPubKey": parent_locking_script,
+ "amount": parent_value,
+ }] if parent_locking_script else None
+ signedtx = node.signrawtransactionwithkey(hexstring=rawtx, privkeys=self.privkeys, prevtxs=prevtxs)
+ tx = CTransaction()
+ assert signedtx["complete"]
+ tx.deserialize(BytesIO(hex_str_to_bytes(signedtx["hex"])))
+ return (tx, signedtx["hex"], my_value, tx.vout[0].scriptPubKey.hex())
+
+ def test_independent(self):
+ self.log.info("Test multiple independent transactions in a package")
+ node = self.nodes[0]
+ # For independent transactions, order doesn't matter.
+ self.assert_testres_equal(self.independent_txns_hex, self.independent_txns_testres)
+
+ self.log.info("Test an otherwise valid package with an extra garbage tx appended")
+ garbage_tx = node.createrawtransaction([{"txid": "00" * 32, "vout": 5}], {self.address: 1})
+ tx = CTransaction()
+ tx.deserialize(BytesIO(hex_str_to_bytes(garbage_tx)))
+ # Only the txid and wtxids are returned because validation is incomplete for the independent txns.
+ # Package validation is atomic: if the node cannot find a UTXO for any single tx in the package,
+ # it terminates immediately to avoid unnecessary, expensive signature verification.
+ package_bad = self.independent_txns_hex + [garbage_tx]
+ testres_bad = self.independent_txns_testres_blank + [{"txid": tx.rehash(), "wtxid": tx.getwtxid(), "allowed": False, "reject-reason": "missing-inputs"}]
+ self.assert_testres_equal(package_bad, testres_bad)
+
+ self.log.info("Check testmempoolaccept tells us when some transactions completed validation successfully")
+ coin = self.coins.pop()
+ tx_bad_sig_hex = node.createrawtransaction([{"txid": coin["txid"], "vout": 0}],
+ {self.address : coin["amount"] - Decimal("0.0001")})
+ tx_bad_sig = CTransaction()
+ tx_bad_sig.deserialize(BytesIO(hex_str_to_bytes(tx_bad_sig_hex)))
+ testres_bad_sig = node.testmempoolaccept(self.independent_txns_hex + [tx_bad_sig_hex])
+ # By the time the signature for the last transaction is checked, all the other transactions
+ # have been fully validated, which is why the node returns full validation results for all
+ # transactions here but empty results in other cases.
+ assert_equal(testres_bad_sig, self.independent_txns_testres + [{
+ "txid": tx_bad_sig.rehash(),
+ "wtxid": tx_bad_sig.getwtxid(), "allowed": False,
+ "reject-reason": "mandatory-script-verify-flag-failed (Operation not valid with the current stack size)"
+ }])
+
+ self.log.info("Check testmempoolaccept reports txns in packages that exceed max feerate")
+ coin = self.coins.pop()
+ tx_high_fee_raw = node.createrawtransaction([{"txid": coin["txid"], "vout": 0}],
+ {self.address : coin["amount"] - Decimal("0.999")})
+ tx_high_fee_signed = node.signrawtransactionwithkey(hexstring=tx_high_fee_raw, privkeys=self.privkeys)
+ assert tx_high_fee_signed["complete"]
+ tx_high_fee = CTransaction()
+ tx_high_fee.deserialize(BytesIO(hex_str_to_bytes(tx_high_fee_signed["hex"])))
+ testres_high_fee = node.testmempoolaccept([tx_high_fee_signed["hex"]])
+ assert_equal(testres_high_fee, [
+ {"txid": tx_high_fee.rehash(), "wtxid": tx_high_fee.getwtxid(), "allowed": False, "reject-reason": "max-fee-exceeded"}
+ ])
+ package_high_fee = [tx_high_fee_signed["hex"]] + self.independent_txns_hex
+ testres_package_high_fee = node.testmempoolaccept(package_high_fee)
+ assert_equal(testres_package_high_fee, testres_high_fee + self.independent_txns_testres_blank)
+
+ def test_chain(self):
+ node = self.nodes[0]
+ first_coin = self.coins.pop()
+
+ # Chain of 25 transactions
+ parent_locking_script = None
+ txid = first_coin["txid"]
+ chain_hex = []
+ chain_txns = []
+ value = first_coin["amount"]
+
+ for _ in range(25):
+ (tx, txhex, value, parent_locking_script) = self.chain_transaction(txid, value, 0, parent_locking_script)
+ txid = tx.rehash()
+ chain_hex.append(txhex)
+ chain_txns.append(tx)
+
+ self.log.info("Check that testmempoolaccept requires packages to be sorted by dependency")
+ assert_equal(node.testmempoolaccept(rawtxs=chain_hex[::-1]),
+ [{"txid": tx.rehash(), "wtxid": tx.getwtxid(), "package-error": "package-not-sorted"} for tx in chain_txns[::-1]])
+
+ self.log.info("Testmempoolaccept a chain of 25 transactions")
+ testres_multiple = node.testmempoolaccept(rawtxs=chain_hex)
+
+ testres_single = []
+ # Test accept and then submit each one individually, which should be identical to package test accept
+ for rawtx in chain_hex:
+ testres = node.testmempoolaccept([rawtx])
+ testres_single.append(testres[0])
+ # Submit the transaction now so its child should have no problem validating
+ node.sendrawtransaction(rawtx)
+ assert_equal(testres_single, testres_multiple)
+
+ # Clean up by clearing the mempool
+ node.generate(1)
+
+ def test_multiple_children(self):
+ node = self.nodes[0]
+
+ self.log.info("Testmempoolaccept a package in which a transaction has two children within the package")
+ first_coin = self.coins.pop()
+ value = (first_coin["amount"] - Decimal("0.0002")) / 2 # Deduct reasonable fee and make 2 outputs
+ inputs = [{"txid": first_coin["txid"], "vout": 0}]
+ outputs = [{self.address : value}, {ADDRESS_BCRT1_P2WSH_OP_TRUE : value}]
+ rawtx = node.createrawtransaction(inputs, outputs)
+
+ parent_signed = node.signrawtransactionwithkey(hexstring=rawtx, privkeys=self.privkeys)
+ parent_tx = CTransaction()
+ assert parent_signed["complete"]
+ parent_tx.deserialize(BytesIO(hex_str_to_bytes(parent_signed["hex"])))
+ parent_txid = parent_tx.rehash()
+ assert node.testmempoolaccept([parent_signed["hex"]])[0]["allowed"]
+
+ parent_locking_script_a = parent_tx.vout[0].scriptPubKey.hex()
+ child_value = value - Decimal("0.0001")
+
+ # Child A
+ (_, tx_child_a_hex, _, _) = self.chain_transaction(parent_txid, child_value, 0, parent_locking_script_a)
+ assert not node.testmempoolaccept([tx_child_a_hex])[0]["allowed"]
+
+ # Child B
+ rawtx_b = node.createrawtransaction([{"txid": parent_txid, "vout": 1}], {self.address : child_value})
+ tx_child_b = CTransaction()
+ tx_child_b.deserialize(BytesIO(hex_str_to_bytes(rawtx_b)))
+ tx_child_b.wit.vtxinwit = [CTxInWitness()]
+ tx_child_b.wit.vtxinwit[0].scriptWitness.stack = [CScript([OP_TRUE])]
+ tx_child_b_hex = tx_child_b.serialize().hex()
+ assert not node.testmempoolaccept([tx_child_b_hex])[0]["allowed"]
+
+ self.log.info("Testmempoolaccept with entire package, should work with children in either order")
+ testres_multiple_ab = node.testmempoolaccept(rawtxs=[parent_signed["hex"], tx_child_a_hex, tx_child_b_hex])
+ testres_multiple_ba = node.testmempoolaccept(rawtxs=[parent_signed["hex"], tx_child_b_hex, tx_child_a_hex])
+ assert all([testres["allowed"] for testres in testres_multiple_ab + testres_multiple_ba])
+
+ testres_single = []
+ # Test accept and then submit each one individually, which should be identical to package testaccept
+ for rawtx in [parent_signed["hex"], tx_child_a_hex, tx_child_b_hex]:
+ testres = node.testmempoolaccept([rawtx])
+ testres_single.append(testres[0])
+ # Submit the transaction now so its child should have no problem validating
+ node.sendrawtransaction(rawtx)
+ assert_equal(testres_single, testres_multiple_ab)
+
+ def create_child_with_parents(self, parents_tx, values, locking_scripts):
+ """Creates a transaction that spends the first output of each parent in parents_tx."""
+ num_parents = len(parents_tx)
+ total_value = sum(values)
+ inputs = [{"txid": tx.rehash(), "vout": 0} for tx in parents_tx]
+ outputs = {self.address : total_value - num_parents * Decimal("0.0001")}
+ rawtx_child = self.nodes[0].createrawtransaction(inputs, outputs)
+ prevtxs = []
+ for i in range(num_parents):
+ prevtxs.append({"txid": parents_tx[i].rehash(), "vout": 0, "scriptPubKey": locking_scripts[i], "amount": values[i]})
+ signedtx_child = self.nodes[0].signrawtransactionwithkey(hexstring=rawtx_child, privkeys=self.privkeys, prevtxs=prevtxs)
+ assert signedtx_child["complete"]
+ return signedtx_child["hex"]
+
+ def test_multiple_parents(self):
+ node = self.nodes[0]
+
+ self.log.info("Testmempoolaccept a package in which a transaction has multiple parents within the package")
+ for num_parents in [2, 10, 24]:
+ # Test a package with num_parents parents and 1 child transaction.
+ package_hex = []
+ parents_tx = []
+ values = []
+ parent_locking_scripts = []
+ for _ in range(num_parents):
+ parent_coin = self.coins.pop()
+ value = parent_coin["amount"]
+ (tx, txhex, value, parent_locking_script) = self.chain_transaction(parent_coin["txid"], value)
+ package_hex.append(txhex)
+ parents_tx.append(tx)
+ values.append(value)
+ parent_locking_scripts.append(parent_locking_script)
+ child_hex = self.create_child_with_parents(parents_tx, values, parent_locking_scripts)
+ # Package accept should work with the parents in any order (as long as parents come before child)
+ for _ in range(10):
+ random.shuffle(package_hex)
+ testres_multiple = node.testmempoolaccept(rawtxs=package_hex + [child_hex])
+ assert all([testres["allowed"] for testres in testres_multiple])
+
+ testres_single = []
+ # Test accept and then submit each one individually, which should be identical to package testaccept
+ for rawtx in package_hex + [child_hex]:
+ testres_single.append(node.testmempoolaccept([rawtx])[0])
+ # Submit the transaction now so its child should have no problem validating
+ node.sendrawtransaction(rawtx)
+ assert_equal(testres_single, testres_multiple)
+
+ def test_conflicting(self):
+ node = self.nodes[0]
+ prevtx = self.coins.pop()
+ inputs = [{"txid": prevtx["txid"], "vout": 0}]
+ output1 = {node.get_deterministic_priv_key().address: 50 - 0.00125}
+ output2 = {ADDRESS_BCRT1_P2WSH_OP_TRUE: 50 - 0.00125}
+
+ # tx1 and tx2 share the same inputs
+ rawtx1 = node.createrawtransaction(inputs, output1)
+ rawtx2 = node.createrawtransaction(inputs, output2)
+ signedtx1 = node.signrawtransactionwithkey(hexstring=rawtx1, privkeys=self.privkeys)
+ signedtx2 = node.signrawtransactionwithkey(hexstring=rawtx2, privkeys=self.privkeys)
+ tx1 = CTransaction()
+ tx1.deserialize(BytesIO(hex_str_to_bytes(signedtx1["hex"])))
+ tx2 = CTransaction()
+ tx2.deserialize(BytesIO(hex_str_to_bytes(signedtx2["hex"])))
+ assert signedtx1["complete"]
+ assert signedtx2["complete"]
+
+ # Ensure tx1 and tx2 are valid by themselves
+ assert node.testmempoolaccept([signedtx1["hex"]])[0]["allowed"]
+ assert node.testmempoolaccept([signedtx2["hex"]])[0]["allowed"]
+
+ self.log.info("Test duplicate transactions in the same package")
+ testres = node.testmempoolaccept([signedtx1["hex"], signedtx1["hex"]])
+ assert_equal(testres, [
+ {"txid": tx1.rehash(), "wtxid": tx1.getwtxid(), "package-error": "conflict-in-package"},
+ {"txid": tx1.rehash(), "wtxid": tx1.getwtxid(), "package-error": "conflict-in-package"}
+ ])
+
+ self.log.info("Test conflicting transactions in the same package")
+ testres = node.testmempoolaccept([signedtx1["hex"], signedtx2["hex"]])
+ assert_equal(testres, [
+ {"txid": tx1.rehash(), "wtxid": tx1.getwtxid(), "package-error": "conflict-in-package"},
+ {"txid": tx2.rehash(), "wtxid": tx2.getwtxid(), "package-error": "conflict-in-package"}
+ ])
+
+ def test_rbf(self):
+ node = self.nodes[0]
+ coin = self.coins.pop()
+ inputs = [{"txid": coin["txid"], "vout": 0, "sequence": BIP125_SEQUENCE_NUMBER}]
+ fee = Decimal('0.00125000')
+ output = {node.get_deterministic_priv_key().address: 50 - fee}
+ raw_replaceable_tx = node.createrawtransaction(inputs, output)
+ signed_replaceable_tx = node.signrawtransactionwithkey(hexstring=raw_replaceable_tx, privkeys=self.privkeys)
+ testres_replaceable = node.testmempoolaccept([signed_replaceable_tx["hex"]])
+ replaceable_tx = CTransaction()
+ replaceable_tx.deserialize(BytesIO(hex_str_to_bytes(signed_replaceable_tx["hex"])))
+ assert_equal(testres_replaceable, [
+ {"txid": replaceable_tx.rehash(), "wtxid": replaceable_tx.getwtxid(),
+ "allowed": True, "vsize": replaceable_tx.get_vsize(), "fees": { "base": fee }}
+ ])
+
+ # Replacement transaction is identical except has double the fee
+ replacement_tx = CTransaction()
+ replacement_tx.deserialize(BytesIO(hex_str_to_bytes(signed_replaceable_tx["hex"])))
+ replacement_tx.vout[0].nValue -= int(fee * COIN) # Doubled fee
+ signed_replacement_tx = node.signrawtransactionwithkey(replacement_tx.serialize().hex(), self.privkeys)
+ replacement_tx.deserialize(BytesIO(hex_str_to_bytes(signed_replacement_tx["hex"])))
+
+ self.log.info("Test that transactions within a package cannot replace each other")
+ testres_rbf_conflicting = node.testmempoolaccept([signed_replaceable_tx["hex"], signed_replacement_tx["hex"]])
+ assert_equal(testres_rbf_conflicting, [
+ {"txid": replaceable_tx.rehash(), "wtxid": replaceable_tx.getwtxid(), "package-error": "conflict-in-package"},
+ {"txid": replacement_tx.rehash(), "wtxid": replacement_tx.getwtxid(), "package-error": "conflict-in-package"}
+ ])
+
+ self.log.info("Test that packages cannot conflict with mempool transactions, even if a valid BIP125 RBF")
+ node.sendrawtransaction(signed_replaceable_tx["hex"])
+ testres_rbf_single = node.testmempoolaccept([signed_replacement_tx["hex"]])
+ # This transaction is a valid BIP125 replace-by-fee
+ assert testres_rbf_single[0]["allowed"]
+ testres_rbf_package = self.independent_txns_testres_blank + [{
+ "txid": replacement_tx.rehash(), "wtxid": replacement_tx.getwtxid(), "allowed": False, "reject-reason": "txn-mempool-conflict"
+ }]
+ self.assert_testres_equal(self.independent_txns_hex + [signed_replacement_tx["hex"]], testres_rbf_package)
+
+if __name__ == "__main__":
+ RPCPackagesTest().main()
diff --git a/test/functional/rpc_rawtransaction.py b/test/functional/rpc_rawtransaction.py
index 86c7b3fbcc..53ddf24e47 100755
--- a/test/functional/rpc_rawtransaction.py
+++ b/test/functional/rpc_rawtransaction.py
@@ -15,6 +15,8 @@ Test the following RPCs:
from collections import OrderedDict
from decimal import Decimal
from io import BytesIO
+
+from test_framework.blocktools import COINBASE_MATURITY
from test_framework.messages import CTransaction, ToHex
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
@@ -66,7 +68,7 @@ class RawTransactionsTest(BitcoinTestFramework):
self.log.info('prepare some coins for multiple *rawtransaction commands')
self.nodes[2].generate(1)
self.sync_all()
- self.nodes[0].generate(101)
+ self.nodes[0].generate(COINBASE_MATURITY + 1)
self.sync_all()
self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(),1.5)
self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(),1.0)
diff --git a/test/functional/rpc_signrawtransaction.py b/test/functional/rpc_signrawtransaction.py
index 60b4d1c744..16b0019866 100755
--- a/test/functional/rpc_signrawtransaction.py
+++ b/test/functional/rpc_signrawtransaction.py
@@ -4,6 +4,7 @@
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Test transaction signing using the signrawtransaction* RPCs."""
+from test_framework.blocktools import COINBASE_MATURITY
from test_framework.address import check_script, script_to_p2sh, script_to_p2wsh
from test_framework.key import ECKey
from test_framework.test_framework import BitcoinTestFramework
@@ -155,7 +156,7 @@ class SignRawTransactionsTest(BitcoinTestFramework):
def test_fully_signed_tx(self):
self.log.info("Test signing a fully signed transaction does nothing")
self.nodes[0].walletpassphrase("password", 9999)
- self.nodes[0].generate(101)
+ self.nodes[0].generate(COINBASE_MATURITY + 1)
rawtx = self.nodes[0].createrawtransaction([], [{self.nodes[0].getnewaddress(): 10}])
fundedtx = self.nodes[0].fundrawtransaction(rawtx)
signedtx = self.nodes[0].signrawtransactionwithwallet(fundedtx["hex"])
@@ -174,7 +175,7 @@ class SignRawTransactionsTest(BitcoinTestFramework):
embedded_pubkey = eckey.get_pubkey().get_bytes().hex()
p2sh_p2wsh_address = self.nodes[1].createmultisig(1, [embedded_pubkey], "p2sh-segwit")
# send transaction to P2SH-P2WSH 1-of-1 multisig address
- self.nodes[0].generate(101)
+ self.nodes[0].generate(COINBASE_MATURITY + 1)
self.nodes[0].sendtoaddress(p2sh_p2wsh_address["address"], 49.999)
self.nodes[0].generate(1)
self.sync_all()
diff --git a/test/functional/rpc_txoutproof.py b/test/functional/rpc_txoutproof.py
index 528da0cbfc..bf96b6353c 100755
--- a/test/functional/rpc_txoutproof.py
+++ b/test/functional/rpc_txoutproof.py
@@ -4,6 +4,7 @@
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Test gettxoutproof and verifytxoutproof RPCs."""
+from test_framework.blocktools import COINBASE_MATURITY
from test_framework.messages import CMerkleBlock, FromHex, ToHex
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import assert_equal, assert_raises_rpc_error
@@ -23,7 +24,7 @@ class MerkleBlockTest(BitcoinTestFramework):
miniwallet = MiniWallet(self.nodes[0])
# Add enough mature utxos to the wallet, so that all txs spend confirmed coins
miniwallet.generate(5)
- self.nodes[0].generate(100)
+ self.nodes[0].generate(COINBASE_MATURITY)
self.sync_all()
chain_height = self.nodes[1].getblockcount()
diff --git a/test/functional/test_framework/blocktools.py b/test/functional/test_framework/blocktools.py
index d08e025178..e91b44e776 100644
--- a/test/functional/test_framework/blocktools.py
+++ b/test/functional/test_framework/blocktools.py
@@ -52,6 +52,9 @@ MAX_BLOCK_SIGOPS_WEIGHT = MAX_BLOCK_SIGOPS * WITNESS_SCALE_FACTOR
# Genesis block time (regtest)
TIME_GENESIS_BLOCK = 1296688602
+# Coinbase transaction outputs can only be spent after this number of new blocks (network rule)
+COINBASE_MATURITY = 100
+
# From BIP141
WITNESS_COMMITMENT_HEADER = b"\xaa\x21\xa9\xed"
diff --git a/test/functional/test_framework/netutil.py b/test/functional/test_framework/netutil.py
index e047e7fa14..5dc723c1d5 100644
--- a/test/functional/test_framework/netutil.py
+++ b/test/functional/test_framework/netutil.py
@@ -151,7 +151,7 @@ def test_ipv6_local():
have_ipv6 = True
try:
s = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
- s.connect(('::1', 0))
+ s.connect(('::1', 1))
except socket.error:
have_ipv6 = False
return have_ipv6
diff --git a/test/functional/test_framework/wallet.py b/test/functional/test_framework/wallet.py
index 395b50c4d8..bfb5916c37 100644
--- a/test/functional/test_framework/wallet.py
+++ b/test/functional/test_framework/wallet.py
@@ -5,7 +5,9 @@
"""A limited-functionality wallet, which may replace a real wallet in tests"""
from decimal import Decimal
+from enum import Enum
from test_framework.address import ADDRESS_BCRT1_P2WSH_OP_TRUE
+from test_framework.key import ECKey
from test_framework.messages import (
COIN,
COutPoint,
@@ -16,8 +18,11 @@ from test_framework.messages import (
)
from test_framework.script import (
CScript,
+ LegacySignatureHash,
+ OP_CHECKSIG,
OP_TRUE,
OP_NOP,
+ SIGHASH_ALL,
)
from test_framework.util import (
assert_equal,
@@ -26,14 +31,46 @@ from test_framework.util import (
)
+class MiniWalletMode(Enum):
+ """Determines the transaction type the MiniWallet is creating and spending.
+
+ For most purposes, the default mode ADDRESS_OP_TRUE should be sufficient;
+ it simply uses a fixed bech32 P2WSH address whose coins are spent with a
+ witness stack of OP_TRUE, i.e. following an anyone-can-spend policy.
+ However, if the transactions need to be modified by the user (e.g. prepending
+ scriptSig for testing opcodes that are activated by a soft-fork), or the txs
+ should contain an actual signature, the raw modes RAW_OP_TRUE and RAW_P2PK
+ can be useful. Summary of modes:
+
+ | output | | tx is | can modify | needs
+ mode | description | address | standard | scriptSig | signing
+ ----------------+-------------------+-----------+----------+------------+----------
+ ADDRESS_OP_TRUE | anyone-can-spend | bech32 | yes | no | no
+ RAW_OP_TRUE | anyone-can-spend | - (raw) | no | yes | no
+ RAW_P2PK | pay-to-public-key | - (raw) | yes | yes | yes
+ """
+ ADDRESS_OP_TRUE = 1
+ RAW_OP_TRUE = 2
+ RAW_P2PK = 3
+
+
class MiniWallet:
- def __init__(self, test_node, *, raw_script=False):
+ def __init__(self, test_node, *, mode=MiniWalletMode.ADDRESS_OP_TRUE):
self._test_node = test_node
self._utxos = []
- if raw_script:
- self._address = None
+ self._priv_key = None
+ self._address = None
+
+ assert isinstance(mode, MiniWalletMode)
+ if mode == MiniWalletMode.RAW_OP_TRUE:
self._scriptPubKey = bytes(CScript([OP_TRUE]))
- else:
+ elif mode == MiniWalletMode.RAW_P2PK:
+ # use simple deterministic private key (k=1)
+ self._priv_key = ECKey()
+ self._priv_key.set((1).to_bytes(32, 'big'), True)
+ pub_key = self._priv_key.get_pubkey()
+ self._scriptPubKey = bytes(CScript([pub_key.get_bytes(), OP_CHECKSIG]))
+ elif mode == MiniWalletMode.ADDRESS_OP_TRUE:
self._address = ADDRESS_BCRT1_P2WSH_OP_TRUE
self._scriptPubKey = hex_str_to_bytes(self._test_node.validateaddress(self._address)['scriptPubKey'])
@@ -50,6 +87,13 @@ class MiniWallet:
if out['scriptPubKey']['hex'] == self._scriptPubKey.hex():
self._utxos.append({'txid': tx['txid'], 'vout': out['n'], 'value': out['value']})
+ def sign_tx(self, tx):
+ """Sign tx that has been created by MiniWallet in P2PK mode"""
+ assert self._priv_key is not None
+ (sighash, err) = LegacySignatureHash(CScript(self._scriptPubKey), tx, 0, SIGHASH_ALL)
+ assert err is None
+ tx.vin[0].scriptSig = CScript([self._priv_key.sign_ecdsa(sighash) + bytes(bytearray([SIGHASH_ALL]))])
+
def generate(self, num_blocks):
"""Generate blocks with coinbase outputs to the internal address, and append the outputs to the internal list"""
blocks = self._test_node.generatetodescriptor(num_blocks, f'raw({self._scriptPubKey.hex()})')
@@ -61,7 +105,7 @@ class MiniWallet:
def get_address(self):
return self._address
- def get_utxo(self, *, txid=''):
+ def get_utxo(self, *, txid='', mark_as_spent=True):
"""
Returns a utxo and marks it as spent (pops it from the internal list)
@@ -74,15 +118,18 @@ class MiniWallet:
if txid:
utxo = next(filter(lambda utxo: txid == utxo['txid'], self._utxos))
index = self._utxos.index(utxo)
- return self._utxos.pop(index)
+ if mark_as_spent:
+ return self._utxos.pop(index)
+ else:
+ return self._utxos[index]
- def send_self_transfer(self, *, fee_rate=Decimal("0.003"), from_node, utxo_to_spend=None):
+ def send_self_transfer(self, *, fee_rate=Decimal("0.003"), from_node, utxo_to_spend=None, locktime=0):
"""Create and send a tx with the specified fee_rate. Fee may be exact or at most one satoshi higher than needed."""
tx = self.create_self_transfer(fee_rate=fee_rate, from_node=from_node, utxo_to_spend=utxo_to_spend)
self.sendrawtransaction(from_node=from_node, tx_hex=tx['hex'])
return tx
- def create_self_transfer(self, *, fee_rate=Decimal("0.003"), from_node, utxo_to_spend=None, mempool_valid=True):
+ def create_self_transfer(self, *, fee_rate=Decimal("0.003"), from_node, utxo_to_spend=None, mempool_valid=True, locktime=0):
"""Create and return a tx with the specified fee_rate. Fee may be exact or at most one satoshi higher than needed."""
self._utxos = sorted(self._utxos, key=lambda k: k['value'])
utxo_to_spend = utxo_to_spend or self._utxos.pop() # Pick the largest utxo (if none provided) and hope it covers the fee
@@ -94,9 +141,15 @@ class MiniWallet:
tx = CTransaction()
tx.vin = [CTxIn(COutPoint(int(utxo_to_spend['txid'], 16), utxo_to_spend['vout']))]
tx.vout = [CTxOut(int(send_value * COIN), self._scriptPubKey)]
+ tx.nLockTime = locktime
if not self._address:
# raw script
- tx.vin[0].scriptSig = CScript([OP_NOP] * 35) # pad to identical size
+ if self._priv_key is not None:
+ # P2PK, need to sign
+ self.sign_tx(tx)
+ else:
+ # anyone-can-spend
+ tx.vin[0].scriptSig = CScript([OP_NOP] * 35) # pad to identical size
else:
tx.wit.vtxinwit = [CTxInWitness()]
tx.wit.vtxinwit[0].scriptWitness.stack = [CScript([OP_TRUE])]
@@ -105,7 +158,10 @@ class MiniWallet:
tx_info = from_node.testmempoolaccept([tx_hex])[0]
assert_equal(mempool_valid, tx_info['allowed'])
if mempool_valid:
- assert_equal(tx_info['vsize'], vsize)
+ # TODO: for P2PK, vsize is not constant due to varying scriptSig length,
+ # so only check this for anyone-can-spend outputs right now
+ if self._priv_key is None:
+ assert_equal(tx_info['vsize'], vsize)
assert_equal(tx_info['fees']['base'], fee)
return {'txid': tx_info['txid'], 'wtxid': tx_info['wtxid'], 'hex': tx_hex, 'tx': tx}
diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py
index 00527e78f1..49f269f8b4 100755
--- a/test/functional/test_runner.py
+++ b/test/functional/test_runner.py
@@ -211,6 +211,7 @@ BASE_SCRIPTS = [
'mempool_package_onemore.py',
'rpc_createmultisig.py --legacy-wallet',
'rpc_createmultisig.py --descriptors',
+ 'rpc_packages.py',
'feature_versionbits_warning.py',
'rpc_preciousblock.py',
'wallet_importprunedfunds.py --legacy-wallet',
diff --git a/test/functional/wallet_abandonconflict.py b/test/functional/wallet_abandonconflict.py
index 2e0edcfa38..d24cc802a4 100755
--- a/test/functional/wallet_abandonconflict.py
+++ b/test/functional/wallet_abandonconflict.py
@@ -12,6 +12,7 @@
"""
from decimal import Decimal
+from test_framework.blocktools import COINBASE_MATURITY
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
assert_equal,
@@ -28,7 +29,7 @@ class AbandonConflictTest(BitcoinTestFramework):
self.skip_if_no_wallet()
def run_test(self):
- self.nodes[1].generate(100)
+ self.nodes[1].generate(COINBASE_MATURITY)
self.sync_blocks()
balance = self.nodes[0].getbalance()
txA = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), Decimal("10"))
diff --git a/test/functional/wallet_address_types.py b/test/functional/wallet_address_types.py
index b3bee1876d..6d93cf412f 100755
--- a/test/functional/wallet_address_types.py
+++ b/test/functional/wallet_address_types.py
@@ -53,6 +53,7 @@ Test that the nodes generate the correct change address type:
from decimal import Decimal
import itertools
+from test_framework.blocktools import COINBASE_MATURITY
from test_framework.test_framework import BitcoinTestFramework
from test_framework.descriptors import (
descsum_create,
@@ -220,7 +221,7 @@ class AddressTypeTest(BitcoinTestFramework):
def run_test(self):
# Mine 101 blocks on node5 to bring nodes out of IBD and make sure that
# no coinbases are maturing for the nodes-under-test during the test
- self.nodes[5].generate(101)
+ self.nodes[5].generate(COINBASE_MATURITY + 1)
self.sync_blocks()
uncompressed_1 = "0496b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52da7589379515d4e0a604f8141781e62294721166bf621e73a82cbf2342c858ee"
@@ -258,7 +259,7 @@ class AddressTypeTest(BitcoinTestFramework):
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"))
+ to_send = (old_balances[from_node] / (COINBASE_MATURITY + 1)).quantize(Decimal("0.00000001"))
sends = {}
addresses = {}
diff --git a/test/functional/wallet_avoidreuse.py b/test/functional/wallet_avoidreuse.py
index 1d3736d9b1..c13d8de4b5 100755
--- a/test/functional/wallet_avoidreuse.py
+++ b/test/functional/wallet_avoidreuse.py
@@ -42,25 +42,25 @@ def count_unspent(node):
r["reused"]["supported"] = supports_reused
return r
-def assert_unspent(node, total_count=None, total_sum=None, reused_supported=None, reused_count=None, reused_sum=None):
+def assert_unspent(node, total_count=None, total_sum=None, reused_supported=None, reused_count=None, reused_sum=None, margin=0.001):
'''Make assertions about a node's unspent output statistics'''
stats = count_unspent(node)
if total_count is not None:
assert_equal(stats["total"]["count"], total_count)
if total_sum is not None:
- assert_approx(stats["total"]["sum"], total_sum, 0.001)
+ assert_approx(stats["total"]["sum"], total_sum, margin)
if reused_supported is not None:
assert_equal(stats["reused"]["supported"], reused_supported)
if reused_count is not None:
assert_equal(stats["reused"]["count"], reused_count)
if reused_sum is not None:
- assert_approx(stats["reused"]["sum"], reused_sum, 0.001)
+ assert_approx(stats["reused"]["sum"], reused_sum, margin)
-def assert_balances(node, mine):
+def assert_balances(node, mine, margin=0.001):
'''Make assertions about a node's getbalances output'''
got = node.getbalances()["mine"]
for k,v in mine.items():
- assert_approx(got[k], v, 0.001)
+ assert_approx(got[k], v, margin)
class AvoidReuseTest(BitcoinTestFramework):
@@ -299,7 +299,7 @@ class AvoidReuseTest(BitcoinTestFramework):
ret_addr = self.nodes[0].getnewaddress()
# send multiple transactions, reusing one address
- for _ in range(11):
+ for _ in range(101):
self.nodes[0].sendtoaddress(new_addr, 1)
self.nodes[0].generate(1)
@@ -311,14 +311,14 @@ class AvoidReuseTest(BitcoinTestFramework):
# getbalances and listunspent should show the remaining outputs
# in the reused address as used/reused
- assert_unspent(self.nodes[1], total_count=2, total_sum=6, reused_count=1, reused_sum=1)
- assert_balances(self.nodes[1], mine={"used": 1, "trusted": 5})
+ assert_unspent(self.nodes[1], total_count=2, total_sum=96, reused_count=1, reused_sum=1, margin=0.01)
+ assert_balances(self.nodes[1], mine={"used": 1, "trusted": 95}, margin=0.01)
def test_full_destination_group_is_preferred(self):
'''
- Test the case where [1] only has 11 outputs of 1 BTC in the same reused
+ Test the case where [1] only has 101 outputs of 1 BTC in the same reused
address and tries to send a small payment of 0.5 BTC. The wallet
- should use 10 outputs from the reused address as inputs and not a
+ should use 100 outputs from the reused address as inputs and not a
single 1 BTC input, in order to join several outputs from the reused
address.
'''
@@ -330,8 +330,8 @@ class AvoidReuseTest(BitcoinTestFramework):
new_addr = self.nodes[1].getnewaddress()
ret_addr = self.nodes[0].getnewaddress()
- # Send 11 outputs of 1 BTC to the same, reused address in the wallet
- for _ in range(11):
+ # Send 101 outputs of 1 BTC to the same, reused address in the wallet
+ for _ in range(101):
self.nodes[0].sendtoaddress(new_addr, 1)
self.nodes[0].generate(1)
@@ -342,14 +342,14 @@ class AvoidReuseTest(BitcoinTestFramework):
txid = self.nodes[1].sendtoaddress(address=ret_addr, amount=0.5)
inputs = self.nodes[1].getrawtransaction(txid, 1)["vin"]
- # The transaction should use 10 inputs exactly
- assert_equal(len(inputs), 10)
+ # The transaction should use 100 inputs exactly
+ assert_equal(len(inputs), 100)
def test_all_destination_groups_are_used(self):
'''
- Test the case where [1] only has 22 outputs of 1 BTC in the same reused
- address and tries to send a payment of 20.5 BTC. The wallet
- should use all 22 outputs from the reused address as inputs.
+ Test the case where [1] only has 202 outputs of 1 BTC in the same reused
+ address and tries to send a payment of 200.5 BTC. The wallet
+ should use all 202 outputs from the reused address as inputs.
'''
self.log.info("Test that all destination groups are used")
@@ -359,20 +359,20 @@ class AvoidReuseTest(BitcoinTestFramework):
new_addr = self.nodes[1].getnewaddress()
ret_addr = self.nodes[0].getnewaddress()
- # Send 22 outputs of 1 BTC to the same, reused address in the wallet
- for _ in range(22):
+ # Send 202 outputs of 1 BTC to the same, reused address in the wallet
+ for _ in range(202):
self.nodes[0].sendtoaddress(new_addr, 1)
self.nodes[0].generate(1)
self.sync_all()
# Sending a transaction that needs to use the full groups
- # of 10 inputs but also the incomplete group of 2 inputs.
- txid = self.nodes[1].sendtoaddress(address=ret_addr, amount=20.5)
+ # of 100 inputs but also the incomplete group of 2 inputs.
+ txid = self.nodes[1].sendtoaddress(address=ret_addr, amount=200.5)
inputs = self.nodes[1].getrawtransaction(txid, 1)["vin"]
- # The transaction should use 22 inputs exactly
- assert_equal(len(inputs), 22)
+ # The transaction should use 202 inputs exactly
+ assert_equal(len(inputs), 202)
if __name__ == '__main__':
diff --git a/test/functional/wallet_backup.py b/test/functional/wallet_backup.py
index f34c1345e0..05a0ef0ea1 100755
--- a/test/functional/wallet_backup.py
+++ b/test/functional/wallet_backup.py
@@ -35,6 +35,7 @@ import os
from random import randint
import shutil
+from test_framework.blocktools import COINBASE_MATURITY
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
assert_equal,
@@ -123,7 +124,7 @@ class WalletBackupTest(BitcoinTestFramework):
self.sync_blocks()
self.nodes[2].generate(1)
self.sync_blocks()
- self.nodes[3].generate(100)
+ self.nodes[3].generate(COINBASE_MATURITY)
self.sync_blocks()
assert_equal(self.nodes[0].getbalance(), 50)
@@ -152,7 +153,7 @@ class WalletBackupTest(BitcoinTestFramework):
self.do_one_round()
# Generate 101 more blocks, so any fees paid mature
- self.nodes[3].generate(101)
+ self.nodes[3].generate(COINBASE_MATURITY + 1)
self.sync_all()
balance0 = self.nodes[0].getbalance()
diff --git a/test/functional/wallet_balance.py b/test/functional/wallet_balance.py
index 433b40faee..204a866c55 100755
--- a/test/functional/wallet_balance.py
+++ b/test/functional/wallet_balance.py
@@ -7,6 +7,7 @@ from decimal import Decimal
import struct
from test_framework.address import ADDRESS_BCRT1_UNSPENDABLE as ADDRESS_WATCHONLY
+from test_framework.blocktools import COINBASE_MATURITY
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
assert_equal,
@@ -72,7 +73,7 @@ class WalletTest(BitcoinTestFramework):
self.nodes[0].generate(1)
self.sync_all()
self.nodes[1].generate(1)
- self.nodes[1].generatetoaddress(101, ADDRESS_WATCHONLY)
+ self.nodes[1].generatetoaddress(COINBASE_MATURITY + 1, ADDRESS_WATCHONLY)
self.sync_all()
if not self.options.descriptors:
diff --git a/test/functional/wallet_basic.py b/test/functional/wallet_basic.py
index 4a1d25bbc5..a052ec7477 100755
--- a/test/functional/wallet_basic.py
+++ b/test/functional/wallet_basic.py
@@ -6,6 +6,7 @@
from decimal import Decimal
from itertools import product
+from test_framework.blocktools import COINBASE_MATURITY
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
assert_array_result,
@@ -65,7 +66,7 @@ class WalletTest(BitcoinTestFramework):
assert_equal(walletinfo['balance'], 0)
self.sync_all(self.nodes[0:3])
- self.nodes[1].generate(101)
+ self.nodes[1].generate(COINBASE_MATURITY + 1)
self.sync_all(self.nodes[0:3])
assert_equal(self.nodes[0].getbalance(), 50)
@@ -158,7 +159,7 @@ class WalletTest(BitcoinTestFramework):
assert_equal(len(self.nodes[1].listlockunspent()), 0)
# Have node1 generate 100 blocks (so node0 can recover the fee)
- self.nodes[1].generate(100)
+ self.nodes[1].generate(COINBASE_MATURITY)
self.sync_all(self.nodes[0:3])
# node0 should end up with 100 btc in block rewards plus fees, but
diff --git a/test/functional/wallet_bumpfee.py b/test/functional/wallet_bumpfee.py
index ff5070c1fa..b21461ee7b 100755
--- a/test/functional/wallet_bumpfee.py
+++ b/test/functional/wallet_bumpfee.py
@@ -16,6 +16,7 @@ make assumptions about execution order.
from decimal import Decimal
import io
+from test_framework.blocktools import COINBASE_MATURITY
from test_framework.blocktools import add_witness_commitment, create_block, create_coinbase, send_to_witness
from test_framework.messages import BIP125_SEQUENCE_NUMBER, CTransaction
from test_framework.test_framework import BitcoinTestFramework
@@ -265,7 +266,7 @@ def test_small_output_with_feerate_succeeds(self, rbf_node, dest_address):
self.log.info('Testing small output with feerate bump succeeds')
# Make sure additional inputs exist
- rbf_node.generatetoaddress(101, rbf_node.getnewaddress())
+ rbf_node.generatetoaddress(COINBASE_MATURITY + 1, rbf_node.getnewaddress())
rbfid = spend_one_input(rbf_node, dest_address)
input_list = rbf_node.getrawtransaction(rbfid, 1)["vin"]
assert_equal(len(input_list), 1)
diff --git a/test/functional/wallet_descriptor.py b/test/functional/wallet_descriptor.py
index 1e032bdd6c..c6f5d334f8 100755
--- a/test/functional/wallet_descriptor.py
+++ b/test/functional/wallet_descriptor.py
@@ -4,6 +4,7 @@
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Test descriptor wallet function."""
+from test_framework.blocktools import COINBASE_MATURITY
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
assert_equal,
@@ -83,7 +84,7 @@ class WalletDescriptorTest(BitcoinTestFramework):
send_wrpc = self.nodes[0].get_wallet_rpc("desc1")
# Generate some coins
- send_wrpc.generatetoaddress(101, send_wrpc.getnewaddress())
+ send_wrpc.generatetoaddress(COINBASE_MATURITY + 1, send_wrpc.getnewaddress())
# Make transactions
self.log.info("Test sending and receiving")
diff --git a/test/functional/wallet_fallbackfee.py b/test/functional/wallet_fallbackfee.py
index 78eef4b790..b28f3ecebc 100755
--- a/test/functional/wallet_fallbackfee.py
+++ b/test/functional/wallet_fallbackfee.py
@@ -3,6 +3,8 @@
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Test wallet replace-by-fee capabilities in conjunction with the fallbackfee."""
+
+from test_framework.blocktools import COINBASE_MATURITY
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import assert_raises_rpc_error
@@ -15,7 +17,7 @@ class WalletRBFTest(BitcoinTestFramework):
self.skip_if_no_wallet()
def run_test(self):
- self.nodes[0].generate(101)
+ self.nodes[0].generate(COINBASE_MATURITY + 1)
# sending a transaction without fee estimations must be possible by default on regtest
self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 1)
diff --git a/test/functional/wallet_groups.py b/test/functional/wallet_groups.py
index c0b76d960f..f32acb8e15 100755
--- a/test/functional/wallet_groups.py
+++ b/test/functional/wallet_groups.py
@@ -4,6 +4,7 @@
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Test wallet group functionality."""
+from test_framework.blocktools import COINBASE_MATURITY
from test_framework.test_framework import BitcoinTestFramework
from test_framework.messages import CTransaction, FromHex, ToHex
from test_framework.util import (
@@ -31,7 +32,7 @@ class WalletGroupTest(BitcoinTestFramework):
def run_test(self):
self.log.info("Setting up")
# Mine some coins
- self.nodes[0].generate(101)
+ self.nodes[0].generate(COINBASE_MATURITY + 1)
# Get some addresses from the two nodes
addr1 = [self.nodes[1].getnewaddress() for _ in range(3)]
diff --git a/test/functional/wallet_hd.py b/test/functional/wallet_hd.py
index 23d132df41..d41a389197 100755
--- a/test/functional/wallet_hd.py
+++ b/test/functional/wallet_hd.py
@@ -7,6 +7,7 @@
import os
import shutil
+from test_framework.blocktools import COINBASE_MATURITY
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
assert_equal,
@@ -48,7 +49,7 @@ class WalletHDTest(BitcoinTestFramework):
# Derive some HD addresses and remember the last
# Also send funds to each add
- self.nodes[0].generate(101)
+ self.nodes[0].generate(COINBASE_MATURITY + 1)
hd_add = None
NUM_HD_ADDS = 10
for i in range(1, NUM_HD_ADDS + 1):
diff --git a/test/functional/wallet_importdescriptors.py b/test/functional/wallet_importdescriptors.py
index 0a3dd56620..a2da16e5a3 100755
--- a/test/functional/wallet_importdescriptors.py
+++ b/test/functional/wallet_importdescriptors.py
@@ -16,6 +16,7 @@ variants.
and test the values returned."""
from test_framework.address import key_to_p2pkh
+from test_framework.blocktools import COINBASE_MATURITY
from test_framework.test_framework import BitcoinTestFramework
from test_framework.descriptors import descsum_create
from test_framework.util import (
@@ -73,7 +74,7 @@ class ImportDescriptorsTest(BitcoinTestFramework):
assert_equal(wpriv.getwalletinfo()['keypoolsize'], 0)
self.log.info('Mining coins')
- w0.generatetoaddress(101, w0.getnewaddress())
+ w0.generatetoaddress(COINBASE_MATURITY + 1, w0.getnewaddress())
# RPC importdescriptors -----------------------------------------------
diff --git a/test/functional/wallet_importmulti.py b/test/functional/wallet_importmulti.py
index 13186b9e1d..0a00c5eed9 100755
--- a/test/functional/wallet_importmulti.py
+++ b/test/functional/wallet_importmulti.py
@@ -15,6 +15,7 @@ variants.
- `test_address()` is called to call getaddressinfo for an address on node1
and test the values returned."""
+from test_framework.blocktools import COINBASE_MATURITY
from test_framework.script import (
CScript,
OP_NOP,
@@ -255,7 +256,7 @@ class ImportMultiTest(BitcoinTestFramework):
# P2SH address
multisig = get_multisig(self.nodes[0])
- self.nodes[1].generate(100)
+ self.nodes[1].generate(COINBASE_MATURITY)
self.nodes[1].sendtoaddress(multisig.p2sh_addr, 10.00)
self.nodes[1].generate(1)
timestamp = self.nodes[1].getblock(self.nodes[1].getbestblockhash())['mediantime']
@@ -276,7 +277,7 @@ class ImportMultiTest(BitcoinTestFramework):
# P2SH + Redeem script
multisig = get_multisig(self.nodes[0])
- self.nodes[1].generate(100)
+ self.nodes[1].generate(COINBASE_MATURITY)
self.nodes[1].sendtoaddress(multisig.p2sh_addr, 10.00)
self.nodes[1].generate(1)
timestamp = self.nodes[1].getblock(self.nodes[1].getbestblockhash())['mediantime']
@@ -297,7 +298,7 @@ class ImportMultiTest(BitcoinTestFramework):
# P2SH + Redeem script + Private Keys + !Watchonly
multisig = get_multisig(self.nodes[0])
- self.nodes[1].generate(100)
+ self.nodes[1].generate(COINBASE_MATURITY)
self.nodes[1].sendtoaddress(multisig.p2sh_addr, 10.00)
self.nodes[1].generate(1)
timestamp = self.nodes[1].getblock(self.nodes[1].getbestblockhash())['mediantime']
@@ -323,7 +324,7 @@ class ImportMultiTest(BitcoinTestFramework):
# P2SH + Redeem script + Private Keys + Watchonly
multisig = get_multisig(self.nodes[0])
- self.nodes[1].generate(100)
+ self.nodes[1].generate(COINBASE_MATURITY)
self.nodes[1].sendtoaddress(multisig.p2sh_addr, 10.00)
self.nodes[1].generate(1)
timestamp = self.nodes[1].getblock(self.nodes[1].getbestblockhash())['mediantime']
diff --git a/test/functional/wallet_importprunedfunds.py b/test/functional/wallet_importprunedfunds.py
index 7635ce2139..ded0e64b1d 100755
--- a/test/functional/wallet_importprunedfunds.py
+++ b/test/functional/wallet_importprunedfunds.py
@@ -5,6 +5,7 @@
"""Test the importprunedfunds and removeprunedfunds RPCs."""
from decimal import Decimal
+from test_framework.blocktools import COINBASE_MATURITY
from test_framework.address import key_to_p2wpkh
from test_framework.key import ECKey
from test_framework.test_framework import BitcoinTestFramework
@@ -24,7 +25,7 @@ class ImportPrunedFundsTest(BitcoinTestFramework):
def run_test(self):
self.log.info("Mining blocks...")
- self.nodes[0].generate(101)
+ self.nodes[0].generate(COINBASE_MATURITY + 1)
self.sync_all()
@@ -46,7 +47,7 @@ class ImportPrunedFundsTest(BitcoinTestFramework):
self.sync_all()
# Node 1 sync test
- assert_equal(self.nodes[1].getblockcount(), 101)
+ assert_equal(self.nodes[1].getblockcount(), COINBASE_MATURITY + 1)
# Address Test - before import
address_info = self.nodes[1].getaddressinfo(address1)
diff --git a/test/functional/wallet_keypool_topup.py b/test/functional/wallet_keypool_topup.py
index 5619d57947..1ecf08b9ac 100755
--- a/test/functional/wallet_keypool_topup.py
+++ b/test/functional/wallet_keypool_topup.py
@@ -13,6 +13,7 @@ Two nodes. Node1 is under test. Node0 is providing transactions and generating b
import os
import shutil
+from test_framework.blocktools import COINBASE_MATURITY
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
assert_equal,
@@ -31,7 +32,7 @@ class KeypoolRestoreTest(BitcoinTestFramework):
def run_test(self):
wallet_path = os.path.join(self.nodes[1].datadir, self.chain, "wallets", self.default_wallet_name, self.wallet_data_filename)
wallet_backup_path = os.path.join(self.nodes[1].datadir, "wallet.bak")
- self.nodes[0].generate(101)
+ self.nodes[0].generate(COINBASE_MATURITY + 1)
self.log.info("Make backup of wallet")
self.stop_node(1)
diff --git a/test/functional/wallet_labels.py b/test/functional/wallet_labels.py
index 551eb72720..2d792bac52 100755
--- a/test/functional/wallet_labels.py
+++ b/test/functional/wallet_labels.py
@@ -11,6 +11,7 @@ RPCs tested are:
"""
from collections import defaultdict
+from test_framework.blocktools import COINBASE_MATURITY
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import assert_equal, assert_raises_rpc_error
from test_framework.wallet_util import test_address
@@ -32,7 +33,7 @@ class WalletLabelsTest(BitcoinTestFramework):
# Note each time we call generate, all generated coins go into
# the same address, so we call twice to get two addresses w/50 each
node.generatetoaddress(nblocks=1, address=node.getnewaddress(label='coinbase'))
- node.generatetoaddress(nblocks=101, address=node.getnewaddress(label='coinbase'))
+ node.generatetoaddress(nblocks=COINBASE_MATURITY + 1, address=node.getnewaddress(label='coinbase'))
assert_equal(node.getbalance(), 100)
# there should be 2 address groups
@@ -104,7 +105,7 @@ class WalletLabelsTest(BitcoinTestFramework):
label.verify(node)
assert_equal(node.getreceivedbylabel(label.name), 2)
label.verify(node)
- node.generate(101)
+ node.generate(COINBASE_MATURITY + 1)
# Check that setlabel can assign a label to a new unused address.
for label in labels:
@@ -124,7 +125,7 @@ class WalletLabelsTest(BitcoinTestFramework):
label.add_address(multisig_address)
label.purpose[multisig_address] = "send"
label.verify(node)
- node.generate(101)
+ node.generate(COINBASE_MATURITY + 1)
# Check that setlabel can change the label of an address from a
# different label.
diff --git a/test/functional/wallet_listsinceblock.py b/test/functional/wallet_listsinceblock.py
index 448720530c..3899971bd7 100755
--- a/test/functional/wallet_listsinceblock.py
+++ b/test/functional/wallet_listsinceblock.py
@@ -5,6 +5,7 @@
"""Test the listsinceblock RPC."""
from test_framework.address import key_to_p2wpkh
+from test_framework.blocktools import COINBASE_MATURITY
from test_framework.key import ECKey
from test_framework.test_framework import BitcoinTestFramework
from test_framework.messages import BIP125_SEQUENCE_NUMBER
@@ -29,7 +30,7 @@ class ListSinceBlockTest(BitcoinTestFramework):
# All nodes are in IBD from genesis, so they'll need the miner (node2) to be an outbound connection, or have
# only one connection. (See fPreferredDownload in net_processing)
self.connect_nodes(1, 2)
- self.nodes[2].generate(101)
+ self.nodes[2].generate(COINBASE_MATURITY + 1)
self.sync_all()
self.test_no_blockhash()
diff --git a/test/functional/wallet_multiwallet.py b/test/functional/wallet_multiwallet.py
index 71d1b96a95..00d2c9ffe4 100755
--- a/test/functional/wallet_multiwallet.py
+++ b/test/functional/wallet_multiwallet.py
@@ -14,6 +14,7 @@ import stat
import time
from test_framework.authproxy import JSONRPCException
+from test_framework.blocktools import COINBASE_MATURITY
from test_framework.test_framework import BitcoinTestFramework
from test_framework.test_node import ErrorMatch
from test_framework.util import (
@@ -229,7 +230,7 @@ class MultiWalletTest(BitcoinTestFramework):
assert_raises_rpc_error(-19, "Wallet file not specified", node.getwalletinfo)
w1, w2, w3, w4, *_ = wallets
- node.generatetoaddress(nblocks=101, address=w1.getnewaddress())
+ node.generatetoaddress(nblocks=COINBASE_MATURITY + 1, address=w1.getnewaddress())
assert_equal(w1.getbalance(), 100)
assert_equal(w2.getbalance(), 0)
assert_equal(w3.getbalance(), 0)
diff --git a/test/functional/wallet_upgradewallet.py b/test/functional/wallet_upgradewallet.py
index fbc0f995d2..e7dd7592b6 100755
--- a/test/functional/wallet_upgradewallet.py
+++ b/test/functional/wallet_upgradewallet.py
@@ -17,6 +17,7 @@ import struct
from io import BytesIO
+from test_framework.blocktools import COINBASE_MATURITY
from test_framework.bdb import dump_bdb_kv
from test_framework.messages import deser_compact_size, deser_string
from test_framework.test_framework import BitcoinTestFramework
@@ -118,11 +119,11 @@ class UpgradeWalletTest(BitcoinTestFramework):
assert_equal(wallet.getwalletinfo()["walletversion"], previous_version)
def run_test(self):
- self.nodes[0].generatetoaddress(101, self.nodes[0].getnewaddress())
+ self.nodes[0].generatetoaddress(COINBASE_MATURITY + 1, self.nodes[0].getnewaddress())
self.dumb_sync_blocks()
# # Sanity check the test framework:
res = self.nodes[0].getblockchaininfo()
- assert_equal(res['blocks'], 101)
+ assert_equal(res['blocks'], COINBASE_MATURITY + 1)
node_master = self.nodes[0]
v16_3_node = self.nodes[1]
v15_2_node = self.nodes[2]
@@ -130,7 +131,7 @@ class UpgradeWalletTest(BitcoinTestFramework):
# Send coins to old wallets for later conversion checks.
v16_3_wallet = v16_3_node.get_wallet_rpc('wallet.dat')
v16_3_address = v16_3_wallet.getnewaddress()
- node_master.generatetoaddress(101, v16_3_address)
+ node_master.generatetoaddress(COINBASE_MATURITY + 1, v16_3_address)
self.dumb_sync_blocks()
v16_3_balance = v16_3_wallet.getbalance()
diff --git a/test/functional/wallet_watchonly.py b/test/functional/wallet_watchonly.py
index c345c382d0..6743c4a49b 100755
--- a/test/functional/wallet_watchonly.py
+++ b/test/functional/wallet_watchonly.py
@@ -5,6 +5,7 @@
"""Test createwallet watchonly arguments.
"""
+from test_framework.blocktools import COINBASE_MATURITY
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
assert_equal,
@@ -36,7 +37,7 @@ class CreateWalletWatchonlyTest(BitcoinTestFramework):
wo_wallet.importpubkey(pubkey=def_wallet.getaddressinfo(wo_change)['pubkey'])
# generate some btc for testing
- node.generatetoaddress(101, a1)
+ node.generatetoaddress(COINBASE_MATURITY + 1, a1)
# send 1 btc to our watch-only address
txid = def_wallet.sendtoaddress(wo_addr, 1)