Skip to content

Commit bf4731e

Browse files
committed
bug
1 parent a64be0e commit bf4731e

6 files changed

+21
-63
lines changed

src/wallet/scriptpubkeyman.cpp

+4-12
Original file line numberDiff line numberDiff line change
@@ -2914,7 +2914,7 @@ isminetype SilentPaymentDescriptorScriptPubKeyMan::IsMine(const CScript& script)
29142914
return ISMINE_NO;
29152915
}
29162916

2917-
isminetype SilentPaymentDescriptorScriptPubKeyMan::IsMine(std::vector<XOnlyPubKey> output_keys, BIP352::PubTweakData& public_data)
2917+
isminetype SilentPaymentDescriptorScriptPubKeyMan::IsMine(std::vector<XOnlyPubKey> output_keys, BIP352::PubTweakData& public_data, std::map<XOnlyPubKey, std::optional<CPubKey>> &found_outputs)
29182918
{
29192919
LOCK(cs_desc_man);
29202920
if (m_wallet_descriptor.descriptor->GetOutputType() != OutputType::SILENT_PAYMENT) {
@@ -2933,6 +2933,7 @@ isminetype SilentPaymentDescriptorScriptPubKeyMan::IsMine(std::vector<XOnlyPubKe
29332933
throw std::runtime_error(strprintf("Error during descriptors tweak top up. Cannot start db transaction wallet %s", m_storage.GetDisplayName()));
29342934
}
29352935
for (const auto& tweak : *tweaks) {
2936+
found_outputs.emplace(std::make_pair(tweak.output, tweak.label));
29362937
if (!TopUpWithDB(batch, tweak.tweak)) {
29372938
throw std::runtime_error(std::string(__func__) + ": writing tweak failed");
29382939
}
@@ -3033,21 +3034,12 @@ std::vector<WalletDestination> SilentPaymentDescriptorScriptPubKeyMan::MarkUnuse
30333034
return {};
30343035
}
30353036

3036-
std::optional<CTxDestination> SilentPaymentDescriptorScriptPubKeyMan::GetLabelledSPDestination(const CTxDestination& dest, BIP352::PubTweakData& public_data)
3037+
std::optional<CTxDestination> SilentPaymentDescriptorScriptPubKeyMan::GetLabelledSPDestination(const XOnlyPubKey xonlypubkey, const CPubKey label)
30373038
{
30383039
LOCK(cs_desc_man);
30393040

30403041
auto sppubkey = GetSpPubKeyFrom(m_wallet_descriptor.descriptor);
3041-
const WitnessV1Taproot* xonlypubkey = std::get_if<WitnessV1Taproot>(&dest);
3042-
if (xonlypubkey == nullptr) return std::nullopt;
3043-
std::vector<XOnlyPubKey> output_keys{*xonlypubkey};
3044-
auto tweaks = BIP352::ScanForSilentPaymentOutputs(sppubkey->scanKey, public_data, sppubkey->spendKey, output_keys, m_map_label_tweaks);
3045-
if (!tweaks.has_value()) return std::nullopt;
3046-
if (tweaks.value().size() == 0) return std::nullopt;
3047-
auto label = tweaks.value()[0].label;
3048-
if (!label.has_value()) return std::nullopt;
3049-
3050-
auto it = m_map_label_tweaks.find(*label);
3042+
auto it = m_map_label_tweaks.find(label);
30513043
if (it == m_map_label_tweaks.end()) return std::nullopt;
30523044
auto label_tweak = it->second;
30533045
CPubKey tweaked_pubkey(sppubkey->spendKey.begin(), sppubkey->spendKey.end());

src/wallet/scriptpubkeyman.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -734,7 +734,7 @@ class SilentPaymentDescriptorScriptPubKeyMan : public DescriptorScriptPubKeyMan
734734
bool CanGetAddresses(bool internal) const override { return true; }
735735

736736
isminetype IsMine(const CScript& script) const override;
737-
isminetype IsMine(std::vector<XOnlyPubKey> output_keys, BIP352::PubTweakData& public_data);
737+
isminetype IsMine(std::vector<XOnlyPubKey> output_keys, BIP352::PubTweakData& public_data, std::map<XOnlyPubKey, std::optional<CPubKey>> &found_outputs);
738738

739739
using DescriptorScriptPubKeyMan::TopUp; // Make both TopUp methods available
740740
// Adds a tweak to m_map_spk_tweaks and writes to DB
@@ -748,7 +748,7 @@ class SilentPaymentDescriptorScriptPubKeyMan : public DescriptorScriptPubKeyMan
748748

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

751-
std::optional<CTxDestination> GetLabelledSPDestination(const CTxDestination& dest, BIP352::PubTweakData& public_data);
751+
std::optional<CTxDestination> GetLabelledSPDestination(const XOnlyPubKey xonlypubkey, const CPubKey label);
752752
};
753753

754754
/** struct containing information needed for migrating legacy wallets to descriptor wallets */

src/wallet/spend.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -1527,9 +1527,10 @@ static util::Result<CreatedTransactionResult> CreateTransactionInternal(
15271527
spent_coins[utxo->outpoint] = Coin{utxo->txout, 0, tx->IsCoinBase()};
15281528
}
15291529
auto sp_data = GetSilentPaymentsData(*tx, spent_coins);
1530+
std::map<XOnlyPubKey, std::optional<CPubKey>> found_outputs;
15301531
if (sp_data.has_value()) {
15311532
for (SilentPaymentDescriptorScriptPubKeyMan* sp_spkm : wallet.GetSilentPaymentsSPKMs()) {
1532-
sp_spkm->IsMine(sp_data->first, sp_data->second);
1533+
sp_spkm->IsMine(sp_data->first, sp_data->second, found_outputs);
15331534
}
15341535
}
15351536
}

src/wallet/test/scriptpubkeyman_tests.cpp

-40
Original file line numberDiff line numberDiff line change
@@ -48,45 +48,5 @@ BOOST_AUTO_TEST_CASE(CanProvide)
4848
BOOST_CHECK(keyman.CanProvide(p2sh_script, data));
4949
}
5050

