Add LoadDescriptorScriptPubKeyMan and SetActiveScriptPubKeyMan to CWallet

This commit is contained in:
Andrew Chow 2019-07-08 15:41:31 -04:00
parent 78f8a92910
commit db7177af8c
4 changed files with 75 additions and 0 deletions

View file

@ -4402,3 +4402,25 @@ void CWallet::ConnectScriptPubKeyManNotifiers()
spk_man->NotifyCanGetAddressesChanged.connect(NotifyCanGetAddressesChanged);
}
}
void CWallet::LoadDescriptorScriptPubKeyMan(uint256 id, WalletDescriptor& desc)
{
auto spk_manager = std::unique_ptr<ScriptPubKeyMan>(new DescriptorScriptPubKeyMan(*this, desc));
m_spk_managers[id] = std::move(spk_manager);
}
void CWallet::SetActiveScriptPubKeyMan(uint256 id, OutputType type, bool internal, bool memonly)
{
auto& spk_mans = internal ? m_internal_spk_managers : m_external_spk_managers;
auto spk_man = m_spk_managers.at(id).get();
spk_man->SetType(type, internal);
spk_mans[type] = spk_man;
if (!memonly) {
WalletBatch batch(*database);
if (!batch.WriteActiveScriptPubKeyMan(static_cast<uint8_t>(type), id, internal)) {
throw std::runtime_error(std::string(__func__) + ": writing active ScriptPubKeyMan id failed");
}
}
NotifyCanGetAddressesChanged();
}

View file

@ -1234,6 +1234,16 @@ public:
//! Connect the signals from ScriptPubKeyMans to the signals in CWallet
void ConnectScriptPubKeyManNotifiers();
//! Instantiate a descriptor ScriptPubKeyMan from the WalletDescriptor and load it
void LoadDescriptorScriptPubKeyMan(uint256 id, WalletDescriptor& desc);
//! Sets the active ScriptPubKeyMan for the specified type and internal
//! @param[in] id The unique id for the ScriptPubKeyMan
//! @param[in] type The OutputType this ScriptPubKeyMan provides addresses for
//! @param[in] internal Whether this ScriptPubKeyMan provides change addresses
//! @param[in] memonly Whether to record this update to the database. Set to true for wallet loading, normally false when actually updating the wallet.
void SetActiveScriptPubKeyMan(uint256 id, OutputType type, bool internal, bool memonly = false);
};
/**

View file

@ -21,6 +21,8 @@
namespace DBKeys {
const std::string ACENTRY{"acentry"};
const std::string ACTIVEEXTERNALSPK{"activeexternalspk"};
const std::string ACTIVEINTERNALSPK{"activeinternalspk"};
const std::string BESTBLOCK_NOMERKLE{"bestblock_nomerkle"};
const std::string BESTBLOCK{"bestblock"};
const std::string CRYPTED_KEY{"ckey"};
@ -41,6 +43,7 @@ const std::string PURPOSE{"purpose"};
const std::string SETTINGS{"settings"};
const std::string TX{"tx"};
const std::string VERSION{"version"};
const std::string WALLETDESCRIPTOR{"walletdescriptor"};
const std::string WATCHMETA{"watchmeta"};
const std::string WATCHS{"watchs"};
} // namespace DBKeys
@ -179,6 +182,12 @@ bool WalletBatch::WriteMinVersion(int nVersion)
return WriteIC(DBKeys::MINVERSION, nVersion);
}
bool WalletBatch::WriteActiveScriptPubKeyMan(uint8_t type, const uint256& id, bool internal)
{
std::string key = internal ? DBKeys::ACTIVEINTERNALSPK : DBKeys::ACTIVEEXTERNALSPK;
return WriteIC(make_pair(key, type), id);
}
class CWalletScanState {
public:
unsigned int nKeys{0};
@ -189,6 +198,8 @@ public:
bool fIsEncrypted{false};
bool fAnyUnordered{false};
std::vector<uint256> vWalletUpgrade;
std::map<OutputType, uint256> m_active_external_spks;
std::map<OutputType, uint256> m_active_internal_spks;
CWalletScanState() {
}
@ -404,6 +415,25 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
} else if (strType == DBKeys::OLD_KEY) {
strErr = "Found unsupported 'wkey' record, try loading with version 0.18";
return false;
} else if (strType == DBKeys::ACTIVEEXTERNALSPK || strType == DBKeys::ACTIVEINTERNALSPK) {
uint8_t type;
ssKey >> type;
uint256 id;
ssValue >> id;
bool internal = strType == DBKeys::ACTIVEINTERNALSPK;
auto& spk_mans = internal ? wss.m_active_internal_spks : wss.m_active_external_spks;
if (spk_mans.count(static_cast<OutputType>(type)) > 0) {
strErr = "Multiple ScriptPubKeyMans specified for a single type";
return false;
}
spk_mans[static_cast<OutputType>(type)] = id;
} else if (strType == DBKeys::WALLETDESCRIPTOR) {
uint256 id;
ssKey >> id;
WalletDescriptor desc;
ssValue >> desc;
pwallet->LoadDescriptorScriptPubKeyMan(id, desc);
} else if (strType != DBKeys::BESTBLOCK && strType != DBKeys::BESTBLOCK_NOMERKLE &&
strType != DBKeys::MINVERSION && strType != DBKeys::ACENTRY &&
strType != DBKeys::VERSION && strType != DBKeys::SETTINGS) {
@ -497,6 +527,14 @@ DBErrors WalletBatch::LoadWallet(CWallet* pwallet)
result = DBErrors::CORRUPT;
}
// Set the active ScriptPubKeyMans
for (auto spk_man_pair : wss.m_active_external_spks) {
pwallet->SetActiveScriptPubKeyMan(spk_man_pair.second, spk_man_pair.first, /* internal */ false, /* memonly */ true);
}
for (auto spk_man_pair : wss.m_active_internal_spks) {
pwallet->SetActiveScriptPubKeyMan(spk_man_pair.second, spk_man_pair.first, /* internal */ true, /* memonly */ true);
}
if (fNoncriticalErrors && result == DBErrors::LOAD_OK)
result = DBErrors::NONCRITICAL_ERROR;

View file

@ -54,6 +54,8 @@ enum class DBErrors
namespace DBKeys {
extern const std::string ACENTRY;
extern const std::string ACTIVEEXTERNALSPK;
extern const std::string ACTIVEINTERNALSPK;
extern const std::string BESTBLOCK;
extern const std::string BESTBLOCK_NOMERKLE;
extern const std::string CRYPTED_KEY;
@ -74,6 +76,7 @@ extern const std::string PURPOSE;
extern const std::string SETTINGS;
extern const std::string TX;
extern const std::string VERSION;
extern const std::string WALLETDESCRIPTOR;
extern const std::string WATCHMETA;
extern const std::string WATCHS;
} // namespace DBKeys
@ -245,6 +248,8 @@ public:
/// Erase destination data tuple from wallet database
bool EraseDestData(const std::string &address, const std::string &key);
bool WriteActiveScriptPubKeyMan(uint8_t type, const uint256& id, bool internal);
DBErrors LoadWallet(CWallet* pwallet);
DBErrors FindWalletTx(std::vector<uint256>& vTxHash, std::vector<CWalletTx>& vWtx);
DBErrors ZapWalletTx(std::vector<CWalletTx>& vWtx);