aboutsummaryrefslogtreecommitdiff
path: root/test/functional
diff options
context:
space:
mode:
Diffstat (limited to 'test/functional')
-rwxr-xr-xtest/functional/mempool_packages.py6
-rwxr-xr-xtest/functional/rpc_mempool_info.py102
-rwxr-xr-xtest/functional/test_runner.py1
3 files changed, 109 insertions, 0 deletions
diff --git a/test/functional/mempool_packages.py b/test/functional/mempool_packages.py
index 068fdc0b65..a2a2caf324 100755
--- a/test/functional/mempool_packages.py
+++ b/test/functional/mempool_packages.py
@@ -100,6 +100,12 @@ class MempoolPackagesTest(BitcoinTestFramework):
entry = self.nodes[0].getmempoolentry(x)
assert_equal(entry, mempool[x])
+ # Check that gettxspendingprevout is consistent with getrawmempool
+ witnesstx = self.nodes[0].gettransaction(txid=x, verbose=True)['decoded']
+ for tx_in in witnesstx["vin"]:
+ spending_result = self.nodes[0].gettxspendingprevout([ {'txid' : tx_in["txid"], 'vout' : tx_in["vout"]} ])
+ assert_equal(spending_result, [ {'txid' : tx_in["txid"], 'vout' : tx_in["vout"], 'spendingtxid' : x} ])
+
# Check that the descendant calculations are correct
assert_equal(entry['descendantcount'], descendant_count)
descendant_fees += entry['fees']['base']
diff --git a/test/functional/rpc_mempool_info.py b/test/functional/rpc_mempool_info.py
new file mode 100755
index 0000000000..cd7a48d387
--- /dev/null
+++ b/test/functional/rpc_mempool_info.py
@@ -0,0 +1,102 @@
+#!/usr/bin/env python3
+# Copyright (c) 2014-2022 The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+"""Test RPCs that retrieve information from the mempool."""
+
+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 import MiniWallet
+
+
+class RPCMempoolInfoTest(BitcoinTestFramework):
+ def set_test_params(self):
+ self.num_nodes = 1
+
+ def run_test(self):
+ self.wallet = MiniWallet(self.nodes[0])
+ self.generate(self.wallet, COINBASE_MATURITY + 1)
+ self.wallet.rescan_utxos()
+ confirmed_utxo = self.wallet.get_utxo()
+
+ # Create a tree of unconfirmed transactions in the mempool:
+ # txA
+ # / \
+ # / \
+ # / \
+ # / \
+ # / \
+ # txB txC
+ # / \ / \
+ # / \ / \
+ # txD txE txF txG
+ # \ /
+ # \ /
+ # txH
+
+ def create_tx(**kwargs):
+ return self.wallet.send_self_transfer_multi(
+ from_node=self.nodes[0],
+ **kwargs,
+ )
+
+ txA = create_tx(utxos_to_spend=[confirmed_utxo], num_outputs=2)
+ txB = create_tx(utxos_to_spend=[txA["new_utxos"][0]], num_outputs=2)
+ txC = create_tx(utxos_to_spend=[txA["new_utxos"][1]], num_outputs=2)
+ txD = create_tx(utxos_to_spend=[txB["new_utxos"][0]], num_outputs=1)
+ txE = create_tx(utxos_to_spend=[txB["new_utxos"][1]], num_outputs=1)
+ txF = create_tx(utxos_to_spend=[txC["new_utxos"][0]], num_outputs=2)
+ txG = create_tx(utxos_to_spend=[txC["new_utxos"][1]], num_outputs=1)
+ txH = create_tx(utxos_to_spend=[txE["new_utxos"][0],txF["new_utxos"][0]], num_outputs=1)
+ txidA, txidB, txidC, txidD, txidE, txidF, txidG, txidH = [
+ tx["txid"] for tx in [txA, txB, txC, txD, txE, txF, txG, txH]
+ ]
+
+ mempool = self.nodes[0].getrawmempool()
+ assert_equal(len(mempool), 8)
+ for txid in [txidA, txidB, txidC, txidD, txidE, txidF, txidG, txidH]:
+ assert_equal(txid in mempool, True)
+
+ self.log.info("Find transactions spending outputs")
+ result = self.nodes[0].gettxspendingprevout([ {'txid' : confirmed_utxo['txid'], 'vout' : 0}, {'txid' : txidA, 'vout' : 1} ])
+ assert_equal(result, [ {'txid' : confirmed_utxo['txid'], 'vout' : 0, 'spendingtxid' : txidA}, {'txid' : txidA, 'vout' : 1, 'spendingtxid' : txidC} ])
+
+ self.log.info("Find transaction spending multiple outputs")
+ result = self.nodes[0].gettxspendingprevout([ {'txid' : txidE, 'vout' : 0}, {'txid' : txidF, 'vout' : 0} ])
+ assert_equal(result, [ {'txid' : txidE, 'vout' : 0, 'spendingtxid' : txidH}, {'txid' : txidF, 'vout' : 0, 'spendingtxid' : txidH} ])
+
+ self.log.info("Find no transaction when output is unspent")
+ result = self.nodes[0].gettxspendingprevout([ {'txid' : txidH, 'vout' : 0} ])
+ assert_equal(result, [ {'txid' : txidH, 'vout' : 0} ])
+ result = self.nodes[0].gettxspendingprevout([ {'txid' : txidA, 'vout' : 5} ])
+ assert_equal(result, [ {'txid' : txidA, 'vout' : 5} ])
+
+ self.log.info("Mixed spent and unspent outputs")
+ result = self.nodes[0].gettxspendingprevout([ {'txid' : txidB, 'vout' : 0}, {'txid' : txidG, 'vout' : 3} ])
+ assert_equal(result, [ {'txid' : txidB, 'vout' : 0, 'spendingtxid' : txidD}, {'txid' : txidG, 'vout' : 3} ])
+
+ self.log.info("Unknown input fields")
+ assert_raises_rpc_error(-3, "Unexpected key unknown", self.nodes[0].gettxspendingprevout, [{'txid' : txidC, 'vout' : 1, 'unknown' : 42}])
+
+ self.log.info("Invalid vout provided")
+ assert_raises_rpc_error(-8, "Invalid parameter, vout cannot be negative", self.nodes[0].gettxspendingprevout, [{'txid' : txidA, 'vout' : -1}])
+
+ self.log.info("Invalid txid provided")
+ assert_raises_rpc_error(-3, "Expected type string for txid, got number", self.nodes[0].gettxspendingprevout, [{'txid' : 42, 'vout' : 0}])
+
+ self.log.info("Missing outputs")
+ assert_raises_rpc_error(-8, "Invalid parameter, outputs are missing", self.nodes[0].gettxspendingprevout, [])
+
+ self.log.info("Missing vout")
+ assert_raises_rpc_error(-3, "Missing vout", self.nodes[0].gettxspendingprevout, [{'txid' : txidA}])
+
+ self.log.info("Missing txid")
+ assert_raises_rpc_error(-3, "Missing txid", self.nodes[0].gettxspendingprevout, [{'vout' : 3}])
+
+
+if __name__ == '__main__':
+ RPCMempoolInfoTest().main()
diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py
index 7d6397d193..a27a0e2a63 100755
--- a/test/functional/test_runner.py
+++ b/test/functional/test_runner.py
@@ -329,6 +329,7 @@ BASE_SCRIPTS = [
'feature_settings.py',
'rpc_getdescriptorinfo.py',
'rpc_mempool_entry_fee_fields_deprecation.py',
+ 'rpc_mempool_info.py',
'rpc_help.py',
'feature_dirsymlinks.py',
'feature_help.py',