<commit_before>// Copyright (c) 2020 The PIVX Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#ifndef PIVX_SAPLINGSCRIPTPUBKEYMAN_H
#define PIVX_SAPLINGSCRIPTPUBKEYMAN_H

#include "consensus/consensus.h"
#include "sapling/note.hpp"
#include "wallet/hdchain.h"
#include "wallet/wallet.h"
#include "wallet/walletdb.h"
#include "sapling/incrementalmerkletree.hpp"

//! Size of witness cache
//  Should be large enough that we can expect not to reorg beyond our cache
//  unless there is some exceptional network disruption.
static const unsigned int WITNESS_CACHE_SIZE = DEFAULT_MAX_REORG_DEPTH + 1;

class CBlock;
class CBlockIndex;

/** Sapling note, its location in a transaction, and number of confirmations. */
struct SaplingNoteEntry
{
    explicit SaplingNoteEntry(const SaplingOutPoint& _op,
                              const libzcash::SaplingPaymentAddress& _addr,
                              const libzcash::SaplingNote& _note,
                              const std::array<unsigned char, ZC_MEMO_SIZE>& _memo,
                              const int _conf) :
                              op(_op), address(_addr), note(_note), memo(_memo),
                              confirmations(_conf) { }
    SaplingOutPoint op;
    libzcash::SaplingPaymentAddress address;
    libzcash::SaplingNote note;
    std::array<unsigned char, ZC_MEMO_SIZE> memo;
    int confirmations;
};

class SaplingNoteData
{
public:

    SaplingNoteData() : nullifier() { }
    SaplingNoteData(const libzcash::SaplingIncomingViewingKey& _ivk) : ivk {_ivk}, nullifier() { }
    SaplingNoteData(const libzcash::SaplingIncomingViewingKey& _ivk, const uint256& n) : ivk {_ivk}, nullifier(n) { }

    /* witnesses/ivk: only for own (received) outputs */
    std::list<SaplingWitness> witnesses;
    Optional<libzcash::SaplingIncomingViewingKey> ivk {nullopt};
    inline bool IsMyNote() const { return ivk != nullopt; }

    /**
     * Cached note amount.
     * It will be loaded the first time that the note is decrypted (when the tx is added to the wallet).
     */
    Optional<CAmount> amount{nullopt};

    /**
     * Cached shielded address
     * It will be loaded the first time that the note is decrypted (when the tx is added to the wallet)
     */
     Optional<libzcash::SaplingPaymentAddress> address{nullopt};

     /**
      * Cached note memo (only for non-empty memo)
      * It will be loaded the first time that the note is decrypted (when the tx is added to the wallet)
      */
     Optional<std::array<unsigned char, ZC_MEMO_SIZE>> memo;

    /**
     * Block height corresponding to the most current witness.
     *
     * When we first create a SaplingNoteData in SaplingScriptPubKeyMan::FindMySaplingNotes, this is set to
     * -1 as a placeholder. The next time CWallet::ChainTip is called, we can
     * determine what height the witness cache for this note is valid for (even
     * if no witnesses were cached), and so can set the correct value in
     * SaplingScriptPubKeyMan::IncrementNoteWitnesses and SaplingScriptPubKeyMan::DecrementNoteWitnesses.
     */
    int witnessHeight{-1};

    /**
     * Cached note nullifier. May not be set if the wallet was not unlocked when
     * this SaplingNoteData was created. If not set, we always assume that the
     * note has not been spent.
     *
     * It's okay to cache the nullifier in the wallet, because we are storing
     * the spending key there too, which could be used to derive this.
     * If the wallet is encrypted, this means that someone with access to the
     * locked wallet cannot spend notes, but can connect received notes to the
     * transactions they are spent in. This is the same security semantics as
     * for transparent addresses.
     */
    Optional<uint256> nullifier;

    ADD_SERIALIZE_METHODS;

    template <typename Stream, typename Operation>
    inline void SerializationOp(Stream& s, Operation ser_action)
    {
        int nVersion = s.GetVersion();
        if (!(s.GetType() & SER_GETHASH)) {
            READWRITE(nVersion);
        }
        READWRITE(ivk);
        READWRITE(nullifier);
        READWRITE(witnesses);
        READWRITE(witnessHeight);
    }

    friend bool operator==(const SaplingNoteData& a, const SaplingNoteData& b) {
        return (a.ivk == b.ivk && a.nullifier == b.nullifier && a.witnessHeight == b.witnessHeight);
    }

    friend bool operator!=(const SaplingNoteData& a, const SaplingNoteData& b) {
        return !(a == b);
    }
};

enum KeyAddResult {
    SpendingKeyExists,
    KeyAlreadyExists,
    KeyAdded,
    KeyNotAdded,
};

typedef std::map<SaplingOutPoint, SaplingNoteData> mapSaplingNoteData_t;

/*
 * Sapling keys manager
 * todo: add real description..
 */
class SaplingScriptPubKeyMan {

public:
    SaplingScriptPubKeyMan(CWallet *parent) : wallet(parent) {}

    ~SaplingScriptPubKeyMan() {};

