Skip to content

Commit

Permalink
bug
Browse files Browse the repository at this point in the history
  • Loading branch information
Eunovo committed Oct 2, 2024
1 parent a64be0e commit bf4731e
Show file tree
Hide file tree
Showing 6 changed files with 21 additions and 63 deletions.
16 changes: 4 additions & 12 deletions src/wallet/scriptpubkeyman.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2914,7 +2914,7 @@ isminetype SilentPaymentDescriptorScriptPubKeyMan::IsMine(const CScript& script)
return ISMINE_NO;
}

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

std::optional<CTxDestination> SilentPaymentDescriptorScriptPubKeyMan::GetLabelledSPDestination(const CTxDestination& dest, BIP352::PubTweakData& public_data)
std::optional<CTxDestination> SilentPaymentDescriptorScriptPubKeyMan::GetLabelledSPDestination(const XOnlyPubKey xonlypubkey, const CPubKey label)
{
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;

auto it = m_map_label_tweaks.find(*label);
auto it = m_map_label_tweaks.find(label);
if (it == m_map_label_tweaks.end()) return std::nullopt;
auto label_tweak = it->second;
CPubKey tweaked_pubkey(sppubkey->spendKey.begin(), sppubkey->spendKey.end());
Expand Down
4 changes: 2 additions & 2 deletions src/wallet/scriptpubkeyman.h
Original file line number Diff line number Diff line change
Expand Up @@ -734,7 +734,7 @@ class SilentPaymentDescriptorScriptPubKeyMan : public DescriptorScriptPubKeyMan
bool CanGetAddresses(bool internal) const override { return true; }

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

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

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

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

/** struct containing information needed for migrating legacy wallets to descriptor wallets */
Expand Down
3 changes: 2 additions & 1 deletion src/wallet/spend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1527,9 +1527,10 @@ static util::Result<CreatedTransactionResult> CreateTransactionInternal(
spent_coins[utxo->outpoint] = Coin{utxo->txout, 0, tx->IsCoinBase()};
}
auto sp_data = GetSilentPaymentsData(*tx, spent_coins);
std::map<XOnlyPubKey, std::optional<CPubKey>> found_outputs;
if (sp_data.has_value()) {
for (SilentPaymentDescriptorScriptPubKeyMan* sp_spkm : wallet.GetSilentPaymentsSPKMs()) {
sp_spkm->IsMine(sp_data->first, sp_data->second);
sp_spkm->IsMine(sp_data->first, sp_data->second, found_outputs);
}
}
}
Expand Down
40 changes: 0 additions & 40 deletions src/wallet/test/scriptpubkeyman_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,45 +48,5 @@ BOOST_AUTO_TEST_CASE(CanProvide)
BOOST_CHECK(keyman.CanProvide(p2sh_script, data));
}

// Test SilentPaymentDescriptorScriptPubKeyMan::GetLabelledSPDestination
// returns the correct label for the given Taproot spk
BOOST_AUTO_TEST_CASE(GetLabelledSPDestination)
{
CWallet wallet(m_node.chain.get(), "", CreateMockableWalletDatabase());
wallet.SetWalletFlag(WALLET_FLAG_DESCRIPTORS);
wallet.SetWalletFlag(WALLET_FLAG_SILENT_PAYMENTS);
{
LOCK(wallet.cs_wallet);
wallet.SetupDescriptorScriptPubKeyMans();
}
SilentPaymentDescriptorScriptPubKeyMan* sp_spk_man = *wallet.GetSilentPaymentsSPKMs().begin();
uint64_t index;
auto labelled_dest = sp_spk_man->GetNewLabelledDestination(index);

CKey private_key = GenerateRandomKey();
CPubKey pubkey = private_key.GetPubKey();
COutPoint prevout(Txid::FromUint256(*uint256::FromHex("daec98e9311f843277e8c59f9dccb42efd4d40881bff215ae82e5724fa754c50")), 0);
WitnessV0KeyHash p2wpkh(pubkey);
CScript scriptPubKey = GetScriptForDestination(p2wpkh);
CScript scriptSig;
auto sp_dest = std::get_if<V0SilentPaymentDestination>(&labelled_dest.value());
auto destinations = BIP352::GenerateSilentPaymentTaprootDestinations(
std::map<size_t, V0SilentPaymentDestination>{{0, *sp_dest}},
std::vector{private_key},
std::vector<KeyPair>(),
prevout
);
auto taproot_dest = destinations.value()[0];

CTxIn tx_in(prevout, scriptSig);
tx_in.scriptWitness.stack.push_back(std::vector<unsigned char>(pubkey.begin(), pubkey.end()));
auto public_data = BIP352::GetSilentPaymentsPublicData(
std::vector{tx_in},
std::map<COutPoint, Coin>{{prevout, Coin(CTxOut(10000, scriptPubKey), 1, false)}}
);
auto retrieved_labelled_dest = sp_spk_man->GetLabelledSPDestination(taproot_dest, *public_data);
BOOST_CHECK(*labelled_dest == *retrieved_labelled_dest);
}

BOOST_AUTO_TEST_SUITE_END()
} // namespace wallet
19 changes: 12 additions & 7 deletions src/wallet/wallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1242,8 +1242,8 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransactionRef& ptx, const std::ma
bool fExisted = mapWallet.count(tx.GetHash()) != 0;
if (fExisted && !fUpdate) return false;

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

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);
const WitnessV1Taproot* xonlypubkey = std::get_if<WitnessV1Taproot>(&dest);
if (sp_spk_man == nullptr || !isMineSilentPayment || xonlypubkey == nullptr) continue;

auto it = silent_payment_outputs.find(*xonlypubkey);
if (it == silent_payment_outputs.end() || !it->second.has_value()) continue;

auto parent_dest = sp_spk_man->GetLabelledSPDestination(*xonlypubkey, it->second.value());
if (!parent_dest.has_value()) continue;
auto parent_addr_data = FindAddressBookEntry(parent_dest.value());
if (parent_addr_data) {
Expand Down Expand Up @@ -1684,11 +1688,12 @@ bool CWallet::IsMine(const CTransaction& tx) const
}


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

auto sp_data = GetSilentPaymentsData(tx, spent_coins);
for (SilentPaymentDescriptorScriptPubKeyMan* sp_spkm : GetSilentPaymentsSPKMs()) {
if (sp_spkm->IsMine(output_keys, public_data)) {
if (sp_spkm->IsMine(sp_data->first, sp_data->second, found_outputs)) {
return true;
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/wallet/wallet.h
Original file line number Diff line number Diff line change
Expand Up @@ -788,7 +788,7 @@ class CWallet final : public WalletStorage, public interfaces::Chain::Notificati
isminetype IsMine(const CTxOut& txout) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
bool IsMine(const CTransaction& tx) const 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);
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);
/** 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 bf4731e

Please sign in to comment.