mirror of
https://github.com/dashpay/dash.git
synced 2024-12-24 19:42:46 +01:00
Merge bitcoin#17304: refactor: Move many functions into LegacyScriptPubKeyMan and further separate it from CWallet
* MOVEONLY: Reorder LegacyScriptPubKeyMan methods Can verify move-only with: git log -p -n1 --color-moved This commit is move-only and doesn't change code or affect behavior. * Refactor: Declare LegacyScriptPubKeyMan methods as virtual This commit does not change behavior. * Refactor: Add new ScriptPubKeyMan virtual methods This commit does not change behavior. * Refactor: Move SetAddressBook call out of LegacyScriptPubKeyMan::GetNewDestination This commit does not change behavior. * Refactor: Move SetWalletFlag out of LegacyScriptPubKeyMan::UpgradeKeyMetadata This commit does not change behavior. * Remove SetWalletFlag from WalletStorage SetWalletFlag is unused. Does not change any behavior * Refactor: Remove UnsetWalletFlag call from LegacyScriptPubKeyMan::SetHDSeed This commit does not change behavior. * refactor: Replace UnsetWalletFlagWithDB with UnsetBlankWalletFlag in ScriptPubKeyMan ScriptPubKeyMan is only using UnsetWalletFlagWithDB to unset the blank wallet flag. Just make that it's own function and not expose the flag writing directly. This does not change behavior. * Refactor: Move SetAddressBookWithDB call out of LegacyScriptPubKeyMan::ImportScriptPubKeys This commit does not change behavior. * Refactor: Move LoadKey LegacyScriptPubKeyMan method definition This commit does not change behavior. * Refactor: Move GetMetadata code out of getaddressinfo Easier to review ignoring whitespace: git log -p -n1 -w This commit does not change behavior. * Refactor: Move MarkUnusedAddresses code out of CWallet::AddToWalletIfInvolvingMe This commit does not change behavior. * Refactor: Move HavePrivateKeys code out of CWallet::CreateWalletFromFile This commit does not change behavior. * Refactor: Move RewriteDB code out of CWallet This commit does not change behavior. * Refactor: Move GetKeypoolSize code out of CWallet This commit does not change behavior. * Refactor: Move nTimeFirstKey accesses out of CWallet This commit does not change behavior. * Re-order methods of scriptpubkeyman for easier backporting changes in future * Fixup for missing cs_wallet lock: ``` wallet/wallet.cpp:4536:41: error: calling function 'GetTimeFirstKey' requires holding mutex 'spk_man->cs_wallet' exclusively [-Werror,-Wthread-safety-analysis] int64_t time = spk_man->GetTimeFirstKey(); ^ wallet/wallet.cpp:4570:106: error: calling function 'GetTimeFirstKey' requires holding mutex 'walletInstance->m_spk_man->cs_wallet' exclusively [-Werror,-Wthread-safety-analysis] walletInstance->WalletLogPrintf("nTimeFirstKey = %u\n", walletInstance->m_spk_man->GetTimeFirstKey()); ``` * Fix 2 locks * more of "refactor: Replace UnsetWalletFlagWithDB with UnsetBlankWalletFlag in ScriptPubKeyMan" * Refactoring GetOldestKeyInPool -> GetOldestKeyTimeInPool, partial bitcoin#10235 Co-authored-by: Andrew Chow <achow101-github@achow101.com> Co-authored-by: UdjinM6 <UdjinM6@users.noreply.github.com>
This commit is contained in:
parent
7228d918f6
commit
9845f8c992
@ -3617,34 +3617,31 @@ UniValue getaddressinfo(const JSONRPCRequest& request)
|
||||
ret.pushKV("label", pwallet->mapAddressBook[dest].name);
|
||||
}
|
||||
ret.pushKV("ischange", pwallet->IsChange(scriptPubKey));
|
||||
const CKeyMetadata* meta = nullptr;
|
||||
const CKeyID *key_id = boost::get<CKeyID>(&dest);
|
||||
if (key_id != nullptr && !key_id->IsNull()) {
|
||||
auto it = pwallet->mapKeyMetadata.find(*key_id);
|
||||
if (it != pwallet->mapKeyMetadata.end()) {
|
||||
meta = &it->second;
|
||||
ScriptPubKeyMan* spk_man = pwallet->GetScriptPubKeyMan();
|
||||
if (spk_man) {
|
||||
const CKeyID *key_id = boost::get<CKeyID>(&dest);
|
||||
const CKeyMetadata* meta = nullptr;
|
||||
if (key_id != nullptr && !key_id->IsNull()) {
|
||||
meta = spk_man->GetMetadata(*key_id);
|
||||
}
|
||||
}
|
||||
if (!meta) {
|
||||
auto it = pwallet->m_script_metadata.find(CScriptID(scriptPubKey));
|
||||
if (it != pwallet->m_script_metadata.end()) {
|
||||
meta = &it->second;
|
||||
if (!meta) {
|
||||
meta = spk_man->GetMetadata(CScriptID(scriptPubKey));
|
||||
}
|
||||
}
|
||||
if (meta) {
|
||||
ret.pushKV("timestamp", meta->nCreateTime);
|
||||
CHDChain hdChainCurrent;
|
||||
LegacyScriptPubKeyMan* spk_man = pwallet->GetLegacyScriptPubKeyMan();
|
||||
if (spk_man != nullptr) {
|
||||
LOCK(pwallet->cs_KeyStore);
|
||||
AssertLockHeld(spk_man->cs_KeyStore);
|
||||
if (key_id && pwallet->mapHdPubKeys.count(*key_id) && spk_man->GetHDChain(hdChainCurrent)) {
|
||||
ret.pushKV("hdchainid", hdChainCurrent.GetID().GetHex());
|
||||
if (meta) {
|
||||
ret.pushKV("timestamp", meta->nCreateTime);
|
||||
CHDChain hdChainCurrent;
|
||||
LegacyScriptPubKeyMan* spk_man = pwallet->GetLegacyScriptPubKeyMan();
|
||||
if (spk_man != nullptr) {
|
||||
LOCK(pwallet->cs_KeyStore);
|
||||
AssertLockHeld(spk_man->cs_KeyStore);
|
||||
if (key_id && pwallet->mapHdPubKeys.count(*key_id) && spk_man->GetHDChain(hdChainCurrent)) {
|
||||
ret.pushKV("hdchainid", hdChainCurrent.GetID().GetHex());
|
||||
}
|
||||
}
|
||||
if (meta->has_key_origin) {
|
||||
ret.pushKV("hdkeypath", WriteHDKeypath(meta->key_origin.path));
|
||||
ret.pushKV("hdmasterfingerprint", HexStr(meta->key_origin.fingerprint));
|
||||
}
|
||||
}
|
||||
if (meta->has_key_origin) {
|
||||
ret.pushKV("hdkeypath", WriteHDKeypath(meta->key_origin.path));
|
||||
ret.pushKV("hdmasterfingerprint", HexStr(meta->key_origin.fingerprint));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -12,9 +12,8 @@
|
||||
#include <wallet/scriptpubkeyman.h>
|
||||
#include <wallet/wallet.h>
|
||||
|
||||
bool LegacyScriptPubKeyMan::GetNewDestination(const std::string label, CTxDestination& dest, std::string& error)
|
||||
bool LegacyScriptPubKeyMan::GetNewDestination(CTxDestination& dest, std::string& error)
|
||||
{
|
||||
LOCK(cs_wallet);
|
||||
error.clear();
|
||||
TopUpKeyPool();
|
||||
|
||||
@ -26,8 +25,6 @@ bool LegacyScriptPubKeyMan::GetNewDestination(const std::string label, CTxDestin
|
||||
}
|
||||
//LearnRelatedScripts(new_key);
|
||||
dest = new_key.GetID();
|
||||
|
||||
m_wallet.SetAddressBook(dest, label, "receive");
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -266,6 +263,62 @@ bool LegacyScriptPubKeyMan::EncryptKeys(CKeyingMaterial& vMasterKeyIn)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LegacyScriptPubKeyMan::GetReservedDestination(bool internal, int64_t& index, CKeyPool& keypool)
|
||||
{
|
||||
{
|
||||
if (!ReserveKeyFromKeyPool(index, keypool, internal)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void LegacyScriptPubKeyMan::KeepDestination(int64_t index)
|
||||
{
|
||||
KeepKey(index);
|
||||
}
|
||||
|
||||
void LegacyScriptPubKeyMan::ReturnDestination(int64_t index, bool internal, const CPubKey& pubkey)
|
||||
{
|
||||
ReturnKey(index, internal, pubkey);
|
||||
}
|
||||
|
||||
bool LegacyScriptPubKeyMan::TopUp(unsigned int size)
|
||||
{
|
||||
return TopUpKeyPool(size);
|
||||
}
|
||||
|
||||
void LegacyScriptPubKeyMan::MarkUnusedAddresses(WalletBatch &batch, const CScript& script, const uint256& hashBlock)
|
||||
{
|
||||
AssertLockHeld(cs_wallet);
|
||||
// extract addresses and check if they match with an unused keypool key
|
||||
for (const auto& keyid : GetAffectedKeys(script, *this)) {
|
||||
std::map<CKeyID, int64_t>::const_iterator mi = m_pool_key_to_index.find(keyid);
|
||||
if (mi != 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()) {
|
||||
WalletLogPrintf("%s: Topping up keypool failed (locked wallet)\n", __func__);
|
||||
}
|
||||
}
|
||||
if (!hashBlock.IsNull()) {
|
||||
int64_t block_time;
|
||||
bool found_block = m_wallet.chain().findBlock(hashBlock, nullptr /* block */, &block_time);
|
||||
assert(found_block);
|
||||
if (mapKeyMetadata[keyid].nCreateTime > block_time) {
|
||||
WalletLogPrintf("%s: Found a key which appears to be used earlier than we expected, updating metadata\n", __func__);
|
||||
CPubKey vchPubKey;
|
||||
bool res = GetPubKey(keyid, vchPubKey);
|
||||
assert(res); // this should never fail
|
||||
mapKeyMetadata[keyid].nCreateTime = block_time;
|
||||
batch.WriteKeyMetadata(mapKeyMetadata[keyid], vchPubKey, true);
|
||||
UpdateTimeFirstKey(block_time);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LegacyScriptPubKeyMan::UpgradeKeyMetadata()
|
||||
{
|
||||
AssertLockHeld(cs_wallet); // mapKeyMetadata
|
||||
@ -314,8 +367,6 @@ void LegacyScriptPubKeyMan::UpgradeKeyMetadata()
|
||||
}
|
||||
}
|
||||
}
|
||||
batch.reset(); //write before setting the flag
|
||||
m_storage.SetWalletFlag(WALLET_FLAG_KEY_ORIGIN_METADATA);
|
||||
}
|
||||
|
||||
void LegacyScriptPubKeyMan::GenerateNewHDChain(const SecureString& secureMnemonic, const SecureString& secureMnemonicPassphrase)
|
||||
@ -421,7 +472,7 @@ bool LegacyScriptPubKeyMan::SetHDChain(WalletBatch &batch, const CHDChain& chain
|
||||
throw std::runtime_error(std::string(__func__) + ": WriteHDChain failed");
|
||||
}
|
||||
|
||||
m_wallet.UnsetWalletFlag(batch, WALLET_FLAG_BLANK_WALLET);
|
||||
m_storage.UnsetBlankWalletFlag(batch);
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -442,7 +493,7 @@ bool LegacyScriptPubKeyMan::SetCryptedHDChain(WalletBatch &batch, const CHDChain
|
||||
if (!batch.WriteCryptedHDChain(chain))
|
||||
throw std::runtime_error(std::string(__func__) + ": WriteCryptedHDChain failed");
|
||||
}
|
||||
m_wallet.UnsetWalletFlag(batch, WALLET_FLAG_BLANK_WALLET);
|
||||
m_storage.UnsetBlankWalletFlag(batch);
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -615,7 +666,30 @@ bool LegacyScriptPubKeyMan::CanGetAddresses(bool internal)
|
||||
return keypool_has_keys;
|
||||
}
|
||||
|
||||
static int64_t GetOldestKeyInPool(const std::set<int64_t>& setKeyPool, WalletBatch& batch) {
|
||||
|
||||
bool LegacyScriptPubKeyMan::HavePrivateKeys() const
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
return !mapKeys.empty() || !mapCryptedKeys.empty();
|
||||
}
|
||||
|
||||
void LegacyScriptPubKeyMan::RewriteDB()
|
||||
{
|
||||
AssertLockHeld(cs_wallet);
|
||||
setInternalKeyPool.clear();
|
||||
setExternalKeyPool.clear();
|
||||
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.
|
||||
}
|
||||
|
||||
static int64_t GetOldestKeyTimeInPool(const std::set<int64_t>& setKeyPool, WalletBatch& batch) {
|
||||
if (setKeyPool.empty()) {
|
||||
// if the keypool is empty, return <NOW>
|
||||
return GetTime();
|
||||
}
|
||||
|
||||
CKeyPool keypool;
|
||||
int64_t nIndex = *(setKeyPool.begin());
|
||||
if (!batch.ReadPool(nIndex, keypool)) {
|
||||
@ -629,19 +703,11 @@ int64_t LegacyScriptPubKeyMan::GetOldestKeyPoolTime()
|
||||
{
|
||||
LOCK(cs_wallet);
|
||||
|
||||
// if the keypool is empty, return <NOW>
|
||||
if (setExternalKeyPool.empty() && setInternalKeyPool.empty())
|
||||
return GetTime();
|
||||
|
||||
WalletBatch batch(m_storage.GetDatabase());
|
||||
int64_t oldestKey = -1;
|
||||
int64_t oldestKey = GetOldestKeyTimeInPool(setExternalKeyPool, batch);
|
||||
|
||||
// load oldest key from keypool, get time and return
|
||||
if (!setInternalKeyPool.empty()) {
|
||||
oldestKey = std::max(GetOldestKeyInPool(setInternalKeyPool, batch), oldestKey);
|
||||
}
|
||||
if (!setExternalKeyPool.empty()) {
|
||||
oldestKey = std::max(GetOldestKeyInPool(setExternalKeyPool, batch), oldestKey);
|
||||
if (IsHDEnabled()) {
|
||||
oldestKey = std::max(GetOldestKeyTimeInPool(setInternalKeyPool, batch), oldestKey);
|
||||
}
|
||||
return oldestKey;
|
||||
}
|
||||
@ -658,6 +724,33 @@ size_t LegacyScriptPubKeyMan::KeypoolCountInternalKeys()
|
||||
return setInternalKeyPool.size();
|
||||
}
|
||||
|
||||
unsigned int LegacyScriptPubKeyMan::GetKeyPoolSize() const
|
||||
{
|
||||
AssertLockHeld(cs_wallet);
|
||||
return setInternalKeyPool.size() + setExternalKeyPool.size();
|
||||
}
|
||||
|
||||
int64_t LegacyScriptPubKeyMan::GetTimeFirstKey() const
|
||||
{
|
||||
AssertLockHeld(cs_wallet);
|
||||
return nTimeFirstKey;
|
||||
}
|
||||
|
||||
const CKeyMetadata* LegacyScriptPubKeyMan::GetMetadata(uint160 id) const
|
||||
{
|
||||
AssertLockHeld(cs_wallet);
|
||||
auto it = mapKeyMetadata.find(CKeyID(id));
|
||||
if (it != mapKeyMetadata.end()) {
|
||||
return &it->second;
|
||||
} else {
|
||||
auto it2 = m_script_metadata.find(CScriptID(id));
|
||||
if (it2 != m_script_metadata.end()) {
|
||||
return &it2->second;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update wallet first key creation time. This should be called whenever keys
|
||||
* are added to the wallet, with the oldest key creation time.
|
||||
@ -674,10 +767,9 @@ void LegacyScriptPubKeyMan::UpdateTimeFirstKey(int64_t nCreateTime)
|
||||
}
|
||||
}
|
||||
|
||||
int64_t LegacyScriptPubKeyMan::GetTimeFirstKey() const
|
||||
bool LegacyScriptPubKeyMan::LoadKey(const CKey& key, const CPubKey &pubkey)
|
||||
{
|
||||
AssertLockHeld(cs_wallet);
|
||||
return nTimeFirstKey;
|
||||
return AddKeyPubKeyInner(key, pubkey);
|
||||
}
|
||||
|
||||
bool LegacyScriptPubKeyMan::AddKeyPubKey(const CKey& secret, const CPubKey &pubkey)
|
||||
@ -722,7 +814,7 @@ bool LegacyScriptPubKeyMan::AddKeyPubKeyWithDB(WalletBatch& batch, const CKey& s
|
||||
secret.GetPrivKey(),
|
||||
mapKeyMetadata[pubkey.GetID()]);
|
||||
}
|
||||
m_wallet.UnsetWalletFlag(batch, WALLET_FLAG_BLANK_WALLET);
|
||||
m_storage.UnsetBlankWalletFlag(batch);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -932,7 +1024,7 @@ bool LegacyScriptPubKeyMan::AddWatchOnlyWithDB(WalletBatch &batch, const CScript
|
||||
UpdateTimeFirstKey(meta.nCreateTime);
|
||||
NotifyWatchonlyChanged(true);
|
||||
if (batch.WriteWatchOnly(dest, meta)) {
|
||||
m_wallet.UnsetWalletFlag(batch, WALLET_FLAG_BLANK_WALLET);
|
||||
m_storage.UnsetBlankWalletFlag(batch);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -1015,7 +1107,7 @@ bool LegacyScriptPubKeyMan::AddHDPubKey(WalletBatch &batch, const CExtPubKey &ex
|
||||
if (!batch.WriteHDPubKey(hdPubKey, mapKeyMetadata[extPubKey.pubkey.GetID()])) {
|
||||
return false;
|
||||
}
|
||||
m_wallet.UnsetWalletFlag(batch, WALLET_FLAG_BLANK_WALLET);
|
||||
m_storage.UnsetBlankWalletFlag(batch);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1331,12 +1423,14 @@ bool LegacyScriptPubKeyMan::TopUpKeyPool(unsigned int kpSize)
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
void LegacyScriptPubKeyMan::AddKeypoolPubkey(const CPubKey& pubkey, const bool internal)
|
||||
{
|
||||
WalletBatch batch(m_storage.GetDatabase());
|
||||
AddKeypoolPubkeyWithDB(pubkey, internal, batch);
|
||||
NotifyCanGetAddressesChanged();
|
||||
}
|
||||
*/
|
||||
|
||||
void LegacyScriptPubKeyMan::AddKeypoolPubkeyWithDB(const CPubKey& pubkey, const bool internal, WalletBatch& batch)
|
||||
{
|
||||
@ -1496,7 +1590,7 @@ bool LegacyScriptPubKeyMan::AddCScriptWithDB(WalletBatch& batch, const CScript&
|
||||
if (!FillableSigningProvider::AddCScript(redeemScript))
|
||||
return false;
|
||||
if (batch.WriteCScript(Hash160(redeemScript), redeemScript)) {
|
||||
m_wallet.UnsetWalletFlag(batch, WALLET_FLAG_BLANK_WALLET);
|
||||
m_storage.UnsetBlankWalletFlag(batch);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -1580,7 +1674,7 @@ bool LegacyScriptPubKeyMan::ImportPubKeys(const std::vector<CKeyID>& ordered_pub
|
||||
return true;
|
||||
}
|
||||
|
||||
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)
|
||||
bool LegacyScriptPubKeyMan::ImportScriptPubKeys(const std::set<CScript>& script_pub_keys, const bool have_solving_data, const int64_t timestamp)
|
||||
{
|
||||
WalletBatch batch(m_storage.GetDatabase());
|
||||
for (const CScript& script : script_pub_keys) {
|
||||
@ -1589,11 +1683,6 @@ bool LegacyScriptPubKeyMan::ImportScriptPubKeys(const std::string& label, const
|
||||
return false;
|
||||
}
|
||||
}
|
||||
CTxDestination dest;
|
||||
ExtractDestination(script, dest);
|
||||
if (apply_label && IsValidDestination(dest)) {
|
||||
m_wallet.SetAddressBookWithDB(batch, dest, label, "receive");
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ public:
|
||||
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 UnsetBlankWalletFlag(WalletBatch&) = 0;
|
||||
virtual bool CanSupportFeature(enum WalletFeature) const = 0;
|
||||
virtual void SetMinVersion(enum WalletFeature, WalletBatch* = nullptr, bool = false) = 0;
|
||||
virtual bool IsLocked(bool fForMixing = false) const = 0;
|
||||
@ -35,6 +35,8 @@ public:
|
||||
//! Default for -keypool
|
||||
static const unsigned int DEFAULT_KEYPOOL_SIZE = 1000;
|
||||
|
||||
std::vector<CKeyID> GetAffectedKeys(const CScript& spk, const SigningProvider& provider);
|
||||
|
||||
/** A key from a CWallet's keypool
|
||||
*
|
||||
* The wallet holds several keypools. These are sets of keys that have not
|
||||
@ -132,31 +134,86 @@ protected:
|
||||
|
||||
public:
|
||||
ScriptPubKeyMan(WalletStorage& storage) : m_storage(storage) {}
|
||||
|
||||
virtual ~ScriptPubKeyMan() {};
|
||||
virtual bool GetNewDestination(CTxDestination& dest, std::string& error) { return false; }
|
||||
virtual isminetype IsMine(const CScript& script) const { return ISMINE_NO; }
|
||||
virtual isminetype IsMine(const CTxDestination& dest) const { return ISMINE_NO; }
|
||||
|
||||
virtual bool GetReservedDestination(bool internal, int64_t& index, CKeyPool& keypool) { return false; }
|
||||
virtual void KeepDestination(int64_t index) {}
|
||||
virtual void ReturnDestination(int64_t index, bool internal, const CPubKey& pubkey) {}
|
||||
|
||||
virtual bool TopUp(unsigned int size = 0) { return false; }
|
||||
|
||||
//! Mark unused addresses as being used
|
||||
virtual void MarkUnusedAddresses(WalletBatch &batch, const CScript& script, const uint256& hashBlock) {}
|
||||
|
||||
/* Returns true if HD is enabled */
|
||||
virtual bool IsHDEnabled() const { return false; }
|
||||
|
||||
/* Returns true if the wallet can give out new addresses. This means it has keys in the keypool or can generate new keys */
|
||||
virtual bool CanGetAddresses(bool internal = false) { return false; }
|
||||
|
||||
virtual bool HavePrivateKeys() const { return false; }
|
||||
|
||||
//! The action to do when the DB needs rewrite
|
||||
virtual void RewriteDB() {}
|
||||
|
||||
virtual int64_t GetOldestKeyPoolTime() { return GetTime(); }
|
||||
|
||||
virtual size_t KeypoolCountExternalKeys() { return 0; }
|
||||
virtual size_t KeypoolCountInternalKeys() { return 0; }
|
||||
virtual unsigned int GetKeyPoolSize() const { return 0; }
|
||||
|
||||
virtual int64_t GetTimeFirstKey() const { return 0; }
|
||||
|
||||
virtual const CKeyMetadata* GetMetadata(uint160 id) const { return nullptr; }
|
||||
};
|
||||
|
||||
class LegacyScriptPubKeyMan : public ScriptPubKeyMan, public FillableSigningProvider
|
||||
{
|
||||
private:
|
||||
using CryptedKeyMap = std::map<CKeyID, std::pair<CPubKey, std::vector<unsigned char>>>;
|
||||
using WatchOnlySet = std::set<CScript>;
|
||||
using WatchKeyMap = std::map<CKeyID, CPubKey>;
|
||||
using HDPubKeyMap = std::map<CKeyID, CHDPubKey>;
|
||||
|
||||
//! will encrypt previously unencrypted keys
|
||||
bool EncryptKeys(CKeyingMaterial& vMasterKeyIn);
|
||||
|
||||
WalletBatch *encrypted_batch GUARDED_BY(cs_wallet) = nullptr;
|
||||
|
||||
using CryptedKeyMap = std::map<CKeyID, std::pair<CPubKey, std::vector<unsigned char>>>;
|
||||
|
||||
CryptedKeyMap mapCryptedKeys GUARDED_BY(cs_KeyStore);
|
||||
WatchOnlySet setWatchOnly GUARDED_BY(cs_KeyStore);
|
||||
WatchKeyMap mapWatchKeys GUARDED_BY(cs_KeyStore);
|
||||
HDPubKeyMap mapHdPubKeys GUARDED_BY(cs_KeyStore); //<! memory map of HD extended pubkeys
|
||||
|
||||
int64_t nTimeFirstKey GUARDED_BY(cs_wallet) = 0;
|
||||
|
||||
bool HaveKeyInner(const CKeyID &address) const;
|
||||
bool AddCryptedKeyInner(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret);
|
||||
bool AddKeyPubKeyInner(const CKey& key, const CPubKey &pubkey);
|
||||
bool AddCryptedKeyInner(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret);
|
||||
bool GetKeyInner(const CKeyID &address, CKey& keyOut) const;
|
||||
bool GetPubKeyInner(const CKeyID &address, CPubKey& vchPubKeyOut) const;
|
||||
|
||||
WalletBatch *encrypted_batch GUARDED_BY(cs_wallet) = nullptr;
|
||||
/**
|
||||
* 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);
|
||||
|
||||
|
||||
void AddKeypoolPubkeyWithDB(const CPubKey& pubkey, const bool internal, WalletBatch& batch);
|
||||
|
||||
/** Add a KeyOriginInfo to the wallet */
|
||||
bool AddKeyOriginWithDB(WalletBatch& batch, const CPubKey& pubkey, const KeyOriginInfo& info);
|
||||
|
||||
/* the HD chain data model (external chain counters) */
|
||||
CHDChain hdChain GUARDED_BY(cs_KeyStore);
|
||||
@ -170,105 +227,8 @@ private:
|
||||
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 AddWatchOnlyInMem(const CScript &dest);
|
||||
|
||||
/** Add a KeyOriginInfo to the wallet */
|
||||
bool AddKeyOriginWithDB(WalletBatch& batch, const CPubKey& pubkey, const KeyOriginInfo& info);
|
||||
|
||||
void AddKeypoolPubkeyWithDB(const CPubKey& pubkey, const bool internal, WalletBatch& batch);
|
||||
|
||||
public:
|
||||
//! 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);
|
||||
|
||||
//! Adds a script to the store and saves it to disk
|
||||
bool AddCScriptWithDB(WalletBatch& batch, const CScript& script);
|
||||
|
||||
public:
|
||||
void LoadKeyPool(int64_t nIndex, const CKeyPool &keypool) 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);
|
||||
|
||||
bool WriteKeyMetadata(const CKeyMetadata& meta, const CPubKey& pubkey, bool overwrite);
|
||||
|
||||
/**
|
||||
* keystore implementation
|
||||
* Generate a new key
|
||||
*/
|
||||
CPubKey GenerateNewKey(WalletBatch& batch, uint32_t nAccountIndex, bool fInternal /*= 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);
|
||||
int64_t GetTimeFirstKey() const 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<unsigned char> &vchCryptedSecret);
|
||||
//! Adds an encrypted key to the store, without saving it to disk (used by LoadWallet)
|
||||
bool LoadCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret);
|
||||
//! GetKey implementation that can derive a HD private key on the fly
|
||||
bool GetKey(const CKeyID &address, CKey& keyOut) const override;
|
||||
//! GetPubKey implementation that also checks the mapHdPubKeys
|
||||
bool GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const override;
|
||||
//! HaveKey implementation that also checks the mapHdPubKeys
|
||||
bool HaveKey(const CKeyID &address) const override;
|
||||
//! Adds a HDPubKey into the wallet(database)
|
||||
bool AddHDPubKey(WalletBatch &batch, const CExtPubKey &extPubKey, bool fInternal);
|
||||
//! loads a HDPubKey into the wallets memory
|
||||
bool LoadHDPubKey(const CHDPubKey &hdPubKey) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||
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 AddWatchOnlyWithDB(WalletBatch &batch, const CScript& dest) 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);
|
||||
size_t KeypoolCountInternalKeys() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||
bool TopUpKeyPool(unsigned int kpSize = 0);
|
||||
void AddKeypoolPubkey(const CPubKey& pubkey, const bool internal);
|
||||
|
||||
//! Fetches a key from the keypool
|
||||
bool GetKeyFromPool(CPubKey &key, bool fInternal /*= false*/);
|
||||
/**
|
||||
* Reserves a key from the keypool and sets nIndex to its index
|
||||
*
|
||||
@ -284,19 +244,136 @@ public:
|
||||
* 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);
|
||||
//! Fetches a key from the keypool
|
||||
bool GetKeyFromPool(CPubKey &key, bool internal /* = false */);
|
||||
int64_t GetOldestKeyPoolTime();
|
||||
|
||||
public:
|
||||
bool GetNewDestination(CTxDestination& dest, std::string& error) override;
|
||||
isminetype IsMine(const CScript& script) const override;
|
||||
isminetype IsMine(const CTxDestination& dest) const override;
|
||||
|
||||
//! will encrypt previously unencrypted keys
|
||||
bool EncryptKeys(CKeyingMaterial& vMasterKeyIn);
|
||||
|
||||
bool GetReservedDestination(bool internal, int64_t& index, CKeyPool& keypool) override;
|
||||
void KeepDestination(int64_t index) override;
|
||||
void ReturnDestination(int64_t index, bool internal, const CPubKey& pubkey) override;
|
||||
|
||||
bool TopUp(unsigned int size = 0) override;
|
||||
|
||||
void MarkUnusedAddresses(WalletBatch &batch, const CScript& script, const uint256& hashBlock) override;
|
||||
|
||||
//! Upgrade stored CKeyMetadata objects to store key origin info as KeyOriginInfo
|
||||
void UpgradeKeyMetadata() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||
|
||||
/* Returns true if HD is enabled */
|
||||
bool IsHDEnabled() const override;
|
||||
|
||||
bool HavePrivateKeys() const override;
|
||||
|
||||
void RewriteDB() override;
|
||||
|
||||
int64_t GetOldestKeyPoolTime() override;
|
||||
size_t KeypoolCountExternalKeys() override EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||
size_t KeypoolCountInternalKeys() override EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||
|
||||
unsigned int GetKeyPoolSize() const override;
|
||||
|
||||
int64_t GetTimeFirstKey() const override EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||
|
||||
const CKeyMetadata* GetMetadata(uint160 id) const override;
|
||||
|
||||
bool CanGetAddresses(bool internal = false) override;
|
||||
|
||||
// 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);
|
||||
|
||||
//! Adds a script to the store and saves it to disk
|
||||
bool AddCScriptWithDB(WalletBatch& batch, const CScript& script);
|
||||
|
||||
//! 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 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);
|
||||
//! Adds an encrypted key to the store, and saves it to disk.
|
||||
bool AddCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret);
|
||||
//! Adds an encrypted key to the store, without saving it to disk (used by LoadWallet)
|
||||
bool LoadCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret);
|
||||
void UpdateTimeFirstKey(int64_t nCreateTime) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||
//! Adds a CScript to the store
|
||||
bool LoadCScript(const CScript& redeemScript);
|
||||
//! Load metadata (used by LoadWallet)
|
||||
void LoadKeyMetadata(const CKeyID& keyID, const CKeyMetadata &metadata) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||
bool WriteKeyMetadata(const CKeyMetadata& meta, const CPubKey& pubkey, bool overwrite);
|
||||
void LoadScriptMetadata(const CScriptID& script_id, const CKeyMetadata &metadata) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||
//! Generate a new key
|
||||
CPubKey GenerateNewKey(WalletBatch& batch, uint32_t nAccountIndex, bool fInternal /*= false*/) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||
|
||||
/* Set the HD chain model (chain child index counters) */
|
||||
bool SetHDChain(WalletBatch &batch, const CHDChain& chain, bool memonly);
|
||||
bool SetCryptedHDChain(WalletBatch &batch, const CHDChain& chain, bool memonly);
|
||||
/**
|
||||
* Marks all keys in the keypool up to and including reserve_key as used.
|
||||
* Set the HD chain model (chain child index counters) using temporary wallet db object
|
||||
* which causes db flush every time these methods are used
|
||||
*/
|
||||
void MarkReserveKeysAsUsed(int64_t keypool_id) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||
bool SetHDChainSingle(const CHDChain& chain, bool memonly);
|
||||
bool SetCryptedHDChainSingle(const CHDChain& chain, bool memonly);
|
||||
|
||||
isminetype IsMine(const CScript& script) const;
|
||||
isminetype IsMine(const CTxDestination& dest) const;
|
||||
//! 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;
|
||||
//! Remove a watch only script from the keystore
|
||||
bool RemoveWatchOnly(const CScript &dest) 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);
|
||||
//! 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);
|
||||
|
||||
//! Fetches a pubkey from mapWatchKeys if it exists there
|
||||
bool GetWatchPubKey(const CKeyID &address, CPubKey &pubkey_out) const;
|
||||
|
||||
/* SigningProvider overrides */
|
||||
//! HaveKey implementation that also checks the mapHdPubKeys
|
||||
bool HaveKey(const CKeyID &address) const override;
|
||||
//! GetKey implementation that can derive a HD private key on the fly
|
||||
bool GetKey(const CKeyID &address, CKey& keyOut) const override;
|
||||
//! GetPubKey implementation that also checks the mapHdPubKeys
|
||||
bool GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const override;
|
||||
bool AddCScript(const CScript& redeemScript) override;
|
||||
/** Implement lookup of key origin information through wallet key metadata. */
|
||||
bool GetKeyOrigin(const CKeyID& keyid, KeyOriginInfo& info) const override;
|
||||
/** Add a KeyOriginInfo to the wallet */
|
||||
bool AddKeyOrigin(const CPubKey& pubkey, const KeyOriginInfo& info);
|
||||
|
||||
void LoadKeyPool(int64_t nIndex, const CKeyPool &keypool) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||
bool TopUpKeyPool(unsigned int kpSize = 0);
|
||||
bool NewKeyPool();
|
||||
// Seems as not used now anywhere in code
|
||||
// void AddKeypoolPubkey(const CPubKey& pubkey, const bool internal);
|
||||
|
||||
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::set<CScript>& script_pub_keys, const bool have_solving_data, const int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||
|
||||
/* Returns true if the wallet can generate new keys */
|
||||
bool CanGenerateKeys();
|
||||
|
||||
//! Adds a HDPubKey into the wallet(database)
|
||||
bool AddHDPubKey(WalletBatch &batch, const CExtPubKey &extPubKey, bool fInternal);
|
||||
//! loads a HDPubKey into the wallets memory
|
||||
bool LoadHDPubKey(const CHDPubKey &hdPubKey) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||
|
||||
/**
|
||||
* HD Wallet Functions
|
||||
@ -309,29 +386,10 @@ public:
|
||||
bool SetCryptedHDChain(const CHDChain& chain);
|
||||
bool GetDecryptedHDChain(CHDChain& hdChainRet);
|
||||
|
||||
/* 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 chain */
|
||||
void GenerateNewHDChain(const SecureString& secureMnemonic, const SecureString& secureMnemonicPassphrase);
|
||||
bool GenerateNewHDChainEncrypted(const SecureString& secureMnemonic, const SecureString& secureMnemonicPassphrase, const SecureString& secureWalletPassphrase);
|
||||
|
||||
/* Set the HD chain model (chain child index counters) */
|
||||
bool SetHDChain(WalletBatch &batch, const CHDChain& chain, bool memonly);
|
||||
bool SetCryptedHDChain(WalletBatch &batch, const CHDChain& chain, bool memonly);
|
||||
/**
|
||||
* Set the HD chain model (chain child index counters) using temporary wallet db object
|
||||
* which causes db flush every time these methods are used
|
||||
*/
|
||||
bool SetHDChainSingle(const CHDChain& chain, bool memonly);
|
||||
bool SetCryptedHDChainSingle(const CHDChain& chain, bool memonly);
|
||||
|
||||
/**
|
||||
* 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
|
||||
@ -346,13 +404,13 @@ public:
|
||||
*/
|
||||
// void LearnAllRelatedScripts(const CPubKey& key);
|
||||
|
||||
/** Implement lookup of key origin information through wallet key metadata. */
|
||||
bool GetKeyOrigin(const CKeyID& keyid, KeyOriginInfo& info) const override;
|
||||
/**
|
||||
* 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 std::string label, CTxDestination& dest, std::string& error);
|
||||
|
||||
/** Add a KeyOriginInfo to the wallet */
|
||||
bool AddKeyOrigin(const CPubKey& pubkey, const KeyOriginInfo& info);
|
||||
std::set<CKeyID> GetKeys() const override;
|
||||
|
||||
// Temporary CWallet accessors and aliases.
|
||||
friend class CWallet;
|
||||
|
@ -337,8 +337,6 @@ std::string COutput::ToString() const
|
||||
return strprintf("COutput(%s, %d, %d) [%s]", tx->GetHash().ToString(), i, nDepth, FormatMoney(tx->tx->vout[i].nValue));
|
||||
}
|
||||
|
||||
std::vector<CKeyID> GetAffectedKeys(const CScript& spk, const SigningProvider& provider);
|
||||
|
||||
const CWalletTx* CWallet::GetWalletTx(const uint256& hash) const
|
||||
{
|
||||
LOCK(cs_wallet);
|
||||
@ -350,10 +348,15 @@ const CWalletTx* CWallet::GetWalletTx(const uint256& hash) const
|
||||
|
||||
void CWallet::UpgradeKeyMetadata()
|
||||
{
|
||||
if (IsLocked() || IsWalletFlagSet(WALLET_FLAG_KEY_ORIGIN_METADATA)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_spk_man) {
|
||||
AssertLockHeld(m_spk_man->cs_wallet);
|
||||
m_spk_man->UpgradeKeyMetadata();
|
||||
}
|
||||
SetWalletFlag(WALLET_FLAG_KEY_ORIGIN_METADATA);
|
||||
}
|
||||
|
||||
bool CWallet::ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, const SecureString& strNewWalletPassphrase)
|
||||
@ -975,33 +978,8 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransactionRef& ptx, CWalletTx::Co
|
||||
WalletBatch batch(*database);
|
||||
// loop though all outputs
|
||||
for (const CTxOut& txout: tx.vout) {
|
||||
// extract addresses, check if they match with an unused keypool key, update metadata if needed
|
||||
if (m_spk_man == nullptr) continue;
|
||||
AssertLockHeld(m_spk_man->cs_wallet);
|
||||
for (const auto& keyid : GetAffectedKeys(txout.scriptPubKey, *m_spk_man)) {
|
||||
std::map<CKeyID, int64_t>::const_iterator mi = 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 (!m_spk_man->TopUpKeyPool()) {
|
||||
WalletLogPrintf("%s: Topping up keypool failed (locked wallet)\n", __func__);
|
||||
}
|
||||
}
|
||||
if (!confirm.hashBlock.IsNull()) {
|
||||
int64_t block_time;
|
||||
bool found_block = chain().findBlock(confirm.hashBlock, nullptr /* block */, &block_time);
|
||||
assert(found_block);
|
||||
if (mapKeyMetadata[keyid].nCreateTime > block_time) {
|
||||
WalletLogPrintf("%s: Found a key which appears to be used earlier than we expected, updating metadata\n", __func__);
|
||||
CPubKey vchPubKey;
|
||||
bool res = m_spk_man->GetPubKey(keyid, vchPubKey);
|
||||
assert(res); // this should never fail
|
||||
mapKeyMetadata[keyid].nCreateTime = block_time;
|
||||
batch.WriteKeyMetadata(mapKeyMetadata[keyid], vchPubKey, true);
|
||||
m_spk_man->UpdateTimeFirstKey(block_time);
|
||||
}
|
||||
}
|
||||
if (auto spk_man = m_spk_man.get()) {
|
||||
spk_man->MarkUnusedAddresses(batch, txout.scriptPubKey, confirm.hashBlock);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1581,10 +1559,10 @@ void CWallet::UnsetWalletFlag(uint64_t flag)
|
||||
{
|
||||
LOCK(cs_wallet);
|
||||
WalletBatch batch(*database);
|
||||
UnsetWalletFlag(batch, flag);
|
||||
UnsetWalletFlagWithDB(batch, flag);
|
||||
}
|
||||
|
||||
void CWallet::UnsetWalletFlag(WalletBatch& batch, uint64_t flag)
|
||||
void CWallet::UnsetWalletFlagWithDB(WalletBatch& batch, uint64_t flag)
|
||||
{
|
||||
LOCK(cs_wallet);
|
||||
m_wallet_flags &= ~flag;
|
||||
@ -1592,6 +1570,11 @@ void CWallet::UnsetWalletFlag(WalletBatch& batch, uint64_t flag)
|
||||
throw std::runtime_error(std::string(__func__) + ": writing wallet flags failed");
|
||||
}
|
||||
|
||||
void CWallet::UnsetBlankWalletFlag(WalletBatch& batch)
|
||||
{
|
||||
UnsetWalletFlagWithDB(batch, WALLET_FLAG_BLANK_WALLET);
|
||||
}
|
||||
|
||||
bool CWallet::IsWalletFlagSet(uint64_t flag) const
|
||||
{
|
||||
return (m_wallet_flags & flag);
|
||||
@ -1688,9 +1671,19 @@ bool CWallet::ImportScriptPubKeys(const std::string& label, const std::set<CScri
|
||||
return false;
|
||||
}
|
||||
AssertLockHeld(spk_man->cs_wallet);
|
||||
if (!spk_man->ImportScriptPubKeys(label, script_pub_keys, have_solving_data, apply_label, timestamp)) {
|
||||
if (!spk_man->ImportScriptPubKeys(script_pub_keys, have_solving_data, timestamp)) {
|
||||
return false;
|
||||
}
|
||||
if (apply_label) {
|
||||
WalletBatch batch(*database);
|
||||
for (const CScript& script : script_pub_keys) {
|
||||
CTxDestination dest;
|
||||
ExtractDestination(script, dest);
|
||||
if (IsValidDestination(dest)) {
|
||||
SetAddressBookWithDB(batch, dest, label, "receive");
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -3574,13 +3567,10 @@ DBErrors CWallet::LoadWallet(bool& fFirstRunRet)
|
||||
{
|
||||
if (database->Rewrite("\x04pool"))
|
||||
{
|
||||
setInternalKeyPool.clear();
|
||||
setExternalKeyPool.clear();
|
||||
if (auto spk_man = m_spk_man.get()) {
|
||||
spk_man->RewriteDB();
|
||||
}
|
||||
nKeysLeftSinceAutoBackup = 0;
|
||||
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.
|
||||
}
|
||||
}
|
||||
|
||||
@ -3645,12 +3635,9 @@ DBErrors CWallet::ZapSelectTx(std::vector<uint256>& vHashIn, std::vector<uint256
|
||||
{
|
||||
if (database->Rewrite("\x04pool"))
|
||||
{
|
||||
setInternalKeyPool.clear();
|
||||
setExternalKeyPool.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.
|
||||
if (auto spk_man = m_spk_man.get()) {
|
||||
spk_man->RewriteDB();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -3732,30 +3719,47 @@ size_t CWallet::KeypoolCountInternalKeys()
|
||||
return count;
|
||||
}
|
||||
|
||||
unsigned int CWallet::GetKeyPoolSize() const
|
||||
{
|
||||
AssertLockHeld(cs_wallet);
|
||||
|
||||
unsigned int count = 0;
|
||||
if (auto spk_man = m_spk_man.get()) {
|
||||
count += spk_man->GetKeyPoolSize();
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
bool CWallet::TopUpKeyPool(unsigned int kpSize)
|
||||
{
|
||||
bool res = true;
|
||||
if (auto spk_man = m_spk_man.get()) {
|
||||
res &= spk_man->TopUpKeyPool(kpSize);
|
||||
res &= spk_man->TopUp(kpSize);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
bool CWallet::GetNewDestination(const std::string label, CTxDestination& dest, std::string& error)
|
||||
{
|
||||
LOCK(cs_wallet);
|
||||
error.clear();
|
||||
bool result = false;
|
||||
auto spk_man = m_spk_man.get();
|
||||
if (spk_man) {
|
||||
result = spk_man->GetNewDestination(label, dest, error);
|
||||
result = spk_man->GetNewDestination(dest, error);
|
||||
}
|
||||
if (result) {
|
||||
SetAddressBook(dest, label, "receive");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool CWallet::GetNewChangeDestination(CTxDestination& dest, std::string& error)
|
||||
{
|
||||
error.clear();
|
||||
m_spk_man->TopUpKeyPool();
|
||||
|
||||
m_spk_man->TopUp();
|
||||
|
||||
ReserveDestination reservedest(this);
|
||||
if (!reservedest.GetReservedDestination(dest, true)) {
|
||||
@ -3928,7 +3932,7 @@ bool ReserveDestination::GetReservedDestination(CTxDestination& dest, bool fInte
|
||||
if (nIndex == -1)
|
||||
{
|
||||
CKeyPool keypool;
|
||||
if (!m_spk_man->ReserveKeyFromKeyPool(nIndex, keypool, fInternalIn)) {
|
||||
if (!m_spk_man->GetReservedDestination(fInternalIn, nIndex, keypool)) {
|
||||
return false;
|
||||
}
|
||||
vchPubKey = keypool.vchPubKey;
|
||||
@ -3943,7 +3947,7 @@ bool ReserveDestination::GetReservedDestination(CTxDestination& dest, bool fInte
|
||||
void ReserveDestination::KeepDestination()
|
||||
{
|
||||
if (nIndex != -1) {
|
||||
m_spk_man->KeepKey(nIndex);
|
||||
m_spk_man->KeepDestination(nIndex);
|
||||
}
|
||||
nIndex = -1;
|
||||
vchPubKey = CPubKey();
|
||||
@ -3953,7 +3957,7 @@ void ReserveDestination::KeepDestination()
|
||||
void ReserveDestination::ReturnDestination()
|
||||
{
|
||||
if (nIndex != -1) {
|
||||
m_spk_man->ReturnKey(nIndex, fInternal, vchPubKey);
|
||||
m_spk_man->ReturnDestination(nIndex, fInternal, vchPubKey);
|
||||
}
|
||||
nIndex = -1;
|
||||
vchPubKey = CPubKey();
|
||||
@ -4341,7 +4345,7 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain,
|
||||
} // Otherwise, do not create a new HD chain
|
||||
|
||||
// Top up the keypool
|
||||
if (walletInstance->m_spk_man->CanGenerateKeys() && !walletInstance->TopUpKeyPool()) {
|
||||
if (walletInstance->m_spk_man->CanGenerateKeys() && !walletInstance->m_spk_man->TopUp()) {
|
||||
return unload_wallet(_("Unable to generate initial keys"));
|
||||
}
|
||||
|
||||
@ -4359,9 +4363,10 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain,
|
||||
error = strprintf(_("Error loading %s: Private keys can only be disabled during creation"), walletFile);
|
||||
return NULL;
|
||||
} else if (walletInstance->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
|
||||
LOCK(walletInstance->cs_KeyStore);
|
||||
if (!walletInstance->mapKeys.empty() || !walletInstance->mapCryptedKeys.empty()) {
|
||||
warnings.push_back(strprintf(_("Warning: Private keys detected in wallet {%s} with disabled private keys"), walletFile));
|
||||
if (walletInstance->m_spk_man) {
|
||||
if (walletInstance->m_spk_man->HavePrivateKeys()) {
|
||||
warnings.push_back(strprintf(_("Warning: Private keys detected in wallet {%s} with disabled private keys"), walletFile));
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (gArgs.IsArgSet("-usehd")) {
|
||||
@ -4526,8 +4531,14 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain,
|
||||
// our wallet birthday (as adjusted for block time variability)
|
||||
// unless a full rescan was requested
|
||||
if (gArgs.GetArg("-rescan", 0) != 2) {
|
||||
if (walletInstance->nTimeFirstKey) {
|
||||
if (Optional<int> first_block = chain.findFirstBlockWithTimeAndHeight(walletInstance->nTimeFirstKey - TIMESTAMP_WINDOW, rescan_height, nullptr)) {
|
||||
Optional<int64_t> time_first_key;
|
||||
if (auto spk_man = walletInstance->m_spk_man.get()) {
|
||||
LOCK(spk_man->cs_wallet);
|
||||
int64_t time = spk_man->GetTimeFirstKey();
|
||||
if (!time_first_key || time < *time_first_key) time_first_key = time;
|
||||
}
|
||||
if (time_first_key) {
|
||||
if (Optional<int> first_block = chain.findFirstBlockWithTimeAndHeight(*time_first_key - TIMESTAMP_WINDOW, rescan_height, nullptr)) {
|
||||
rescan_height = *first_block;
|
||||
}
|
||||
}
|
||||
@ -4557,7 +4568,10 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain,
|
||||
walletInstance->WalletLogPrintf("setInternalKeyPool.size() = %u\n", walletInstance->KeypoolCountInternalKeys());
|
||||
walletInstance->WalletLogPrintf("mapWallet.size() = %u\n", walletInstance->mapWallet.size());
|
||||
walletInstance->WalletLogPrintf("mapAddressBook.size() = %u\n", walletInstance->mapAddressBook.size());
|
||||
walletInstance->WalletLogPrintf("nTimeFirstKey = %u\n", walletInstance->nTimeFirstKey);
|
||||
if (auto spk_man = walletInstance->m_spk_man.get()) {
|
||||
LOCK(spk_man->cs_wallet);
|
||||
walletInstance->WalletLogPrintf("nTimeFirstKey = %u\n", spk_man->GetTimeFirstKey());
|
||||
}
|
||||
}
|
||||
|
||||
return walletInstance;
|
||||
|
@ -730,6 +730,14 @@ private:
|
||||
|
||||
std::atomic<uint64_t> m_wallet_flags{0};
|
||||
|
||||
bool SetAddressBookWithDB(WalletBatch& batch, const CTxDestination& address, const std::string& strName, const std::string& strPurpose);
|
||||
|
||||
//! Unsets a wallet flag and saves it to disk
|
||||
void UnsetWalletFlagWithDB(WalletBatch& batch, uint64_t flag);
|
||||
|
||||
//! Unset the blank wallet flag and saves it to disk
|
||||
void UnsetBlankWalletFlag(WalletBatch& batch) override;
|
||||
|
||||
/** Interface for accessing chain state. */
|
||||
interfaces::Chain* m_chain;
|
||||
|
||||
@ -1096,16 +1104,11 @@ public:
|
||||
void AutoLockMasternodeCollaterals();
|
||||
DBErrors ZapSelectTx(std::vector<uint256>& vHashIn, std::vector<uint256>& vHashOut) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||
|
||||
bool SetAddressBookWithDB(WalletBatch& batch, const CTxDestination& address, const std::string& strName, const std::string& strPurpose);
|
||||
bool SetAddressBook(const CTxDestination& address, const std::string& strName, const std::string& purpose);
|
||||
|
||||
bool DelAddressBook(const CTxDestination& address);
|
||||
|
||||
unsigned int GetKeyPoolSize() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
|
||||
{
|
||||
AssertLockHeld(cs_wallet);
|
||||
return setInternalKeyPool.size() + setExternalKeyPool.size();
|
||||
}
|
||||
unsigned int GetKeyPoolSize() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||
|
||||
//! 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) override;
|
||||
@ -1229,11 +1232,10 @@ public:
|
||||
void BlockUntilSyncedToCurrentChain() LOCKS_EXCLUDED(cs_main, cs_wallet);
|
||||
|
||||
/** set a single wallet flag */
|
||||
void SetWalletFlag(uint64_t flags) override;
|
||||
void SetWalletFlag(uint64_t flags);
|
||||
|
||||
/** Unsets a single wallet flag */
|
||||
void UnsetWalletFlag(uint64_t flag);
|
||||
void UnsetWalletFlag(WalletBatch& batch, uint64_t flag);
|
||||
|
||||
/** check if a certain wallet flag is set */
|
||||
bool IsWalletFlagSet(uint64_t flag) const override;
|
||||
@ -1284,12 +1286,6 @@ public:
|
||||
LegacyScriptPubKeyMan::WatchKeyMap& mapWatchKeys GUARDED_BY(cs_KeyStore) = m_spk_man->mapWatchKeys;
|
||||
LegacyScriptPubKeyMan::HDPubKeyMap& mapHdPubKeys GUARDED_BY(cs_KeyStore) = m_spk_man->mapHdPubKeys;
|
||||
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 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;
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user