51-
// Test SilentPaymentDescriptorScriptPubKeyMan::GetLabelledSPDestination
52-
// returns the correct label for the given Taproot spk
53-
BOOST_AUTO_TEST_CASE(GetLabelledSPDestination)
54-
{
55-
CWallet wallet(m_node.chain.get(), "", CreateMockableWalletDatabase());
56-
wallet.SetWalletFlag(WALLET_FLAG_DESCRIPTORS);
57-
wallet.SetWalletFlag(WALLET_FLAG_SILENT_PAYMENTS);
58-
{
59-
LOCK(wallet.cs_wallet);
60-
wallet.SetupDescriptorScriptPubKeyMans();
61-
}
62-
SilentPaymentDescriptorScriptPubKeyMan* sp_spk_man = *wallet.GetSilentPaymentsSPKMs().begin();
63-
uint64_t index;
64-
auto labelled_dest = sp_spk_man->GetNewLabelledDestination(index);
65-
66-
CKey private_key = GenerateRandomKey();
67-
CPubKey pubkey = private_key.GetPubKey();
68-
COutPoint prevout(Txid::FromUint256(*uint256::FromHex("daec98e9311f843277e8c59f9dccb42efd4d40881bff215ae82e5724fa754c50")), 0);
69-
WitnessV0KeyHash p2wpkh(pubkey);
70-
CScript scriptPubKey = GetScriptForDestination(p2wpkh);
71-
CScript scriptSig;
72-
auto sp_dest = std::get_if<V0SilentPaymentDestination>(&labelled_dest.value());
73-
auto destinations = BIP352::GenerateSilentPaymentTaprootDestinations(
74-
std::map<size_t, V0SilentPaymentDestination>{{0, *sp_dest}},
75-
std::vector{private_key},
76-
std::vector<KeyPair>(),
77-
prevout
78-
);
79-
auto taproot_dest = destinations.value()[0];
80-
81-
CTxIn tx_in(prevout, scriptSig);
82-
tx_in.scriptWitness.stack.push_back(std::vector<unsigned char>(pubkey.begin(), pubkey.end()));
83-
auto public_data = BIP352::GetSilentPaymentsPublicData(
84-
std::vector{tx_in},
85-
std::map<COutPoint, Coin>{{prevout, Coin(CTxOut(10000, scriptPubKey), 1, false)}}
86-
);
87-
auto retrieved_labelled_dest = sp_spk_man->GetLabelledSPDestination(taproot_dest, *public_data);
88-
BOOST_CHECK(*labelled_dest == *retrieved_labelled_dest);
89-
}
90-
9151
BOOST_AUTO_TEST_SUITE_END()
9252
} // namespace wallet

