Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
b90233b
MOVEONLY: Reorder LegacyScriptPubKeyMan methods
achow101 Oct 7, 2019
9967896
Refactor: Declare LegacyScriptPubKeyMan methods as virtual
achow101 Oct 7, 2019
3486f57
Refactor: Add new ScriptPubKeyMan virtual methods
achow101 Oct 7, 2019
a5f1865
Refactor: Move SetAddressBook call out of LegacyScriptPubKeyMan::GetN…
achow101 Oct 7, 2019
7df44e3
Refactor: Move SetWalletFlag out of LegacyScriptPubKeyMan::UpgradeKey…
achow101 Oct 7, 2019
19f31ba
Remove SetWalletFlag from WalletStorage
achow101 Oct 29, 2019
0b44815
Refactor: Remove UnsetWalletFlag call from LegacyScriptPubKeyMan::Set…
achow101 Oct 7, 2019
1c8a86f
refactor: Replace UnsetWalletFlagWithDB with UnsetBlankWalletFlag in …
achow101 Oct 29, 2019
7bb82e4
Refactor: Move SetAddressBookWithDB call out of LegacyScriptPubKeyMan…
achow101 Oct 7, 2019
f5b6133
Refactor: Move LoadKey LegacyScriptPubKeyMan method definition
achow101 Oct 7, 2019
12550f7
Refactor: Move GetMetadata code out of getaddressinfo
achow101 Oct 7, 2019
2509409
Refactor: Move MarkUnusedAddresses code out of CWallet::AddToWalletIf…
achow101 Oct 7, 2019
6ebf30c
Refactor: Move HavePrivateKeys code out of CWallet::CreateWalletFromFile
achow101 Oct 7, 2019
9a4c230
Refactor: Move RewriteDB code out of CWallet
achow101 Oct 7, 2019
8d8eaa6
Refactor: Move GetKeypoolSize code out of CWallet
achow101 Oct 7, 2019
084cf05
Refactor: Move nTimeFirstKey accesses out of CWallet
achow101 Oct 7, 2019
1e889f2
Re-order methods of scriptpubkeyman for easier backporting changes in…
knst Aug 18, 2022
4b8f984
Fixup for missing cs_wallet lock:
knst Aug 30, 2022
62f7d93
Fix 2 locks
UdjinM6 Aug 31, 2022
04fbaff
more of "refactor: Replace UnsetWalletFlagWithDB with UnsetBlankWalle…
UdjinM6 Aug 31, 2022
c1fbc8b
Refactoring GetOldestKeyInPool -> GetOldestKeyTimeInPool, partial bit…
knst Sep 13, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 24 additions & 27 deletions src/wallet/rpcwallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
if (!meta) {
auto it = pwallet->m_script_metadata.find(CScriptID(scriptPubKey));
if (it != pwallet->m_script_metadata.end()) {
meta = &it->second;
}
}
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());
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) {
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->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));
}
}

Expand Down
155 changes: 122 additions & 33 deletions src/wallet/scriptpubkeyman.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand All @@ -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;
}

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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)) {
Expand All @@ -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;
}
Expand All @@ -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.
Expand All @@ -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)
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand All @@ -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;
}
Expand Down
Loading