Closes #29466.
removeprunedfunds only accepted a single txid, but the underlying CWallet::RemoveTxs already takes a vector and performs the removal in one atomic db transaction. This PR lets the RPC accept an array of txids so many transactions can be removed in a single wallet db transaction. A single txid string remains supported for backwards compatibility (via ParamFormat::JSON_OR_STRING in the bitcoin-cli conversion table, following the getblockstats hash_or_height precedent).
This adopts and reworks #29468 (by leo-aa88, credited as co-author) and addresses the feedback given there and in #32501:
Backwards compatibility (raised in #29468): a plain string is still accepted, both positionally and as a named argument. The argument is renamed
txid→txids; keeping atxidalias is not possible becauserpc_help.pyenforces that arguments namedtxidare plain strings API-wide.Performance justification (requested in #29468): benchmarked on regtest (macOS 26, arm64, SQLite wallet), removing imported pruned-funds transactions:
| method | N=250 | N=1000 | |---|---|---| | individual RPC calls | 0.031s | 0.129s | | one JSON-RPC batch of individual calls | 0.011s | 0.048s | | one array call (this PR) | 0.001s | 0.005s |
The JSON-RPC batch row addresses the "just use batch RPC calls" alternative raised in #29468: batching requests removes HTTP overhead, but the server still runs one wallet db txn per call — per the discussion in #29466, wallet db writes cannot be batched by batching RPC requests. The gains grow with wallet size and disk sync cost.
Atomicity documented and tested:
RemoveTxsruns within one db txn, so if any txid cannot be removed, none are. The functional test covers this (a failing array leaves the other transactions in place), plus empty-array and invalid-hex errors, and the legacy single-string form.
Testing done: wallet_importprunedfunds.py, wallet_resendwallettransactions.py, and rpc_help.py pass locally; all bitcoin-cli forms exercised manually (bare string, array of two, named txids=, empty array, invalid hex).
🤖 Generated with Claude Code