mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-09-06 18:01:09 +02:00
Merge bitcoin/bitcoin#32845: rpc, test: Fix JSON parsing errors in unloadwallet and getdescriptoractivity RPCs
c5c1960f93
doc: Add release notes for changes in RPCs (pablomartin4btc)90fd5acbe5
rpc, test: Fix error message in getdescriptoractivity (pablomartin4btc)39fef1d203
test: Add missing logging info for each test (pablomartin4btc)53ac704efd
rpc, test: Fix error message in unloadwallet (pablomartin4btc)1fc3a8e8e7
rpc, test: Add EnsureUniqueWalletName tests (pablomartin4btc)b635bc0896
rpc, util: Add EnsureUniqueWalletName (pablomartin4btc) Pull request description: Currently, `unloadwallet` RPC call fails with a JSON parsing error when no `wallet_name` argument is provided. This behavior is misleading because the error originates from a low-level JSON type mismatch, rather than clearly indicating that the wallet name or RPC endpoint (`-rpcwallet=...`) is missing. Also, found out that the [issue](https://github.com/bitcoin/bitcoin/pull/13111#issuecomment-398831543) was noticed during its implementation but never addressed. In addition, I've verified all RPC commands calls finding that `getdescriptoractivity` had the same problem, but related to the array input types (blockhashes & descriptors), so I've corrected that RPC as well. For consistency I've added the missing logging info for each test case in `test/functional/rpc_getdescriptoractivity.py` in preparation for the new test. **_-Before_** ``` ./build/bin/bitcoin-cli -regtest -datadir=/tmp/btc unloadwallet error code: -3 error message: JSON value of type number is not of expected type string ``` ``` ./build/bin/bitcoin-cli -regtest -datadir=/tmp/btc getdescriptoractivity error code: -3 error message: JSON value of type null is not of expected type array ``` ``` ./build/bin/bitcoin-cli -regtest -datadir=/tmp/btc getdescriptoractivity '[]' error code: -3 error message: JSON value of type null is not of expected type array ``` **_-After_** ``` ./build/bin/bitcoin-cli -regtest -datadir=/tmp/btc unloadwallet error code: -8 error message: Either the RPC endpoint wallet or the wallet name parameter must be provided ``` ``` ./build/bin/bitcoin-cli -regtest -datadir=/tmp/btc getdescriptoractivity error code: -1 error message: getdescriptoractivity ["blockhash",...] [scanobjects,...] ( include_mempool ) Get spend and receive activity associated with a set of descriptors for a set of blocks. This command pairs well with the `relevant_blocks` output of `scanblocks()`. This call may take several minutes. If you encounter timeouts, try specifying no RPC timeout (bitcoin-cli -rpcclienttimeout=0) Arguments: 1. blockhashes (json array, required) The list of blockhashes to examine for activity. Order doesn't matter. Must be along main chain or an error is thrown. [ "blockhash", (string) A valid blockhash ... ] 2. scanobjects (json array, required) Array of scan objects. Every scan object is either a string descriptor or an object: [ "descriptor", (string) An output descriptor { (json object) An object with output descriptor and metadata "desc": "str", (string, required) An output descriptor "range": n or [n,n], (numeric or array, optional, default=1000) The range of HD chain indexes to explore (either end or [begin,end]) }, ... ] 3. include_mempool (boolean, optional, default=true) Whether to include unconfirmed activity ... ``` ``` ./build/bin/bitcoin-cli -regtest -datadir=/tmp/btc getdescriptoractivity '[]' error code: -1 error message: getdescriptoractivity ["blockhash",...] [scanobjects,...] ( include_mempool ) ... ``` ACKs for top commit: achow101: ACKc5c1960f93
stickies-v: re-ACKc5c1960f93
furszy: ACKc5c1960f93
Tree-SHA512: e831ff1acbfd15d2ce3a69bb408cce94664c0b63b2aa2f4627a05c6c052241ae3b5cc238219ef1b30afb489a4a3f4c3030e2168b0c8f08b4d20805d050d810f5
This commit is contained in:
@@ -31,13 +31,16 @@ class GetBlocksActivityTest(BitcoinTestFramework):
|
||||
self.test_confirmed_and_unconfirmed(node, wallet)
|
||||
self.test_receive_then_spend(node, wallet)
|
||||
self.test_no_address(node, wallet)
|
||||
self.test_required_args(node)
|
||||
|
||||
def test_no_activity(self, node):
|
||||
self.log.info("Test that no activity is found for an unused address")
|
||||
_, _, addr_1 = getnewdestination()
|
||||
result = node.getdescriptoractivity([], [f"addr({addr_1})"], True)
|
||||
assert_equal(len(result['activity']), 0)
|
||||
|
||||
def test_activity_in_block(self, node, wallet):
|
||||
self.log.info("Test that receive activity is correctly reported in a mined block")
|
||||
_, spk_1, addr_1 = getnewdestination(address_type='bech32m')
|
||||
txid = wallet.send_to(from_node=node, scriptPubKey=spk_1, amount=1 * COIN)['txid']
|
||||
blockhash = self.generate(node, 1)[0]
|
||||
@@ -67,6 +70,7 @@ class GetBlocksActivityTest(BitcoinTestFramework):
|
||||
|
||||
|
||||
def test_no_mempool_inclusion(self, node, wallet):
|
||||
self.log.info("Test that mempool transactions are not included when include_mempool argument is False")
|
||||
_, spk_1, addr_1 = getnewdestination()
|
||||
wallet.send_to(from_node=node, scriptPubKey=spk_1, amount=1 * COIN)
|
||||
|
||||
@@ -81,6 +85,7 @@ class GetBlocksActivityTest(BitcoinTestFramework):
|
||||
assert_equal(len(result['activity']), 0)
|
||||
|
||||
def test_multiple_addresses(self, node, wallet):
|
||||
self.log.info("Test querying multiple addresses returns all activity correctly")
|
||||
_, spk_1, addr_1 = getnewdestination()
|
||||
_, spk_2, addr_2 = getnewdestination()
|
||||
wallet.send_to(from_node=node, scriptPubKey=spk_1, amount=1 * COIN)
|
||||
@@ -113,6 +118,7 @@ class GetBlocksActivityTest(BitcoinTestFramework):
|
||||
assert a2['amount'] == 2.0
|
||||
|
||||
def test_invalid_blockhash(self, node, wallet):
|
||||
self.log.info("Test that passing an invalid blockhash raises appropriate RPC error")
|
||||
self.generate(node, 20) # Generate to get more fees
|
||||
|
||||
_, spk_1, addr_1 = getnewdestination()
|
||||
@@ -125,6 +131,7 @@ class GetBlocksActivityTest(BitcoinTestFramework):
|
||||
node.getdescriptoractivity, [invalid_blockhash], [f"addr({addr_1})"], True)
|
||||
|
||||
def test_invalid_descriptor(self, node, wallet):
|
||||
self.log.info("Test that an invalid descriptor raises the correct RPC error")
|
||||
blockhash = self.generate(node, 1)[0]
|
||||
_, _, addr_1 = getnewdestination()
|
||||
|
||||
@@ -133,6 +140,7 @@ class GetBlocksActivityTest(BitcoinTestFramework):
|
||||
node.getdescriptoractivity, [blockhash], [f"addrx({addr_1})"], True)
|
||||
|
||||
def test_confirmed_and_unconfirmed(self, node, wallet):
|
||||
self.log.info("Test that both confirmed and unconfirmed transactions are reported correctly")
|
||||
self.generate(node, 20) # Generate to get more fees
|
||||
|
||||
_, spk_1, addr_1 = getnewdestination()
|
||||
@@ -162,6 +170,7 @@ class GetBlocksActivityTest(BitcoinTestFramework):
|
||||
|
||||
def test_receive_then_spend(self, node, wallet):
|
||||
"""Also important because this tests multiple blockhashes."""
|
||||
self.log.info("Test receive and spend activities across different blocks are reported consistently")
|
||||
self.generate(node, 20) # Generate to get more fees
|
||||
|
||||
sent1 = wallet.send_self_transfer(from_node=node)
|
||||
@@ -189,11 +198,13 @@ class GetBlocksActivityTest(BitcoinTestFramework):
|
||||
assert_equal(result, node.getdescriptoractivity(
|
||||
[blockhash_1, blockhash_2], [wallet.get_descriptor()], True))
|
||||
|
||||
self.log.info("Test that duplicated blockhash request does not report duplicated results")
|
||||
# Test that duplicating a blockhash yields the same result.
|
||||
assert_equal(result, node.getdescriptoractivity(
|
||||
[blockhash_1, blockhash_2, blockhash_2], [wallet.get_descriptor()], True))
|
||||
|
||||
def test_no_address(self, node, wallet):
|
||||
self.log.info("Test that activity is still reported for scripts without an associated address")
|
||||
raw_wallet = MiniWallet(self.nodes[0], mode=MiniWalletMode.RAW_P2PK)
|
||||
self.generate(raw_wallet, 100)
|
||||
|
||||
@@ -221,6 +232,11 @@ class GetBlocksActivityTest(BitcoinTestFramework):
|
||||
assert_equal(list(a2['output_spk'].keys()), ['asm', 'desc', 'hex', 'type'])
|
||||
assert a2['amount'] == Decimal(no_addr_tx["tx"].vout[0].nValue) / COIN
|
||||
|
||||
def test_required_args(self, node):
|
||||
self.log.info("Test that required arguments must be passed")
|
||||
assert_raises_rpc_error(-1, "getdescriptoractivity", node.getdescriptoractivity)
|
||||
assert_raises_rpc_error(-1, "getdescriptoractivity", node.getdescriptoractivity, [])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
GetBlocksActivityTest(__file__).main()
|
||||
|
@@ -524,8 +524,8 @@ class WalletMigrationTest(BitcoinTestFramework):
|
||||
def test_nonexistent(self):
|
||||
self.log.info("Check migratewallet errors for nonexistent wallets")
|
||||
default = self.master_node.get_wallet_rpc(self.default_wallet_name)
|
||||
assert_raises_rpc_error(-8, "RPC endpoint wallet and wallet_name parameter specify different wallets", default.migratewallet, "someotherwallet")
|
||||
assert_raises_rpc_error(-8, "Either RPC endpoint wallet or wallet_name parameter must be provided", self.master_node.migratewallet)
|
||||
assert_raises_rpc_error(-8, "The RPC endpoint wallet and the wallet name parameter specify different wallets", default.migratewallet, "someotherwallet")
|
||||
assert_raises_rpc_error(-8, "Either the RPC endpoint wallet or the wallet name parameter must be provided", self.master_node.migratewallet)
|
||||
assert_raises_rpc_error(-4, "Error: Wallet does not exist", self.master_node.migratewallet, "notawallet")
|
||||
|
||||
def test_unloaded_by_path(self):
|
||||
|
@@ -343,10 +343,10 @@ class MultiWalletTest(BitcoinTestFramework):
|
||||
self.log.info("Test dynamic wallet unloading")
|
||||
|
||||
# Test `unloadwallet` errors
|
||||
assert_raises_rpc_error(-3, "JSON value of type null is not of expected type string", self.nodes[0].unloadwallet)
|
||||
assert_raises_rpc_error(-8, "Either the RPC endpoint wallet or the wallet name parameter must be provided", self.nodes[0].unloadwallet)
|
||||
assert_raises_rpc_error(-18, "Requested wallet does not exist or is not loaded", self.nodes[0].unloadwallet, "dummy")
|
||||
assert_raises_rpc_error(-18, "Requested wallet does not exist or is not loaded", node.get_wallet_rpc("dummy").unloadwallet)
|
||||
assert_raises_rpc_error(-8, "RPC endpoint wallet and wallet_name parameter specify different wallets", w1.unloadwallet, "w2"),
|
||||
assert_raises_rpc_error(-8, "The RPC endpoint wallet and the wallet name parameter specify different wallets", w1.unloadwallet, "w2"),
|
||||
|
||||
# Successfully unload the specified wallet name
|
||||
self.nodes[0].unloadwallet("w1")
|
||||
|
Reference in New Issue
Block a user