Skip to content

Commit

Permalink
wallet: Add silent payment taproot scriptPubKeys to addressbook
Browse files Browse the repository at this point in the history
- Get SPLabel destination from scriptPubKey and Public Tweak Data
- Add WitnessV1Taproot destination to AddressBook with the SPLabel Destination's address book label
  • Loading branch information
Eunovo committed Sep 17, 2024
1 parent 05bd7ed commit cf66c20
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 16 deletions.
18 changes: 18 additions & 0 deletions src/wallet/scriptpubkeyman.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3033,4 +3033,22 @@ std::vector<WalletDestination> SilentPaymentDescriptorScriptPubKeyMan::MarkUnuse
return {};
}

std::optional<CTxDestination> SilentPaymentDescriptorScriptPubKeyMan::GetLabelledSPDestination(const CTxDestination& dest, BIP352::PubTweakData& public_data)
{
LOCK(cs_desc_man);

auto sppubkey = GetSpPubKeyFrom(m_wallet_descriptor.descriptor);
const WitnessV1Taproot* xonlypubkey = std::get_if<WitnessV1Taproot>(&dest);
if (xonlypubkey == nullptr) return std::nullopt;
std::vector<XOnlyPubKey> output_keys{*xonlypubkey};
auto tweaks = BIP352::ScanForSilentPaymentOutputs(sppubkey->scanKey, public_data, sppubkey->spendKey, output_keys, m_map_label_tweaks);
if (!tweaks.has_value()) return std::nullopt;
if (tweaks.value().size() == 0) return std::nullopt;
auto label = tweaks.value()[0].label;
if (!label.has_value()) return std::nullopt;

V0SilentPaymentDestination sp_dest(sppubkey->scanKey.GetPubKey(), *label);
return sp_dest;
}

} // namespace wallet
2 changes: 2 additions & 0 deletions src/wallet/scriptpubkeyman.h
Original file line number Diff line number Diff line change
Expand Up @@ -747,6 +747,8 @@ class SilentPaymentDescriptorScriptPubKeyMan : public DescriptorScriptPubKeyMan
void AddTweak(const uint256& tweak);

std::vector<WalletDestination> MarkUnusedAddresses(const CScript& script) override;

std::optional<CTxDestination> GetLabelledSPDestination(const CTxDestination& dest, BIP352::PubTweakData& public_data);
};

/** struct containing information needed for migrating legacy wallets to descriptor wallets */
Expand Down
42 changes: 27 additions & 15 deletions src/wallet/wallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1241,12 +1241,17 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransactionRef& ptx, const std::ma

bool fExisted = mapWallet.count(tx.GetHash()) != 0;
if (fExisted && !fUpdate) return false;
if (fExisted || IsMine(tx, spent_coins) || IsFromMe(tx))

auto sp_data = GetSilentPaymentsData(tx, spent_coins);
bool isMineSilentPayment = !tx.IsCoinBase() && IsMineSilentPayment(sp_data->first, sp_data->second);
if (fExisted || IsMine(tx) || isMineSilentPayment || IsFromMe(tx))
{
/* Check if any keys in the wallet keypool that were supposed to be unused
* have appeared in a new transaction. If so, remove those keys from the keypool.
* This can happen when restoring an old wallet backup that does not contain
* the mostly recently created transactions from newer versions of the wallet.
*
* Also find any labelled silent payment taproot scriptPubKeys and add them to the AddressBook
*/

// loop though all outputs
Expand All @@ -1268,6 +1273,21 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransactionRef& ptx, const std::ma
SetAddressBook(dest.dest, "", AddressPurpose::RECEIVE);
}
}

SilentPaymentDescriptorScriptPubKeyMan* sp_spk_man = dynamic_cast<SilentPaymentDescriptorScriptPubKeyMan*>(spk_man);
if (sp_spk_man == nullptr || !isMineSilentPayment) continue;

CTxDestination dest;
ExtractDestination(txout.scriptPubKey, dest);
auto parent_dest = sp_spk_man->GetLabelledSPDestination(dest, sp_data->second);
if (!parent_dest.has_value()) continue;
auto parent_addr_data = FindAddressBookEntry(parent_dest.value());
if (parent_addr_data) {
SetAddressBook(dest, parent_addr_data->GetLabel(), AddressPurpose::RECEIVE);
} else {
SetAddressBook(*parent_dest, "", AddressPurpose::RECEIVE);
SetAddressBook(dest, "", AddressPurpose::RECEIVE);
}
}
}

Expand Down Expand Up @@ -1663,24 +1683,16 @@ bool CWallet::IsMine(const CTransaction& tx) const
return false;
}

bool CWallet::IsMine(const CTransaction& tx, const std::map<COutPoint, Coin>& spent_coins)
{

bool CWallet::IsMineSilentPayment(std::vector<XOnlyPubKey> output_keys, BIP352::PubTweakData &public_data) {
AssertLockHeld(cs_wallet);
if (IsMine(tx)) return true;

// Check for silent payments too
if (IsWalletFlagSet(WALLET_FLAG_SILENT_PAYMENTS) && !tx.IsCoinBase()) {
auto sp_data = GetSilentPaymentsData(tx, spent_coins);
if (!sp_data.has_value()) {
return false;
}
for (SilentPaymentDescriptorScriptPubKeyMan* sp_spkm : GetSilentPaymentsSPKMs()) {
if (sp_spkm->IsMine(sp_data->first, sp_data->second)) {
return true;
}
for (SilentPaymentDescriptorScriptPubKeyMan* sp_spkm : GetSilentPaymentsSPKMs()) {
if (sp_spkm->IsMine(output_keys, public_data)) {
return true;
}
}

return false;
}

Expand Down
2 changes: 1 addition & 1 deletion src/wallet/wallet.h
Original file line number Diff line number Diff line change
Expand Up @@ -785,8 +785,8 @@ class CWallet final : public WalletStorage, public interfaces::Chain::Notificati
CAmount GetDebit(const CTxIn& txin, const isminefilter& filter) const;
isminetype IsMine(const CTxOut& txout) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
bool IsMine(const CTransaction& tx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
bool IsMine(const CTransaction& tx, const std::map<COutPoint, Coin>& spent_coins) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
isminetype IsMine(const COutPoint& outpoint) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
bool IsMineSilentPayment(std::vector<XOnlyPubKey> output_keys, BIP352::PubTweakData &public_data) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
/** should probably be renamed to IsRelevantToMe */
bool IsFromMe(const CTransaction& tx) const;
CAmount GetDebit(const CTransaction& tx, const isminefilter& filter) const;
Expand Down

0 comments on commit cf66c20

Please sign in to comment.