Merge pull request #2646 from PastaPastaPasta/backports-0.15-pr4

Backports 0.15 pr4
This commit is contained in:
Alexander Block 2019-01-29 15:52:03 +01:00 committed by GitHub
commit 15e1c3b080
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 720 additions and 515 deletions

View File

@ -56,7 +56,7 @@ class Variant(collections.namedtuple("Variant", "call data rescan prune")):
"scriptPubKey": {
"address": self.address["address"]
},
"timestamp": timestamp + RESCAN_WINDOW + (1 if self.rescan == Rescan.late_timestamp else 0),
"timestamp": timestamp + TIMESTAMP_WINDOW + (1 if self.rescan == Rescan.late_timestamp else 0),
"pubkeys": [self.address["pubkey"]] if self.data == Data.pub else [],
"keys": [self.key] if self.data == Data.priv else [],
"label": self.label,
@ -108,7 +108,7 @@ ImportNode = collections.namedtuple("ImportNode", "prune rescan")
IMPORT_NODES = [ImportNode(*fields) for fields in itertools.product((False, True), repeat=2)]
# Rescans start at the earliest block up to 2 hours before the key timestamp.
RESCAN_WINDOW = 2 * 60 * 60
TIMESTAMP_WINDOW = 2 * 60 * 60
class ImportRescanTest(BitcoinTestFramework):
@ -142,7 +142,7 @@ class ImportRescanTest(BitcoinTestFramework):
self.nodes[0].generate(1)
assert_equal(self.nodes[0].getrawmempool(), [])
timestamp = self.nodes[0].getblockheader(self.nodes[0].getbestblockhash())["time"]
set_node_times(self.nodes, timestamp + RESCAN_WINDOW + 1)
set_node_times(self.nodes, timestamp + TIMESTAMP_WINDOW + 1)
self.nodes[0].generate(1)
sync_blocks(self.nodes)

View File

@ -19,7 +19,7 @@ MIN_BLOCKS_TO_KEEP = 288
# Rescans start at the earliest block up to 2 hours before a key timestamp, so
# the manual prune RPC avoids pruning blocks in the same window to be
# compatible with pruning based on key creation time.
RESCAN_WINDOW = 2 * 60 * 60
TIMESTAMP_WINDOW = 2 * 60 * 60
def calc_usage(blockdir):
@ -242,7 +242,7 @@ class PruneTest(BitcoinTestFramework):
def height(index):
if use_timestamp:
return node.getblockheader(node.getblockhash(index))["time"] + RESCAN_WINDOW
return node.getblockheader(node.getblockhash(index))["time"] + TIMESTAMP_WINDOW
else:
return index

View File

