mirror of
https://github.com/dashpay/dash.git
synced 2024-12-24 19:42:46 +01:00
Merge pull request #2646 from PastaPastaPasta/backports-0.15-pr4
Backports 0.15 pr4
This commit is contained in:
commit
15e1c3b080
@ -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)
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
14
src/chain.h
14
src/chain.h
@ -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:
|
||||
|
@ -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.");
|
||||
}
|
||||
|
@ -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");
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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));
|
||||
}
|
||||
};
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -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
|
||||
|
@ -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
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user