Merge bbc9e4133c into merged_master (Bitcoin PR #17304)

This commit is contained in:
Andrew Poelstra 2020-11-09 21:20:51 +00:00
commit 84bc0faf8f
5 changed files with 419 additions and 232 deletions

View file

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