Page MenuHomePhabricator

D7119.diff
No OneTemporary

D7119.diff

diff --git a/src/interfaces/wallet.cpp b/src/interfaces/wallet.cpp
--- a/src/interfaces/wallet.cpp
+++ b/src/interfaces/wallet.cpp
@@ -44,7 +44,7 @@
result.txout_address_is_mine.emplace_back(
ExtractDestination(txout.scriptPubKey,
result.txout_address.back())
- ? IsMine(wallet, result.txout_address.back())
+ ? wallet.IsMine(result.txout_address.back())
: ISMINE_NO);
}
result.credit = wtx.GetCredit(locked_chain, ISMINE_ALL);
@@ -132,15 +132,22 @@
return m_wallet->chainParams;
}
bool getPubKey(const CKeyID &address, CPubKey &pub_key) override {
- return m_wallet->GetPubKey(address, pub_key);
+ return m_wallet->GetLegacyScriptPubKeyMan()->GetPubKey(address,
+ pub_key);
}
bool getPrivKey(const CKeyID &address, CKey &key) override {
- return m_wallet->GetKey(address, key);
+ return m_wallet->GetLegacyScriptPubKeyMan()->GetKey(address, key);
}
bool isSpendable(const CTxDestination &dest) override {
- return IsMine(*m_wallet, dest) & ISMINE_SPENDABLE;
+ return m_wallet->IsMine(dest) & ISMINE_SPENDABLE;
}
- bool haveWatchOnly() override { return m_wallet->HaveWatchOnly(); };
+ bool haveWatchOnly() override {
+ auto spk_man = m_wallet->GetLegacyScriptPubKeyMan();
+ if (spk_man) {
+ return spk_man->HaveWatchOnly();
+ }
+ return false;
+ };
bool setAddressBook(const CTxDestination &dest, const std::string &name,
const std::string &purpose) override {
return m_wallet->SetAddressBook(dest, name, purpose);
@@ -159,7 +166,7 @@
*name = it->second.name;
}
if (is_mine) {
- *is_mine = IsMine(*m_wallet, dest);
+ *is_mine = m_wallet->IsMine(dest);
}
if (purpose) {
*purpose = it->second.purpose;
@@ -170,13 +177,14 @@
LOCK(m_wallet->cs_wallet);
std::vector<WalletAddress> result;
for (const auto &item : m_wallet->mapAddressBook) {
- result.emplace_back(item.first, IsMine(*m_wallet, item.first),
+ result.emplace_back(item.first, m_wallet->IsMine(item.first),
item.second.name, item.second.purpose);
}
return result;
}
void learnRelatedScripts(const CPubKey &key, OutputType type) override {
- m_wallet->LearnRelatedScripts(key, type);
+ m_wallet->GetLegacyScriptPubKeyMan()->LearnRelatedScripts(key,
+ type);
}
bool addDestData(const CTxDestination &dest, const std::string &key,
const std::string &value) override {
@@ -319,7 +327,7 @@
result.balance = bal.m_mine_trusted;
result.unconfirmed_balance = bal.m_mine_untrusted_pending;
result.immature_balance = bal.m_mine_immature;
- result.have_watch_only = m_wallet->HaveWatchOnly();
+ result.have_watch_only = haveWatchOnly();
if (result.have_watch_only) {
result.watch_only_balance = bal.m_watchonly_trusted;
result.unconfirmed_watch_only_balance =
diff --git a/src/qt/test/wallettests.cpp b/src/qt/test/wallettests.cpp
--- a/src/qt/test/wallettests.cpp
+++ b/src/qt/test/wallettests.cpp
@@ -120,12 +120,14 @@
bool firstRun;
wallet->LoadWallet(firstRun);
{
+ auto spk_man = wallet->GetLegacyScriptPubKeyMan();
LOCK(wallet->cs_wallet);
+ AssertLockHeld(spk_man->cs_wallet);
wallet->SetAddressBook(
GetDestinationForKey(test.coinbaseKey.GetPubKey(),
wallet->m_default_address_type),
"", "receive");
- wallet->AddKeyPubKey(test.coinbaseKey, test.coinbaseKey.GetPubKey());
+ spk_man->AddKeyPubKey(test.coinbaseKey, test.coinbaseKey.GetPubKey());
}
{
auto locked_chain = wallet->chain().lock();
diff --git a/src/test/util.cpp b/src/test/util.cpp
--- a/src/test/util.cpp
+++ b/src/test/util.cpp
@@ -32,13 +32,15 @@
}
void importaddress(CWallet &wallet, const std::string &address) {
+ auto spk_man = wallet.GetLegacyScriptPubKeyMan();
LOCK(wallet.cs_wallet);
+ AssertLockHeld(spk_man->cs_wallet);
const auto dest = DecodeDestination(address, wallet.chainParams);
assert(IsValidDestination(dest));
const auto script = GetScriptForDestination(dest);
wallet.MarkDirty();
- assert(!wallet.HaveWatchOnly(script));
- if (!wallet.AddWatchOnly(script, 0 /* nCreateTime */)) {
+ assert(!spk_man->HaveWatchOnly(script));
+ if (!spk_man->AddWatchOnly(script, 0 /* nCreateTime */)) {
assert(false);
}
wallet.SetAddressBook(dest, /* label */ "", "receive");
diff --git a/src/wallet/init.cpp b/src/wallet/init.cpp
--- a/src/wallet/init.cpp
+++ b/src/wallet/init.cpp
@@ -13,7 +13,6 @@
#include <util/system.h>
#include <util/translation.h>
#include <wallet/rpcdump.h>
-#include <wallet/scriptpubkeyman.h>
#include <wallet/wallet.h>
#include <walletinitinterface.h>
diff --git a/src/wallet/ismine.h b/src/wallet/ismine.h
--- a/src/wallet/ismine.h
+++ b/src/wallet/ismine.h
@@ -28,9 +28,6 @@
/** used for bitflags of isminetype */
typedef uint8_t isminefilter;
-isminetype IsMine(const CWallet &wallet, const CScript &scriptPubKey);
-isminetype IsMine(const CWallet &wallet, const CTxDestination &dest);
-
/**
* Cachable amount subdivided into watchonly and spendable parts.
*/
diff --git a/src/wallet/psbtwallet.cpp b/src/wallet/psbtwallet.cpp
--- a/src/wallet/psbtwallet.cpp
+++ b/src/wallet/psbtwallet.cpp
@@ -44,14 +44,16 @@
}
complete &=
- SignPSBTInput(HidingSigningProvider(pwallet, !sign, !bip32derivs),
+ SignPSBTInput(HidingSigningProvider(pwallet->GetSigningProvider(),
+ !sign, !bip32derivs),
psbtx, i, sighash_type);
}
// Fill in the bip32 keypaths and redeemscripts for the outputs so that
// hardware wallets can identify change
for (size_t i = 0; i < psbtx.tx->vout.size(); ++i) {
- UpdatePSBTOutput(HidingSigningProvider(pwallet, true, !bip32derivs),
+ UpdatePSBTOutput(HidingSigningProvider(pwallet->GetSigningProvider(),
+ true, !bip32derivs),
psbtx, i);
}
diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp
--- a/src/wallet/rpcdump.cpp
+++ b/src/wallet/rpcdump.cpp
@@ -52,14 +52,14 @@
return ret.str();
}
-static bool GetWalletAddressesForKey(const Config &config,
- CWallet *const pwallet,
- const CKeyID &keyid, std::string &strAddr,
- std::string &strLabel)
+static bool
+GetWalletAddressesForKey(const Config &config, LegacyScriptPubKeyMan *spk_man,
+ CWallet *const pwallet, const CKeyID &keyid,
+ std::string &strAddr, std::string &strLabel)
EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet) {
bool fLabelFound = false;
CKey key;
- pwallet->GetKey(keyid, key);
+ spk_man->GetKey(keyid, key);
for (const auto &dest : GetAllDestinationsForKey(key.GetPubKey())) {
if (pwallet->mapAddressBook.count(dest)) {
if (!strAddr.empty()) {
@@ -141,6 +141,12 @@
"private keys disabled");
}
+ LegacyScriptPubKeyMan *spk_man = pwallet->GetLegacyScriptPubKeyMan();
+ if (!spk_man) {
+ throw JSONRPCError(RPC_WALLET_ERROR,
+ "This type of wallet does not support this command");
+ }
+
WalletRescanReserver reserver(pwallet);
bool fRescan = true;
{
@@ -283,6 +289,12 @@
}
.Check(request);
+ LegacyScriptPubKeyMan *spk_man = pwallet->GetLegacyScriptPubKeyMan();
+ if (!spk_man) {
+ throw JSONRPCError(RPC_WALLET_ERROR,
+ "This type of wallet does not support this command");
+ }
+
std::string strLabel;
if (!request.params[1].isNull()) {
strLabel = request.params[1].get_str();
@@ -533,6 +545,12 @@
}
.Check(request);
+ LegacyScriptPubKeyMan *spk_man = pwallet->GetLegacyScriptPubKeyMan();
+ if (!spk_man) {
+ throw JSONRPCError(RPC_WALLET_ERROR,
+ "This type of wallet does not support this command");
+ }
+
std::string strLabel;
if (!request.params[1].isNull()) {
strLabel = request.params[1].get_str();
@@ -626,6 +644,12 @@
}
.Check(request);
+ LegacyScriptPubKeyMan *spk_man = pwallet->GetLegacyScriptPubKeyMan();
+ if (!spk_man) {
+ throw JSONRPCError(RPC_WALLET_ERROR,
+ "This type of wallet does not support this command");
+ }
+
if (pwallet->chain().havePruned()) {
// Exit early and print an error.
// If a block is pruned after this check, we will import the key(s),
@@ -824,6 +848,12 @@
}
.Check(request);
+ LegacyScriptPubKeyMan *spk_man = pwallet->GetLegacyScriptPubKeyMan();
+ if (!spk_man) {
+ throw JSONRPCError(RPC_WALLET_ERROR,
+ "This type of wallet does not support this command");
+ }
+
auto locked_chain = pwallet->chain().lock();
LOCK(pwallet->cs_wallet);
@@ -836,12 +866,12 @@
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY,
"Invalid Bitcoin address");
}
- auto keyid = GetKeyForDestination(*pwallet, dest);
+ auto keyid = GetKeyForDestination(*spk_man, dest);
if (keyid.IsNull()) {
throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to a key");
}
CKey vchSecret;
- if (!pwallet->GetKey(keyid, vchSecret)) {
+ if (!spk_man->GetKey(keyid, vchSecret)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Private key for address " +
strAddress + " is not known");
}
@@ -879,8 +909,15 @@
}
.Check(request);
+ LegacyScriptPubKeyMan *spk_man = pwallet->GetLegacyScriptPubKeyMan();
+ if (!spk_man) {
+ throw JSONRPCError(RPC_WALLET_ERROR,
+ "This type of wallet does not support this command");
+ }
+
auto locked_chain = pwallet->chain().lock();
LOCK(pwallet->cs_wallet);
+ AssertLockHeld(spk_man->cs_wallet);
EnsureWalletIsUnlocked(pwallet);
@@ -908,10 +945,10 @@
}
std::map<CKeyID, int64_t> mapKeyBirth;
- const std::map<CKeyID, int64_t> &mapKeyPool = pwallet->GetAllReserveKeys();
+ const std::map<CKeyID, int64_t> &mapKeyPool = spk_man->GetAllReserveKeys();
pwallet->GetKeyBirthTimes(*locked_chain, mapKeyBirth);
- std::set<CScriptID> scripts = pwallet->GetCScripts();
+ std::set<CScriptID> scripts = spk_man->GetCScripts();
// sort time/key pairs
std::vector<std::pair<int64_t, CKeyID>> vKeyBirth;
@@ -937,10 +974,10 @@
file << "\n";
// add the base58check encoded extended master if the wallet uses HD
- CKeyID seed_id = pwallet->GetHDChain().seed_id;
+ CKeyID seed_id = spk_man->GetHDChain().seed_id;
if (!seed_id.IsNull()) {
CKey seed;
- if (pwallet->GetKey(seed_id, seed)) {
+ if (spk_man->GetKey(seed_id, seed)) {
CExtKey masterKey;
masterKey.SetSeed(seed.begin(), seed.size());
@@ -956,26 +993,26 @@
std::string strAddr;
std::string strLabel;
CKey key;
- if (pwallet->GetKey(keyid, key)) {
+ if (spk_man->GetKey(keyid, key)) {
file << strprintf("%s %s ", EncodeSecret(key), strTime);
- if (GetWalletAddressesForKey(config, pwallet, keyid, strAddr,
- strLabel)) {
+ if (GetWalletAddressesForKey(config, spk_man, pwallet, keyid,
+ strAddr, strLabel)) {
file << strprintf("label=%s", strLabel);
} else if (keyid == seed_id) {
file << "hdseed=1";
} else if (mapKeyPool.count(keyid)) {
file << "reserve=1";
- } else if (pwallet->mapKeyMetadata[keyid].hdKeypath == "s") {
+ } else if (spk_man->mapKeyMetadata[keyid].hdKeypath == "s") {
file << "inactivehdseed=1";
} else {
file << "change=1";
}
file << strprintf(
" # addr=%s%s\n", strAddr,
- (pwallet->mapKeyMetadata[keyid].has_key_origin
+ (spk_man->mapKeyMetadata[keyid].has_key_origin
? " hdkeypath=" +
WriteHDKeypath(
- pwallet->mapKeyMetadata[keyid].key_origin.path)
+ spk_man->mapKeyMetadata[keyid].key_origin.path)
: ""));
}
}
@@ -985,11 +1022,11 @@
std::string create_time = "0";
std::string address = EncodeDestination(ScriptHash(scriptid), config);
// get birth times for scripts with metadata
- auto it = pwallet->m_script_metadata.find(scriptid);
- if (it != pwallet->m_script_metadata.end()) {
+ auto it = spk_man->m_script_metadata.find(scriptid);
+ if (it != spk_man->m_script_metadata.end()) {
create_time = FormatISO8601DateTime(it->second.nCreateTime);
}
- if (pwallet->GetCScript(scriptid, script)) {
+ if (spk_man->GetCScript(scriptid, script)) {
file << strprintf("%s %s script=1",
HexStr(script.begin(), script.end()),
create_time);
@@ -1440,7 +1477,7 @@
// Check whether we have any work to do
for (const CScript &script : script_pub_keys) {
- if (::IsMine(*pwallet, script) & ISMINE_SPENDABLE) {
+ if (pwallet->IsMine(script) & ISMINE_SPENDABLE) {
throw JSONRPCError(RPC_WALLET_ERROR,
"The wallet already contains the private "
"key for this address or script (\"" +
@@ -1649,6 +1686,12 @@
RPCTypeCheck(mainRequest.params, {UniValue::VARR, UniValue::VOBJ});
+ LegacyScriptPubKeyMan *spk_man = pwallet->GetLegacyScriptPubKeyMan();
+ if (!spk_man) {
+ throw JSONRPCError(RPC_WALLET_ERROR,
+ "This type of wallet does not support this command");
+ }
+
const UniValue &requests = mainRequest.params[0];
// Default options
diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp
--- a/src/wallet/rpcwallet.cpp
+++ b/src/wallet/rpcwallet.cpp
@@ -56,7 +56,7 @@
/**
* Checks if a CKey is in the given CWallet compressed or otherwise
*/
-bool HaveKey(const CWallet &wallet, const CKey &key) {
+bool HaveKey(const SigningProvider &wallet, const CKey &key) {
CKey key2;
key2.Set(key.begin(), key.end(), !key.IsCompressed());
return wallet.HaveKey(key.GetPubKey().GetID()) ||
@@ -318,7 +318,7 @@
std::string old_label = pwallet->mapAddressBook[dest].name;
std::string label = LabelFromValue(request.params[1]);
- if (IsMine(*pwallet, dest)) {
+ if (pwallet->IsMine(dest)) {
pwallet->SetAddressBook(dest, label, "receive");
} else {
pwallet->SetAddressBook(dest, label, "send");
@@ -603,9 +603,11 @@
throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key");
}
+ const SigningProvider *provider = pwallet->GetSigningProvider();
+
CKey key;
CKeyID keyID(*pkhash);
- if (!pwallet->GetKey(keyID, key)) {
+ if (!provider->GetKey(keyID, key)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Private key not available");
}
@@ -674,7 +676,7 @@
"Invalid Bitcoin address");
}
CScript scriptPubKey = GetScriptForDestination(dest);
- if (!IsMine(*pwallet, scriptPubKey)) {
+ if (!pwallet->IsMine(scriptPubKey)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Address not found in wallet");
}
@@ -773,7 +775,7 @@
for (const CTxOut &txout : wtx.tx->vout) {
CTxDestination address;
if (ExtractDestination(txout.scriptPubKey, address) &&
- IsMine(*pwallet, address) && setAddress.count(address)) {
+ pwallet->IsMine(address) && setAddress.count(address)) {
if (wtx.GetDepthInMainChain(*locked_chain) >= nMinDepth) {
nAmount += txout.nValue;
}
@@ -1112,6 +1114,12 @@
}
.Check(request);
+ LegacyScriptPubKeyMan *spk_man = pwallet->GetLegacyScriptPubKeyMan();
+ if (!spk_man) {
+ throw JSONRPCError(RPC_WALLET_ERROR,
+ "This type of wallet does not support this command");
+ }
+
auto locked_chain = pwallet->chain().lock();
LOCK(pwallet->cs_wallet);
@@ -1131,7 +1139,7 @@
keys_or_addrs[i].get_str().length() == 130)) {
pubkeys.push_back(HexToPubKey(keys_or_addrs[i].get_str()));
} else {
- pubkeys.push_back(AddrToPubKey(config.GetChainParams(), pwallet,
+ pubkeys.push_back(AddrToPubKey(config.GetChainParams(), spk_man,
keys_or_addrs[i].get_str()));
}
}
@@ -1141,7 +1149,7 @@
// Construct using pay-to-script-hash:
CScript inner;
CTxDestination dest = AddAndGetMultisigDestination(
- required, pubkeys, output_type, *pwallet, inner);
+ required, pubkeys, output_type, *spk_man, inner);
pwallet->SetAddressBook(dest, label, "send");
UniValue result(UniValue::VOBJ);
@@ -1219,7 +1227,7 @@
continue;
}
- isminefilter mine = IsMine(*pwallet, address);
+ isminefilter mine = pwallet->IsMine(address);
if (!(mine & filter)) {
continue;
}
@@ -1469,7 +1477,7 @@
for (const COutputEntry &s : listSent) {
UniValue entry(UniValue::VOBJ);
if (involvesWatchonly ||
- (::IsMine(*pwallet, s.destination) & ISMINE_WATCH_ONLY)) {
+ (pwallet->IsMine(s.destination) & ISMINE_WATCH_ONLY)) {
entry.pushKV("involvesWatchonly", true);
}
MaybePushAddress(entry, s.destination);
@@ -1502,7 +1510,7 @@
}
UniValue entry(UniValue::VOBJ);
if (involvesWatchonly ||
- (::IsMine(*pwallet, r.destination) & ISMINE_WATCH_ONLY)) {
+ (pwallet->IsMine(r.destination) & ISMINE_WATCH_ONLY)) {
entry.pushKV("involvesWatchonly", true);
}
MaybePushAddress(entry, r.destination);
@@ -2791,7 +2799,8 @@
}
balances.pushKV("mine", balances_mine);
}
- if (wallet.HaveWatchOnly()) {
+ auto spk_man = wallet.GetLegacyScriptPubKeyMan();
+ if (spk_man && spk_man->HaveWatchOnly()) {
UniValue balances_watchonly{UniValue::VOBJ};
balances_watchonly.pushKV("trusted",
ValueFromAmount(bal.m_watchonly_trusted));
@@ -2888,7 +2897,15 @@
obj.pushKV("txcount", (int)pwallet->mapWallet.size());
obj.pushKV("keypoololdest", pwallet->GetOldestKeyPoolTime());
obj.pushKV("keypoolsize", (int64_t)kpExternalSize);
- CKeyID seed_id = pwallet->GetHDChain().seed_id;
+
+ LegacyScriptPubKeyMan *spk_man = pwallet->GetLegacyScriptPubKeyMan();
+ if (spk_man) {
+ CKeyID seed_id = spk_man->GetHDChain().seed_id;
+ if (!seed_id.IsNull()) {
+ obj.pushKV("hdseedid", seed_id.GetHex());
+ }
+ }
+
if (pwallet->CanSupportFeature(FEATURE_HD_SPLIT)) {
obj.pushKV("keypoolsize_hd_internal",
int64_t(pwallet->GetKeyPoolSize() - kpExternalSize));
@@ -2897,9 +2914,6 @@
obj.pushKV("unlocked_until", pwallet->nRelockTime);
}
obj.pushKV("paytxfee", ValueFromAmount(pwallet->m_pay_tx_fee.GetFeePerK()));
- if (!seed_id.IsNull()) {
- obj.pushKV("hdseedid", seed_id.GetHex());
- }
obj.pushKV("private_keys_enabled",
!pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS));
if (pwallet->IsScanning()) {
@@ -3453,11 +3467,12 @@
entry.pushKV("label", i->second.name);
}
+ const SigningProvider *provider = pwallet->GetSigningProvider();
if (scriptPubKey.IsPayToScriptHash()) {
const CScriptID &hash =
CScriptID(boost::get<ScriptHash>(address));
CScript redeemScript;
- if (pwallet->GetCScript(hash, redeemScript)) {
+ if (provider->GetCScript(hash, redeemScript)) {
entry.pushKV("redeemScript", HexStr(redeemScript.begin(),
redeemScript.end()));
}
@@ -3471,7 +3486,8 @@
entry.pushKV("spendable", out.fSpendable);
entry.pushKV("solvable", out.fSolvable);
if (out.fSolvable) {
- auto descriptor = InferDescriptor(scriptPubKey, *pwallet);
+ auto descriptor = InferDescriptor(
+ scriptPubKey, *pwallet->GetLegacyScriptPubKeyMan());
entry.pushKV("desc", descriptor->ToString());
}
if (avoid_reuse) {
@@ -3819,7 +3835,8 @@
// Parse the prevtxs array
ParsePrevouts(request.params[1], nullptr, coins);
- return SignTransaction(mtx, pwallet, coins, request.params[2]);
+ return SignTransaction(mtx, &*pwallet->GetLegacyScriptPubKeyMan(), coins,
+ request.params[2]);
}
UniValue rescanblockchain(const Config &config, const JSONRPCRequest &request) {
@@ -3932,7 +3949,7 @@
class DescribeWalletAddressVisitor : public boost::static_visitor<UniValue> {
public:
- CWallet *const pwallet;
+ const SigningProvider *const provider;
void ProcessSubScript(const CScript &subscript, UniValue &obj) const {
// Always present: script type and redeemscript
@@ -3973,8 +3990,8 @@
}
}
- explicit DescribeWalletAddressVisitor(CWallet *_pwallet)
- : pwallet(_pwallet) {}
+ explicit DescribeWalletAddressVisitor(const SigningProvider *_provider)
+ : provider(_provider) {}
UniValue operator()(const CNoDestination &dest) const {
return UniValue(UniValue::VOBJ);
@@ -3984,7 +4001,7 @@
CKeyID keyID(pkhash);
UniValue obj(UniValue::VOBJ);
CPubKey vchPubKey;
- if (pwallet && pwallet->GetPubKey(keyID, vchPubKey)) {
+ if (provider && provider->GetPubKey(keyID, vchPubKey)) {
obj.pushKV("pubkey", HexStr(vchPubKey));
obj.pushKV("iscompressed", vchPubKey.IsCompressed());
}
@@ -3995,7 +4012,7 @@
CScriptID scriptID(scripthash);
UniValue obj(UniValue::VOBJ);
CScript subscript;
- if (pwallet && pwallet->GetCScript(scriptID, subscript)) {
+ if (provider && provider->GetCScript(scriptID, subscript)) {
ProcessSubScript(subscript, obj);
}
return obj;
@@ -4006,9 +4023,13 @@
const CTxDestination &dest) {
UniValue ret(UniValue::VOBJ);
UniValue detail = DescribeAddress(dest);
+ const SigningProvider *provider = nullptr;
+ if (pwallet) {
+ provider = pwallet->GetSigningProvider();
+ }
ret.pushKVs(detail);
ret.pushKVs(
- boost::apply_visitor(DescribeWalletAddressVisitor(pwallet), dest));
+ boost::apply_visitor(DescribeWalletAddressVisitor(provider), dest));
return ret;
}
@@ -4132,13 +4153,15 @@
CScript scriptPubKey = GetScriptForDestination(dest);
ret.pushKV("scriptPubKey",
HexStr(scriptPubKey.begin(), scriptPubKey.end()));
+ const SigningProvider *provider = pwallet->GetSigningProvider();
- isminetype mine = IsMine(*pwallet, dest);
+ isminetype mine = pwallet->IsMine(dest);
ret.pushKV("ismine", bool(mine & ISMINE_SPENDABLE));
- bool solvable = IsSolvable(*pwallet, scriptPubKey);
+ bool solvable = IsSolvable(*provider, scriptPubKey);
ret.pushKV("solvable", solvable);
if (solvable) {
- ret.pushKV("desc", InferDescriptor(scriptPubKey, *pwallet)->ToString());
+ ret.pushKV("desc",
+ InferDescriptor(scriptPubKey, *provider)->ToString());
}
ret.pushKV("iswatchonly", bool(mine & ISMINE_WATCH_ONLY));
UniValue detail = DescribeWalletAddress(pwallet, dest);
@@ -4148,7 +4171,7 @@
}
ret.pushKV("ischange", pwallet->IsChange(scriptPubKey));
const CKeyMetadata *meta = nullptr;
- CKeyID key_id = GetKeyForDestination(*pwallet, dest);
+ CKeyID key_id = GetKeyForDestination(*provider, dest);
if (!key_id.IsNull()) {
auto it = pwallet->mapKeyMetadata.find(key_id);
if (it != pwallet->mapKeyMetadata.end()) {
@@ -4342,6 +4365,12 @@
}
.Check(request);
+ LegacyScriptPubKeyMan *spk_man = pwallet->GetLegacyScriptPubKeyMan();
+ if (!spk_man) {
+ throw JSONRPCError(RPC_WALLET_ERROR,
+ "This type of wallet does not support this command");
+ }
+
if (pwallet->chain().isInitialBlockDownload()) {
throw JSONRPCError(
RPC_CLIENT_IN_INITIAL_DOWNLOAD,
@@ -4374,7 +4403,7 @@
CPubKey master_pub_key;
if (request.params[1].isNull()) {
- master_pub_key = pwallet->GenerateNewSeed();
+ master_pub_key = spk_man->GenerateNewSeed();
} else {
CKey key = DecodeSecret(request.params[1].get_str());
if (!key.IsValid()) {
@@ -4382,18 +4411,18 @@
"Invalid private key");
}
- if (HaveKey(*pwallet, key)) {
+ if (HaveKey(*spk_man, key)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY,
"Already have this key (either as an HD seed or "
"as a loose private key)");
}
- master_pub_key = pwallet->DeriveNewSeed(key);
+ master_pub_key = spk_man->DeriveNewSeed(key);
}
- pwallet->SetHDSeed(master_pub_key);
+ spk_man->SetHDSeed(master_pub_key);
if (flush_key_pool) {
- pwallet->NewKeyPool();
+ spk_man->NewKeyPool();
}
return NullUniValue;
diff --git a/src/wallet/scriptpubkeyman.h b/src/wallet/scriptpubkeyman.h
--- a/src/wallet/scriptpubkeyman.h
+++ b/src/wallet/scriptpubkeyman.h
@@ -16,6 +16,27 @@
enum class OutputType;
+// Wallet storage things that ScriptPubKeyMans need in order to be able to store
+// things to the wallet database. It provides access to things that are part of
+// the entire wallet and not specific to a ScriptPubKeyMan such as wallet flags,
+// wallet version, encryption keys, encryption status, and the database itself.
+// This allows a ScriptPubKeyMan to have callbacks into CWallet without causing
+// a circular dependency. WalletStorage should be the same for all
+// ScriptPubKeyMans.
+class WalletStorage {
+public:
+ virtual ~WalletStorage() = default;
+ virtual const std::string GetDisplayName() const = 0;
+ virtual WalletDatabase &GetDatabase() = 0;
+ virtual bool IsWalletFlagSet(uint64_t) const = 0;
+ virtual void SetWalletFlag(uint64_t) = 0;
+ virtual void UnsetWalletFlagWithDB(WalletBatch &, uint64_t) = 0;
+ virtual bool CanSupportFeature(enum WalletFeature) const = 0;
+ virtual void SetMinVersion(enum WalletFeature, WalletBatch * = nullptr,
+ bool = false) = 0;
+ virtual bool IsLocked() const = 0;
+};
+
//! Default for -keypool
static const unsigned int DEFAULT_KEYPOOL_SIZE = 1000;
@@ -119,4 +140,273 @@
}
};
+/*
+ * A class implementing ScriptPubKeyMan manages some (or all) scriptPubKeys used
+ * in a wallet. It contains the scripts and keys related to the scriptPubKeys it
+ * manages. A ScriptPubKeyMan will be able to give out scriptPubKeys to be used,
+ * as well as marking when a scriptPubKey has been used. It also handles when
+ * and how to store a scriptPubKey and its related scripts and keys, including
+ * encryption.
+ */
+class ScriptPubKeyMan {
+protected:
+ WalletStorage &m_storage;
+
+public:
+ ScriptPubKeyMan(WalletStorage &storage) : m_storage(storage) {}
+};
+
+class LegacyScriptPubKeyMan : public ScriptPubKeyMan,
+ public FillableSigningProvider {
+private:
+ using CryptedKeyMap =
+ std::map<CKeyID, std::pair<CPubKey, std::vector<uint8_t>>>;
+ using WatchOnlySet = std::set<CScript>;
+ using WatchKeyMap = std::map<CKeyID, CPubKey>;
+
+ //! will encrypt previously unencrypted keys
+ bool EncryptKeys(CKeyingMaterial &vMasterKeyIn);
+
+ CryptedKeyMap mapCryptedKeys GUARDED_BY(cs_KeyStore);
+ WatchOnlySet setWatchOnly GUARDED_BY(cs_KeyStore);
+ WatchKeyMap mapWatchKeys GUARDED_BY(cs_KeyStore);
+
+ bool AddCryptedKeyInner(const CPubKey &vchPubKey,
+ const std::vector<uint8_t> &vchCryptedSecret);
+ bool AddKeyPubKeyInner(const CKey &key, const CPubKey &pubkey);
+
+ WalletBatch *encrypted_batch GUARDED_BY(cs_wallet) = nullptr;
+
+ /* the HD chain data model (external chain counters) */
+ CHDChain hdChain;
+
+ /* HD derive new child key (on internal or external chain) */
+ void DeriveNewChildKey(WalletBatch &batch, CKeyMetadata &metadata,
+ CKey &secret, bool internal = false)
+ EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
+
+ std::set<int64_t> setInternalKeyPool GUARDED_BY(cs_wallet);
+ std::set<int64_t> setExternalKeyPool GUARDED_BY(cs_wallet);
+ std::set<int64_t> set_pre_split_keypool GUARDED_BY(cs_wallet);
+ int64_t m_max_keypool_index GUARDED_BY(cs_wallet) = 0;
+ std::map<CKeyID, int64_t> m_pool_key_to_index;
+
+ int64_t nTimeFirstKey GUARDED_BY(cs_wallet) = 0;
+
+ /**
+ * Private version of AddWatchOnly method which does not accept a
+ * timestamp, and which will reset the wallet's nTimeFirstKey value to 1 if
+ * the watch key did not previously have a timestamp associated with it.
+ * Because this is an inherited virtual method, it is accessible despite
+ * being marked private, but it is marked private anyway to encourage use
+ * of the other AddWatchOnly which accepts a timestamp and sets
+ * nTimeFirstKey more intelligently for more efficient rescans.
+ */
+ bool AddWatchOnly(const CScript &dest) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
+ bool AddWatchOnlyWithDB(WalletBatch &batch, const CScript &dest)
+ EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
+ bool AddWatchOnlyInMem(const CScript &dest);
+
+ /** Add a KeyOriginInfo to the wallet */
+ bool AddKeyOriginWithDB(WalletBatch &batch, const CPubKey &pubkey,
+ const KeyOriginInfo &info);
+
+ //! Adds a key to the store, and saves it to disk.
+ bool AddKeyPubKeyWithDB(WalletBatch &batch, const CKey &key,
+ const CPubKey &pubkey)
+ EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
+
+ //! Adds a watch-only address to the store, and saves it to disk.
+ bool AddWatchOnlyWithDB(WalletBatch &batch, const CScript &dest,
+ int64_t create_time)
+ EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
+
+ void AddKeypoolPubkeyWithDB(const CPubKey &pubkey, const bool internal,
+ WalletBatch &batch);
+
+ //! Adds a script to the store and saves it to disk
+ bool AddCScriptWithDB(WalletBatch &batch, const CScript &script);
+
+public:
+ //! Fetches a key from the keypool
+ bool GetKeyFromPool(CPubKey &key, bool internal = false);
+ void LoadKeyPool(int64_t nIndex, const CKeyPool &keypool)
+ EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
+ void MarkPreSplitKeys() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
+
+ // Map from Key ID to key metadata.
+ std::map<CKeyID, CKeyMetadata> mapKeyMetadata GUARDED_BY(cs_wallet);
+
+ // Map from Script ID to key metadata (for watch-only keys).
+ std::map<CScriptID, CKeyMetadata> m_script_metadata GUARDED_BY(cs_wallet);
+
+ /**
+ * keystore implementation
+ * Generate a new key
+ */
+ CPubKey GenerateNewKey(WalletBatch &batch, bool internal = false)
+ EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
+ //! Adds a key to the store, and saves it to disk.
+ bool AddKeyPubKey(const CKey &key, const CPubKey &pubkey) override
+ EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
+ //! Adds a key to the store, without saving it to disk (used by LoadWallet)
+ bool LoadKey(const CKey &key, const CPubKey &pubkey) {
+ return AddKeyPubKeyInner(key, pubkey);
+ }
+ //! Load metadata (used by LoadWallet)
+ void LoadKeyMetadata(const CKeyID &keyID, const CKeyMetadata &metadata)
+ EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
+ void LoadScriptMetadata(const CScriptID &script_id,
+ const CKeyMetadata &metadata)
+ EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
+ //! Upgrade stored CKeyMetadata objects to store key origin info as
+ //! KeyOriginInfo
+ void UpgradeKeyMetadata() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
+ void UpdateTimeFirstKey(int64_t nCreateTime)
+ EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
+
+ //! Adds an encrypted key to the store, and saves it to disk.
+ bool AddCryptedKey(const CPubKey &vchPubKey,
+ const std::vector<uint8_t> &vchCryptedSecret);
+ //! Adds an encrypted key to the store, without saving it to disk (used by
+ //! LoadWallet)
+ bool LoadCryptedKey(const CPubKey &vchPubKey,
+ const std::vector<uint8_t> &vchCryptedSecret);
+ bool GetKey(const CKeyID &address, CKey &keyOut) const override;
+ bool GetPubKey(const CKeyID &address, CPubKey &vchPubKeyOut) const override;
+ bool HaveKey(const CKeyID &address) const override;
+ std::set<CKeyID> GetKeys() const override;
+ bool AddCScript(const CScript &redeemScript) override;
+ bool LoadCScript(const CScript &redeemScript);
+
+ //! Adds a watch-only address to the store, and saves it to disk.
+ bool AddWatchOnly(const CScript &dest, int64_t nCreateTime)
+ EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
+ bool RemoveWatchOnly(const CScript &dest)
+ EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
+ //! Adds a watch-only address to the store, without saving it to disk (used
+ //! by LoadWallet)
+ bool LoadWatchOnly(const CScript &dest);
+ //! Returns whether the watch-only script is in the wallet
+ bool HaveWatchOnly(const CScript &dest) const;
+ //! Returns whether there are any watch-only things in the wallet
+ bool HaveWatchOnly() const;
+ //! Fetches a pubkey from mapWatchKeys if it exists there
+ bool GetWatchPubKey(const CKeyID &address, CPubKey &pubkey_out) const;
+
+ bool ImportScripts(const std::set<CScript> scripts, int64_t timestamp)
+ EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
+ bool ImportPrivKeys(const std::map<CKeyID, CKey> &privkey_map,
+ const int64_t timestamp)
+ EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
+ bool ImportPubKeys(
+ const std::vector<CKeyID> &ordered_pubkeys,
+ const std::map<CKeyID, CPubKey> &pubkey_map,
+ const std::map<CKeyID, std::pair<CPubKey, KeyOriginInfo>> &key_origins,
+ const bool add_keypool, const bool internal, const int64_t timestamp)
+ EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
+ bool ImportScriptPubKeys(const std::string &label,
+ const std::set<CScript> &script_pub_keys,
+ const bool have_solving_data,
+ const bool apply_label, const int64_t timestamp)
+ EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
+
+ bool NewKeyPool();
+ size_t KeypoolCountExternalKeys() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
+ bool TopUpKeyPool(unsigned int kpSize = 0);
+
+ /**
+ * Reserves a key from the keypool and sets nIndex to its index
+ *
+ * @param[out] nIndex the index of the key in keypool
+ * @param[out] keypool the keypool the key was drawn from, which could be
+ * the the pre-split pool if present, or the internal or external pool
+ * @param fRequestedInternal true if the caller would like the key drawn
+ * from the internal keypool, false if external is preferred
+ *
+ * @return true if succeeded, false if failed due to empty keypool
+ * @throws std::runtime_error if keypool read failed, key was invalid,
+ * was not found in the wallet, or was misclassified in the internal
+ * or external keypool
+ */
+ bool ReserveKeyFromKeyPool(int64_t &nIndex, CKeyPool &keypool,
+ bool fRequestedInternal);
+ void KeepKey(int64_t nIndex);
+ void ReturnKey(int64_t nIndex, bool fInternal, const CPubKey &pubkey);
+ int64_t GetOldestKeyPoolTime();
+ /**
+ * Marks all keys in the keypool up to and including reserve_key as used.
+ */
+ void MarkReserveKeysAsUsed(int64_t keypool_id)
+ EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
+ const std::map<CKeyID, int64_t> &GetAllReserveKeys() const {
+ return m_pool_key_to_index;
+ }
+ bool GetNewDestination(const OutputType type, const std::string label,
+ CTxDestination &dest, std::string &error);
+
+ isminetype IsMine(const CScript &script) const;
+
+ /* Set the HD chain model (chain child index counters) */
+ void SetHDChain(const CHDChain &chain, bool memonly);
+ const CHDChain &GetHDChain() const { return hdChain; }
+
+ /* Returns true if HD is enabled */
+ bool IsHDEnabled() const;
+
+ /* Returns true if the wallet can generate new keys */
+ bool CanGenerateKeys();
+
+ /* Returns true if the wallet can give out new addresses. This means it has
+ * keys in the keypool or can generate new keys */
+ bool CanGetAddresses(bool internal = false);
+
+ /* Generates a new HD seed (will not be activated) */
+ CPubKey GenerateNewSeed();
+
+ /* Derives a new HD seed (will not be activated) */
+ CPubKey DeriveNewSeed(const CKey &key);
+
+ /* Set the current HD seed (will reset the chain child index counters)
+ Sets the seed's version based on the current wallet version (so the
+ caller must ensure the current wallet version is correct before calling
+ this function). */
+ void SetHDSeed(const CPubKey &key);
+
+ /**
+ * Explicitly make the wallet learn the related scripts for outputs to the
+ * given key. This is purely to make the wallet file compatible with older
+ * software, as FillableSigningProvider automatically does this implicitly
+ * for all keys now.
+ */
+ void LearnRelatedScripts(const CPubKey &key, OutputType);
+
+ /**
+ * Same as LearnRelatedScripts, but when the OutputType is not known (and
+ * could be anything).
+ */
+ void LearnAllRelatedScripts(const CPubKey &key);
+
+ /** Implement lookup of key origin information through wallet key metadata.
+ */
+ bool GetKeyOrigin(const CKeyID &keyid, KeyOriginInfo &info) const override;
+
+ // Temporary CWallet accessors and aliases.
+ friend class CWallet;
+ friend class ReserveDestination;
+ LegacyScriptPubKeyMan(CWallet &wallet);
+ bool SetCrypted();
+ bool IsCrypted() const;
+ void NotifyWatchonlyChanged(bool fHaveWatchOnly) const;
+ void NotifyCanGetAddressesChanged() const;
+ template <typename... Params>
+ void WalletLogPrintf(const std::string &fmt,
+ const Params &... parameters) const;
+ CWallet &m_wallet;
+ RecursiveMutex &cs_wallet;
+ CKeyingMaterial &vMasterKey GUARDED_BY(cs_KeyStore);
+ std::atomic<bool> &fUseCrypto;
+ bool &fDecryptionThoroughlyChecked;
+};
+
#endif // BITCOIN_WALLET_SCRIPTPUBKEYMAN_H
diff --git a/src/wallet/scriptpubkeyman.cpp b/src/wallet/scriptpubkeyman.cpp
--- a/src/wallet/scriptpubkeyman.cpp
+++ b/src/wallet/scriptpubkeyman.cpp
@@ -12,8 +12,10 @@
#include <wallet/scriptpubkeyman.h>
#include <wallet/wallet.h>
-bool CWallet::GetNewDestination(const OutputType type, const std::string label,
- CTxDestination &dest, std::string &error) {
+bool LegacyScriptPubKeyMan::GetNewDestination(const OutputType type,
+ const std::string label,
+ CTxDestination &dest,
+ std::string &error) {
LOCK(cs_wallet);
error.clear();
TopUpKeyPool();
@@ -27,7 +29,7 @@
LearnRelatedScripts(new_key, type);
dest = GetDestinationForKey(new_key, type);
- SetAddressBook(dest, label, "receive");
+ m_wallet.SetAddressBook(dest, label, "receive");
return true;
}
@@ -58,7 +60,8 @@
INVALID = 3, //! Not spendable by anyone (P2SH inside P2SH)
};
-bool HaveKeys(const std::vector<valtype> &pubkeys, const CWallet &keystore) {
+bool HaveKeys(const std::vector<valtype> &pubkeys,
+ const LegacyScriptPubKeyMan &keystore) {
for (const valtype &pubkey : pubkeys) {
CKeyID keyID = CPubKey(pubkey).GetID();
if (!keystore.HaveKey(keyID)) {
@@ -68,7 +71,8 @@
return true;
}
-IsMineResult IsMineInner(const CWallet &keystore, const CScript &scriptPubKey,
+IsMineResult IsMineInner(const LegacyScriptPubKeyMan &keystore,
+ const CScript &scriptPubKey,
IsMineSigVersion sigversion) {
IsMineResult ret = IsMineResult::NO;
@@ -135,8 +139,8 @@
} // namespace
-isminetype IsMine(const CWallet &keystore, const CScript &scriptPubKey) {
- switch (IsMineInner(keystore, scriptPubKey, IsMineSigVersion::TOP)) {
+isminetype LegacyScriptPubKeyMan::IsMine(const CScript &script) const {
+ switch (IsMineInner(*this, script, IsMineSigVersion::TOP)) {
case IsMineResult::INVALID:
case IsMineResult::NO:
return ISMINE_NO;
@@ -187,7 +191,7 @@
return true;
}
-bool CWallet::EncryptKeys(CKeyingMaterial &vMasterKeyIn) {
+bool LegacyScriptPubKeyMan::EncryptKeys(CKeyingMaterial &vMasterKeyIn) {
LOCK(cs_KeyStore);
if (!mapCryptedKeys.empty() || IsCrypted()) {
return false;
@@ -211,13 +215,14 @@
return true;
}
-void CWallet::UpgradeKeyMetadata() {
+void LegacyScriptPubKeyMan::UpgradeKeyMetadata() {
AssertLockHeld(cs_wallet);
- if (IsLocked() || IsWalletFlagSet(WALLET_FLAG_KEY_ORIGIN_METADATA)) {
+ if (m_storage.IsLocked() ||
+ m_storage.IsWalletFlagSet(WALLET_FLAG_KEY_ORIGIN_METADATA)) {
return;
}
- auto batch = std::make_unique<WalletBatch>(*database);
+ auto batch = std::make_unique<WalletBatch>(m_storage.GetDatabase());
for (auto &meta_pair : mapKeyMetadata) {
CKeyMetadata &meta = meta_pair.second;
// If the hdKeypath is "s", that's the seed and it doesn't have a key
@@ -250,18 +255,18 @@
// write before setting the flag
batch.reset();
- SetWalletFlag(WALLET_FLAG_KEY_ORIGIN_METADATA);
+ m_storage.SetWalletFlag(WALLET_FLAG_KEY_ORIGIN_METADATA);
}
-bool CWallet::IsHDEnabled() const {
+bool LegacyScriptPubKeyMan::IsHDEnabled() const {
return !hdChain.seed_id.IsNull();
}
-bool CWallet::CanGetAddresses(bool internal) {
+bool LegacyScriptPubKeyMan::CanGetAddresses(bool internal) {
LOCK(cs_wallet);
// Check if the keypool has keys
bool keypool_has_keys;
- if (internal && CanSupportFeature(FEATURE_HD_SPLIT)) {
+ if (internal && m_storage.CanSupportFeature(FEATURE_HD_SPLIT)) {
keypool_has_keys = setInternalKeyPool.size() > 0;
} else {
keypool_has_keys = KeypoolCountExternalKeys() > 0;
@@ -290,14 +295,14 @@
return keypool.nTime;
}
-int64_t CWallet::GetOldestKeyPoolTime() {
+int64_t LegacyScriptPubKeyMan::GetOldestKeyPoolTime() {
LOCK(cs_wallet);
- WalletBatch batch(*database);
+ WalletBatch batch(m_storage.GetDatabase());
// load oldest key from keypool, get time and return
int64_t oldestKey = GetOldestKeyTimeInPool(setExternalKeyPool, batch);
- if (IsHDEnabled() && CanSupportFeature(FEATURE_HD_SPLIT)) {
+ if (IsHDEnabled() && m_storage.CanSupportFeature(FEATURE_HD_SPLIT)) {
oldestKey = std::max(GetOldestKeyTimeInPool(setInternalKeyPool, batch),
oldestKey);
if (!set_pre_split_keypool.empty()) {
@@ -310,7 +315,7 @@
return oldestKey;
}
-size_t CWallet::KeypoolCountExternalKeys() {
+size_t LegacyScriptPubKeyMan::KeypoolCountExternalKeys() {
AssertLockHeld(cs_wallet);
return setExternalKeyPool.size() + set_pre_split_keypool.size();
}
@@ -319,7 +324,7 @@
* Update wallet first key creation time. This should be called whenever keys
* are added to the wallet, with the oldest key creation time.
*/
-void CWallet::UpdateTimeFirstKey(int64_t nCreateTime) {
+void LegacyScriptPubKeyMan::UpdateTimeFirstKey(int64_t nCreateTime) {
AssertLockHeld(cs_wallet);
if (nCreateTime <= 1) {
// Cannot determine birthday information, so set the wallet birthday to
@@ -330,17 +335,17 @@
}
}
-bool CWallet::AddKeyPubKey(const CKey &secret, const CPubKey &pubkey) {
- WalletBatch batch(*database);
- return CWallet::AddKeyPubKeyWithDB(batch, secret, pubkey);
+bool LegacyScriptPubKeyMan::AddKeyPubKey(const CKey &secret,
+ const CPubKey &pubkey) {
+ WalletBatch batch(m_storage.GetDatabase());
+ return LegacyScriptPubKeyMan::AddKeyPubKeyWithDB(batch, secret, pubkey);
}
-bool CWallet::AddKeyPubKeyWithDB(WalletBatch &batch, const CKey &secret,
- const CPubKey &pubkey) {
- AssertLockHeld(cs_wallet);
-
+bool LegacyScriptPubKeyMan::AddKeyPubKeyWithDB(WalletBatch &batch,
+ const CKey &secret,
+ const CPubKey &pubkey) {
// Make sure we aren't adding private keys to private key disabled wallets
- assert(!IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS));
+ assert(!m_storage.IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS));
// FillableSigningProvider has no concept of wallet databases, but calls
// AddCryptedKey which is overridden below. To avoid flushes, the database
@@ -377,11 +382,11 @@
mapKeyMetadata[pubkey.GetID()]);
}
- UnsetWalletFlagWithDB(batch, WALLET_FLAG_BLANK_WALLET);
+ m_storage.UnsetWalletFlagWithDB(batch, WALLET_FLAG_BLANK_WALLET);
return true;
}
-bool CWallet::LoadCScript(const CScript &redeemScript) {
+bool LegacyScriptPubKeyMan::LoadCScript(const CScript &redeemScript) {
/**
* A sanity check was added in pull #3843 to avoid adding redeemScripts that
* never can be redeemed. However, old wallets may still contain these. Do
@@ -401,26 +406,28 @@
return FillableSigningProvider::AddCScript(redeemScript);
}
-void CWallet::LoadKeyMetadata(const CKeyID &keyID, const CKeyMetadata &meta) {
+void LegacyScriptPubKeyMan::LoadKeyMetadata(const CKeyID &keyID,
+ const CKeyMetadata &meta) {
AssertLockHeld(cs_wallet);
UpdateTimeFirstKey(meta.nCreateTime);
mapKeyMetadata[keyID] = meta;
}
-void CWallet::LoadScriptMetadata(const CScriptID &script_id,
- const CKeyMetadata &meta) {
+void LegacyScriptPubKeyMan::LoadScriptMetadata(const CScriptID &script_id,
+ const CKeyMetadata &meta) {
AssertLockHeld(cs_wallet);
UpdateTimeFirstKey(meta.nCreateTime);
m_script_metadata[script_id] = meta;
}
-bool CWallet::AddKeyPubKeyInner(const CKey &key, const CPubKey &pubkey) {
+bool LegacyScriptPubKeyMan::AddKeyPubKeyInner(const CKey &key,
+ const CPubKey &pubkey) {
LOCK(cs_KeyStore);
if (!IsCrypted()) {
return FillableSigningProvider::AddKeyPubKey(key, pubkey);
}
- if (IsLocked()) {
+ if (m_storage.IsLocked()) {
return false;
}
@@ -437,13 +444,13 @@
return true;
}
-bool CWallet::LoadCryptedKey(const CPubKey &vchPubKey,
- const std::vector<uint8_t> &vchCryptedSecret) {
+bool LegacyScriptPubKeyMan::LoadCryptedKey(
+ const CPubKey &vchPubKey, const std::vector<uint8_t> &vchCryptedSecret) {
return AddCryptedKeyInner(vchPubKey, vchCryptedSecret);
}
-bool CWallet::AddCryptedKeyInner(const CPubKey &vchPubKey,
- const std::vector<uint8_t> &vchCryptedSecret) {
+bool LegacyScriptPubKeyMan::AddCryptedKeyInner(
+ const CPubKey &vchPubKey, const std::vector<uint8_t> &vchCryptedSecret) {
LOCK(cs_KeyStore);
if (!SetCrypted()) {
return false;
@@ -453,8 +460,8 @@
return true;
}
-bool CWallet::AddCryptedKey(const CPubKey &vchPubKey,
- const std::vector<uint8_t> &vchCryptedSecret) {
+bool LegacyScriptPubKeyMan::AddCryptedKey(
+ const CPubKey &vchPubKey, const std::vector<uint8_t> &vchCryptedSecret) {
if (!AddCryptedKeyInner(vchPubKey, vchCryptedSecret)) {
return false;
}
@@ -465,16 +472,17 @@
vchPubKey, vchCryptedSecret, mapKeyMetadata[vchPubKey.GetID()]);
}
- return WalletBatch(*database).WriteCryptedKey(
- vchPubKey, vchCryptedSecret, mapKeyMetadata[vchPubKey.GetID()]);
+ return WalletBatch(m_storage.GetDatabase())
+ .WriteCryptedKey(vchPubKey, vchCryptedSecret,
+ mapKeyMetadata[vchPubKey.GetID()]);
}
-bool CWallet::HaveWatchOnly(const CScript &dest) const {
+bool LegacyScriptPubKeyMan::HaveWatchOnly(const CScript &dest) const {
LOCK(cs_KeyStore);
return setWatchOnly.count(dest) > 0;
}
-bool CWallet::HaveWatchOnly() const {
+bool LegacyScriptPubKeyMan::HaveWatchOnly() const {
LOCK(cs_KeyStore);
return (!setWatchOnly.empty());
}
@@ -485,7 +493,7 @@
(pubKeyOut = CPubKey(solutions[0])).IsFullyValid();
}
-bool CWallet::RemoveWatchOnly(const CScript &dest) {
+bool LegacyScriptPubKeyMan::RemoveWatchOnly(const CScript &dest) {
AssertLockHeld(cs_wallet);
{
LOCK(cs_KeyStore);
@@ -500,14 +508,14 @@
NotifyWatchonlyChanged(false);
}
- return WalletBatch(*database).EraseWatchOnly(dest);
+ return WalletBatch(m_storage.GetDatabase()).EraseWatchOnly(dest);
}
-bool CWallet::LoadWatchOnly(const CScript &dest) {
+bool LegacyScriptPubKeyMan::LoadWatchOnly(const CScript &dest) {
return AddWatchOnlyInMem(dest);
}
-bool CWallet::AddWatchOnlyInMem(const CScript &dest) {
+bool LegacyScriptPubKeyMan::AddWatchOnlyInMem(const CScript &dest) {
LOCK(cs_KeyStore);
setWatchOnly.insert(dest);
CPubKey pubKey;
@@ -517,7 +525,8 @@
return true;
}
-bool CWallet::AddWatchOnlyWithDB(WalletBatch &batch, const CScript &dest) {
+bool LegacyScriptPubKeyMan::AddWatchOnlyWithDB(WalletBatch &batch,
+ const CScript &dest) {
if (!AddWatchOnlyInMem(dest)) {
return false;
}
@@ -526,31 +535,33 @@
UpdateTimeFirstKey(meta.nCreateTime);
NotifyWatchonlyChanged(true);
if (batch.WriteWatchOnly(dest, meta)) {
- UnsetWalletFlagWithDB(batch, WALLET_FLAG_BLANK_WALLET);
+ m_storage.UnsetWalletFlagWithDB(batch, WALLET_FLAG_BLANK_WALLET);
return true;
}
return false;
}
-bool CWallet::AddWatchOnlyWithDB(WalletBatch &batch, const CScript &dest,
- int64_t create_time) {
+bool LegacyScriptPubKeyMan::AddWatchOnlyWithDB(WalletBatch &batch,
+ const CScript &dest,
+ int64_t create_time) {
m_script_metadata[CScriptID(dest)].nCreateTime = create_time;
return AddWatchOnlyWithDB(batch, dest);
}
-bool CWallet::AddWatchOnly(const CScript &dest) {
- WalletBatch batch(*database);
+bool LegacyScriptPubKeyMan::AddWatchOnly(const CScript &dest) {
+ WalletBatch batch(m_storage.GetDatabase());
return AddWatchOnlyWithDB(batch, dest);
}
-bool CWallet::AddWatchOnly(const CScript &dest, int64_t nCreateTime) {
+bool LegacyScriptPubKeyMan::AddWatchOnly(const CScript &dest,
+ int64_t nCreateTime) {
m_script_metadata[CScriptID(dest)].nCreateTime = nCreateTime;
return AddWatchOnly(dest);
}
-void CWallet::SetHDChain(const CHDChain &chain, bool memonly) {
+void LegacyScriptPubKeyMan::SetHDChain(const CHDChain &chain, bool memonly) {
LOCK(cs_wallet);
- if (!memonly && !WalletBatch(*database).WriteHDChain(chain)) {
+ if (!memonly && !WalletBatch(m_storage.GetDatabase()).WriteHDChain(chain)) {
throw std::runtime_error(std::string(__func__) +
": writing chain failed");
}
@@ -558,7 +569,7 @@
hdChain = chain;
}
-bool CWallet::HaveKey(const CKeyID &address) const {
+bool LegacyScriptPubKeyMan::HaveKey(const CKeyID &address) const {
LOCK(cs_KeyStore);
if (!IsCrypted()) {
return FillableSigningProvider::HaveKey(address);
@@ -566,7 +577,7 @@
return mapCryptedKeys.count(address) > 0;
}
-bool CWallet::GetKey(const CKeyID &address, CKey &keyOut) const {
+bool LegacyScriptPubKeyMan::GetKey(const CKeyID &address, CKey &keyOut) const {
LOCK(cs_KeyStore);
if (!IsCrypted()) {
return FillableSigningProvider::GetKey(address, keyOut);
@@ -581,7 +592,8 @@
return false;
}
-bool CWallet::GetKeyOrigin(const CKeyID &keyID, KeyOriginInfo &info) const {
+bool LegacyScriptPubKeyMan::GetKeyOrigin(const CKeyID &keyID,
+ KeyOriginInfo &info) const {
CKeyMetadata meta;
{
LOCK(cs_wallet);
@@ -601,7 +613,8 @@
return true;
}
-bool CWallet::GetWatchPubKey(const CKeyID &address, CPubKey &pubkey_out) const {
+bool LegacyScriptPubKeyMan::GetWatchPubKey(const CKeyID &address,
+ CPubKey &pubkey_out) const {
LOCK(cs_KeyStore);
WatchKeyMap::const_iterator it = mapWatchKeys.find(address);
if (it != mapWatchKeys.end()) {
@@ -611,7 +624,8 @@
return false;
}
-bool CWallet::GetPubKey(const CKeyID &address, CPubKey &vchPubKeyOut) const {
+bool LegacyScriptPubKeyMan::GetPubKey(const CKeyID &address,
+ CPubKey &vchPubKeyOut) const {
LOCK(cs_KeyStore);
if (!IsCrypted()) {
if (!FillableSigningProvider::GetPubKey(address, vchPubKeyOut)) {
@@ -630,12 +644,13 @@
return GetWatchPubKey(address, vchPubKeyOut);
}
-CPubKey CWallet::GenerateNewKey(WalletBatch &batch, bool internal) {
- assert(!IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS));
- assert(!IsWalletFlagSet(WALLET_FLAG_BLANK_WALLET));
+CPubKey LegacyScriptPubKeyMan::GenerateNewKey(WalletBatch &batch,
+ bool internal) {
+ assert(!m_storage.IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS));
+ assert(!m_storage.IsWalletFlagSet(WALLET_FLAG_BLANK_WALLET));
AssertLockHeld(cs_wallet);
// default to compressed public keys if we want 0.6.0 wallets
- bool fCompressed = CanSupportFeature(FEATURE_COMPRPUBKEY);
+ bool fCompressed = m_storage.CanSupportFeature(FEATURE_COMPRPUBKEY);
CKey secret;
@@ -648,14 +663,14 @@
if (IsHDEnabled()) {
DeriveNewChildKey(
batch, metadata, secret,
- (CanSupportFeature(FEATURE_HD_SPLIT) ? internal : false));
+ (m_storage.CanSupportFeature(FEATURE_HD_SPLIT) ? internal : false));
} else {
secret.MakeNewKey(fCompressed);
}
// Compressed public keys were introduced in version 0.6.0
if (fCompressed) {
- SetMinVersion(FEATURE_COMPRPUBKEY);
+ m_storage.SetMinVersion(FEATURE_COMPRPUBKEY);
}
CPubKey pubkey = secret.GetPubKey();
@@ -673,8 +688,9 @@
const uint32_t BIP32_HARDENED_KEY_LIMIT = 0x80000000;
-void CWallet::DeriveNewChildKey(WalletBatch &batch, CKeyMetadata &metadata,
- CKey &secret, bool internal) {
+void LegacyScriptPubKeyMan::DeriveNewChildKey(WalletBatch &batch,
+ CKeyMetadata &metadata,
+ CKey &secret, bool internal) {
// for now we use a fixed keypath scheme of m/0'/0'/k
// seed (256bit)
CKey seed;
@@ -700,7 +716,7 @@
masterKey.Derive(accountKey, BIP32_HARDENED_KEY_LIMIT);
// derive m/0'/0' (external chain) OR m/0'/1' (internal chain)
- assert(internal ? CanSupportFeature(FEATURE_HD_SPLIT) : true);
+ assert(internal ? m_storage.CanSupportFeature(FEATURE_HD_SPLIT) : true);
accountKey.Derive(chainChildKey,
BIP32_HARDENED_KEY_LIMIT + (internal ? 1 : 0));
@@ -747,7 +763,8 @@
}
}
-void CWallet::LoadKeyPool(int64_t nIndex, const CKeyPool &keypool) {
+void LegacyScriptPubKeyMan::LoadKeyPool(int64_t nIndex,
+ const CKeyPool &keypool) {
AssertLockHeld(cs_wallet);
if (keypool.m_pre_split) {
set_pre_split_keypool.insert(nIndex);
@@ -768,21 +785,21 @@
}
}
-bool CWallet::CanGenerateKeys() {
+bool LegacyScriptPubKeyMan::CanGenerateKeys() {
// A wallet can generate keys if it has an HD seed (IsHDEnabled) or it is a
// non-HD wallet (pre FEATURE_HD)
LOCK(cs_wallet);
- return IsHDEnabled() || !CanSupportFeature(FEATURE_HD);
+ return IsHDEnabled() || !m_storage.CanSupportFeature(FEATURE_HD);
}
-CPubKey CWallet::GenerateNewSeed() {
- assert(!IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS));
+CPubKey LegacyScriptPubKeyMan::GenerateNewSeed() {
+ assert(!m_storage.IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS));
CKey key;
key.MakeNewKey(true);
return DeriveNewSeed(key);
}
-CPubKey CWallet::DeriveNewSeed(const CKey &key) {
+CPubKey LegacyScriptPubKeyMan::DeriveNewSeed(const CKey &key) {
int64_t nCreationTime = GetTime();
CKeyMetadata metadata(nCreationTime);
@@ -809,30 +826,30 @@
return seed;
}
-void CWallet::SetHDSeed(const CPubKey &seed) {
+void LegacyScriptPubKeyMan::SetHDSeed(const CPubKey &seed) {
LOCK(cs_wallet);
// Store the keyid (hash160) together with the child index counter in the
// database as a hdchain object.
CHDChain newHdChain;
- newHdChain.nVersion = CanSupportFeature(FEATURE_HD_SPLIT)
+ newHdChain.nVersion = m_storage.CanSupportFeature(FEATURE_HD_SPLIT)
? CHDChain::VERSION_HD_CHAIN_SPLIT
: CHDChain::VERSION_HD_BASE;
newHdChain.seed_id = seed.GetID();
SetHDChain(newHdChain, false);
NotifyCanGetAddressesChanged();
- UnsetWalletFlag(WALLET_FLAG_BLANK_WALLET);
+ m_wallet.UnsetWalletFlag(WALLET_FLAG_BLANK_WALLET);
}
/**
* Mark old keypool keys as used, and generate all new keys.
*/
-bool CWallet::NewKeyPool() {
- if (IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
+bool LegacyScriptPubKeyMan::NewKeyPool() {
+ if (m_storage.IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
return false;
}
LOCK(cs_wallet);
- WalletBatch batch(*database);
+ WalletBatch batch(m_storage.GetDatabase());
for (const int64_t nIndex : setInternalKeyPool) {
batch.ErasePool(nIndex);
@@ -855,18 +872,18 @@
return false;
}
- WalletLogPrintf("CWallet::NewKeyPool rewrote keypool\n");
+ WalletLogPrintf("LegacyScriptPubKeyMan::NewKeyPool rewrote keypool\n");
return true;
}
-bool CWallet::TopUpKeyPool(unsigned int kpSize) {
+bool LegacyScriptPubKeyMan::TopUpKeyPool(unsigned int kpSize) {
if (!CanGenerateKeys()) {
return false;
}
{
LOCK(cs_wallet);
- if (IsLocked()) {
+ if (m_storage.IsLocked()) {
return false;
}
@@ -887,12 +904,12 @@
int64_t missingInternal = std::max<int64_t>(
std::max<int64_t>(nTargetSize, 1) - setInternalKeyPool.size(), 0);
- if (!IsHDEnabled() || !CanSupportFeature(FEATURE_HD_SPLIT)) {
+ if (!IsHDEnabled() || !m_storage.CanSupportFeature(FEATURE_HD_SPLIT)) {
// don't create extra internal keys
missingInternal = 0;
}
bool internal = false;
- WalletBatch batch(*database);
+ WalletBatch batch(m_storage.GetDatabase());
for (int64_t i = missingInternal + missingExternal; i--;) {
if (i < missingInternal) {
internal = true;
@@ -914,8 +931,9 @@
return true;
}
-void CWallet::AddKeypoolPubkeyWithDB(const CPubKey &pubkey, const bool internal,
- WalletBatch &batch) {
+void LegacyScriptPubKeyMan::AddKeypoolPubkeyWithDB(const CPubKey &pubkey,
+ const bool internal,
+ WalletBatch &batch) {
LOCK(cs_wallet);
// How in the hell did you use so many keys?
assert(m_max_keypool_index < std::numeric_limits<int64_t>::max());
@@ -932,14 +950,15 @@
m_pool_key_to_index[pubkey.GetID()] = index;
}
-void CWallet::KeepKey(int64_t nIndex) {
+void LegacyScriptPubKeyMan::KeepKey(int64_t nIndex) {
// Remove from key pool.
- WalletBatch batch(*database);
+ WalletBatch batch(m_storage.GetDatabase());
batch.ErasePool(nIndex);
WalletLogPrintf("keypool keep %d\n", nIndex);
}
-void CWallet::ReturnKey(int64_t nIndex, bool fInternal, const CPubKey &pubkey) {
+void LegacyScriptPubKeyMan::ReturnKey(int64_t nIndex, bool fInternal,
+ const CPubKey &pubkey) {
// Return to key pool
{
LOCK(cs_wallet);
@@ -957,7 +976,7 @@
WalletLogPrintf("keypool return %d\n", nIndex);
}
-bool CWallet::GetKeyFromPool(CPubKey &result, bool internal) {
+bool LegacyScriptPubKeyMan::GetKeyFromPool(CPubKey &result, bool internal) {
if (!CanGetAddresses(internal)) {
return false;
}
@@ -966,11 +985,11 @@
LOCK(cs_wallet);
int64_t nIndex;
if (!ReserveKeyFromKeyPool(nIndex, keypool, internal) &&
- !IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
- if (IsLocked()) {
+ !m_storage.IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
+ if (m_storage.IsLocked()) {
return false;
}
- WalletBatch batch(*database);
+ WalletBatch batch(m_storage.GetDatabase());
result = GenerateNewKey(batch, internal);
return true;
}
@@ -981,8 +1000,9 @@
return true;
}
-bool CWallet::ReserveKeyFromKeyPool(int64_t &nIndex, CKeyPool &keypool,
- bool fRequestedInternal) {
+bool LegacyScriptPubKeyMan::ReserveKeyFromKeyPool(int64_t &nIndex,
+ CKeyPool &keypool,
+ bool fRequestedInternal) {
nIndex = -1;
keypool.vchPubKey = CPubKey();
{
@@ -992,8 +1012,8 @@
bool fReturningInternal = fRequestedInternal;
fReturningInternal &=
- (IsHDEnabled() && CanSupportFeature(FEATURE_HD_SPLIT)) ||
- IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS);
+ (IsHDEnabled() && m_storage.CanSupportFeature(FEATURE_HD_SPLIT)) ||
+ m_storage.IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS);
bool use_split_keypool = set_pre_split_keypool.empty();
std::set<int64_t> &setKeyPool =
use_split_keypool
@@ -1005,7 +1025,7 @@
return false;
}
- WalletBatch batch(*database);
+ WalletBatch batch(m_storage.GetDatabase());
auto it = setKeyPool.begin();
nIndex = *it;
@@ -1035,15 +1055,16 @@
return true;
}
-void CWallet::LearnRelatedScripts(const CPubKey &key, OutputType type) {
+void LegacyScriptPubKeyMan::LearnRelatedScripts(const CPubKey &key,
+ OutputType type) {
// Nothing to do...
}
-void CWallet::LearnAllRelatedScripts(const CPubKey &key) {
+void LegacyScriptPubKeyMan::LearnAllRelatedScripts(const CPubKey &key) {
// Nothing to do...
}
-void CWallet::MarkReserveKeysAsUsed(int64_t keypool_id) {
+void LegacyScriptPubKeyMan::MarkReserveKeysAsUsed(int64_t keypool_id) {
AssertLockHeld(cs_wallet);
bool internal = setInternalKeyPool.count(keypool_id);
if (!internal) {
@@ -1057,7 +1078,7 @@
: &set_pre_split_keypool);
auto it = setKeyPool->begin();
- WalletBatch batch(*database);
+ WalletBatch batch(m_storage.GetDatabase());
while (it != std::end(*setKeyPool)) {
const int64_t &index = *(it);
if (index > keypool_id) {
@@ -1090,8 +1111,8 @@
return ret;
}
-void CWallet::MarkPreSplitKeys() {
- WalletBatch batch(*database);
+void LegacyScriptPubKeyMan::MarkPreSplitKeys() {
+ WalletBatch batch(m_storage.GetDatabase());
for (auto it = setExternalKeyPool.begin();
it != setExternalKeyPool.end();) {
int64_t index = *it;
@@ -1110,25 +1131,26 @@
}
}
-bool CWallet::AddCScript(const CScript &redeemScript) {
- WalletBatch batch(*database);
+bool LegacyScriptPubKeyMan::AddCScript(const CScript &redeemScript) {
+ WalletBatch batch(m_storage.GetDatabase());
return AddCScriptWithDB(batch, redeemScript);
}
-bool CWallet::AddCScriptWithDB(WalletBatch &batch,
- const CScript &redeemScript) {
+bool LegacyScriptPubKeyMan::AddCScriptWithDB(WalletBatch &batch,
+ const CScript &redeemScript) {
if (!FillableSigningProvider::AddCScript(redeemScript)) {
return false;
}
if (batch.WriteCScript(Hash160(redeemScript), redeemScript)) {
- UnsetWalletFlagWithDB(batch, WALLET_FLAG_BLANK_WALLET);
+ m_storage.UnsetWalletFlagWithDB(batch, WALLET_FLAG_BLANK_WALLET);
return true;
}
return false;
}
-bool CWallet::AddKeyOriginWithDB(WalletBatch &batch, const CPubKey &pubkey,
- const KeyOriginInfo &info) {
+bool LegacyScriptPubKeyMan::AddKeyOriginWithDB(WalletBatch &batch,
+ const CPubKey &pubkey,
+ const KeyOriginInfo &info) {
LOCK(cs_wallet);
std::copy(info.fingerprint, info.fingerprint + 4,
mapKeyMetadata[pubkey.GetID()].key_origin.fingerprint);
@@ -1138,9 +1160,9 @@
return batch.WriteKeyMetadata(mapKeyMetadata[pubkey.GetID()], pubkey, true);
}
-bool CWallet::ImportScripts(const std::set<CScript> scripts,
- int64_t timestamp) {
- WalletBatch batch(*database);
+bool LegacyScriptPubKeyMan::ImportScripts(const std::set<CScript> scripts,
+ int64_t timestamp) {
+ WalletBatch batch(m_storage.GetDatabase());
for (const auto &entry : scripts) {
CScriptID id(entry);
if (HaveCScript(id)) {
@@ -1163,9 +1185,9 @@
return true;
}
-bool CWallet::ImportPrivKeys(const std::map<CKeyID, CKey> &privkey_map,
- const int64_t timestamp) {
- WalletBatch batch(*database);
+bool LegacyScriptPubKeyMan::ImportPrivKeys(
+ const std::map<CKeyID, CKey> &privkey_map, const int64_t timestamp) {
+ WalletBatch batch(m_storage.GetDatabase());
for (const auto &entry : privkey_map) {
const CKey &key = entry.second;
CPubKey pubkey = key.GetPubKey();
@@ -1187,12 +1209,12 @@
return true;
}
-bool CWallet::ImportPubKeys(
+bool LegacyScriptPubKeyMan::ImportPubKeys(
const std::vector<CKeyID> &ordered_pubkeys,
const std::map<CKeyID, CPubKey> &pubkey_map,
const std::map<CKeyID, std::pair<CPubKey, KeyOriginInfo>> &key_origins,
const bool add_keypool, const bool internal, const int64_t timestamp) {
- WalletBatch batch(*database);
+ WalletBatch batch(m_storage.GetDatabase());
for (const auto &entry : key_origins) {
AddKeyOriginWithDB(batch, entry.second.first, entry.second.second);
}
@@ -1223,14 +1245,13 @@
return true;
}
-bool CWallet::ImportScriptPubKeys(const std::string &label,
- const std::set<CScript> &script_pub_keys,
- const bool have_solving_data,
- const bool apply_label,
- const int64_t timestamp) {
- WalletBatch batch(*database);
+bool LegacyScriptPubKeyMan::ImportScriptPubKeys(
+ const std::string &label, const std::set<CScript> &script_pub_keys,
+ const bool have_solving_data, const bool apply_label,
+ const int64_t timestamp) {
+ WalletBatch batch(m_storage.GetDatabase());
for (const CScript &script : script_pub_keys) {
- if (!have_solving_data || !::IsMine(*this, script)) {
+ if (!have_solving_data || !IsMine(script)) {
// Always call AddWatchOnly for non-solvable watch-only, so that
// watch timestamp gets updated
if (!AddWatchOnlyWithDB(batch, script, timestamp)) {
@@ -1240,13 +1261,13 @@
CTxDestination dest;
ExtractDestination(script, dest);
if (apply_label && IsValidDestination(dest)) {
- SetAddressBookWithDB(batch, dest, label, "receive");
+ m_wallet.SetAddressBookWithDB(batch, dest, label, "receive");
}
}
return true;
}
-std::set<CKeyID> CWallet::GetKeys() const {
+std::set<CKeyID> LegacyScriptPubKeyMan::GetKeys() const {
LOCK(cs_KeyStore);
if (!IsCrypted()) {
return FillableSigningProvider::GetKeys();
@@ -1257,3 +1278,27 @@
}
return set_address;
}
+
+// Temporary CWallet accessors and aliases.
+LegacyScriptPubKeyMan::LegacyScriptPubKeyMan(CWallet &wallet)
+ : ScriptPubKeyMan(wallet), m_wallet(wallet), cs_wallet(wallet.cs_wallet),
+ vMasterKey(wallet.vMasterKey), fUseCrypto(wallet.fUseCrypto),
+ fDecryptionThoroughlyChecked(wallet.fDecryptionThoroughlyChecked) {}
+
+bool LegacyScriptPubKeyMan::SetCrypted() {
+ return m_wallet.SetCrypted();
+}
+bool LegacyScriptPubKeyMan::IsCrypted() const {
+ return m_wallet.IsCrypted();
+}
+void LegacyScriptPubKeyMan::NotifyWatchonlyChanged(bool fHaveWatchOnly) const {
+ return m_wallet.NotifyWatchonlyChanged(fHaveWatchOnly);
+}
+void LegacyScriptPubKeyMan::NotifyCanGetAddressesChanged() const {
+ return m_wallet.NotifyCanGetAddressesChanged();
+}
+template <typename... Params>
+void LegacyScriptPubKeyMan::WalletLogPrintf(
+ const std::string &fmt, const Params &... parameters) const {
+ return m_wallet.WalletLogPrintf(fmt, parameters...);
+}
diff --git a/src/wallet/test/ismine_tests.cpp b/src/wallet/test/ismine_tests.cpp
--- a/src/wallet/test/ismine_tests.cpp
+++ b/src/wallet/test/ismine_tests.cpp
@@ -43,12 +43,12 @@
scriptPubKey = GetScriptForRawPubKey(pubkeys[0]);
// Keystore does not have key
- result = IsMine(keystore, scriptPubKey);
+ result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
// Keystore has key
- keystore.AddKey(keys[0]);
- result = IsMine(keystore, scriptPubKey);
+ BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
+ result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
}
@@ -60,12 +60,13 @@
scriptPubKey = GetScriptForRawPubKey(uncompressedPubkey);
// Keystore does not have key
- result = IsMine(keystore, scriptPubKey);
+ result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
// Keystore has key
- keystore.AddKey(uncompressedKey);
- result = IsMine(keystore, scriptPubKey);
+ BOOST_CHECK(
+ keystore.GetLegacyScriptPubKeyMan()->AddKey(uncompressedKey));
+ result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
}
@@ -77,12 +78,12 @@
scriptPubKey = GetScriptForDestination(PKHash(pubkeys[0]));
// Keystore does not have key
- result = IsMine(keystore, scriptPubKey);
+ result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
// Keystore has key
- keystore.AddKey(keys[0]);
- result = IsMine(keystore, scriptPubKey);
+ BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
+ result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
}
@@ -94,12 +95,13 @@
scriptPubKey = GetScriptForDestination(PKHash(uncompressedPubkey));
// Keystore does not have key
- result = IsMine(keystore, scriptPubKey);
+ result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
// Keystore has key
- keystore.AddKey(uncompressedKey);
- result = IsMine(keystore, scriptPubKey);
+ BOOST_CHECK(
+ keystore.GetLegacyScriptPubKeyMan()->AddKey(uncompressedKey));
+ result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
}
@@ -113,17 +115,18 @@
scriptPubKey = GetScriptForDestination(ScriptHash(redeemScript));
// Keystore does not have redeemScript or key
- result = IsMine(keystore, scriptPubKey);
+ result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
// Keystore has redeemScript but no key
- keystore.AddCScript(redeemScript);
- result = IsMine(keystore, scriptPubKey);
+ BOOST_CHECK(
+ keystore.GetLegacyScriptPubKeyMan()->AddCScript(redeemScript));
+ result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
// Keystore has redeemScript and key
- keystore.AddKey(keys[0]);
- result = IsMine(keystore, scriptPubKey);
+ BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
+ result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
}
@@ -139,12 +142,14 @@
GetScriptForDestination(ScriptHash(redeemscript_inner));
scriptPubKey = GetScriptForDestination(ScriptHash(redeemscript));
- BOOST_CHECK(keystore.AddCScript(redeemscript));
- BOOST_CHECK(keystore.AddCScript(redeemscript_inner));
- BOOST_CHECK(keystore.AddCScript(scriptPubKey));
- BOOST_CHECK(keystore.AddKey(keys[0]));
-
- result = IsMine(keystore, scriptPubKey);
+ BOOST_CHECK(
+ keystore.GetLegacyScriptPubKeyMan()->AddCScript(redeemscript));
+ BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(
+ redeemscript_inner));
+ BOOST_CHECK(
+ keystore.GetLegacyScriptPubKeyMan()->AddCScript(scriptPubKey));
+ BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
+ result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
}
@@ -158,25 +163,27 @@
GetScriptForMultisig(2, {uncompressedPubkey, pubkeys[1]});
// Keystore does not have any keys
- result = IsMine(keystore, scriptPubKey);
+ result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
// Keystore has 1/2 keys
- keystore.AddKey(uncompressedKey);
+ BOOST_CHECK(
+ keystore.GetLegacyScriptPubKeyMan()->AddKey(uncompressedKey));
- result = IsMine(keystore, scriptPubKey);
+ result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
// Keystore has 2/2 keys
- keystore.AddKey(keys[1]);
+ BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[1]));
- result = IsMine(keystore, scriptPubKey);
+ result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
// Keystore has 2/2 keys and the script
- keystore.AddCScript(scriptPubKey);
+ BOOST_CHECK(
+ keystore.GetLegacyScriptPubKeyMan()->AddCScript(scriptPubKey));
- result = IsMine(keystore, scriptPubKey);
+ result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
}
@@ -185,20 +192,22 @@
CWallet keystore(Params(), chain.get(), WalletLocation(),
WalletDatabase::CreateDummy());
LOCK(keystore.cs_wallet);
- BOOST_CHECK(keystore.AddKey(uncompressedKey));
- BOOST_CHECK(keystore.AddKey(keys[1]));
+ BOOST_CHECK(
+ keystore.GetLegacyScriptPubKeyMan()->AddKey(uncompressedKey));
+ BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[1]));
CScript redeemScript =
GetScriptForMultisig(2, {uncompressedPubkey, pubkeys[1]});
scriptPubKey = GetScriptForDestination(ScriptHash(redeemScript));
// Keystore has no redeemScript
- result = IsMine(keystore, scriptPubKey);
+ result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
// Keystore has redeemScript
- BOOST_CHECK(keystore.AddCScript(redeemScript));
- result = IsMine(keystore, scriptPubKey);
+ BOOST_CHECK(
+ keystore.GetLegacyScriptPubKeyMan()->AddCScript(redeemScript));
+ result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
}
@@ -207,12 +216,12 @@
CWallet keystore(Params(), chain.get(), WalletLocation(),
WalletDatabase::CreateDummy());
LOCK(keystore.cs_wallet);
- BOOST_CHECK(keystore.AddKey(keys[0]));
+ BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
scriptPubKey.clear();
scriptPubKey << OP_RETURN << ToByteVector(pubkeys[0]);
- result = IsMine(keystore, scriptPubKey);
+ result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
}
@@ -221,12 +230,12 @@
CWallet keystore(Params(), chain.get(), WalletLocation(),
WalletDatabase::CreateDummy());
LOCK(keystore.cs_wallet);
- BOOST_CHECK(keystore.AddKey(keys[0]));
+ BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
scriptPubKey.clear();
scriptPubKey << OP_9 << OP_ADD << OP_11 << OP_EQUAL;
- result = IsMine(keystore, scriptPubKey);
+ result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
}
}
diff --git a/src/wallet/test/psbt_wallet_tests.cpp b/src/wallet/test/psbt_wallet_tests.cpp
--- a/src/wallet/test/psbt_wallet_tests.cpp
+++ b/src/wallet/test/psbt_wallet_tests.cpp
@@ -17,6 +17,7 @@
BOOST_FIXTURE_TEST_SUITE(psbt_wallet_tests, WalletTestingSetup)
BOOST_AUTO_TEST_CASE(psbt_updater_test) {
+ auto spk_man = m_wallet.GetLegacyScriptPubKeyMan();
LOCK(m_wallet.cs_wallet);
// Create prevtxs and add to wallet
@@ -55,7 +56,7 @@
"dae4dba2fbfef536d752ae"),
SER_NETWORK, PROTOCOL_VERSION);
s_rs1 >> rs1;
- m_wallet.AddCScript(rs1);
+ spk_man->AddCScript(rs1);
CScript rs2;
CDataStream s_rs2(
@@ -64,16 +65,16 @@
"6151926860221f0e7352ae"),
SER_NETWORK, PROTOCOL_VERSION);
s_rs2 >> rs2;
- m_wallet.AddCScript(rs2);
+ spk_man->AddCScript(rs2);
// Add hd seed
// Mainnet and uncompressed form of
// cUkG8i1RFfWGWy5ziR11zJ5V4U4W3viSFCfyJmZnvQaUsd1xuF3T
CKey key =
DecodeSecret("5KSSJQ7UNfFGwVgpCZDSHm5rVNhMFcFtvWM3zQ8mW4qNDEN7LFd");
- CPubKey master_pub_key = m_wallet.DeriveNewSeed(key);
- m_wallet.SetHDSeed(master_pub_key);
- m_wallet.NewKeyPool();
+ CPubKey master_pub_key = spk_man->DeriveNewSeed(key);
+ spk_man->SetHDSeed(master_pub_key);
+ spk_man->NewKeyPool();
// Call FillPSBT
PartiallySignedTransaction psbtx;
diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp
--- a/src/wallet/test/wallet_tests.cpp
+++ b/src/wallet/test/wallet_tests.cpp
@@ -28,8 +28,10 @@
BOOST_FIXTURE_TEST_SUITE(wallet_tests, WalletTestingSetup)
static void AddKey(CWallet &wallet, const CKey &key) {
+ auto spk_man = wallet.GetLegacyScriptPubKeyMan();
LOCK(wallet.cs_wallet);
- wallet.AddKeyPubKey(key, key.GetPubKey());
+ AssertLockHeld(spk_man->cs_wallet);
+ spk_man->AddKeyPubKey(key, key.GetPubKey());
}
BOOST_FIXTURE_TEST_CASE(scan_for_wallet_transactions, TestChain100Setup) {
@@ -224,10 +226,12 @@
std::shared_ptr<CWallet> wallet =
std::make_shared<CWallet>(Params(), chain.get(), WalletLocation(),
WalletDatabase::CreateDummy());
+ auto spk_man = wallet->GetLegacyScriptPubKeyMan();
LOCK(wallet->cs_wallet);
- wallet->mapKeyMetadata[coinbaseKey.GetPubKey().GetID()].nCreateTime =
+ AssertLockHeld(spk_man->cs_wallet);
+ spk_man->mapKeyMetadata[coinbaseKey.GetPubKey().GetID()].nCreateTime =
KEY_TIME;
- wallet->AddKeyPubKey(coinbaseKey, coinbaseKey.GetPubKey());
+ spk_man->AddKeyPubKey(coinbaseKey, coinbaseKey.GetPubKey());
JSONRPCRequest request;
request.params.setArray();
@@ -273,11 +277,13 @@
auto chain = interfaces::MakeChain(node, Params());
CWallet wallet(Params(), chain.get(), WalletLocation(),
WalletDatabase::CreateDummy());
+ auto spk_man = wallet.GetLegacyScriptPubKeyMan();
CWalletTx wtx(&wallet, m_coinbase_txns.back());
auto locked_chain = chain->lock();
LockAssertion lock(::cs_main);
LOCK(wallet.cs_wallet);
+ AssertLockHeld(spk_man->cs_wallet);
wtx.SetConf(CWalletTx::Status::CONFIRMED,
::ChainActive().Tip()->GetBlockHash(), 0);
@@ -289,7 +295,7 @@
// Invalidate the cached value, add the key, and make sure a new immature
// credit amount is calculated.
wtx.MarkDirty();
- wallet.AddKeyPubKey(coinbaseKey, coinbaseKey.GetPubKey());
+ BOOST_CHECK(spk_man->AddKeyPubKey(coinbaseKey, coinbaseKey.GetPubKey()));
BOOST_CHECK_EQUAL(wtx.GetImmatureCredit(*locked_chain), 50 * COIN);
}
@@ -368,40 +374,42 @@
BOOST_CHECK_EQUAL(values[1], "val_rr1");
}
-// Test some watch-only wallet methods by the procedure of loading
-// (LoadWatchOnly), checking (HaveWatchOnly), getting (GetWatchPubKey) and
-// removing (RemoveWatchOnly) a given PubKey, resp. its corresponding P2PK
+// Test some watch-only LegacyScriptPubKeyMan methods by the procedure of
+// loading (LoadWatchOnly), checking (HaveWatchOnly), getting (GetWatchPubKey)
+// and removing (RemoveWatchOnly) a given PubKey, resp. its corresponding P2PK
// Script. Results of the the impact on the address -> PubKey map is dependent
// on whether the PubKey is a point on the curve
-static void TestWatchOnlyPubKey(CWallet &wallet, const CPubKey &add_pubkey) {
+static void TestWatchOnlyPubKey(LegacyScriptPubKeyMan *spk_man,
+ const CPubKey &add_pubkey) {
CScript p2pk = GetScriptForRawPubKey(add_pubkey);
CKeyID add_address = add_pubkey.GetID();
CPubKey found_pubkey;
- LOCK(wallet.cs_wallet);
+ LOCK(spk_man->cs_wallet);
// all Scripts (i.e. also all PubKeys) are added to the general watch-only
// set
- BOOST_CHECK(!wallet.HaveWatchOnly(p2pk));
- wallet.LoadWatchOnly(p2pk);
- BOOST_CHECK(wallet.HaveWatchOnly(p2pk));
+ BOOST_CHECK(!spk_man->HaveWatchOnly(p2pk));
+ spk_man->LoadWatchOnly(p2pk);
+ BOOST_CHECK(spk_man->HaveWatchOnly(p2pk));
// only PubKeys on the curve shall be added to the watch-only address ->
// PubKey map
bool is_pubkey_fully_valid = add_pubkey.IsFullyValid();
if (is_pubkey_fully_valid) {
- BOOST_CHECK(wallet.GetWatchPubKey(add_address, found_pubkey));
+ BOOST_CHECK(spk_man->GetWatchPubKey(add_address, found_pubkey));
BOOST_CHECK(found_pubkey == add_pubkey);
} else {
- BOOST_CHECK(!wallet.GetWatchPubKey(add_address, found_pubkey));
+ BOOST_CHECK(!spk_man->GetWatchPubKey(add_address, found_pubkey));
// passed key is unchanged
BOOST_CHECK(found_pubkey == CPubKey());
}
- wallet.RemoveWatchOnly(p2pk);
- BOOST_CHECK(!wallet.HaveWatchOnly(p2pk));
+ AssertLockHeld(spk_man->cs_wallet);
+ spk_man->RemoveWatchOnly(p2pk);
+ BOOST_CHECK(!spk_man->HaveWatchOnly(p2pk));
if (is_pubkey_fully_valid) {
- BOOST_CHECK(!wallet.GetWatchPubKey(add_address, found_pubkey));
+ BOOST_CHECK(!spk_man->GetWatchPubKey(add_address, found_pubkey));
// passed key is unchanged
BOOST_CHECK(found_pubkey == add_pubkey);
}
@@ -416,36 +424,37 @@
assert(pubkey.IsValid());
}
-// Test watch-only wallet logic for PubKeys
+// Test watch-only logic for PubKeys
BOOST_AUTO_TEST_CASE(WatchOnlyPubKeys) {
CKey key;
CPubKey pubkey;
+ LegacyScriptPubKeyMan *spk_man = m_wallet.GetLegacyScriptPubKeyMan();
- BOOST_CHECK(!m_wallet.HaveWatchOnly());
+ BOOST_CHECK(!spk_man->HaveWatchOnly());
// uncompressed valid PubKey
key.MakeNewKey(false);
pubkey = key.GetPubKey();
assert(!pubkey.IsCompressed());
- TestWatchOnlyPubKey(m_wallet, pubkey);
+ TestWatchOnlyPubKey(spk_man, pubkey);
// uncompressed cryptographically invalid PubKey
PollutePubKey(pubkey);
- TestWatchOnlyPubKey(m_wallet, pubkey);
+ TestWatchOnlyPubKey(spk_man, pubkey);
// compressed valid PubKey
key.MakeNewKey(true);
pubkey = key.GetPubKey();
assert(pubkey.IsCompressed());
- TestWatchOnlyPubKey(m_wallet, pubkey);
+ TestWatchOnlyPubKey(spk_man, pubkey);
// compressed cryptographically invalid PubKey
PollutePubKey(pubkey);
- TestWatchOnlyPubKey(m_wallet, pubkey);
+ TestWatchOnlyPubKey(spk_man, pubkey);
// invalid empty PubKey
pubkey = CPubKey();
- TestWatchOnlyPubKey(m_wallet, pubkey);
+ TestWatchOnlyPubKey(spk_man, pubkey);
}
class ListCoinsTestingSetup : public TestChain100Setup {
diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h
--- a/src/wallet/wallet.h
+++ b/src/wallet/wallet.h
@@ -19,8 +19,8 @@
#include <validationinterface.h>
#include <wallet/coinselection.h>
#include <wallet/crypter.h>
-#include <wallet/ismine.h>
#include <wallet/rpcwallet.h>
+#include <wallet/scriptpubkeyman.h>
#include <wallet/walletdb.h>
#include <wallet/walletutil.h>
@@ -138,6 +138,7 @@
protected:
//! The wallet to reserve from
CWallet *pwallet;
+ LegacyScriptPubKeyMan *m_spk_man{nullptr};
//! The index of the address's key in the keypool
int64_t nIndex{-1};
//! The public key for the address
@@ -622,11 +623,10 @@
class WalletRescanReserver;
/**
- * A CWallet is an extension of a keystore, which also maintains a set of
- * transactions and balances, and provides the ability to create new
- * transactions.
+ * A CWallet maintains a set of transactions and balances, and provides the
+ * ability to create new transactions.
*/
-class CWallet final : public FillableSigningProvider,
+class CWallet final : public WalletStorage,
public interfaces::Chain::Notifications {
private:
CKeyingMaterial vMasterKey GUARDED_BY(cs_KeyStore);
@@ -638,25 +638,9 @@
//! keeps track of whether Unlock has run a thorough check before
bool fDecryptionThoroughlyChecked;
- using CryptedKeyMap =
- std::map<CKeyID, std::pair<CPubKey, std::vector<uint8_t>>>;
- using WatchOnlySet = std::set<CScript>;
- using WatchKeyMap = std::map<CKeyID, CPubKey>;
-
bool SetCrypted();
-
- //! will encrypt previously unencrypted keys
- bool EncryptKeys(CKeyingMaterial &vMasterKeyIn);
-
bool Unlock(const CKeyingMaterial &vMasterKeyIn,
bool accept_no_keys = false);
- CryptedKeyMap mapCryptedKeys GUARDED_BY(cs_KeyStore);
- WatchOnlySet setWatchOnly GUARDED_BY(cs_KeyStore);
- WatchKeyMap mapWatchKeys GUARDED_BY(cs_KeyStore);
-
- bool AddCryptedKeyInner(const CPubKey &vchPubKey,
- const std::vector<uint8_t> &vchCryptedSecret);
- bool AddKeyPubKeyInner(const CKey &key, const CPubKey &pubkey);
std::atomic<bool> fAbortRescan{false};
// controlled by WalletRescanReserver
@@ -666,8 +650,6 @@
std::mutex mutexScanning;
friend class WalletRescanReserver;
- WalletBatch *encrypted_batch GUARDED_BY(cs_wallet) = nullptr;
-
//! the current wallet version: clients below this version are not able to
//! load the wallet
int nWalletVersion GUARDED_BY(cs_wallet) = FEATURE_BASE;
@@ -741,63 +723,14 @@
bool update_tx = true)
EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
- /* the HD chain data model (external chain counters) */
- CHDChain hdChain;
-
- /* HD derive new child key (on internal or external chain) */
- void DeriveNewChildKey(WalletBatch &batch, CKeyMetadata &metadata,
- CKey &secret, bool internal = false)
- EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
-
- std::set<int64_t> setInternalKeyPool GUARDED_BY(cs_wallet);
- std::set<int64_t> setExternalKeyPool GUARDED_BY(cs_wallet);
- std::set<int64_t> set_pre_split_keypool GUARDED_BY(cs_wallet);
- int64_t m_max_keypool_index GUARDED_BY(cs_wallet) = 0;
- std::map<CKeyID, int64_t> m_pool_key_to_index;
std::atomic<uint64_t> m_wallet_flags{0};
- int64_t nTimeFirstKey GUARDED_BY(cs_wallet) = 0;
-
- /**
- * Private version of AddWatchOnly method which does not accept a timestamp,
- * and which will reset the wallet's nTimeFirstKey value to 1 if the watch
- * key did not previously have a timestamp associated with it. Because this
- * is an inherited virtual method, it is accessible despite being marked
- * private, but it is marked private anyway to encourage use of the other
- * AddWatchOnly which accepts a timestamp and sets nTimeFirstKey more
- * intelligently for more efficient rescans.
- */
- bool AddWatchOnly(const CScript &dest) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
- bool AddWatchOnlyWithDB(WalletBatch &batch, const CScript &dest)
- EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
- bool AddWatchOnlyInMem(const CScript &dest);
-
- /** Add a KeyOriginInfo to the wallet */
- bool AddKeyOriginWithDB(WalletBatch &batch, const CPubKey &pubkey,
- const KeyOriginInfo &info);
-
- //! Adds a key to the store, and saves it to disk.
- bool AddKeyPubKeyWithDB(WalletBatch &batch, const CKey &key,
- const CPubKey &pubkey)
- EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
-
- //! Adds a watch-only address to the store, and saves it to disk.
- bool AddWatchOnlyWithDB(WalletBatch &batch, const CScript &dest,
- int64_t create_time)
- EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
-
- void AddKeypoolPubkeyWithDB(const CPubKey &pubkey, const bool internal,
- WalletBatch &batch);
-
bool SetAddressBookWithDB(WalletBatch &batch, const CTxDestination &address,
const std::string &strName,
const std::string &strPurpose);
- //! Adds a script to the store and saves it to disk
- bool AddCScriptWithDB(WalletBatch &batch, const CScript &script);
-
//! Unsets a wallet flag and saves it to disk
- void UnsetWalletFlagWithDB(WalletBatch &batch, uint64_t flag);
+ void UnsetWalletFlagWithDB(WalletBatch &batch, uint64_t flag) override;
/** Interface for accessing chain state. */
interfaces::Chain *m_chain;
@@ -820,9 +753,6 @@
*/
BlockHash m_last_block_processed GUARDED_BY(cs_wallet);
- //! Fetches a key from the keypool
- bool GetKeyFromPool(CPubKey &key, bool internal = false);
-
public:
const CChainParams &chainParams;
/*
@@ -836,6 +766,7 @@
* be necessary.
*/
WalletDatabase &GetDBHandle() { return *database; }
+ WalletDatabase &GetDatabase() override { return *database; }
/**
* Select a set of coins such that nValueRet >= nTargetValue and at least
@@ -856,16 +787,6 @@
*/
const std::string &GetName() const { return m_location.GetName(); }
- void LoadKeyPool(int64_t nIndex, const CKeyPool &keypool)
- EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
- void MarkPreSplitKeys() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
-
- // Map from Key ID to key metadata.
- std::map<CKeyID, CKeyMetadata> mapKeyMetadata GUARDED_BY(cs_wallet);
-
- // Map from Script ID to key metadata (for watch-only keys).
- std::map<CScriptID, CKeyMetadata> m_script_metadata GUARDED_BY(cs_wallet);
-
typedef std::map<unsigned int, CMasterKey> MasterKeyMap;
MasterKeyMap mapMasterKeys;
unsigned int nMasterKeyMaxID = 0;
@@ -886,7 +807,7 @@
}
bool IsCrypted() const { return fUseCrypto; }
- bool IsLocked() const;
+ bool IsLocked() const override;
bool Lock();
/** Interface to assert chain access and if successful lock it */
@@ -920,7 +841,7 @@
//! check whether we are allowed to upgrade (or already support) to the
//! named feature
- bool CanSupportFeature(enum WalletFeature wf) const
+ bool CanSupportFeature(enum WalletFeature wf) const override
EXCLUSIVE_LOCKS_REQUIRED(cs_wallet) {
AssertLockHeld(cs_wallet);
return nWalletMaxVersion >= wf;
@@ -1001,25 +922,6 @@
return fScanningWallet ? double(m_scanning_progress) : 0;
}
- /**
- * keystore implementation
- * Generate a new key
- */
- CPubKey GenerateNewKey(WalletBatch &batch, bool internal = false)
- EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
- //! Adds a key to the store, and saves it to disk.
- bool AddKeyPubKey(const CKey &key, const CPubKey &pubkey) override
- EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
- //! Adds a key to the store, without saving it to disk (used by LoadWallet)
- bool LoadKey(const CKey &key, const CPubKey &pubkey) {
- return AddKeyPubKeyInner(key, pubkey);
- }
- //! Load metadata (used by LoadWallet)
- void LoadKeyMetadata(const CKeyID &keyID, const CKeyMetadata &metadata)
- EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
- void LoadScriptMetadata(const CScriptID &script_id,
- const CKeyMetadata &metadata)
- EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
//! Upgrade stored CKeyMetadata objects to store key origin info as
//! KeyOriginInfo
void UpgradeKeyMetadata() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
@@ -1030,22 +932,6 @@
nWalletMaxVersion = std::max(nWalletMaxVersion, nVersion);
return true;
}
- void UpdateTimeFirstKey(int64_t nCreateTime)
- EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
-
- //! Adds an encrypted key to the store, and saves it to disk.
- bool AddCryptedKey(const CPubKey &vchPubKey,
- const std::vector<uint8_t> &vchCryptedSecret);
- //! Adds an encrypted key to the store, without saving it to disk (used by
- //! LoadWallet)
- bool LoadCryptedKey(const CPubKey &vchPubKey,
- const std::vector<uint8_t> &vchCryptedSecret);
- bool GetKey(const CKeyID &address, CKey &keyOut) const override;
- bool GetPubKey(const CKeyID &address, CPubKey &vchPubKeyOut) const override;
- bool HaveKey(const CKeyID &address) const override;
- std::set<CKeyID> GetKeys() const override;
- bool AddCScript(const CScript &redeemScript) override;
- bool LoadCScript(const CScript &redeemScript);
//! Adds a destination data tuple to the store, and saves it to disk
bool AddDestData(const CTxDestination &dest, const std::string &key,
@@ -1067,21 +953,6 @@
std::vector<std::string> GetDestValues(const std::string &prefix) const
EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
- //! Adds a watch-only address to the store, and saves it to disk.
- bool AddWatchOnly(const CScript &dest, int64_t nCreateTime)
- EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
- bool RemoveWatchOnly(const CScript &dest)
- EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
- //! Adds a watch-only address to the store, without saving it to disk (used
- //! by LoadWallet)
- bool LoadWatchOnly(const CScript &dest);
- //! Returns whether the watch-only script is in the wallet
- bool HaveWatchOnly(const CScript &dest) const;
- //! Returns whether there are any watch-only things in the wallet
- bool HaveWatchOnly() const;
- //! Fetches a pubkey from mapWatchKeys if it exists there
- bool GetWatchPubKey(const CKeyID &address, CPubKey &pubkey_out) const;
-
//! Holds a timestamp at which point the wallet is scheduled (externally) to
//! be relocked. Caller must arrange for actual relocking to occur via
//! Lock().
@@ -1244,37 +1115,10 @@
*/
Amount m_default_max_tx_fee{DEFAULT_TRANSACTION_MAXFEE};
- bool NewKeyPool();
size_t KeypoolCountExternalKeys() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
bool TopUpKeyPool(unsigned int kpSize = 0);
- /**
- * Reserves a key from the keypool and sets nIndex to its index
- *
- * @param[out] nIndex the index of the key in keypool
- * @param[out] keypool the keypool the key was drawn from, which could be
- * the the pre-split pool if present, or the internal or external pool
- * @param fRequestedInternal true if the caller would like the key drawn
- * from the internal keypool, false if external is preferred
- *
- * @return true if succeeded, false if failed due to empty keypool
- * @throws std::runtime_error if keypool read failed, key was invalid,
- * was not found in the wallet, or was misclassified in the internal
- * or external keypool
- */
- bool ReserveKeyFromKeyPool(int64_t &nIndex, CKeyPool &keypool,
- bool fRequestedInternal);
- void KeepKey(int64_t nIndex);
- void ReturnKey(int64_t nIndex, bool fInternal, const CPubKey &pubkey);
int64_t GetOldestKeyPoolTime();
- /**
- * Marks all keys in the keypool up to and including reserve_key as used.
- */
- void MarkReserveKeysAsUsed(int64_t keypool_id)
- EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
- const std::map<CKeyID, int64_t> &GetAllReserveKeys() const {
- return m_pool_key_to_index;
- }
std::set<std::set<CTxDestination>> GetAddressGroupings()
EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
@@ -1288,6 +1132,8 @@
bool GetNewChangeDestination(const OutputType type, CTxDestination &dest,
std::string &error);
+ isminetype IsMine(const CTxDestination &dest) const;
+ isminetype IsMine(const CScript &script) const;
isminetype IsMine(const CTxIn &txin) const;
/**
* Returns amount of debit if the input matches the filter, otherwise
@@ -1328,7 +1174,7 @@
//! signify that a particular wallet feature is now used. this may change
//! nWalletVersion and nWalletMaxVersion if those are lower
void SetMinVersion(enum WalletFeature, WalletBatch *batch_in = nullptr,
- bool fExplicit = false);
+ bool fExplicit = false) override;
//! change which version we're allowed to upgrade to (note that this does
//! not immediately imply upgrading to that format)
@@ -1431,38 +1277,15 @@
bool BackupWallet(const std::string &strDest);
- /* Set the HD chain model (chain child index counters) */
- void SetHDChain(const CHDChain &chain, bool memonly);
- const CHDChain &GetHDChain() const { return hdChain; }
-
/* Returns true if HD is enabled */
bool IsHDEnabled() const;
- /* Returns true if the wallet can generate new keys */
- bool CanGenerateKeys();
-
/**
* Returns true if the wallet can give out new addresses. This means it has
* keys in the keypool or can generate new keys.
*/
bool CanGetAddresses(bool internal = false);
- /* Generates a new HD seed (will not be activated) */
- CPubKey GenerateNewSeed();
-
- /**
- * Derives a new HD seed (will not be activated)
- */
- CPubKey DeriveNewSeed(const CKey &key);
-
- /**
- * Set the current HD seed (will reset the chain child index counters)
- * Sets the seed's version based on the current wallet version (so the
- * caller must ensure the current wallet version is correct before calling
- * this function).
- */
- void SetHDSeed(const CPubKey &key);
-
/**
* Blocks until the wallet state is up-to-date to /at least/ the current
* chain at the time this function is entered.
@@ -1471,24 +1294,10 @@
*/
void BlockUntilSyncedToCurrentChain() LOCKS_EXCLUDED(cs_main, cs_wallet);
- /**
- * Explicitly make the wallet learn the related scripts for outputs to the
- * given key. This is purely to make the wallet file compatible with older
- * software, as FillableSigningProvider automatically does this implicitly
- * for all keys now.
- */
- void LearnRelatedScripts(const CPubKey &key, OutputType);
-
- /**
- * Same as LearnRelatedScripts, but when the OutputType is not known (and
- * could be anything).
- */
- void LearnAllRelatedScripts(const CPubKey &key);
-
/**
* Set a single wallet flag.
*/
- void SetWalletFlag(uint64_t flags);
+ void SetWalletFlag(uint64_t flags) override;
/**
* Unsets a single wallet flag.
@@ -1498,7 +1307,7 @@
/**
* Check if a certain wallet flag is set.
*/
- bool IsWalletFlagSet(uint64_t flag) const;
+ bool IsWalletFlagSet(uint64_t flag) const override;
/**
* Overwrite all flags by the given uint64_t.
@@ -1510,7 +1319,7 @@
* Returns a bracketed wallet name for displaying in logs, will return
* [default wallet] if the wallet has no name.
*/
- const std::string GetDisplayName() const {
+ const std::string GetDisplayName() const override {
std::string wallet_name =
GetName().length() == 0 ? "default wallet" : GetName();
return strprintf("[%s]", wallet_name);
@@ -1532,10 +1341,46 @@
parameters...);
};
- /**
- * Implement lookup of key origin information through wallet key metadata.
- */
- bool GetKeyOrigin(const CKeyID &keyid, KeyOriginInfo &info) const override;
+ ScriptPubKeyMan *GetScriptPubKeyMan() const;
+ const SigningProvider *GetSigningProvider() const;
+ LegacyScriptPubKeyMan *GetLegacyScriptPubKeyMan() const;
+
+ // Temporary LegacyScriptPubKeyMan accessors and aliases.
+ friend class LegacyScriptPubKeyMan;
+ std::unique_ptr<LegacyScriptPubKeyMan> m_spk_man =
+ std::make_unique<LegacyScriptPubKeyMan>(*this);
+ RecursiveMutex &cs_KeyStore = m_spk_man->cs_KeyStore;
+ LegacyScriptPubKeyMan::KeyMap &
+ mapKeys GUARDED_BY(cs_KeyStore) = m_spk_man->mapKeys;
+ LegacyScriptPubKeyMan::ScriptMap &
+ mapScripts GUARDED_BY(cs_KeyStore) = m_spk_man->mapScripts;
+ LegacyScriptPubKeyMan::CryptedKeyMap &
+ mapCryptedKeys GUARDED_BY(cs_KeyStore) = m_spk_man->mapCryptedKeys;
+ LegacyScriptPubKeyMan::WatchOnlySet &
+ setWatchOnly GUARDED_BY(cs_KeyStore) = m_spk_man->setWatchOnly;
+ LegacyScriptPubKeyMan::WatchKeyMap &
+ mapWatchKeys GUARDED_BY(cs_KeyStore) = m_spk_man->mapWatchKeys;
+ WalletBatch *&
+ encrypted_batch GUARDED_BY(cs_wallet) = m_spk_man->encrypted_batch;
+ std::set<int64_t> &setInternalKeyPool GUARDED_BY(cs_wallet) =
+ m_spk_man->setInternalKeyPool;
+ std::set<int64_t> &setExternalKeyPool GUARDED_BY(cs_wallet) =
+ m_spk_man->setExternalKeyPool;
+ int64_t &nTimeFirstKey GUARDED_BY(cs_wallet) = m_spk_man->nTimeFirstKey;
+ std::map<CKeyID, CKeyMetadata> &
+ mapKeyMetadata GUARDED_BY(cs_wallet) = m_spk_man->mapKeyMetadata;
+ std::map<CScriptID, CKeyMetadata> &
+ m_script_metadata GUARDED_BY(cs_wallet) = m_spk_man->m_script_metadata;
+ void MarkPreSplitKeys() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet) {
+ AssertLockHeld(m_spk_man->cs_wallet);
+ m_spk_man->MarkPreSplitKeys();
+ }
+ void MarkReserveKeysAsUsed(int64_t keypool_id)
+ EXCLUSIVE_LOCKS_REQUIRED(cs_wallet) {
+ AssertLockHeld(m_spk_man->cs_wallet);
+ m_spk_man->MarkReserveKeysAsUsed(keypool_id);
+ }
+ using CryptedKeyMap = LegacyScriptPubKeyMan::CryptedKeyMap;
};
/**
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -31,7 +31,6 @@
#include <util/validation.h>
#include <wallet/coincontrol.h>
#include <wallet/fees.h>
-#include <wallet/scriptpubkeyman.h>
#include <boost/algorithm/string/replace.hpp>
@@ -231,9 +230,9 @@
}
// Set a seed for the wallet
- CPubKey master_pub_key = wallet->GenerateNewSeed();
- wallet->SetHDSeed(master_pub_key);
- wallet->NewKeyPool();
+ CPubKey master_pub_key = wallet->m_spk_man->GenerateNewSeed();
+ wallet->m_spk_man->SetHDSeed(master_pub_key);
+ wallet->m_spk_man->NewKeyPool();
// Relock the wallet
wallet->Lock();
@@ -271,6 +270,13 @@
return &(it->second);
}
+void CWallet::UpgradeKeyMetadata() {
+ AssertLockHeld(m_spk_man->cs_wallet);
+ if (m_spk_man) {
+ m_spk_man->UpgradeKeyMetadata();
+ }
+}
+
bool CWallet::Unlock(const SecureString &strWalletPassphrase,
bool accept_no_keys) {
CCrypter crypter;
@@ -617,13 +623,16 @@
}
encrypted_batch->WriteMasterKey(nMasterKeyMaxID, kMasterKey);
- if (!EncryptKeys(_vMasterKey)) {
- encrypted_batch->TxnAbort();
- delete encrypted_batch;
- encrypted_batch = nullptr;
- // We now probably have half of our keys encrypted in memory, and
- // half not... die and let the user reload the unencrypted wallet.
- assert(false);
+ if (auto spk_man = m_spk_man.get()) {
+ if (!spk_man->EncryptKeys(_vMasterKey)) {
+ encrypted_batch->TxnAbort();
+ delete encrypted_batch;
+ encrypted_batch = nullptr;
+ // We now probably have half of our keys encrypted in memory,
+ // and half not... die and let the user reload the unencrypted
+ // wallet.
+ assert(false);
+ }
}
// Encryption was introduced in version 0.4.0
@@ -644,12 +653,12 @@
Lock();
Unlock(strWalletPassphrase);
- // If we are using HD, replace the HD seed with a new one
- if (IsHDEnabled()) {
- SetHDSeed(GenerateNewSeed());
+ // if we are using HD, replace the HD seed with a new one
+ if (m_spk_man->IsHDEnabled()) {
+ m_spk_man->SetHDSeed(m_spk_man->GenerateNewSeed());
}
- NewKeyPool();
+ m_spk_man->NewKeyPool();
Lock();
// Need to completely rewrite the wallet file; if we don't, bdb might
@@ -751,7 +760,7 @@
CTxDestination dst;
if (ExtractDestination(srctx->tx->vout[n].scriptPubKey, dst)) {
- if (::IsMine(*this, dst)) {
+ if (IsMine(dst)) {
LOCK(cs_wallet);
if (used && !GetDestData(dst, "used", nullptr)) {
// p for "present", opposite of absent (null)
@@ -765,7 +774,7 @@
bool CWallet::IsUsedDestination(const CTxDestination &dst) const {
LOCK(cs_wallet);
- return ::IsMine(*this, dst) && GetDestData(dst, "used", nullptr);
+ return IsMine(dst) && GetDestData(dst, "used", nullptr);
}
bool CWallet::IsUsedDestination(const TxId &txid, unsigned int n) const {
@@ -932,16 +941,16 @@
// extract addresses and check if they match with an unused keypool
// key
for (const auto &keyid :
- GetAffectedKeys(txout.scriptPubKey, *this)) {
+ GetAffectedKeys(txout.scriptPubKey, *m_spk_man)) {
std::map<CKeyID, int64_t>::const_iterator mi =
- m_pool_key_to_index.find(keyid);
- if (mi != m_pool_key_to_index.end()) {
+ m_spk_man->m_pool_key_to_index.find(keyid);
+ if (mi != m_spk_man->m_pool_key_to_index.end()) {
WalletLogPrintf("%s: Detected a used keypool key, mark all "
"keypool key up to this key as used\n",
__func__);
MarkReserveKeysAsUsed(mi->second);
- if (!TopUpKeyPool()) {
+ if (!m_spk_man->TopUpKeyPool()) {
WalletLogPrintf(
"%s: Topping up keypool failed (locked wallet)\n",
__func__);
@@ -1215,12 +1224,19 @@
}
isminetype CWallet::IsMine(const CTxOut &txout) const {
- return ::IsMine(*this, txout.scriptPubKey);
+ return IsMine(txout.scriptPubKey);
}
-isminetype IsMine(const CWallet &keystore, const CTxDestination &dest) {
- CScript script = GetScriptForDestination(dest);
- return IsMine(keystore, script);
+isminetype CWallet::IsMine(const CTxDestination &dest) const {
+ return IsMine(GetScriptForDestination(dest));
+}
+
+isminetype CWallet::IsMine(const CScript &script) const {
+ isminetype result = ISMINE_NO;
+ if (auto spk_man = m_spk_man.get()) {
+ result = spk_man->IsMine(script);
+ }
+ return result;
}
Amount CWallet::GetCredit(const CTxOut &txout,
@@ -1246,7 +1262,7 @@
// outputs are 'the send' and which are 'the change' will need to be
// implemented (maybe extend CWalletTx to remember which output, if any, was
// change).
- if (::IsMine(*this, script)) {
+ if (IsMine(script)) {
CTxDestination address;
if (!ExtractDestination(script, address)) {
return true;
@@ -1351,6 +1367,24 @@
return nChange;
}
+bool CWallet::IsHDEnabled() const {
+ bool result = true;
+ if (auto spk_man = m_spk_man.get()) {
+ result &= spk_man->IsHDEnabled();
+ }
+ return result;
+}
+
+bool CWallet::CanGetAddresses(bool internal) {
+ {
+ auto spk_man = m_spk_man.get();
+ if (spk_man && spk_man->CanGetAddresses(internal)) {
+ return true;
+ }
+ }
+ return false;
+}
+
void CWallet::SetWalletFlag(uint64_t flags) {
LOCK(cs_wallet);
m_wallet_flags |= flags;
@@ -1407,7 +1441,9 @@
const CScript &scriptPubKey = txout.scriptPubKey;
SignatureData sigdata;
- if (!ProduceSignature(*this,
+ const SigningProvider *provider = GetSigningProvider();
+
+ if (!ProduceSignature(*provider,
use_max_sig ? DUMMY_MAXIMUM_SIGNATURE_CREATOR
: DUMMY_SIGNATURE_CREATOR,
scriptPubKey, sigdata)) {
@@ -1435,6 +1471,57 @@
return true;
}
+bool CWallet::ImportScripts(const std::set<CScript> scripts,
+ int64_t timestamp) {
+ auto spk_man = GetLegacyScriptPubKeyMan();
+ if (!spk_man) {
+ return false;
+ }
+ AssertLockHeld(spk_man->cs_wallet);
+ return spk_man->ImportScripts(scripts, timestamp);
+}
+
+bool CWallet::ImportPrivKeys(const std::map<CKeyID, CKey> &privkey_map,
+ const int64_t timestamp) {
+ auto spk_man = GetLegacyScriptPubKeyMan();
+ if (!spk_man) {
+ return false;
+ }
+ AssertLockHeld(spk_man->cs_wallet);
+ return spk_man->ImportPrivKeys(privkey_map, timestamp);
+}
+
+bool CWallet::ImportPubKeys(
+ const std::vector<CKeyID> &ordered_pubkeys,
+ const std::map<CKeyID, CPubKey> &pubkey_map,
+ const std::map<CKeyID, std::pair<CPubKey, KeyOriginInfo>> &key_origins,
+ const bool add_keypool, const bool internal, const int64_t timestamp) {
+ auto spk_man = GetLegacyScriptPubKeyMan();
+ if (!spk_man) {
+ return false;
+ }
+ AssertLockHeld(spk_man->cs_wallet);
+ return spk_man->ImportPubKeys(ordered_pubkeys, pubkey_map, key_origins,
+ add_keypool, internal, timestamp);
+}
+
+bool CWallet::ImportScriptPubKeys(const std::string &label,
+ const std::set<CScript> &script_pub_keys,
+ const bool have_solving_data,
+ const bool apply_label,
+ const int64_t timestamp) {
+ auto spk_man = GetLegacyScriptPubKeyMan();
+ if (!spk_man) {
+ return false;
+ }
+ AssertLockHeld(spk_man->cs_wallet);
+ if (!spk_man->ImportScriptPubKeys(label, script_pub_keys, have_solving_data,
+ apply_label, timestamp)) {
+ return false;
+ }
+ return true;
+}
+
int64_t CalculateMaximumSignedTxSize(const CTransaction &tx,
const CWallet *wallet, bool use_max_sig) {
std::vector<CTxOut> txouts;
@@ -2234,7 +2321,11 @@
continue;
}
- bool solvable = IsSolvable(*this, wtx.tx->vout[i].scriptPubKey);
+ const SigningProvider *provider = GetSigningProvider();
+
+ bool solvable =
+ provider ? IsSolvable(*provider, wtx.tx->vout[i].scriptPubKey)
+ : false;
bool spendable =
((mine & ISMINE_SPENDABLE) != ISMINE_NO) ||
(((mine & ISMINE_WATCH_ONLY) != ISMINE_NO) &&
@@ -2552,7 +2643,13 @@
const Amount amount = mi->second.tx->vout[input.prevout.GetN()].nValue;
SignatureData sigdata;
SigHashType sigHashType = SigHashType().withForkId();
- if (!ProduceSignature(*this,
+
+ const SigningProvider *provider = GetSigningProvider();
+ if (!provider) {
+ return false;
+ }
+
+ if (!ProduceSignature(*provider,
MutableTransactionSignatureCreator(
&tx, nIn, amount, sigHashType),
scriptPubKey, sigdata)) {
@@ -3044,8 +3141,13 @@
const CScript &scriptPubKey = coin.txout.scriptPubKey;
SignatureData sigdata;
+ const SigningProvider *provider = GetSigningProvider();
+ if (!provider) {
+ return false;
+ }
+
if (!ProduceSignature(
- *this,
+ *provider,
MutableTransactionSignatureCreator(
&txNew, nIn, coin.txout.nValue, sigHashType),
scriptPubKey, sigdata)) {
@@ -3150,7 +3252,7 @@
if (database->Rewrite("\x04pool")) {
setInternalKeyPool.clear();
setExternalKeyPool.clear();
- m_pool_key_to_index.clear();
+ m_spk_man->m_pool_key_to_index.clear();
// Note: can't top-up keypool here, because wallet is locked.
// User will be prompted to unlock wallet the next operation
// that requires a new key.
@@ -3190,7 +3292,7 @@
if (database->Rewrite("\x04pool")) {
setInternalKeyPool.clear();
setExternalKeyPool.clear();
- m_pool_key_to_index.clear();
+ m_spk_man->m_pool_key_to_index.clear();
// Note: can't top-up keypool here, because wallet is locked.
// User will be prompted to unlock wallet the next operation
// that requires a new key.
@@ -3213,7 +3315,7 @@
LOCK(cs_wallet);
setInternalKeyPool.clear();
setExternalKeyPool.clear();
- m_pool_key_to_index.clear();
+ m_spk_man->m_pool_key_to_index.clear();
// Note: can't top-up keypool here, because wallet is locked.
// User will be prompted to unlock wallet the next operation
// that requires a new key.
@@ -3245,7 +3347,7 @@
}
NotifyAddressBookChanged(this, address, strName,
- ::IsMine(*this, address) != ISMINE_NO, strPurpose,
+ IsMine(address) != ISMINE_NO, strPurpose,
(fUpdated ? CT_UPDATED : CT_NEW));
if (!strPurpose.empty() && !batch.WritePurpose(address, strPurpose)) {
return false;
@@ -3273,20 +3375,50 @@
mapAddressBook.erase(address);
}
- NotifyAddressBookChanged(this, address, "",
- ::IsMine(*this, address) != ISMINE_NO, "",
- CT_DELETED);
+ NotifyAddressBookChanged(this, address, "", IsMine(address) != ISMINE_NO,
+ "", CT_DELETED);
WalletBatch(*database).ErasePurpose(address);
return WalletBatch(*database).EraseName(address);
}
+size_t CWallet::KeypoolCountExternalKeys() {
+ AssertLockHeld(cs_wallet);
+
+ unsigned int count = 0;
+ if (auto spk_man = m_spk_man.get()) {
+ AssertLockHeld(spk_man->cs_wallet);
+ count += spk_man->KeypoolCountExternalKeys();
+ }
+
+ return count;
+}
+
+bool CWallet::TopUpKeyPool(unsigned int kpSize) {
+ bool res = true;
+ if (auto spk_man = m_spk_man.get()) {
+ res &= spk_man->TopUpKeyPool(kpSize);
+ }
+ return res;
+}
+
+bool CWallet::GetNewDestination(const OutputType type, const std::string label,
+ CTxDestination &dest, std::string &error) {
+ error.clear();
+ bool result = false;
+ auto spk_man = m_spk_man.get();
+ if (spk_man) {
+ result = spk_man->GetNewDestination(type, label, dest, error);
+ }
+ return result;
+}
+
bool CWallet::GetNewChangeDestination(const OutputType type,
CTxDestination &dest,
std::string &error) {
error.clear();
- TopUpKeyPool();
+ m_spk_man->TopUpKeyPool();
ReserveDestination reservedest(this);
if (!reservedest.GetReservedDestination(type, dest, true)) {
@@ -3298,6 +3430,14 @@
return true;
}
+int64_t CWallet::GetOldestKeyPoolTime() {
+ int64_t oldestKey = std::numeric_limits<int64_t>::max();
+ if (auto spk_man = m_spk_man.get()) {
+ oldestKey = spk_man->GetOldestKeyPoolTime();
+ }
+ return oldestKey;
+}
+
std::map<CTxDestination, Amount>
CWallet::GetAddressBalances(interfaces::Chain::Lock &locked_chain) {
std::map<CTxDestination, Amount> balances;
@@ -3466,13 +3606,18 @@
bool ReserveDestination::GetReservedDestination(const OutputType type,
CTxDestination &dest,
bool internal) {
+ m_spk_man = pwallet->GetLegacyScriptPubKeyMan();
+ if (!m_spk_man) {
+ return false;
+ }
+
if (!pwallet->CanGetAddresses(internal)) {
return false;
}
if (nIndex == -1) {
CKeyPool keypool;
- if (!pwallet->ReserveKeyFromKeyPool(nIndex, keypool, internal)) {
+ if (!m_spk_man->ReserveKeyFromKeyPool(nIndex, keypool, internal)) {
return false;
}
@@ -3481,7 +3626,7 @@
}
assert(vchPubKey.IsValid());
- pwallet->LearnRelatedScripts(vchPubKey, type);
+ m_spk_man->LearnRelatedScripts(vchPubKey, type);
address = GetDestinationForKey(vchPubKey, type);
dest = address;
return true;
@@ -3489,7 +3634,7 @@
void ReserveDestination::KeepDestination() {
if (nIndex != -1) {
- pwallet->KeepKey(nIndex);
+ m_spk_man->KeepKey(nIndex);
}
nIndex = -1;
@@ -3499,7 +3644,7 @@
void ReserveDestination::ReturnDestination() {
if (nIndex != -1) {
- pwallet->ReturnKey(nIndex, fInternal, vchPubKey);
+ m_spk_man->ReturnKey(nIndex, fInternal, vchPubKey);
}
nIndex = -1;
vchPubKey = CPubKey();
@@ -3541,8 +3686,12 @@
AssertLockHeld(cs_wallet);
mapKeyBirth.clear();
+ LegacyScriptPubKeyMan *spk_man = GetLegacyScriptPubKeyMan();
+ assert(spk_man != nullptr);
+ AssertLockHeld(spk_man->cs_wallet);
+
// Get birth times for keys with metadata.
- for (const auto &entry : mapKeyMetadata) {
+ for (const auto &entry : spk_man->mapKeyMetadata) {
if (entry.second.nCreateTime) {
mapKeyBirth[entry.first] = entry.second.nCreateTime;
}
@@ -3554,7 +3703,7 @@
const int max_height =
tip_height && *tip_height > 144 ? *tip_height - 144 : 0;
std::map<CKeyID, int> mapKeyFirstBlock;
- for (const CKeyID &keyid : GetKeys()) {
+ for (const CKeyID &keyid : spk_man->GetKeys()) {
if (mapKeyBirth.count(keyid) == 0) {
mapKeyFirstBlock[keyid] = max_height;
}
@@ -3575,7 +3724,7 @@
for (const CTxOut &txout : wtx.tx->vout) {
// Iterate over all their outputs...
for (const auto &keyid :
- GetAffectedKeys(txout.scriptPubKey, *this)) {
+ GetAffectedKeys(txout.scriptPubKey, *spk_man)) {
// ... and all their affected keys.
std::map<CKeyID, int>::iterator rit =
mapKeyFirstBlock.find(keyid);
@@ -3897,13 +4046,13 @@
bool hd_upgrade = false;
bool split_upgrade = false;
if (walletInstance->CanSupportFeature(FEATURE_HD) &&
- !walletInstance->IsHDEnabled()) {
+ !walletInstance->m_spk_man->IsHDEnabled()) {
walletInstance->WalletLogPrintf("Upgrading wallet to HD\n");
walletInstance->SetMinVersion(FEATURE_HD);
// generate a new master key
- CPubKey masterPubKey = walletInstance->GenerateNewSeed();
- walletInstance->SetHDSeed(masterPubKey);
+ CPubKey masterPubKey = walletInstance->m_spk_man->GenerateNewSeed();
+ walletInstance->m_spk_man->SetHDSeed(masterPubKey);
hd_upgrade = true;
}
// Upgrade to HD chain split if necessary
@@ -3919,7 +4068,7 @@
}
// Regenerate the keypool if upgraded to HD
if (hd_upgrade) {
- if (!walletInstance->TopUpKeyPool()) {
+ if (!walletInstance->m_spk_man->TopUpKeyPool()) {
error = _("Unable to generate keys").translated;
return nullptr;
}
@@ -3935,13 +4084,13 @@
if (!(wallet_creation_flags &
(WALLET_FLAG_DISABLE_PRIVATE_KEYS | WALLET_FLAG_BLANK_WALLET))) {
// generate a new seed
- CPubKey seed = walletInstance->GenerateNewSeed();
- walletInstance->SetHDSeed(seed);
+ CPubKey seed = walletInstance->m_spk_man->GenerateNewSeed();
+ walletInstance->m_spk_man->SetHDSeed(seed);
}
// Top up the keypool
- if (walletInstance->CanGenerateKeys() &&
- !walletInstance->TopUpKeyPool()) {
+ if (walletInstance->m_spk_man->CanGenerateKeys() &&
+ !walletInstance->m_spk_man->TopUpKeyPool()) {
error = _("Unable to generate initial keys").translated;
return nullptr;
}
@@ -4339,3 +4488,15 @@
NotifyStatusChanged(this);
return true;
}
+
+ScriptPubKeyMan *CWallet::GetScriptPubKeyMan() const {
+ return m_spk_man.get();
+}
+
+const SigningProvider *CWallet::GetSigningProvider() const {
+ return m_spk_man.get();
+}
+
+LegacyScriptPubKeyMan *CWallet::GetLegacyScriptPubKeyMan() const {
+ return m_spk_man.get();
+}
diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp
--- a/src/wallet/walletdb.cpp
+++ b/src/wallet/walletdb.cpp
@@ -16,7 +16,6 @@
#include <sync.h>
#include <util/system.h>
#include <util/time.h>
-#include <wallet/scriptpubkeyman.h>
#include <wallet/wallet.h>
#include <atomic>
@@ -212,7 +211,8 @@
static bool ReadKeyValue(CWallet *pwallet, CDataStream &ssKey,
CDataStream &ssValue, CWalletScanState &wss,
std::string &strType, std::string &strErr)
- EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet) {
+ EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet,
+ pwallet->GetLegacyScriptPubKeyMan()->cs_wallet) {
try {
// Unserialize
// Taking advantage of the fact that pair serialization is just the two
@@ -278,7 +278,7 @@
char fYes;
ssValue >> fYes;
if (fYes == '1') {
- pwallet->LoadWatchOnly(script);
+ pwallet->GetLegacyScriptPubKeyMan()->LoadWatchOnly(script);
}
} else if (strType == DBKeys::KEY) {
CPubKey vchPubKey;
@@ -327,11 +327,14 @@
strErr = "Error reading wallet database: CPrivKey corrupt";
return false;
}
- if (!pwallet->LoadKey(key, vchPubKey)) {
- strErr = "Error reading wallet database: LoadKey failed";
+ if (!pwallet->GetLegacyScriptPubKeyMan()->LoadKey(key, vchPubKey)) {
+ strErr = "Error reading wallet database: "
+ "LegacyScriptPubKeyMan::LoadKey failed";
return false;
}
} else if (strType == DBKeys::MASTER_KEY) {
+ // Master encryption key is loaded into only the wallet and not any
+ // of the ScriptPubKeyMans.
unsigned int nID;
ssKey >> nID;
CMasterKey kMasterKey;
@@ -357,8 +360,10 @@
ssValue >> vchPrivKey;
wss.nCKeys++;
- if (!pwallet->LoadCryptedKey(vchPubKey, vchPrivKey)) {
- strErr = "Error reading wallet database: LoadCryptedKey failed";
+ if (!pwallet->GetLegacyScriptPubKeyMan()->LoadCryptedKey(
+ vchPubKey, vchPrivKey)) {
+ strErr = "Error reading wallet database: "
+ "LegacyScriptPubKeyMan::LoadCryptedKey failed";
return false;
}
wss.fIsEncrypted = true;
@@ -368,15 +373,16 @@
CKeyMetadata keyMeta;
ssValue >> keyMeta;
wss.nKeyMeta++;
-
- pwallet->LoadKeyMetadata(vchPubKey.GetID(), keyMeta);
+ pwallet->GetLegacyScriptPubKeyMan()->LoadKeyMetadata(
+ vchPubKey.GetID(), keyMeta);
} else if (strType == DBKeys::WATCHMETA) {
CScript script;
ssKey >> script;
CKeyMetadata keyMeta;
ssValue >> keyMeta;
wss.nKeyMeta++;
- pwallet->LoadScriptMetadata(CScriptID(script), keyMeta);
+ pwallet->GetLegacyScriptPubKeyMan()->LoadScriptMetadata(
+ CScriptID(script), keyMeta);
} else if (strType == DBKeys::DEFAULTKEY) {
// We don't want or need the default key, but if there is one set,
// we want to make sure that it is valid so that we can detect
@@ -393,14 +399,15 @@
CKeyPool keypool;
ssValue >> keypool;
- pwallet->LoadKeyPool(nIndex, keypool);
+ pwallet->GetLegacyScriptPubKeyMan()->LoadKeyPool(nIndex, keypool);
} else if (strType == DBKeys::CSCRIPT) {
uint160 hash;
ssKey >> hash;
CScript script;
ssValue >> script;
- if (!pwallet->LoadCScript(script)) {
- strErr = "Error reading wallet database: LoadCScript failed";
+ if (!pwallet->GetLegacyScriptPubKeyMan()->LoadCScript(script)) {
+ strErr = "Error reading wallet database: "
+ "LegacyScriptPubKeyMan::LoadCScript failed";
return false;
}
} else if (strType == DBKeys::ORDERPOSNEXT) {
@@ -416,7 +423,7 @@
} else if (strType == DBKeys::HDCHAIN) {
CHDChain chain;
ssValue >> chain;
- pwallet->SetHDChain(chain, true);
+ pwallet->GetLegacyScriptPubKeyMan()->SetHDChain(chain, true);
} else if (strType == DBKeys::FLAGS) {
uint64_t flags;
ssValue >> flags;
@@ -461,6 +468,7 @@
DBErrors result = DBErrors::LOAD_OK;
LOCK(pwallet->cs_wallet);
+ AssertLockHeld(pwallet->GetLegacyScriptPubKeyMan()->cs_wallet);
try {
int nMinVersion = 0;
if (m_batch.Read(DBKeys::MINVERSION, nMinVersion)) {
@@ -551,7 +559,10 @@
// nTimeFirstKey is only reliable if all keys have metadata
if ((wss.nKeys + wss.nCKeys + wss.nWatchKeys) != wss.nKeyMeta) {
- pwallet->UpdateTimeFirstKey(1);
+ auto spk_man = pwallet->GetLegacyScriptPubKeyMan();
+ if (spk_man) {
+ spk_man->UpdateTimeFirstKey(1);
+ }
}
for (const TxId &txid : wss.vWalletUpgrade) {
@@ -759,6 +770,7 @@
{
// Required in LoadKeyMetadata():
LOCK(dummyWallet->cs_wallet);
+ AssertLockHeld(dummyWallet->GetLegacyScriptPubKeyMan()->cs_wallet);
fReadOK = ReadKeyValue(dummyWallet, ssKey, ssValue, dummyWss, strType,
strErr);
}
diff --git a/src/wallet/wallettool.cpp b/src/wallet/wallettool.cpp
--- a/src/wallet/wallettool.cpp
+++ b/src/wallet/wallettool.cpp
@@ -42,8 +42,9 @@
wallet_instance->SetMinVersion(FEATURE_HD_SPLIT);
// generate a new HD seed
- CPubKey seed = wallet_instance->GenerateNewSeed();
- wallet_instance->SetHDSeed(seed);
+ auto spk_man = wallet_instance->GetLegacyScriptPubKeyMan();
+ CPubKey seed = spk_man->GenerateNewSeed();
+ spk_man->SetHDSeed(seed);
tfm::format(std::cout, "Topping up keypool...\n");
wallet_instance->TopUpKeyPool();
@@ -111,7 +112,7 @@
tfm::format(std::cout, "Encrypted: %s\n",
wallet_instance->IsCrypted() ? "yes" : "no");
tfm::format(std::cout, "HD (hd seed available): %s\n",
- wallet_instance->GetHDChain().seed_id.IsNull() ? "no" : "yes");
+ wallet_instance->IsHDEnabled() ? "yes" : "no");
tfm::format(std::cout, "Keypool Size: %u\n",
wallet_instance->GetKeyPoolSize());
tfm::format(std::cout, "Transactions: %zu\n",
diff --git a/test/lint/lint-circular-dependencies.sh b/test/lint/lint-circular-dependencies.sh
--- a/test/lint/lint-circular-dependencies.sh
+++ b/test/lint/lint-circular-dependencies.sh
@@ -25,7 +25,6 @@
"wallet/fees -> wallet/wallet -> wallet/fees"
"wallet/rpcwallet -> wallet/wallet -> wallet/rpcwallet"
"wallet/wallet -> wallet/walletdb -> wallet/wallet"
- "wallet/ismine -> wallet/wallet -> wallet/ismine"
"avalanche/processor -> validation -> avalanche/processor"
"chainparams -> protocol -> chainparams"
"chainparamsbase -> util/system -> chainparamsbase"
@@ -33,6 +32,7 @@
"script/scriptcache -> validation -> script/scriptcache"
"seeder/bitcoin -> seeder/db -> seeder/bitcoin"
"chainparams -> protocol -> config -> chainparams"
+ "wallet/scriptpubkeyman -> wallet/wallet -> wallet/scriptpubkeyman"
)
EXIT_CODE=0
diff --git a/test/lint/lint-format-strings.py b/test/lint/lint-format-strings.py
--- a/test/lint/lint-format-strings.py
+++ b/test/lint/lint-format-strings.py
@@ -26,6 +26,11 @@
("src/wallet/wallet.h",
"LogPrintf((\"%s \" + fmt).c_str(), GetDisplayName(), parameters...)"),
("src/logging.h", "LogPrintf(const char *fmt, const Args &... args)"),
+ ("src/wallet/scriptpubkeyman.h",
+ "WalletLogPrintf(const std::string& fmt, const Params&... parameters)"),
+ ("src/wallet/scriptpubkeyman.cpp", "WalletLogPrintf(fmt, parameters...)"),
+ ("src/wallet/scriptpubkeyman.cpp",
+ "WalletLogPrintf(const std::string& fmt, const Params&... parameters)"),
]
FUNCTION_NAMES_AND_NUMBER_OF_LEADING_ARGUMENTS = [

File Metadata

Mime Type
text/plain
Expires
Sat, Mar 1, 11:17 (19 h, 27 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
5187558
Default Alt Text
D7119.diff (130 KB)

Event Timeline