From a73c70df07025e9349cb6b0ddf59e644e6e680bc Mon Sep 17 00:00:00 2001 From: panleone Date: Fri, 7 Apr 2023 12:02:12 +0200 Subject: [PATCH] Return a vector of stakable shield notes --- src/sapling/saplingscriptpubkeyman.cpp | 44 ++++++++++++++++++++++++++ src/sapling/saplingscriptpubkeyman.h | 3 ++ 2 files changed, 47 insertions(+) diff --git a/src/sapling/saplingscriptpubkeyman.cpp b/src/sapling/saplingscriptpubkeyman.cpp index d0b9009a5e54b6..36f3243612518f 100644 --- a/src/sapling/saplingscriptpubkeyman.cpp +++ b/src/sapling/saplingscriptpubkeyman.cpp @@ -6,6 +6,7 @@ #include "sapling/saplingscriptpubkeyman.h" #include "chain.h" // for CBlockIndex +#include "saplingscriptpubkeyman.h" #include "validation.h" // for ReadBlockFromDisk() void SaplingScriptPubKeyMan::AddToSaplingSpends(const uint256& nullifier, const uint256& wtxid) @@ -540,6 +541,49 @@ void SaplingScriptPubKeyMan::GetFilteredNotes( } } } +void SaplingScriptPubKeyMan::GetStakableNotes(std::vector& shieldInputs, int minDepth) +{ + LOCK(wallet->cs_wallet); + for (auto& p : wallet->mapWallet) { + const CWalletTx& wtx = p.second; + // Filter coinbase/coinstakes transactions that don't have Sapling outputs + if ((wtx.IsCoinBase() || wtx.IsCoinStake()) && wtx.mapSaplingNoteData.empty()) { + continue; + } + // Filter the transactions before checking for notes + const int depth = wtx.GetDepthInMainChain(); + if (!IsFinalTx(wtx.tx, wallet->GetLastBlockHeight() + 1, GetAdjustedTime()) || + depth < minDepth) { + continue; + } + for (const auto& it : wtx.mapSaplingNoteData) { + const SaplingOutPoint& op = it.first; + const SaplingNoteData& nd = it.second; + + // skip sent notes + if (!nd.IsMyNote()) continue; + + // recover plaintext and address + auto optNotePtAndAddress = wtx.DecryptSaplingNote(op); + assert(static_cast(optNotePtAndAddress)); + + const libzcash::SaplingIncomingViewingKey& ivk = *(nd.ivk); + const libzcash::SaplingNotePlaintext& notePt = optNotePtAndAddress->first; + const libzcash::SaplingPaymentAddress& pa = optNotePtAndAddress->second; + auto note = notePt.note(ivk).get(); + + // skip notes which cannot be spent + if (!HaveSpendingKeyForPaymentAddress(pa)) { + continue; + } + + if (nd.nullifier && IsSaplingSpent(*nd.nullifier)) { + continue; + } + shieldInputs.emplace_back(CShieldStake(note.value(), *nd.nullifier)); + } + } +} /* Return list of available notes grouped by sapling address. */ std::map> SaplingScriptPubKeyMan::ListNotes() const diff --git a/src/sapling/saplingscriptpubkeyman.h b/src/sapling/saplingscriptpubkeyman.h index 5462e58a0ab7ab..830826da33d95f 100644 --- a/src/sapling/saplingscriptpubkeyman.h +++ b/src/sapling/saplingscriptpubkeyman.h @@ -294,6 +294,9 @@ class SaplingScriptPubKeyMan { bool requireSpendingKey=true, bool ignoreLocked=true) const; + /* Return a list of notes that are stakable */ + void GetStakableNotes(std::vector& shieldInputs, int minDepth); + /* Return list of available notes grouped by sapling address. */ std::map> ListNotes() const;