Skip to content

Commit

Permalink
Add LoadDescriptorScriptPubKeyMan and SetActiveScriptPubKeyMan to CWa…
Browse files Browse the repository at this point in the history
…llet
  • Loading branch information
achow101 committed Apr 23, 2020
1 parent 78f8a92 commit db7177a
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 0 deletions.
22 changes: 22 additions & 0 deletions src/wallet/wallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
10 changes: 10 additions & 0 deletions src/wallet/wallet.h
Original file line number Diff line number Diff line change
Expand Up @@ -1234,6 +1234,16 @@ class CWallet final : public WalletStorage, public interfaces::Chain::Notificati

//! 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);
};

/**
Expand Down
38 changes: 38 additions & 0 deletions src/wallet/walletdb.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"};
Expand All @@ -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
Expand Down Expand Up @@ -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};
Expand All @@ -189,6 +198,8 @@ class CWalletScanState {
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() {
}
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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;

Expand Down
5 changes: 5 additions & 0 deletions src/wallet/walletdb.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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
Expand Down Expand Up @@ -245,6 +248,8 @@ class WalletBatch
/// 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);
Expand Down

0 comments on commit db7177a

Please sign in to comment.