Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F13115516
D7119.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
130 KB
Subscribers
None
D7119.diff
View Options
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
Details
Attached
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)
Attached To
D7119: [backport#17260 3/3] Refactor: Split up CWallet and LegacyScriptPubKeyMan and classes
Event Timeline
Log In to Comment