diff options
Diffstat (limited to 'src/wallet')
-rw-r--r-- | src/wallet/rpcwallet.cpp | 386 | ||||
-rw-r--r-- | src/wallet/rpcwallet.h | 3 | ||||
-rw-r--r-- | src/wallet/wallet.cpp | 12 |
3 files changed, 338 insertions, 63 deletions
diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 8f378acd1a..8b95c56a5f 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -16,6 +16,7 @@ #include <policy/policy.h> #include <policy/rbf.h> #include <rpc/mining.h> +#include <rpc/rawtransaction.h> #include <rpc/safemode.h> #include <rpc/server.h> #include <rpc/util.h> @@ -25,6 +26,7 @@ #include <utilmoneystr.h> #include <wallet/coincontrol.h> #include <wallet/feebumper.h> +#include <wallet/rpcwallet.h> #include <wallet/wallet.h> #include <wallet/walletdb.h> #include <wallet/walletutil.h> @@ -3235,6 +3237,75 @@ UniValue fundrawtransaction(const JSONRPCRequest& request) return result; } +UniValue signrawtransactionwithwallet(const JSONRPCRequest& request) +{ + CWallet * const pwallet = GetWalletForJSONRPCRequest(request); + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { + return NullUniValue; + } + + if (request.fHelp || request.params.size() < 1 || request.params.size() > 3) + throw std::runtime_error( + "signrawtransactionwithwallet \"hexstring\" ( [{\"txid\":\"id\",\"vout\":n,\"scriptPubKey\":\"hex\",\"redeemScript\":\"hex\"},...] sighashtype )\n" + "\nSign inputs for raw transaction (serialized, hex-encoded).\n" + "The second optional argument (may be null) is an array of previous transaction outputs that\n" + "this transaction depends on but may not yet be in the block chain.\n" + + HelpRequiringPassphrase(pwallet) + "\n" + + "\nArguments:\n" + "1. \"hexstring\" (string, required) The transaction hex string\n" + "2. \"prevtxs\" (string, optional) An json array of previous dependent transaction outputs\n" + " [ (json array of json objects, or 'null' if none provided)\n" + " {\n" + " \"txid\":\"id\", (string, required) The transaction id\n" + " \"vout\":n, (numeric, required) The output number\n" + " \"scriptPubKey\": \"hex\", (string, required) script key\n" + " \"redeemScript\": \"hex\", (string, required for P2SH or P2WSH) redeem script\n" + " \"amount\": value (numeric, required) The amount spent\n" + " }\n" + " ,...\n" + " ]\n" + "3. \"sighashtype\" (string, optional, default=ALL) The signature hash type. Must be one of\n" + " \"ALL\"\n" + " \"NONE\"\n" + " \"SINGLE\"\n" + " \"ALL|ANYONECANPAY\"\n" + " \"NONE|ANYONECANPAY\"\n" + " \"SINGLE|ANYONECANPAY\"\n" + + "\nResult:\n" + "{\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" + " \"errors\" : [ (json array of objects) Script verification errors (if there are any)\n" + " {\n" + " \"txid\" : \"hash\", (string) The hash of the referenced, previous transaction\n" + " \"vout\" : n, (numeric) The index of the output to spent and used as input\n" + " \"scriptSig\" : \"hex\", (string) The hex-encoded signature script\n" + " \"sequence\" : n, (numeric) Script sequence number\n" + " \"error\" : \"text\" (string) Verification or signing error related to the input\n" + " }\n" + " ,...\n" + " ]\n" + "}\n" + + "\nExamples:\n" + + HelpExampleCli("signrawtransactionwithwallet", "\"myhex\"") + + HelpExampleRpc("signrawtransactionwithwallet", "\"myhex\"") + ); + + RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VARR, UniValue::VSTR}, true); + + CMutableTransaction mtx; + if (!DecodeHexTx(mtx, request.params[0].get_str(), true)) { + throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed"); + } + + // Sign the transaction + LOCK2(cs_main, pwallet->cs_wallet); + return SignTransaction(mtx, request.params[1], pwallet, false, request.params[2]); +} + UniValue bumpfee(const JSONRPCRequest& request) { CWallet * const pwallet = GetWalletForJSONRPCRequest(request); @@ -3514,6 +3585,209 @@ UniValue rescanblockchain(const JSONRPCRequest& request) return response; } +class DescribeWalletAddressVisitor : public boost::static_visitor<UniValue> +{ +public: + CWallet * const pwallet; + + void ProcessSubScript(const CScript& subscript, UniValue& obj, bool include_addresses = false) const + { + // Always present: script type and redeemscript + txnouttype which_type; + std::vector<std::vector<unsigned char>> solutions_data; + Solver(subscript, which_type, solutions_data); + obj.pushKV("script", GetTxnOutputType(which_type)); + obj.pushKV("hex", HexStr(subscript.begin(), subscript.end())); + + CTxDestination embedded; + UniValue a(UniValue::VARR); + if (ExtractDestination(subscript, embedded)) { + // Only when the script corresponds to an address. + UniValue subobj(UniValue::VOBJ); + UniValue detail = DescribeAddress(embedded); + subobj.pushKVs(detail); + UniValue wallet_detail = boost::apply_visitor(*this, embedded); + subobj.pushKVs(wallet_detail); + subobj.pushKV("address", EncodeDestination(embedded)); + subobj.pushKV("scriptPubKey", HexStr(subscript.begin(), subscript.end())); + // Always report the pubkey at the top level, so that `getnewaddress()['pubkey']` always works. + if (subobj.exists("pubkey")) obj.pushKV("pubkey", subobj["pubkey"]); + obj.pushKV("embedded", std::move(subobj)); + if (include_addresses) a.push_back(EncodeDestination(embedded)); + } else if (which_type == TX_MULTISIG) { + // Also report some information on multisig scripts (which do not have a corresponding address). + // TODO: abstract out the common functionality between this logic and ExtractDestinations. + obj.pushKV("sigsrequired", solutions_data[0][0]); + UniValue pubkeys(UniValue::VARR); + for (size_t i = 1; i < solutions_data.size() - 1; ++i) { + CPubKey key(solutions_data[i].begin(), solutions_data[i].end()); + if (include_addresses) a.push_back(EncodeDestination(key.GetID())); + pubkeys.push_back(HexStr(key.begin(), key.end())); + } + obj.pushKV("pubkeys", std::move(pubkeys)); + } + + // The "addresses" field is confusing because it refers to public keys using their P2PKH address. + // For that reason, only add the 'addresses' field when needed for backward compatibility. New applications + // can use the 'embedded'->'address' field for P2SH or P2WSH wrapped addresses, and 'pubkeys' for + // inspecting multisig participants. + if (include_addresses) obj.pushKV("addresses", std::move(a)); + } + + explicit DescribeWalletAddressVisitor(CWallet* _pwallet) : pwallet(_pwallet) {} + + UniValue operator()(const CNoDestination& dest) const { return UniValue(UniValue::VOBJ); } + + UniValue operator()(const CKeyID& keyID) const + { + UniValue obj(UniValue::VOBJ); + CPubKey vchPubKey; + if (pwallet && pwallet->GetPubKey(keyID, vchPubKey)) { + obj.pushKV("pubkey", HexStr(vchPubKey)); + obj.pushKV("iscompressed", vchPubKey.IsCompressed()); + } + return obj; + } + + UniValue operator()(const CScriptID& scriptID) const + { + UniValue obj(UniValue::VOBJ); + CScript subscript; + if (pwallet && pwallet->GetCScript(scriptID, subscript)) { + ProcessSubScript(subscript, obj, IsDeprecatedRPCEnabled("validateaddress")); + } + return obj; + } + + UniValue operator()(const WitnessV0KeyHash& id) const + { + UniValue obj(UniValue::VOBJ); + CPubKey pubkey; + if (pwallet && pwallet->GetPubKey(CKeyID(id), pubkey)) { + obj.pushKV("pubkey", HexStr(pubkey)); + } + return obj; + } + + UniValue operator()(const WitnessV0ScriptHash& id) const + { + UniValue obj(UniValue::VOBJ); + CScript subscript; + CRIPEMD160 hasher; + uint160 hash; + hasher.Write(id.begin(), 32).Finalize(hash.begin()); + if (pwallet && pwallet->GetCScript(CScriptID(hash), subscript)) { + ProcessSubScript(subscript, obj); + } + return obj; + } + + UniValue operator()(const WitnessUnknown& id) const { return UniValue(UniValue::VOBJ); } +}; + +UniValue DescribeWalletAddress(CWallet* pwallet, const CTxDestination& dest) +{ + UniValue ret(UniValue::VOBJ); + UniValue detail = DescribeAddress(dest); + ret.pushKVs(detail); + ret.pushKVs(boost::apply_visitor(DescribeWalletAddressVisitor(pwallet), dest)); + return ret; +} + +UniValue getaddressinfo(const JSONRPCRequest& request) +{ + CWallet * const pwallet = GetWalletForJSONRPCRequest(request); + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { + return NullUniValue; + } + + if (request.fHelp || request.params.size() != 1) { + throw std::runtime_error( + "getaddressinfo \"address\"\n" + "\nReturn information about the given bitcoin address. Some information requires the address\n" + "to be in the wallet.\n" + "\nArguments:\n" + "1. \"address\" (string, required) The bitcoin address to get the information of.\n" + "\nResult:\n" + "{\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" + " \"iswatchonly\" : true|false, (boolean) If the address is watchonly\n" + " \"isscript\" : true|false, (boolean) If the key is a script\n" + " \"iswitness\" : true|false, (boolean) If the address is a witness address\n" + " \"witness_version\" : version (numeric, optional) The version number of the witness program\n" + " \"witness_program\" : \"hex\" (string, optional) The hex value of the witness program\n" + " \"script\" : \"type\" (string, optional) The output script type. Only if \"isscript\" is true and the redeemscript is known. Possible types: nonstandard, pubkey, pubkeyhash, scripthash, multisig, nulldata, witness_v0_keyhash, witness_v0_scripthash, witness_unknown\n" + " \"hex\" : \"hex\", (string, optional) The redeemscript for the p2sh address\n" + " \"pubkeys\" (string, optional) Array of pubkeys associated with the known redeemscript (only if \"script\" is \"multisig\")\n" + " [\n" + " \"pubkey\"\n" + " ,...\n" + " ]\n" + " \"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\", \"hdmasterkeyid\") and relation to the wallet (\"ismine\", \"iswatchonly\", \"account\").\n" + " \"iscompressed\" : true|false, (boolean) If the address is compressed\n" + " \"account\" : \"account\" (string) The account associated with the address, \"\" is the default account\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" + " \"hdmasterkeyid\" : \"<hash160>\" (string, optional) The Hash160 of the HD master pubkey\n" + "}\n" + "\nExamples:\n" + + HelpExampleCli("getaddressinfo", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"") + + HelpExampleRpc("getaddressinfo", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"") + ); + } + + LOCK(pwallet->cs_wallet); + + UniValue ret(UniValue::VOBJ); + CTxDestination dest = DecodeDestination(request.params[0].get_str()); + + // Make sure the destination is valid + if (!IsValidDestination(dest)) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address"); + } + + std::string currentAddress = EncodeDestination(dest); + ret.pushKV("address", currentAddress); + + CScript scriptPubKey = GetScriptForDestination(dest); + ret.pushKV("scriptPubKey", HexStr(scriptPubKey.begin(), scriptPubKey.end())); + + isminetype mine = IsMine(*pwallet, dest); + ret.pushKV("ismine", bool(mine & ISMINE_SPENDABLE)); + ret.pushKV("iswatchonly", bool(mine & ISMINE_WATCH_ONLY)); + UniValue detail = DescribeWalletAddress(pwallet, dest); + ret.pushKVs(detail); + if (pwallet->mapAddressBook.count(dest)) { + ret.pushKV("account", pwallet->mapAddressBook[dest].name); + } + const CKeyMetadata* meta = nullptr; + CKeyID key_id = GetKeyForDestination(*pwallet, dest); + if (!key_id.IsNull()) { + auto it = pwallet->mapKeyMetadata.find(key_id); + if (it != pwallet->mapKeyMetadata.end()) { + meta = &it->second; + } + } + if (!meta) { + auto it = pwallet->m_script_metadata.find(CScriptID(scriptPubKey)); + if (it != pwallet->m_script_metadata.end()) { + meta = &it->second; + } + } + if (meta) { + ret.pushKV("timestamp", meta->nCreateTime); + if (!meta->hdKeypath.empty()) { + ret.pushKV("hdkeypath", meta->hdKeypath); + ret.pushKV("hdmasterkeyid", meta->hdMasterKeyID.GetHex()); + } + } + return ret; +} + extern UniValue abortrescan(const JSONRPCRequest& request); // in rpcdump.cpp extern UniValue dumpprivkey(const JSONRPCRequest& request); // in rpcdump.cpp extern UniValue importprivkey(const JSONRPCRequest& request); @@ -3527,61 +3801,63 @@ extern UniValue importmulti(const JSONRPCRequest& request); extern UniValue rescanblockchain(const JSONRPCRequest& request); static const CRPCCommand commands[] = -{ // category name actor (function) argNames - // --------------------- ------------------------ ----------------------- ---------- - { "rawtransactions", "fundrawtransaction", &fundrawtransaction, {"hexstring","options","iswitness"} }, - { "hidden", "resendwallettransactions", &resendwallettransactions, {} }, - { "wallet", "abandontransaction", &abandontransaction, {"txid"} }, - { "wallet", "abortrescan", &abortrescan, {} }, - { "wallet", "addmultisigaddress", &addmultisigaddress, {"nrequired","keys","account","address_type"} }, - { "hidden", "addwitnessaddress", &addwitnessaddress, {"address","p2sh"} }, - { "wallet", "backupwallet", &backupwallet, {"destination"} }, - { "wallet", "bumpfee", &bumpfee, {"txid", "options"} }, - { "wallet", "dumpprivkey", &dumpprivkey, {"address"} }, - { "wallet", "dumpwallet", &dumpwallet, {"filename"} }, - { "wallet", "encryptwallet", &encryptwallet, {"passphrase"} }, - { "wallet", "getaccountaddress", &getaccountaddress, {"account"} }, - { "wallet", "getaccount", &getaccount, {"address"} }, - { "wallet", "getaddressesbyaccount", &getaddressesbyaccount, {"account"} }, - { "wallet", "getbalance", &getbalance, {"account","minconf","include_watchonly"} }, - { "wallet", "getnewaddress", &getnewaddress, {"account","address_type"} }, - { "wallet", "getrawchangeaddress", &getrawchangeaddress, {"address_type"} }, - { "wallet", "getreceivedbyaccount", &getreceivedbyaccount, {"account","minconf"} }, - { "wallet", "getreceivedbyaddress", &getreceivedbyaddress, {"address","minconf"} }, - { "wallet", "gettransaction", &gettransaction, {"txid","include_watchonly"} }, - { "wallet", "getunconfirmedbalance", &getunconfirmedbalance, {} }, - { "wallet", "getwalletinfo", &getwalletinfo, {} }, - { "wallet", "importmulti", &importmulti, {"requests","options"} }, - { "wallet", "importprivkey", &importprivkey, {"privkey","label","rescan"} }, - { "wallet", "importwallet", &importwallet, {"filename"} }, - { "wallet", "importaddress", &importaddress, {"address","label","rescan","p2sh"} }, - { "wallet", "importprunedfunds", &importprunedfunds, {"rawtransaction","txoutproof"} }, - { "wallet", "importpubkey", &importpubkey, {"pubkey","label","rescan"} }, - { "wallet", "keypoolrefill", &keypoolrefill, {"newsize"} }, - { "wallet", "listaccounts", &listaccounts, {"minconf","include_watchonly"} }, - { "wallet", "listaddressgroupings", &listaddressgroupings, {} }, - { "wallet", "listlockunspent", &listlockunspent, {} }, - { "wallet", "listreceivedbyaccount", &listreceivedbyaccount, {"minconf","include_empty","include_watchonly"} }, - { "wallet", "listreceivedbyaddress", &listreceivedbyaddress, {"minconf","include_empty","include_watchonly"} }, - { "wallet", "listsinceblock", &listsinceblock, {"blockhash","target_confirmations","include_watchonly","include_removed"} }, - { "wallet", "listtransactions", &listtransactions, {"account","count","skip","include_watchonly"} }, - { "wallet", "listunspent", &listunspent, {"minconf","maxconf","addresses","include_unsafe","query_options"} }, - { "wallet", "listwallets", &listwallets, {} }, - { "wallet", "lockunspent", &lockunspent, {"unlock","transactions"} }, - { "wallet", "move", &movecmd, {"fromaccount","toaccount","amount","minconf","comment"} }, - { "wallet", "sendfrom", &sendfrom, {"fromaccount","toaddress","amount","minconf","comment","comment_to"} }, - { "wallet", "sendmany", &sendmany, {"fromaccount","amounts","minconf","comment","subtractfeefrom","replaceable","conf_target","estimate_mode"} }, - { "wallet", "sendtoaddress", &sendtoaddress, {"address","amount","comment","comment_to","subtractfeefromamount","replaceable","conf_target","estimate_mode"} }, - { "wallet", "setaccount", &setaccount, {"address","account"} }, - { "wallet", "settxfee", &settxfee, {"amount"} }, - { "wallet", "signmessage", &signmessage, {"address","message"} }, - { "wallet", "walletlock", &walletlock, {} }, - { "wallet", "walletpassphrasechange", &walletpassphrasechange, {"oldpassphrase","newpassphrase"} }, - { "wallet", "walletpassphrase", &walletpassphrase, {"passphrase","timeout"} }, - { "wallet", "removeprunedfunds", &removeprunedfunds, {"txid"} }, - { "wallet", "rescanblockchain", &rescanblockchain, {"start_height", "stop_height"} }, - - { "generating", "generate", &generate, {"nblocks","maxtries"} }, +{ // category name actor (function) argNames + // --------------------- ------------------------ ----------------------- ---------- + { "rawtransactions", "fundrawtransaction", &fundrawtransaction, {"hexstring","options","iswitness"} }, + { "hidden", "resendwallettransactions", &resendwallettransactions, {} }, + { "wallet", "abandontransaction", &abandontransaction, {"txid"} }, + { "wallet", "abortrescan", &abortrescan, {} }, + { "wallet", "addmultisigaddress", &addmultisigaddress, {"nrequired","keys","account","address_type"} }, + { "hidden", "addwitnessaddress", &addwitnessaddress, {"address","p2sh"} }, + { "wallet", "backupwallet", &backupwallet, {"destination"} }, + { "wallet", "bumpfee", &bumpfee, {"txid", "options"} }, + { "wallet", "dumpprivkey", &dumpprivkey, {"address"} }, + { "wallet", "dumpwallet", &dumpwallet, {"filename"} }, + { "wallet", "encryptwallet", &encryptwallet, {"passphrase"} }, + { "wallet", "getaccountaddress", &getaccountaddress, {"account"} }, + { "wallet", "getaccount", &getaccount, {"address"} }, + { "wallet", "getaddressesbyaccount", &getaddressesbyaccount, {"account"} }, + { "wallet", "getaddressinfo", &getaddressinfo, {"address"} }, + { "wallet", "getbalance", &getbalance, {"account","minconf","include_watchonly"} }, + { "wallet", "getnewaddress", &getnewaddress, {"account","address_type"} }, + { "wallet", "getrawchangeaddress", &getrawchangeaddress, {"address_type"} }, + { "wallet", "getreceivedbyaccount", &getreceivedbyaccount, {"account","minconf"} }, + { "wallet", "getreceivedbyaddress", &getreceivedbyaddress, {"address","minconf"} }, + { "wallet", "gettransaction", &gettransaction, {"txid","include_watchonly"} }, + { "wallet", "getunconfirmedbalance", &getunconfirmedbalance, {} }, + { "wallet", "getwalletinfo", &getwalletinfo, {} }, + { "wallet", "importmulti", &importmulti, {"requests","options"} }, + { "wallet", "importprivkey", &importprivkey, {"privkey","label","rescan"} }, + { "wallet", "importwallet", &importwallet, {"filename"} }, + { "wallet", "importaddress", &importaddress, {"address","label","rescan","p2sh"} }, + { "wallet", "importprunedfunds", &importprunedfunds, {"rawtransaction","txoutproof"} }, + { "wallet", "importpubkey", &importpubkey, {"pubkey","label","rescan"} }, + { "wallet", "keypoolrefill", &keypoolrefill, {"newsize"} }, + { "wallet", "listaccounts", &listaccounts, {"minconf","include_watchonly"} }, + { "wallet", "listaddressgroupings", &listaddressgroupings, {} }, + { "wallet", "listlockunspent", &listlockunspent, {} }, + { "wallet", "listreceivedbyaccount", &listreceivedbyaccount, {"minconf","include_empty","include_watchonly"} }, + { "wallet", "listreceivedbyaddress", &listreceivedbyaddress, {"minconf","include_empty","include_watchonly"} }, + { "wallet", "listsinceblock", &listsinceblock, {"blockhash","target_confirmations","include_watchonly","include_removed"} }, + { "wallet", "listtransactions", &listtransactions, {"account","count","skip","include_watchonly"} }, + { "wallet", "listunspent", &listunspent, {"minconf","maxconf","addresses","include_unsafe","query_options"} }, + { "wallet", "listwallets", &listwallets, {} }, + { "wallet", "lockunspent", &lockunspent, {"unlock","transactions"} }, + { "wallet", "move", &movecmd, {"fromaccount","toaccount","amount","minconf","comment"} }, + { "wallet", "sendfrom", &sendfrom, {"fromaccount","toaddress","amount","minconf","comment","comment_to"} }, + { "wallet", "sendmany", &sendmany, {"fromaccount","amounts","minconf","comment","subtractfeefrom","replaceable","conf_target","estimate_mode"} }, + { "wallet", "sendtoaddress", &sendtoaddress, {"address","amount","comment","comment_to","subtractfeefromamount","replaceable","conf_target","estimate_mode"} }, + { "wallet", "setaccount", &setaccount, {"address","account"} }, + { "wallet", "settxfee", &settxfee, {"amount"} }, + { "wallet", "signmessage", &signmessage, {"address","message"} }, + { "wallet", "signrawtransactionwithwallet", &signrawtransactionwithwallet, {"hexstring","prevtxs","sighashtype"} }, + { "wallet", "walletlock", &walletlock, {} }, + { "wallet", "walletpassphrasechange", &walletpassphrasechange, {"oldpassphrase","newpassphrase"} }, + { "wallet", "walletpassphrase", &walletpassphrase, {"passphrase","timeout"} }, + { "wallet", "removeprunedfunds", &removeprunedfunds, {"txid"} }, + { "wallet", "rescanblockchain", &rescanblockchain, {"start_height", "stop_height"} }, + + { "generating", "generate", &generate, {"nblocks","maxtries"} }, }; void RegisterWalletRPCCommands(CRPCTable &t) diff --git a/src/wallet/rpcwallet.h b/src/wallet/rpcwallet.h index 77f7b42b23..84f161abb5 100644 --- a/src/wallet/rpcwallet.h +++ b/src/wallet/rpcwallet.h @@ -10,6 +10,7 @@ class CRPCTable; class CWallet; class JSONRPCRequest; +class UniValue; void RegisterWalletRPCCommands(CRPCTable &t); @@ -25,4 +26,6 @@ std::string HelpRequiringPassphrase(CWallet *); void EnsureWalletIsUnlocked(CWallet *); bool EnsureWalletIsAvailable(CWallet *, bool avoidException); +UniValue getaddressinfo(const JSONRPCRequest& request); +UniValue signrawtransactionwithwallet(const JSONRPCRequest& request); #endif //BITCOIN_WALLET_RPCWALLET_H diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 408a01c50b..b35f8c7f2b 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1668,20 +1668,15 @@ CBlockIndex* CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, CBlock dProgressStart = GuessVerificationProgress(chainParams.TxData(), pindex); dProgressTip = GuessVerificationProgress(chainParams.TxData(), tip); } + double gvp = dProgressStart; while (pindex && !fAbortRescan) { if (pindex->nHeight % 100 == 0 && dProgressTip - dProgressStart > 0.0) { - double gvp = 0; - { - LOCK(cs_main); - gvp = GuessVerificationProgress(chainParams.TxData(), pindex); - } ShowProgress(_("Rescanning..."), std::max(1, std::min(99, (int)((gvp - dProgressStart) / (dProgressTip - dProgressStart) * 100)))); } if (GetTime() >= nNow + 60) { nNow = GetTime(); - LOCK(cs_main); - LogPrintf("Still rescanning. At block %d. Progress=%f\n", pindex->nHeight, GuessVerificationProgress(chainParams.TxData(), pindex)); + LogPrintf("Still rescanning. At block %d. Progress=%f\n", pindex->nHeight, gvp); } CBlock block; @@ -1705,6 +1700,7 @@ CBlockIndex* CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, CBlock { LOCK(cs_main); pindex = chainActive.Next(pindex); + gvp = GuessVerificationProgress(chainParams.TxData(), pindex); if (tip != chainActive.Tip()) { tip = chainActive.Tip(); // in case the tip has changed, update progress max @@ -1713,7 +1709,7 @@ CBlockIndex* CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, CBlock } } if (pindex && fAbortRescan) { - LogPrintf("Rescan aborted at block %d. Progress=%f\n", pindex->nHeight, GuessVerificationProgress(chainParams.TxData(), pindex)); + LogPrintf("Rescan aborted at block %d. Progress=%f\n", pindex->nHeight, gvp); } ShowProgress(_("Rescanning..."), 100); // hide progress dialog in GUI } |