    /**<commit_msg>DB: include new cache data of SaplingNoteData in the serialization<commit_after>// Copyright (c) 2020 The PIVX Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#ifndef PIVX_SAPLINGSCRIPTPUBKEYMAN_H
#define PIVX_SAPLINGSCRIPTPUBKEYMAN_H

#include "consensus/consensus.h"
#include "sapling/note.hpp"
#include "wallet/hdchain.h"
#include "wallet/wallet.h"
#include "wallet/walletdb.h"
#include "sapling/incrementalmerkletree.hpp"

//! Size of witness cache
//  Should be large enough that we can expect not to reorg beyond our cache
//  unless there is some exceptional network disruption.
static const unsigned int WITNESS_CACHE_SIZE = DEFAULT_MAX_REORG_DEPTH + 1;

class CBlock;
class CBlockIndex;

/** Sapling note, its location in a transaction, and number of confirmations. */
struct SaplingNoteEntry
{
    explicit SaplingNoteEntry(const SaplingOutPoint& _op,
                              const libzcash::SaplingPaymentAddress& _addr,
                              const libzcash::SaplingNote& _note,
                              const std::array<unsigned char, ZC_MEMO_SIZE>& _memo,
                              const int _conf) :
                              op(_op), address(_addr), note(_note), memo(_memo),
                              confirmations(_conf) { }
    SaplingOutPoint op;
    libzcash::SaplingPaymentAddress address;
    libzcash::SaplingNote note;
    std::array<unsigned char, ZC_MEMO_SIZE> memo;
    int confirmations;
};

class SaplingNoteData
{
public:

    SaplingNoteData() : nullifier() { }
    SaplingNoteData(const libzcash::SaplingIncomingViewingKey& _ivk) : ivk {_ivk}, nullifier() { }
    SaplingNoteData(const libzcash::SaplingIncomingViewingKey& _ivk, const uint256& n) : ivk {_ivk}, nullifier(n) { }

    /* witnesses/ivk: only for own (received) outputs */
    std::list<SaplingWitness> witnesses;
    Optional<libzcash::SaplingIncomingViewingKey> ivk {nullopt};
    inline bool IsMyNote() const { return ivk != nullopt; }

    /**
     * Cached note amount.
     * It will be loaded the first time that the note is decrypted (when the tx is added to the wallet).
     */
    Optional<CAmount> amount{nullopt};

    /**
     * Cached shielded address
     * It will be loaded the first time that the note is decrypted (when the tx is added to the wallet)
     */
     Optional<libzcash::SaplingPaymentAddress> address{nullopt};

     /**
      * Cached note memo (only for non-empty memo)
      * It will be loaded the first time that the note is decrypted (when the tx is added to the wallet)
      */
     Optional<std::array<unsigned char, ZC_MEMO_SIZE>> memo;

    /**
     * Block height corresponding to the most current witness.
     *
     * When we first create a SaplingNoteData in SaplingScriptPubKeyMan::FindMySaplingNotes, this is set to
     * -1 as a placeholder. The next time CWallet::ChainTip is called, we can
     * determine what height the witness cache for this note is valid for (even
     * if no witnesses were cached), and so can set the correct value in
     * SaplingScriptPubKeyMan::IncrementNoteWitnesses and SaplingScriptPubKeyMan::DecrementNoteWitnesses.
     */
    int witnessHeight{-1};

    /**
     * Cached note nullifier. May not be set if the wallet was not unlocked when
     * this SaplingNoteData was created. If not set, we always assume that the
     * note has not been spent.
     *
     * It's okay to cache the nullifier in the wallet, because we are storing
     * the spending key there too, which could be used to derive this.
     * If the wallet is encrypted, this means that someone with access to the
     * locked wallet cannot spend notes, but can connect received notes to the
     * transactions they are spent in. This is the same security semantics as
     * for transparent addresses.
     */
    Optional<uint256> nullifier;

    ADD_SERIALIZE_METHODS;

    template <typename Stream, typename Operation>
    inline void SerializationOp(Stream& s, Operation ser_action)
    {
        int nVersion = s.GetVersion();
        if (!(s.GetType() & SER_GETHASH)) {
            READWRITE(nVersion);
        }
        READWRITE(ivk);
        READWRITE(nullifier);
        READWRITE(witnesses);
        READWRITE(witnessHeight);
        READWRITE(amount);
        READWRITE(address);
        READWRITE(memo);
    }

    friend bool operator==(const SaplingNoteData& a, const SaplingNoteData& b) {
        return (a.ivk == b.ivk &&
                a.nullifier == b.nullifier &&
                a.witnessHeight == b.witnessHeight &&
                a.amount == b.amount &&
                a.address == b.address &&
                a.memo == b.memo);
    }

    friend bool operator!=(const SaplingNoteData& a, const SaplingNoteData& b) {
        return !(a == b);
    }
};

enum KeyAddResult {
    SpendingKeyExists,
    KeyAlreadyExists,
    KeyAdded,
    KeyNotAdded,
};

typedef std::map<SaplingOutPoint, SaplingNoteData> mapSaplingNoteData_t;

/*
 * Sapling keys manager
 * todo: add real description..
 */
class SaplingScriptPubKeyMan {

public:
    SaplingScriptPubKeyMan(CWallet *parent) : wallet(parent) {}

    ~SaplingScriptPubKeyMan() {};

    /**
{'fraction_non_alphanumeric': 0.08749145591250855, 'fraction_numerical': 0.002538814568889757, 'mean_word_length': 2.9346907414521706, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 25, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5612351', 'n_tokens_mistral': 3119, 'n_tokens_neox': 2954, 'n_words': 968}