This PR simplifies the argument parsing logic and resolves practical issues for bitcoin-cli and similar binaries (e.g. bitcoin-wallet) making their usage more consistent and predictable, enabling valid patterns such as mixing commands with wallet- or RPC-specific options—without relying on argument ordering quirks.
<details> <summary>What's changed in ArgsManager that allows the above.</summary>
Previously,
ArgsManagerstopped interpreting options once a non-option argument was encountered (non-GNU parsing). For example:bitcoind -a -b param -cwould ignore
-cbecause it followed the non-option argumentparam. In some cases '-c' is interpreted as an argument for 'param', producing unexpected behavior (eg empty arrays for listtransactions command).This PR changes the behavior so that options following non-option argument are recognized and processed (GNU parsing). This is needed for workflows for tools like CLI where command arguments may be followed by wallet- or RPC-specific options, e.g.:
bitcoin-cli -rpcwallet="" listtransactions -rpcwallet=mywallet bitcoin-cli getaddressinfo <address> -rpcwallet=mywallet(other binaries could also benefit from this change, e.g.
bitcoin-wallet)bitcoin-wallet create -wallet=newnameInvalid options passed after non-options will be treated as RPC arguments that begin with a
-character (so no behavioural change againstmaster), e.g.:bitcoin-cli -regtest -datadir=/tmp/btc createwallet -mywallet { "name": "-mywallet" }
</details>
<details><summary>Before and after outputs running RPC commands from <code>CLI</code>/ <code>bitcoin-cli</code>.</summary><ul> <li><details><summary>wallet commands using <code>CLI</code>:</summary><ul> <li><details><summary><code>getaddressinfo</code></summary><ul> <li>before/ <code>master</code>
./build_master/bin/bitcoin-cli -regtest -datadir=/tmp/btc getaddressinfo bcrt1qrnz5xlcwz5d85n3fag6v0vc4lryjc90jhqtpsh -rpcwallet=nonExistent
error message:
getaddressinfo "address"
...
</li> <li>after
./build/bin/bitcoin-cli -regtest -datadir=/tmp/btc getaddressinfo bcrt1qrnz5xlcwz5d85n3fag6v0vc4lryjc90jhqtpsh -rpcwallet=nonExistent
error code: -18
error message:
Requested wallet does not exist or is not loaded
</li> </ul></details></li> <li><details><summary><code>listtransactions</code></summary><ul> <li>before/ <code>master</code>
./build_master/bin/bitcoin-cli -regtest -datadir=/tmp/btc listtransactions -rpcwallet=nonExistent
[
]
</li> <li>after
./build/bin/bitcoin-cli -regtest -datadir=/tmp/btc listtransactions -rpcwallet=nonExistent
error code: -18
error message:
Requested wallet does not exist or is not loaded
</li> </ul></details></li> <li><details><summary>any command that needs an option to be specifed, it can be added at the end directly instead of before the command</summary><ul> <li>before/ <code>master</code>
./build_master/bin/bitcoin-cli -regtest -datadir=/tmp/btc listtransactions
error code: -19
error message:
Multiple wallets are loaded. Please select which wallet to use by requesting the RPC through the /wallet/<walletname> URI path. Or for the CLI, specify the "-rpcwallet=<walletname>" option before the command (run "bitcoin-cli -h" for help or "bitcoin-cli listwallets" to see which wallets are currently loaded).
./build_master/bin/bitcoin-cli -regtest -datadir=/tmp/btc listtransactions -rpcwallet=""
error code: -19
error message:
Multiple wallets are loaded. Please select which wallet to use by requesting the RPC through the /wallet/<walletname> URI path. Or for the CLI, specify the "-rpcwallet=<walletname>" option before the command (run "bitcoin-cli -h" for help or "bitcoin-cli listwallets" to see which wallets are currently loaded).
</li> <li>after
/build/bin/bitcoin-cli -regtest -datadir=/tmp/btc listtransactions -rpcwallet=""
[
{
"address": "bcrt1q5pqkrlfrp9rvsg43sxxagrees7r7ul6uyskhs4",
"parent_descs": [
"wpkh([76a11ab0/84h/1h/0h]tpubDCDCuyC1Rtm1weZ5kfBYtdchcmqa2t8db7M68wsPHbWhUrYnzFTrHu7ufVVRydt3FdWQy8iNmKbZYbgpWWcEKPAj896x53UbS6i2xRD1qct/0/*)#kuff3m9t"
],
"category": "immature",
"amount": 50.00000000,
"label": "",
...
</li> </ul></details></li> </ul></details></li> <li><details><summary>other binaries could benefit from it, e.g. <code>bitcoin-wallet:</code></summary><ul> <li><details><summary><code>create</code> command</summary><ul> <li>before/ <code>master</code>
./build_master/bin/bitcoin-wallet -regtest -datadir=/tmp/btc create
Wallet name must be provided when creating a new wallet.
(-wallet option has to be passed before the create command in order to work)
./build_master/bin/bitcoin-wallet -regtest -datadir=/tmp/btc create -wallet=newWalletName
Error: Additional arguments provided (-wallet=newWalletName). Methods do not take arguments. Please refer to `-help`.
</li> <li>after
./build/bin/bitcoin-wallet -regtest -datadir=/tmp/btc create -wallet=newWallet
Topping up keypool...
Wallet info
===========
Name: newWallet
Format: sqlite
Descriptors: yes
Encrypted: no
HD (hd seed available): yes
Keypool Size: 8000
Transactions: 0
Address Book: 0
</li> </ul></details></li> </ul></details></li> </ul> <!-- End --> </details>
-<ins>Notes</ins>:
<ins>Backwards compatibility</ins>: This PR is backward compatible in the sense that it allows new valid invocations that were previously rejected (failed or somehow ignored). In
master, any valid option following a command is treated as a positional argument. This can lead to unexpected RPC errors or help messages due to mismatched argument types. With this PR, those cases are parsed as proper options when applicable.bitcoin-clicontinues to accept RPC arguments that begin with a-character as currently inmaster(checkcreatewalletexample in "What's change in ArgsManager" section above).bitcoin-clicould distinguish between options that begin with single and double dashes, and treat options after the RPC method name that begin with double dashes as RPC named parameters (check example in 4th commit message body).Refactored both
ArgsManager::ProcessOptionKey(new function added in this PR) andArgsManager::ParseParametersin separated commits making the code clearer and the PR much easier to follow and review.