@ -14,6 +14,20 @@
#include <vector>
/**
* Maximum amount of time that a block timestamp is allowed to exceed the
* current network-adjusted time before the block will be accepted.
*/
static const int64_t MAX_FUTURE_BLOCK_TIME = 2 * 60 * 60;
/**
* Timestamp window used as a grace period by code that compares external
* timestamps (such as timestamps passed to RPCs, or wallet key creation times)
* to block timestamps. This should be set at least as high as
* MAX_FUTURE_BLOCK_TIME.
*/
static const int64_t TIMESTAMP_WINDOW = MAX_FUTURE_BLOCK_TIME;
class CBlockFileInfo
{
public:

View File

@ -1009,7 +1009,7 @@ UniValue pruneblockchain(const JSONRPCRequest& request)
// too low to be a block time (corresponds to timestamp from Sep 2001).
if (heightParam > 1000000000) {
// Add a 2 hour buffer to include blocks which might have had old timestamps
CBlockIndex* pindex = chainActive.FindEarliestAtLeast(heightParam - 7200);
CBlockIndex* pindex = chainActive.FindEarliestAtLeast(heightParam - TIMESTAMP_WINDOW);
if (!pindex) {
throw JSONRPCError(RPC_INTERNAL_ERROR, "Could not find block with at least the specified timestamp.");
}

View File

@ -17,12 +17,11 @@
#include "rpc/server.h"
#include "util.h"
#include "utilmoneystr.h"
#include "wallet/rpcwallet.h"
#ifdef ENABLE_WALLET
#include "wallet/wallet.h"
#endif // ENABLE_WALLET
bool EnsureWalletIsAvailable(bool avoidException);
void gobject_count_help()
{
throw std::runtime_error(
@ -137,10 +136,11 @@ void gobject_prepare_help()
UniValue gobject_prepare(const JSONRPCRequest& request)
{
CWallet* const pwallet = GetWalletForJSONRPCRequest(request);
if (request.fHelp || (request.params.size() != 5 && request.params.size() != 6 && request.params.size() != 8))
gobject_prepare_help();
if (!EnsureWalletIsAvailable(request.fHelp))
if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
return NullUniValue;
// ASSEMBLE NEW GOVERNANCE OBJECT FROM USER PARAMETERS
@ -190,13 +190,13 @@ UniValue gobject_prepare(const JSONRPCRequest& request)
throw JSONRPCError(RPC_INVALID_PARAMETER, "Watchdogs are deprecated");
}
LOCK2(cs_main, pwalletMain->cs_wallet);
LOCK2(cs_main, pwallet->cs_wallet);
std::string strError = "";
if (!govobj.IsValidLocally(strError, false))
throw JSONRPCError(RPC_INTERNAL_ERROR, "Governance object is not valid - " + govobj.GetHash().ToString() + " - " + strError);
EnsureWalletIsUnlocked();
EnsureWalletIsUnlocked(pwallet);
// If specified, spend this outpoint as the proposal fee
COutPoint outpoint;
@ -211,17 +211,17 @@ UniValue gobject_prepare(const JSONRPCRequest& request)
}
CWalletTx wtx;
if (!pwalletMain->GetBudgetSystemCollateralTX(wtx, govobj.GetHash(), govobj.GetMinCollateralFee(), useIS, outpoint)) {
if (!pwallet->GetBudgetSystemCollateralTX(wtx, govobj.GetHash(), govobj.GetMinCollateralFee(), useIS, outpoint)) {
std::string err = "Error making collateral transaction for governance object. Please check your wallet balance and make sure your wallet is unlocked.";
if (request.params.size() == 8) err += "Please verify your specified output is valid and is enough for the combined proposal fee and transaction fee.";
throw JSONRPCError(RPC_INTERNAL_ERROR, err);
}
// -- make our change address
CReserveKey reservekey(pwalletMain);
CReserveKey reservekey(pwallet);
// -- send the tx to the network
CValidationState state;
if (!pwalletMain->CommitTransaction(wtx, reservekey, g_connman.get(), state, NetMsgType::TX)) {
if (!pwallet->CommitTransaction(wtx, reservekey, g_connman.get(), state, NetMsgType::TX)) {
throw JSONRPCError(RPC_INTERNAL_ERROR, "CommitTransaction failed! Reason given: " + state.GetRejectReason());
}
@ -536,6 +536,7 @@ void gobject_vote_many_help()
UniValue gobject_vote_many(const JSONRPCRequest& request)
{
CWallet* const pwallet = GetWalletForJSONRPCRequest(request);
if (request.fHelp || request.params.size() != 4)
gobject_vote_many_help();
@ -555,7 +556,7 @@ UniValue gobject_vote_many(const JSONRPCRequest& request)
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid vote outcome. Please use one of the following: 'yes', 'no' or 'abstain'");
}
if (!pwalletMain) {
if (!pwallet) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "vote-many not supported when wallet is disabled.");
}
@ -564,7 +565,7 @@ UniValue gobject_vote_many(const JSONRPCRequest& request)
auto mnList = deterministicMNManager->GetListAtChainTip();
mnList.ForEachMN(true, [&](const CDeterministicMNCPtr& dmn) {
CKey votingKey;
if (pwalletMain->GetKey(dmn->pdmnState->keyIDVoting, votingKey)) {
if (pwallet->GetKey(dmn->pdmnState->keyIDVoting, votingKey)) {
votingKeys.emplace(dmn->proTxHash, votingKey);
}
});
@ -587,6 +588,7 @@ void gobject_vote_alias_help()
UniValue gobject_vote_alias(const JSONRPCRequest& request)
{
CWallet* const pwallet = GetWalletForJSONRPCRequest(request);
if (request.fHelp || request.params.size() != 5)
gobject_vote_alias_help();
@ -606,7 +608,7 @@ UniValue gobject_vote_alias(const JSONRPCRequest& request)
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid vote outcome. Please use one of the following: 'yes', 'no' or 'abstain'");
}
if (!pwalletMain) {
if (!pwallet) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "vote-alias not supported when wallet is disabled");
}

View File

@ -19,6 +19,8 @@
#include "utilmoneystr.h"
#include "txmempool.h"
#include "wallet/rpcwallet.h"
#include "evo/specialtx.h"
#include "evo/deterministicmns.h"
@ -28,14 +30,11 @@
UniValue masternodelist(const JSONRPCRequest& request);
bool EnsureWalletIsAvailable(bool avoidException);
#ifdef ENABLE_WALLET
void EnsureWalletIsUnlocked();
UniValue privatesend(const JSONRPCRequest& request)
{
if (!EnsureWalletIsAvailable(request.fHelp))
CWallet* const pwallet = GetWalletForJSONRPCRequest(request);
if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
return NullUniValue;
if (request.fHelp || request.params.size() != 1)
@ -54,8 +53,8 @@ UniValue privatesend(const JSONRPCRequest& request)
if (request.params[0].get_str() == "start") {
{
LOCK(pwalletMain->cs_wallet);
if (pwalletMain->IsLocked(true))
LOCK(pwallet->cs_wallet);
if (pwallet->IsLocked(true))
throw JSONRPCError(RPC_WALLET_UNLOCK_NEEDED, "Error: Please unlock wallet for mixing with walletpassphrase first.");
}
@ -107,9 +106,10 @@ UniValue getpoolinfo(const JSONRPCRequest& request)
obj.push_back(Pair("pools", pools));
}
if (pwalletMain) {
obj.push_back(Pair("keys_left", pwalletMain->nKeysLeftSinceAutoBackup));
obj.push_back(Pair("warnings", pwalletMain->nKeysLeftSinceAutoBackup < PRIVATESEND_KEYS_THRESHOLD_WARNING
CWallet* const pwallet = GetWalletForJSONRPCRequest(request);
if (pwallet) {
obj.push_back(Pair("keys_left", pwallet->nKeysLeftSinceAutoBackup));
obj.push_back(Pair("warnings", pwallet->nKeysLeftSinceAutoBackup < PRIVATESEND_KEYS_THRESHOLD_WARNING
? "WARNING: keypool is almost depleted!" : ""));
}
#else // ENABLE_WALLET
@ -311,15 +311,16 @@ void masternode_outputs_help()
UniValue masternode_outputs(const JSONRPCRequest& request)
{
CWallet* const pwallet = GetWalletForJSONRPCRequest(request);
if (request.fHelp)
masternode_outputs_help();
if (!EnsureWalletIsAvailable(request.fHelp))
if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
return NullUniValue;
// Find possible candidates
std::vector<COutput> vPossibleCoins;
pwalletMain->AvailableCoins(vPossibleCoins, true, NULL, false, ONLY_1000);
pwallet->AvailableCoins(vPossibleCoins, true, NULL, false, ONLY_1000);
UniValue obj(UniValue::VOBJ);
for (const auto& out : vPossibleCoins) {

View File

@ -16,6 +16,7 @@
#include "utilstrencodings.h"
#include "validation.h"
#ifdef ENABLE_WALLET
#include "wallet/rpcwallet.h"
#include "wallet/wallet.h"
#include "wallet/walletdb.h"
#endif
@ -75,7 +76,9 @@ UniValue getinfo(const JSONRPCRequest& request)
);
#ifdef ENABLE_WALLET
LOCK2(cs_main, pwalletMain ? &pwalletMain->cs_wallet : NULL);
CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
LOCK2(cs_main, pwallet ? &pwallet->cs_wallet : NULL);
#else
LOCK(cs_main);
#endif
@ -87,11 +90,11 @@ UniValue getinfo(const JSONRPCRequest& request)
obj.push_back(Pair("version", CLIENT_VERSION));
obj.push_back(Pair("protocolversion", PROTOCOL_VERSION));
#ifdef ENABLE_WALLET
if (pwalletMain) {
obj.push_back(Pair("walletversion", pwalletMain->GetVersion()));
obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance())));
if (pwallet) {
obj.push_back(Pair("walletversion", pwallet->GetVersion()));
obj.push_back(Pair("balance", ValueFromAmount(pwallet->GetBalance())));
if(!fLiteMode)
obj.push_back(Pair("privatesend_balance", ValueFromAmount(pwalletMain->GetAnonymizedBalance())));
obj.push_back(Pair("privatesend_balance", ValueFromAmount(pwallet->GetAnonymizedBalance())));
}
#endif
obj.push_back(Pair("blocks", (int)chainActive.Height()));
@ -102,12 +105,13 @@ UniValue getinfo(const JSONRPCRequest& request)
obj.push_back(Pair("difficulty", (double)GetDifficulty()));
obj.push_back(Pair("testnet", Params().NetworkIDString() == CBaseChainParams::TESTNET));
#ifdef ENABLE_WALLET
if (pwalletMain) {
obj.push_back(Pair("keypoololdest", pwalletMain->GetOldestKeyPoolTime()));
obj.push_back(Pair("keypoolsize", (int)pwalletMain->GetKeyPoolSize()));
if (pwallet) {
obj.push_back(Pair("keypoololdest", pwallet->GetOldestKeyPoolTime()));
obj.push_back(Pair("keypoolsize", (int)pwallet->GetKeyPoolSize()));
}
if (pwallet && pwallet->IsCrypted()) {
obj.push_back(Pair("unlocked_until", pwallet->nRelockTime));
}
if (pwalletMain && pwalletMain->IsCrypted())
obj.push_back(Pair("unlocked_until", nWalletUnlockTime));
obj.push_back(Pair("paytxfee", ValueFromAmount(payTxFee.GetFeePerK())));
#endif
obj.push_back(Pair("relayfee", ValueFromAmount(::minRelayTxFee.GetFeePerK())));
@ -181,13 +185,17 @@ UniValue mnsync(const JSONRPCRequest& request)
class DescribeAddressVisitor : public boost::static_visitor<UniValue>
{
public:
CWallet * const pwallet;
DescribeAddressVisitor(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;
obj.push_back(Pair("isscript", false));
if (pwalletMain && pwalletMain->GetPubKey(keyID, vchPubKey)) {
if (pwallet && pwallet->GetPubKey(keyID, vchPubKey)) {
obj.push_back(Pair("pubkey", HexStr(vchPubKey)));
obj.push_back(Pair("iscompressed", vchPubKey.IsCompressed()));
}
@ -198,7 +206,7 @@ public:
UniValue obj(UniValue::VOBJ);
CScript subscript;
obj.push_back(Pair("isscript", true));
if (pwalletMain && pwalletMain->GetCScript(scriptID, subscript)) {
if (pwallet && pwallet->GetCScript(scriptID, subscript)) {
std::vector<CTxDestination> addresses;
txnouttype whichType;
int nRequired;
@ -325,7 +333,9 @@ UniValue validateaddress(const JSONRPCRequest& request)
);
#ifdef ENABLE_WALLET
LOCK2(cs_main, pwalletMain ? &pwalletMain->cs_wallet : NULL);
CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
LOCK2(cs_main, pwallet ? &pwallet->cs_wallet : NULL);
#else
LOCK(cs_main);
#endif
@ -345,16 +355,17 @@ UniValue validateaddress(const JSONRPCRequest& request)
ret.push_back(Pair("scriptPubKey", HexStr(scriptPubKey.begin(), scriptPubKey.end())));
#ifdef ENABLE_WALLET
isminetype mine = pwalletMain ? IsMine(*pwalletMain, dest) : ISMINE_NO;
isminetype mine = pwallet ? IsMine(*pwallet, dest) : ISMINE_NO;
ret.push_back(Pair("ismine", (mine & ISMINE_SPENDABLE) ? true : false));
ret.push_back(Pair("iswatchonly", (mine & ISMINE_WATCH_ONLY) ? true: false));
UniValue detail = boost::apply_visitor(DescribeAddressVisitor(), dest);
UniValue detail = boost::apply_visitor(DescribeAddressVisitor(pwallet), dest);
ret.pushKVs(detail);
if (pwalletMain && pwalletMain->mapAddressBook.count(dest))
ret.push_back(Pair("account", pwalletMain->mapAddressBook[dest].name));
if (pwallet && pwallet->mapAddressBook.count(dest)) {
ret.push_back(Pair("account", pwallet->mapAddressBook[dest].name));
}
CKeyID keyID;
if (pwalletMain) {
const auto& meta = pwalletMain->mapKeyMetadata;
if (pwallet) {
const auto& meta = pwallet->mapKeyMetadata;
auto it = address.GetKeyID(keyID) ? meta.find(keyID) : meta.end();
if (it == meta.end()) {
it = meta.find(CScriptID(scriptPubKey));
@ -364,8 +375,8 @@ UniValue validateaddress(const JSONRPCRequest& request)
}
CHDChain hdChainCurrent;
if (!keyID.IsNull() && pwalletMain->mapHdPubKeys.count(keyID) && pwalletMain->GetHDChain(hdChainCurrent)) {
ret.push_back(Pair("hdkeypath", pwalletMain->mapHdPubKeys[keyID].GetKeyPath()));
if (!keyID.IsNull() && pwallet->mapHdPubKeys.count(keyID) && pwallet->GetHDChain(hdChainCurrent)) {
ret.push_back(Pair("hdkeypath", pwallet->mapHdPubKeys[keyID].GetKeyPath()));
ret.push_back(Pair("hdchainid", hdChainCurrent.GetID().GetHex()));
}
}
@ -374,10 +385,13 @@ UniValue validateaddress(const JSONRPCRequest& request)
return ret;
}
// Needed even with !ENABLE_WALLET, to pass (ignored) pointers around
class CWallet;
/**
* Used by addmultisigaddress / createmultisig:
*/
CScript _createmultisig_redeemScript(const UniValue& params)
CScript _createmultisig_redeemScript(CWallet * const pwallet, const UniValue& params)
{
int nRequired = params[0].get_int();
const UniValue& keys = params[1].get_array();
@ -399,16 +413,16 @@ CScript _createmultisig_redeemScript(const UniValue& params)
#ifdef ENABLE_WALLET
// Case 1: Dash address and we have full public key:
CBitcoinAddress address(ks);
if (pwalletMain && address.IsValid())
{
if (pwallet && address.IsValid()) {
CKeyID keyID;
if (!address.GetKeyID(keyID))
throw std::runtime_error(
strprintf("%s does not refer to a key",ks));
CPubKey vchPubKey;
if (!pwalletMain->GetPubKey(keyID, vchPubKey))
if (!pwallet->GetPubKey(keyID, vchPubKey)) {
throw std::runtime_error(
strprintf("no full public key for address %s",ks));
}
if (!vchPubKey.IsFullyValid())
throw std::runtime_error(" Invalid public key: "+ks);
pubkeys[i] = vchPubKey;
@ -440,6 +454,12 @@ CScript _createmultisig_redeemScript(const UniValue& params)
UniValue createmultisig(const JSONRPCRequest& request)
{
#ifdef ENABLE_WALLET
CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
#else
CWallet * const pwallet = NULL;
#endif
if (request.fHelp || request.params.size() < 2 || request.params.size() > 2)
{
std::string msg = "createmultisig nrequired [\"key\",...]\n"
@ -470,7 +490,7 @@ UniValue createmultisig(const JSONRPCRequest& request)
}
// Construct using pay-to-script-hash:
CScript inner = _createmultisig_redeemScript(request.params);
CScript inner = _createmultisig_redeemScript(pwallet, request.params);
CScriptID innerID(inner);
CBitcoinAddress address(innerID);

View File

@ -26,6 +26,7 @@
#include "utilstrencodings.h"
#include "instantx.h"
#ifdef ENABLE_WALLET
#include "wallet/rpcwallet.h"
#include "wallet/wallet.h"
#endif
@ -678,6 +679,10 @@ static void TxInErrorToJSON(const CTxIn& txin, UniValue& vErrorsRet, const std::
UniValue signrawtransaction(const JSONRPCRequest& request)
{
#ifdef ENABLE_WALLET
CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
#endif
if (request.fHelp || request.params.size() < 1 || request.params.size() > 4)
throw std::runtime_error(
"signrawtransaction \"hexstring\" ( [{\"txid\":\"id\",\"vout\":n,\"scriptPubKey\":\"hex\",\"redeemScript\":\"hex\"},...] [\"privatekey1\",...] sighashtype )\n"
@ -687,7 +692,7 @@ UniValue signrawtransaction(const JSONRPCRequest& request)
"The third optional argument (may be null) is an array of base58-encoded private\n"
"keys that, if given, will be the only keys used to sign the transaction.\n"
#ifdef ENABLE_WALLET
+ HelpRequiringPassphrase() + "\n"
+ HelpRequiringPassphrase(pwallet) + "\n"
#endif
"\nArguments:\n"
@ -737,7 +742,7 @@ UniValue signrawtransaction(const JSONRPCRequest& request)
);
#ifdef ENABLE_WALLET
LOCK2(cs_main, pwalletMain ? &pwalletMain->cs_wallet : NULL);
LOCK2(cs_main, pwallet ? &pwallet->cs_wallet : NULL);
#else
LOCK(cs_main);
#endif
@ -798,8 +803,9 @@ UniValue signrawtransaction(const JSONRPCRequest& request)
}
}
#ifdef ENABLE_WALLET
else if (pwalletMain)
EnsureWalletIsUnlocked();
else if (pwallet) {
EnsureWalletIsUnlocked(pwallet);
}
#endif
// Add previous txouts given in the RPC call:
@ -865,7 +871,7 @@ UniValue signrawtransaction(const JSONRPCRequest& request)
}
#ifdef ENABLE_WALLET
const CKeyStore& keystore = ((fGivenKeys || !pwalletMain) ? tempKeystore : *pwalletMain);
const CKeyStore& keystore = ((fGivenKeys || !pwallet) ? tempKeystore : *pwallet);
#else
const CKeyStore& keystore = tempKeystore;
#endif

View File

@ -14,6 +14,7 @@
#ifdef ENABLE_WALLET
#include "wallet/coincontrol.h"
#include "wallet/wallet.h"
#include "wallet/rpcwallet.h"
#endif//ENABLE_WALLET
#include "netbase.h"
@ -31,16 +32,16 @@ extern UniValue sendrawtransaction(const JSONRPCRequest& request);
#endif//ENABLE_WALLET
// Allows to specify Dash address or priv key. In case of Dash address, the priv key is taken from the wallet
static CKey ParsePrivKey(const std::string &strKeyOrAddress, bool allowAddresses = true) {
static CKey ParsePrivKey(CWallet* pwallet, const std::string &strKeyOrAddress, bool allowAddresses = true) {
CBitcoinAddress address;
if (allowAddresses && address.SetString(strKeyOrAddress) && address.IsValid()) {
#ifdef ENABLE_WALLET
if (!pwalletMain) {
if (!pwallet) {
throw std::runtime_error("addresses not supported when wallet is disabled");
}
CKeyID keyId;
CKey key;
if (!address.GetKeyID(keyId) || !pwalletMain->GetKey(keyId, key))
if (!address.GetKeyID(keyId) || !pwallet->GetKey(keyId, key))
throw std::runtime_error(strprintf("non-wallet or invalid address %s", strKeyOrAddress));
return key;
#else//ENABLE_WALLET
@ -90,10 +91,10 @@ static CBLSSecretKey ParseBLSSecretKey(const std::string& hexKey, const std::str
#ifdef ENABLE_WALLET
template<typename SpecialTxPayload>
static void FundSpecialTx(CMutableTransaction& tx, const SpecialTxPayload& payload, const CTxDestination& fundDest)
static void FundSpecialTx(CWallet* pwallet, CMutableTransaction& tx, const SpecialTxPayload& payload, const CTxDestination& fundDest)
{
assert(pwalletMain != NULL);
LOCK2(cs_main, pwalletMain->cs_wallet);
assert(pwallet != NULL);
LOCK2(cs_main, pwallet->cs_wallet);
CTxDestination nodest = CNoDestination();
if (fundDest == nodest) {
@ -124,7 +125,7 @@ static void FundSpecialTx(CMutableTransaction& tx, const SpecialTxPayload& paylo
coinControl.fRequireAllInputs = false;
std::vector<COutput> vecOutputs;
pwalletMain->AvailableCoins(vecOutputs);
pwallet->AvailableCoins(vecOutputs);
for (const auto& out : vecOutputs) {
CTxDestination txDest;
@ -143,7 +144,7 @@ static void FundSpecialTx(CMutableTransaction& tx, const SpecialTxPayload& paylo
int nChangePos = -1;
std::string strFailReason;
if (!pwalletMain->CreateTransaction(vecSend, wtx, reservekey, nFee, nChangePos, strFailReason, &coinControl, false, ALL_COINS, false, tx.vExtraPayload.size())) {
if (!pwallet->CreateTransaction(vecSend, wtx, reservekey, nFee, nChangePos, strFailReason, &coinControl, false, ALL_COINS, false, tx.vExtraPayload.size())) {
throw JSONRPCError(RPC_INTERNAL_ERROR, strFailReason);
}
@ -310,6 +311,7 @@ void protx_register_submit_help()
// handles register, register_prepare and register_fund in one method
UniValue protx_register(const JSONRPCRequest& request)
{
CWallet* const pwallet = GetWalletForJSONRPCRequest(request);
bool isExternalRegister = request.params[0].get_str() == "register";
bool isFundRegister = request.params[0].get_str() == "register_fund";
bool isPrepareRegister = request.params[0].get_str() == "register_prepare";
@ -355,8 +357,8 @@ UniValue protx_register(const JSONRPCRequest& request)
paramIdx += 2;
// TODO unlock on failure
LOCK(pwalletMain->cs_wallet);
pwalletMain->LockCoin(ptx.collateralOutpoint);
LOCK(pwallet->cs_wallet);
pwallet->LockCoin(ptx.collateralOutpoint);
}
if (request.params[paramIdx].get_str() != "") {
@ -365,7 +367,7 @@ UniValue protx_register(const JSONRPCRequest& request)
}
}
CKey keyOwner = ParsePrivKey(request.params[paramIdx + 1].get_str(), true);
CKey keyOwner = ParsePrivKey(pwallet, request.params[paramIdx + 1].get_str(), true);
CBLSPublicKey pubKeyOperator = ParseBLSPubKey(request.params[paramIdx + 2].get_str(), "operator BLS address");
CKeyID keyIDVoting = keyOwner.GetPubKey().GetID();
if (request.params[paramIdx + 3].get_str() != "") {
@ -403,7 +405,7 @@ UniValue protx_register(const JSONRPCRequest& request)
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Dash address: ") + request.params[paramIdx + 6].get_str());
}
FundSpecialTx(tx, ptx, fundAddress.Get());
FundSpecialTx(pwallet, tx, ptx, fundAddress.Get());
UpdateSpecialTxInputsHash(tx, ptx);
if (isFundRegister) {
@ -445,7 +447,7 @@ UniValue protx_register(const JSONRPCRequest& request)
} else {
// lets prove we own the collateral
CKey key;
if (!pwalletMain->GetKey(keyID, key)) {
if (!pwallet->GetKey(keyID, key)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("collateral key not in wallet: %s", CBitcoinAddress(keyID).ToString()));
}
SignSpecialTxPayloadByString(tx, ptx, key);
@ -508,6 +510,7 @@ void protx_update_service_help()
UniValue protx_update_service(const JSONRPCRequest& request)
{
CWallet* const pwallet = GetWalletForJSONRPCRequest(request);
if (request.fHelp || (request.params.size() < 4 || request.params.size() > 6))
protx_update_service_help();
@ -567,7 +570,7 @@ UniValue protx_update_service(const JSONRPCRequest& request)
}
}
FundSpecialTx(tx, ptx, feeSource);
FundSpecialTx(pwallet, tx, ptx, feeSource);
SignSpecialTxPayloadByHash(tx, ptx, keyOperator);
SetTxPayload(tx, ptx);
@ -602,6 +605,7 @@ void protx_update_registrar_help()
UniValue protx_update_registrar(const JSONRPCRequest& request)
{
CWallet* const pwallet = GetWalletForJSONRPCRequest(request);
if (request.fHelp || (request.params.size() != 5 && request.params.size() != 6)) {
protx_update_registrar_help();
}
@ -650,7 +654,7 @@ UniValue protx_update_registrar(const JSONRPCRequest& request)
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Dash address: ") + request.params[5].get_str());
}
FundSpecialTx(tx, ptx, feeSourceAddress.Get());
FundSpecialTx(pwallet, tx, ptx, feeSourceAddress.Get());
SignSpecialTxPayloadByHash(tx, ptx, keyOwner);
SetTxPayload(tx, ptx);
@ -680,6 +684,7 @@ void protx_revoke_help()
UniValue protx_revoke(const JSONRPCRequest& request)
{
CWallet* const pwallet = GetWalletForJSONRPCRequest(request);
if (request.fHelp || (request.params.size() < 3 || request.params.size() > 5)) {
protx_revoke_help();
}
@ -715,17 +720,17 @@ UniValue protx_revoke(const JSONRPCRequest& request)
CBitcoinAddress feeSourceAddress = CBitcoinAddress(request.params[4].get_str());
if (!feeSourceAddress.IsValid())
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Dash address: ") + request.params[4].get_str());
FundSpecialTx(tx, ptx, feeSourceAddress.Get());
FundSpecialTx(pwallet, tx, ptx, feeSourceAddress.Get());
} else if (dmn->pdmnState->scriptOperatorPayout != CScript()) {
// Using funds from previousely specified operator payout address
CTxDestination txDest;
ExtractDestination(dmn->pdmnState->scriptOperatorPayout, txDest);
FundSpecialTx(tx, ptx, txDest);
FundSpecialTx(pwallet, tx, ptx, txDest);
} else if (dmn->pdmnState->scriptPayout != CScript()) {
// Using funds from previousely specified masternode payout address
CTxDestination txDest;
ExtractDestination(dmn->pdmnState->scriptPayout, txDest);
FundSpecialTx(tx, ptx, txDest);
FundSpecialTx(pwallet, tx, ptx, txDest);
} else {
throw JSONRPCError(RPC_INTERNAL_ERROR, "No payout or fee source addresses found, can't revoke");
}
@ -756,28 +761,28 @@ void protx_list_help()
);
}
static bool CheckWalletOwnsKey(const CKeyID& keyID) {
static bool CheckWalletOwnsKey(CWallet* pwallet, const CKeyID& keyID) {
#ifndef ENABLE_WALLET
return false;
#else
if (!pwalletMain) {
if (!pwallet) {
return false;
}
return pwalletMain->HaveKey(keyID);
return pwallet->HaveKey(keyID);
#endif
}
static bool CheckWalletOwnsScript(const CScript& script) {
static bool CheckWalletOwnsScript(CWallet* pwallet, const CScript& script) {
#ifndef ENABLE_WALLET
return false;
#else
if (!pwalletMain) {
if (!pwallet) {
return false;
}
CTxDestination dest;
if (ExtractDestination(script, dest)) {
if ((boost::get<CKeyID>(&dest) && pwalletMain->HaveKey(*boost::get<CKeyID>(&dest))) || (boost::get<CScriptID>(&dest) && pwalletMain->HaveCScript(*boost::get<CScriptID>(&dest)))) {
if ((boost::get<CKeyID>(&dest) && pwallet->HaveKey(*boost::get<CKeyID>(&dest))) || (boost::get<CScriptID>(&dest) && pwallet->HaveCScript(*boost::get<CScriptID>(&dest)))) {
return true;
}
}
@ -785,7 +790,7 @@ static bool CheckWalletOwnsScript(const CScript& script) {
#endif
}
UniValue BuildDMNListEntry(const CDeterministicMNCPtr& dmn, bool detailed)
UniValue BuildDMNListEntry(CWallet* pwallet, const CDeterministicMNCPtr& dmn, bool detailed)
{
if (!detailed) {
return dmn->proTxHash.ToString();
@ -798,15 +803,15 @@ UniValue BuildDMNListEntry(const CDeterministicMNCPtr& dmn, bool detailed)
int confirmations = GetUTXOConfirmations(dmn->collateralOutpoint);
o.push_back(Pair("confirmations", confirmations));
bool hasOwnerKey = CheckWalletOwnsKey(dmn->pdmnState->keyIDOwner);
bool hasOwnerKey = CheckWalletOwnsKey(pwallet, dmn->pdmnState->keyIDOwner);
bool hasOperatorKey = false; //CheckWalletOwnsKey(dmn->pdmnState->keyIDOperator);
bool hasVotingKey = CheckWalletOwnsKey(dmn->pdmnState->keyIDVoting);
bool hasVotingKey = CheckWalletOwnsKey(pwallet, dmn->pdmnState->keyIDVoting);
bool ownsCollateral = false;
CTransactionRef collateralTx;
uint256 tmpHashBlock;
if (GetTransaction(dmn->collateralOutpoint.hash, collateralTx, Params().GetConsensus(), tmpHashBlock)) {
ownsCollateral = CheckWalletOwnsScript(collateralTx->vout[dmn->collateralOutpoint.n].scriptPubKey);
ownsCollateral = CheckWalletOwnsScript(pwallet, collateralTx->vout[dmn->collateralOutpoint.n].scriptPubKey);
}
UniValue walletObj(UniValue::VOBJ);
@ -814,8 +819,8 @@ UniValue BuildDMNListEntry(const CDeterministicMNCPtr& dmn, bool detailed)
walletObj.push_back(Pair("hasOperatorKey", hasOperatorKey));
walletObj.push_back(Pair("hasVotingKey", hasVotingKey));
walletObj.push_back(Pair("ownsCollateral", ownsCollateral));
walletObj.push_back(Pair("ownsPayeeScript", CheckWalletOwnsScript(dmn->pdmnState->scriptPayout)));
walletObj.push_back(Pair("ownsOperatorRewardScript", CheckWalletOwnsScript(dmn->pdmnState->scriptOperatorPayout)));
walletObj.push_back(Pair("ownsPayeeScript", CheckWalletOwnsScript(pwallet, dmn->pdmnState->scriptPayout)));
walletObj.push_back(Pair("ownsOperatorRewardScript", CheckWalletOwnsScript(pwallet, dmn->pdmnState->scriptOperatorPayout)));
o.push_back(Pair("wallet", walletObj));
return o;
@ -828,9 +833,9 @@ UniValue protx_list(const JSONRPCRequest& request)
}
#ifdef ENABLE_WALLET
bool hasWallet = pwalletMain != nullptr;
CWallet* const pwallet = GetWalletForJSONRPCRequest(request);
#else
bool hasWallet = false;
CWallet* const pwallet = nullptr;
#endif
std::string type = "registered";
@ -843,11 +848,11 @@ UniValue protx_list(const JSONRPCRequest& request)
LOCK(cs_main);
if (type == "wallet") {
if (!hasWallet) {
if (!pwallet) {
throw std::runtime_error("\"protx list wallet\" not supported when wallet is disabled");
}
#ifdef ENABLE_WALLET
LOCK2(cs_main, pwalletMain->cs_wallet);
LOCK2(cs_main, pwallet->cs_wallet);
if (request.params.size() > 3) {
protx_list_help();
@ -861,7 +866,7 @@ UniValue protx_list(const JSONRPCRequest& request)
}
std::vector<COutPoint> vOutpts;
pwalletMain->ListProTxCoins(vOutpts);
pwallet->ListProTxCoins(vOutpts);
std::set<COutPoint> setOutpts;
for (const auto& outpt : vOutpts) {
setOutpts.emplace(outpt);
@ -870,11 +875,11 @@ UniValue protx_list(const JSONRPCRequest& request)
CDeterministicMNList mnList = deterministicMNManager->GetListForBlock(chainActive[height]->GetBlockHash());
mnList.ForEachMN(false, [&](const CDeterministicMNCPtr& dmn) {
if (setOutpts.count(dmn->collateralOutpoint) ||
CheckWalletOwnsKey(dmn->pdmnState->keyIDOwner) ||
CheckWalletOwnsKey(dmn->pdmnState->keyIDVoting) ||
CheckWalletOwnsScript(dmn->pdmnState->scriptPayout) ||
CheckWalletOwnsScript(dmn->pdmnState->scriptOperatorPayout)) {
ret.push_back(BuildDMNListEntry(dmn, detailed));
CheckWalletOwnsKey(pwallet, dmn->pdmnState->keyIDOwner) ||
CheckWalletOwnsKey(pwallet, dmn->pdmnState->keyIDVoting) ||
CheckWalletOwnsScript(pwallet, dmn->pdmnState->scriptPayout) ||
CheckWalletOwnsScript(pwallet, dmn->pdmnState->scriptOperatorPayout)) {
ret.push_back(BuildDMNListEntry(pwallet, dmn, detailed));
}
});
#endif
@ -895,7 +900,7 @@ UniValue protx_list(const JSONRPCRequest& request)
CDeterministicMNList mnList = deterministicMNManager->GetListForBlock(chainActive[height]->GetBlockHash());
bool onlyValid = type == "valid";
mnList.ForEachMN(onlyValid, [&](const CDeterministicMNCPtr& dmn) {
ret.push_back(BuildDMNListEntry(dmn, detailed));
ret.push_back(BuildDMNListEntry(pwallet, dmn, detailed));
});
} else {
throw JSONRPCError(RPC_INVALID_PARAMETER, "invalid type specified");
@ -920,13 +925,19 @@ UniValue protx_info(const JSONRPCRequest& request)
protx_info_help();
}
#ifdef ENABLE_WALLET
CWallet* const pwallet = GetWalletForJSONRPCRequest(request);
#else
CWallet* const pwallet = nullptr;
#endif
uint256 proTxHash = ParseHashV(request.params[1], "proTxHash");
auto mnList = deterministicMNManager->GetListAtChainTip();
auto dmn = mnList.GetMN(proTxHash);
if (!dmn) {
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("%s not found", proTxHash.ToString()));
}
return BuildDMNListEntry(dmn, true);
return BuildDMNListEntry(pwallet, dmn, true);
}
void protx_diff_help()
@ -1013,13 +1024,13 @@ UniValue protx(const JSONRPCRequest& request)
}
#ifdef ENABLE_WALLET
bool hasWallet = pwalletMain != nullptr;
CWallet* const pwallet = GetWalletForJSONRPCRequest(request);
#else
bool hasWallet = false;
CWallet* const pwallet = nullptr;
#endif
auto checkWallet = [&](const std::string& command) {
if (!hasWallet) {
if (!pwallet) {
throw std::runtime_error(strprintf("%s not supported when wallet is disabled", command));
}
};

View File

@ -226,7 +226,7 @@ bool ParseBoolV(const UniValue& v, const std::string &strName)
* Note: This interface may still be subject to change.
*/
std::string CRPCTable::help(const std::string& strCommand, const std::string& strSubCommand) const
std::string CRPCTable::help(const std::string& strCommand, const std::string& strSubCommand, const JSONRPCRequest& helpreq) const
{
std::string strRet;
std::string category;
@ -237,16 +237,19 @@ std::string CRPCTable::help(const std::string& strCommand, const std::string& st
vCommands.push_back(make_pair(mi->second->category + mi->first, mi->second));
sort(vCommands.begin(), vCommands.end());
JSONRPCRequest jreq(helpreq);
jreq.fHelp = true;
jreq.params = UniValue();
BOOST_FOREACH(const PAIRTYPE(std::string, const CRPCCommand*)& command, vCommands)
{
const CRPCCommand *pcmd = command.second;
std::string strMethod = pcmd->name;
if ((strCommand != "" || pcmd->category == "hidden") && strMethod != strCommand)
continue;
jreq.strMethod = strMethod;
try
{
JSONRPCRequest jreq;
jreq.fHelp = true;
if (!strSubCommand.empty()) {
jreq.params.setArray();
jreq.params.push_back(strSubCommand);
@ -302,7 +305,7 @@ UniValue help(const JSONRPCRequest& jsonRequest)
if (jsonRequest.params.size() > 1)
strSubCommand = jsonRequest.params[1].get_str();
return tableRPC.help(strCommand, strSubCommand);
return tableRPC.help(strCommand, strSubCommand, jsonRequest);
}

View File

@ -152,7 +152,7 @@ private:
public:
CRPCTable();
const CRPCCommand* operator[](const std::string& name) const;
std::string help(const std::string& strCommand, const std::string& strSubCommand) const;
std::string help(const std::string& name, const std::string& strSubCommand, const JSONRPCRequest& helpreq) const;
/**
* Execute a method.
@ -192,16 +192,12 @@ extern int64_t ParseInt64V(const UniValue& v, const std::string &strName);
extern double ParseDoubleV(const UniValue& v, const std::string &strName);
extern bool ParseBoolV(const UniValue& v, const std::string &strName);
extern int64_t nWalletUnlockTime;
extern CAmount AmountFromValue(const UniValue& value);
extern UniValue ValueFromAmount(const CAmount& amount);
extern double GetDifficulty(const CBlockIndex* blockindex = NULL);
extern std::string HelpRequiringPassphrase();
extern std::string HelpExampleCli(const std::string& methodname, const std::string& args);
extern std::string HelpExampleRpc(const std::string& methodname, const std::string& args);
extern void EnsureWalletIsUnlocked();
bool StartRPC();
void InterruptRPC();
void StopRPC();

View File

@ -17,7 +17,8 @@ static const std::string CHARS_ALPHA_NUM = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJ
static const std::string SAFE_CHARS[] =
{
CHARS_ALPHA_NUM + " .,;-_/:?@()", // SAFE_CHARS_DEFAULT
CHARS_ALPHA_NUM + " .,;-_?@" // SAFE_CHARS_UA_COMMENT
CHARS_ALPHA_NUM + " .,;-_?@", // SAFE_CHARS_UA_COMMENT
CHARS_ALPHA_NUM + ".-_", // SAFE_CHARS_FILENAME
};
std::string SanitizeString(const std::string& str, int rule)

View File

@ -26,7 +26,8 @@
enum SafeChars
{
SAFE_CHARS_DEFAULT, //!< The full set of allowed chars
SAFE_CHARS_UA_COMMENT //!< BIP-0014 subset
SAFE_CHARS_UA_COMMENT, //!< BIP-0014 subset
SAFE_CHARS_FILENAME, //!< Chars allowed in filenames
};
/**

View File

@ -3324,7 +3324,7 @@ bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& sta
return state.Invalid(false, REJECT_INVALID, "time-too-old", strprintf("block's timestamp is too early %d %d", block.GetBlockTime(), pindexPrev->GetMedianTimePast()));
// Check timestamp
if (block.GetBlockTime() > nAdjustedTime + 2 * 60 * 60)
if (block.GetBlockTime() > nAdjustedTime + MAX_FUTURE_BLOCK_TIME)
return state.Invalid(false, REJECT_INVALID, "time-too-new", strprintf("block timestamp too far in the future %d %d", block.GetBlockTime(), nAdjustedTime + 2 * 60 * 60));
// check for version 2, 3 and 4 upgrades

View File

@ -17,6 +17,8 @@
#include "merkleblock.h"
#include "core_io.h"
#include "rpcwallet.h"
#include <fstream>
#include <stdint.h>
@ -28,9 +30,6 @@
#include <boost/assign/list_of.hpp>
#include <boost/foreach.hpp>
void EnsureWalletIsUnlocked();
bool EnsureWalletIsAvailable(bool avoidException);
std::string static EncodeDumpTime(int64_t nTime) {
return DateTimeStrFormat("%Y-%m-%dT%H:%M:%SZ", nTime);
}
@ -76,9 +75,11 @@ std::string DecodeDumpString(const std::string &str) {
UniValue importprivkey(const JSONRPCRequest& request)
{
if (!EnsureWalletIsAvailable(request.fHelp))
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(
"importprivkey \"dashprivkey\" ( \"label\" ) ( rescan )\n"
@ -102,9 +103,9 @@ UniValue importprivkey(const JSONRPCRequest& request)
);
LOCK2(cs_main, pwalletMain->cs_wallet);
LOCK2(cs_main, pwallet->cs_wallet);
EnsureWalletIsUnlocked();
EnsureWalletIsUnlocked(pwallet);
std::string strSecret = request.params[0].get_str();
std::string strLabel = "";
@ -131,66 +132,73 @@ UniValue importprivkey(const JSONRPCRequest& request)
assert(key.VerifyPubKey(pubkey));
CKeyID vchAddress = pubkey.GetID();
{
pwalletMain->MarkDirty();
pwalletMain->SetAddressBook(vchAddress, strLabel, "receive");
pwallet->MarkDirty();
pwallet->SetAddressBook(vchAddress, strLabel, "receive");
// Don't throw error in case a key is already there
if (pwalletMain->HaveKey(vchAddress))
if (pwallet->HaveKey(vchAddress)) {
return NullUniValue;
}
pwalletMain->mapKeyMetadata[vchAddress].nCreateTime = 1;
pwallet->mapKeyMetadata[vchAddress].nCreateTime = 1;
if (!pwalletMain->AddKeyPubKey(key, pubkey))
if (!pwallet->AddKeyPubKey(key, pubkey)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Error adding key to wallet");
}
// whenever a key is imported, we need to scan the whole chain
pwalletMain->UpdateTimeFirstKey(1);
pwallet->UpdateTimeFirstKey(1);
if (fRescan) {
pwalletMain->ScanForWalletTransactions(chainActive.Genesis(), true);
pwallet->ScanForWalletTransactions(chainActive.Genesis(), true);
}
}
return NullUniValue;
}
void ImportAddress(const CBitcoinAddress& address, const std::string& strLabel);
void ImportScript(const CScript& script, const std::string& strLabel, bool isRedeemScript)
void ImportAddress(CWallet*, const CBitcoinAddress& address, const std::string& strLabel);
void ImportScript(CWallet * const pwallet, const CScript& script, const std::string& strLabel, bool isRedeemScript)
{
if (!isRedeemScript && ::IsMine(*pwalletMain, script) == ISMINE_SPENDABLE)
if (!isRedeemScript && ::IsMine(*pwallet, script) == ISMINE_SPENDABLE) {
throw JSONRPCError(RPC_WALLET_ERROR, "The wallet already contains the private key for this address or script");
}
pwalletMain->MarkDirty();
pwallet->MarkDirty();
if (!pwalletMain->HaveWatchOnly(script) && !pwalletMain->AddWatchOnly(script, 0 /* nCreateTime */))
if (!pwallet->HaveWatchOnly(script) && !pwallet->AddWatchOnly(script, 0 /* nCreateTime */)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet");
}
if (isRedeemScript) {
if (!pwalletMain->HaveCScript(script) && !pwalletMain->AddCScript(script))
if (!pwallet->HaveCScript(script) && !pwallet->AddCScript(script)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Error adding p2sh redeemScript to wallet");
ImportAddress(CBitcoinAddress(CScriptID(script)), strLabel);
}
ImportAddress(pwallet, CBitcoinAddress(CScriptID(script)), strLabel);
} else {
CTxDestination destination;
if (ExtractDestination(script, destination)) {
pwalletMain->SetAddressBook(destination, strLabel, "receive");
pwallet->SetAddressBook(destination, strLabel, "receive");
}
}
}
void ImportAddress(const CBitcoinAddress& address, const std::string& strLabel)
void ImportAddress(CWallet * const pwallet, const CBitcoinAddress& address, const std::string& strLabel)
{
CScript script = GetScriptForDestination(address.Get());
ImportScript(script, strLabel, false);
ImportScript(pwallet, script, strLabel, false);
// add to address book or update label
if (address.IsValid())
pwalletMain->SetAddressBook(address.Get(), strLabel, "receive");
pwallet->SetAddressBook(address.Get(), strLabel, "receive");
}
UniValue importaddress(const JSONRPCRequest& request)
{
if (!EnsureWalletIsAvailable(request.fHelp))
CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
}
if (request.fHelp || request.params.size() < 1 || request.params.size() > 4)
throw std::runtime_error(
"importaddress \"address\" ( \"label\" rescan p2sh )\n"
@ -231,24 +239,24 @@ UniValue importaddress(const JSONRPCRequest& request)
if (request.params.size() > 3)
fP2SH = request.params[3].get_bool();
LOCK2(cs_main, pwalletMain->cs_wallet);
LOCK2(cs_main, pwallet->cs_wallet);
CBitcoinAddress address(request.params[0].get_str());
if (address.IsValid()) {
if (fP2SH)
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Cannot use the p2sh flag with an address - use a script instead");
ImportAddress(address, strLabel);
ImportAddress(pwallet, address, strLabel);
} else if (IsHex(request.params[0].get_str())) {
std::vector<unsigned char> data(ParseHex(request.params[0].get_str()));
ImportScript(CScript(data.begin(), data.end()), strLabel, fP2SH);
ImportScript(pwallet, CScript(data.begin(), data.end()), strLabel, fP2SH);
} else {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Dash address or script");
}
if (fRescan)
{
pwalletMain->ScanForWalletTransactions(chainActive.Genesis(), true);
pwalletMain->ReacceptWalletTransactions();
pwallet->ScanForWalletTransactions(chainActive.Genesis(), true);
pwallet->ReacceptWalletTransactions();
}
return NullUniValue;
@ -256,8 +264,10 @@ UniValue importaddress(const JSONRPCRequest& request)
UniValue importprunedfunds(const JSONRPCRequest& request)
{
if (!EnsureWalletIsAvailable(request.fHelp))
CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
}
if (request.fHelp || request.params.size() != 2)
throw std::runtime_error(
@ -272,7 +282,7 @@ UniValue importprunedfunds(const JSONRPCRequest& request)
if (!DecodeHexTx(tx, request.params[0].get_str()))
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
uint256 hashTx = tx.GetHash();
CWalletTx wtx(pwalletMain, MakeTransactionRef(std::move(tx)));
CWalletTx wtx(pwallet, MakeTransactionRef(std::move(tx)));
CDataStream ssMB(ParseHexV(request.params[1], "proof"), SER_NETWORK, PROTOCOL_VERSION);
CMerkleBlock merkleBlock;
@ -303,10 +313,10 @@ UniValue importprunedfunds(const JSONRPCRequest& request)
wtx.nIndex = txnIndex;
wtx.hashBlock = merkleBlock.header.GetHash();
LOCK2(cs_main, pwalletMain->cs_wallet);
LOCK2(cs_main, pwallet->cs_wallet);
if (pwalletMain->IsMine(wtx)) {
pwalletMain->AddToWallet(wtx, false);
if (pwallet->IsMine(wtx)) {
pwallet->AddToWallet(wtx, false);
return NullUniValue;
}
@ -315,8 +325,10 @@ UniValue importprunedfunds(const JSONRPCRequest& request)
UniValue removeprunedfunds(const JSONRPCRequest& request)
{
if (!EnsureWalletIsAvailable(request.fHelp))
CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
}
if (request.fHelp || request.params.size() != 1)
throw std::runtime_error(
@ -330,7 +342,7 @@ UniValue removeprunedfunds(const JSONRPCRequest& request)
+ HelpExampleRpc("removprunedfunds", "\"a8d0c0184dde994a09ec054286f1ce581bebf46446a512166eae7628734ea0a5\"")
);
LOCK2(cs_main, pwalletMain->cs_wallet);
LOCK2(cs_main, pwallet->cs_wallet);
uint256 hash;
hash.SetHex(request.params[0].get_str());
@ -338,7 +350,7 @@ UniValue removeprunedfunds(const JSONRPCRequest& request)
vHash.push_back(hash);
std::vector<uint256> vHashOut;
if(pwalletMain->ZapSelectTx(vHash, vHashOut) != DB_LOAD_OK) {
if (pwallet->ZapSelectTx(vHash, vHashOut) != DB_LOAD_OK) {
throw JSONRPCError(RPC_INTERNAL_ERROR, "Could not properly delete the transaction.");
}
@ -351,8 +363,10 @@ UniValue removeprunedfunds(const JSONRPCRequest& request)
UniValue importpubkey(const JSONRPCRequest& request)
{
if (!EnsureWalletIsAvailable(request.fHelp))
CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
}
if (request.fHelp || request.params.size() < 1 || request.params.size() > 4)
throw std::runtime_error(
@ -392,15 +406,15 @@ UniValue importpubkey(const JSONRPCRequest& request)
if (!pubKey.IsFullyValid())
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Pubkey is not a valid public key");
LOCK2(cs_main, pwalletMain->cs_wallet);
LOCK2(cs_main, pwallet->cs_wallet);
ImportAddress(CBitcoinAddress(pubKey.GetID()), strLabel);
ImportScript(GetScriptForRawPubKey(pubKey), strLabel, false);
ImportAddress(pwallet, CBitcoinAddress(pubKey.GetID()), strLabel);
ImportScript(pwallet, GetScriptForRawPubKey(pubKey), strLabel, false);
if (fRescan)
{
pwalletMain->ScanForWalletTransactions(chainActive.Genesis(), true);
pwalletMain->ReacceptWalletTransactions();
pwallet->ScanForWalletTransactions(chainActive.Genesis(), true);
pwallet->ReacceptWalletTransactions();
}
return NullUniValue;
@ -409,9 +423,11 @@ UniValue importpubkey(const JSONRPCRequest& request)
UniValue importwallet(const JSONRPCRequest& request)
{
if (!EnsureWalletIsAvailable(request.fHelp))
CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
}
if (request.fHelp || request.params.size() != 1)
throw std::runtime_error(
"importwallet \"filename\"\n"
@ -430,9 +446,9 @@ UniValue importwallet(const JSONRPCRequest& request)
if (fPruneMode)
throw JSONRPCError(RPC_WALLET_ERROR, "Importing wallets is disabled in pruned mode");
LOCK2(cs_main, pwalletMain->cs_wallet);
LOCK2(cs_main, pwallet->cs_wallet);
EnsureWalletIsUnlocked();
EnsureWalletIsUnlocked(pwallet);
std::ifstream file;
file.open(request.params[0].get_str().c_str(), std::ios::in | std::ios::ate);
@ -446,9 +462,9 @@ UniValue importwallet(const JSONRPCRequest& request)
int64_t nFilesize = std::max((int64_t)1, (int64_t)file.tellg());
file.seekg(0, file.beg);
pwalletMain->ShowProgress(_("Importing..."), 0); // show progress dialog in GUI
pwallet->ShowProgress(_("Importing..."), 0); // show progress dialog in GUI
while (file.good()) {
pwalletMain->ShowProgress("", std::max(1, std::min(99, (int)(((double)file.tellg() / (double)nFilesize) * 100))));
pwallet->ShowProgress("", std::max(1, std::min(99, (int)(((double)file.tellg() / (double)nFilesize) * 100))));
std::string line;
std::getline(file, line);
if (line.empty() || line[0] == '#')
@ -465,7 +481,7 @@ UniValue importwallet(const JSONRPCRequest& request)
CPubKey pubkey = key.GetPubKey();
assert(key.VerifyPubKey(pubkey));
CKeyID keyid = pubkey.GetID();
if (pwalletMain->HaveKey(keyid)) {
if (pwallet->HaveKey(keyid)) {
LogPrintf("Skipping import of %s (key already present)\n", CBitcoinAddress(keyid).ToString());
continue;
}
@ -485,25 +501,24 @@ UniValue importwallet(const JSONRPCRequest& request)
}
}
LogPrintf("Importing %s...\n", CBitcoinAddress(keyid).ToString());
if (!pwalletMain->AddKeyPubKey(key, pubkey)) {
if (!pwallet->AddKeyPubKey(key, pubkey)) {
fGood = false;
continue;
}
pwalletMain->mapKeyMetadata[keyid].nCreateTime = nTime;
pwallet->mapKeyMetadata[keyid].nCreateTime = nTime;
if (fLabel)
pwalletMain->SetAddressBook(keyid, strLabel, "receive");
pwallet->SetAddressBook(keyid, strLabel, "receive");
nTimeBegin = std::min(nTimeBegin, nTime);
}
file.close();
pwalletMain->ShowProgress("", 100); // hide progress dialog in GUI
pwallet->ShowProgress("", 100); // hide progress dialog in GUI
pwalletMain->UpdateTimeFirstKey(nTimeBegin);
CBlockIndex *pindex = chainActive.FindEarliestAtLeast(nTimeBegin - 7200);
pwallet->UpdateTimeFirstKey(nTimeBegin);
CBlockIndex* pindex = chainActive.FindEarliestAtLeast(nTimeBegin - TIMESTAMP_WINDOW);
LogPrintf("Rescanning last %i blocks\n", pindex ? chainActive.Height() - pindex->nHeight + 1 : 0);
pwalletMain->ScanForWalletTransactions(pindex);
pwalletMain->MarkDirty();
pwallet->ScanForWalletTransactions(pindex);
pwallet->MarkDirty();
if (!fGood)
throw JSONRPCError(RPC_WALLET_ERROR, "Error adding some keys to wallet");
@ -513,7 +528,8 @@ UniValue importwallet(const JSONRPCRequest& request)
UniValue importelectrumwallet(const JSONRPCRequest& request)
{
if (!EnsureWalletIsAvailable(request.fHelp))
CWallet* const pwallet = GetWalletForJSONRPCRequest(request);
if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
return NullUniValue;
if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
@ -535,9 +551,9 @@ UniValue importelectrumwallet(const JSONRPCRequest& request)
if (fPruneMode)
throw JSONRPCError(RPC_WALLET_ERROR, "Importing wallets is disabled in pruned mode");
LOCK2(cs_main, pwalletMain->cs_wallet);
LOCK2(cs_main, pwallet->cs_wallet);
EnsureWalletIsUnlocked();
EnsureWalletIsUnlocked(pwallet);
std::ifstream file;
std::string strFileName = request.params[0].get_str();
@ -558,11 +574,11 @@ UniValue importelectrumwallet(const JSONRPCRequest& request)
int64_t nFilesize = std::max((int64_t)1, (int64_t)file.tellg());
file.seekg(0, file.beg);
pwalletMain->ShowProgress(_("Importing..."), 0); // show progress dialog in GUI
pwallet->ShowProgress(_("Importing..."), 0); // show progress dialog in GUI
if(strFileExt == "csv") {
while (file.good()) {
pwalletMain->ShowProgress("", std::max(1, std::min(99, (int)(((double)file.tellg() / (double)nFilesize) * 100))));
pwallet->ShowProgress("", std::max(1, std::min(99, (int)(((double)file.tellg() / (double)nFilesize) * 100))));
std::string line;
std::getline(file, line);
if (line.empty() || line == "address,private_key")
@ -578,12 +594,12 @@ UniValue importelectrumwallet(const JSONRPCRequest& request)
CPubKey pubkey = key.GetPubKey();
assert(key.VerifyPubKey(pubkey));
CKeyID keyid = pubkey.GetID();
if (pwalletMain->HaveKey(keyid)) {
if (pwallet->HaveKey(keyid)) {
LogPrintf("Skipping import of %s (key already present)\n", CBitcoinAddress(keyid).ToString());
continue;
}
LogPrintf("Importing %s...\n", CBitcoinAddress(keyid).ToString());
if (!pwalletMain->AddKeyPubKey(key, pubkey)) {
if (!pwallet->AddKeyPubKey(key, pubkey)) {
fGood = false;
continue;
}
@ -600,7 +616,7 @@ UniValue importelectrumwallet(const JSONRPCRequest& request)
std::vector<std::string> vKeys = data.getKeys();
for (size_t i = 0; i < data.size(); i++) {
pwalletMain->ShowProgress("", std::max(1, std::min(99, int(i*100/data.size()))));
pwallet->ShowProgress("", std::max(1, std::min(99, int(i*100/data.size()))));
if(!data[vKeys[i]].isStr())
continue;
CBitcoinSecret vchSecret;
@ -610,19 +626,19 @@ UniValue importelectrumwallet(const JSONRPCRequest& request)
CPubKey pubkey = key.GetPubKey();
assert(key.VerifyPubKey(pubkey));
CKeyID keyid = pubkey.GetID();
if (pwalletMain->HaveKey(keyid)) {
if (pwallet->HaveKey(keyid)) {
LogPrintf("Skipping import of %s (key already present)\n", CBitcoinAddress(keyid).ToString());
continue;
}
LogPrintf("Importing %s...\n", CBitcoinAddress(keyid).ToString());
if (!pwalletMain->AddKeyPubKey(key, pubkey)) {
if (!pwallet->AddKeyPubKey(key, pubkey)) {
fGood = false;
continue;
}
}
}
file.close();
pwalletMain->ShowProgress("", 100); // hide progress dialog in GUI
pwallet->ShowProgress("", 100); // hide progress dialog in GUI
// Whether to perform rescan after import
int nStartHeight = 0;
@ -633,10 +649,10 @@ UniValue importelectrumwallet(const JSONRPCRequest& request)
// Assume that electrum wallet was created at that block
int nTimeBegin = chainActive[nStartHeight]->GetBlockTime();
pwalletMain->UpdateTimeFirstKey(nTimeBegin);
pwallet->UpdateTimeFirstKey(nTimeBegin);
LogPrintf("Rescanning %i blocks\n", chainActive.Height() - nStartHeight + 1);
pwalletMain->ScanForWalletTransactions(chainActive[nStartHeight], true);
pwallet->ScanForWalletTransactions(chainActive[nStartHeight], true);
if (!fGood)
throw JSONRPCError(RPC_WALLET_ERROR, "Error adding some keys to wallet");
@ -646,9 +662,11 @@ UniValue importelectrumwallet(const JSONRPCRequest& request)
UniValue dumpprivkey(const JSONRPCRequest& request)
{
if (!EnsureWalletIsAvailable(request.fHelp))
CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
}
if (request.fHelp || request.params.size() != 1)
throw std::runtime_error(
"dumpprivkey \"address\"\n"
@ -664,9 +682,9 @@ UniValue dumpprivkey(const JSONRPCRequest& request)
+ HelpExampleRpc("dumpprivkey", "\"myaddress\"")
);
LOCK2(cs_main, pwalletMain->cs_wallet);
LOCK2(cs_main, pwallet->cs_wallet);
EnsureWalletIsUnlocked();
EnsureWalletIsUnlocked(pwallet);
std::string strAddress = request.params[0].get_str();
CBitcoinAddress address;
@ -676,14 +694,16 @@ UniValue dumpprivkey(const JSONRPCRequest& request)
if (!address.GetKeyID(keyID))
throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to a key");
CKey vchSecret;
if (!pwalletMain->GetKey(keyID, vchSecret))
if (!pwallet->GetKey(keyID, vchSecret)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Private key for address " + strAddress + " is not known");
}
return CBitcoinSecret(vchSecret).ToString();
}
UniValue dumphdinfo(const JSONRPCRequest& request)
{
if (!EnsureWalletIsAvailable(request.fHelp))
CWallet* const pwallet = GetWalletForJSONRPCRequest(request);
if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
return NullUniValue;
if (request.fHelp || request.params.size() != 0)
@ -701,15 +721,15 @@ UniValue dumphdinfo(const JSONRPCRequest& request)
+ HelpExampleRpc("dumphdinfo", "")
);
LOCK(pwalletMain->cs_wallet);
LOCK(pwallet->cs_wallet);
EnsureWalletIsUnlocked();
EnsureWalletIsUnlocked(pwallet);
CHDChain hdChainCurrent;
if (!pwalletMain->GetHDChain(hdChainCurrent))
if (!pwallet->GetHDChain(hdChainCurrent))
throw JSONRPCError(RPC_WALLET_ERROR, "This wallet is not a HD wallet.");
if (!pwalletMain->GetDecryptedHDChain(hdChainCurrent))
if (!pwallet->GetDecryptedHDChain(hdChainCurrent))
throw JSONRPCError(RPC_INTERNAL_ERROR, "Cannot decrypt HD seed");
SecureString ssMnemonic;
@ -726,9 +746,11 @@ UniValue dumphdinfo(const JSONRPCRequest& request)
UniValue dumpwallet(const JSONRPCRequest& request)
{
if (!EnsureWalletIsAvailable(request.fHelp))
CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
}
if (request.fHelp || request.params.size() != 1)
throw std::runtime_error(
"dumpwallet \"filename\"\n"
@ -740,9 +762,9 @@ UniValue dumpwallet(const JSONRPCRequest& request)
+ HelpExampleRpc("dumpwallet", "\"test\"")
);
LOCK2(cs_main, pwalletMain->cs_wallet);
LOCK2(cs_main, pwallet->cs_wallet);
EnsureWalletIsUnlocked();
EnsureWalletIsUnlocked(pwallet);
std::ofstream file;
file.open(request.params[0].get_str().c_str());
@ -751,8 +773,8 @@ UniValue dumpwallet(const JSONRPCRequest& request)
std::map<CTxDestination, int64_t> mapKeyBirth;
std::set<CKeyID> setKeyPool;
pwalletMain->GetKeyBirthTimes(mapKeyBirth);
pwalletMain->GetAllReserveKeys(setKeyPool);
pwallet->GetKeyBirthTimes(mapKeyBirth);
pwallet->GetAllReserveKeys(setKeyPool);
// sort time/key pairs
std::vector<std::pair<int64_t, CKeyID> > vKeyBirth;
@ -779,10 +801,10 @@ UniValue dumpwallet(const JSONRPCRequest& request)
// add the base58check encoded extended master if the wallet uses HD
CHDChain hdChainCurrent;
if (pwalletMain->GetHDChain(hdChainCurrent))
if (pwallet->GetHDChain(hdChainCurrent))
{
if (!pwalletMain->GetDecryptedHDChain(hdChainCurrent))
if (!pwallet->GetDecryptedHDChain(hdChainCurrent))
throw JSONRPCError(RPC_INTERNAL_ERROR, "Cannot decrypt HD chain");
SecureString ssMnemonic;
@ -827,16 +849,16 @@ UniValue dumpwallet(const JSONRPCRequest& request)
std::string strTime = EncodeDumpTime(it->first);
std::string strAddr = CBitcoinAddress(keyid).ToString();
CKey key;
if (pwalletMain->GetKey(keyid, key)) {
if (pwallet->GetKey(keyid, key)) {
file << strprintf("%s %s ", CBitcoinSecret(key).ToString(), strTime);
if (pwalletMain->mapAddressBook.count(keyid)) {
file << strprintf("label=%s", EncodeDumpString(pwalletMain->mapAddressBook[keyid].name));
if (pwallet->mapAddressBook.count(keyid)) {
file << strprintf("label=%s", EncodeDumpString(pwallet->mapAddressBook[keyid].name));
} else if (setKeyPool.count(keyid)) {
file << "reserve=1";
} else {
file << "change=1";
}
file << strprintf(" # addr=%s%s\n", strAddr, (pwalletMain->mapHdPubKeys.count(keyid) ? " hdkeypath="+pwalletMain->mapHdPubKeys[keyid].GetKeyPath() : ""));
file << strprintf(" # addr=%s%s\n", strAddr, (pwallet->mapHdPubKeys.count(keyid) ? " hdkeypath="+pwallet->mapHdPubKeys[keyid].GetKeyPath() : ""));
}
}
file << "\n";
@ -852,7 +874,7 @@ UniValue dumpwallet(const JSONRPCRequest& request)
}
UniValue ProcessImport(const UniValue& data, const int64_t timestamp)
UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, const int64_t timestamp)
{
try {
bool success = false;
@ -934,32 +956,32 @@ UniValue ProcessImport(const UniValue& data, const int64_t timestamp)
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid P2SH address / script");
}
pwalletMain->MarkDirty();
pwallet->MarkDirty();
if (!pwalletMain->HaveWatchOnly(redeemScript) && !pwalletMain->AddWatchOnly(redeemScript, timestamp)) {
if (!pwallet->HaveWatchOnly(redeemScript) && !pwallet->AddWatchOnly(redeemScript, timestamp)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet");
}
if (!pwalletMain->HaveCScript(redeemScript) && !pwalletMain->AddCScript(redeemScript)) {
if (!pwallet->HaveCScript(redeemScript) && !pwallet->AddCScript(redeemScript)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Error adding p2sh redeemScript to wallet");
}
CBitcoinAddress redeemAddress = CBitcoinAddress(CScriptID(redeemScript));
CScript redeemDestination = GetScriptForDestination(redeemAddress.Get());
if (::IsMine(*pwalletMain, redeemDestination) == ISMINE_SPENDABLE) {
if (::IsMine(*pwallet, redeemDestination) == ISMINE_SPENDABLE) {
throw JSONRPCError(RPC_WALLET_ERROR, "The wallet already contains the private key for this address or script");
}
pwalletMain->MarkDirty();
pwallet->MarkDirty();
if (!pwalletMain->HaveWatchOnly(redeemDestination) && !pwalletMain->AddWatchOnly(redeemDestination, timestamp)) {
if (!pwallet->HaveWatchOnly(redeemDestination) && !pwallet->AddWatchOnly(redeemDestination, timestamp)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet");
}
// add to address book or update label
if (address.IsValid()) {
pwalletMain->SetAddressBook(address.Get(), label, "receive");
pwallet->SetAddressBook(address.Get(), label, "receive");
}
// Import private keys.
@ -984,20 +1006,20 @@ UniValue ProcessImport(const UniValue& data, const int64_t timestamp)
assert(key.VerifyPubKey(pubkey));
CKeyID vchAddress = pubkey.GetID();
pwalletMain->MarkDirty();
pwalletMain->SetAddressBook(vchAddress, label, "receive");
pwallet->MarkDirty();
pwallet->SetAddressBook(vchAddress, label, "receive");
if (pwalletMain->HaveKey(vchAddress)) {
if (pwallet->HaveKey(vchAddress)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Already have this key");
}
pwalletMain->mapKeyMetadata[vchAddress].nCreateTime = timestamp;
pwallet->mapKeyMetadata[vchAddress].nCreateTime = timestamp;
if (!pwalletMain->AddKeyPubKey(key, pubkey)) {
if (!pwallet->AddKeyPubKey(key, pubkey)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Error adding key to wallet");
}
pwalletMain->UpdateTimeFirstKey(timestamp);
pwallet->UpdateTimeFirstKey(timestamp);
}
}
@ -1040,31 +1062,31 @@ UniValue ProcessImport(const UniValue& data, const int64_t timestamp)
CScript pubKeyScript = GetScriptForDestination(pubKeyAddress.Get());
if (::IsMine(*pwalletMain, pubKeyScript) == ISMINE_SPENDABLE) {
if (::IsMine(*pwallet, pubKeyScript) == ISMINE_SPENDABLE) {
throw JSONRPCError(RPC_WALLET_ERROR, "The wallet already contains the private key for this address or script");
}
pwalletMain->MarkDirty();
pwallet->MarkDirty();
if (!pwalletMain->HaveWatchOnly(pubKeyScript) && !pwalletMain->AddWatchOnly(pubKeyScript, timestamp)) {
if (!pwallet->HaveWatchOnly(pubKeyScript) && !pwallet->AddWatchOnly(pubKeyScript, timestamp)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet");
}
// add to address book or update label
if (pubKeyAddress.IsValid()) {
pwalletMain->SetAddressBook(pubKeyAddress.Get(), label, "receive");
pwallet->SetAddressBook(pubKeyAddress.Get(), label, "receive");
}
// TODO Is this necessary?
CScript scriptRawPubKey = GetScriptForRawPubKey(pubKey);
if (::IsMine(*pwalletMain, scriptRawPubKey) == ISMINE_SPENDABLE) {
if (::IsMine(*pwallet, scriptRawPubKey) == ISMINE_SPENDABLE) {
throw JSONRPCError(RPC_WALLET_ERROR, "The wallet already contains the private key for this address or script");
}
pwalletMain->MarkDirty();
pwallet->MarkDirty();
if (!pwalletMain->HaveWatchOnly(scriptRawPubKey) && !pwalletMain->AddWatchOnly(scriptRawPubKey, timestamp)) {
if (!pwallet->HaveWatchOnly(scriptRawPubKey) && !pwallet->AddWatchOnly(scriptRawPubKey, timestamp)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet");
}
@ -1112,40 +1134,40 @@ UniValue ProcessImport(const UniValue& data, const int64_t timestamp)
}
CKeyID vchAddress = pubKey.GetID();
pwalletMain->MarkDirty();
pwalletMain->SetAddressBook(vchAddress, label, "receive");
pwallet->MarkDirty();
pwallet->SetAddressBook(vchAddress, label, "receive");
if (pwalletMain->HaveKey(vchAddress)) {
if (pwallet->HaveKey(vchAddress)) {
return false;
}
pwalletMain->mapKeyMetadata[vchAddress].nCreateTime = timestamp;
pwallet->mapKeyMetadata[vchAddress].nCreateTime = timestamp;
if (!pwalletMain->AddKeyPubKey(key, pubKey)) {
if (!pwallet->AddKeyPubKey(key, pubKey)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Error adding key to wallet");
}
pwalletMain->UpdateTimeFirstKey(timestamp);
pwallet->UpdateTimeFirstKey(timestamp);
success = true;
}
// Import scriptPubKey only.
if (pubKeys.size() == 0 && keys.size() == 0) {
if (::IsMine(*pwalletMain, script) == ISMINE_SPENDABLE) {
if (::IsMine(*pwallet, script) == ISMINE_SPENDABLE) {
throw JSONRPCError(RPC_WALLET_ERROR, "The wallet already contains the private key for this address or script");
}
pwalletMain->MarkDirty();
pwallet->MarkDirty();
if (!pwalletMain->HaveWatchOnly(script) && !pwalletMain->AddWatchOnly(script, timestamp)) {
if (!pwallet->HaveWatchOnly(script) && !pwallet->AddWatchOnly(script, timestamp)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet");
}
if (scriptPubKey.getType() == UniValue::VOBJ) {
// add to address book or update label
if (address.IsValid()) {
pwalletMain->SetAddressBook(address.Get(), label, "receive");
pwallet->SetAddressBook(address.Get(), label, "receive");
}
}
@ -1185,6 +1207,11 @@ int64_t GetImportTimestamp(const UniValue& data, int64_t now)
UniValue importmulti(const JSONRPCRequest& mainRequest)
{
CWallet * const pwallet = GetWalletForJSONRPCRequest(mainRequest);
if (!EnsureWalletIsAvailable(pwallet, mainRequest.fHelp)) {
return NullUniValue;
}
// clang-format off
if (mainRequest.fHelp || mainRequest.params.size() < 1 || mainRequest.params.size() > 2)
throw std::runtime_error(
@ -1223,9 +1250,6 @@ UniValue importmulti(const JSONRPCRequest& mainRequest)
" [{ \"success\": true } , { \"success\": false, \"error\": { \"code\": -1, \"message\": \"Internal Server Error\"} }, ... ]\n");
// clang-format on
if (!EnsureWalletIsAvailable(mainRequest.fHelp)) {
return NullUniValue;
}
RPCTypeCheck(mainRequest.params, boost::assign::list_of(UniValue::VARR)(UniValue::VOBJ));
@ -1242,8 +1266,8 @@ UniValue importmulti(const JSONRPCRequest& mainRequest)
}
}
LOCK2(cs_main, pwalletMain->cs_wallet);
EnsureWalletIsUnlocked();
LOCK2(cs_main, pwallet->cs_wallet);
EnsureWalletIsUnlocked(pwallet);
// Verify all timestamps are present before importing any keys.
const int64_t now = chainActive.Tip() ? chainActive.Tip()->GetMedianTimePast() : 0;
@ -1265,7 +1289,7 @@ UniValue importmulti(const JSONRPCRequest& mainRequest)
BOOST_FOREACH (const UniValue& data, requests.getValues()) {
const int64_t timestamp = std::max(GetImportTimestamp(data, now), minimumTimestamp);
const UniValue result = ProcessImport(data, timestamp);
const UniValue result = ProcessImport(pwallet, data, timestamp);
response.push_back(result);
if (!fRescan) {
@ -1284,11 +1308,11 @@ UniValue importmulti(const JSONRPCRequest& mainRequest)
}
if (fRescan && fRunScan && requests.size()) {
CBlockIndex* pindex = nLowestTimestamp > minimumTimestamp ? chainActive.FindEarliestAtLeast(std::max<int64_t>(nLowestTimestamp - 7200, 0)) : chainActive.Genesis();
CBlockIndex* pindex = nLowestTimestamp > minimumTimestamp ? chainActive.FindEarliestAtLeast(std::max<int64_t>(nLowestTimestamp - TIMESTAMP_WINDOW, 0)) : chainActive.Genesis();
CBlockIndex* scannedRange = nullptr;
if (pindex) {
scannedRange = pwalletMain->ScanForWalletTransactions(pindex, true);
pwalletMain->ReacceptWalletTransactions();
scannedRange = pwallet->ScanForWalletTransactions(pindex, true);
pwallet->ReacceptWalletTransactions();
}
if (!scannedRange || scannedRange->nHeight > pindex->nHeight) {
@ -1301,7 +1325,7 @@ UniValue importmulti(const JSONRPCRequest& mainRequest)
// range, or if the import result already has an error set, let
// the result stand unmodified. Otherwise replace the result
// with an error message.
if (GetImportTimestamp(request, now) - 7200 >= scannedRange->GetBlockTimeMax() || results.at(i).exists("error")) {
if (GetImportTimestamp(request, now) - TIMESTAMP_WINDOW >= scannedRange->GetBlockTimeMax() || results.at(i).exists("error")) {
response.push_back(results.at(i));
} else {
UniValue result = UniValue(UniValue::VOBJ);

File diff suppressed because it is too large Load Diff

View File

@ -6,7 +6,20 @@
#define BITCOIN_WALLET_RPCWALLET_H
class CRPCTable;
class JSONRPCRequest;
void RegisterWalletRPCCommands(CRPCTable &t);
/**
* Figures out what wallet, if any, to use for a JSONRPCRequest.
*
* @param[in] request JSONRPCRequest that wishes to access a wallet
* @return NULL if no wallet should be used, or a pointer to the CWallet
*/
CWallet *GetWalletForJSONRPCRequest(const JSONRPCRequest&);
std::string HelpRequiringPassphrase(CWallet *);
void EnsureWalletIsUnlocked(CWallet *);
bool EnsureWalletIsAvailable(CWallet *, bool avoidException);
#endif //BITCOIN_WALLET_RPCWALLET_H

View File

@ -415,7 +415,7 @@ BOOST_FIXTURE_TEST_CASE(rescan, TestChain100Setup)
CKey futureKey;
futureKey.MakeNewKey(true);
key.pushKV("scriptPubKey", HexStr(GetScriptForRawPubKey(futureKey.GetPubKey())));
key.pushKV("timestamp", newTip->GetBlockTimeMax() + 7200);
key.pushKV("timestamp", newTip->GetBlockTimeMax() + TIMESTAMP_WINDOW);
key.pushKV("internal", UniValue(true));
keys.push_back(key);
JSONRPCRequest request;

View File

@ -1904,7 +1904,7 @@ CBlockIndex* CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool f
// no need to read and scan block, if block was created before
// our wallet birthday (as adjusted for block time variability)
while (pindex && nTimeFirstKey && (pindex->GetBlockTime() < (nTimeFirstKey - 7200)))
while (pindex && nTimeFirstKey && (pindex->GetBlockTime() < (nTimeFirstKey - TIMESTAMP_WINDOW)))
pindex = chainActive.Next(pindex);
ShowProgress(_("Rescanning..."), 0); // show rescan progress in GUI as dialog or on splashscreen, if -rescan on startup
@ -4749,7 +4749,7 @@ void CWallet::GetKeyBirthTimes(std::map<CTxDestination, int64_t> &mapKeyBirth) c
// Extract block timestamps for those keys
for (std::map<CKeyID, CBlockIndex*>::const_iterator it = mapKeyFirstBlock.begin(); it != mapKeyFirstBlock.end(); it++)
mapKeyBirth[it->first] = it->second->GetBlockTime() - 7200; // block times can be 2h off
mapKeyBirth[it->first] = it->second->GetBlockTime() - TIMESTAMP_WINDOW; // block times can be 2h off
}
bool CWallet::AddDestData(const CTxDestination &dest, const std::string &key, const std::string &value)
@ -5061,6 +5061,12 @@ bool CWallet::InitLoadWallet()
std::string walletFile = GetArg("-wallet", DEFAULT_WALLET_DAT);
if (walletFile.find_first_of("/\\") != std::string::npos) {
return InitError(_("-wallet parameter must only specify a filename (not a path)"));
} else if (SanitizeString(walletFile, SAFE_CHARS_FILENAME) != walletFile) {
return InitError(_("Invalid characters in -wallet filename"));
}
CWallet * const pwallet = CreateWalletFromFile(walletFile);
if (!pwallet) {
return false;

View File

@ -884,6 +884,9 @@ public:
//! Adds a watch-only address to the store, without saving it to disk (used by LoadWallet)
bool LoadWatchOnly(const CScript &dest);
//! Holds a timestamp at which point the wallet is scheduled (externally) to be relocked. Caller must arrange for actual relocking to occur via Lock().
int64_t nRelockTime;
bool Unlock(const SecureString& strWalletPassphrase, bool fForMixingOnly = false);
bool ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, const SecureString& strNewWalletPassphrase);
bool EncryptWallet(const SecureString& strWalletPassphrase);