src/wallet/wallet.cpp
/**
 * Update mapSaplingNullifiersToNotes, computing the nullifier from a cached witness if necessary.
 */
Update mapSaplingNullifiersToNotes, computing the nullifier from a cached witness if necessary.
Update mapSaplingNullifiersToNotes computing the nullifier from a cached witness if necessary .
void CWallet::UpdateSaplingNullifierNoteMapWithTx(CWalletTx& wtx) {
    LOCK(cs_wallet);
    for (mapSaplingNoteData_t::value_type &item : wtx.mapSaplingNoteData) {
        SaplingOutPoint op = item.first;
        SaplingNoteData nd = item.second;
        if (nd.witnesses.empty()) {
            if (item.second.nullifier) {
                mapSaplingNullifiersToNotes.erase(item.second.nullifier.get());
            }
            item.second.nullifier = boost::none;
        }
        else {
            uint64_t position = nd.witnesses.front().position();
            SaplingFullViewingKey fvk = mapSaplingFullViewingKeys.at(nd.ivk);
            OutputDescription output = wtx.vShieldedOutput[op.n];
            auto optPlaintext = SaplingNotePlaintext::decrypt(output.encCiphertext, nd.ivk, output.ephemeralKey, output.cm);
            if (!optPlaintext) {
                assert(false);
            }
            auto optNote = optPlaintext.get().note(nd.ivk);
            if (!optNote) {
                assert(false);
            }
            auto optNullifier = optNote.get().nullifier(fvk, position);
            if (!optNullifier) {
                assert(false);
            }
            uint256 nullifier = optNullifier.get();
            mapSaplingNullifiersToNotes[nullifier] = op;
            item.second.nullifier = nullifier;
        }
    }
}
void CWallet :: UpdateSaplingNullifierNoteMapWithTx ( CWalletTx & wtx ) { LOCK ( cs_wallet ) ; for ( mapSaplingNoteData_t :: value_type & item : wtx . mapSaplingNoteData ) { SaplingOutPoint op = item . first ; SaplingNoteData nd = item . second ; if ( nd . witnesses . empty ( ) ) { if ( item . second . nullifier ) { mapSaplingNullifiersToNotes . erase ( item . second . nullifier . get ( ) ) ; } item . second . nullifier = boost :: none ; } else { uint64_t position = nd . witnesses . front ( ) . position ( ) ; SaplingFullViewingKey fvk = mapSaplingFullViewingKeys . at ( nd . ivk ) ; OutputDescription output = wtx . vShieldedOutput [ op . n ] ; auto optPlaintext = SaplingNotePlaintext :: decrypt ( output . encCiphertext , nd . ivk , output . ephemeralKey , output . cm ) ; if ( ! optPlaintext ) { assert ( false ) ; } auto optNote = optPlaintext . get ( ) . note ( nd . ivk ) ; if ( ! optNote ) { assert ( false ) ; } auto optNullifier = optNote . get ( ) . nullifier ( fvk , position ) ; if ( ! optNullifier ) { assert ( false ) ; } uint256 nullifier = optNullifier . get ( ) ; mapSaplingNullifiersToNotes [ nullifier ] = op ; item . second . nullifier = nullifier ; } } }
Update mapSaplingNullifiersToNotes, computing the nullifier from a cached witness if necessary.
Update mapSaplingNullifiersToNotes computing the nullifier from a cached witness if necessary .
// If there are no witnesses, erase the nullifier and associated mapping. // An item in mapSaplingNoteData must have already been successfully decrypted, // otherwise the item would not exist in the first place. // This should not happen.  If it does, maybe the position has been corrupted or miscalculated?