mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-02-03 09:56:38 -05:00
Box the wallet: Add multiple keyman maps and loops
Add wallet logic for dealing with multiple ScriptPubKeyMan instances. This doesn't change current behavior because there is still only a single LegacyScriptPubKeyMan. But in the future the new logic will be used to support descriptor wallets.
This commit is contained in:
parent
4977c30d59
commit
c729afd0a3
4 changed files with 177 additions and 44 deletions
|
@ -470,6 +470,34 @@ int64_t LegacyScriptPubKeyMan::GetTimeFirstKey() const
|
||||||
return nTimeFirstKey;
|
return nTimeFirstKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const SigningProvider* LegacyScriptPubKeyMan::GetSigningProvider(const CScript& script) const
|
||||||
|
{
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LegacyScriptPubKeyMan::CanProvide(const CScript& script, SignatureData& sigdata)
|
||||||
|
{
|
||||||
|
if (IsMine(script) != ISMINE_NO) {
|
||||||
|
// If it IsMine, we can always provide in some way
|
||||||
|
return true;
|
||||||
|
} else if (HaveCScript(CScriptID(script))) {
|
||||||
|
// We can still provide some stuff if we have the script, but IsMine failed because we don't have keys
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
// If, given the stuff in sigdata, we could make a valid sigature, then we can provide for this script
|
||||||
|
ProduceSignature(*this, DUMMY_SIGNATURE_CREATOR, script, sigdata);
|
||||||
|
if (!sigdata.signatures.empty()) {
|
||||||
|
// If we could make signatures, make sure we have a private key to actually make a signature
|
||||||
|
bool has_privkeys = false;
|
||||||
|
for (const auto& key_sig_pair : sigdata.signatures) {
|
||||||
|
has_privkeys |= HaveKey(key_sig_pair.first);
|
||||||
|
}
|
||||||
|
return has_privkeys;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const CKeyMetadata* LegacyScriptPubKeyMan::GetMetadata(const CTxDestination& dest) const
|
const CKeyMetadata* LegacyScriptPubKeyMan::GetMetadata(const CTxDestination& dest) const
|
||||||
{
|
{
|
||||||
LOCK(cs_KeyStore);
|
LOCK(cs_KeyStore);
|
||||||
|
@ -491,6 +519,11 @@ const CKeyMetadata* LegacyScriptPubKeyMan::GetMetadata(const CTxDestination& des
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint256 LegacyScriptPubKeyMan::GetID() const
|
||||||
|
{
|
||||||
|
return UINT256_ONE();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update wallet first key creation time. This should be called whenever keys
|
* Update wallet first key creation time. This should be called whenever keys
|
||||||
* are added to the wallet, with the oldest key creation time.
|
* are added to the wallet, with the oldest key creation time.
|
||||||
|
|
|
@ -196,8 +196,16 @@ public:
|
||||||
|
|
||||||
virtual int64_t GetTimeFirstKey() const { return 0; }
|
virtual int64_t GetTimeFirstKey() const { return 0; }
|
||||||
|
|
||||||
//! Return address metadata
|
|
||||||
virtual const CKeyMetadata* GetMetadata(const CTxDestination& dest) const { return nullptr; }
|
virtual const CKeyMetadata* GetMetadata(const CTxDestination& dest) const { return nullptr; }
|
||||||
|
|
||||||
|
virtual const SigningProvider* GetSigningProvider(const CScript& script) const { return nullptr; }
|
||||||
|
|
||||||
|
/** Whether this ScriptPubKeyMan can provide a SigningProvider (via GetSigningProvider) that, combined with
|
||||||
|
* sigdata, can produce a valid signature.
|
||||||
|
*/
|
||||||
|
virtual bool CanProvide(const CScript& script, SignatureData& sigdata) { return false; }
|
||||||
|
|
||||||
|
virtual uint256 GetID() const { return uint256(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
class LegacyScriptPubKeyMan : public ScriptPubKeyMan, public FillableSigningProvider
|
class LegacyScriptPubKeyMan : public ScriptPubKeyMan, public FillableSigningProvider
|
||||||
|
@ -319,6 +327,12 @@ public:
|
||||||
|
|
||||||
bool CanGetAddresses(bool internal = false) override;
|
bool CanGetAddresses(bool internal = false) override;
|
||||||
|
|
||||||
|
const SigningProvider* GetSigningProvider(const CScript& script) const override;
|
||||||
|
|
||||||
|
bool CanProvide(const CScript& script, SignatureData& sigdata) override;
|
||||||
|
|
||||||
|
uint256 GetID() const override;
|
||||||
|
|
||||||
// Map from Key ID to key metadata.
|
// Map from Key ID to key metadata.
|
||||||
std::map<CKeyID, CKeyMetadata> mapKeyMetadata GUARDED_BY(cs_KeyStore);
|
std::map<CKeyID, CKeyMetadata> mapKeyMetadata GUARDED_BY(cs_KeyStore);
|
||||||
|
|
||||||
|
|
|
@ -220,7 +220,7 @@ WalletCreationStatus CreateWallet(interfaces::Chain& chain, const SecureString&
|
||||||
// Set a seed for the wallet
|
// Set a seed for the wallet
|
||||||
{
|
{
|
||||||
LOCK(wallet->cs_wallet);
|
LOCK(wallet->cs_wallet);
|
||||||
if (auto spk_man = wallet->m_spk_man.get()) {
|
for (auto spk_man : wallet->GetActiveScriptPubKeyMans()) {
|
||||||
if (!spk_man->SetupGeneration()) {
|
if (!spk_man->SetupGeneration()) {
|
||||||
error = "Unable to generate initial keys";
|
error = "Unable to generate initial keys";
|
||||||
return WalletCreationStatus::CREATION_FAILED;
|
return WalletCreationStatus::CREATION_FAILED;
|
||||||
|
@ -551,7 +551,8 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
|
||||||
}
|
}
|
||||||
encrypted_batch->WriteMasterKey(nMasterKeyMaxID, kMasterKey);
|
encrypted_batch->WriteMasterKey(nMasterKeyMaxID, kMasterKey);
|
||||||
|
|
||||||
if (auto spk_man = m_spk_man.get()) {
|
for (const auto& spk_man_pair : m_spk_managers) {
|
||||||
|
auto spk_man = spk_man_pair.second.get();
|
||||||
if (!spk_man->Encrypt(_vMasterKey, encrypted_batch)) {
|
if (!spk_man->Encrypt(_vMasterKey, encrypted_batch)) {
|
||||||
encrypted_batch->TxnAbort();
|
encrypted_batch->TxnAbort();
|
||||||
delete encrypted_batch;
|
delete encrypted_batch;
|
||||||
|
@ -580,7 +581,7 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
|
||||||
Unlock(strWalletPassphrase);
|
Unlock(strWalletPassphrase);
|
||||||
|
|
||||||
// if we are using HD, replace the HD seed with a new one
|
// if we are using HD, replace the HD seed with a new one
|
||||||
if (auto spk_man = m_spk_man.get()) {
|
if (auto spk_man = GetLegacyScriptPubKeyMan()) {
|
||||||
if (spk_man->IsHDEnabled()) {
|
if (spk_man->IsHDEnabled()) {
|
||||||
if (!spk_man->SetupGeneration(true)) {
|
if (!spk_man->SetupGeneration(true)) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -925,8 +926,8 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransactionRef& ptx, CWalletTx::Co
|
||||||
|
|
||||||
// loop though all outputs
|
// loop though all outputs
|
||||||
for (const CTxOut& txout: tx.vout) {
|
for (const CTxOut& txout: tx.vout) {
|
||||||
if (auto spk_man = m_spk_man.get()) {
|
for (const auto& spk_man_pair : m_spk_managers) {
|
||||||
spk_man->MarkUnusedAddresses(txout.scriptPubKey);
|
spk_man_pair.second->MarkUnusedAddresses(txout.scriptPubKey);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1197,8 +1198,8 @@ isminetype CWallet::IsMine(const CTxDestination& dest) const
|
||||||
isminetype CWallet::IsMine(const CScript& script) const
|
isminetype CWallet::IsMine(const CScript& script) const
|
||||||
{
|
{
|
||||||
isminetype result = ISMINE_NO;
|
isminetype result = ISMINE_NO;
|
||||||
if (auto spk_man = m_spk_man.get()) {
|
for (const auto& spk_man_pair : m_spk_managers) {
|
||||||
result = spk_man->IsMine(script);
|
result = std::max(result, spk_man_pair.second->IsMine(script));
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -1317,8 +1318,8 @@ CAmount CWallet::GetChange(const CTransaction& tx) const
|
||||||
bool CWallet::IsHDEnabled() const
|
bool CWallet::IsHDEnabled() const
|
||||||
{
|
{
|
||||||
bool result = true;
|
bool result = true;
|
||||||
if (auto spk_man = m_spk_man.get()) {
|
for (const auto& spk_man_pair : m_spk_managers) {
|
||||||
result &= spk_man->IsHDEnabled();
|
result &= spk_man_pair.second->IsHDEnabled();
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -1326,8 +1327,9 @@ bool CWallet::IsHDEnabled() const
|
||||||
bool CWallet::CanGetAddresses(bool internal)
|
bool CWallet::CanGetAddresses(bool internal)
|
||||||
{
|
{
|
||||||
LOCK(cs_wallet);
|
LOCK(cs_wallet);
|
||||||
{
|
if (m_spk_managers.empty()) return false;
|
||||||
auto spk_man = m_spk_man.get();
|
for (OutputType t : OUTPUT_TYPES) {
|
||||||
|
auto spk_man = GetScriptPubKeyMan(t, internal);
|
||||||
if (spk_man && spk_man->CanGetAddresses(internal)) {
|
if (spk_man && spk_man->CanGetAddresses(internal)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -2990,16 +2992,17 @@ DBErrors CWallet::LoadWallet(bool& fFirstRunRet)
|
||||||
{
|
{
|
||||||
if (database->Rewrite("\x04pool"))
|
if (database->Rewrite("\x04pool"))
|
||||||
{
|
{
|
||||||
if (auto spk_man = m_spk_man.get()) {
|
for (const auto& spk_man_pair : m_spk_managers) {
|
||||||
spk_man->RewriteDB();
|
spk_man_pair.second->RewriteDB();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// This wallet is in its first run if there are no ScriptPubKeyMans and it isn't blank or no privkeys
|
// This wallet is in its first run if there are no ScriptPubKeyMans and it isn't blank or no privkeys
|
||||||
{
|
fFirstRunRet = m_spk_managers.empty() && !IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS) && !IsWalletFlagSet(WALLET_FLAG_BLANK_WALLET);
|
||||||
fFirstRunRet = !m_spk_man
|
if (fFirstRunRet) {
|
||||||
&& !IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS) && !IsWalletFlagSet(WALLET_FLAG_BLANK_WALLET);
|
assert(m_external_spk_managers.empty());
|
||||||
|
assert(m_internal_spk_managers.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nLoadWalletRet != DBErrors::LOAD_OK)
|
if (nLoadWalletRet != DBErrors::LOAD_OK)
|
||||||
|
@ -3023,8 +3026,8 @@ DBErrors CWallet::ZapSelectTx(std::vector<uint256>& vHashIn, std::vector<uint256
|
||||||
{
|
{
|
||||||
if (database->Rewrite("\x04pool"))
|
if (database->Rewrite("\x04pool"))
|
||||||
{
|
{
|
||||||
if (auto spk_man = m_spk_man.get()) {
|
for (const auto& spk_man_pair : m_spk_managers) {
|
||||||
spk_man->RewriteDB();
|
spk_man_pair.second->RewriteDB();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3044,8 +3047,8 @@ DBErrors CWallet::ZapWalletTx(std::vector<CWalletTx>& vWtx)
|
||||||
{
|
{
|
||||||
if (database->Rewrite("\x04pool"))
|
if (database->Rewrite("\x04pool"))
|
||||||
{
|
{
|
||||||
if (auto spk_man = m_spk_man.get()) {
|
for (const auto& spk_man_pair : m_spk_managers) {
|
||||||
spk_man->RewriteDB();
|
spk_man_pair.second->RewriteDB();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3105,7 +3108,7 @@ size_t CWallet::KeypoolCountExternalKeys()
|
||||||
AssertLockHeld(cs_wallet);
|
AssertLockHeld(cs_wallet);
|
||||||
|
|
||||||
unsigned int count = 0;
|
unsigned int count = 0;
|
||||||
if (auto spk_man = m_spk_man.get()) {
|
for (auto spk_man : GetActiveScriptPubKeyMans()) {
|
||||||
count += spk_man->KeypoolCountExternalKeys();
|
count += spk_man->KeypoolCountExternalKeys();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3117,7 +3120,7 @@ unsigned int CWallet::GetKeyPoolSize() const
|
||||||
AssertLockHeld(cs_wallet);
|
AssertLockHeld(cs_wallet);
|
||||||
|
|
||||||
unsigned int count = 0;
|
unsigned int count = 0;
|
||||||
if (auto spk_man = m_spk_man.get()) {
|
for (auto spk_man : GetActiveScriptPubKeyMans()) {
|
||||||
count += spk_man->GetKeyPoolSize();
|
count += spk_man->GetKeyPoolSize();
|
||||||
}
|
}
|
||||||
return count;
|
return count;
|
||||||
|
@ -3127,7 +3130,7 @@ bool CWallet::TopUpKeyPool(unsigned int kpSize)
|
||||||
{
|
{
|
||||||
LOCK(cs_wallet);
|
LOCK(cs_wallet);
|
||||||
bool res = true;
|
bool res = true;
|
||||||
if (auto spk_man = m_spk_man.get()) {
|
for (auto spk_man : GetActiveScriptPubKeyMans()) {
|
||||||
res &= spk_man->TopUp(kpSize);
|
res &= spk_man->TopUp(kpSize);
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
|
@ -3138,7 +3141,7 @@ bool CWallet::GetNewDestination(const OutputType type, const std::string label,
|
||||||
LOCK(cs_wallet);
|
LOCK(cs_wallet);
|
||||||
error.clear();
|
error.clear();
|
||||||
bool result = false;
|
bool result = false;
|
||||||
auto spk_man = m_spk_man.get();
|
auto spk_man = GetScriptPubKeyMan(type, false /* internal */);
|
||||||
if (spk_man) {
|
if (spk_man) {
|
||||||
spk_man->TopUp();
|
spk_man->TopUp();
|
||||||
result = spk_man->GetNewDestination(type, dest, error);
|
result = spk_man->GetNewDestination(type, dest, error);
|
||||||
|
@ -3169,8 +3172,8 @@ int64_t CWallet::GetOldestKeyPoolTime()
|
||||||
{
|
{
|
||||||
LOCK(cs_wallet);
|
LOCK(cs_wallet);
|
||||||
int64_t oldestKey = std::numeric_limits<int64_t>::max();
|
int64_t oldestKey = std::numeric_limits<int64_t>::max();
|
||||||
if (auto spk_man = m_spk_man.get()) {
|
for (const auto& spk_man_pair : m_spk_managers) {
|
||||||
oldestKey = spk_man->GetOldestKeyPoolTime();
|
oldestKey = std::min(oldestKey, spk_man_pair.second->GetOldestKeyPoolTime());
|
||||||
}
|
}
|
||||||
return oldestKey;
|
return oldestKey;
|
||||||
}
|
}
|
||||||
|
@ -3339,7 +3342,7 @@ std::set<CTxDestination> CWallet::GetLabelAddresses(const std::string& label) co
|
||||||
|
|
||||||
bool ReserveDestination::GetReservedDestination(CTxDestination& dest, bool internal)
|
bool ReserveDestination::GetReservedDestination(CTxDestination& dest, bool internal)
|
||||||
{
|
{
|
||||||
m_spk_man = pwallet->GetLegacyScriptPubKeyMan();
|
m_spk_man = pwallet->GetScriptPubKeyMan(type, internal);
|
||||||
if (!m_spk_man) {
|
if (!m_spk_man) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -3716,7 +3719,7 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain,
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (auto spk_man = walletInstance->m_spk_man.get()) {
|
for (auto spk_man : walletInstance->GetActiveScriptPubKeyMans()) {
|
||||||
if (!spk_man->Upgrade(prev_version, error)) {
|
if (!spk_man->Upgrade(prev_version, error)) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -3735,7 +3738,7 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain,
|
||||||
|
|
||||||
if (!(wallet_creation_flags & (WALLET_FLAG_DISABLE_PRIVATE_KEYS | WALLET_FLAG_BLANK_WALLET))) {
|
if (!(wallet_creation_flags & (WALLET_FLAG_DISABLE_PRIVATE_KEYS | WALLET_FLAG_BLANK_WALLET))) {
|
||||||
LOCK(walletInstance->cs_wallet);
|
LOCK(walletInstance->cs_wallet);
|
||||||
if (auto spk_man = walletInstance->m_spk_man.get()) {
|
for (auto spk_man : walletInstance->GetActiveScriptPubKeyMans()) {
|
||||||
if (!spk_man->SetupGeneration()) {
|
if (!spk_man->SetupGeneration()) {
|
||||||
error = _("Unable to generate initial keys").translated;
|
error = _("Unable to generate initial keys").translated;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -3750,9 +3753,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);
|
error = strprintf(_("Error loading %s: Private keys can only be disabled during creation").translated, walletFile);
|
||||||
return NULL;
|
return NULL;
|
||||||
} else if (walletInstance->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
|
} else if (walletInstance->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
|
||||||
if (walletInstance->m_spk_man) {
|
for (auto spk_man : walletInstance->GetActiveScriptPubKeyMans()) {
|
||||||
if (walletInstance->m_spk_man->HavePrivateKeys()) {
|
if (spk_man->HavePrivateKeys()) {
|
||||||
warnings.push_back(strprintf(_("Warning: Private keys detected in wallet {%s} with disabled private keys").translated, walletFile));
|
warnings.push_back(strprintf(_("Warning: Private keys detected in wallet {%s} with disabled private keys").translated, walletFile));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3906,7 +3910,7 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain,
|
||||||
// No need to read and scan block if block was created before
|
// No need to read and scan block if block was created before
|
||||||
// our wallet birthday (as adjusted for block time variability)
|
// our wallet birthday (as adjusted for block time variability)
|
||||||
Optional<int64_t> time_first_key;
|
Optional<int64_t> time_first_key;
|
||||||
if (auto spk_man = walletInstance->m_spk_man.get()) {
|
for (auto spk_man : walletInstance->GetAllScriptPubKeyMans()) {
|
||||||
int64_t time = spk_man->GetTimeFirstKey();
|
int64_t time = spk_man->GetTimeFirstKey();
|
||||||
if (!time_first_key || time < *time_first_key) time_first_key = time;
|
if (!time_first_key || time < *time_first_key) time_first_key = time;
|
||||||
}
|
}
|
||||||
|
@ -4096,8 +4100,8 @@ bool CWallet::Unlock(const CKeyingMaterial& vMasterKeyIn, bool accept_no_keys)
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
LOCK(cs_wallet);
|
LOCK(cs_wallet);
|
||||||
if (m_spk_man) {
|
for (const auto& spk_man_pair : m_spk_managers) {
|
||||||
if (!m_spk_man->CheckDecryptionKey(vMasterKeyIn, accept_no_keys)) {
|
if (!spk_man_pair.second->CheckDecryptionKey(vMasterKeyIn, accept_no_keys)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4107,24 +4111,82 @@ bool CWallet::Unlock(const CKeyingMaterial& vMasterKeyIn, bool accept_no_keys)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::set<ScriptPubKeyMan*> CWallet::GetActiveScriptPubKeyMans() const
|
||||||
|
{
|
||||||
|
std::set<ScriptPubKeyMan*> spk_mans;
|
||||||
|
for (bool internal : {false, true}) {
|
||||||
|
for (OutputType t : OUTPUT_TYPES) {
|
||||||
|
auto spk_man = GetScriptPubKeyMan(t, internal);
|
||||||
|
if (spk_man) {
|
||||||
|
spk_mans.insert(spk_man);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return spk_mans;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::set<ScriptPubKeyMan*> CWallet::GetAllScriptPubKeyMans() const
|
||||||
|
{
|
||||||
|
std::set<ScriptPubKeyMan*> spk_mans;
|
||||||
|
for (const auto& spk_man_pair : m_spk_managers) {
|
||||||
|
spk_mans.insert(spk_man_pair.second.get());
|
||||||
|
}
|
||||||
|
return spk_mans;
|
||||||
|
}
|
||||||
|
|
||||||
|
ScriptPubKeyMan* CWallet::GetScriptPubKeyMan(const OutputType& type, bool internal) const
|
||||||
|
{
|
||||||
|
const std::map<OutputType, ScriptPubKeyMan*>& spk_managers = internal ? m_internal_spk_managers : m_external_spk_managers;
|
||||||
|
std::map<OutputType, ScriptPubKeyMan*>::const_iterator it = spk_managers.find(type);
|
||||||
|
if (it == spk_managers.end()) {
|
||||||
|
WalletLogPrintf("%s scriptPubKey Manager for output type %d does not exist\n", internal ? "Internal" : "External", static_cast<int>(type));
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
|
||||||
ScriptPubKeyMan* CWallet::GetScriptPubKeyMan(const CScript& script) const
|
ScriptPubKeyMan* CWallet::GetScriptPubKeyMan(const CScript& script) const
|
||||||
{
|
{
|
||||||
return m_spk_man.get();
|
SignatureData sigdata;
|
||||||
|
for (const auto& spk_man_pair : m_spk_managers) {
|
||||||
|
if (spk_man_pair.second->CanProvide(script, sigdata)) {
|
||||||
|
return spk_man_pair.second.get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
ScriptPubKeyMan* CWallet::GetScriptPubKeyMan(const uint256& id) const
|
||||||
|
{
|
||||||
|
if (m_spk_managers.count(id) > 0) {
|
||||||
|
return m_spk_managers.at(id).get();
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
const SigningProvider* CWallet::GetSigningProvider(const CScript& script) const
|
const SigningProvider* CWallet::GetSigningProvider(const CScript& script) const
|
||||||
{
|
{
|
||||||
return m_spk_man.get();
|
SignatureData sigdata;
|
||||||
|
return GetSigningProvider(script, sigdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
const SigningProvider* CWallet::GetSigningProvider(const CScript& script, SignatureData& sigdata) const
|
const SigningProvider* CWallet::GetSigningProvider(const CScript& script, SignatureData& sigdata) const
|
||||||
{
|
{
|
||||||
return m_spk_man.get();
|
for (const auto& spk_man_pair : m_spk_managers) {
|
||||||
|
if (spk_man_pair.second->CanProvide(script, sigdata)) {
|
||||||
|
return spk_man_pair.second->GetSigningProvider(script);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
LegacyScriptPubKeyMan* CWallet::GetLegacyScriptPubKeyMan() const
|
LegacyScriptPubKeyMan* CWallet::GetLegacyScriptPubKeyMan() const
|
||||||
{
|
{
|
||||||
return m_spk_man.get();
|
// Legacy wallets only have one ScriptPubKeyMan which is a LegacyScriptPubKeyMan.
|
||||||
|
// Everything in m_internal_spk_managers and m_external_spk_managers point to the same legacyScriptPubKeyMan.
|
||||||
|
auto it = m_internal_spk_managers.find(OutputType::LEGACY);
|
||||||
|
if (it == m_internal_spk_managers.end()) return nullptr;
|
||||||
|
return dynamic_cast<LegacyScriptPubKeyMan*>(it->second);
|
||||||
}
|
}
|
||||||
|
|
||||||
LegacyScriptPubKeyMan* CWallet::GetOrCreateLegacyScriptPubKeyMan()
|
LegacyScriptPubKeyMan* CWallet::GetOrCreateLegacyScriptPubKeyMan()
|
||||||
|
@ -4135,7 +4197,16 @@ LegacyScriptPubKeyMan* CWallet::GetOrCreateLegacyScriptPubKeyMan()
|
||||||
|
|
||||||
void CWallet::SetupLegacyScriptPubKeyMan()
|
void CWallet::SetupLegacyScriptPubKeyMan()
|
||||||
{
|
{
|
||||||
if (!m_spk_man) m_spk_man = MakeUnique<LegacyScriptPubKeyMan>(*this);
|
if (!m_internal_spk_managers.empty() || !m_external_spk_managers.empty() || !m_spk_managers.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto spk_manager = std::unique_ptr<ScriptPubKeyMan>(new LegacyScriptPubKeyMan(*this));
|
||||||
|
for (const auto& type : OUTPUT_TYPES) {
|
||||||
|
m_internal_spk_managers[type] = spk_manager.get();
|
||||||
|
m_external_spk_managers[type] = spk_manager.get();
|
||||||
|
}
|
||||||
|
m_spk_managers[spk_manager->GetID()] = std::move(spk_manager);
|
||||||
}
|
}
|
||||||
|
|
||||||
const CKeyingMaterial& CWallet::GetEncryptionKey() const
|
const CKeyingMaterial& CWallet::GetEncryptionKey() const
|
||||||
|
|
|
@ -702,6 +702,13 @@ private:
|
||||||
*/
|
*/
|
||||||
int m_last_block_processed_height GUARDED_BY(cs_wallet) = -1;
|
int m_last_block_processed_height GUARDED_BY(cs_wallet) = -1;
|
||||||
|
|
||||||
|
std::map<OutputType, ScriptPubKeyMan*> m_external_spk_managers;
|
||||||
|
std::map<OutputType, ScriptPubKeyMan*> m_internal_spk_managers;
|
||||||
|
|
||||||
|
// Indexed by a unique identifier produced by each ScriptPubKeyMan using
|
||||||
|
// ScriptPubKeyMan::GetID. In many cases it will be the hash of an internal structure
|
||||||
|
std::map<uint256, std::unique_ptr<ScriptPubKeyMan>> m_spk_managers;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/*
|
/*
|
||||||
* Main wallet lock.
|
* Main wallet lock.
|
||||||
|
@ -1132,13 +1139,25 @@ public:
|
||||||
LogPrintf(("%s " + fmt).c_str(), GetDisplayName(), parameters...);
|
LogPrintf(("%s " + fmt).c_str(), GetDisplayName(), parameters...);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//! Returns all unique ScriptPubKeyMans in m_internal_spk_managers and m_external_spk_managers
|
||||||
|
std::set<ScriptPubKeyMan*> GetActiveScriptPubKeyMans() const;
|
||||||
|
|
||||||
|
//! Returns all unique ScriptPubKeyMans
|
||||||
|
std::set<ScriptPubKeyMan*> GetAllScriptPubKeyMans() const;
|
||||||
|
|
||||||
|
//! Get the ScriptPubKeyMan for the given OutputType and internal/external chain.
|
||||||
|
ScriptPubKeyMan* GetScriptPubKeyMan(const OutputType& type, bool internal) const;
|
||||||
|
|
||||||
//! Get the ScriptPubKeyMan for a script
|
//! Get the ScriptPubKeyMan for a script
|
||||||
ScriptPubKeyMan* GetScriptPubKeyMan(const CScript& script) const;
|
ScriptPubKeyMan* GetScriptPubKeyMan(const CScript& script) const;
|
||||||
|
//! Get the ScriptPubKeyMan by id
|
||||||
|
ScriptPubKeyMan* GetScriptPubKeyMan(const uint256& id) const;
|
||||||
|
|
||||||
//! Get the SigningProvider for a script
|
//! Get the SigningProvider for a script
|
||||||
const SigningProvider* GetSigningProvider(const CScript& script) const;
|
const SigningProvider* GetSigningProvider(const CScript& script) const;
|
||||||
const SigningProvider* GetSigningProvider(const CScript& script, SignatureData& sigdata) const;
|
const SigningProvider* GetSigningProvider(const CScript& script, SignatureData& sigdata) const;
|
||||||
|
|
||||||
|
//! Get the LegacyScriptPubKeyMan which is used for all types, internal, and external.
|
||||||
LegacyScriptPubKeyMan* GetLegacyScriptPubKeyMan() const;
|
LegacyScriptPubKeyMan* GetLegacyScriptPubKeyMan() const;
|
||||||
LegacyScriptPubKeyMan* GetOrCreateLegacyScriptPubKeyMan();
|
LegacyScriptPubKeyMan* GetOrCreateLegacyScriptPubKeyMan();
|
||||||
|
|
||||||
|
@ -1148,10 +1167,6 @@ public:
|
||||||
const CKeyingMaterial& GetEncryptionKey() const override;
|
const CKeyingMaterial& GetEncryptionKey() const override;
|
||||||
bool HasEncryptionKeys() const override;
|
bool HasEncryptionKeys() const override;
|
||||||
|
|
||||||
// Temporary LegacyScriptPubKeyMan accessors and aliases.
|
|
||||||
friend class LegacyScriptPubKeyMan;
|
|
||||||
std::unique_ptr<LegacyScriptPubKeyMan> m_spk_man;
|
|
||||||
|
|
||||||
/** Get last block processed height */
|
/** Get last block processed height */
|
||||||
int GetLastBlockHeight() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
|
int GetLastBlockHeight() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Reference in a new issue