src/wallet/wallet.cpp
/**
 * Find notes in the wallet filtered by payment addresses, min depth, max depth,
 * if the note is spent, if a spending key is required, and if the notes are locked.
 * These notes are decrypted and added to the output parameter vector, outEntries.
 */
Find notes in the wallet filtered by payment addresses, min depth, max depth,
if the note is spent, if a spending key is required, and if the notes are locked.
These notes are decrypted and added to the output parameter vector, outEntries.
Find notes in the wallet filtered by payment addresses min depth max depth if the note is spent if a spending key is required and if the notes are locked . These notes are decrypted and added to the output parameter vector outEntries .
void CWallet::GetFilteredNotes(
    std::vector<SproutNoteEntry>& sproutEntries,
    std::vector<SaplingNoteEntry>& saplingEntries,
    std::set<PaymentAddress>& filterAddresses,
    int minDepth,
    int maxDepth,
    bool ignoreSpent,
    bool requireSpendingKey,
    bool ignoreLocked,
    bool ignoreUnspendable)
{
    LOCK2(cs_main, cs_wallet);
    for (auto & p : mapWallet) {
        CWalletTx wtx = p.second;
        if (!CheckFinalTx(wtx) ||
            wtx.GetBlocksToMaturity() > 0 ||
            wtx.GetDepthInMainChain() < minDepth ||
            wtx.GetDepthInMainChain() > maxDepth) {
            continue;
        }
        for (auto & pair : wtx.mapSproutNoteData) {
            JSOutPoint jsop = pair.first;
            SproutNoteData nd = pair.second;
            SproutPaymentAddress pa = nd.address;
            if (!(filterAddresses.empty() || filterAddresses.count(pa))) {
                continue;
            }
            if (ignoreSpent && nd.nullifier && IsSproutSpent(*nd.nullifier)) {
                continue;
            }
            if (requireSpendingKey && !HaveSproutSpendingKey(pa)) {
                continue;
            }
            if (ignoreLocked && IsLockedNote(jsop)) {
                continue;
            }
            int i = jsop.js; 
            int j = jsop.n; 
            ZCNoteDecryption decryptor;
            if (!GetNoteDecryptor(pa, decryptor)) {
                throw std::runtime_error(strprintf("Could not find note decryptor for payment address %s", EncodePaymentAddress(pa)));
            }
            auto hSig = wtx.vJoinSplit[i].h_sig(*pzelcashParams, wtx.joinSplitPubKey);
            try {
                SproutNotePlaintext plaintext = SproutNotePlaintext::decrypt(
                        decryptor,
                        wtx.vJoinSplit[i].ciphertexts[j],
                        wtx.vJoinSplit[i].ephemeralKey,
                        hSig,
                        (unsigned char) j);
                sproutEntries.push_back(SproutNoteEntry {
                    jsop, pa, plaintext.note(pa), plaintext.memo(), wtx.GetDepthInMainChain() });
            } catch (const note_decryption_failed &err) {
                throw std::runtime_error(strprintf("Could not decrypt note for payment address %s", EncodePaymentAddress(pa)));
            } catch (const std::exception &exc) {
                throw std::runtime_error(strprintf("Error while decrypting note for payment address %s: %s", EncodePaymentAddress(pa), exc.what()));
            }
        }
        for (auto & pair : wtx.mapSaplingNoteData) {
            SaplingOutPoint op = pair.first;
            SaplingNoteData nd = pair.second;
            auto maybe_pt = SaplingNotePlaintext::decrypt(
                wtx.vShieldedOutput[op.n].encCiphertext,
                nd.ivk,
                wtx.vShieldedOutput[op.n].ephemeralKey,
                wtx.vShieldedOutput[op.n].cm);
            assert(static_cast<bool>(maybe_pt));
            auto notePt = maybe_pt.get();
            auto maybe_pa = nd.ivk.address(notePt.d);
            assert(static_cast<bool>(maybe_pa));
            auto pa = maybe_pa.get();
            if (!(filterAddresses.empty() || filterAddresses.count(pa))) {
                continue;
            }
            if (ignoreSpent && nd.nullifier && IsSaplingSpent(*nd.nullifier)) {
                continue;
            }
            if (requireSpendingKey) {
                libzelcash::SaplingIncomingViewingKey ivk;
                libzelcash::SaplingFullViewingKey fvk;
                if (!(GetSaplingIncomingViewingKey(pa, ivk) &&
                    GetSaplingFullViewingKey(ivk, fvk) &&
                    HaveSaplingSpendingKey(fvk))) {
                    continue;
                }
            }
            if (ignoreLocked && IsLockedNote(op)) {
                continue;
            }
            auto note = notePt.note(nd.ivk).get();
            saplingEntries.push_back(SaplingNoteEntry {
                op, pa, note, notePt.memo(), wtx.GetDepthInMainChain() });
        }
    }
}
void CWallet :: GetFilteredNotes ( std :: vector < SproutNoteEntry > & sproutEntries , std :: vector < SaplingNoteEntry > & saplingEntries , std :: set < PaymentAddress > & filterAddresses , int minDepth , int maxDepth , bool ignoreSpent , bool requireSpendingKey , bool ignoreLocked , bool ignoreUnspendable ) { LOCK2 ( cs_main , cs_wallet ) ; for ( auto & p : mapWallet ) { CWalletTx wtx = p . second ; if ( ! CheckFinalTx ( wtx ) || wtx . GetBlocksToMaturity ( ) > 0 || wtx . GetDepthInMainChain ( ) < minDepth || wtx . GetDepthInMainChain ( ) > maxDepth ) { continue ; } for ( auto & pair : wtx . mapSproutNoteData ) { JSOutPoint jsop = pair . first ; SproutNoteData nd = pair . second ; SproutPaymentAddress pa = nd . address ; if ( ! ( filterAddresses . empty ( ) || filterAddresses . count ( pa ) ) ) { continue ; } if ( ignoreSpent && nd . nullifier && IsSproutSpent ( * nd . nullifier ) ) { continue ; } if ( requireSpendingKey && ! HaveSproutSpendingKey ( pa ) ) { continue ; } if ( ignoreLocked && IsLockedNote ( jsop ) ) { continue ; } int i = jsop . js ; int j = jsop . n ; ZCNoteDecryption decryptor ; if ( ! GetNoteDecryptor ( pa , decryptor ) ) { throw std :: runtime_error ( strprintf ( " " , EncodePaymentAddress ( pa ) ) ) ; } auto hSig = wtx . vJoinSplit [ i ] . h_sig ( * pzelcashParams , wtx . joinSplitPubKey ) ; try { SproutNotePlaintext plaintext = SproutNotePlaintext :: decrypt ( decryptor , wtx . vJoinSplit [ i ] . ciphertexts [ j ] , wtx . vJoinSplit [ i ] . ephemeralKey , hSig , ( unsigned char ) j ) ; sproutEntries . push_back ( SproutNoteEntry { jsop , pa , plaintext . note ( pa ) , plaintext . memo ( ) , wtx . GetDepthInMainChain ( ) } ) ; } catch ( const note_decryption_failed & err ) { throw std :: runtime_error ( strprintf ( " " , EncodePaymentAddress ( pa ) ) ) ; } catch ( const std :: exception & exc ) { throw std :: runtime_error ( strprintf ( " " , EncodePaymentAddress ( pa ) , exc . what ( ) ) ) ; } } for ( auto & pair : wtx . mapSaplingNoteData ) { SaplingOutPoint op = pair . first ; SaplingNoteData nd = pair . second ; auto maybe_pt = SaplingNotePlaintext :: decrypt ( wtx . vShieldedOutput [ op . n ] . encCiphertext , nd . ivk , wtx . vShieldedOutput [ op . n ] . ephemeralKey , wtx . vShieldedOutput [ op . n ] . cm ) ; assert ( static_cast < bool > ( maybe_pt ) ) ; auto notePt = maybe_pt . get ( ) ; auto maybe_pa = nd . ivk . address ( notePt . d ) ; assert ( static_cast < bool > ( maybe_pa ) ) ; auto pa = maybe_pa . get ( ) ; if ( ! ( filterAddresses . empty ( ) || filterAddresses . count ( pa ) ) ) { continue ; } if ( ignoreSpent && nd . nullifier && IsSaplingSpent ( * nd . nullifier ) ) { continue ; } if ( requireSpendingKey ) { libzelcash :: SaplingIncomingViewingKey ivk ; libzelcash :: SaplingFullViewingKey fvk ; if ( ! ( GetSaplingIncomingViewingKey ( pa , ivk ) && GetSaplingFullViewingKey ( ivk , fvk ) && HaveSaplingSpendingKey ( fvk ) ) ) { continue ; } } if ( ignoreLocked && IsLockedNote ( op ) ) { continue ; } auto note = notePt . note ( nd . ivk ) . get ( ) ; saplingEntries . push_back ( SaplingNoteEntry { op , pa , note , notePt . memo ( ) , wtx . GetDepthInMainChain ( ) } ) ; } } }
Find notes in the wallet filtered by payment addresses, min depth, max depth,
 if the note is spent, if a spending key is required, and if the notes are locked.
Find notes in the wallet filtered by payment addresses min depth max depth if the note is spent if a spending key is required and if the notes are locked .
// Filter the transactions before checking for notes // skip notes which belong to a different payment address in the wallet // skip note which has been spent // skip notes which cannot be spent // skip locked notes // Index into CTransaction.vJoinSplit // Index into JSDescription.ciphertexts // Get cached decryptor // Note decryptors are created when the wallet is loaded, so it should always exist // determine amount of funds in the note // Couldn't decrypt with this spending key // Unexpected failure // skip notes which belong to a different payment address in the wallet // skip notes which cannot be spent // skip locked notes