src/wallet/wallet.cpp

+12-7
Original file line numberDiff line numberDiff line change
@@ -1242,8 +1242,8 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransactionRef& ptx, const std::ma
12421242
bool fExisted = mapWallet.count(tx.GetHash()) != 0;
12431243
if (fExisted && !fUpdate) return false;
12441244

1245-
auto sp_data = GetSilentPaymentsData(tx, spent_coins);
1246-
bool isMineSilentPayment = !tx.IsCoinBase() && sp_data && IsMineSilentPayment(sp_data->first, sp_data->second);
1245+
std::map<XOnlyPubKey, std::optional<CPubKey>> silent_payment_outputs;
1246+
bool isMineSilentPayment = !tx.IsCoinBase() && IsMineSilentPayment(tx, spent_coins, silent_payment_outputs);
12471247
if (fExisted || IsMine(tx) || isMineSilentPayment || IsFromMe(tx))
12481248
{
12491249
/* Check if any keys in the wallet keypool that were supposed to be unused
@@ -1275,11 +1275,15 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransactionRef& ptx, const std::ma
12751275
}
12761276

12771277
SilentPaymentDescriptorScriptPubKeyMan* sp_spk_man = dynamic_cast<SilentPaymentDescriptorScriptPubKeyMan*>(spk_man);
1278-
if (sp_spk_man == nullptr || !isMineSilentPayment) continue;
1279-
12801278
CTxDestination dest;
12811279
ExtractDestination(txout.scriptPubKey, dest);
1282-
auto parent_dest = sp_spk_man->GetLabelledSPDestination(dest, sp_data->second);
1280+
const WitnessV1Taproot* xonlypubkey = std::get_if<WitnessV1Taproot>(&dest);
1281+
if (sp_spk_man == nullptr || !isMineSilentPayment || xonlypubkey == nullptr) continue;
1282+
1283+
auto it = silent_payment_outputs.find(*xonlypubkey);
1284+
if (it == silent_payment_outputs.end() || !it->second.has_value()) continue;
1285+
1286+
auto parent_dest = sp_spk_man->GetLabelledSPDestination(*xonlypubkey, it->second.value());
12831287
if (!parent_dest.has_value()) continue;
12841288
auto parent_addr_data = FindAddressBookEntry(parent_dest.value());
12851289
if (parent_addr_data) {
@@ -1684,11 +1688,12 @@ bool CWallet::IsMine(const CTransaction& tx) const
16841688
}
16851689

16861690

1687-
bool CWallet::IsMineSilentPayment(std::vector<XOnlyPubKey> output_keys, BIP352::PubTweakData &public_data) {
1691+
bool CWallet::IsMineSilentPayment(const CTransaction& tx, const std::map<COutPoint, Coin>& spent_coins, std::map<XOnlyPubKey, std::optional<CPubKey>>& found_outputs) {
16881692
AssertLockHeld(cs_wallet);
16891693

1694+
auto sp_data = GetSilentPaymentsData(tx, spent_coins);
16901695
for (SilentPaymentDescriptorScriptPubKeyMan* sp_spkm : GetSilentPaymentsSPKMs()) {
1691-
if (sp_spkm->IsMine(output_keys, public_data)) {
1696+
if (sp_spkm->IsMine(sp_data->first, sp_data->second, found_outputs)) {
16921697
return true;
16931698
}
16941699
}

src/wallet/wallet.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -788,7 +788,7 @@ class CWallet final : public WalletStorage, public interfaces::Chain::Notificati
788788
isminetype IsMine(const CTxOut& txout) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
789789
bool IsMine(const CTransaction& tx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
790790
isminetype IsMine(const COutPoint& outpoint) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
791-
bool IsMineSilentPayment(std::vector<XOnlyPubKey> output_keys, BIP352::PubTweakData &public_data) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
791+
bool IsMineSilentPayment(const CTransaction& tx, const std::map<COutPoint, Coin>& spent_coins, std::map<XOnlyPubKey, std::optional<CPubKey>>& found_outputs) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
792792
/** should probably be renamed to IsRelevantToMe */
793793
bool IsFromMe(const CTransaction& tx) const;
794794
CAmount GetDebit(const CTransaction& tx, const isminefilter& filter) const;

0 commit comments

Comments
 (0)