aboutsummaryrefslogtreecommitdiff
path: root/src/wallet/rpcdump.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/wallet/rpcdump.cpp')
-rw-r--r--src/wallet/rpcdump.cpp133
1 files changed, 47 insertions, 86 deletions
diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp
index d08b80cc20..c97bc38e6f 100644
--- a/src/wallet/rpcdump.cpp
+++ b/src/wallet/rpcdump.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -41,7 +41,7 @@ int64_t static DecodeDumpTime(const std::string &str) {
std::string static EncodeDumpString(const std::string &str) {
std::stringstream ret;
- for (unsigned char c : str) {
+ for (const unsigned char c : str) {
if (c <= 32 || c >= 128 || c == '%') {
ret << '%' << HexStr(&c, &c + 1);
} else {
@@ -86,6 +86,17 @@ static bool GetWalletAddressesForKey(CWallet * const pwallet, const CKeyID &keyi
return fLabelFound;
}
+static const int64_t TIMESTAMP_MIN = 0;
+
+static void RescanWallet(CWallet& wallet, const WalletRescanReserver& reserver, int64_t time_begin = TIMESTAMP_MIN, bool update = true)
+{
+ int64_t scanned_time = wallet.RescanFromTime(time_begin, reserver, update);
+ if (wallet.IsAbortingRescan()) {
+ throw JSONRPCError(RPC_MISC_ERROR, "Rescan aborted by user.");
+ } else if (scanned_time > time_begin) {
+ throw JSONRPCError(RPC_WALLET_ERROR, "Rescan was unable to fully rescan the blockchain. Some transactions may be missing.");
+ }
+}
UniValue importprivkey(const JSONRPCRequest& request)
{
@@ -104,7 +115,7 @@ UniValue importprivkey(const JSONRPCRequest& request)
"1. \"privkey\" (string, required) The private key (see dumpprivkey)\n"
"2. \"label\" (string, optional, default=\"\") An optional label\n"
"3. rescan (boolean, optional, default=true) Rescan the wallet for transactions\n"
- "\nNote: This call can take minutes to complete if rescan is true, during that time, other rpc calls\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"
"\nExamples:\n"
"\nDump a private key\n"
@@ -172,13 +183,7 @@ UniValue importprivkey(const JSONRPCRequest& request)
}
}
if (fRescan) {
- int64_t scanned_time = pwallet->RescanFromTime(TIMESTAMP_MIN, reserver, true /* update */);
- if (pwallet->IsAbortingRescan()) {
- throw JSONRPCError(RPC_MISC_ERROR, "Rescan aborted by user.");
- }
- if (scanned_time > TIMESTAMP_MIN) {
- throw JSONRPCError(RPC_WALLET_ERROR, "Rescan was unable to fully rescan the blockchain. Some transactions may be missing.");
- }
+ RescanWallet(*pwallet, reserver);
}
return NullUniValue;
@@ -257,24 +262,24 @@ UniValue importaddress(const JSONRPCRequest& request)
if (request.fHelp || request.params.size() < 1 || request.params.size() > 4)
throw std::runtime_error(
"importaddress \"address\" ( \"label\" rescan p2sh )\n"
- "\nAdds a script (in hex) or address 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"
"\nArguments:\n"
- "1. \"script\" (string, required) The hex-encoded script (or address)\n"
+ "1. \"address\" (string, required) The Bitcoin address (or hex-encoded script)\n"
"2. \"label\" (string, optional, default=\"\") An optional label\n"
"3. rescan (boolean, optional, default=true) Rescan the wallet for transactions\n"
"4. p2sh (boolean, optional, default=false) Add the P2SH version of the script as well\n"
- "\nNote: This call can take minutes to complete if rescan is true, during that time, other rpc calls\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"
"\nExamples:\n"
- "\nImport a script with rescan\n"
- + HelpExampleCli("importaddress", "\"myscript\"") +
+ "\nImport an address with rescan\n"
+ + HelpExampleCli("importaddress", "\"myaddress\"") +
"\nImport using a label without rescan\n"
- + HelpExampleCli("importaddress", "\"myscript\" \"testing\" false") +
+ + HelpExampleCli("importaddress", "\"myaddress\" \"testing\" false") +
"\nAs a JSON-RPC call\n"
- + HelpExampleRpc("importaddress", "\"myscript\", \"testing\", false")
+ + HelpExampleRpc("importaddress", "\"myaddress\", \"testing\", false")
);
@@ -318,13 +323,7 @@ UniValue importaddress(const JSONRPCRequest& request)
}
if (fRescan)
{
- int64_t scanned_time = pwallet->RescanFromTime(TIMESTAMP_MIN, reserver, true /* update */);
- if (pwallet->IsAbortingRescan()) {
- throw JSONRPCError(RPC_MISC_ERROR, "Rescan aborted by user.");
- }
- if (scanned_time > TIMESTAMP_MIN) {
- throw JSONRPCError(RPC_WALLET_ERROR, "Rescan was unable to fully rescan the blockchain. Some transactions may be missing.");
- }
+ RescanWallet(*pwallet, reserver);
pwallet->ReacceptWalletTransactions();
}
@@ -440,7 +439,7 @@ UniValue importpubkey(const JSONRPCRequest& request)
return NullUniValue;
}
- if (request.fHelp || request.params.size() < 1 || request.params.size() > 4)
+ if (request.fHelp || request.params.size() < 1 || request.params.size() > 3)
throw std::runtime_error(
"importpubkey \"pubkey\" ( \"label\" rescan )\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"
@@ -448,7 +447,7 @@ UniValue importpubkey(const JSONRPCRequest& request)
"1. \"pubkey\" (string, required) The hex-encoded public key\n"
"2. \"label\" (string, optional, default=\"\") An optional label\n"
"3. rescan (boolean, optional, default=true) Rescan the wallet for transactions\n"
- "\nNote: This call can take minutes to complete if rescan is true, during that time, other rpc calls\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"
"\nExamples:\n"
"\nImport a public key with rescan\n"
@@ -495,13 +494,7 @@ UniValue importpubkey(const JSONRPCRequest& request)
}
if (fRescan)
{
- int64_t scanned_time = pwallet->RescanFromTime(TIMESTAMP_MIN, reserver, true /* update */);
- if (pwallet->IsAbortingRescan()) {
- throw JSONRPCError(RPC_MISC_ERROR, "Rescan aborted by user.");
- }
- if (scanned_time > TIMESTAMP_MIN) {
- throw JSONRPCError(RPC_WALLET_ERROR, "Rescan was unable to fully rescan the blockchain. Some transactions may be missing.");
- }
+ RescanWallet(*pwallet, reserver);
pwallet->ReacceptWalletTransactions();
}
@@ -559,7 +552,7 @@ UniValue importwallet(const JSONRPCRequest& request)
// Use uiInterface.ShowProgress instead of pwallet.ShowProgress because pwallet.ShowProgress has a cancel button tied to AbortRescan which
// we don't want for this progress bar showing the import progress. uiInterface.ShowProgress does not have a cancel button.
- uiInterface.ShowProgress(_("Importing..."), 0, false); // show progress dialog in GUI
+ uiInterface.ShowProgress(strprintf("%s " + _("Importing..."), pwallet->GetDisplayName()), 0, false); // show progress dialog in GUI
while (file.good()) {
uiInterface.ShowProgress("", std::max(1, std::min(99, (int)(((double)file.tellg() / (double)nFilesize) * 100))), false);
std::string line;
@@ -577,25 +570,25 @@ UniValue importwallet(const JSONRPCRequest& request)
assert(key.VerifyPubKey(pubkey));
CKeyID keyid = pubkey.GetID();
if (pwallet->HaveKey(keyid)) {
- LogPrintf("Skipping import of %s (key already present)\n", EncodeDestination(keyid));
+ pwallet->WalletLogPrintf("Skipping import of %s (key already present)\n", EncodeDestination(keyid));
continue;
}
int64_t nTime = DecodeDumpTime(vstr[1]);
std::string strLabel;
bool fLabel = true;
for (unsigned int nStr = 2; nStr < vstr.size(); nStr++) {
- if (boost::algorithm::starts_with(vstr[nStr], "#"))
+ if (vstr[nStr].front() == '#')
break;
if (vstr[nStr] == "change=1")
fLabel = false;
if (vstr[nStr] == "reserve=1")
fLabel = false;
- if (boost::algorithm::starts_with(vstr[nStr], "label=")) {
+ if (vstr[nStr].substr(0,6) == "label=") {
strLabel = DecodeDumpString(vstr[nStr].substr(6));
fLabel = true;
}
}
- LogPrintf("Importing %s...\n", EncodeDestination(keyid));
+ pwallet->WalletLogPrintf("Importing %s...\n", EncodeDestination(keyid));
if (!pwallet->AddKeyPubKey(key, pubkey)) {
fGood = false;
continue;
@@ -609,11 +602,11 @@ UniValue importwallet(const JSONRPCRequest& request)
CScript script = CScript(vData.begin(), vData.end());
CScriptID id(script);
if (pwallet->HaveCScript(id)) {
- LogPrintf("Skipping import of %s (script already present)\n", vstr[0]);
+ pwallet->WalletLogPrintf("Skipping import of %s (script already present)\n", vstr[0]);
continue;
}
if(!pwallet->AddCScript(script)) {
- LogPrintf("Error importing script %s\n", vstr[0]);
+ pwallet->WalletLogPrintf("Error importing script %s\n", vstr[0]);
fGood = false;
continue;
}
@@ -629,13 +622,7 @@ UniValue importwallet(const JSONRPCRequest& request)
pwallet->UpdateTimeFirstKey(nTimeBegin);
}
uiInterface.ShowProgress("", 100, false); // hide progress dialog in GUI
- int64_t scanned_time = pwallet->RescanFromTime(nTimeBegin, reserver, false /* update */);
- if (pwallet->IsAbortingRescan()) {
- throw JSONRPCError(RPC_MISC_ERROR, "Rescan aborted by user.");
- }
- if (scanned_time > nTimeBegin) {
- throw JSONRPCError(RPC_WALLET_ERROR, "Rescan was unable to fully rescan the blockchain. Some transactions may be missing.");
- }
+ RescanWallet(*pwallet, reserver, nTimeBegin, false /* update */);
pwallet->MarkDirty();
if (!fGood)
@@ -718,15 +705,15 @@ UniValue dumpwallet(const JSONRPCRequest& request)
EnsureWalletIsUnlocked(pwallet);
- boost::filesystem::path filepath = request.params[0].get_str();
- filepath = boost::filesystem::absolute(filepath);
+ fs::path filepath = request.params[0].get_str();
+ filepath = fs::absolute(filepath);
/* Prevent arbitrary files from being overwritten. There have been reports
* that users have overwritten wallet files this way:
* https://github.com/bitcoin/bitcoin/issues/9934
* It may also avoid other security issues.
*/
- if (boost::filesystem::exists(filepath)) {
+ if (fs::exists(filepath)) {
throw JSONRPCError(RPC_INVALID_PARAMETER, filepath.string() + " already exists. If you are sure this is what you want, move it out of the way first");
}
@@ -861,6 +848,9 @@ static UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, con
std::vector<unsigned char> vData(ParseHex(output));
script = CScript(vData.begin(), vData.end());
+ if (!ExtractDestination(script, dest) && !internal) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Internal must be set to true for nonstandard scriptPubKey imports.");
+ }
}
// Watchonly and private keys
@@ -873,11 +863,6 @@ static UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, con
throw JSONRPCError(RPC_INVALID_PARAMETER, "Incompatibility found between internal and label");
}
- // Not having Internal + Script
- if (!internal && isScript) {
- throw JSONRPCError(RPC_INVALID_PARAMETER, "Internal must be set for hex scriptPubKey");
- }
-
// Keys / PubKeys size check.
if (!isP2SH && (keys.size() > 1 || pubKeys.size() > 1)) { // Address / scriptPubKey
throw JSONRPCError(RPC_INVALID_PARAMETER, "More than private key given for one address");
@@ -981,21 +966,10 @@ static UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, con
CTxDestination pubkey_dest = pubKey.GetID();
// Consistency check.
- if (!isScript && !(pubkey_dest == dest)) {
+ if (!(pubkey_dest == dest)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Consistency check failed");
}
- // Consistency check.
- if (isScript) {
- CTxDestination destination;
-
- if (ExtractDestination(script, destination)) {
- if (!(destination == pubkey_dest)) {
- throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Consistency check failed");
- }
- }
- }
-
CScript pubKeyScript = GetScriptForDestination(pubkey_dest);
if (::IsMine(*pwallet, pubKeyScript) == ISMINE_SPENDABLE) {
@@ -1046,21 +1020,10 @@ static UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, con
CTxDestination pubkey_dest = pubKey.GetID();
// Consistency check.
- if (!isScript && !(pubkey_dest == dest)) {
+ if (!(pubkey_dest == dest)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Consistency check failed");
}
- // Consistency check.
- if (isScript) {
- CTxDestination destination;
-
- if (ExtractDestination(script, destination)) {
- if (!(destination == pubkey_dest)) {
- throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Consistency check failed");
- }
- }
- }
-
CKeyID vchAddress = pubKey.GetID();
pwallet->MarkDirty();
pwallet->SetAddressBook(vchAddress, label, "receive");
@@ -1092,11 +1055,9 @@ static UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, con
throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet");
}
- if (scriptPubKey.getType() == UniValue::VOBJ) {
- // add to address book or update label
- if (IsValidDestination(dest)) {
- pwallet->SetAddressBook(dest, label, "receive");
- }
+ // add to address book or update label
+ if (IsValidDestination(dest)) {
+ pwallet->SetAddressBook(dest, label, "receive");
}
success = true;
@@ -1162,7 +1123,7 @@ UniValue importmulti(const JSONRPCRequest& mainRequest)
" \"keys\": [\"<key>\", ... ] , (array, optional) Array of strings giving private keys whose corresponding public keys must occur in the output or redeemscript\n"
" \"internal\": <true> , (boolean, optional, default: false) Stating whether matching outputs should be treated as not incoming payments\n"
" \"watchonly\": <true> , (boolean, optional, default: false) Stating whether matching outputs should be considered watched even when they're not spendable, only allowed if keys are empty\n"
- " \"label\": <label> , (string, optional, default: '') Label to assign to the address (aka account name, for now), only allowed with internal=false\n"
+ " \"label\": <label> , (string, optional, default: '') Label to assign to the address, only allowed with internal=false\n"
" }\n"
" ,...\n"
" ]\n"
@@ -1170,7 +1131,7 @@ UniValue importmulti(const JSONRPCRequest& mainRequest)
" {\n"
" \"rescan\": <false>, (boolean, optional, default: true) Stating if should rescan the blockchain after all imports\n"
" }\n"
- "\nNote: This call can take minutes to complete if rescan is true, during that time, other rpc calls\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"
"\nExamples:\n" +
HelpExampleCli("importmulti", "'[{ \"scriptPubKey\": { \"address\": \"<my address>\" }, \"timestamp\":1455191478 }, "