aboutsummaryrefslogtreecommitdiff
path: root/src/wallet
diff options
context:
space:
mode:
Diffstat (limited to 'src/wallet')
-rw-r--r--src/wallet/db.cpp39
-rw-r--r--src/wallet/db.h81
-rw-r--r--src/wallet/rpcdump.cpp148
-rw-r--r--src/wallet/rpcwallet.cpp564
-rw-r--r--src/wallet/wallet.cpp4
-rw-r--r--src/wallet/wallet.h16
6 files changed, 468 insertions, 384 deletions
diff --git a/src/wallet/db.cpp b/src/wallet/db.cpp
index 3677194a40..a2e795056a 100644
--- a/src/wallet/db.cpp
+++ b/src/wallet/db.cpp
@@ -263,6 +263,45 @@ BerkeleyEnvironment::VerifyResult BerkeleyEnvironment::Verify(const std::string&
return (fRecovered ? VerifyResult::RECOVER_OK : VerifyResult::RECOVER_FAIL);
}
+BerkeleyBatch::SafeDbt::SafeDbt()
+{
+ m_dbt.set_flags(DB_DBT_MALLOC);
+}
+
+BerkeleyBatch::SafeDbt::SafeDbt(void* data, size_t size)
+ : m_dbt(data, size)
+{
+}
+
+BerkeleyBatch::SafeDbt::~SafeDbt()
+{
+ if (m_dbt.get_data() != nullptr) {
+ // Clear memory, e.g. in case it was a private key
+ memory_cleanse(m_dbt.get_data(), m_dbt.get_size());
+ // under DB_DBT_MALLOC, data is malloced by the Dbt, but must be
+ // freed by the caller.
+ // https://docs.oracle.com/cd/E17275_01/html/api_reference/C/dbt.html
+ if (m_dbt.get_flags() & DB_DBT_MALLOC) {
+ free(m_dbt.get_data());
+ }
+ }
+}
+
+const void* BerkeleyBatch::SafeDbt::get_data() const
+{
+ return m_dbt.get_data();
+}
+
+u_int32_t BerkeleyBatch::SafeDbt::get_size() const
+{
+ return m_dbt.get_size();
+}
+
+BerkeleyBatch::SafeDbt::operator Dbt*()
+{
+ return &m_dbt;
+}
+
bool BerkeleyBatch::Recover(const fs::path& file_path, void *callbackDataIn, bool (*recoverKVcallback)(void* callbackData, CDataStream ssKey, CDataStream ssValue), std::string& newFilename)
{
std::string filename;
diff --git a/src/wallet/db.h b/src/wallet/db.h
index e453d441d7..9dc373c89b 100644
--- a/src/wallet/db.h
+++ b/src/wallet/db.h
@@ -191,10 +191,29 @@ private:
bool IsDummy() { return env == nullptr; }
};
-
/** RAII class that provides access to a Berkeley database */
class BerkeleyBatch
{
+ /** RAII class that automatically cleanses its data on destruction */
+ class SafeDbt final
+ {
+ Dbt m_dbt;
+
+ public:
+ // construct Dbt with internally-managed data
+ SafeDbt();
+ // construct Dbt with provided data
+ SafeDbt(void* data, size_t size);
+ ~SafeDbt();
+
+ // delegate to Dbt
+ const void* get_data() const;
+ u_int32_t get_size() const;
+
+ // conversion operator to access the underlying Dbt
+ operator Dbt*();
+ };
+
protected:
Db* pdb;
std::string strFile;
@@ -222,7 +241,6 @@ public:
/* verifies the database file */
static bool VerifyDatabaseFile(const fs::path& file_path, std::string& warningStr, std::string& errorStr, BerkeleyEnvironment::recoverFunc_type recoverFunc);
-public:
template <typename K, typename T>
bool Read(const K& key, T& value)
{
@@ -233,13 +251,11 @@ public:
CDataStream ssKey(SER_DISK, CLIENT_VERSION);
ssKey.reserve(1000);
ssKey << key;
- Dbt datKey(ssKey.data(), ssKey.size());
+ SafeDbt datKey(ssKey.data(), ssKey.size());
// Read
- Dbt datValue;
- datValue.set_flags(DB_DBT_MALLOC);
- int ret = pdb->get(activeTxn, &datKey, &datValue, 0);
- memory_cleanse(datKey.get_data(), datKey.get_size());
+ SafeDbt datValue;
+ int ret = pdb->get(activeTxn, datKey, datValue, 0);
bool success = false;
if (datValue.get_data() != nullptr) {
// Unserialize value
@@ -250,10 +266,6 @@ public:
} catch (const std::exception&) {
// In this case success remains 'false'
}
-
- // Clear and free memory
- memory_cleanse(datValue.get_data(), datValue.get_size());
- free(datValue.get_data());
}
return ret == 0 && success;
}
@@ -270,20 +282,16 @@ public:
CDataStream ssKey(SER_DISK, CLIENT_VERSION);
ssKey.reserve(1000);
ssKey << key;
- Dbt datKey(ssKey.data(), ssKey.size());
+ SafeDbt datKey(ssKey.data(), ssKey.size());
// Value
CDataStream ssValue(SER_DISK, CLIENT_VERSION);
ssValue.reserve(10000);
ssValue << value;
- Dbt datValue(ssValue.data(), ssValue.size());
+ SafeDbt datValue(ssValue.data(), ssValue.size());
// Write
- int ret = pdb->put(activeTxn, &datKey, &datValue, (fOverwrite ? 0 : DB_NOOVERWRITE));
-
- // Clear memory in case it was a private key
- memory_cleanse(datKey.get_data(), datKey.get_size());
- memory_cleanse(datValue.get_data(), datValue.get_size());
+ int ret = pdb->put(activeTxn, datKey, datValue, (fOverwrite ? 0 : DB_NOOVERWRITE));
return (ret == 0);
}
@@ -299,13 +307,10 @@ public:
CDataStream ssKey(SER_DISK, CLIENT_VERSION);
ssKey.reserve(1000);
ssKey << key;
- Dbt datKey(ssKey.data(), ssKey.size());
+ SafeDbt datKey(ssKey.data(), ssKey.size());
// Erase
- int ret = pdb->del(activeTxn, &datKey, 0);
-
- // Clear memory
- memory_cleanse(datKey.get_data(), datKey.get_size());
+ int ret = pdb->del(activeTxn, datKey, 0);
return (ret == 0 || ret == DB_NOTFOUND);
}
@@ -319,13 +324,10 @@ public:
CDataStream ssKey(SER_DISK, CLIENT_VERSION);
ssKey.reserve(1000);
ssKey << key;
- Dbt datKey(ssKey.data(), ssKey.size());
+ SafeDbt datKey(ssKey.data(), ssKey.size());
// Exists
- int ret = pdb->exists(activeTxn, &datKey, 0);
-
- // Clear memory
- memory_cleanse(datKey.get_data(), datKey.get_size());
+ int ret = pdb->exists(activeTxn, datKey, 0);
return (ret == 0);
}
@@ -340,20 +342,12 @@ public:
return pcursor;
}
- int ReadAtCursor(Dbc* pcursor, CDataStream& ssKey, CDataStream& ssValue, bool setRange = false)
+ int ReadAtCursor(Dbc* pcursor, CDataStream& ssKey, CDataStream& ssValue)
{
// Read at cursor
- Dbt datKey;
- unsigned int fFlags = DB_NEXT;
- if (setRange) {
- datKey.set_data(ssKey.data());
- datKey.set_size(ssKey.size());
- fFlags = DB_SET_RANGE;
- }
- Dbt datValue;
- datKey.set_flags(DB_DBT_MALLOC);
- datValue.set_flags(DB_DBT_MALLOC);
- int ret = pcursor->get(&datKey, &datValue, fFlags);
+ SafeDbt datKey;
+ SafeDbt datValue;
+ int ret = pcursor->get(datKey, datValue, DB_NEXT);
if (ret != 0)
return ret;
else if (datKey.get_data() == nullptr || datValue.get_data() == nullptr)
@@ -366,16 +360,9 @@ public:
ssValue.SetType(SER_DISK);
ssValue.clear();
ssValue.write((char*)datValue.get_data(), datValue.get_size());
-
- // Clear and free memory
- memory_cleanse(datKey.get_data(), datKey.get_size());
- memory_cleanse(datValue.get_data(), datValue.get_size());
- free(datKey.get_data());
- free(datValue.get_data());
return 0;
}
-public:
bool TxnBegin()
{
if (!pdb || activeTxn)
diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp
index c24703968d..2e62a6979f 100644
--- a/src/wallet/rpcdump.cpp
+++ b/src/wallet/rpcdump.cpp
@@ -111,16 +111,16 @@ UniValue importprivkey(const JSONRPCRequest& request)
throw std::runtime_error(
RPCHelpMan{"importprivkey",
"\nAdds a private key (as returned by dumpprivkey) to your wallet. Requires a new wallet backup.\n"
- "Hint: use importmulti to import more than one private key.\n",
+ "Hint: use importmulti to import more than one private key.\n"
+ "\nNote: This call can take over an hour to complete if rescan is true, during that time, other rpc calls\n"
+ "may report that the imported key exists but related transactions are still missing, leading to temporarily incorrect/bogus balances and unspent outputs until rescan completes.\n",
{
{"privkey", RPCArg::Type::STR, /* opt */ false, /* default_val */ "", "The private key (see dumpprivkey)"},
{"label", RPCArg::Type::STR, /* opt */ true, /* default_val */ "current label if address exists, otherwise \"\"", "An optional label"},
{"rescan", RPCArg::Type::BOOL, /* opt */ true, /* default_val */ "true", "Rescan the wallet for transactions"},
- }}
- .ToString() +
- "\nNote: This call can take over an hour to complete if rescan is true, during that time, other rpc calls\n"
- "may report that the imported key exists but related transactions are still missing, leading to temporarily incorrect/bogus balances and unspent outputs until rescan completes.\n"
- "\nExamples:\n"
+ },
+ RPCResults{},
+ RPCExamples{
"\nDump a private key\n"
+ HelpExampleCli("dumpprivkey", "\"myaddress\"") +
"\nImport the private key with rescan\n"
@@ -131,7 +131,8 @@ UniValue importprivkey(const JSONRPCRequest& request)
+ HelpExampleCli("importprivkey", "\"mykey\" \"\" false") +
"\nAs a JSON-RPC call\n"
+ HelpExampleRpc("importprivkey", "\"mykey\", \"testing\", false")
- );
+ },
+ }.ToString());
WalletRescanReserver reserver(pwallet);
@@ -209,16 +210,18 @@ UniValue abortrescan(const JSONRPCRequest& request)
if (request.fHelp || request.params.size() > 0)
throw std::runtime_error(
RPCHelpMan{"abortrescan",
- "\nStops current wallet rescan triggered by an RPC call, e.g. by an importprivkey call.\n", {}}
- .ToString() +
- "\nExamples:\n"
+ "\nStops current wallet rescan triggered by an RPC call, e.g. by an importprivkey call.\n",
+ {},
+ RPCResults{},
+ RPCExamples{
"\nImport a private key\n"
+ HelpExampleCli("importprivkey", "\"mykey\"") +
"\nAbort the running wallet rescan\n"
+ HelpExampleCli("abortrescan", "") +
"\nAs a JSON-RPC call\n"
+ HelpExampleRpc("abortrescan", "")
- );
+ },
+ }.ToString());
if (!pwallet->IsScanning() || pwallet->IsAbortingRescan()) return false;
pwallet->AbortRescan();
@@ -272,27 +275,28 @@ UniValue importaddress(const JSONRPCRequest& request)
if (request.fHelp || request.params.size() < 1 || request.params.size() > 4)
throw std::runtime_error(
RPCHelpMan{"importaddress",
- "\nAdds an address or script (in hex) that can be watched as if it were in your wallet but cannot be used to spend. Requires a new wallet backup.\n",
+ "\nAdds an address or script (in hex) that can be watched as if it were in your wallet but cannot be used to spend. Requires a new wallet backup.\n"
+ "\nNote: This call can take over an hour to complete if rescan is true, during that time, other rpc calls\n"
+ "may report that the imported address exists but related transactions are still missing, leading to temporarily incorrect/bogus balances and unspent outputs until rescan completes.\n"
+ "If you have the full public key, you should call importpubkey instead of this.\n"
+ "\nNote: If you import a non-standard raw script in hex form, outputs sending to it will be treated\n"
+ "as change, and not show up in many RPCs.\n",
{
{"address", RPCArg::Type::STR, /* opt */ false, /* default_val */ "", "The Bitcoin address (or hex-encoded script)"},
{"label", RPCArg::Type::STR, /* opt */ true, /* default_val */ "\"\"", "An optional label"},
{"rescan", RPCArg::Type::BOOL, /* opt */ true, /* default_val */ "true", "Rescan the wallet for transactions"},
{"p2sh", RPCArg::Type::BOOL, /* opt */ true, /* default_val */ "false", "Add the P2SH version of the script as well"},
- }}
- .ToString() +
- "\nNote: This call can take over an hour to complete if rescan is true, during that time, other rpc calls\n"
- "may report that the imported address exists but related transactions are still missing, leading to temporarily incorrect/bogus balances and unspent outputs until rescan completes.\n"
- "If you have the full public key, you should call importpubkey instead of this.\n"
- "\nNote: If you import a non-standard raw script in hex form, outputs sending to it will be treated\n"
- "as change, and not show up in many RPCs.\n"
- "\nExamples:\n"
+ },
+ RPCResults{},
+ RPCExamples{
"\nImport an address with rescan\n"
+ HelpExampleCli("importaddress", "\"myaddress\"") +
"\nImport using a label without rescan\n"
+ HelpExampleCli("importaddress", "\"myaddress\" \"testing\" false") +
"\nAs a JSON-RPC call\n"
+ HelpExampleRpc("importaddress", "\"myaddress\", \"testing\", false")
- );
+ },
+ }.ToString());
std::string strLabel;
@@ -358,8 +362,10 @@ UniValue importprunedfunds(const JSONRPCRequest& request)
{
{"rawtransaction", RPCArg::Type::STR_HEX, /* opt */ false, /* default_val */ "", "A raw transaction in hex funding an already-existing address in wallet"},
{"txoutproof", RPCArg::Type::STR_HEX, /* opt */ false, /* default_val */ "", "The hex output from gettxoutproof that contains the transaction"},
- }}
- .ToString()
+ },
+ RPCResults{},
+ RPCExamples{""},
+ }.ToString()
);
CMutableTransaction tx;
@@ -422,13 +428,14 @@ UniValue removeprunedfunds(const JSONRPCRequest& request)
"\nDeletes the specified transaction from the wallet. Meant for use with pruned wallets and as a companion to importprunedfunds. This will affect wallet balances.\n",
{
{"txid", RPCArg::Type::STR_HEX, /* opt */ false, /* default_val */ "", "The hex-encoded id of the transaction you are deleting"},
- }}
- .ToString() +
- "\nExamples:\n"
- + HelpExampleCli("removeprunedfunds", "\"a8d0c0184dde994a09ec054286f1ce581bebf46446a512166eae7628734ea0a5\"") +
+ },
+ RPCResults{},
+ RPCExamples{
+ HelpExampleCli("removeprunedfunds", "\"a8d0c0184dde994a09ec054286f1ce581bebf46446a512166eae7628734ea0a5\"") +
"\nAs a JSON-RPC call\n"
+ HelpExampleRpc("removeprunedfunds", "\"a8d0c0184dde994a09ec054286f1ce581bebf46446a512166eae7628734ea0a5\"")
- );
+ },
+ }.ToString());
auto locked_chain = pwallet->chain().lock();
LOCK(pwallet->cs_wallet);
@@ -460,23 +467,24 @@ UniValue importpubkey(const JSONRPCRequest& request)
if (request.fHelp || request.params.size() < 1 || request.params.size() > 3)
throw std::runtime_error(
RPCHelpMan{"importpubkey",
- "\nAdds a public key (in hex) that can be watched as if it were in your wallet but cannot be used to spend. Requires a new wallet backup.\n",
+ "\nAdds a public key (in hex) that can be watched as if it were in your wallet but cannot be used to spend. Requires a new wallet backup.\n"
+ "\nNote: This call can take over an hour to complete if rescan is true, during that time, other rpc calls\n"
+ "may report that the imported pubkey exists but related transactions are still missing, leading to temporarily incorrect/bogus balances and unspent outputs until rescan completes.\n",
{
{"pubkey", RPCArg::Type::STR, /* opt */ false, /* default_val */ "", "The hex-encoded public key"},
{"label", RPCArg::Type::STR, /* opt */ true, /* default_val */ "\"\"", "An optional label"},
{"rescan", RPCArg::Type::BOOL, /* opt */ true, /* default_val */ "true", "Rescan the wallet for transactions"},
- }}
- .ToString() +
- "\nNote: This call can take over an hour to complete if rescan is true, during that time, other rpc calls\n"
- "may report that the imported pubkey exists but related transactions are still missing, leading to temporarily incorrect/bogus balances and unspent outputs until rescan completes.\n"
- "\nExamples:\n"
+ },
+ RPCResults{},
+ RPCExamples{
"\nImport a public key with rescan\n"
+ HelpExampleCli("importpubkey", "\"mypubkey\"") +
"\nImport using a label without rescan\n"
+ HelpExampleCli("importpubkey", "\"mypubkey\" \"testing\" false") +
"\nAs a JSON-RPC call\n"
+ HelpExampleRpc("importpubkey", "\"mypubkey\", \"testing\", false")
- );
+ },
+ }.ToString());
std::string strLabel;
@@ -537,16 +545,17 @@ UniValue importwallet(const JSONRPCRequest& request)
"\nImports keys from a wallet dump file (see dumpwallet). Requires a new wallet backup to include imported keys.\n",
{
{"filename", RPCArg::Type::STR, /* opt */ false, /* default_val */ "", "The wallet file"},
- }}
- .ToString() +
- "\nExamples:\n"
+ },
+ RPCResults{},
+ RPCExamples{
"\nDump the wallet\n"
+ HelpExampleCli("dumpwallet", "\"test\"") +
"\nImport the wallet\n"
+ HelpExampleCli("importwallet", "\"test\"") +
"\nImport using the json rpc call\n"
+ HelpExampleRpc("importwallet", "\"test\"")
- );
+ },
+ }.ToString());
if (fPruneMode)
throw JSONRPCError(RPC_WALLET_ERROR, "Importing wallets is disabled in pruned mode");
@@ -671,15 +680,16 @@ UniValue dumpprivkey(const JSONRPCRequest& request)
"Then the importprivkey can be used with this output\n",
{
{"address", RPCArg::Type::STR, /* opt */ false, /* default_val */ "", "The bitcoin address for the private key"},
- }}
- .ToString() +
- "\nResult:\n"
+ },
+ RPCResult{
"\"key\" (string) The private key\n"
- "\nExamples:\n"
- + HelpExampleCli("dumpprivkey", "\"myaddress\"")
+ },
+ RPCExamples{
+ HelpExampleCli("dumpprivkey", "\"myaddress\"")
+ HelpExampleCli("importprivkey", "\"mykey\"")
+ HelpExampleRpc("dumpprivkey", "\"myaddress\"")
- );
+ },
+ }.ToString());
auto locked_chain = pwallet->chain().lock();
LOCK(pwallet->cs_wallet);
@@ -720,16 +730,17 @@ UniValue dumpwallet(const JSONRPCRequest& request)
"only backing up the seed itself, and must be backed up too (e.g. ensure you back up the whole dumpfile).\n",
{
{"filename", RPCArg::Type::STR, /* opt */ false, /* default_val */ "", "The filename with path (either absolute or relative to bitcoind)"},
- }}
- .ToString() +
- "\nResult:\n"
+ },
+ RPCResult{
"{ (json object)\n"
" \"filename\" : { (string) The filename with full absolute path\n"
"}\n"
- "\nExamples:\n"
- + HelpExampleCli("dumpwallet", "\"test\"")
+ },
+ RPCExamples{
+ HelpExampleCli("dumpwallet", "\"test\"")
+ HelpExampleRpc("dumpwallet", "\"test\"")
- );
+ },
+ }.ToString());
auto locked_chain = pwallet->chain().lock();
LOCK(pwallet->cs_wallet);
@@ -850,9 +861,9 @@ struct ImportData
enum class ScriptContext
{
- TOP, //! Top-level scriptPubKey
- P2SH, //! P2SH redeemScript
- WITNESS_V0, //! P2WSH witnessScript
+ TOP, //!< Top-level scriptPubKey
+ P2SH, //!< P2SH redeemScript
+ WITNESS_V0, //!< P2WSH witnessScript
};
// Analyse the provided scriptPubKey, determining which keys and which redeem scripts from the ImportData struct are needed to spend it, and mark them as used.
@@ -1149,7 +1160,11 @@ UniValue importmulti(const JSONRPCRequest& mainRequest)
if (mainRequest.fHelp || mainRequest.params.size() < 1 || mainRequest.params.size() > 2)
throw std::runtime_error(
RPCHelpMan{"importmulti",
- "\nImport addresses/scripts (with private or public keys, redeem script (P2SH)), rescanning all addresses in one-shot-only (rescan can be disabled via options). Requires a new wallet backup.\n",
+ "\nImport addresses/scripts (with private or public keys, redeem script (P2SH)), optionally rescanning the blockchain from the earliest creation time of the imported scripts. Requires a new wallet backup.\n"
+ "If an address/script is imported without all of the private keys required to spend from that address, it will be watchonly. The 'watchonly' option must be set to true in this case or a warning will be returned.\n"
+ "Conversely, if all the private keys are provided and the address/script is spendable, the watchonly option must be set to false, or a warning will be returned.\n"
+ "\nNote: This call can take over an hour to complete if rescan is true, during that time, other rpc calls\n"
+ "may report that the imported keys, addresses or scripts exists but related transactions are still missing.\n",
{
{"requests", RPCArg::Type::ARR, /* opt */ false, /* default_val */ "", "Data to be imported",
{
@@ -1179,7 +1194,7 @@ UniValue importmulti(const JSONRPCRequest& mainRequest)
}
},
{"internal", RPCArg::Type::BOOL, /* opt */ true, /* default_val */ "false", "Stating whether matching outputs should be treated as not incoming payments (also known as change)"},
- {"watchonly", RPCArg::Type::BOOL, /* opt */ true, /* default_val */ "false", "Stating whether matching outputs should be considered watched even when not all private keys are provided."},
+ {"watchonly", RPCArg::Type::BOOL, /* opt */ true, /* default_val */ "false", "Stating whether matching outputs should be considered watchonly."},
{"label", RPCArg::Type::STR, /* opt */ true, /* default_val */ "''", "Label to assign to the address, only allowed with internal=false"},
},
},
@@ -1190,17 +1205,18 @@ UniValue importmulti(const JSONRPCRequest& mainRequest)
{"rescan", RPCArg::Type::BOOL, /* opt */ true, /* default_val */ "true", "Stating if should rescan the blockchain after all imports"},
},
"\"options\""},
- }}
- .ToString() +
- "\nNote: This call can take over an hour to complete if rescan is true, during that time, other rpc calls\n"
- "may report that the imported keys, addresses or scripts exists but related transactions are still missing.\n"
- "\nExamples:\n" +
- HelpExampleCli("importmulti", "'[{ \"scriptPubKey\": { \"address\": \"<my address>\" }, \"timestamp\":1455191478 }, "
- "{ \"scriptPubKey\": { \"address\": \"<my 2nd address>\" }, \"label\": \"example 2\", \"timestamp\": 1455191480 }]'") +
- HelpExampleCli("importmulti", "'[{ \"scriptPubKey\": { \"address\": \"<my address>\" }, \"timestamp\":1455191478 }]' '{ \"rescan\": false}'") +
-
+ },
+ RPCResult{
"\nResponse is an array with the same size as the input that has the execution result :\n"
- " [{\"success\": true}, {\"success\": true, \"warnings\": [\"Ignoring irrelevant private key\"]}, {\"success\": false, \"error\": {\"code\": -1, \"message\": \"Internal Server Error\"}}, ...]\n");
+ " [{\"success\": true}, {\"success\": true, \"warnings\": [\"Ignoring irrelevant private key\"]}, {\"success\": false, \"error\": {\"code\": -1, \"message\": \"Internal Server Error\"}}, ...]\n"
+ },
+ RPCExamples{
+ HelpExampleCli("importmulti", "'[{ \"scriptPubKey\": { \"address\": \"<my address>\" }, \"timestamp\":1455191478 }, "
+ "{ \"scriptPubKey\": { \"address\": \"<my 2nd address>\" }, \"label\": \"example 2\", \"timestamp\": 1455191480 }]'") +
+ HelpExampleCli("importmulti", "'[{ \"scriptPubKey\": { \"address\": \"<my address>\" }, \"timestamp\":1455191478 }]' '{ \"rescan\": false}'")
+ },
+ }.ToString()
+ );
RPCTypeCheck(mainRequest.params, {UniValue::VARR, UniValue::VOBJ});
diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp
index 32173a92d0..270a61ade8 100644
--- a/src/wallet/rpcwallet.cpp
+++ b/src/wallet/rpcwallet.cpp
@@ -160,14 +160,15 @@ static UniValue getnewaddress(const JSONRPCRequest& request)
{
{"label", RPCArg::Type::STR, /* opt */ true, /* default_val */ "null", "The label name for the address to be linked to. If not provided, the default label \"\" is used. It can also be set to the empty string \"\" to represent the default label. The label does not need to exist, it will be created if there is no label by the given name."},
{"address_type", RPCArg::Type::STR, /* opt */ true, /* default_val */ "set by -addresstype", "The address type to use. Options are \"legacy\", \"p2sh-segwit\", and \"bech32\"."},
- }}
- .ToString() +
- "\nResult:\n"
+ },
+ RPCResult{
"\"address\" (string) The new bitcoin address\n"
- "\nExamples:\n"
- + HelpExampleCli("getnewaddress", "")
+ },
+ RPCExamples{
+ HelpExampleCli("getnewaddress", "")
+ HelpExampleRpc("getnewaddress", "")
- );
+ },
+ }.ToString());
if (pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Error: Private keys are disabled for this wallet");
@@ -220,14 +221,15 @@ static UniValue getrawchangeaddress(const JSONRPCRequest& request)
"This is for use with raw transactions, NOT normal use.\n",
{
{"address_type", RPCArg::Type::STR, /* opt */ true, /* default_val */ "set by -changetype", "The address type to use. Options are \"legacy\", \"p2sh-segwit\", and \"bech32\"."},
- }}
- .ToString() +
- "\nResult:\n"
+ },
+ RPCResult{
"\"address\" (string) The address\n"
- "\nExamples:\n"
- + HelpExampleCli("getrawchangeaddress", "")
+ },
+ RPCExamples{
+ HelpExampleCli("getrawchangeaddress", "")
+ HelpExampleRpc("getrawchangeaddress", "")
- );
+ },
+ }.ToString());
if (pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Error: Private keys are disabled for this wallet");
@@ -276,12 +278,13 @@ static UniValue setlabel(const JSONRPCRequest& request)
{
{"address", RPCArg::Type::STR, /* opt */ false, /* default_val */ "", "The bitcoin address to be associated with a label."},
{"label", RPCArg::Type::STR, /* opt */ false, /* default_val */ "", "The label to assign to the address."},
- }}
- .ToString() +
- "\nExamples:\n"
- + HelpExampleCli("setlabel", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" \"tabby\"")
+ },
+ RPCResults{},
+ RPCExamples{
+ HelpExampleCli("setlabel", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" \"tabby\"")
+ HelpExampleRpc("setlabel", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\", \"tabby\"")
- );
+ },
+ }.ToString());
LOCK(pwallet->cs_wallet);
@@ -372,16 +375,17 @@ static UniValue sendtoaddress(const JSONRPCRequest& request)
" \"UNSET\"\n"
" \"ECONOMICAL\"\n"
" \"CONSERVATIVE\""},
- }}
- .ToString() +
- "\nResult:\n"
+ },
+ RPCResult{
"\"txid\" (string) The transaction id.\n"
- "\nExamples:\n"
- + HelpExampleCli("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.1")
+ },
+ RPCExamples{
+ HelpExampleCli("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.1")
+ HelpExampleCli("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.1 \"donation\" \"seans outpost\"")
+ HelpExampleCli("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.1 \"\" \"\" true")
+ HelpExampleRpc("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\", 0.1, \"donation\", \"seans outpost\"")
- );
+ },
+ }.ToString());
// Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now
@@ -449,9 +453,8 @@ static UniValue listaddressgroupings(const JSONRPCRequest& request)
"\nLists groups of addresses which have had their common ownership\n"
"made public by common use as inputs or as the resulting change\n"
"in past transactions\n",
- {}}
- .ToString() +
- "\nResult:\n"
+ {},
+ RPCResult{
"[\n"
" [\n"
" [\n"
@@ -463,10 +466,12 @@ static UniValue listaddressgroupings(const JSONRPCRequest& request)
" ]\n"
" ,...\n"
"]\n"
- "\nExamples:\n"
- + HelpExampleCli("listaddressgroupings", "")
+ },
+ RPCExamples{
+ HelpExampleCli("listaddressgroupings", "")
+ HelpExampleRpc("listaddressgroupings", "")
- );
+ },
+ }.ToString());
// Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now
@@ -513,11 +518,11 @@ static UniValue signmessage(const JSONRPCRequest& request)
{
{"address", RPCArg::Type::STR, /* opt */ false, /* default_val */ "", "The bitcoin address to use for the private key."},
{"message", RPCArg::Type::STR, /* opt */ false, /* default_val */ "", "The message to create a signature of."},
- }}
- .ToString() +
- "\nResult:\n"
+ },
+ RPCResult{
"\"signature\" (string) The signature of the message encoded in base 64\n"
- "\nExamples:\n"
+ },
+ RPCExamples{
"\nUnlock the wallet for 30 seconds\n"
+ HelpExampleCli("walletpassphrase", "\"mypassphrase\" 30") +
"\nCreate the signature\n"
@@ -526,7 +531,8 @@ static UniValue signmessage(const JSONRPCRequest& request)
+ HelpExampleCli("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" \"signature\" \"my message\"") +
"\nAs a JSON-RPC call\n"
+ HelpExampleRpc("signmessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\", \"my message\"")
- );
+ },
+ }.ToString());
auto locked_chain = pwallet->chain().lock();
LOCK(pwallet->cs_wallet);
@@ -578,11 +584,11 @@ static UniValue getreceivedbyaddress(const JSONRPCRequest& request)
{
{"address", RPCArg::Type::STR, /* opt */ false, /* default_val */ "", "The bitcoin address for transactions."},
{"minconf", RPCArg::Type::NUM, /* opt */ true, /* default_val */ "1", "Only include transactions confirmed at least this many times."},
- }}
- .ToString() +
- "\nResult:\n"
+ },
+ RPCResult{
"amount (numeric) The total amount in " + CURRENCY_UNIT + " received at this address.\n"
- "\nExamples:\n"
+ },
+ RPCExamples{
"\nThe amount from transactions with at least 1 confirmation\n"
+ HelpExampleCli("getreceivedbyaddress", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\"") +
"\nThe amount including unconfirmed transactions, zero confirmations\n"
@@ -591,7 +597,8 @@ static UniValue getreceivedbyaddress(const JSONRPCRequest& request)
+ HelpExampleCli("getreceivedbyaddress", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" 6") +
"\nAs a JSON-RPC call\n"
+ HelpExampleRpc("getreceivedbyaddress", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\", 6")
- );
+ },
+ }.ToString());
// Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now
@@ -649,11 +656,11 @@ static UniValue getreceivedbylabel(const JSONRPCRequest& request)
{
{"label", RPCArg::Type::STR, /* opt */ false, /* default_val */ "", "The selected label, may be the default label using \"\"."},
{"minconf", RPCArg::Type::NUM, /* opt */ true, /* default_val */ "1", "Only include transactions confirmed at least this many times."},
- }}
- .ToString() +
- "\nResult:\n"
+ },
+ RPCResult{
"amount (numeric) The total amount in " + CURRENCY_UNIT + " received for this label.\n"
- "\nExamples:\n"
+ },
+ RPCExamples{
"\nAmount received by the default label with at least 1 confirmation\n"
+ HelpExampleCli("getreceivedbylabel", "\"\"") +
"\nAmount received at the tabby label including unconfirmed amounts with zero confirmations\n"
@@ -662,7 +669,8 @@ static UniValue getreceivedbylabel(const JSONRPCRequest& request)
+ HelpExampleCli("getreceivedbylabel", "\"tabby\" 6") +
"\nAs a JSON-RPC call\n"
+ HelpExampleRpc("getreceivedbylabel", "\"tabby\", 6")
- );
+ },
+ }.ToString());
// Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now
@@ -721,18 +729,19 @@ static UniValue getbalance(const JSONRPCRequest& request)
{"dummy", RPCArg::Type::STR, /* opt */ true, /* default_val */ "null", "Remains for backward compatibility. Must be excluded or set to \"*\"."},
{"minconf", RPCArg::Type::NUM, /* opt */ true, /* default_val */ "0", "Only include transactions confirmed at least this many times."},
{"include_watchonly", RPCArg::Type::BOOL, /* opt */ true, /* default_val */ "false", "Also include balance in watch-only addresses (see 'importaddress')"},
- }}
- .ToString() +
- "\nResult:\n"
+ },
+ RPCResult{
"amount (numeric) The total amount in " + CURRENCY_UNIT + " received for this wallet.\n"
- "\nExamples:\n"
+ },
+ RPCExamples{
"\nThe total amount in the wallet with 1 or more confirmations\n"
+ HelpExampleCli("getbalance", "") +
"\nThe total amount in the wallet at least 6 blocks confirmed\n"
+ HelpExampleCli("getbalance", "\"*\" 6") +
"\nAs a JSON-RPC call\n"
+ HelpExampleRpc("getbalance", "\"*\", 6")
- );
+ },
+ }.ToString());
// Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now
@@ -771,8 +780,11 @@ static UniValue getunconfirmedbalance(const JSONRPCRequest &request)
if (request.fHelp || request.params.size() > 0)
throw std::runtime_error(
RPCHelpMan{"getunconfirmedbalance",
- "Returns the server's total unconfirmed balance\n", {}}
- .ToString());
+ "Returns the server's total unconfirmed balance\n",
+ {},
+ RPCResults{},
+ RPCExamples{""},
+ }.ToString());
// Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now
@@ -822,12 +834,12 @@ static UniValue sendmany(const JSONRPCRequest& request)
" \"UNSET\"\n"
" \"ECONOMICAL\"\n"
" \"CONSERVATIVE\""},
- }}
- .ToString() +
- "\nResult:\n"
+ },
+ RPCResult{
"\"txid\" (string) The transaction id for the send. Only 1 transaction is created regardless of \n"
" the number of addresses.\n"
- "\nExamples:\n"
+ },
+ RPCExamples{
"\nSend two amounts to two different addresses:\n"
+ HelpExampleCli("sendmany", "\"\" \"{\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\\\":0.01,\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\"") +
"\nSend two amounts to two different addresses setting the confirmation and comment:\n"
@@ -836,7 +848,8 @@ static UniValue sendmany(const JSONRPCRequest& request)
+ HelpExampleCli("sendmany", "\"\" \"{\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\\\":0.01,\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\" 1 \"\" \"[\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\\\",\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\"]\"") +
"\nAs a JSON-RPC call\n"
+ HelpExampleRpc("sendmany", "\"\", {\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\":0.01,\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\":0.02}, 6, \"testing\"")
- );
+ },
+ }.ToString());
// Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now
@@ -967,19 +980,20 @@ static UniValue addmultisigaddress(const JSONRPCRequest& request)
},
{"label", RPCArg::Type::STR, /* opt */ true, /* default_val */ "null", "A label to assign the addresses to."},
{"address_type", RPCArg::Type::STR, /* opt */ true, /* default_val */ "set by -addresstype", "The address type to use. Options are \"legacy\", \"p2sh-segwit\", and \"bech32\"."},
- }}
- .ToString() +
- "\nResult:\n"
+ },
+ RPCResult{
"{\n"
" \"address\":\"multisigaddress\", (string) The value of the new multisig address.\n"
" \"redeemScript\":\"script\" (string) The string value of the hex-encoded redemption script.\n"
"}\n"
- "\nExamples:\n"
+ },
+ RPCExamples{
"\nAdd a multisig address from 2 addresses\n"
+ HelpExampleCli("addmultisigaddress", "2 \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"") +
"\nAs a JSON-RPC call\n"
+ HelpExampleRpc("addmultisigaddress", "2, \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"")
- ;
+ },
+ }.ToString();
throw std::runtime_error(msg);
}
@@ -1196,9 +1210,8 @@ static UniValue listreceivedbyaddress(const JSONRPCRequest& request)
{"include_empty", RPCArg::Type::BOOL, /* opt */ true, /* default_val */ "false", "Whether to include addresses that haven't received any payments."},
{"include_watchonly", RPCArg::Type::BOOL, /* opt */ true, /* default_val */ "false", "Whether to include watch-only addresses (see 'importaddress')."},
{"address_filter", RPCArg::Type::STR, /* opt */ true, /* default_val */ "null", "If present, only return information on this address."},
- }}
- .ToString() +
- "\nResult:\n"
+ },
+ RPCResult{
"[\n"
" {\n"
" \"involvesWatchonly\" : true, (bool) Only returned if imported addresses were involved in transaction\n"
@@ -1213,13 +1226,14 @@ static UniValue listreceivedbyaddress(const JSONRPCRequest& request)
" }\n"
" ,...\n"
"]\n"
-
- "\nExamples:\n"
- + HelpExampleCli("listreceivedbyaddress", "")
+ },
+ RPCExamples{
+ HelpExampleCli("listreceivedbyaddress", "")
+ HelpExampleCli("listreceivedbyaddress", "6 true")
+ HelpExampleRpc("listreceivedbyaddress", "6, true, true")
+ HelpExampleRpc("listreceivedbyaddress", "6, true, true, \"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\"")
- );
+ },
+ }.ToString());
// Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now
@@ -1248,9 +1262,8 @@ static UniValue listreceivedbylabel(const JSONRPCRequest& request)
{"minconf", RPCArg::Type::NUM, /* opt */ true, /* default_val */ "1", "The minimum number of confirmations before payments are included."},
{"include_empty", RPCArg::Type::BOOL, /* opt */ true, /* default_val */ "false", "Whether to include labels that haven't received any payments."},
{"include_watchonly", RPCArg::Type::BOOL, /* opt */ true, /* default_val */ "false", "Whether to include watch-only addresses (see 'importaddress')."},
- }}
- .ToString() +
- "\nResult:\n"
+ },
+ RPCResult{
"[\n"
" {\n"
" \"involvesWatchonly\" : true, (bool) Only returned if imported addresses were involved in transaction\n"
@@ -1260,12 +1273,13 @@ static UniValue listreceivedbylabel(const JSONRPCRequest& request)
" }\n"
" ,...\n"
"]\n"
-
- "\nExamples:\n"
- + HelpExampleCli("listreceivedbylabel", "")
+ },
+ RPCExamples{
+ HelpExampleCli("listreceivedbylabel", "")
+ HelpExampleCli("listreceivedbylabel", "6 true")
+ HelpExampleRpc("listreceivedbylabel", "6, true, true")
- );
+ },
+ }.ToString());
// Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now
@@ -1391,9 +1405,8 @@ UniValue listtransactions(const JSONRPCRequest& request)
{"count", RPCArg::Type::NUM, /* opt */ true, /* default_val */ "10", "The number of transactions to return"},
{"skip", RPCArg::Type::NUM, /* opt */ true, /* default_val */ "0", "The number of transactions to skip"},
{"include_watchonly", RPCArg::Type::BOOL, /* opt */ true, /* default_val */ "false", "Include transactions to watch-only addresses (see 'importaddress')"},
- }}
- .ToString() +
- "\nResult:\n"
+ },
+ RPCResult{
"[\n"
" {\n"
" \"address\":\"address\", (string) The bitcoin address of the transaction.\n"
@@ -1425,15 +1438,16 @@ UniValue listtransactions(const JSONRPCRequest& request)
" 'send' category of transactions.\n"
" }\n"
"]\n"
-
- "\nExamples:\n"
+ },
+ RPCExamples{
"\nList the most recent 10 transactions in the systems\n"
+ HelpExampleCli("listtransactions", "") +
"\nList transactions 100 to 120\n"
+ HelpExampleCli("listtransactions", "\"*\" 20 100") +
"\nAs a JSON-RPC call\n"
+ HelpExampleRpc("listtransactions", "\"*\", 20, 100")
- );
+ },
+ }.ToString());
// Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now
@@ -1526,9 +1540,8 @@ static UniValue listsinceblock(const JSONRPCRequest& request)
{"include_watchonly", RPCArg::Type::BOOL, /* opt */ true, /* default_val */ "false", "Include transactions to watch-only addresses (see 'importaddress')"},
{"include_removed", RPCArg::Type::BOOL, /* opt */ true, /* default_val */ "true", "Show transactions that were removed due to a reorg in the \"removed\" array\n"
" (not guaranteed to work on pruned nodes)"},
- }}
- .ToString() +
- "\nResult:\n"
+ },
+ RPCResult{
"{\n"
" \"transactions\": [\n"
" \"address\":\"address\", (string) The bitcoin address of the transaction.\n"
@@ -1563,11 +1576,13 @@ static UniValue listsinceblock(const JSONRPCRequest& request)
" ],\n"
" \"lastblock\": \"lastblockhash\" (string) The hash of the block (target_confirmations-1) from the best block on the main chain. This is typically used to feed back into listsinceblock the next time you call it. So you would generally use a target_confirmations of say 6, so you will be continually re-notified of transactions until they've reached 6 confirmations plus any new ones\n"
"}\n"
- "\nExamples:\n"
- + HelpExampleCli("listsinceblock", "")
+ },
+ RPCExamples{
+ HelpExampleCli("listsinceblock", "")
+ HelpExampleCli("listsinceblock", "\"000000000000000bacf66f7497b7dc45ef753ee9a7d38571037cdb1a57f663ad\" 6")
+ HelpExampleRpc("listsinceblock", "\"000000000000000bacf66f7497b7dc45ef753ee9a7d38571037cdb1a57f663ad\", 6")
- );
+ },
+ }.ToString());
// Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now
@@ -1664,9 +1679,8 @@ static UniValue gettransaction(const JSONRPCRequest& request)
{
{"txid", RPCArg::Type::STR, /* opt */ false, /* default_val */ "", "The transaction id"},
{"include_watchonly", RPCArg::Type::BOOL, /* opt */ true, /* default_val */ "false", "Whether to include watch-only addresses in balance calculation and details[]"},
- }}
- .ToString() +
- "\nResult:\n"
+ },
+ RPCResult{
"{\n"
" \"amount\" : x.xxx, (numeric) The transaction amount in " + CURRENCY_UNIT + "\n"
" \"fee\": x.xxx, (numeric) The amount of the fee in " + CURRENCY_UNIT + ". This is negative and only available for the \n"
@@ -1701,12 +1715,13 @@ static UniValue gettransaction(const JSONRPCRequest& request)
" ],\n"
" \"hex\" : \"data\" (string) Raw data for transaction\n"
"}\n"
-
- "\nExamples:\n"
- + HelpExampleCli("gettransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
+ },
+ RPCExamples{
+ HelpExampleCli("gettransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
+ HelpExampleCli("gettransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\" true")
+ HelpExampleRpc("gettransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
- );
+ },
+ }.ToString());
// Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now
@@ -1769,13 +1784,13 @@ static UniValue abandontransaction(const JSONRPCRequest& request)
"It has no effect on transactions which are already abandoned.\n",
{
{"txid", RPCArg::Type::STR_HEX, /* opt */ false, /* default_val */ "", "The transaction id"},
- }}
- .ToString() +
- "\nResult:\n"
- "\nExamples:\n"
- + HelpExampleCli("abandontransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
+ },
+ RPCResults{},
+ RPCExamples{
+ HelpExampleCli("abandontransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
+ HelpExampleRpc("abandontransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
- );
+ },
+ }.ToString());
}
// Make sure the results are valid at least up to the most recent block
@@ -1813,12 +1828,13 @@ static UniValue backupwallet(const JSONRPCRequest& request)
"\nSafely copies current wallet file to destination, which can be a directory or a path with filename.\n",
{
{"destination", RPCArg::Type::STR, /* opt */ false, /* default_val */ "", "The destination directory or file"},
- }}
- .ToString() +
- "\nExamples:\n"
- + HelpExampleCli("backupwallet", "\"backup.dat\"")
+ },
+ RPCResults{},
+ RPCExamples{
+ HelpExampleCli("backupwallet", "\"backup.dat\"")
+ HelpExampleRpc("backupwallet", "\"backup.dat\"")
- );
+ },
+ }.ToString());
// Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now
@@ -1852,12 +1868,13 @@ static UniValue keypoolrefill(const JSONRPCRequest& request)
HelpRequiringPassphrase(pwallet) + "\n",
{
{"newsize", RPCArg::Type::NUM, /* opt */ true, /* default_val */ "100", "The new keypool size"},
- }}
- .ToString() +
- "\nExamples:\n"
- + HelpExampleCli("keypoolrefill", "")
+ },
+ RPCResults{},
+ RPCExamples{
+ HelpExampleCli("keypoolrefill", "")
+ HelpExampleRpc("keypoolrefill", "")
- );
+ },
+ }.ToString());
if (pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Error: Private keys are disabled for this wallet");
@@ -1898,23 +1915,24 @@ static UniValue walletpassphrase(const JSONRPCRequest& request)
throw std::runtime_error(
RPCHelpMan{"walletpassphrase",
"\nStores the wallet decryption key in memory for 'timeout' seconds.\n"
- "This is needed prior to performing transactions related to private keys such as sending bitcoins\n",
+ "This is needed prior to performing transactions related to private keys such as sending bitcoins\n"
+ "\nNote:\n"
+ "Issuing the walletpassphrase command while the wallet is already unlocked will set a new unlock\n"
+ "time that overrides the old one.\n",
{
{"passphrase", RPCArg::Type::STR, /* opt */ false, /* default_val */ "", "The wallet passphrase"},
{"timeout", RPCArg::Type::NUM, /* opt */ false, /* default_val */ "", "The time to keep the decryption key in seconds; capped at 100000000 (~3 years)."},
- }}
- .ToString() +
- "\nNote:\n"
- "Issuing the walletpassphrase command while the wallet is already unlocked will set a new unlock\n"
- "time that overrides the old one.\n"
- "\nExamples:\n"
+ },
+ RPCResults{},
+ RPCExamples{
"\nUnlock the wallet for 60 seconds\n"
+ HelpExampleCli("walletpassphrase", "\"my pass phrase\" 60") +
"\nLock the wallet again (before 60 seconds)\n"
+ HelpExampleCli("walletlock", "") +
"\nAs a JSON-RPC call\n"
+ HelpExampleRpc("walletpassphrase", "\"my pass phrase\", 60")
- );
+ },
+ }.ToString());
}
auto locked_chain = pwallet->chain().lock();
@@ -1987,12 +2005,13 @@ static UniValue walletpassphrasechange(const JSONRPCRequest& request)
{
{"oldpassphrase", RPCArg::Type::STR, /* opt */ false, /* default_val */ "", "The current passphrase"},
{"newpassphrase", RPCArg::Type::STR, /* opt */ false, /* default_val */ "", "The new passphrase"},
- }}
- .ToString() +
- "\nExamples:\n"
- + HelpExampleCli("walletpassphrasechange", "\"old one\" \"new one\"")
+ },
+ RPCResults{},
+ RPCExamples{
+ HelpExampleCli("walletpassphrasechange", "\"old one\" \"new one\"")
+ HelpExampleRpc("walletpassphrasechange", "\"old one\", \"new one\"")
- );
+ },
+ }.ToString());
}
auto locked_chain = pwallet->chain().lock();
@@ -2039,9 +2058,9 @@ static UniValue walletlock(const JSONRPCRequest& request)
"\nRemoves the wallet encryption key from memory, locking the wallet.\n"
"After calling this method, you will need to call walletpassphrase again\n"
"before being able to call any methods which require the wallet to be unlocked.\n",
- {}}
- .ToString() +
- "\nExamples:\n"
+ {},
+ RPCResults{},
+ RPCExamples{
"\nSet the passphrase for 2 minutes to perform a transaction\n"
+ HelpExampleCli("walletpassphrase", "\"my pass phrase\" 120") +
"\nPerform a send (requires passphrase set)\n"
@@ -2050,7 +2069,8 @@ static UniValue walletlock(const JSONRPCRequest& request)
+ HelpExampleCli("walletlock", "") +
"\nAs a JSON-RPC call\n"
+ HelpExampleRpc("walletlock", "")
- );
+ },
+ }.ToString());
}
auto locked_chain = pwallet->chain().lock();
@@ -2086,9 +2106,9 @@ static UniValue encryptwallet(const JSONRPCRequest& request)
"If the wallet is already encrypted, use the walletpassphrasechange call.\n",
{
{"passphrase", RPCArg::Type::STR, /* opt */ false, /* default_val */ "", "The pass phrase to encrypt the wallet with. It must be at least 1 character, but should be long."},
- }}
- .ToString() +
- "\nExamples:\n"
+ },
+ RPCResults{},
+ RPCExamples{
"\nEncrypt your wallet\n"
+ HelpExampleCli("encryptwallet", "\"my pass phrase\"") +
"\nNow set the passphrase to use the wallet, such as for signing or sending bitcoin\n"
@@ -2099,7 +2119,8 @@ static UniValue encryptwallet(const JSONRPCRequest& request)
+ HelpExampleCli("walletlock", "") +
"\nAs a JSON-RPC call\n"
+ HelpExampleRpc("encryptwallet", "\"my pass phrase\"")
- );
+ },
+ }.ToString());
}
auto locked_chain = pwallet->chain().lock();
@@ -2157,12 +2178,11 @@ static UniValue lockunspent(const JSONRPCRequest& request)
},
},
},
- }}
- .ToString() +
- "\nResult:\n"
+ },
+ RPCResult{
"true|false (boolean) Whether the command was successful or not\n"
-
- "\nExamples:\n"
+ },
+ RPCExamples{
"\nList the unspent transactions\n"
+ HelpExampleCli("listunspent", "") +
"\nLock an unspent transaction\n"
@@ -2173,7 +2193,8 @@ static UniValue lockunspent(const JSONRPCRequest& request)
+ HelpExampleCli("lockunspent", "true \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
"\nAs a JSON-RPC call\n"
+ HelpExampleRpc("lockunspent", "false, \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"")
- );
+ },
+ }.ToString());
// Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now
@@ -2269,9 +2290,8 @@ static UniValue listlockunspent(const JSONRPCRequest& request)
RPCHelpMan{"listlockunspent",
"\nReturns list of temporarily unspendable outputs.\n"
"See the lockunspent call to lock and unlock transactions for spending.\n",
- {}}
- .ToString() +
- "\nResult:\n"
+ {},
+ RPCResult{
"[\n"
" {\n"
" \"txid\" : \"transactionid\", (string) The transaction id locked\n"
@@ -2279,7 +2299,8 @@ static UniValue listlockunspent(const JSONRPCRequest& request)
" }\n"
" ,...\n"
"]\n"
- "\nExamples:\n"
+ },
+ RPCExamples{
"\nList the unspent transactions\n"
+ HelpExampleCli("listunspent", "") +
"\nLock an unspent transaction\n"
@@ -2290,7 +2311,8 @@ static UniValue listlockunspent(const JSONRPCRequest& request)
+ HelpExampleCli("lockunspent", "true \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
"\nAs a JSON-RPC call\n"
+ HelpExampleRpc("listlockunspent", "")
- );
+ },
+ }.ToString());
auto locked_chain = pwallet->chain().lock();
LOCK(pwallet->cs_wallet);
@@ -2326,14 +2348,15 @@ static UniValue settxfee(const JSONRPCRequest& request)
"\nSet the transaction fee per kB for this wallet. Overrides the global -paytxfee command line parameter.\n",
{
{"amount", RPCArg::Type::AMOUNT, /* opt */ false, /* default_val */ "", "The transaction fee in " + CURRENCY_UNIT + "/kB"},
- }}
- .ToString() +
- "\nResult\n"
+ },
+ RPCResult{
"true|false (boolean) Returns true if successful\n"
- "\nExamples:\n"
- + HelpExampleCli("settxfee", "0.00001")
+ },
+ RPCExamples{
+ HelpExampleCli("settxfee", "0.00001")
+ HelpExampleRpc("settxfee", "0.00001")
- );
+ },
+ }.ToString());
}
auto locked_chain = pwallet->chain().lock();
@@ -2365,9 +2388,9 @@ static UniValue getwalletinfo(const JSONRPCRequest& request)
if (request.fHelp || request.params.size() != 0)
throw std::runtime_error(
RPCHelpMan{"getwalletinfo",
- "Returns an object containing various wallet state info.\n", {}}
- .ToString() +
- "\nResult:\n"
+ "Returns an object containing various wallet state info.\n",
+ {},
+ RPCResult{
"{\n"
" \"walletname\": xxxxx, (string) the wallet name\n"
" \"walletversion\": xxxxx, (numeric) the wallet version\n"
@@ -2384,10 +2407,12 @@ static UniValue getwalletinfo(const JSONRPCRequest& request)
" \"hdmasterkeyid\": \"<hash160>\" (string, optional) alias for hdseedid retained for backwards-compatibility. Will be removed in V0.18.\n"
" \"private_keys_enabled\": true|false (boolean) false if privatekeys are disabled for this wallet (enforced watch-only wallet)\n"
"}\n"
- "\nExamples:\n"
- + HelpExampleCli("getwalletinfo", "")
+ },
+ RPCExamples{
+ HelpExampleCli("getwalletinfo", "")
+ HelpExampleRpc("getwalletinfo", "")
- );
+ },
+ }.ToString());
// Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now
@@ -2428,8 +2453,9 @@ static UniValue listwalletdir(const JSONRPCRequest& request)
if (request.fHelp || request.params.size() != 0) {
throw std::runtime_error(
RPCHelpMan{"listwalletdir",
- "Returns a list of wallets in the wallet directory.\n", {}}
- .ToString() +
+ "Returns a list of wallets in the wallet directory.\n",
+ {},
+ RPCResult{
"{\n"
" \"wallets\" : [ (json array of objects)\n"
" {\n"
@@ -2438,10 +2464,12 @@ static UniValue listwalletdir(const JSONRPCRequest& request)
" ,...\n"
" ]\n"
"}\n"
- "\nExamples:\n"
- + HelpExampleCli("listwalletdir", "")
+ },
+ RPCExamples{
+ HelpExampleCli("listwalletdir", "")
+ HelpExampleRpc("listwalletdir", "")
- );
+ },
+ }.ToString());
}
UniValue wallets(UniValue::VARR);
@@ -2463,17 +2491,18 @@ static UniValue listwallets(const JSONRPCRequest& request)
RPCHelpMan{"listwallets",
"Returns a list of currently loaded wallets.\n"
"For full information on the wallet, use \"getwalletinfo\"\n",
- {}}
- .ToString() +
- "\nResult:\n"
+ {},
+ RPCResult{
"[ (json array of strings)\n"
" \"walletname\" (string) the wallet name\n"
" ...\n"
"]\n"
- "\nExamples:\n"
- + HelpExampleCli("listwallets", "")
+ },
+ RPCExamples{
+ HelpExampleCli("listwallets", "")
+ HelpExampleRpc("listwallets", "")
- );
+ },
+ }.ToString());
UniValue obj(UniValue::VARR);
@@ -2500,17 +2529,18 @@ static UniValue loadwallet(const JSONRPCRequest& request)
"\napplied to the new wallet (eg -zapwallettxes, upgradewallet, rescan, etc).\n",
{
{"filename", RPCArg::Type::STR, /* opt */ false, /* default_val */ "", "The wallet directory or .dat file."},
- }}
- .ToString() +
- "\nResult:\n"
+ },
+ RPCResult{
"{\n"
" \"name\" : <wallet_name>, (string) The wallet name if loaded successfully.\n"
" \"warning\" : <warning>, (string) Warning message if wallet was not loaded cleanly.\n"
"}\n"
- "\nExamples:\n"
- + HelpExampleCli("loadwallet", "\"test.dat\"")
+ },
+ RPCExamples{
+ HelpExampleCli("loadwallet", "\"test.dat\"")
+ HelpExampleRpc("loadwallet", "\"test.dat\"")
- );
+ },
+ }.ToString());
WalletLocation location(request.params[0].get_str());
std::string error;
@@ -2554,17 +2584,18 @@ static UniValue createwallet(const JSONRPCRequest& request)
{
{"wallet_name", RPCArg::Type::STR, /* opt */ false, /* default_val */ "", "The name for the new wallet. If this is a path, the wallet will be created at the path location."},
{"disable_private_keys", RPCArg::Type::BOOL, /* opt */ true, /* default_val */ "false", "Disable the possibility of private keys (only watchonlys are possible in this mode)."},
- }}
- .ToString() +
- "\nResult:\n"
+ },
+ RPCResult{
"{\n"
" \"name\" : <wallet_name>, (string) The wallet name if created successfully. If the wallet was created using a full path, the wallet_name will be the full path.\n"
" \"warning\" : <warning>, (string) Warning message if wallet was not loaded cleanly.\n"
"}\n"
- "\nExamples:\n"
- + HelpExampleCli("createwallet", "\"testwallet\"")
+ },
+ RPCExamples{
+ HelpExampleCli("createwallet", "\"testwallet\"")
+ HelpExampleRpc("createwallet", "\"testwallet\"")
- );
+ },
+ }.ToString());
}
std::string error;
std::string warning;
@@ -2608,12 +2639,13 @@ static UniValue unloadwallet(const JSONRPCRequest& request)
"Specifying the wallet name on a wallet endpoint is invalid.",
{
{"wallet_name", RPCArg::Type::STR, /* opt */ true, /* default_val */ "the wallet name from the RPC request", "The name of the wallet to unload."},
- }}
- .ToString() +
- "\nExamples:\n"
- + HelpExampleCli("unloadwallet", "wallet_name")
+ },
+ RPCResults{},
+ RPCExamples{
+ HelpExampleCli("unloadwallet", "wallet_name")
+ HelpExampleRpc("unloadwallet", "wallet_name")
- );
+ },
+ }.ToString());
}
std::string wallet_name;
@@ -2655,12 +2687,15 @@ static UniValue resendwallettransactions(const JSONRPCRequest& request)
throw std::runtime_error(
RPCHelpMan{"resendwallettransactions",
"Immediately re-broadcast unconfirmed wallet transactions to all peers.\n"
- "Intended only for testing; the wallet code periodically re-broadcasts\n",
- {}}
- .ToString() +
- "automatically.\n"
+ "Intended only for testing; the wallet code periodically re-broadcasts\n"
+ "automatically.\n",
+ {},
+ RPCResult{
"Returns an RPC error if -walletbroadcast is set to false.\n"
"Returns array of transaction ids that were re-broadcast.\n"
+ },
+ RPCExamples{""},
+ }.ToString()
);
if (!g_connman)
@@ -2715,9 +2750,8 @@ static UniValue listunspent(const JSONRPCRequest& request)
{"minimumSumAmount", RPCArg::Type::AMOUNT, /* opt */ true, /* default_val */ "unlimited", "Minimum sum value of all UTXOs in " + CURRENCY_UNIT + ""},
},
"query_options"},
- }}
- .ToString() +
- "\nResult\n"
+ },
+ RPCResult{
"[ (array of json object)\n"
" {\n"
" \"txid\" : \"txid\", (string) the transaction id \n"
@@ -2737,14 +2771,15 @@ static UniValue listunspent(const JSONRPCRequest& request)
" }\n"
" ,...\n"
"]\n"
-
- "\nExamples\n"
- + HelpExampleCli("listunspent", "")
+ },
+ RPCExamples{
+ HelpExampleCli("listunspent", "")
+ HelpExampleCli("listunspent", "6 9999999 \"[\\\"1PGFqEzfmQch1gKD3ra4k18PNj3tTUUSqg\\\",\\\"1LtvqCaApEdUGFkpKMM4MstjcaL4dKg8SP\\\"]\"")
+ HelpExampleRpc("listunspent", "6, 9999999 \"[\\\"1PGFqEzfmQch1gKD3ra4k18PNj3tTUUSqg\\\",\\\"1LtvqCaApEdUGFkpKMM4MstjcaL4dKg8SP\\\"]\"")
+ HelpExampleCli("listunspent", "6 9999999 '[]' true '{ \"minimumAmount\": 0.005 }'")
+ HelpExampleRpc("listunspent", "6, 9999999, [] , true, { \"minimumAmount\": 0.005 } ")
- );
+ },
+ }.ToString());
int nMinDepth = 1;
if (!request.params[0].isNull()) {
@@ -3027,15 +3062,15 @@ static UniValue fundrawtransaction(const JSONRPCRequest& request)
"options"},
{"iswitness", RPCArg::Type::BOOL, /* opt */ true, /* default_val */ "depends on heuristic tests", "Whether the transaction hex is a serialized witness transaction \n"
" If iswitness is not present, heuristic tests will be used in decoding"},
- }}
- .ToString() +
- "\nResult:\n"
+ },
+ RPCResult{
"{\n"
" \"hex\": \"value\", (string) The resulting raw transaction (hex-encoded string)\n"
" \"fee\": n, (numeric) Fee in " + CURRENCY_UNIT + " the resulting transaction pays\n"
" \"changepos\": n (numeric) The position of the added change output, or -1\n"
"}\n"
- "\nExamples:\n"
+ },
+ RPCExamples{
"\nCreate a transaction with no inputs\n"
+ HelpExampleCli("createrawtransaction", "\"[]\" \"{\\\"myaddress\\\":0.01}\"") +
"\nAdd sufficient unsigned inputs to meet the output value\n"
@@ -3044,7 +3079,8 @@ static UniValue fundrawtransaction(const JSONRPCRequest& request)
+ HelpExampleCli("signrawtransaction", "\"fundedtransactionhex\"") +
"\nSend the transaction\n"
+ HelpExampleCli("sendrawtransaction", "\"signedtransactionhex\"")
- );
+ },
+ }.ToString());
RPCTypeCheck(request.params, {UniValue::VSTR, UniValueType(), UniValue::VBOOL});
@@ -3061,7 +3097,7 @@ static UniValue fundrawtransaction(const JSONRPCRequest& request)
FundTransaction(pwallet, tx, fee, change_position, request.params[1]);
UniValue result(UniValue::VOBJ);
- result.pushKV("hex", EncodeHexTx(tx));
+ result.pushKV("hex", EncodeHexTx(CTransaction(tx)));
result.pushKV("fee", ValueFromAmount(fee));
result.pushKV("changepos", change_position);
@@ -3106,9 +3142,8 @@ UniValue signrawtransactionwithwallet(const JSONRPCRequest& request)
" \"ALL|ANYONECANPAY\"\n"
" \"NONE|ANYONECANPAY\"\n"
" \"SINGLE|ANYONECANPAY\""},
- }}
- .ToString() +
- "\nResult:\n"
+ },
+ RPCResult{
"{\n"
" \"hex\" : \"value\", (string) The hex-encoded raw transaction with signature(s)\n"
" \"complete\" : true|false, (boolean) If the transaction has a complete set of signatures\n"
@@ -3123,11 +3158,12 @@ UniValue signrawtransactionwithwallet(const JSONRPCRequest& request)
" ,...\n"
" ]\n"
"}\n"
-
- "\nExamples:\n"
- + HelpExampleCli("signrawtransactionwithwallet", "\"myhex\"")
+ },
+ RPCExamples{
+ HelpExampleCli("signrawtransactionwithwallet", "\"myhex\"")
+ HelpExampleRpc("signrawtransactionwithwallet", "\"myhex\"")
- );
+ },
+ }.ToString());
RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VARR, UniValue::VSTR}, true);
@@ -3189,18 +3225,20 @@ static UniValue bumpfee(const JSONRPCRequest& request)
" \"CONSERVATIVE\""},
},
"options"},
- }}
- .ToString() +
- "\nResult:\n"
+ },
+ RPCResult{
"{\n"
" \"txid\": \"value\", (string) The id of the new transaction\n"
" \"origfee\": n, (numeric) Fee of the replaced transaction\n"
" \"fee\": n, (numeric) Fee of the new transaction\n"
" \"errors\": [ str... ] (json array of strings) Errors encountered during processing (may be empty)\n"
"}\n"
- "\nExamples:\n"
+ },
+ RPCExamples{
"\nBump the fee, get the new transaction\'s txid\n" +
- HelpExampleCli("bumpfee", "<txid>"));
+ HelpExampleCli("bumpfee", "<txid>")
+ },
+ }.ToString());
}
RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VOBJ});
@@ -3315,14 +3353,15 @@ UniValue generate(const JSONRPCRequest& request)
{
{"nblocks", RPCArg::Type::NUM, /* opt */ false, /* default_val */ "", "How many blocks are generated immediately."},
{"maxtries", RPCArg::Type::NUM, /* opt */ true, /* default_val */ "1000000", "How many iterations to try."},
- }}
- .ToString() +
- "\nResult:\n"
+ },
+ RPCResult{
"[ blockhashes ] (array) hashes of blocks generated\n"
- "\nExamples:\n"
+ },
+ RPCExamples{
"\nGenerate 11 blocks\n"
+ HelpExampleCli("generate", "11")
- );
+ },
+ }.ToString());
}
if (!IsDeprecatedRPCEnabled("generate")) {
@@ -3369,17 +3408,18 @@ UniValue rescanblockchain(const JSONRPCRequest& request)
{
{"start_height", RPCArg::Type::NUM, /* opt */ true, /* default_val */ "0", "block height where the rescan should start"},
{"stop_height", RPCArg::Type::NUM, /* opt */ true, /* default_val */ "tip height", "the last block height that should be scanned"},
- }}
- .ToString() +
- "\nResult:\n"
+ },
+ RPCResult{
"{\n"
" \"start_height\" (numeric) The block height where the rescan has started. If omitted, rescan started from the genesis block.\n"
" \"stop_height\" (numeric) The height of the last rescanned block. If omitted, rescan stopped at the chain tip.\n"
"}\n"
- "\nExamples:\n"
- + HelpExampleCli("rescanblockchain", "100000 120000")
+ },
+ RPCExamples{
+ HelpExampleCli("rescanblockchain", "100000 120000")
+ HelpExampleRpc("rescanblockchain", "100000, 120000")
- );
+ },
+ }.ToString());
}
WalletRescanReserver reserver(pwallet);
@@ -3576,14 +3616,12 @@ UniValue getaddressinfo(const JSONRPCRequest& request)
"to be in the wallet.\n",
{
{"address", RPCArg::Type::STR, /* opt */ false, /* default_val */ "", "The bitcoin address to get the information of."},
- }}
- .ToString() +
- "\nResult:\n"
+ },
+ RPCResult{
"{\n"
" \"address\" : \"address\", (string) The bitcoin address validated\n"
" \"scriptPubKey\" : \"hex\", (string) The hex-encoded scriptPubKey generated by the address\n"
" \"ismine\" : true|false, (boolean) If the address is yours or not\n"
- " \"solvable\" : true|false, (boolean) If the address is solvable by the wallet\n"
" \"iswatchonly\" : true|false, (boolean) If the address is watchonly\n"
" \"solvable\" : true|false, (boolean) Whether we know how to spend coins sent to this address, ignoring the possible lack of private keys\n"
" \"desc\" : \"desc\", (string, optional) A descriptor for spending coins sent to this address (only when solvable)\n"
@@ -3602,7 +3640,7 @@ UniValue getaddressinfo(const JSONRPCRequest& request)
" \"sigsrequired\" : xxxxx (numeric, optional) Number of signatures required to spend multisig output (only if \"script\" is \"multisig\")\n"
" \"pubkey\" : \"publickeyhex\", (string, optional) The hex value of the raw public key, for single-key addresses (possibly embedded in P2SH or P2WSH)\n"
" \"embedded\" : {...}, (object, optional) Information about the address embedded in P2SH or P2WSH, if relevant and known. It includes all getaddressinfo output fields for the embedded address, excluding metadata (\"timestamp\", \"hdkeypath\", \"hdseedid\") and relation to the wallet (\"ismine\", \"iswatchonly\").\n"
- " \"iscompressed\" : true|false, (boolean) If the address is compressed\n"
+ " \"iscompressed\" : true|false, (boolean, optional) If the pubkey is compressed\n"
" \"label\" : \"label\" (string) The label associated with the address, \"\" is the default label\n"
" \"timestamp\" : timestamp, (number, optional) The creation time of the key if available in seconds since epoch (Jan 1 1970 GMT)\n"
" \"hdkeypath\" : \"keypath\" (string, optional) The HD keypath if the key is HD and available\n"
@@ -3616,10 +3654,12 @@ UniValue getaddressinfo(const JSONRPCRequest& request)
" },...\n"
" ]\n"
"}\n"
- "\nExamples:\n"
- + HelpExampleCli("getaddressinfo", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"")
+ },
+ RPCExamples{
+ HelpExampleCli("getaddressinfo", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"")
+ HelpExampleRpc("getaddressinfo", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"")
- );
+ },
+ }.ToString());
}
LOCK(pwallet->cs_wallet);
@@ -3646,7 +3686,6 @@ UniValue getaddressinfo(const JSONRPCRequest& request)
ret.pushKV("desc", InferDescriptor(scriptPubKey, *pwallet)->ToString());
}
ret.pushKV("iswatchonly", bool(mine & ISMINE_WATCH_ONLY));
- ret.pushKV("solvable", IsSolvable(*pwallet, scriptPubKey));
UniValue detail = DescribeWalletAddress(pwallet, dest);
ret.pushKVs(detail);
if (pwallet->mapAddressBook.count(dest)) {
@@ -3704,18 +3743,19 @@ static UniValue getaddressesbylabel(const JSONRPCRequest& request)
"\nReturns the list of addresses assigned the specified label.\n",
{
{"label", RPCArg::Type::STR, /* opt */ false, /* default_val */ "", "The label."},
- }}
- .ToString() +
- "\nResult:\n"
+ },
+ RPCResult{
"{ (json object with addresses as keys)\n"
" \"address\": { (json object with information about address)\n"
" \"purpose\": \"string\" (string) Purpose of address (\"send\" for sending address, \"receive\" for receiving address)\n"
" },...\n"
"}\n"
- "\nExamples:\n"
- + HelpExampleCli("getaddressesbylabel", "\"tabby\"")
+ },
+ RPCExamples{
+ HelpExampleCli("getaddressesbylabel", "\"tabby\"")
+ HelpExampleRpc("getaddressesbylabel", "\"tabby\"")
- );
+ },
+ }.ToString());
LOCK(pwallet->cs_wallet);
@@ -3751,14 +3791,14 @@ static UniValue listlabels(const JSONRPCRequest& request)
"\nReturns the list of all labels, or labels that are assigned to addresses with a specific purpose.\n",
{
{"purpose", RPCArg::Type::STR, /* opt */ true, /* default_val */ "null", "Address purpose to list labels for ('send','receive'). An empty string is the same as not providing this argument."},
- }}
- .ToString() +
- "\nResult:\n"
+ },
+ RPCResult{
"[ (json array of string)\n"
" \"label\", (string) Label name\n"
" ...\n"
"]\n"
- "\nExamples:\n"
+ },
+ RPCExamples{
"\nList all labels\n"
+ HelpExampleCli("listlabels", "") +
"\nList labels that have receiving addresses\n"
@@ -3767,7 +3807,8 @@ static UniValue listlabels(const JSONRPCRequest& request)
+ HelpExampleCli("listlabels", "send") +
"\nAs a JSON-RPC call\n"
+ HelpExampleRpc("listlabels", "receive")
- );
+ },
+ }.ToString());
LOCK(pwallet->cs_wallet);
@@ -3815,14 +3856,15 @@ UniValue sethdseed(const JSONRPCRequest& request)
" keypool will be used until it has been depleted."},
{"seed", RPCArg::Type::STR, /* opt */ true, /* default_val */ "random seed", "The WIF private key to use as the new HD seed.\n"
" The seed value can be retrieved using the dumpwallet command. It is the private key marked hdseed=1"},
- }}
- .ToString() +
- "\nExamples:\n"
- + HelpExampleCli("sethdseed", "")
+ },
+ RPCResults{},
+ RPCExamples{
+ HelpExampleCli("sethdseed", "")
+ HelpExampleCli("sethdseed", "false")
+ HelpExampleCli("sethdseed", "true \"wifkey\"")
+ HelpExampleRpc("sethdseed", "true, \"wifkey\"")
- );
+ },
+ }.ToString());
}
if (IsInitialBlockDownload()) {
@@ -3959,18 +4001,18 @@ UniValue walletprocesspsbt(const JSONRPCRequest& request)
" \"NONE|ANYONECANPAY\"\n"
" \"SINGLE|ANYONECANPAY\""},
{"bip32derivs", RPCArg::Type::BOOL, /* opt */ true, /* default_val */ "false", "If true, includes the BIP 32 derivation paths for public keys if we know them"},
- }}
- .ToString() +
- "\nResult:\n"
+ },
+ RPCResult{
"{\n"
" \"psbt\" : \"value\", (string) The base64-encoded partially signed transaction\n"
" \"complete\" : true|false, (boolean) If the transaction has a complete set of signatures\n"
" ]\n"
"}\n"
-
- "\nExamples:\n"
- + HelpExampleCli("walletprocesspsbt", "\"psbt\"")
- );
+ },
+ RPCExamples{
+ HelpExampleCli("walletprocesspsbt", "\"psbt\"")
+ },
+ }.ToString());
RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VBOOL, UniValue::VSTR});
@@ -4041,8 +4083,7 @@ UniValue walletcreatefundedpsbt(const JSONRPCRequest& request)
},
},
},
- {"locktime", RPCArg::Type::NUM, /* opt */ true, /* default_val */ "0", "Raw locktime. Non-0 value also locktime-activates inputs\n"
- " Allows this transaction to be replaced by a transaction with higher fees. If provided, it is an error if explicit sequence numbers are incompatible."},
+ {"locktime", RPCArg::Type::NUM, /* opt */ true, /* default_val */ "0", "Raw locktime. Non-0 value also locktime-activates inputs"},
{"options", RPCArg::Type::OBJ, /* opt */ true, /* default_val */ "null", "",
{
{"changeAddress", RPCArg::Type::STR_HEX, /* opt */ true, /* default_val */ "pool address", "The bitcoin address to receive the change"},
@@ -4069,18 +4110,19 @@ UniValue walletcreatefundedpsbt(const JSONRPCRequest& request)
},
"options"},
{"bip32derivs", RPCArg::Type::BOOL, /* opt */ true, /* default_val */ "false", "If true, includes the BIP 32 derivation paths for public keys if we know them"},
- }}
- .ToString() +
- "\nResult:\n"
+ },
+ RPCResult{
"{\n"
" \"psbt\": \"value\", (string) The resulting raw transaction (base64-encoded string)\n"
" \"fee\": n, (numeric) Fee in " + CURRENCY_UNIT + " the resulting transaction pays\n"
" \"changepos\": n (numeric) The position of the added change output, or -1\n"
"}\n"
- "\nExamples:\n"
+ },
+ RPCExamples{
"\nCreate a transaction with no inputs\n"
+ HelpExampleCli("walletcreatefundedpsbt", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\" \"[{\\\"data\\\":\\\"00010203\\\"}]\"")
- );
+ },
+ }.ToString());
RPCTypeCheck(request.params, {
UniValue::VARR,
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index bea9ebefa3..ddeff8ba09 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -1505,7 +1505,7 @@ int64_t CalculateMaximumSignedTxSize(const CTransaction &tx, const CWallet *wall
// implies that we can sign for every input.
return -1;
}
- return GetVirtualTransactionSize(txNew);
+ return GetVirtualTransactionSize(CTransaction(txNew));
}
int CalculateMaximumSignedInputSize(const CTxOut& txout, const CWallet* wallet, bool use_max_sig)
@@ -2857,7 +2857,7 @@ bool CWallet::CreateTransaction(interfaces::Chain::Lock& locked_chain, const std
txNew.vin.push_back(CTxIn(coin.outpoint,CScript()));
}
- nBytes = CalculateMaximumSignedTxSize(txNew, this, coin_control.fAllowWatchOnly);
+ nBytes = CalculateMaximumSignedTxSize(CTransaction(txNew), this, coin_control.fAllowWatchOnly);
if (nBytes < 0) {
strFailReason = _("Signing transaction failed");
return false;
diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h
index fa18e3a6fa..6f787416dd 100644
--- a/src/wallet/wallet.h
+++ b/src/wallet/wallet.h
@@ -35,8 +35,8 @@
#include <vector>
//! Responsible for reading and validating the -wallet arguments and verifying the wallet database.
-// This function will perform salvage on the wallet if requested, as long as only one wallet is
-// being loaded (WalletParameterInteraction forbids -salvagewallet, -zapwallettxes or -upgradewallet with multiwallet).
+//! This function will perform salvage on the wallet if requested, as long as only one wallet is
+//! being loaded (WalletParameterInteraction forbids -salvagewallet, -zapwallettxes or -upgradewallet with multiwallet).
bool VerifyWallets(interfaces::Chain& chain, const std::vector<std::string>& wallet_files);
//! Load wallet databases.
@@ -55,10 +55,10 @@ void StopWallets();
void UnloadWallets();
//! Explicitly unload and delete the wallet.
-// Blocks the current thread after signaling the unload intent so that all
-// wallet clients release the wallet.
-// Note that, when blocking is not required, the wallet is implicitly unloaded
-// by the shared pointer deleter.
+//! Blocks the current thread after signaling the unload intent so that all
+//! wallet clients release the wallet.
+//! Note that, when blocking is not required, the wallet is implicitly unloaded
+//! by the shared pointer deleter.
void UnloadWallet(std::shared_ptr<CWallet>&& wallet);
bool AddWallet(const std::shared_ptr<CWallet>& wallet);
@@ -587,8 +587,8 @@ public:
int64_t nTimeCreated;
int64_t nTimeExpires;
std::string strComment;
- //! todo: add something to note what created it (user, getnewaddress, change)
- //! maybe should have a map<string, string> property map
+ // todo: add something to note what created it (user, getnewaddress, change)
+ // maybe should have a map<string, string> property map
explicit CWalletKey(int64_t nExpires=0);