Changeset View
Changeset View
Standalone View
Standalone View
src/wallet/wallet.cpp
Show First 20 Lines • Show All 2,782 Lines • ▼ Show 20 Lines | for (size_t i = 0; i < tx.vin.size(); i++) { | ||||
input_errors[i] = "Unable to sign input, missing keys"; | input_errors[i] = "Unable to sign input, missing keys"; | ||||
continue; | continue; | ||||
} | } | ||||
} | } | ||||
// When there are no available providers for the remaining inputs, use the | // When there are no available providers for the remaining inputs, use the | ||||
// legacy provider so we can get proper error messages. | // legacy provider so we can get proper error messages. | ||||
auto legacy_spk_man = GetLegacyScriptPubKeyMan(); | auto legacy_spk_man = GetLegacyScriptPubKeyMan(); | ||||
if (legacy_spk_man->SignTransaction(tx, coins, sighash, input_errors)) { | if (legacy_spk_man && | ||||
legacy_spk_man->SignTransaction(tx, coins, sighash, input_errors)) { | |||||
return true; | return true; | ||||
} | } | ||||
return false; | return false; | ||||
} | } | ||||
TransactionError CWallet::FillPSBT(PartiallySignedTransaction &psbtx, | TransactionError CWallet::FillPSBT(PartiallySignedTransaction &psbtx, | ||||
bool &complete, SigHashType sighash_type, | bool &complete, SigHashType sighash_type, | ||||
▲ Show 20 Lines • Show All 2,122 Lines • ▼ Show 20 Lines | for (bool internal : {false, true}) { | ||||
m_spk_managers[id] = std::move(spk_manager); | m_spk_managers[id] = std::move(spk_manager); | ||||
SetActiveScriptPubKeyMan(id, t, internal); | SetActiveScriptPubKeyMan(id, t, internal); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
void CWallet::SetActiveScriptPubKeyMan(uint256 id, OutputType type, | void CWallet::SetActiveScriptPubKeyMan(uint256 id, OutputType type, | ||||
bool internal, bool memonly) { | bool internal, bool memonly) { | ||||
WalletLogPrintf( | |||||
"Setting spkMan to active: id = %s, type = %d, internal = %d\n", | |||||
id.ToString(), static_cast<int>(type), static_cast<int>(internal)); | |||||
auto &spk_mans = | auto &spk_mans = | ||||
internal ? m_internal_spk_managers : m_external_spk_managers; | internal ? m_internal_spk_managers : m_external_spk_managers; | ||||
auto spk_man = m_spk_managers.at(id).get(); | auto spk_man = m_spk_managers.at(id).get(); | ||||
spk_man->SetType(type, internal); | spk_man->SetType(type, internal); | ||||
spk_mans[type] = spk_man; | spk_mans[type] = spk_man; | ||||
if (!memonly) { | if (!memonly) { | ||||
WalletBatch batch(*database); | WalletBatch batch(*database); | ||||
Show All 10 Lines | |||||
bool CWallet::IsLegacy() const { | bool CWallet::IsLegacy() const { | ||||
if (m_internal_spk_managers.count(OutputType::LEGACY) == 0) { | if (m_internal_spk_managers.count(OutputType::LEGACY) == 0) { | ||||
return false; | return false; | ||||
} | } | ||||
auto spk_man = dynamic_cast<LegacyScriptPubKeyMan *>( | auto spk_man = dynamic_cast<LegacyScriptPubKeyMan *>( | ||||
m_internal_spk_managers.at(OutputType::LEGACY)); | m_internal_spk_managers.at(OutputType::LEGACY)); | ||||
return spk_man != nullptr; | return spk_man != nullptr; | ||||
} | } | ||||
DescriptorScriptPubKeyMan * | |||||
CWallet::GetDescriptorScriptPubKeyMan(const WalletDescriptor &desc) const { | |||||
for (auto &spk_man_pair : m_spk_managers) { | |||||
// Try to downcast to DescriptorScriptPubKeyMan then check if the | |||||
// descriptors match | |||||
DescriptorScriptPubKeyMan *spk_manager = | |||||
dynamic_cast<DescriptorScriptPubKeyMan *>( | |||||
spk_man_pair.second.get()); | |||||
if (spk_manager != nullptr && spk_manager->HasWalletDescriptor(desc)) { | |||||
return spk_manager; | |||||
} | |||||
} | |||||
return nullptr; | |||||
} | |||||
ScriptPubKeyMan * | |||||
CWallet::AddWalletDescriptor(WalletDescriptor &desc, | |||||
const FlatSigningProvider &signing_provider, | |||||
const std::string &label) { | |||||
if (!IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) { | |||||
WalletLogPrintf( | |||||
"Cannot add WalletDescriptor to a non-descriptor wallet\n"); | |||||
return nullptr; | |||||
} | |||||
LOCK(cs_wallet); | |||||
auto new_spk_man = std::unique_ptr<DescriptorScriptPubKeyMan>( | |||||
new DescriptorScriptPubKeyMan(*this, desc)); | |||||
// If we already have this descriptor, remove it from the maps but add the | |||||
// existing cache to desc | |||||
auto old_spk_man = GetDescriptorScriptPubKeyMan(desc); | |||||
if (old_spk_man) { | |||||
WalletLogPrintf("Update existing descriptor: %s\n", | |||||
desc.descriptor->ToString()); | |||||
{ | |||||
LOCK(old_spk_man->cs_desc_man); | |||||
new_spk_man->SetCache(old_spk_man->GetWalletDescriptor().cache); | |||||
} | |||||
// Remove from maps of active spkMans | |||||
auto old_spk_man_id = old_spk_man->GetID(); | |||||
for (bool internal : {false, true}) { | |||||
for (OutputType t : OUTPUT_TYPES) { | |||||
auto active_spk_man = GetScriptPubKeyMan(t, internal); | |||||
if (active_spk_man && | |||||
active_spk_man->GetID() == old_spk_man_id) { | |||||
if (internal) { | |||||
m_internal_spk_managers.erase(t); | |||||
} else { | |||||
m_external_spk_managers.erase(t); | |||||
} | |||||
break; | |||||
} | |||||
} | |||||
} | |||||
m_spk_managers.erase(old_spk_man_id); | |||||
} | |||||
// Add the private keys to the descriptor | |||||
for (const auto &entry : signing_provider.keys) { | |||||
const CKey &key = entry.second; | |||||
new_spk_man->AddDescriptorKey(key, key.GetPubKey()); | |||||
} | |||||
// Top up key pool, the manager will generate new scriptPubKeys internally | |||||
new_spk_man->TopUp(); | |||||
// Apply the label if necessary | |||||
// Note: we disable labels for ranged descriptors | |||||
if (!desc.descriptor->IsRange()) { | |||||
auto script_pub_keys = new_spk_man->GetScriptPubKeys(); | |||||
if (script_pub_keys.empty()) { | |||||
WalletLogPrintf( | |||||
"Could not generate scriptPubKeys (cache is empty)\n"); | |||||
return nullptr; | |||||
} | |||||
CTxDestination dest; | |||||
if (ExtractDestination(script_pub_keys.at(0), dest)) { | |||||
SetAddressBook(dest, label, "receive"); | |||||
} | |||||
} | |||||
// Save the descriptor to memory | |||||
auto ret = new_spk_man.get(); | |||||
m_spk_managers[new_spk_man->GetID()] = std::move(new_spk_man); | |||||
// Save the descriptor to DB | |||||
ret->WriteDescriptor(); | |||||
return ret; | |||||
} |