mirror of
https://github.com/ElementsProject/elements.git
synced 2026-08-15 12:51:00 +02:00
Merge bbc9e4133c into merged_master (Bitcoin PR #17304)
This commit is contained in:
commit
84bc0faf8f
5 changed files with 419 additions and 232 deletions
|
|
@ -4152,26 +4152,24 @@ UniValue getaddressinfo(const JSONRPCRequest& request)
|
|||
ret.pushKV("label", pwallet->mapAddressBook[dest].name);
|
||||
}
|
||||
ret.pushKV("ischange", pwallet->IsChange(scriptPubKey));
|
||||
const CKeyMetadata* meta = nullptr;
|
||||
CKeyID key_id = GetKeyForDestination(*provider, dest);
|
||||
if (!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) {
|
||||
CKeyID key_id = GetKeyForDestination(*provider, dest);
|
||||
const CKeyMetadata* meta = nullptr;
|
||||
if (!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);
|
||||
if (meta->has_key_origin) {
|
||||
ret.pushKV("hdkeypath", WriteHDKeypath(meta->key_origin.path));
|
||||
ret.pushKV("hdseedid", meta->hd_seed_id.GetHex());
|
||||
ret.pushKV("hdmasterfingerprint", HexStr(meta->key_origin.fingerprint, meta->key_origin.fingerprint + 4));
|
||||
if (meta) {
|
||||
ret.pushKV("timestamp", meta->nCreateTime);
|
||||
if (meta->has_key_origin) {
|
||||
ret.pushKV("hdkeypath", WriteHDKeypath(meta->key_origin.path));
|
||||
ret.pushKV("hdseedid", meta->hd_seed_id.GetHex());
|
||||
ret.pushKV("hdmasterfingerprint", HexStr(meta->key_origin.fingerprint, meta->key_origin.fingerprint + 4));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -11,9 +11,8 @@
|
|||
#include <wallet/scriptpubkeyman.h>
|
||||
#include <wallet/wallet.h>
|
||||
|
||||
bool LegacyScriptPubKeyMan::GetNewDestination(const OutputType type, const std::string label, CTxDestination& dest, std::string& error, bool add_blinding_key)
|
||||
bool LegacyScriptPubKeyMan::GetNewDestination(const OutputType type, CTxDestination& dest, std::string& error, bool add_blinding_key)
|
||||
{
|
||||
LOCK(cs_wallet);
|
||||
error.clear();
|
||||
TopUpKeyPool();
|
||||
|
||||
|
|
@ -30,7 +29,6 @@ bool LegacyScriptPubKeyMan::GetNewDestination(const OutputType type, const std::
|
|||
dest = GetDestinationForKey(new_key, type, blinding_pubkey);
|
||||
}
|
||||
|
||||
m_wallet.SetAddressBook(dest, label, "receive");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -275,6 +273,48 @@ bool LegacyScriptPubKeyMan::EncryptKeys(CKeyingMaterial& vMasterKeyIn)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool LegacyScriptPubKeyMan::GetReservedDestination(const OutputType type, 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(const CScript& script)
|
||||
{
|
||||
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__);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LegacyScriptPubKeyMan::UpgradeKeyMetadata()
|
||||
{
|
||||
AssertLockHeld(cs_wallet);
|
||||
|
|
@ -308,8 +348,19 @@ void LegacyScriptPubKeyMan::UpgradeKeyMetadata()
|
|||
}
|
||||
}
|
||||
}
|
||||
batch.reset(); //write before setting the flag
|
||||
m_storage.SetWalletFlag(WALLET_FLAG_KEY_ORIGIN_METADATA);
|
||||
}
|
||||
|
||||
bool LegacyScriptPubKeyMan::SetupGeneration(bool force)
|
||||
{
|
||||
if ((CanGenerateKeys() && !force) || m_storage.IsLocked()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SetHDSeed(GenerateNewSeed());
|
||||
if (!NewKeyPool()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LegacyScriptPubKeyMan::IsHDEnabled() const
|
||||
|
|
@ -334,6 +385,58 @@ bool LegacyScriptPubKeyMan::CanGetAddresses(bool internal)
|
|||
return keypool_has_keys;
|
||||
}
|
||||
|
||||
bool LegacyScriptPubKeyMan::Upgrade(int prev_version, std::string& error)
|
||||
{
|
||||
AssertLockHeld(cs_wallet);
|
||||
error = "";
|
||||
bool hd_upgrade = false;
|
||||
bool split_upgrade = false;
|
||||
if (m_storage.CanSupportFeature(FEATURE_HD) && !IsHDEnabled()) {
|
||||
WalletLogPrintf("Upgrading wallet to HD\n");
|
||||
m_storage.SetMinVersion(FEATURE_HD);
|
||||
|
||||
// generate a new master key
|
||||
CPubKey masterPubKey = GenerateNewSeed();
|
||||
SetHDSeed(masterPubKey);
|
||||
hd_upgrade = true;
|
||||
}
|
||||
// Upgrade to HD chain split if necessary
|
||||
if (m_storage.CanSupportFeature(FEATURE_HD_SPLIT)) {
|
||||
WalletLogPrintf("Upgrading wallet to use HD chain split\n");
|
||||
m_storage.SetMinVersion(FEATURE_PRE_SPLIT_KEYPOOL);
|
||||
split_upgrade = FEATURE_HD_SPLIT > prev_version;
|
||||
}
|
||||
// Mark all keys currently in the keypool as pre-split
|
||||
if (split_upgrade) {
|
||||
MarkPreSplitKeys();
|
||||
}
|
||||
// Regenerate the keypool if upgraded to HD
|
||||
if (hd_upgrade) {
|
||||
if (!TopUpKeyPool()) {
|
||||
error = _("Unable to generate keys").translated;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
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()) {
|
||||
return GetTime();
|
||||
|
|
@ -372,6 +475,33 @@ size_t LegacyScriptPubKeyMan::KeypoolCountExternalKeys()
|
|||
return setExternalKeyPool.size() + set_pre_split_keypool.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.
|
||||
|
|
@ -388,6 +518,11 @@ void LegacyScriptPubKeyMan::UpdateTimeFirstKey(int64_t nCreateTime)
|
|||
}
|
||||
}
|
||||
|
||||
bool LegacyScriptPubKeyMan::LoadKey(const CKey& key, const CPubKey &pubkey)
|
||||
{
|
||||
return AddKeyPubKeyInner(key, pubkey);
|
||||
}
|
||||
|
||||
bool LegacyScriptPubKeyMan::AddKeyPubKey(const CKey& secret, const CPubKey &pubkey)
|
||||
{
|
||||
WalletBatch batch(m_storage.GetDatabase());
|
||||
|
|
@ -430,7 +565,7 @@ bool LegacyScriptPubKeyMan::AddKeyPubKeyWithDB(WalletBatch& batch, const CKey& s
|
|||
secret.GetPrivKey(),
|
||||
mapKeyMetadata[pubkey.GetID()]);
|
||||
}
|
||||
m_storage.UnsetWalletFlagWithDB(batch, WALLET_FLAG_BLANK_WALLET);
|
||||
m_storage.UnsetBlankWalletFlag(batch);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -587,7 +722,7 @@ bool LegacyScriptPubKeyMan::AddWatchOnlyWithDB(WalletBatch &batch, const CScript
|
|||
UpdateTimeFirstKey(meta.nCreateTime);
|
||||
NotifyWatchonlyChanged(true);
|
||||
if (batch.WriteWatchOnly(dest, meta)) {
|
||||
m_storage.UnsetWalletFlagWithDB(batch, WALLET_FLAG_BLANK_WALLET);
|
||||
m_storage.UnsetBlankWalletFlag(batch);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
@ -865,7 +1000,8 @@ void LegacyScriptPubKeyMan::SetHDSeed(const CPubKey& seed)
|
|||
newHdChain.seed_id = seed.GetID();
|
||||
SetHDChain(newHdChain, false);
|
||||
NotifyCanGetAddressesChanged();
|
||||
m_wallet.UnsetWalletFlag(WALLET_FLAG_BLANK_WALLET);
|
||||
WalletBatch batch(m_storage.GetDatabase());
|
||||
m_storage.UnsetBlankWalletFlag(batch);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1144,7 +1280,7 @@ bool LegacyScriptPubKeyMan::AddCScriptWithDB(WalletBatch& batch, const CScript&
|
|||
if (!FillableSigningProvider::AddCScript(redeemScript))
|
||||
return false;
|
||||
if (batch.WriteCScript(Hash160(redeemScript), redeemScript)) {
|
||||
m_storage.UnsetWalletFlagWithDB(batch, WALLET_FLAG_BLANK_WALLET);
|
||||
m_storage.UnsetBlankWalletFlag(batch);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
@ -1239,7 +1375,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) {
|
||||
|
|
@ -1248,11 +1384,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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,8 +28,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 UnsetWalletFlagWithDB(WalletBatch&, 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() const = 0;
|
||||
|
|
@ -38,6 +37,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 one (for pre HD-split wallets) or several keypools. These
|
||||
|
|
@ -145,41 +146,68 @@ protected:
|
|||
|
||||
public:
|
||||
ScriptPubKeyMan(WalletStorage& storage) : m_storage(storage) {}
|
||||
virtual ~ScriptPubKeyMan() {};
|
||||
virtual bool GetNewDestination(const OutputType type, CTxDestination& dest, std::string& error, bool add_blinding_key) { return false; }
|
||||
virtual isminetype IsMine(const CScript& script) const { return ISMINE_NO; }
|
||||
|
||||
virtual bool GetReservedDestination(const OutputType type, 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(const CScript& script) {}
|
||||
|
||||
/** Sets up the key generation stuff, i.e. generates new HD seeds and sets them as active.
|
||||
* Returns false if already setup or setup fails, true if setup is successful
|
||||
* Set force=true to make it re-setup if already setup, used for upgrades
|
||||
*/
|
||||
virtual bool SetupGeneration(bool force = false) { return false; }
|
||||
|
||||
/* 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; }
|
||||
|
||||
/** Upgrades the wallet to the specified version */
|
||||
virtual bool Upgrade(int prev_version, std::string& error) { 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 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>;
|
||||
|
||||
//! 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);
|
||||
|
||||
bool AddCryptedKeyInner(const CPubKey &vchPubKey, const std::vector<unsigned char> &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;
|
||||
|
||||
bool AddKeyPubKeyInner(const CKey& key, const CPubKey &pubkey);
|
||||
bool AddCryptedKeyInner(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret);
|
||||
|
||||
/**
|
||||
* Private version of AddWatchOnly method which does not accept a
|
||||
* timestamp, and which will reset the wallet's nTimeFirstKey value to 1 if
|
||||
|
|
@ -192,80 +220,34 @@ private:
|
|||
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 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 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:
|
||||
/** 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;
|
||||
|
||||
/* 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;
|
||||
|
||||
//! 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<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);
|
||||
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
|
||||
|
|
@ -282,31 +264,109 @@ private:
|
|||
* 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, bool add_blinding_key);
|
||||
|
||||
isminetype IsMine(const CScript& script) const;
|
||||
public:
|
||||
bool GetNewDestination(const OutputType type, CTxDestination& dest, std::string& error, bool add_blinding_key) override;
|
||||
isminetype IsMine(const CScript& script) const override;
|
||||
|
||||
//! will encrypt previously unencrypted keys
|
||||
bool EncryptKeys(CKeyingMaterial& vMasterKeyIn);
|
||||
|
||||
bool GetReservedDestination(const OutputType type, 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(const CScript& script) override;
|
||||
|
||||
//! Upgrade stored CKeyMetadata objects to store key origin info as KeyOriginInfo
|
||||
void UpgradeKeyMetadata() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||
|
||||
bool IsHDEnabled() const override;
|
||||
|
||||
bool SetupGeneration(bool force = false) override;
|
||||
|
||||
bool Upgrade(int prev_version, std::string& error) override;
|
||||
|
||||
bool HavePrivateKeys() const override;
|
||||
|
||||
void RewriteDB() override;
|
||||
|
||||
int64_t GetOldestKeyPoolTime() override;
|
||||
size_t KeypoolCountExternalKeys() override EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||
unsigned int GetKeyPoolSize() const override;
|
||||
|
||||
int64_t GetTimeFirstKey() const override;
|
||||
|
||||
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 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);
|
||||
void LoadScriptMetadata(const CScriptID& script_id, const CKeyMetadata &metadata) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||
//! Generate a new key
|
||||
CPubKey GenerateNewKey(WalletBatch& batch, bool internal = false) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||
|
||||
/* 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;
|
||||
//! 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);
|
||||
bool AddWatchOnly(const CScript& dest, int64_t nCreateTime) 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 */
|
||||
bool HaveKey(const CKeyID &address) const override;
|
||||
bool GetKey(const CKeyID &address, CKey& keyOut) const override;
|
||||
bool GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const override;
|
||||
bool AddCScript(const CScript& redeemScript) override;
|
||||
bool GetKeyOrigin(const CKeyID& keyid, KeyOriginInfo& info) const override;
|
||||
|
||||
//! Load a keypool entry
|
||||
void LoadKeyPool(int64_t nIndex, const CKeyPool &keypool) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||
bool TopUpKeyPool(unsigned int kpSize = 0);
|
||||
bool NewKeyPool();
|
||||
void MarkPreSplitKeys() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||
|
||||
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();
|
||||
|
||||
/* 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();
|
||||
|
||||
|
|
@ -333,9 +393,13 @@ private:
|
|||
*/
|
||||
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; }
|
||||
|
||||
std::set<CKeyID> GetKeys() const override;
|
||||
// Temporary CWallet accessors and aliases.
|
||||
friend class CWallet;
|
||||
friend class ReserveDestination;
|
||||
|
|
|
|||
|
|
@ -216,9 +216,14 @@ WalletCreationStatus CreateWallet(interfaces::Chain& chain, const SecureString&
|
|||
}
|
||||
|
||||
// Set a seed for the wallet
|
||||
CPubKey master_pub_key = wallet->m_spk_man->GenerateNewSeed();
|
||||
wallet->m_spk_man->SetHDSeed(master_pub_key);
|
||||
wallet->m_spk_man->NewKeyPool();
|
||||
{
|
||||
if (auto spk_man = wallet->m_spk_man.get()) {
|
||||
if (!spk_man->SetupGeneration()) {
|
||||
error = "Unable to generate initial keys";
|
||||
return WalletCreationStatus::CREATION_FAILED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Relock the wallet
|
||||
wallet->Lock();
|
||||
|
|
@ -242,8 +247,6 @@ std::string COutput::ToString() const
|
|||
return strprintf("COutput(%s, %d, %d) [%s] [%s]", tx->GetHash().ToString(), i, nDepth, FormatMoney(tx->GetOutputValueOut(i)), tx->GetOutputAsset(i).GetHex());
|
||||
}
|
||||
|
||||
std::vector<CKeyID> GetAffectedKeys(const CScript& spk, const SigningProvider& provider);
|
||||
|
||||
const CWalletTx* CWallet::GetWalletTx(const uint256& hash) const
|
||||
{
|
||||
LOCK(cs_wallet);
|
||||
|
|
@ -255,10 +258,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::Unlock(const SecureString& strWalletPassphrase, bool accept_no_keys)
|
||||
|
|
@ -568,11 +576,11 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
|
|||
Unlock(strWalletPassphrase);
|
||||
|
||||
// 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());
|
||||
if (auto spk_man = m_spk_man.get()) {
|
||||
if (spk_man->IsHDEnabled()) {
|
||||
spk_man->SetupGeneration(true);
|
||||
}
|
||||
}
|
||||
|
||||
m_spk_man->NewKeyPool();
|
||||
Lock();
|
||||
|
||||
// Need to completely rewrite the wallet file; if we don't, bdb might keep
|
||||
|
|
@ -877,17 +885,8 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransactionRef& ptx, CWalletTx::St
|
|||
|
||||
// loop though all outputs
|
||||
for (const CTxOut& txout: tx.vout) {
|
||||
// extract addresses and check if they match with an unused keypool key
|
||||
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 (auto spk_man = m_spk_man.get()) {
|
||||
spk_man->MarkUnusedAddresses(txout.scriptPubKey);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1350,6 +1349,11 @@ void CWallet::UnsetWalletFlagWithDB(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);
|
||||
|
|
@ -1446,9 +1450,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;
|
||||
}
|
||||
|
||||
|
|
@ -3533,12 +3547,9 @@ DBErrors CWallet::LoadWallet(bool& fFirstRunRet)
|
|||
{
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3570,12 +3581,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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3594,13 +3602,9 @@ DBErrors CWallet::ZapWalletTx(std::vector<CWalletTx>& vWtx)
|
|||
{
|
||||
if (database->Rewrite("\x04pool"))
|
||||
{
|
||||
LOCK(cs_wallet);
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3667,11 +3671,22 @@ size_t CWallet::KeypoolCountExternalKeys()
|
|||
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;
|
||||
}
|
||||
|
|
@ -3694,12 +3709,17 @@ bool CWallet::GetOnlinePakKey(CPubKey& online_pubkey, std::string& error)
|
|||
|
||||
bool CWallet::GetNewDestination(const OutputType type, const std::string label, CTxDestination& dest, std::string& error, bool add_blinding_key)
|
||||
{
|
||||
LOCK(cs_wallet);
|
||||
error.clear();
|
||||
bool result = false;
|
||||
auto spk_man = m_spk_man.get();
|
||||
if (spk_man) {
|
||||
result = spk_man->GetNewDestination(type, label, dest, error, add_blinding_key);
|
||||
result = spk_man->GetNewDestination(type, dest, error, add_blinding_key);
|
||||
}
|
||||
if (result) {
|
||||
SetAddressBook(dest, label, "receive");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -3707,7 +3727,7 @@ bool CWallet::GetNewChangeDestination(const OutputType type, CTxDestination& des
|
|||
{
|
||||
error.clear();
|
||||
|
||||
m_spk_man->TopUpKeyPool();
|
||||
m_spk_man->TopUp();
|
||||
|
||||
ReserveDestination reservedest(this);
|
||||
if (!reservedest.GetReservedDestination(type, dest, true)) {
|
||||
|
|
@ -3897,7 +3917,7 @@ bool ReserveDestination::GetReservedDestination(const OutputType type, CTxDestin
|
|||
if (nIndex == -1)
|
||||
{
|
||||
CKeyPool keypool;
|
||||
if (!m_spk_man->ReserveKeyFromKeyPool(nIndex, keypool, internal)) {
|
||||
if (!m_spk_man->GetReservedDestination(type, internal, nIndex, keypool)) {
|
||||
return false;
|
||||
}
|
||||
vchPubKey = keypool.vchPubKey;
|
||||
|
|
@ -3919,7 +3939,7 @@ void ReserveDestination::SetBlindingPubKey(const OutputType type, const CPubKey&
|
|||
void ReserveDestination::KeepDestination()
|
||||
{
|
||||
if (nIndex != -1)
|
||||
m_spk_man->KeepKey(nIndex);
|
||||
m_spk_man->KeepDestination(nIndex);
|
||||
nIndex = -1;
|
||||
vchPubKey = CPubKey();
|
||||
address = CNoDestination();
|
||||
|
|
@ -3928,7 +3948,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();
|
||||
|
|
@ -4274,31 +4294,10 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
bool hd_upgrade = false;
|
||||
bool split_upgrade = false;
|
||||
if (walletInstance->CanSupportFeature(FEATURE_HD) && !walletInstance->m_spk_man->IsHDEnabled()) {
|
||||
walletInstance->WalletLogPrintf("Upgrading wallet to HD\n");
|
||||
walletInstance->SetMinVersion(FEATURE_HD);
|
||||
|
||||
// generate a new master key
|
||||
CPubKey masterPubKey = walletInstance->m_spk_man->GenerateNewSeed();
|
||||
walletInstance->m_spk_man->SetHDSeed(masterPubKey);
|
||||
hd_upgrade = true;
|
||||
}
|
||||
// Upgrade to HD chain split if necessary
|
||||
if (walletInstance->CanSupportFeature(FEATURE_HD_SPLIT)) {
|
||||
walletInstance->WalletLogPrintf("Upgrading wallet to use HD chain split\n");
|
||||
walletInstance->SetMinVersion(FEATURE_PRE_SPLIT_KEYPOOL);
|
||||
split_upgrade = FEATURE_HD_SPLIT > prev_version;
|
||||
}
|
||||
// Mark all keys currently in the keypool as pre-split
|
||||
if (split_upgrade) {
|
||||
walletInstance->MarkPreSplitKeys();
|
||||
}
|
||||
// Regenerate the keypool if upgraded to HD
|
||||
if (hd_upgrade) {
|
||||
if (!walletInstance->m_spk_man->TopUpKeyPool()) {
|
||||
error = _("Unable to generate keys").translated;
|
||||
if (auto spk_man = walletInstance->m_spk_man.get()) {
|
||||
std::string error;
|
||||
if (!spk_man->Upgrade(prev_version, error)) {
|
||||
chain.initError(error);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
|
@ -4311,15 +4310,12 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain,
|
|||
|
||||
walletInstance->SetWalletFlags(wallet_creation_flags, false);
|
||||
if (!(wallet_creation_flags & (WALLET_FLAG_DISABLE_PRIVATE_KEYS | WALLET_FLAG_BLANK_WALLET))) {
|
||||
// generate a new seed
|
||||
CPubKey seed = walletInstance->m_spk_man->GenerateNewSeed();
|
||||
walletInstance->m_spk_man->SetHDSeed(seed);
|
||||
}
|
||||
|
||||
// Top up the keypool
|
||||
if (walletInstance->m_spk_man->CanGenerateKeys() && !walletInstance->m_spk_man->TopUpKeyPool()) {
|
||||
error = _("Unable to generate initial keys").translated;
|
||||
return nullptr;
|
||||
if (auto spk_man = walletInstance->m_spk_man.get()) {
|
||||
if (!spk_man->SetupGeneration()) {
|
||||
error = _("Unable to generate initial keys").translated;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto locked_chain = chain.lock();
|
||||
|
|
@ -4329,9 +4325,10 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain,
|
|||
error = strprintf(_("Error loading %s: Private keys can only be disabled during creation").translated, 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").translated, 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").translated, walletFile));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -4481,8 +4478,13 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain,
|
|||
|
||||
// No need to read and scan block if block was created before
|
||||
// our wallet birthday (as adjusted for block time variability)
|
||||
if (walletInstance->nTimeFirstKey) {
|
||||
if (Optional<int> first_block = locked_chain->findFirstBlockWithTimeAndHeight(walletInstance->nTimeFirstKey - TIMESTAMP_WINDOW, rescan_height, nullptr)) {
|
||||
Optional<int64_t> time_first_key;
|
||||
if (auto spk_man = walletInstance->m_spk_man.get()) {
|
||||
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 = locked_chain->findFirstBlockWithTimeAndHeight(*time_first_key - TIMESTAMP_WINDOW, rescan_height, nullptr)) {
|
||||
rescan_height = *first_block;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -752,7 +752,10 @@ private:
|
|||
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) override;
|
||||
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;
|
||||
|
|
@ -1108,11 +1111,7 @@ public:
|
|||
|
||||
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;
|
||||
|
|
@ -1209,7 +1208,7 @@ 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);
|
||||
|
|
@ -1247,13 +1246,6 @@ public:
|
|||
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;
|
||||
|
||||
//
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue