<NME> wallet.h
<BEF> // Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2016 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#ifndef BITCOIN_WALLET_WALLET_H
#define BITCOIN_WALLET_WALLET_H

#include "amount.h"
#include "../sigma/coin.h"
#include "../liblelantus/coin.h"
#include "streams.h"
#include "tinyformat.h"
#include "ui_interface.h"
#include "utilstrencodings.h"
#include "validationinterface.h"
#include "script/ismine.h"
#include "script/sign.h"
#include "wallet/crypter.h"
#include "wallet/walletdb.h"
#include "wallet/rpcwallet.h"
#include "wallet/mnemoniccontainer.h"
#include "../base58.h"
#include "firo_params.h"
#include "univalue.h"

#include "hdmint/tracker.h"
#include "hdmint/wallet.h"

#include "primitives/mint_spend.h"

#include "bip47/paymentcode.h"


#include <algorithm>
#include <atomic>
#include <map>
#include <set>
#include <stdexcept>
#include <stdint.h>
#include <string>
#include <utility>
#include <vector>

#include <boost/shared_ptr.hpp>
#include <boost/thread.hpp>

extern CWallet* pwalletMain;

/**
 * Settings
 */
extern CFeeRate payTxFee;
extern unsigned int nTxConfirmTarget;
extern bool bSpendZeroConfChange;
extern bool fSendFreeTransactions;
extern bool fWalletRbf;

static const unsigned int DEFAULT_KEYPOOL_SIZE = 100;
//! -paytxfee default
static const CAmount DEFAULT_TRANSACTION_FEE = 0;
//! -fallbackfee default
static const CAmount DEFAULT_FALLBACK_FEE = 20000;
//! -mintxfee default
static const CAmount DEFAULT_TRANSACTION_MINFEE = 1000;
//! minimum recommended increment for BIP 125 replacement txs
static const CAmount WALLET_INCREMENTAL_RELAY_FEE = 5000;
//! target minimum change amount
static const CAmount MIN_CHANGE = CENT;
//! final minimum change amount after paying for fees
static const CAmount MIN_FINAL_CHANGE = MIN_CHANGE/2;
//! Default for -spendzeroconfchange
static const bool DEFAULT_SPEND_ZEROCONF_CHANGE = true;
//! Default for -sendfreetransactions
static const bool DEFAULT_SEND_FREE_TRANSACTIONS = false;
//! Default for -walletrejectlongchains
static const bool DEFAULT_WALLET_REJECT_LONG_CHAINS = false;
//! -txconfirmtarget default
static const unsigned int DEFAULT_TX_CONFIRM_TARGET = 6;
//! -walletrbf default
static const bool DEFAULT_WALLET_RBF = false;
//! Largest (in bytes) free transaction we're willing to create
static const unsigned int MAX_FREE_TRANSACTION_CREATE_SIZE = 1000;
static const bool DEFAULT_WALLETBROADCAST = true;
static const bool DEFAULT_DISABLE_WALLET = false;

static const bool DEFAULT_UPGRADE_CHAIN = false;

//! if set, all keys will be derived by using BIP32
static const bool DEFAULT_USE_HD_WALLET = true;

//! if set, all keys will be derived by using BIP39
static const bool DEFAULT_USE_MNEMONIC = true;

extern const char * DEFAULT_WALLET_DAT;

const uint32_t BIP32_HARDENED_KEY_LIMIT = 0x80000000;
const uint32_t BIP44_INDEX = 0x2C;
const uint32_t BIP44_TEST_INDEX = 0x1;   // https://github.com/satoshilabs/slips/blob/master/slip-0044.md#registered-coin-types
const uint32_t BIP44_FIRO_INDEX = 0x88; // https://github.com/satoshilabs/slips/blob/master/slip-0044.md#registered-coin-types
const uint32_t BIP44_MINT_INDEX = 0x2;
#ifdef ENABLE_ELYSIUM
const uint32_t BIP44_ELYSIUM_MINT_INDEX_V0 = 0x3;
const uint32_t BIP44_ELYSIUM_MINT_INDEX_V1 = 0x4;
#endif
const uint32_t BIP44_MINT_VALUE_INDEX = 0x5;

class CBlockIndex;
class CCoinControl;
class COutput;
class CReserveKey;
class CScript;
class CTxMemPool;
class CWalletTx;
namespace bip47 {
class CPaymentChannel;
}


namespace bip47 {
    class CPaymentCode;
    class CWallet;
}

/** (client) version numbers for particular wallet features */
enum WalletFeature
{
    FEATURE_BASE = 10500, // the earliest version new wallets supports (only useful for getinfo's clientversion output)

    FEATURE_WALLETCRYPT = 40000, // wallet encryption
    FEATURE_COMPRPUBKEY = 60000, // compressed public keys

    FEATURE_HD = 130000, // Hierarchical key derivation after BIP32 (HD Wallet)
    FEATURE_LATEST = FEATURE_COMPRPUBKEY // HD is optional, use FEATURE_COMPRPUBKEY as latest version
};

struct CompactTallyItem
{
    CBitcoinAddress address;
    CAmount nAmount;
    std::vector<CTxIn> vecTxIn;
    CompactTallyItem()
    {
        nAmount = 0;
    }
};


/** A key pool entry */
class CKeyPool
{
public:
    int64_t nTime;
    CPubKey vchPubKey;

    CKeyPool();
    CKeyPool(const CPubKey& vchPubKeyIn);

    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(nTime);
        READWRITE(vchPubKey);
    }
};

/** Address book data */
class CAddressBookData
{
public:
    std::string name;
    std::string purpose;

    CAddressBookData()
    {
        purpose = "unknown";
    }

    typedef std::map<std::string, std::string> StringMap;
    StringMap destdata;
};

struct CRecipient
{
    CScript scriptPubKey;
    CAmount nAmount;
    bool fSubtractFeeFromAmount;
};

typedef std::map<std::string, std::string> mapValue_t;


static inline void ReadOrderPos(int64_t& nOrderPos, mapValue_t& mapValue)
{
    if (!mapValue.count("n"))
    {
        nOrderPos = -1; // TODO: calculate elsewhere
        return;
    }
    nOrderPos = atoi64(mapValue["n"].c_str());
}


static inline void WriteOrderPos(const int64_t& nOrderPos, mapValue_t& mapValue)
{
    if (nOrderPos == -1)
        return;
    mapValue["n"] = i64tostr(nOrderPos);
}

struct COutputEntry
{
    CTxDestination destination;
    CAmount amount;
    int vout;
};

/** A transaction with a merkle branch linking it to the block chain. */
class CMerkleTx
{
private:
  /** Constant used in hashBlock to indicate tx has been abandoned */
    static const uint256 ABANDON_HASH;

public:
    CTransactionRef tx;
    uint256 hashBlock;

    /* An nIndex == -1 means that hashBlock (in nonzero) refers to the earliest
     * block in the chain we know this or any in-wallet dependency conflicts
     * with. Older clients interpret nIndex == -1 as unconfirmed for backward
     * compatibility.
     */
    int nIndex;

    CMerkleTx()
    {
        SetTx(MakeTransactionRef());
        Init();
    }

    CMerkleTx(CTransactionRef arg)
    {
        SetTx(std::move(arg));
        Init();
    }

    /** Helper conversion operator to allow passing CMerkleTx where CTransaction is expected.
     *  TODO: adapt callers and remove this operator. */
    operator const CTransaction&() const { return *tx; }

    void Init()
    {
        hashBlock = uint256();
        nIndex = -1;
    }

    void SetTx(CTransactionRef arg)
    {
        tx = std::move(arg);
    }

    ADD_SERIALIZE_METHODS;

    template <typename Stream, typename Operation>
    inline void SerializationOp(Stream& s, Operation ser_action) {
        std::vector<uint256> vMerkleBranch; // For compatibility with older versions.
        READWRITE(tx);
        READWRITE(hashBlock);
        READWRITE(vMerkleBranch);
        READWRITE(nIndex);
    }

    void SetMerkleBranch(const CBlockIndex* pIndex, int posInBlock);

    /**
     * Return depth of transaction in blockchain:
     * <0  : conflicts with a transaction this deep in the blockchain
     *  0  : in memory pool, waiting to be included in a block
     * >=1 : this many blocks deep in the main chain
     */
    int GetDepthInMainChain(const CBlockIndex* &pindexRet) const;
    int GetDepthInMainChain() const { const CBlockIndex *pindexRet; return GetDepthInMainChain(pindexRet); }

    int GetDepthInMainChain(const CBlockIndex* &pindexRet, bool enableIX) const;
    int GetDepthInMainChain(bool enableIX) const { const CBlockIndex *pindexRet; return GetDepthInMainChain(pindexRet, enableIX); }

    bool IsInMainChain() const { const CBlockIndex *pindexRet; return GetDepthInMainChain(pindexRet) > 0; }
    bool IsLockedByLLMQInstantSend() const;
    bool IsChainLocked() const;
    int GetBlocksToMaturity() const;

    bool AcceptToMemoryPool(const CAmount& nAbsurdFee, CValidationState& state);
    bool hashUnset() const { return (hashBlock.IsNull() || hashBlock == ABANDON_HASH); }
    bool isAbandoned() const { return (hashBlock == ABANDON_HASH); }
    void setAbandoned() { hashBlock = ABANDON_HASH; }

    const uint256& GetHash() const { return tx->GetHash(); }
    bool IsCoinBase() const { return tx->IsCoinBase(); }
};

/**
 * A transaction with a bunch of additional info that only the owner cares about.
 * It includes any unrecorded transactions needed to link it back to the block chain.
 */
class CWalletTx : public CMerkleTx
{
private:
    const CWallet* pwallet;

public:
    mapValue_t mapValue;
    std::vector<std::pair<std::string, std::string> > vOrderForm;
    unsigned int fTimeReceivedIsTxTime;
    unsigned int nTimeReceived; //!< time received by this node
    unsigned int nTimeSmart;
    /**
     * From me flag is set to 1 for transactions that were created by the wallet
     * on this bitcoin node, and set to 0 for transactions that were created
     * externally and came in through the network or sendrawtransaction RPC.
     */
    char fFromMe;
    std::string strFromAccount;
    int64_t nOrderPos; //!< position in ordered transaction list
    std::unordered_set<uint32_t> changes; //!< positions of changes in vout

    // memory only
    mutable bool fDebitCached;
    mutable bool fCreditCached;
    mutable bool fImmatureCreditCached;
    mutable bool fAvailableCreditCached;
    mutable bool fWatchDebitCached;
    mutable bool fWatchCreditCached;
    mutable bool fImmatureWatchCreditCached;
    mutable bool fAvailableWatchCreditCached;
    mutable bool fChangeCached;
    mutable CAmount nDebitCached;
    mutable CAmount nCreditCached;
    mutable CAmount nImmatureCreditCached;
    mutable CAmount nAvailableCreditCached;
    mutable CAmount nWatchDebitCached;
    mutable CAmount nWatchCreditCached;
    mutable CAmount nImmatureWatchCreditCached;
    mutable CAmount nAvailableWatchCreditCached;
    mutable CAmount nChangeCached;

    CWalletTx()
    {
        Init(NULL);
    }

    CWalletTx(const CWallet* pwalletIn, CTransactionRef arg) : CMerkleTx(std::move(arg))
    {
        Init(pwalletIn);
    }

    void Init(const CWallet* pwalletIn)
    {
        pwallet = pwalletIn;
        mapValue.clear();
        vOrderForm.clear();
        fTimeReceivedIsTxTime = false;
        nTimeReceived = 0;
        nTimeSmart = 0;
        fFromMe = false;
        strFromAccount.clear();
        fDebitCached = false;
        fCreditCached = false;
        fImmatureCreditCached = false;
        fAvailableCreditCached = false;
        fWatchDebitCached = false;
        fWatchCreditCached = false;
        fImmatureWatchCreditCached = false;
        fAvailableWatchCreditCached = false;
        fChangeCached = false;
        nDebitCached = 0;
        nCreditCached = 0;
        nImmatureCreditCached = 0;
        nAvailableCreditCached = 0;
        nWatchDebitCached = 0;
        nWatchCreditCached = 0;
        nAvailableWatchCreditCached = 0;
        nImmatureWatchCreditCached = 0;
        nChangeCached = 0;
        nOrderPos = -1;
        changes.clear();
    }

    ADD_SERIALIZE_METHODS;

    template <typename Stream, typename Operation>
    inline void SerializationOp(Stream& s, Operation ser_action) {
        constexpr uint32_t FLAG_WITH_CHANGES = 0x00000001;

        if (ser_action.ForRead())
            Init(NULL);

        char fSpent = false;
        uint32_t flags = 0;

        if (!ser_action.ForRead())
        {
            flags = FLAG_WITH_CHANGES;

            mapValue["fromaccount"] = strFromAccount;
            mapValue["flags"] = strprintf("0x%x", flags);

            WriteOrderPos(nOrderPos, mapValue);

            if (nTimeSmart)
                mapValue["timesmart"] = strprintf("%u", nTimeSmart);
        }

        READWRITE(*(CMerkleTx*)this);
        std::vector<CMerkleTx> vUnused; //!< Used to be vtxPrev
        READWRITE(vUnused);
        READWRITE(mapValue);
        READWRITE(vOrderForm);
        READWRITE(fTimeReceivedIsTxTime);
        READWRITE(nTimeReceived);
        READWRITE(fFromMe);
        READWRITE(fSpent);

        if (ser_action.ForRead())
        {
            strFromAccount = mapValue["fromaccount"];

            ReadOrderPos(nOrderPos, mapValue);

            nTimeSmart = mapValue.count("timesmart") ? (unsigned int)atoi64(mapValue["timesmart"]) : 0;

            auto it = mapValue.find("flags");
            if (it != mapValue.end()) {
                flags = static_cast<uint32_t>(std::strtoul(it->second.c_str(), nullptr, 0));
            }
        }

        if (flags & FLAG_WITH_CHANGES) {
            READWRITE(changes);
        }

        mapValue.erase("fromaccount");
        mapValue.erase("version");
        mapValue.erase("spent");
        mapValue.erase("n");
        mapValue.erase("timesmart");
        mapValue.erase("flags");
    }

    //! make sure balances are recalculated
    void MarkDirty()
    {
        fCreditCached = false;
        fAvailableCreditCached = false;
        fImmatureCreditCached = false;
        fWatchDebitCached = false;
        fWatchCreditCached = false;
        fAvailableWatchCreditCached = false;
        fImmatureWatchCreditCached = false;
        fDebitCached = false;
        fChangeCached = false;
    }

    void BindWallet(CWallet *pwalletIn)
    {
        pwallet = pwalletIn;
        MarkDirty();
    }

    //! filter decides which addresses will count towards the debit
    CAmount GetDebit(const isminefilter& filter) const;
    CAmount GetCredit(const isminefilter& filter) const;
    CAmount GetImmatureCredit(bool fUseCache=true) const;
    CAmount GetAvailableCredit(bool fUseCache=true, bool fExcludeLocked = false) const;
    CAmount GetImmatureWatchOnlyCredit(const bool& fUseCache=true) const;
    CAmount GetAvailableWatchOnlyCredit(const bool& fUseCache=true) const;
    CAmount GetAnonymizedCredit(bool fUseCache=true) const;
    CAmount GetChange() const;

    void GetAmounts(std::list<COutputEntry>& listReceived,
                    std::list<COutputEntry>& listSent, CAmount& nFee, std::string& strSentAccount, const isminefilter& filter) const;

    bool IsFromMe(const isminefilter& filter) const
    {
        return (GetDebit(filter) > 0);
    }

    // True if only scriptSigs are different
    bool IsEquivalentTo(const CWalletTx& tx) const;

    bool InMempool() const;
    bool InStempool() const;
    bool IsTrusted() const;

    bool IsChange(uint32_t out) const;
    bool IsChange(const CTxOut& out) const;

    int64_t GetTxTime() const;
    int GetRequestCount() const;

    bool RelayWalletTransaction(CConnman* connman);

    std::set<uint256> GetConflicts() const;
};




class COutput
{
public:
    const CWalletTx *tx;
    int i;
    int nDepth;
    bool fSpendable;
    bool fSolvable;

    COutput(const CWalletTx *txIn, int iIn, int nDepthIn, bool fSpendableIn, bool fSolvableIn)
    {
        tx = txIn; i = iIn; nDepth = nDepthIn; fSpendable = fSpendableIn; fSolvable = fSolvableIn;
    }

    std::string ToString() const;
};




/** Private key that includes an expiration date in case it never gets used. */
class CWalletKey
{
public:
    CPrivKey vchPrivKey;
    int64_t nTimeCreated;
    int64_t nTimeExpires;
    std::string strComment;
    //! todo: add something to note what created it (user, getnewaddress, change)
    //!   maybe should have a map<string, string> property map

    CWalletKey(int64_t nExpires=0);

    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(vchPrivKey);
        READWRITE(nTimeCreated);
        READWRITE(nTimeExpires);
        READWRITE(LIMITED_STRING(strComment, 65536));
    }
};

/**
 * Internal transfers.
 * Database key is acentry<account><counter>.
 */
class CAccountingEntry
{
public:
    std::string strAccount;
    CAmount nCreditDebit;
    int64_t nTime;
    std::string strOtherAccount;
    std::string strComment;
    mapValue_t mapValue;
    int64_t nOrderPos; //!< position in ordered transaction list
    uint64_t nEntryNo;

    CAccountingEntry()
    {
        SetNull();
    }

    void SetNull()
    {
        nCreditDebit = 0;
        nTime = 0;
        strAccount.clear();
        strOtherAccount.clear();
        strComment.clear();
        nOrderPos = -1;
        nEntryNo = 0;
    }

    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);
        //! Note: strAccount is serialized as part of the key, not here.
        READWRITE(nCreditDebit);
        READWRITE(nTime);
        READWRITE(LIMITED_STRING(strOtherAccount, 65536));

        if (!ser_action.ForRead())
        {
            WriteOrderPos(nOrderPos, mapValue);

            if (!(mapValue.empty() && _ssExtra.empty()))
            {
                CDataStream ss(s.GetType(), s.GetVersion());
                ss.insert(ss.begin(), '\0');
                ss << mapValue;
                ss.insert(ss.end(), _ssExtra.begin(), _ssExtra.end());
                strComment.append(ss.str());
            }
        }

        READWRITE(LIMITED_STRING(strComment, 65536));

        size_t nSepPos = strComment.find("\0", 0, 1);
        if (ser_action.ForRead())
        {
            mapValue.clear();
            if (std::string::npos != nSepPos)
            {
                CDataStream ss(std::vector<char>(strComment.begin() + nSepPos + 1, strComment.end()), s.GetType(), s.GetVersion());
                ss >> mapValue;
                _ssExtra = std::vector<char>(ss.begin(), ss.end());
            }
            ReadOrderPos(nOrderPos, mapValue);
        }
        if (std::string::npos != nSepPos)
            strComment.erase(nSepPos);

        mapValue.erase("n");
    }

private:
    std::vector<char> _ssExtra;
};

class LelantusJoinSplitBuilder;

/**
 * A CWallet is an extension of a keystore, which also maintains a set of transactions and balances,
 * and provides the ability to create new transactions.
 */
class CWallet : public CCryptoKeyStore, public CValidationInterface
{
private:
    static std::atomic<bool> fFlushThreadRunning;

    /**
     * Select a set of coins such that nValueRet >= nTargetValue and at least
     * all coins from coinControl are selected; Never select unconfirmed coins
     * if they are not ours
     */
    bool SelectCoins(const std::vector<COutput>& vAvailableCoins, const CAmount& nTargetValue, std::set<std::pair<const CWalletTx*,unsigned int> >& setCoinsRet, CAmount& nValueRet, const CCoinControl *coinControl = NULL, bool fForUseInInstantSend = true) const;

    CWalletDB *pwalletdbEncryption;

    //! the current wallet version: clients below this version are not able to load the wallet
    int nWalletVersion;

    //! the maximum wallet format version: memory-only variable that specifies to what version this wallet may be upgraded
    int nWalletMaxVersion;

    int64_t nNextResend;
    int64_t nLastResend;
    bool fBroadcastTransactions;

    mutable bool fAnonymizableTallyCached;
    mutable std::vector<CompactTallyItem> vecAnonymizableTallyCached;
    mutable bool fAnonymizableTallyCachedNonDenom;
    mutable std::vector<CompactTallyItem> vecAnonymizableTallyCachedNonDenom;

    /**
     * Used to keep track of spent outpoints, and
     * detect and report conflicts (double-spends or
     * mutated transactions where the mutant gets mined).
     */
    typedef std::multimap<COutPoint, uint256> TxSpends;
    TxSpends mapTxSpends;
    void AddToSpends(const COutPoint& outpoint, const uint256& wtxid);
    void AddToSpends(const uint256& wtxid);

    std::set<COutPoint> setWalletUTXO;

    /* Mark a transaction (and its in-wallet descendants) as conflicting with a particular block. */
    void MarkConflicted(const uint256& hashBlock, const uint256& hashTx);

    void SyncMetaData(std::pair<TxSpends::iterator, TxSpends::iterator>);

    /* the HD chain data model (external chain counters) */
    CHDChain hdChain;
    MnemonicContainer mnemonicContainer;

    bool fFileBacked;

    std::set<int64_t> setKeyPool;

    std::map<CKeyID, int64_t> m_pool_key_to_index;

    int64_t nTimeFirstKey;

    std::shared_ptr<bip47::CWallet> bip47wallet;

    /**
     * Private version of AddWatchOnly method which does not accept a
     * timestamp, and which will reset the wallet's nTimeFirstKey value to 1 if
     * the watch key did not previously have a timestamp associated with it.
     * Because this is an inherited virtual method, it is accessible despite
     * being marked private, but it is marked private anyway to encourage use
     * of the other AddWatchOnly which accepts a timestamp and sets
     * nTimeFirstKey more intelligently for more efficient rescans.
     */
    bool AddWatchOnly(const CScript& dest) override;

public:
    /*
     * Main wallet lock.
     * This lock protects all the fields added by CWallet
     *   except for:
     *      fFileBacked (immutable after instantiation)
     *      strWalletFile (immutable after instantiation)
     */
    mutable CCriticalSection cs_wallet;

    const std::string strWalletFile;

    void LoadKeyPool(int nIndex, const CKeyPool &keypool)
    {
        setKeyPool.insert(nIndex);

        m_pool_key_to_index[keypool.vchPubKey.GetID()] = nIndex;
        // If no metadata exists yet, create a default with the pool key's
        // creation time. Note that this may be overwritten by actually
        // stored metadata for that key later, which is fine.
        CKeyID keyid = keypool.vchPubKey.GetID();
        if (mapKeyMetadata.count(keyid) == 0)
            mapKeyMetadata[keyid] = CKeyMetadata(keypool.nTime);
    }

    // Map from Key ID (for regular keys) or Script ID (for watch-only keys) to
    // key metadata.
    std::map<CTxDestination, CKeyMetadata> mapKeyMetadata;
    //znode
    int64_t nKeysLeftSinceAutoBackup;

    typedef std::map<unsigned int, CMasterKey> MasterKeyMap;
    MasterKeyMap mapMasterKeys;
    unsigned int nMasterKeyMaxID;

    std::unique_ptr<CHDMintWallet> zwallet;

    CWallet()
    {
        SetNull();
    }

    CWallet(const std::string& strWalletFileIn) : strWalletFile(strWalletFileIn)
    {
        SetNull();
        fFileBacked = true;
    }

    ~CWallet()
    {
        delete pwalletdbEncryption;
        pwalletdbEncryption = NULL;
    }

    void SetNull()
    {
        nWalletVersion = FEATURE_BASE;
        nWalletMaxVersion = FEATURE_BASE;
        fFileBacked = false;
        nMasterKeyMaxID = 0;
        pwalletdbEncryption = NULL;
        nOrderPosNext = 0;
        nNextResend = 0;
        nLastResend = 0;
        nTimeFirstKey = 0;
        fBroadcastTransactions = false;
        fAnonymizableTallyCached = false;
        fAnonymizableTallyCachedNonDenom = false;
        vecAnonymizableTallyCached.clear();
        vecAnonymizableTallyCachedNonDenom.clear();
        zwallet = NULL;
        bip47wallet.reset();
    }

    std::map<uint256, CWalletTx> mapWallet;
    std::list<CAccountingEntry> laccentries;
    bool EraseFromWallet(uint256 hash);
    typedef std::pair<CWalletTx*, CAccountingEntry*> TxPair;
    typedef std::multimap<int64_t, TxPair > TxItems;
    TxItems wtxOrdered;

    int64_t nOrderPosNext;
    std::map<uint256, int> mapRequestCount;

    std::map<CTxDestination, CAddressBookData> mapAddressBook;
    std::multimap<std::string, std::string> mapCustomKeyValues;

    CPubKey vchDefaultKey;

    std::set<COutPoint> setLockedCoins;

    const CWalletTx* GetWalletTx(const uint256& hash) const;

    //! check whether we are allowed to upgrade (or already support) to the named feature
    bool CanSupportFeature(enum WalletFeature wf) { AssertLockHeld(cs_wallet); return nWalletMaxVersion >= wf; }

    /**
     * populate vCoins with vector of available COutputs.
     */
    void AvailableCoins(std::vector<COutput>& vCoins, bool fOnlyConfirmed=true, const CCoinControl *coinControl = NULL, bool fIncludeZeroValue=false, bool fForUseInInstantSend = false) const;

    void AvailableCoinsForLMint(std::vector<std::pair<CAmount, std::vector<COutput>>>& valueAndUTXO, const CCoinControl *coinControl) const;

    bool IsHDSeedAvailable() { return !hdChain.masterKeyID.IsNull(); }

    /**
     * Shuffle and select coins until nTargetValue is reached while avoiding
     * small change; This method is stochastic for some inputs and upon
    CAmount GetNeedsToBeAnonymizedBalance(CAmount nMinBalance = 0) const;
    CAmount GetDenominatedBalance(bool unconfirmed=false) const;

    /** \brief Selects coins to spend, and coins to re-mint based on the required amount to spend, provided by the user. As the lower denomination now is 0.1 zcoin, user's request will be rounded up to the nearest 0.1. This difference between the user's requested value, and the actually spent value will be left to the miners as a fee.
     * \param[in] required Required amount to spend.
     * \param[out] coinsToSpend_out Coins which user needs to spend.
    void UnlockAllCoins();
    void ListLockedCoins(std::vector<COutPoint>& vOutpts);
    void ListProTxCoins(std::vector<COutPoint>& vOutpts);

    bool HasMasternode();

    // znode
    /// Get 1000 FIRO output and keys which can be used for the Znode
    bool GetZnodeVinAndKeys(CTxIn& txinRet, CPubKey& pubKeyRet, CKey& keyRet, std::string strTxHash = "", std::string strOutputIndex = "");
    /// Extract txin information and keys from output
    bool GetVinAndKeysFromOutput(COutput out, CTxIn& txinRet, CPubKey& pubKeyRet, CKey& keyRet);

    CPubKey GetKeyFromKeypath(uint32_t nChange, uint32_t nChild, CKey& secret);
    /**
     * keystore implementation
     * Generate a new key
     */
    CPubKey GenerateNewKey(uint32_t nChange=0, bool fWriteChain=true);
    void DeriveNewChildKey(CKeyMetadata& metadata, CKey& secret);
    //! Adds a key to the store, and saves it to disk.
    bool AddKeyPubKey(const CKey& key, const CPubKey &pubkey) override;
    //! Adds a key to the store, without saving it to disk (used by LoadWallet)
    bool LoadKey(const CKey& key, const CPubKey &pubkey) { return CCryptoKeyStore::AddKeyPubKey(key, pubkey); }
    //! Load metadata (used by LoadWallet)
    bool LoadKeyMetadata(const CTxDestination& pubKey, const CKeyMetadata &metadata);

    bool LoadMinVersion(int nVersion) { AssertLockHeld(cs_wallet); nWalletVersion = nVersion; nWalletMaxVersion = std::max(nWalletMaxVersion, nVersion); return true; }
    void UpdateTimeFirstKey(int64_t nCreateTime);

    //! Adds an encrypted key to the store, and saves it to disk.
    bool AddCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret) override;
    //! Adds an encrypted key to the store, without saving it to disk (used by LoadWallet)
    bool LoadCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret);
    bool AddCScript(const CScript& redeemScript) override;
    bool LoadCScript(const CScript& redeemScript);

    //! Adds a destination data tuple to the store, and saves it to disk
    bool AddDestData(const CTxDestination &dest, const std::string &key, const std::string &value);
    //! Erases a destination data tuple in the store and on disk
    bool EraseDestData(const CTxDestination &dest, const std::string &key);
    //! Adds a destination data tuple to the store, without saving it to disk
    bool LoadDestData(const CTxDestination &dest, const std::string &key, const std::string &value);
    //! Look up a destination data tuple in the store, return true if found false otherwise
    bool GetDestData(const CTxDestination &dest, const std::string &key, std::string *value) const;

    //! Adds a watch-only address to the store, and saves it to disk.
    bool AddWatchOnly(const CScript& dest, int64_t nCreateTime);
    bool RemoveWatchOnly(const CScript &dest) override;
    //! Adds a watch-only address to the store, without saving it to disk (used by LoadWallet)
    bool LoadWatchOnly(const CScript &dest);

    //! Holds a timestamp at which point the wallet is scheduled (externally) to be relocked. Caller must arrange for actual relocking to occur via Lock().
    int64_t nRelockTime;

    bool Unlock(const SecureString& strWalletPassphrase, const bool& fFirstUnlock=false);
    bool ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, const SecureString& strNewWalletPassphrase);
    bool EncryptWallet(const SecureString& strWalletPassphrase);

    void GetKeyBirthTimes(std::map<CTxDestination, int64_t> &mapKeyBirth) const;

    /**
     * Increment the next transaction order id
     * @return next transaction order id
     */
    int64_t IncOrderPosNext(CWalletDB *pwalletdb = NULL);
    DBErrors ReorderTransactions();
    bool AccountMove(std::string strFrom, std::string strTo, CAmount nAmount, std::string strComment = "");
    bool GetAccountPubkey(CPubKey &pubKey, std::string strAccount, bool bForceNew = false);

    void MarkDirty();
    bool AddToWallet(const CWalletTx& wtxIn, bool fFlushOnClose=true);
    bool LoadToWallet(const CWalletTx& wtxIn);
    void SyncTransaction(const CTransaction& tx, const CBlockIndex *pindex, int posInBlock) override;
    bool AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlockIndex* pIndex, int posInBlock, bool fUpdate);
    CBlockIndex* ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate = false, bool fRecoverMnemonic = false);
    void ReacceptWalletTransactions();
    void ResendWalletTransactions(int64_t nBestBlockTime, CConnman* connman) override;
    std::vector<uint256> ResendWalletTransactionsBefore(int64_t nTime, CConnman* connman);
    CAmount GetBalance(bool fExcludeLocked = false) const;
    std::pair<CAmount, CAmount> GetPrivateBalance() const;
    std::pair<CAmount, CAmount> GetPrivateBalance(size_t &confirmed, size_t &unconfirmed) const;
    CAmount GetUnconfirmedBalance() const;
    CAmount GetImmatureBalance() const;
    CAmount GetWatchOnlyBalance() const;
    CAmount GetUnconfirmedWatchOnlyBalance() const;
    CAmount GetImmatureWatchOnlyBalance() const;
    CAmount GetLegacyBalance(const isminefilter& filter, int minDepth, const std::string* account, bool fAddLocked = false) const;

    static std::vector<CRecipient> CreateSigmaMintRecipients(
        std::vector<sigma::PrivateCoin>& coins,
        std::vector<CHDMint>& vDMints);

    static CRecipient CreateLelantusMintRecipient(
        lelantus::PrivateCoin& coin,
        CHDMint& vDMint,
        bool generate = true);

    static int GetRequiredCoinCountForAmount(
        const CAmount& required,
        const std::vector<sigma::CoinDenomination>& denominations);

    static CAmount SelectMintCoinsForAmount(
        const CAmount& required,
        const std::vector<sigma::CoinDenomination>& denominations,
        std::vector<sigma::CoinDenomination>& coinsOut);

    static CAmount SelectSpendCoinsForAmount(
        const CAmount& required,
        const std::list<CSigmaEntry>& coinsIn,
        std::vector<CSigmaEntry>& coinsOut);

    // Returns a list of unspent and verified coins, I.E. coins which are ready
    // to be spent.
    std::list<CSigmaEntry> GetAvailableCoins(const CCoinControl *coinControl = NULL, bool includeUnsafe = false, bool forEstimation = false) const;

    std::list<CLelantusEntry> GetAvailableLelantusCoins(const CCoinControl *coinControl = NULL, bool includeUnsafe = false, bool forEstimation = false) const;

    std::vector<unsigned char> EncryptMintAmount(uint64_t amount, const secp_primitives::GroupElement& pubcoin) const;

    bool DecryptMintAmount(const std::vector<unsigned char>& encryptedValue, const secp_primitives::GroupElement& pubcoin, uint64_t& amount) const;


    /** \brief Selects coins to spend, and coins to re-mint based on the required amount to spend, provided by the user. As the lower denomination now is 0.1 firo, user's request will be rounded up to the nearest 0.1. This difference between the user's requested value, and the actually spent value will be left to the miners as a fee.
     * \param[in] required Required amount to spend.
     * \param[out] coinsToSpend_out Coins which user needs to spend.
     * \param[out] coinsToMint_out Coins which will be re-minted by the user to get the change back.
     * \returns true, if it was possible to spend exactly required(rounded up to 0.1 firo) amount using coins we have.
     */
    bool GetCoinsToSpend(
        CAmount required,
        std::vector<CSigmaEntry>& coinsToSpend_out,
        std::vector<sigma::CoinDenomination>& coinsToMint_out,
        std::list<CSigmaEntry>& coins,
        const size_t coinsLimit = SIZE_MAX,
        const CAmount amountLimit = MAX_MONEY,
        const CCoinControl *coinControl = NULL) const;

    bool GetCoinsToJoinSplit(
            CAmount required,
            std::vector<CLelantusEntry>& coinsToSpend_out,
            CAmount& changeToMint,
            std::list<CLelantusEntry> coins,
            const size_t coinsToSpendLimit = SIZE_MAX,
            const CAmount amountToSpendLimit = MAX_MONEY,
            const CCoinControl *coinControl = NULL) const;

    /**
     * Insert additional inputs into the transaction by
     * calling CreateTransaction();
     */
    bool FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, bool overrideEstimatedFeeRate, const CFeeRate& specificFeeRate, int& nChangePosInOut, std::string& strFailReason, bool includeWatching, bool lockUnspents, const std::set<int>& setSubtractFeeFromOutputs, bool keepReserveKey = true, const CTxDestination& destChange = CNoDestination());

    /**
     * Create a new transaction paying the recipients with a set of coins
     * selected by SelectCoins(); Also create the change output, when needed
     * @note passing nChangePosInOut as -1 will result in setting a random position
     */
    bool CreateTransaction(const std::vector<CRecipient>& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet, int& nChangePosInOut,
                           std::string& strFailReason, const CCoinControl *coinControl = NULL, bool sign = true, int nExtraPayloadSize = 0, bool fUseInstantSend=false);

    /**
     * Add Mint and Spend functions
     */
    void ListAvailableSigmaMintCoins(std::vector <COutput> &vCoins, bool fOnlyConfirmed) const;
    void ListAvailableLelantusMintCoins(std::vector<COutput> &vCoins, bool fOnlyConfirmed) const;

    bool CreateMintTransaction(const std::vector<CRecipient>& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet, int& nChangePosInOut,
                           std::string& strFailReason, const CCoinControl *coinControl = NULL, bool sign = true);
    bool CreateMintTransaction(CScript pubCoin, int64_t nValue,
                                       CWalletTx& wtxNew, CReserveKey& reservekey, int64_t& nFeeRet, std::string& strFailReason, const CCoinControl *coinControl=NULL);
    bool CreateLelantusMintTransactions(CAmount valueToMint, std::vector<std::pair<CWalletTx, CAmount>>& wtxAndFee,
                                        CAmount& nAllFeeRet, std::vector<CHDMint>& dMints,
                                        std::list<CReserveKey>& reservekeys, int& nChangePosInOut,
                                        std::string& strFailReason, const CCoinControl *coinControl, bool autoMintAll = false, bool sign = true);

    CWalletTx CreateSigmaSpendTransaction(
        const std::vector<CRecipient>& recipients,
        CAmount& fee,
        std::vector<CSigmaEntry>& selected,
        std::vector<CHDMint>& changes,
        bool& fChangeAddedToFee,
        const CCoinControl *coinControl = NULL);

    CWalletTx CreateLelantusJoinSplitTransaction(
        const std::vector<CRecipient>& recipients,
        CAmount& fee,
        const std::vector<CAmount>& newMints,
        std::vector<CLelantusEntry>& spendCoins,
        std::vector<CSigmaEntry>& sigmaSpendCoins,
        std::vector<CHDMint>& mintCoins,
        const CCoinControl *coinControl = NULL,
        std::function<void(CTxOut & , LelantusJoinSplitBuilder const &)> modifier = nullptr);

    bool CommitSigmaTransaction(CWalletTx& wtxNew, std::vector<CSigmaEntry>& selectedCoins, std::vector<CHDMint>& changes);
    bool CommitLelantusTransaction(CWalletTx& wtxNew, std::vector<CLelantusEntry>& spendCoins, std::vector<CSigmaEntry>& sigmaSpendCoins, std::vector<CHDMint>& mintCoins);
    std::string SendMoney(CScript scriptPubKey, int64_t nValue, CWalletTx& wtxNew, bool fAskFee=false);
    std::string SendMoneyToDestination(const CTxDestination &address, int64_t nValue, CWalletTx& wtxNew, bool fAskFee=false);

    std::string MintAndStoreSigma(
        const std::vector<CRecipient>& vecSend,
        const std::vector<sigma::PrivateCoin>& privCoins,
        std::vector<CHDMint> vDMints,
        CWalletTx &wtxNew,
        bool fAskFee=false,
        const CCoinControl *coinControl = NULL);

    std::string MintAndStoreLelantus(
            const CAmount& value,
            std::vector<std::pair<CWalletTx, CAmount>>& wtxAndFee,
            std::vector<CHDMint>& mints,
            bool autoMintAll = false,
            bool fAskFee = false,
            const CCoinControl *coinControl = NULL);

    std::vector<CSigmaEntry> SpendSigma(const std::vector<CRecipient>& recipients, CWalletTx& result);
    std::vector<CSigmaEntry> SpendSigma(const std::vector<CRecipient>& recipients, CWalletTx& result, CAmount& fee);

    std::vector<CLelantusEntry> JoinSplitLelantus(const std::vector<CRecipient>& recipients, const std::vector<CAmount>& newMints, CWalletTx& result);

    std::pair<CAmount, unsigned int> EstimateJoinSplitFee(CAmount required, bool subtractFeeFromAmount, std::list<CSigmaEntry> sigmaCoins, std::list<CLelantusEntry> coins, const CCoinControl *coinControl);

    bool GetMint(const uint256& hashSerial, CSigmaEntry& sigmaEntry, bool forEstimation = false) const;

    bool GetMint(const uint256& hashSerial, CLelantusEntry& mint, bool forEstimation = false) const;

    bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey, CConnman* connman, CValidationState& state);


    bool CreateCollateralTransaction(CMutableTransaction& txCollateral, std::string& strReason);
    bool ConvertList(std::vector<CTxIn> vecTxIn, std::vector<CAmount>& vecAmounts);

    void ListAccountCreditDebit(const std::string& strAccount, std::list<CAccountingEntry>& entries);
    bool AddAccountingEntry(const CAccountingEntry&);
    bool AddAccountingEntry(const CAccountingEntry&, CWalletDB *pwalletdb);
    template <typename ContainerType>
    bool DummySignTx(CMutableTransaction &txNew, const ContainerType &coins);

    static CFeeRate minTxFee;
    static CFeeRate fallbackFee;
    /**
     * Estimate the minimum fee considering user set parameters
     * and the required fee
     */
    static CAmount GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool);
    /**
     * Estimate the minimum fee considering required fee and targetFee or if 0
     * then fee estimation for nConfirmTarget
     */
    static CAmount GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool, CAmount targetFee);
    /**
     * Return the minimum required fee taking into account the
     * floating relay fee and user set minimum transaction fee
     */
    static CAmount GetRequiredFee(unsigned int nTxBytes);

    bool NewKeyPool();
    bool TopUpKeyPool(unsigned int kpSize = 0);
    void ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& keypool);
    void KeepKey(int64_t nIndex);
    void ReturnKey(int64_t nIndex, const CPubKey& pubkey);
    bool GetKeyFromPool(CPubKey &key);
    int64_t GetOldestKeyPoolTime();
    /**
     * Marks all keys in the keypool up to and including reserve_key as used.
     */
    void MarkReserveKeysAsUsed(int64_t keypool_id);
    const std::map<CKeyID, int64_t>& GetAllReserveKeys() const { return m_pool_key_to_index; }

    std::set< std::set<CTxDestination> > GetAddressGroupings();
    std::map<CTxDestination, CAmount> GetAddressBalances();

    std::set<CTxDestination> GetAccountAddresses(const std::string& strAccount) const;

    isminetype IsMine(const CTxIn& txin, const CTransaction& tx) const;
    /**
     * Returns amount of debit if the input matches the
     * filter, otherwise returns 0
     */
    CAmount GetDebit(const CTxIn& txin, const CTransaction&tx, const isminefilter& filter) const;
    isminetype IsMine(const CTxOut& txout) const;
    CAmount GetCredit(const CTxOut& txout, const isminefilter& filter) const;
    bool IsChange(const uint256& tx, const CTxOut& txout) const;
    CAmount GetChange(const uint256& tx, const CTxOut& txout) const;
    bool IsMine(const CTransaction& tx) const;
    /** should probably be renamed to IsRelevantToMe */
    bool IsFromMe(const CTransaction& tx) const;
    CAmount GetDebit(const CTransaction& tx, const isminefilter& filter) const;
    /** Returns whether all of the inputs match the filter */
    bool IsAllFromMe(const CTransaction& tx, const isminefilter& filter) const;
    CAmount GetCredit(const CTransaction& tx, const isminefilter& filter) const;
    CAmount GetChange(const CTransaction& tx) const;
    void SetBestChain(const CBlockLocator& loc) override;

    DBErrors LoadWallet(bool& fFirstRunRet);
    void AutoLockMasternodeCollaterals();
    DBErrors ZapWalletTx(std::vector<CWalletTx>& vWtx);
    DBErrors ZapSelectTx(std::vector<uint256>& vHashIn, std::vector<uint256>& vHashOut);

    // Remove all CSigmaEntry and CHDMint objects from WalletDB.
    DBErrors ZapSigmaMints();
    // Remove all Lelantus HDMint objects from WalletDB
    DBErrors ZapLelantusMints();

    bool SetAddressBook(const CTxDestination& address, const std::string& strName, const std::string& purpose);

    bool DelAddressBook(const CTxDestination& address);

    bool UpdatedTransaction(const uint256 &hashTx) override;
    const std::string& GetAccountName(const CScript& scriptPubKey) const;

    void Inventory(const uint256 &hash) override
    {
        {
            LOCK(cs_wallet);
            std::map<uint256, int>::iterator mi = mapRequestCount.find(hash);
            if (mi != mapRequestCount.end())
                (*mi).second++;
        }
    }

    void GetScriptForMining(boost::shared_ptr<CReserveScript> &script) override;
    void ResetRequestCount(const uint256 &hash) override
    {
        LOCK(cs_wallet);
        mapRequestCount[hash] = 0;
    };

    unsigned int GetKeyPoolSize()
    {
        AssertLockHeld(cs_wallet); // setKeyPool
        return setKeyPool.size();
    }

    bool SetDefaultKey(const CPubKey &vchPubKey);

    //! signify that a particular wallet feature is now used. this may change nWalletVersion and nWalletMaxVersion if those are lower
    bool SetMinVersion(enum WalletFeature, CWalletDB* pwalletdbIn = NULL, bool fExplicit = false);

    //! change which version we're allowed to upgrade to (note that this does not immediately imply upgrading to that format)
    bool SetMaxVersion(int nVersion);

    //! get the current wallet format (the oldest client version guaranteed to understand this wallet)
    int GetVersion() { LOCK(cs_wallet); return nWalletVersion; }

    //! Get wallet transactions that conflict with given transaction (spend same outputs)
    std::set<uint256> GetConflicts(const uint256& txid) const;

    //! Check if a given transaction has any of its outputs spent by another transaction in the wallet
    bool HasWalletSpend(const uint256& txid) const;

    //! Flush wallet (bitdb flush)
    void Flush(bool shutdown=false);

    //! Verify the wallet database and perform salvage if required
    static bool Verify();

    /**
     * Address book entry changed.
     * @note called with lock cs_wallet held.
     */
    boost::signals2::signal<void (CWallet *wallet, const CTxDestination
            &address, const std::string &label, bool isMine,
            const std::string &purpose,
            ChangeType status)> NotifyAddressBookChanged;

    /**
     * Wallet transaction added, removed or updated.
     * @note called with lock cs_wallet held.
     */
    boost::signals2::signal<void (CWallet *wallet, const uint256 &hashTx,
            ChangeType status)> NotifyTransactionChanged;
    /**
     * sigma/lelantus entry changed.
     * @note called with lock cs_wallet held.
     */
    boost::signals2::signal<void (CWallet *wallet, const std::string &pubCoin, const std::string &isUsed, ChangeType status)> NotifyZerocoinChanged;


    /** Show progress e.g. for rescan */
    boost::signals2::signal<void (const std::string &title, int nProgress)> ShowProgress;

    /** Watch-only address added */
    boost::signals2::signal<void (bool fHaveWatchOnly)> NotifyWatchonlyChanged;

    /** Payment code added */
    boost::signals2::signal<void (bip47::CPaymentCodeDescription)> NotifyPcodeCreated;

    /** Payment code labeled */
    boost::signals2::signal<void (std::string pcode, std::string label, bool removed)> NotifyPcodeLabeled;

    /** Unlock required (for example for adding a privkey to the wallet),  */
    boost::signals2::signal<void (int receiverAccountNum, CBlockIndex* pBlockIndex)> NotifyBip47KeysChanged;

    /** IS-lock received */
    boost::signals2::signal<void ()> NotifyISLockReceived;

    /** ChainLock received */
    boost::signals2::signal<void (int height)> NotifyChainLockReceived;

    /** Inquire whether this wallet broadcasts transactions. */
    bool GetBroadcastTransactions() const { return fBroadcastTransactions; }
    /** Set whether this wallet broadcasts transactions. */
    void SetBroadcastTransactions(bool broadcast) { fBroadcastTransactions = broadcast; }

    /* Mark a transaction (and it in-wallet descendants) as abandoned so its inputs may be respent. */
    bool AbandonTransaction(const uint256& hashTx);

    /** Mark a transaction as replaced by another transaction (e.g., BIP 125). */
    bool MarkReplaced(const uint256& originalHash, const uint256& newHash);

    /* Returns the wallets help message */
    static std::string GetWalletHelpString(bool showDebug);

    /* Initializes the wallet, returns a new CWallet instance or a null pointer in case of an error */
    static CWallet* CreateWalletFromFile(const std::string walletFile);
    static bool InitLoadWallet();

    /**
     * Wallet post-init setup
     * Gives the wallet a chance to register repetitive tasks and complete post-init tasks
     */
    void postInitProcess(boost::thread_group& threadGroup);

    /* Wallets parameter interaction */
    static bool ParameterInteraction();

    bool BackupWallet(const std::string& strDest);

    /* Set the HD chain model (chain child index counters) */
    bool SetHDChain(const CHDChain& chain, bool memonly, bool& upgradeChain, bool genNewKeyPool = true);
    bool SetHDChain(const CHDChain& chain, bool memonly) { bool upgradeChain = DEFAULT_UPGRADE_CHAIN; return SetHDChain(chain, memonly, upgradeChain); }
    const CHDChain& GetHDChain() { return hdChain; }

    bool SetMnemonicContainer(const MnemonicContainer& mnContainer, bool memonly);
    const MnemonicContainer& GetMnemonicContainer() { return mnemonicContainer; }

    bool EncryptMnemonicContainer(const CKeyingMaterial& vMasterKeyIn);
    bool DecryptMnemonicContainer(MnemonicContainer& mnContainer);

    void GenerateNewMnemonic();

    /* Returns true if HD is enabled */
    bool IsHDEnabled();

    /* Generates a new HD master key (will not be activated) */
    CPubKey GenerateNewHDMasterKey();

    /* Set the current HD master key (will reset the chain child index counters) */
    bool SetHDMasterKey(const CPubKey& key, const int cHDChainVersion=CHDChain().CURRENT_VERSION);

    /**************************************************************************/
    /* bip47 */
    /* Generates and strores a new payment code for receiving*/
    bip47::CPaymentCode GeneratePcode(std::string const & label);

    /*Prepares and sends a notification tx using Lelantus facilities*/
    CWalletTx PrepareAndSendNotificationTx(bip47::CPaymentCode const & theirPcode);

    /* Lists all receiving pcodes as tuples of (pcode, label, notification address) */
    std::vector<bip47::CPaymentCodeDescription> ListPcodes();

    /* Creates a payment channel for their payment code. */
    bip47::CPaymentChannel & SetupPchannel(bip47::CPaymentCode const & theirPcode);

    /* Stores the notification tx id into the wallet database */
    void SetNotificationTxId(bip47::CPaymentCode const & theirPcode, uint256 const & txid);

    /* Returns next unused address for their payment code. Throws if no payment channel was setup */
    CBitcoinAddress GetTheirNextAddress(bip47::CPaymentCode const & theirPcode) const;

    /* Returns and stores a next unused address for their payment code. Throws if no payment channel was setup */
    CBitcoinAddress GenerateTheirNextAddress(bip47::CPaymentCode const & theirPcode);

    /*Loads previously stored bip47 accounts */
    void LoadBip47Wallet();

    std::shared_ptr<bip47::CWallet const>  GetBip47Wallet() const;

    boost::optional<bip47::CPaymentCodeDescription> FindPcode(bip47::CPaymentCode const & pcode) const;
    boost::optional<bip47::CPaymentCodeDescription> FindPcode(CBitcoinAddress const & address) const;

    /*Marks address as used for a receiving bip47 account. Returns the account if found*/
    bip47::CAccountReceiver const * AddressUsed(CBitcoinAddress const & address);

    /*Checks if this is a BIP47 transaction and handles it. May send an unlock request if wallet is locked.*/
    void HandleBip47Transaction(CWalletTx const & wtx);

    /*Attaches a new label to a sending payment code.*/
    void LabelSendingPcode(bip47::CPaymentCode const & pcode, std::string const & label, bool remove = false);
    std::string GetSendingPcodeLabel(bip47::CPaymentCode const & pcode) const;

    /*Relabels an existing receiving payment code*/
    void LabelReceivingPcode(bip47::CPaymentCode const & pcode, std::string const & label);

    /*Sets used address number for a sending or receiving payment channel*/
    size_t SetUsedAddressNumber(bip47::CPaymentCode const & pcode, size_t number);

    void NotifyTransactionLock(const CTransaction &tx) override;
    void NotifyChainLock(const CBlockIndex* pindexChainLock) override;
};

/** A key allocated from the key pool. */
class CReserveKey : public CReserveScript
{
protected:
    CWallet* pwallet;
    int64_t nIndex;
    CPubKey vchPubKey;
public:
    CReserveKey(CWallet* pwalletIn)
    {
        nIndex = -1;
        pwallet = pwalletIn;
    }

    ~CReserveKey()
    {
        ReturnKey();
    }

    void ReturnKey();
    bool GetReservedKey(CPubKey &pubkey);
    void KeepKey();
    void KeepScript() { KeepKey(); }
};


/**
 * Account information.
 * Stored in wallet with key "acc"+string account name.
 */
class CAccount
{
public:
    CPubKey vchPubKey;

    CAccount()
    {
        SetNull();
    }

    void SetNull()
    {
        vchPubKey = CPubKey();
    }

    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(vchPubKey);
    }
};

bool CompSigmaHeight(const CSigmaEntry& a, const CSigmaEntry& b);
bool CompSigmaID(const CSigmaEntry& a, const CSigmaEntry& b);

// Helper for producing a bunch of max-sized low-S signatures (eg 72 bytes)
// ContainerType is meant to hold pair<CWalletTx *, int>, and be iterable
// so that each entry corresponds to each vIn, in order.
template <typename ContainerType>
bool CWallet::DummySignTx(CMutableTransaction &txNew, const ContainerType &coins)
{
    // Fill in dummy signatures for fee calculation.
    int nIn = 0;
    for (const auto& coin : coins)
    {
        const CScript& scriptPubKey = coin.first->tx->vout[coin.second].scriptPubKey;
        SignatureData sigdata;

        if (!ProduceSignature(DummySignatureCreator(this), scriptPubKey, sigdata))
        {
            return false;
        } else {
            UpdateTransaction(txNew, nIn, sigdata);
        }

        nIn++;
    }
    return true;
}

CWalletTx PrepareAndSendNotificationTx(CWallet* pwallet, bip47::CPaymentCode const & theirPcode);

#endif // BITCOIN_WALLET_WALLET_H

<MSG> Applied review comments

<DFF> @@ -827,6 +827,10 @@ public:
     CAmount GetNeedsToBeAnonymizedBalance(CAmount nMinBalance = 0) const;
     CAmount GetDenominatedBalance(bool unconfirmed=false) const;
 
+    // Returns a list of unspent and verified coins, I.E. coins which are ready 
+    // to be spent.
+    std::list<CZerocoinEntryV3> GetAvailableCoins() const;
+
     /** \brief Selects coins to spend, and coins to re-mint based on the required amount to spend, provided by the user. As the lower denomination now is 0.1 zcoin, user's request will be rounded up to the nearest 0.1. This difference between the user's requested value, and the actually spent value will be left to the miners as a fee.
      * \param[in] required Required amount to spend.
      * \param[out] coinsToSpend_out Coins which user needs to spend.

{'commit': 'diff --git a/Dockerfile b/Dockerfile\nindex d6f0740d5..556524b15 100644\n--- a/Dockerfile\n+++ b/Dockerfile\n@@ -57,8 +57,16 @@ USER zcoind\n RUN mkdir /home/zcoind/.zcoin\n VOLUME [ "/home/zcoind/.zcoin" ]\n \n+# Main network ports\n EXPOSE 8168\n EXPOSE 8888\n+\n+# Test network ports\n+EXPOSE 18168\n+EXPOSE 18888\n+\n+# Regression test network ports\n EXPOSE 18444\n+EXPOSE 28888\n \n ENTRYPOINT [ "/usr/bin/zcoind" ]\ndiff --git a/configure.ac b/configure.ac\nindex 2b77b8f61..fa5ccea87 100644\n--- a/configure.ac\n+++ b/configure.ac\n@@ -1159,7 +1159,7 @@ if test x$need_bundled_univalue = xyes; then\n fi\n \n AX_SUBDIRS_CONFIGURE([src/secp256k1], [[--disable-shared], [--with-pic], [--with-bignum=no], [--enable-module-recovery], [--enable-experimental], [--enable-module-ecdh]])\n-AX_SUBDIRS_CONFIGURE([src/tor], [[--disable-unittests], [--disable-system-torrc], [--disable-systemd], [--disable-lzma], [--disable-zstd], [--disable-asciidoc], [--with-openssl-dir=$($PKG_CONFIG --variable=libdir openssl)], [CFLAGS=$($PKG_CONFIG --cflags openssl) -O2]])\n+AX_SUBDIRS_CONFIGURE([src/tor], [[--disable-unittests], [--disable-system-torrc], [--disable-systemd], [--disable-lzma], [--disable-zstd], [--disable-asciidoc]])\n \n \n AC_OUTPUT\ndiff --git a/contrib/debian/rules b/contrib/debian/rules\nold mode 100644\nnew mode 100755\ndiff --git a/contrib/devtools/check-doc.py b/contrib/devtools/check-doc.py\nold mode 100644\nnew mode 100755\ndiff --git a/contrib/devtools/clang-format-diff.py b/contrib/devtools/clang-format-diff.py\nold mode 100644\nnew mode 100755\ndiff --git a/contrib/devtools/clang-format.py b/contrib/devtools/clang-format.py\nold mode 100644\nnew mode 100755\ndiff --git a/contrib/devtools/fix-copyright-headers.py b/contrib/devtools/fix-copyright-headers.py\nold mode 100644\nnew mode 100755\ndiff --git a/contrib/devtools/git-subtree-check.sh b/contrib/devtools/git-subtree-check.sh\nold mode 100644\nnew mode 100755\ndiff --git a/contrib/devtools/github-merge.py b/contrib/devtools/github-merge.py\nold mode 100644\nnew mode 100755\ndiff --git a/contrib/devtools/optimize-pngs.py b/contrib/devtools/optimize-pngs.py\nold mode 100644\nnew mode 100755\ndiff --git a/contrib/devtools/security-check.py b/contrib/devtools/security-check.py\nold mode 100644\nnew mode 100755\ndiff --git a/contrib/devtools/symbol-check.py b/contrib/devtools/symbol-check.py\nold mode 100644\nnew mode 100755\ndiff --git a/contrib/devtools/test-security-check.py b/contrib/devtools/test-security-check.py\nold mode 100644\nnew mode 100755\ndiff --git a/contrib/devtools/update-translations.py b/contrib/devtools/update-translations.py\nold mode 100644\nnew mode 100755\ndiff --git a/contrib/linearize/linearize-data.py b/contrib/linearize/linearize-data.py\nold mode 100644\nnew mode 100755\ndiff --git a/contrib/linearize/linearize-hashes.py b/contrib/linearize/linearize-hashes.py\nold mode 100644\nnew mode 100755\ndiff --git a/contrib/macdeploy/custom_dsstore.py b/contrib/macdeploy/custom_dsstore.py\nold mode 100644\nnew mode 100755\ndiff --git a/contrib/macdeploy/detached-sig-apply.sh b/contrib/macdeploy/detached-sig-apply.sh\nold mode 100644\nnew mode 100755\ndiff --git a/contrib/macdeploy/detached-sig-create.sh b/contrib/macdeploy/detached-sig-create.sh\nold mode 100644\nnew mode 100755\ndiff --git a/contrib/macdeploy/macdeployqtplus b/contrib/macdeploy/macdeployqtplus\nold mode 100644\nnew mode 100755\ndiff --git a/contrib/qt_translations.py b/contrib/qt_translations.py\nold mode 100644\nnew mode 100755\ndiff --git a/contrib/seeds/generate-seeds.py b/contrib/seeds/generate-seeds.py\nold mode 100644\nnew mode 100755\ndiff --git a/contrib/seeds/makeseeds.py b/contrib/seeds/makeseeds.py\nold mode 100644\nnew mode 100755\ndiff --git a/contrib/spendfrom/spendfrom.py b/contrib/spendfrom/spendfrom.py\nold mode 100644\nnew mode 100755\ndiff --git a/contrib/testgen/gen_base58_test_vectors.py b/contrib/testgen/gen_base58_test_vectors.py\nold mode 100644\nnew mode 100755\ndiff --git a/contrib/tidy_datadir.sh b/contrib/tidy_datadir.sh\nold mode 100644\nnew mode 100755\ndiff --git a/contrib/verify-commits/gpg.sh b/contrib/verify-commits/gpg.sh\nold mode 100644\nnew mode 100755\ndiff --git a/contrib/verify-commits/pre-push-hook.sh b/contrib/verify-commits/pre-push-hook.sh\nold mode 100644\nnew mode 100755\ndiff --git a/contrib/verify-commits/verify-commits.sh b/contrib/verify-commits/verify-commits.sh\nold mode 100644\nnew mode 100755\ndiff --git a/contrib/verifybinaries/verify.sh b/contrib/verifybinaries/verify.sh\nold mode 100644\nnew mode 100755\ndiff --git a/contrib/zmq/zmq_sub.py b/contrib/zmq/zmq_sub.py\nold mode 100644\nnew mode 100755\ndiff --git a/src/Makefile.am b/src/Makefile.am\nindex 90dfbec08..ea9960117 100644\n--- a/src/Makefile.am\n+++ b/src/Makefile.am\n@@ -465,13 +465,19 @@ libsigma_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)\n libsigma_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)\n libsigma_a_SOURCES = \\\n   libzerocoin/common/GeneratorVector.h \\\n+  libzerocoin/common/GeneratorVector.hpp \\\n   libzerocoin/sigma/R1Proof.h \\\n   libzerocoin/sigma/R1ProofGenerator.h \\\n+  libzerocoin/sigma/R1ProofGenerator.hpp \\\n   libzerocoin/sigma/R1ProofVerifier.h \\\n+  libzerocoin/sigma/R1ProofVerifier.hpp \\\n   libzerocoin/sigma/SigmaPlusProof.h \\\n   libzerocoin/sigma/SigmaPlusProver.h \\\n+  libzerocoin/sigma/SigmaPlusProver.hpp \\\n   libzerocoin/sigma/SigmaPlusVerifier.h \\\n+  libzerocoin/sigma/SigmaPlusVerifier.hpp \\\n   libzerocoin/sigma/SigmaPrimitives.h \\\n+  libzerocoin/sigma/SigmaPrimitives.hpp \\\n   libzerocoin/sigma/Coin.h \\\n   libzerocoin/sigma/Coin.cpp \\\n   libzerocoin/sigma/CoinSpend.cpp \\\n@@ -479,7 +485,8 @@ libsigma_a_SOURCES = \\\n   libzerocoin/sigma/SpendMetaDataV3.cpp \\\n   libzerocoin/sigma/SpendMetaDataV3.h \\\n   libzerocoin/sigma/Params.h \\\n-  libzerocoin/sigma/Params.cpp\n+  libzerocoin/sigma/Params.cpp \\\n+  libzerocoin/sigma/OpenSSL_context.h\n \n if GLIBC_BACK_COMPAT\n libbitcoin_util_a_SOURCES += compat/glibc_compat.cpp\ndiff --git a/src/libzerocoin/sigma/test/coin_spend_tests.cpp b/src/libzerocoin/sigma/test/coin_spend_tests.cpp\nindex c65abd757..03104b8ff 100644\n--- a/src/libzerocoin/sigma/test/coin_spend_tests.cpp\n+++ b/src/libzerocoin/sigma/test/coin_spend_tests.cpp\n@@ -32,10 +32,10 @@ BOOST_AUTO_TEST_CASE(serialize_deserialize_test)\n     // deserialize\n     sigma::CoinSpendV3 new_coin(params, serialized);\n \n-    BOOST_TEST(coin.getAccumulatorBlockHash().Compare(new_coin.getAccumulatorBlockHash())==0);\n-    BOOST_TEST(coin.getCoinSerialNumber() == new_coin.getCoinSerialNumber());\n-    BOOST_TEST(coin.getDenomination() == new_coin.getDenomination());\n-    BOOST_TEST(coin.getVersion() == new_coin.getVersion());\n+    BOOST_CHECK(coin.getAccumulatorBlockHash().Compare(new_coin.getAccumulatorBlockHash())==0);\n+    BOOST_CHECK(coin.getCoinSerialNumber() == new_coin.getCoinSerialNumber());\n+    BOOST_CHECK(coin.getDenomination() == new_coin.getDenomination());\n+    BOOST_CHECK(coin.getVersion() == new_coin.getVersion());\n }\n \n BOOST_AUTO_TEST_CASE(different_anonymity_set)\n@@ -55,7 +55,7 @@ BOOST_AUTO_TEST_CASE(different_anonymity_set)\n     sigma::CoinSpendV3 coin(params,privcoin,anonymity_set, metaData);\n     sigma::CoinSpendV3 coin2(params,privcoin,anonymity_set, metaData);\n \n-    BOOST_TEST(coin.getCoinSerialNumber() == coin2.getCoinSerialNumber());\n+    BOOST_CHECK(coin.getCoinSerialNumber() == coin2.getCoinSerialNumber());\n \n     // use different anonymity_set\n     const sigma::PrivateCoinV3 privcoin3(params, sigma::CoinDenominationV3::SIGMA_DENOM_1);\n@@ -68,7 +68,7 @@ BOOST_AUTO_TEST_CASE(different_anonymity_set)\n \n     sigma::CoinSpendV3 coin3(params, privcoin, anonymity_set3, metaData);\n \n-    BOOST_TEST(coin.getCoinSerialNumber() == coin3.getCoinSerialNumber());    \n+    BOOST_CHECK(coin.getCoinSerialNumber() == coin3.getCoinSerialNumber());    \n }\n \n BOOST_AUTO_TEST_CASE(out_of_anonymity_set)\n@@ -109,7 +109,7 @@ BOOST_AUTO_TEST_CASE(verify_test)\n  \n     sigma::CoinSpendV3 spend_coin(params, privcoin, anonymity_set, metaData);\n \n-    BOOST_TEST(spend_coin.Verify(anonymity_set, metaData));\n+    BOOST_CHECK(spend_coin.Verify(anonymity_set, metaData));\n }\n \n BOOST_AUTO_TEST_CASE(verify_test_valid_set_plus_one)\n@@ -138,7 +138,7 @@ BOOST_AUTO_TEST_CASE(verify_test_valid_set_plus_one)\n     anonymity_set2.push_back(pubcoin);\n     anonymity_set2.push_back(pubcoin2);\n \n-    BOOST_TEST(!spend_coin.Verify(anonymity_set2, metaData));\n+    BOOST_CHECK(!spend_coin.Verify(anonymity_set2, metaData));\n }\n \n BOOST_AUTO_TEST_CASE(verify_test_valid_set_subtract_one)\n@@ -167,7 +167,7 @@ BOOST_AUTO_TEST_CASE(verify_test_valid_set_subtract_one)\n     std::vector<sigma::PublicCoinV3> anonymity_set2;\n     anonymity_set2.push_back(pubcoin);\n \n-    BOOST_TEST(!spend_coin.Verify(anonymity_set2, metaData));\n+    BOOST_CHECK(!spend_coin.Verify(anonymity_set2, metaData));\n }\n \n BOOST_AUTO_TEST_CASE(verify_test_with_accumulatorBlockHash)\n@@ -185,7 +185,7 @@ BOOST_AUTO_TEST_CASE(verify_test_with_accumulatorBlockHash)\n     sigma::SpendMetaDataV3 metaData(0, uint256S("120"), uint256S("120"));\n     sigma::CoinSpendV3 spend_coin(params, privcoin, anonymity_set, metaData);\n \n-    BOOST_TEST(spend_coin.Verify(anonymity_set, metaData));\n+    BOOST_CHECK(spend_coin.Verify(anonymity_set, metaData));\n }\n \n BOOST_AUTO_TEST_SUITE_END()\ndiff --git a/src/libzerocoin/sigma/test/primitives_tests.cpp b/src/libzerocoin/sigma/test/primitives_tests.cpp\nindex 79e33d360..35bff2dee 100644\n--- a/src/libzerocoin/sigma/test/primitives_tests.cpp\n+++ b/src/libzerocoin/sigma/test/primitives_tests.cpp\n@@ -23,7 +23,7 @@ BOOST_AUTO_TEST_CASE(pedersen_commitment_test)\n     secp_primitives::GroupElement c;\n     c = sigma::SigmaPrimitives<secp_primitives::Scalar,secp_primitives::GroupElement>::commit(g, x, h, r);\n \n-    BOOST_TEST(expected == c);\n+    BOOST_CHECK(expected == c);\n }\n \n BOOST_AUTO_TEST_CASE(homomorphic_test)\n@@ -83,7 +83,7 @@ BOOST_AUTO_TEST_CASE(commit2_test)\n     secp_primitives::GroupElement resulted;\n     sigma::SigmaPrimitives<secp_primitives::Scalar,secp_primitives::GroupElement>::commit(g,h_,x_,r,resulted);\n \n-    BOOST_TEST(expected == resulted);\n+    BOOST_CHECK(expected == resulted);\n }\n \n BOOST_AUTO_TEST_CASE(commit2_vs_test)\n@@ -113,7 +113,7 @@ BOOST_AUTO_TEST_CASE(commit2_vs_test)\n     secp_primitives::GroupElement resulted;\n     sigma::SigmaPrimitives<secp_primitives::Scalar,secp_primitives::GroupElement>::commit(g,h_,x_,r,resulted);\n \n-    BOOST_TEST(expected == resulted);\n+    BOOST_CHECK(expected == resulted);\n }\n \n BOOST_AUTO_TEST_CASE(commit2_homomorphic_test)\ndiff --git a/src/libzerocoin/sigma/test/sigma_primitive_types_test.cpp b/src/libzerocoin/sigma/test/sigma_primitive_types_test.cpp\nindex fb8d3ba67..fb24b8edb 100644\n--- a/src/libzerocoin/sigma/test/sigma_primitive_types_test.cpp\n+++ b/src/libzerocoin/sigma/test/sigma_primitive_types_test.cpp\n@@ -17,7 +17,7 @@ BOOST_AUTO_TEST_CASE(scalar_test)\n     secp_primitives::Scalar s2(s);\n     \n     // Make sure that copy constructor works correctly.\n-    BOOST_TEST(s == s2);\n+    BOOST_CHECK(s == s2);\n }\n \n BOOST_AUTO_TEST_SUITE_END()\ndiff --git a/src/main.cpp b/src/main.cpp\nindex 1e026af97..d52e9dafd 100644\n--- a/src/main.cpp\n+++ b/src/main.cpp\n@@ -1417,10 +1417,13 @@ bool AcceptToMemoryPoolWorker(\n                 //                LogPrintf("cause by -> non-BIP68-final!\\n");\n                 //                return state.DoS(0, false, REJECT_NONSTANDARD, "non-BIP68-final");\n                 //            }\n+            } else if (tx.IsZerocoinSpendV3()){\n+                nValueIn = GetSpendTransactionInputV3(tx);\n             }\n+\n         } // LOCK\n \n-        if (!tx.IsZerocoinSpend() && !tx.IsZerocoinSpendV3() && fCheckInputs) {\n+        if (!tx.IsZerocoinSpend() && fCheckInputs) {\n \n             // Check for non-standard pay-to-script-hash in inputs\n             if (!fTestNet && fRequireStandard && !AreInputsStandard(tx, view)) {\n@@ -1441,18 +1444,24 @@ bool AcceptToMemoryPoolWorker(\n             double nPriorityDummy = 0;\n             pool.ApplyDeltas(hash, nPriorityDummy, nModifiedFees);\n \n-            CAmount inChainInputValue;\n-            double dPriority = view.GetPriority(tx, chainActive.Height(), inChainInputValue);\n-\n-            // Keep track of transactions that spend a coinbase, which we re-scan\n-            // during reorgs to ensure COINBASE_MATURITY is still met.\n+            CAmount inChainInputValue = 0;\n+            double dPriority = 0;\n             bool fSpendsCoinbase = false;\n-            BOOST_FOREACH(const CTxIn &txin, tx.vin) { const CCoins *coins = view.AccessCoins(txin.prevout.hash);\n-                                                       if (coins->IsCoinBase()) {\n-                                                           fSpendsCoinbase = true;\n-                                                           break;\n-                                                       }\n-                                                     }\n+            if(!tx.IsZerocoinSpendV3()) {\n+                dPriority = view.GetPriority(tx, chainActive.Height(), inChainInputValue);\n+\n+                // Keep track of transactions that spend a coinbase, which we re-scan\n+                // during reorgs to ensure COINBASE_MATURITY is still met.\n+                BOOST_FOREACH(\n+                const CTxIn& txin, tx.vin) {\n+                    const CCoins* coins = view.AccessCoins(txin.prevout.hash);\n+                    if (coins->IsCoinBase()) {\n+                        fSpendsCoinbase = true;\n+                        break;\n+                    }\n+                }\n+            }\n+\n             CTxMemPoolEntry entry(tx, nFees, GetTime(), dPriority, chainActive.Height(), pool.HasNoInputsOf(tx),\n                                   inChainInputValue, fSpendsCoinbase, nSigOpsCost, lp);\n             \n@@ -1745,98 +1754,7 @@ bool AcceptToMemoryPoolWorker(\n                 if (!pool.exists(hash))\n                     return state.DoS(0, false, REJECT_INSUFFICIENTFEE, "mempool full");\n             }\n-        } else if (tx.IsZerocoinSpendV3()) {\n-            LockPoints lp;\n-            double dPriority = 0;\n-            double fSpendsCoinbase = false;\n-            CAmount inChainInputValue = 0;\n-\n-            CAmount nValueOut = tx.GetValueOut();\n-            nValueIn = GetSpendTransactionInputV3(tx);\n-            CAmount nFees = nValueIn - nValueOut;\n-            CAmount nModifiedFees = nFees;\n-            double nPriorityDummy = 0;\n-            pool.ApplyDeltas(hash, nPriorityDummy, nModifiedFees);\n-\n-            int64_t txMinFee = tx.GetMinFee(1000, true, GMF_RELAY);;\n-            if (fLimitFree && nFees < txMinFee) {\n-                LogPrintf("not enough fee, nFees=%d, txMinFee=%d\\n", nFees, txMinFee);\n-                return state.DoS(0, false, REJECT_INSUFFICIENTFEE, "not enough fee", false, strprintf("nFees=%d, txMinFee=%d", nFees, txMinFee));\n-            }\n-\n-            int64_t nSigOpsCost = GetLegacySigOpCount(tx);\n-            CTxMemPoolEntry entry(tx, nFees, GetTime(), dPriority, chainActive.Height(), pool.HasNoInputsOf(tx),\n-                                  inChainInputValue, fSpendsCoinbase, nSigOpsCost, lp);\n-\n-            unsigned int nSize = entry.GetTxSize();\n-\n-            if (fLimitFree && nFees < CTransaction::nMinRelayTxFee) {\n-                static CCriticalSection csFreeLimiter;\n-                static double dFreeCount;\n-                static int64_t nLastTime;\n-                int64_t nNow = GetTime();\n-\n-                LOCK(csFreeLimiter);\n-\n-                // Use an exponentially decaying ~10-minute window:\n-                dFreeCount *= pow(1.0 - 1.0 / 600.0, (double) (nNow - nLastTime));\n-                nLastTime = nNow;\n-                // -limitfreerelay unit is thousand-bytes-per-minute\n-                // At default rate it would take over a month to fill 1GB\n-                if (dFreeCount + nSize >= GetArg("-limitfreerelay", DEFAULT_LIMITFREERELAY) * 10 * 1000) {\n-                    LogPrintf("cause by -> rate limited free transaction\\n");\n-                    return state.DoS(0, false, REJECT_INSUFFICIENTFEE, "rate limited free transaction");\n-                }\n-                LogPrint("mempool", "Rate limit dFreeCount: %g => %g\\n", dFreeCount, dFreeCount + nSize);\n-                dFreeCount += nSize;\n-            }\n-\n-            if (nAbsurdFee && nFees > CTransaction::nMinRelayTxFee * 1000) {\n-                return state.Invalid(false, REJECT_HIGHFEE, "insane fee",\n-                                     strprintf("%d > %d", nFees, CTransaction::nMinRelayTxFee * 1000));\n-            }\n-\n-            // Check against previous transactions\n-            // This is done last to help prevent CPU exhaustion denial-of-service attacks.\n-            unsigned int scriptVerifyFlags = SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC;\n-            //        if (!Params().RequireStandard()) {\n-            //            scriptVerifyFlags = GetArg("-promiscuousmempoolflags", scriptVerifyFlags);\n-            //        }\n-            PrecomputedTransactionData txdata(tx);\n-            if (!CheckInputs(tx, state, view, true, scriptVerifyFlags, true, txdata)) {\n-                // SCRIPT_VERIFY_CLEANSTACK requires SCRIPT_VERIFY_WITNESS, so we\n-                // need to turn both off, and compare against just turning off CLEANSTACK\n-                // to see if the failure is specifically due to witness validation.\n-                //            if (tx.wit.IsNull() && CheckInputs(tx, state, view, true,\n-                //                                               scriptVerifyFlags &\n-                //                                               ~(SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_CLEANSTACK),\n-                //                                               true, txdata) &&\n-                //                !CheckInputs(tx, state, view, true, scriptVerifyFlags & ~SCRIPT_VERIFY_CLEANSTACK, true, txdata)) {\n-                //                // Only the witness is missing, so the transaction itself may be fine.\n-                //                state.SetCorruptionPossible();\n-                //            }\n-                LogPrintf("CheckInputs --> Failed!\\n");\n-                return false;\n-            }\n-\n-            // Check again against just the consensus-critical mandatory script\n-            // verification flags, in case of bugs in the standard flags that cause\n-            // transactions to pass as valid when they\'re actually invalid. For\n-            // instance the STRICTENC flag was incorrectly allowing certain\n-            // CHECKSIG NOT scripts to pass, even though they were invalid.\n-            //\n-            // There is a similar check in CreateNewBlock() to prevent creating\n-            // invalid blocks, however allowing such transactions into the mempool\n-            // can be exploited as a DoS attack.\n-            //        if (!CheckInputs(tx, state, view, true, MANDATORY_SCRIPT_VERIFY_FLAGS, true, txdata)) {\n-            //            return error(\n-            //                    "%s: BUG! PLEASE REPORT THIS! ConnectInputs failed against MANDATORY but not STANDARD flags %s, %s",\n-            //                    __func__, hash.ToString(), FormatStateMessage(state));\n-            //        }\n-\n-            CTxMemPool::setEntries setAncestors;\n-            pool.addUnchecked(hash, entry, setAncestors, !IsInitialBlockDownload());\n-        } else {\n+        }  else {\n             LockPoints lp;\n             double dPriority = 0;\n             double fSpendsCoinbase = false;\ndiff --git a/src/main.h b/src/main.h\nindex a1af948eb..63ba001f5 100644\n--- a/src/main.h\n+++ b/src/main.h\n@@ -55,7 +55,7 @@ static const bool DEFAULT_WHITELISTRELAY = true;\n static const bool DEFAULT_WHITELISTFORCERELAY = true;\n /** Default for -minrelaytxfee, minimum relay fee for transactions */\n //btzc: update zcoin fee\n-static const unsigned int DEFAULT_MIN_RELAY_TX_FEE = CENT / 10; //0.001 zcoin,\n+static const unsigned int DEFAULT_MIN_RELAY_TX_FEE = CENT / 1000; //0.00001 zcoin,\n static const unsigned int MAX_STANDARD_TX_SIZE = 300000;\n //! -maxtxfee default\n static const CAmount DEFAULT_TRANSACTION_MAXFEE = 1000 * CENT;\ndiff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp\nindex 7bba86c21..3585d9124 100644\n--- a/src/qt/sendcoinsdialog.cpp\n+++ b/src/qt/sendcoinsdialog.cpp\n@@ -103,7 +103,7 @@ SendCoinsDialog::SendCoinsDialog(const PlatformStyle *platformStyle, QWidget *pa\n         settings.setValue("nTransactionFee", (qint64)DEFAULT_TRANSACTION_FEE);\n     if (!settings.contains("fPayOnlyMinFee"))\n         settings.setValue("fPayOnlyMinFee", false);\n-    ui->customFee->setValue(CENT/10);\n+    ui->customFee->setValue(DEFAULT_MIN_RELAY_TX_FEE);\n     ui->checkBoxMinimumFee->setChecked(true);\n     minimizeFeeSection(false);\n }\ndiff --git a/src/secp256k1/build-aux/m4/m4_ax_cxx_compile_stdcxx.m4 b/src/secp256k1/build-aux/m4/m4_ax_cxx_compile_stdcxx.m4\nnew file mode 100644\nindex 000000000..43087b2e6\n--- /dev/null\n+++ b/src/secp256k1/build-aux/m4/m4_ax_cxx_compile_stdcxx.m4\n@@ -0,0 +1,951 @@\n+# ===========================================================================\n+#  https://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx.html\n+# ===========================================================================\n+#\n+# SYNOPSIS\n+#\n+#   AX_CXX_COMPILE_STDCXX(VERSION, [ext|noext], [mandatory|optional])\n+#\n+# DESCRIPTION\n+#\n+#   Check for baseline language coverage in the compiler for the specified\n+#   version of the C++ standard.  If necessary, add switches to CXX and\n+#   CXXCPP to enable support.  VERSION may be \'11\' (for the C++11 standard)\n+#   or \'14\' (for the C++14 standard).\n+#\n+#   The second argument, if specified, indicates whether you insist on an\n+#   extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g.\n+#   -std=c++11).  If neither is specified, you get whatever works, with\n+#   preference for an extended mode.\n+#\n+#   The third argument, if specified \'mandatory\' or if left unspecified,\n+#   indicates that baseline support for the specified C++ standard is\n+#   required and that the macro should error out if no mode with that\n+#   support is found.  If specified \'optional\', then configuration proceeds\n+#   regardless, after defining HAVE_CXX${VERSION} if and only if a\n+#   supporting mode is found.\n+#\n+# LICENSE\n+#\n+#   Copyright (c) 2008 Benjamin Kosnik <bkoz@redhat.com>\n+#   Copyright (c) 2012 Zack Weinberg <zackw@panix.com>\n+#   Copyright (c) 2013 Roy Stogner <roystgnr@ices.utexas.edu>\n+#   Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov <sokolov@google.com>\n+#   Copyright (c) 2015 Paul Norman <penorman@mac.com>\n+#   Copyright (c) 2015 Moritz Klammler <moritz@klammler.eu>\n+#   Copyright (c) 2016, 2018 Krzesimir Nowak <qdlacz@gmail.com>\n+#   Copyright (c) 2019 Enji Cooper <yaneurabeya@gmail.com>\n+#\n+#   Copying and distribution of this file, with or without modification, are\n+#   permitted in any medium without royalty provided the copyright notice\n+#   and this notice are preserved.  This file is offered as-is, without any\n+#   warranty.\n+\n+#serial 11\n+\n+dnl  This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro\n+dnl  (serial version number 13).\n+\n+AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl\n+  m4_if([$1], [11], [ax_cxx_compile_alternatives="11 0x"],\n+        [$1], [14], [ax_cxx_compile_alternatives="14 1y"],\n+        [$1], [17], [ax_cxx_compile_alternatives="17 1z"],\n+        [m4_fatal([invalid first argument `$1\' to AX_CXX_COMPILE_STDCXX])])dnl\n+  m4_if([$2], [], [],\n+        [$2], [ext], [],\n+        [$2], [noext], [],\n+        [m4_fatal([invalid second argument `$2\' to AX_CXX_COMPILE_STDCXX])])dnl\n+  m4_if([$3], [], [ax_cxx_compile_cxx$1_required=true],\n+        [$3], [mandatory], [ax_cxx_compile_cxx$1_required=true],\n+        [$3], [optional], [ax_cxx_compile_cxx$1_required=false],\n+        [m4_fatal([invalid third argument `$3\' to AX_CXX_COMPILE_STDCXX])])\n+  AC_LANG_PUSH([C++])dnl\n+  ac_success=no\n+\n+  m4_if([$2], [noext], [], [dnl\n+  if test x$ac_success = xno; then\n+    for alternative in ${ax_cxx_compile_alternatives}; do\n+      switch="-std=gnu++${alternative}"\n+      cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch])\n+      AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch,\n+                     $cachevar,\n+        [ac_save_CXX="$CXX"\n+         CXX="$CXX $switch"\n+         AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],\n+          [eval $cachevar=yes],\n+          [eval $cachevar=no])\n+         CXX="$ac_save_CXX"])\n+      if eval test x\\$$cachevar = xyes; then\n+        CXX="$CXX $switch"\n+        if test -n "$CXXCPP" ; then\n+          CXXCPP="$CXXCPP $switch"\n+        fi\n+        ac_success=yes\n+        break\n+      fi\n+    done\n+  fi])\n+\n+  m4_if([$2], [ext], [], [dnl\n+  if test x$ac_success = xno; then\n+    dnl HP\'s aCC needs +std=c++11 according to:\n+    dnl http://h21007.www2.hp.com/portal/download/files/unprot/aCxx/PDF_Release_Notes/769149-001.pdf\n+    dnl Cray\'s crayCC needs "-h std=c++11"\n+    for alternative in ${ax_cxx_compile_alternatives}; do\n+      for switch in -std=c++${alternative} +std=c++${alternative} "-h std=c++${alternative}"; do\n+        cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch])\n+        AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch,\n+                       $cachevar,\n+          [ac_save_CXX="$CXX"\n+           CXX="$CXX $switch"\n+           AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],\n+            [eval $cachevar=yes],\n+            [eval $cachevar=no])\n+           CXX="$ac_save_CXX"])\n+        if eval test x\\$$cachevar = xyes; then\n+          CXX="$CXX $switch"\n+          if test -n "$CXXCPP" ; then\n+            CXXCPP="$CXXCPP $switch"\n+          fi\n+          ac_success=yes\n+          break\n+        fi\n+      done\n+      if test x$ac_success = xyes; then\n+        break\n+      fi\n+    done\n+  fi])\n+  AC_LANG_POP([C++])\n+  if test x$ax_cxx_compile_cxx$1_required = xtrue; then\n+    if test x$ac_success = xno; then\n+      AC_MSG_ERROR([*** A compiler with support for C++$1 language features is required.])\n+    fi\n+  fi\n+  if test x$ac_success = xno; then\n+    HAVE_CXX$1=0\n+    AC_MSG_NOTICE([No compiler with C++$1 support was found])\n+  else\n+    HAVE_CXX$1=1\n+    AC_DEFINE(HAVE_CXX$1,1,\n+              [define if the compiler supports basic C++$1 syntax])\n+  fi\n+  AC_SUBST(HAVE_CXX$1)\n+])\n+\n+\n+dnl  Test body for checking C++11 support\n+\n+m4_define([_AX_CXX_COMPILE_STDCXX_testbody_11],\n+  _AX_CXX_COMPILE_STDCXX_testbody_new_in_11\n+)\n+\n+\n+dnl  Test body for checking C++14 support\n+\n+m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14],\n+  _AX_CXX_COMPILE_STDCXX_testbody_new_in_11\n+  _AX_CXX_COMPILE_STDCXX_testbody_new_in_14\n+)\n+\n+m4_define([_AX_CXX_COMPILE_STDCXX_testbody_17],\n+  _AX_CXX_COMPILE_STDCXX_testbody_new_in_11\n+  _AX_CXX_COMPILE_STDCXX_testbody_new_in_14\n+  _AX_CXX_COMPILE_STDCXX_testbody_new_in_17\n+)\n+\n+dnl  Tests for new features in C++11\n+\n+m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_11], [[\n+\n+// If the compiler admits that it is not ready for C++11, why torture it?\n+// Hopefully, this will speed up the test.\n+\n+#ifndef __cplusplus\n+\n+#error "This is not a C++ compiler"\n+\n+#elif __cplusplus < 201103L\n+\n+#error "This is not a C++11 compiler"\n+\n+#else\n+\n+namespace cxx11\n+{\n+\n+  namespace test_static_assert\n+  {\n+\n+    template <typename T>\n+    struct check\n+    {\n+      static_assert(sizeof(int) <= sizeof(T), "not big enough");\n+    };\n+\n+  }\n+\n+  namespace test_final_override\n+  {\n+\n+    struct Base\n+    {\n+      virtual ~Base() {}\n+      virtual void f() {}\n+    };\n+\n+    struct Derived : public Base\n+    {\n+      virtual ~Derived() override {}\n+      virtual void f() override {}\n+    };\n+\n+  }\n+\n+  namespace test_double_right_angle_brackets\n+  {\n+\n+    template < typename T >\n+    struct check {};\n+\n+    typedef check<void> single_type;\n+    typedef check<check<void>> double_type;\n+    typedef check<check<check<void>>> triple_type;\n+    typedef check<check<check<check<void>>>> quadruple_type;\n+\n+  }\n+\n+  namespace test_decltype\n+  {\n+\n+    int\n+    f()\n+    {\n+      int a = 1;\n+      decltype(a) b = 2;\n+      return a + b;\n+    }\n+\n+  }\n+\n+  namespace test_type_deduction\n+  {\n+\n+    template < typename T1, typename T2 >\n+    struct is_same\n+    {\n+      static const bool value = false;\n+    };\n+\n+    template < typename T >\n+    struct is_same<T, T>\n+    {\n+      static const bool value = true;\n+    };\n+\n+    template < typename T1, typename T2 >\n+    auto\n+    add(T1 a1, T2 a2) -> decltype(a1 + a2)\n+    {\n+      return a1 + a2;\n+    }\n+\n+    int\n+    test(const int c, volatile int v)\n+    {\n+      static_assert(is_same<int, decltype(0)>::value == true, "");\n+      static_assert(is_same<int, decltype(c)>::value == false, "");\n+      static_assert(is_same<int, decltype(v)>::value == false, "");\n+      auto ac = c;\n+      auto av = v;\n+      auto sumi = ac + av + \'x\';\n+      auto sumf = ac + av + 1.0;\n+      static_assert(is_same<int, decltype(ac)>::value == true, "");\n+      static_assert(is_same<int, decltype(av)>::value == true, "");\n+      static_assert(is_same<int, decltype(sumi)>::value == true, "");\n+      static_assert(is_same<int, decltype(sumf)>::value == false, "");\n+      static_assert(is_same<int, decltype(add(c, v))>::value == true, "");\n+      return (sumf > 0.0) ? sumi : add(c, v);\n+    }\n+\n+  }\n+\n+  namespace test_noexcept\n+  {\n+\n+    int f() { return 0; }\n+    int g() noexcept { return 0; }\n+\n+    static_assert(noexcept(f()) == false, "");\n+    static_assert(noexcept(g()) == true, "");\n+\n+  }\n+\n+  namespace test_constexpr\n+  {\n+\n+    template < typename CharT >\n+    unsigned long constexpr\n+    strlen_c_r(const CharT *const s, const unsigned long acc) noexcept\n+    {\n+      return *s ? strlen_c_r(s + 1, acc + 1) : acc;\n+    }\n+\n+    template < typename CharT >\n+    unsigned long constexpr\n+    strlen_c(const CharT *const s) noexcept\n+    {\n+      return strlen_c_r(s, 0UL);\n+    }\n+\n+    static_assert(strlen_c("") == 0UL, "");\n+    static_assert(strlen_c("1") == 1UL, "");\n+    static_assert(strlen_c("example") == 7UL, "");\n+    static_assert(strlen_c("another\\0example") == 7UL, "");\n+\n+  }\n+\n+  namespace test_rvalue_references\n+  {\n+\n+    template < int N >\n+    struct answer\n+    {\n+      static constexpr int value = N;\n+    };\n+\n+    answer<1> f(int&)       { return answer<1>(); }\n+    answer<2> f(const int&) { return answer<2>(); }\n+    answer<3> f(int&&)      { return answer<3>(); }\n+\n+    void\n+    test()\n+    {\n+      int i = 0;\n+      const int c = 0;\n+      static_assert(decltype(f(i))::value == 1, "");\n+      static_assert(decltype(f(c))::value == 2, "");\n+      static_assert(decltype(f(0))::value == 3, "");\n+    }\n+\n+  }\n+\n+  namespace test_uniform_initialization\n+  {\n+\n+    struct test\n+    {\n+      static const int zero {};\n+      static const int one {1};\n+    };\n+\n+    static_assert(test::zero == 0, "");\n+    static_assert(test::one == 1, "");\n+\n+  }\n+\n+  namespace test_lambdas\n+  {\n+\n+    void\n+    test1()\n+    {\n+      auto lambda1 = [](){};\n+      auto lambda2 = lambda1;\n+      lambda1();\n+      lambda2();\n+    }\n+\n+    int\n+    test2()\n+    {\n+      auto a = [](int i, int j){ return i + j; }(1, 2);\n+      auto b = []() -> int { return \'0\'; }();\n+      auto c = [=](){ return a + b; }();\n+      auto d = [&](){ return c; }();\n+      auto e = [a, &b](int x) mutable {\n+        const auto identity = [](int y){ return y; };\n+        for (auto i = 0; i < a; ++i)\n+          a += b--;\n+        return x + identity(a + b);\n+      }(0);\n+      return a + b + c + d + e;\n+    }\n+\n+    int\n+    test3()\n+    {\n+      const auto nullary = [](){ return 0; };\n+      const auto unary = [](int x){ return x; };\n+      using nullary_t = decltype(nullary);\n+      using unary_t = decltype(unary);\n+      const auto higher1st = [](nullary_t f){ return f(); };\n+      const auto higher2nd = [unary](nullary_t f1){\n+        return [unary, f1](unary_t f2){ return f2(unary(f1())); };\n+      };\n+      return higher1st(nullary) + higher2nd(nullary)(unary);\n+    }\n+\n+  }\n+\n+  namespace test_variadic_templates\n+  {\n+\n+    template <int...>\n+    struct sum;\n+\n+    template <int N0, int... N1toN>\n+    struct sum<N0, N1toN...>\n+    {\n+      static constexpr auto value = N0 + sum<N1toN...>::value;\n+    };\n+\n+    template <>\n+    struct sum<>\n+    {\n+      static constexpr auto value = 0;\n+    };\n+\n+    static_assert(sum<>::value == 0, "");\n+    static_assert(sum<1>::value == 1, "");\n+    static_assert(sum<23>::value == 23, "");\n+    static_assert(sum<1, 2>::value == 3, "");\n+    static_assert(sum<5, 5, 11>::value == 21, "");\n+    static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, "");\n+\n+  }\n+\n+  // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae\n+  // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function\n+  // because of this.\n+  namespace test_template_alias_sfinae\n+  {\n+\n+    struct foo {};\n+\n+    template<typename T>\n+    using member = typename T::member_type;\n+\n+    template<typename T>\n+    void func(...) {}\n+\n+    template<typename T>\n+    void func(member<T>*) {}\n+\n+    void test();\n+\n+    void test() { func<foo>(0); }\n+\n+  }\n+\n+}  // namespace cxx11\n+\n+#endif  // __cplusplus >= 201103L\n+\n+]])\n+\n+\n+dnl  Tests for new features in C++14\n+\n+m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_14], [[\n+\n+// If the compiler admits that it is not ready for C++14, why torture it?\n+// Hopefully, this will speed up the test.\n+\n+#ifndef __cplusplus\n+\n+#error "This is not a C++ compiler"\n+\n+#elif __cplusplus < 201402L\n+\n+#error "This is not a C++14 compiler"\n+\n+#else\n+\n+namespace cxx14\n+{\n+\n+  namespace test_polymorphic_lambdas\n+  {\n+\n+    int\n+    test()\n+    {\n+      const auto lambda = [](auto&&... args){\n+        const auto istiny = [](auto x){\n+          return (sizeof(x) == 1UL) ? 1 : 0;\n+        };\n+        const int aretiny[] = { istiny(args)... };\n+        return aretiny[0];\n+      };\n+      return lambda(1, 1L, 1.0f, \'1\');\n+    }\n+\n+  }\n+\n+  namespace test_binary_literals\n+  {\n+\n+    constexpr auto ivii = 0b0000000000101010;\n+    static_assert(ivii == 42, "wrong value");\n+\n+  }\n+\n+  namespace test_generalized_constexpr\n+  {\n+\n+    template < typename CharT >\n+    constexpr unsigned long\n+    strlen_c(const CharT *const s) noexcept\n+    {\n+      auto length = 0UL;\n+      for (auto p = s; *p; ++p)\n+        ++length;\n+      return length;\n+    }\n+\n+    static_assert(strlen_c("") == 0UL, "");\n+    static_assert(strlen_c("x") == 1UL, "");\n+    static_assert(strlen_c("test") == 4UL, "");\n+    static_assert(strlen_c("another\\0test") == 7UL, "");\n+\n+  }\n+\n+  namespace test_lambda_init_capture\n+  {\n+\n+    int\n+    test()\n+    {\n+      auto x = 0;\n+      const auto lambda1 = [a = x](int b){ return a + b; };\n+      const auto lambda2 = [a = lambda1(x)](){ return a; };\n+      return lambda2();\n+    }\n+\n+  }\n+\n+  namespace test_digit_separators\n+  {\n+\n+    constexpr auto ten_million = 100\'000\'000;\n+    static_assert(ten_million == 100000000, "");\n+\n+  }\n+\n+  namespace test_return_type_deduction\n+  {\n+\n+    auto f(int& x) { return x; }\n+    decltype(auto) g(int& x) { return x; }\n+\n+    template < typename T1, typename T2 >\n+    struct is_same\n+    {\n+      static constexpr auto value = false;\n+    };\n+\n+    template < typename T >\n+    struct is_same<T, T>\n+    {\n+      static constexpr auto value = true;\n+    };\n+\n+    int\n+    test()\n+    {\n+      auto x = 0;\n+      static_assert(is_same<int, decltype(f(x))>::value, "");\n+      static_assert(is_same<int&, decltype(g(x))>::value, "");\n+      return x;\n+    }\n+\n+  }\n+\n+}  // namespace cxx14\n+\n+#endif  // __cplusplus >= 201402L\n+\n+]])\n+\n+\n+dnl  Tests for new features in C++17\n+\n+m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_17], [[\n+\n+// If the compiler admits that it is not ready for C++17, why torture it?\n+// Hopefully, this will speed up the test.\n+\n+#ifndef __cplusplus\n+\n+#error "This is not a C++ compiler"\n+\n+#elif __cplusplus < 201703L\n+\n+#error "This is not a C++17 compiler"\n+\n+#else\n+\n+#include <initializer_list>\n+#include <utility>\n+#include <type_traits>\n+\n+namespace cxx17\n+{\n+\n+  namespace test_constexpr_lambdas\n+  {\n+\n+    constexpr int foo = [](){return 42;}();\n+\n+  }\n+\n+  namespace test::nested_namespace::definitions\n+  {\n+\n+  }\n+\n+  namespace test_fold_expression\n+  {\n+\n+    template<typename... Args>\n+    int multiply(Args... args)\n+    {\n+      return (args * ... * 1);\n+    }\n+\n+    template<typename... Args>\n+    bool all(Args... args)\n+    {\n+      return (args && ...);\n+    }\n+\n+  }\n+\n+  namespace test_extended_static_assert\n+  {\n+\n+    static_assert (true);\n+\n+  }\n+\n+  namespace test_auto_brace_init_list\n+  {\n+\n+    auto foo = {5};\n+    auto bar {5};\n+\n+    static_assert(std::is_same<std::initializer_list<int>, decltype(foo)>::value);\n+    static_assert(std::is_same<int, decltype(bar)>::value);\n+  }\n+\n+  namespace test_typename_in_template_template_parameter\n+  {\n+\n+    template<template<typename> typename X> struct D;\n+\n+  }\n+\n+  namespace test_fallthrough_nodiscard_maybe_unused_attributes\n+  {\n+\n+    int f1()\n+    {\n+      return 42;\n+    }\n+\n+    [[nodiscard]] int f2()\n+    {\n+      [[maybe_unused]] auto unused = f1();\n+\n+      switch (f1())\n+      {\n+      case 17:\n+        f1();\n+        [[fallthrough]];\n+      case 42:\n+        f1();\n+      }\n+      return f1();\n+    }\n+\n+  }\n+\n+  namespace test_extended_aggregate_initialization\n+  {\n+\n+    struct base1\n+    {\n+      int b1, b2 = 42;\n+    };\n+\n+    struct base2\n+    {\n+      base2() {\n+        b3 = 42;\n+      }\n+      int b3;\n+    };\n+\n+    struct derived : base1, base2\n+    {\n+        int d;\n+    };\n+\n+    derived d1 {{1, 2}, {}, 4};  // full initialization\n+    derived d2 {{}, {}, 4};      // value-initialized bases\n+\n+  }\n+\n+  namespace test_general_range_based_for_loop\n+  {\n+\n+    struct iter\n+    {\n+      int i;\n+\n+      int& operator* ()\n+      {\n+        return i;\n+      }\n+\n+      const int& operator* () const\n+      {\n+        return i;\n+      }\n+\n+      iter& operator++()\n+      {\n+        ++i;\n+        return *this;\n+      }\n+    };\n+\n+    struct sentinel\n+    {\n+      int i;\n+    };\n+\n+    bool operator== (const iter& i, const sentinel& s)\n+    {\n+      return i.i == s.i;\n+    }\n+\n+    bool operator!= (const iter& i, const sentinel& s)\n+    {\n+      return !(i == s);\n+    }\n+\n+    struct range\n+    {\n+      iter begin() const\n+      {\n+        return {0};\n+      }\n+\n+      sentinel end() const\n+      {\n+        return {5};\n+      }\n+    };\n+\n+    void f()\n+    {\n+      range r {};\n+\n+      for (auto i : r)\n+      {\n+        [[maybe_unused]] auto v = i;\n+      }\n+    }\n+\n+  }\n+\n+  namespace test_lambda_capture_asterisk_this_by_value\n+  {\n+\n+    struct t\n+    {\n+      int i;\n+      int foo()\n+      {\n+        return [*this]()\n+        {\n+          return i;\n+        }();\n+      }\n+    };\n+\n+  }\n+\n+  namespace test_enum_class_construction\n+  {\n+\n+    enum class byte : unsigned char\n+    {};\n+\n+    byte foo {42};\n+\n+  }\n+\n+  namespace test_constexpr_if\n+  {\n+\n+    template <bool cond>\n+    int f ()\n+    {\n+      if constexpr(cond)\n+      {\n+        return 13;\n+      }\n+      else\n+      {\n+        return 42;\n+      }\n+    }\n+\n+  }\n+\n+  namespace test_selection_statement_with_initializer\n+  {\n+\n+    int f()\n+    {\n+      return 13;\n+    }\n+\n+    int f2()\n+    {\n+      if (auto i = f(); i > 0)\n+      {\n+        return 3;\n+      }\n+\n+      switch (auto i = f(); i + 4)\n+      {\n+      case 17:\n+        return 2;\n+\n+      default:\n+        return 1;\n+      }\n+    }\n+\n+  }\n+\n+  namespace test_template_argument_deduction_for_class_templates\n+  {\n+\n+    template <typename T1, typename T2>\n+    struct pair\n+    {\n+      pair (T1 p1, T2 p2)\n+        : m1 {p1},\n+          m2 {p2}\n+      {}\n+\n+      T1 m1;\n+      T2 m2;\n+    };\n+\n+    void f()\n+    {\n+      [[maybe_unused]] auto p = pair{13, 42u};\n+    }\n+\n+  }\n+\n+  namespace test_non_type_auto_template_parameters\n+  {\n+\n+    template <auto n>\n+    struct B\n+    {};\n+\n+    B<5> b1;\n+    B<\'a\'> b2;\n+\n+  }\n+\n+  namespace test_structured_bindings\n+  {\n+\n+    int arr[2] = { 1, 2 };\n+    std::pair<int, int> pr = { 1, 2 };\n+\n+    auto f1() -> int(&)[2]\n+    {\n+      return arr;\n+    }\n+\n+    auto f2() -> std::pair<int, int>&\n+    {\n+      return pr;\n+    }\n+\n+    struct S\n+    {\n+      int x1 : 2;\n+      volatile double y1;\n+    };\n+\n+    S f3()\n+    {\n+      return {};\n+    }\n+\n+    auto [ x1, y1 ] = f1();\n+    auto& [ xr1, yr1 ] = f1();\n+    auto [ x2, y2 ] = f2();\n+    auto& [ xr2, yr2 ] = f2();\n+    const auto [ x3, y3 ] = f3();\n+\n+  }\n+\n+  namespace test_exception_spec_type_system\n+  {\n+\n+    struct Good {};\n+    struct Bad {};\n+\n+    void g1() noexcept;\n+    void g2();\n+\n+    template<typename T>\n+    Bad\n+    f(T*, T*);\n+\n+    template<typename T1, typename T2>\n+    Good\n+    f(T1*, T2*);\n+\n+    static_assert (std::is_same_v<Good, decltype(f(g1, g2))>);\n+\n+  }\n+\n+  namespace test_inline_variables\n+  {\n+\n+    template<class T> void f(T)\n+    {}\n+\n+    template<class T> inline T g(T)\n+    {\n+      return T{};\n+    }\n+\n+    template<> inline void f<>(int)\n+    {}\n+\n+    template<> int g<>(int)\n+    {\n+      return 5;\n+    }\n+\n+  }\n+\n+}  // namespace cxx17\n+\n+#endif  // __cplusplus < 201703L\n+\n+]])\ndiff --git a/src/secp256k1/configure.ac b/src/secp256k1/configure.ac\nindex 7b0a099db..1cf9d4f6f 100644\n--- a/src/secp256k1/configure.ac\n+++ b/src/secp256k1/configure.ac\n@@ -33,6 +33,8 @@ if test x"$ac_cv_prog_cc_c89" = x"no"; then\n fi\n AM_PROG_AS\n \n+AX_CXX_COMPILE_STDCXX([11], [noext], [mandatory])\n+\n case $host_os in\n   *darwin*)\n      if  test x$cross_compiling != xyes; then\ndiff --git a/src/secp256k1/include/GroupElement.h b/src/secp256k1/include/GroupElement.h\nindex a544d1396..0e8727d63 100644\n--- a/src/secp256k1/include/GroupElement.h\n+++ b/src/secp256k1/include/GroupElement.h\n@@ -72,7 +72,7 @@ public:\n   // These functions are for READWRITE() in serialize.h\n   unsigned int GetSerializeSize(int nType=0, int nVersion=0) const\n   {\n-     return memoryRequired();    \n+     return memoryRequired();\n   }\n \n   template<typename Stream>\n@@ -96,13 +96,7 @@ public:\n   //function name like in CBignum\n   std::vector<unsigned char> getvch() const;\n \n-  struct hasher {\n-  public:\n-      std::size_t operator()(const GroupElement& x) const\n-      {\n-          return std::hash<std::string>()(x.tostring());\n-      }\n-  };\n+  std::size_t hash() const;\n \n private:\n     GroupElement(const void *g);\n@@ -114,4 +108,15 @@ private:\n \n } // namespace secp_primitives\n \n+namespace std {\n+    template<>\n+    struct hash<secp_primitives::GroupElement>\n+    {\n+        size_t operator()(const secp_primitives::GroupElement& g) const\n+        {\n+            return g.hash();\n+        }\n+    };\n+} // namespace std\n+\n #endif // SECP_GROUP_ELEMENT_H__\ndiff --git a/src/secp256k1/src/cpp/GroupElement.cpp b/src/secp256k1/src/cpp/GroupElement.cpp\nindex 5a84d2c51..1ee70748e 100644\n--- a/src/secp256k1/src/cpp/GroupElement.cpp\n+++ b/src/secp256k1/src/cpp/GroupElement.cpp\n@@ -13,8 +13,11 @@\n #include "../ecmult_impl.h"\n \n #include <openssl/rand.h>\n-#include <stdlib.h>\n+\n #include <sstream>\n+#include <stdexcept>\n+\n+#include <stdlib.h>\n \n static secp256k1_ecmult_context ctx;\n \n@@ -193,7 +196,7 @@ static void _convertToFieldElement(secp256k1_fe *r, const char* str, int base) {\n                 throw std::invalid_argument("invalid number base 10");\n             }\n             break;\n-        \n+\n         case 16:\n             if (ch >= \'0\' && ch <= \'9\') {\n                 src[i] = ch - \'0\';\n@@ -526,4 +529,16 @@ std::vector<unsigned char> GroupElement::getvch() const {\n     return result;\n }\n \n+std::size_t GroupElement::hash() const\n+{\n+    const unsigned char *g = reinterpret_cast<const unsigned char *>(g_);\n+    std::size_t h = 0;\n+\n+    for (std::size_t i = 0; i < sizeof(secp256k1_gej); i++) {\n+        h ^= g[i];\n+    }\n+\n+    return h;\n+}\n+\n } // namespace secp_primitives\ndiff --git a/src/test/mtp_malformed_tests.cpp b/src/test/mtp_malformed_tests.cpp\nindex 88d828f25..0d00c7b1a 100644\n--- a/src/test/mtp_malformed_tests.cpp\n+++ b/src/test/mtp_malformed_tests.cpp\n@@ -38,6 +38,8 @@\n #include <boost/thread.hpp>\n #include <boost/interprocess/streams/bufferstream.hpp>\n \n+#include <ios>\n+\n BOOST_FIXTURE_TEST_SUITE(mtp_malformed_tests, MtpMalformedTestingSetup)\n \n BOOST_AUTO_TEST_CASE(mtp_malformed)\n@@ -130,7 +132,7 @@ BOOST_AUTO_TEST_CASE(mtp_malformed)\n     mybufstream.clear();\n     mybufstream << *bMtp.mtpHashData;\n     mybufstream.insert(mybufstream.begin(), 0);\n-    BOOST_CHECK_EXCEPTION(mybufstream >> outh, std::runtime_error, no_check);\n+    BOOST_CHECK_EXCEPTION(mybufstream >> outh, std::ios_base::failure, [](const std::ios_base::failure&) { return true; });\n \n     mybufstream.clear();\n     mybufstream << *bMtp.mtpHashData;\n@@ -142,12 +144,12 @@ BOOST_AUTO_TEST_CASE(mtp_malformed)\n     mybufstream << *bMtp.mtpHashData;\n     for(auto &it : mybufstream)\n         it = rand()%256;\n-    BOOST_CHECK_EXCEPTION(mybufstream >> outh, std::runtime_error, no_check);\n+    BOOST_CHECK_EXCEPTION(mybufstream >> outh, std::ios_base::failure, [](const std::ios_base::failure&) { return true; });\n \n     mybufstream.clear();\n     mybufstream << *bMtp.mtpHashData;\n     mybufstream.resize(mybufstream.size()/2);\n-    BOOST_CHECK_EXCEPTION(mybufstream >> outh, std::runtime_error, no_check);\n+    BOOST_CHECK_EXCEPTION(mybufstream >> outh, std::ios_base::failure, [](const std::ios_base::failure&) { return true; });\n     Params(CBaseChainParams::REGTEST).SetRegTestMtpSwitchTime(INT_MAX);\n }\n \ndiff --git a/src/test/sigma_state_tests.cpp b/src/test/sigma_state_tests.cpp\nindex bebc330a2..f7f0d79e5 100644\n--- a/src/test/sigma_state_tests.cpp\n+++ b/src/test/sigma_state_tests.cpp\n@@ -37,10 +37,10 @@ std::vector<PrivateCoinV3> generateCoins(\n std::vector<PublicCoinV3> getPubcoins(const std::vector<PrivateCoinV3> coins)\n {\n     std::vector<sigma::PublicCoinV3> pubCoins;\n-    \n+\n     BOOST_FOREACH(auto& coin, coins)\n         pubCoins.push_back(coin.getPublicCoin());\n-    \n+\n     return pubCoins;\n }\n \n@@ -343,7 +343,7 @@ BOOST_AUTO_TEST_CASE(sigma_addspendtomempool)\n \n     std::vector<sigma::PublicCoinV3> anonymity_set;\n     anonymity_set.push_back(pubcoin);\n-    \n+\n     // Doesn\'t really matter what metadata we give here, it must pass.\n     sigma::SpendMetaDataV3 metaData(0, uint256S("120"), uint256S("120"));\n \n@@ -432,7 +432,7 @@ BOOST_AUTO_TEST_CASE(sigma_canaddspendtomempool_used)\n \n     std::vector<sigma::PublicCoinV3> anonymity_set;\n     anonymity_set.push_back(pubcoin);\n- \n+\n     // Doesn\'t really matter what metadata we give here, it must pass.\n     sigma::SpendMetaDataV3 metaData(0, uint256S("120"), uint256S("120"));\n \n@@ -471,7 +471,7 @@ BOOST_AUTO_TEST_CASE(sigma_reset)\n \n     std::vector<sigma::PublicCoinV3> anonymity_set;\n     anonymity_set.push_back(pubcoin);\n- \n+\n     // Doesn\'t really matter what metadata we give here, it must pass.\n     sigma::SpendMetaDataV3 metaData(0, uint256S("120"), uint256S("120"));\n \n@@ -593,7 +593,7 @@ BOOST_AUTO_TEST_CASE(zerocoin_sigma_addblock_minted_spend)\n     CBlockIndex index = CreateBlockIndex(1);\n     std::pair<CoinDenominationV3, int> denomination1Group1(\n         CoinDenominationV3::SIGMA_DENOM_1,1);\n-    \n+\n \tindex.mintedPubCoinsV3[denomination1Group1].push_back(pubcoin1);\n \tindex.mintedPubCoinsV3[denomination1Group1].push_back(pubcoin2);\n \n@@ -609,7 +609,7 @@ BOOST_AUTO_TEST_CASE(zerocoin_sigma_addblock_minted_spend)\n     anonymity_set.push_back(pubcoin1);\n     anonymity_set.push_back(pubcoin2);\n \n- \n+\n     // Doesn\'t really matter what metadata we give here, it must pass.\n     sigma::SpendMetaDataV3 metaData(0, uint256S("120"), uint256S("120"));\n \n@@ -657,7 +657,7 @@ BOOST_AUTO_TEST_CASE(zerocoin_sigma_removeblock_remove)\n     auto index1 = CreateBlockIndex(1);\n     std::pair<CoinDenominationV3, int> denomination1Group1(CoinDenominationV3::SIGMA_DENOM_1, 1);\n     index1.mintedPubCoinsV3[denomination1Group1] = pubCoins;\n-    \n+\n     // add index 2 with 10 minted and 1 spend\n     auto coins2 = generateCoins(params,10, CoinDenominationV3::SIGMA_DENOM_1);\n     auto pubCoins2 = getPubcoins(coins2);\n@@ -689,7 +689,7 @@ BOOST_AUTO_TEST_CASE(zerocoin_sigma_removeblock_remove)\n \n \tBOOST_CHECK_MESSAGE(zerocoinState->usedCoinSerials.size() == 0,\n \t  "Unexpected usedCoinSerials size, remove index contain 1 spend.");\n-    \n+\n     BOOST_CHECK_MESSAGE(zerocoinState->latestCoinIds[CoinDenominationV3::SIGMA_DENOM_1] == 1,\n       "Unexpected lastestcoinId");\n \n@@ -705,7 +705,7 @@ BOOST_AUTO_TEST_CASE(zerocoin_sigma_removeblock_remove)\n \n \tBOOST_CHECK_MESSAGE(zerocoinState->usedCoinSerials.size() == 0,\n \t  "Unexpected usedCoinSerials size, remove index contain no spend.");\n-    \n+\n     BOOST_CHECK_MESSAGE(zerocoinState->latestCoinIds[CoinDenominationV3::SIGMA_DENOM_1] == 0,\n       "Unexpected lastestcoinId remove all");\n \n@@ -734,7 +734,7 @@ BOOST_AUTO_TEST_CASE(getmempoolconflictingtxhash_added_yes)\n \n     auto txid = uint256S("c8cdacf6b51275a3de9496073c75708abde26cb2f6cb164e0a1a0ed942c3c6e7");\n \n-    BOOST_TEST(state.AddSpendToMempool(serial, txid));\n+    BOOST_CHECK(state.AddSpendToMempool(serial, txid));\n     BOOST_CHECK(state.GetMempoolConflictingTxHash(serial) == txid);\n }\n \n@@ -757,7 +757,7 @@ BOOST_AUTO_TEST_CASE(zerocoingetspendserialnumberv3_valid_tx_valid_vin)\n     serializedCoinSpend << coinSpend;\n \n     // create tx and vin\n-    \n+\n     CTxIn newTxIn;\n     newTxIn.scriptSig = CScript();\n     newTxIn.prevout.SetNull();\n@@ -815,7 +815,7 @@ BOOST_AUTO_TEST_CASE(zerocoingetspendserialnumberv3_valid_tx_valid_vin)\n     newTxVin3.scriptSig.assign(tmp3.begin(), tmp3.end());\n \n     newtx.vin.push_back(newTxVin3);\n-    \n+\n     CTransaction ctx3(newtx);\n \n     BOOST_CHECK_MESSAGE(ZerocoinGetSpendSerialNumberV3(ctx3, newTxVin3) == Scalar(uint64_t(0)),\n@@ -841,7 +841,7 @@ BOOST_AUTO_TEST_CASE(zerocoingetspendserialnumberv3_invalid_script)\n     serializedCoinSpend << coinSpend;\n \n     // create tx and vin\n-    \n+\n     CTxIn newTxIn;\n     newTxIn.scriptSig = CScript();\n     newTxIn.prevout.SetNull();\n@@ -999,7 +999,7 @@ BOOST_AUTO_TEST_CASE(sigma_getcoinsetforspend)\n     int nextIndex = 0;\n     std::vector<CBlockIndex> indexes;\n     indexes.resize(101);\n-    \n+\n     // nextIndex = 0\n     indexes[nextIndex] = CreateBlockIndex(nextIndex);\n     chainActive.SetTip(&indexes[nextIndex]);\n@@ -1014,7 +1014,7 @@ BOOST_AUTO_TEST_CASE(sigma_getcoinsetforspend)\n     // add index 1 with 10 SIGMA_DENOM_1\n     auto coins = generateCoins(params, 10, CoinDenominationV3::SIGMA_DENOM_1);\n     auto pubCoins = getPubcoins(coins);\n-    \n+\n     // add index 2 with 1 DENOM_1  mints and 1 spend\n     auto coins2 = generateCoins(params, 1, CoinDenominationV3::SIGMA_DENOM_1);\n     auto pubCoins2 = getPubcoins(coins2);\n@@ -1036,7 +1036,7 @@ BOOST_AUTO_TEST_CASE(sigma_getcoinsetforspend)\n     indexes[nextIndex].mintedPubCoinsV3[denomination10Group1] = pubCoins3;\n \n     chainActive.SetTip(&indexes[nextIndex]);\n-    \n+\n     // nextIndex = 3\n     nextIndex++;\n     for( ; nextIndex<=100; nextIndex++){\n@@ -1059,7 +1059,7 @@ BOOST_AUTO_TEST_CASE(sigma_getcoinsetforspend)\n \n     std::vector<PublicCoinV3> coins_out1;\n     // maxheight > blockheight\n-    coins_amount = zerocoinState->GetCoinSetForSpend(&chainActive, nextIndex, \n+    coins_amount = zerocoinState->GetCoinSetForSpend(&chainActive, nextIndex,\n     CoinDenominationV3::SIGMA_DENOM_10, 1, blockHash_out, coins_out1);\n     BOOST_CHECK_MESSAGE(coins_amount == 5, "Unexpected Coins amount for spend, should be 5.");\n     BOOST_CHECK_MESSAGE(coins_out1 == pubCoins3, "Unexpected coins out for denom 10.");\n@@ -1067,7 +1067,7 @@ BOOST_AUTO_TEST_CASE(sigma_getcoinsetforspend)\n \n     std::vector<PublicCoinV3> coins_out2;\n     // maxheight > blockheight another denom\n-    coins_amount = zerocoinState->GetCoinSetForSpend(&chainActive, nextIndex, \n+    coins_amount = zerocoinState->GetCoinSetForSpend(&chainActive, nextIndex,\n     CoinDenominationV3::SIGMA_DENOM_1, 1, blockHash_out, coins_out2);\n     BOOST_CHECK_MESSAGE(coins_amount == 11, "Unexpected Coins amount for spend, should be 11.");\n     BOOST_CHECK_MESSAGE(coins_out2.size() == pubCoins2.size() + pubCoins.size(), "Unexpected coins out for denom 1.");\ndiff --git a/src/wallet/test/sigma_tests.cpp b/src/wallet/test/sigma_tests.cpp\nindex 09a422ca4..87fc066ab 100644\n--- a/src/wallet/test/sigma_tests.cpp\n+++ b/src/wallet/test/sigma_tests.cpp\n@@ -3,6 +3,7 @@\n // file COPYING or http://www.opensource.org/licenses/mit-license.php.\n \n #include "../wallet.h"\n+#include "../walletexcept.h"\n \n #include "../../libzerocoin/sigma/CoinSpend.h"\n #include "../../main.h"\n@@ -83,6 +84,13 @@ static void GenerateBlockWithCoins(const std::vector<std::pair<sigma::CoinDenomi\n     chainActive.SetTip(&block->second);\n }\n \n+static void GenerateEmptyBlocks(int number_of_blocks)\n+{\n+    for (int i = 0; i < number_of_blocks; ++i) {\n+        GenerateBlockWithCoins({});\n+   }\n+}\n+\n static bool CheckDenominationCoins(\n         const std::vector<std::pair<sigma::CoinDenominationV3, int>>& expected,\n         std::vector<sigma::CoinDenominationV3> actualDenominations)\n@@ -228,6 +236,7 @@ BOOST_AUTO_TEST_CASE(get_coin_different_denomination)\n     std::vector<std::pair<sigma::CoinDenominationV3, int>> newCoins;\n     GetCoinSetByDenominationAmount(newCoins, 2, 1, 1, 1, 1);\n     GenerateBlockWithCoins(newCoins);\n+    GenerateEmptyBlocks(5);\n \n     CAmount require(111 * COIN + 7 * COIN / 10); // 111.7\n \n@@ -245,6 +254,7 @@ BOOST_AUTO_TEST_CASE(get_coin_round_up)\n     std::vector<std::pair<sigma::CoinDenominationV3, int>> newCoins;\n     GetCoinSetByDenominationAmount(newCoins, 5, 5, 5, 5, 5);\n     GenerateBlockWithCoins(newCoins);\n+    GenerateEmptyBlocks(5);\n \n     // This must get rounded up to 111.8\n     CAmount require(111 * COIN + 7 * COIN / 10 + 5 * COIN / 100); // 111.75\n@@ -273,6 +283,7 @@ BOOST_AUTO_TEST_CASE(get_coin_not_enough)\n     std::vector<std::pair<sigma::CoinDenominationV3, int>> newCoins;\n     GetCoinSetByDenominationAmount(newCoins, 1, 1, 1, 1, 1);\n     GenerateBlockWithCoins(newCoins);\n+    GenerateEmptyBlocks(5);\n \n     CAmount require(111 * COIN + 7 * COIN / 10); // 111.7\n \n@@ -282,11 +293,28 @@ BOOST_AUTO_TEST_CASE(get_coin_not_enough)\n         "Expect not enough coin and equal to one for each denomination");\n }\n \n+BOOST_AUTO_TEST_CASE(get_coin_cannot_spend_unconfirmed_coins)\n+{\n+    std::vector<std::pair<sigma::CoinDenominationV3, int>> newCoins;\n+    GetCoinSetByDenominationAmount(newCoins, 1, 1, 1, 1, 1);\n+    GenerateBlockWithCoins(newCoins);\n+    // Intentionally do not create 5 more blocks after this one, so coins can not be spent.\n+    // GenerateEmptyBlocks(5);\n+\n+    CAmount require(111 * COIN + 5 * COIN / 10); // 111.5\n+\n+    std::vector<CZerocoinEntryV3> coins;\n+    std::vector<sigma::CoinDenominationV3> coinsToMint;\n+    BOOST_CHECK_MESSAGE(!pwalletMain->GetCoinsToSpend(require, coins, coinsToMint),\n+        "Expect not enough coin and equal to one for each denomination");\n+}\n+\n BOOST_AUTO_TEST_CASE(get_coin_minimize_coins_spend_fit_amount)\n {\n     std::vector<std::pair<sigma::CoinDenominationV3, int>> newCoins;\n     GetCoinSetByDenominationAmount(newCoins, 0, 0, 0, 10, 1);\n     GenerateBlockWithCoins(newCoins);\n+    GenerateEmptyBlocks(5);\n \n     CAmount require(100 * COIN);\n \n@@ -307,6 +335,7 @@ BOOST_AUTO_TEST_CASE(get_coin_minimize_coins_spend)\n     std::vector<std::pair<sigma::CoinDenominationV3, int>> newCoins;\n     GetCoinSetByDenominationAmount(newCoins, 1, 0, 7, 1, 1);\n     GenerateBlockWithCoins(newCoins);\n+    GenerateEmptyBlocks(5);\n \n     CAmount require(17 * COIN);\n \n@@ -327,6 +356,7 @@ BOOST_AUTO_TEST_CASE(get_coin_choose_smallest_enough)\n     std::vector<std::pair<sigma::CoinDenominationV3, int>> newCoins;\n     GetCoinSetByDenominationAmount(newCoins, 1, 1, 1, 1, 1);\n     GenerateBlockWithCoins(newCoins);\n+    GenerateEmptyBlocks(5);\n \n     CAmount require(9 * COIN / 10); // 0.9\n \n@@ -382,6 +412,7 @@ BOOST_AUTO_TEST_CASE(create_spend_with_insufficient_coins)\n     std::vector<CRecipient> recipients;\n \n     GenerateBlockWithCoins({ std::make_pair(sigma::CoinDenominationV3::SIGMA_DENOM_10, 1) });\n+    GenerateEmptyBlocks(5);\n \n     recipients.push_back(CRecipient{\n         .scriptPubKey = GetScriptForDestination(randomAddr1.Get()),\n@@ -403,8 +434,8 @@ BOOST_AUTO_TEST_CASE(create_spend_with_insufficient_coins)\n \n     BOOST_CHECK_EXCEPTION(\n         pwalletMain->CreateZerocoinSpendTransactionV3(recipients, fee, selected, changes),\n-        std::runtime_error,\n-        [](const std::runtime_error& e) { return e.what() == std::string("Insufficient funds"); });\n+        InsufficientFunds,\n+        [](const InsufficientFunds& e) { return e.what() == std::string("Insufficient funds"); });\n }\n \n BOOST_AUTO_TEST_CASE(create_spend_with_confirmation_less_than_6)\n@@ -436,8 +467,8 @@ BOOST_AUTO_TEST_CASE(create_spend_with_confirmation_less_than_6)\n \n     BOOST_CHECK_EXCEPTION(\n         pwalletMain->CreateZerocoinSpendTransactionV3(recipients, fee, selected, changes),\n-        std::runtime_error,\n-        [](const std::runtime_error& e) { return e.what() == std::string("Has to have at least two mint coins with at least 6 confirmation in order to spend a coin"); });\n+        InsufficientFunds,\n+        [](const InsufficientFunds& e) { return e.what() == std::string("Insufficient funds"); });\n }\n \n BOOST_AUTO_TEST_CASE(create_spend_with_coins_less_than_2)\n@@ -448,11 +479,7 @@ BOOST_AUTO_TEST_CASE(create_spend_with_coins_less_than_2)\n     std::vector<CRecipient> recipients;\n \n     GenerateBlockWithCoins({ std::make_pair(sigma::CoinDenominationV3::SIGMA_DENOM_10, 1) });\n-    GenerateBlockWithCoins({});\n-    GenerateBlockWithCoins({});\n-    GenerateBlockWithCoins({});\n-    GenerateBlockWithCoins({});\n-    GenerateBlockWithCoins({});\n+    GenerateEmptyBlocks(5);\n \n     recipients.push_back(CRecipient{\n         .scriptPubKey = GetScriptForDestination(randomAddr1.Get()),\n@@ -474,11 +501,7 @@ BOOST_AUTO_TEST_CASE(create_spend_with_coins_more_than_1)\n     std::vector<CRecipient> recipients;\n \n     GenerateBlockWithCoins({ std::make_pair(sigma::CoinDenominationV3::SIGMA_DENOM_10, 2) });\n-    GenerateBlockWithCoins({});\n-    GenerateBlockWithCoins({});\n-    GenerateBlockWithCoins({});\n-    GenerateBlockWithCoins({});\n-    GenerateBlockWithCoins({});\n+    GenerateEmptyBlocks(5);\n \n     recipients.push_back(CRecipient{\n         .scriptPubKey = GetScriptForDestination(randomAddr1.Get()),\n@@ -494,19 +517,19 @@ BOOST_AUTO_TEST_CASE(create_spend_with_coins_more_than_1)\n \n     CWalletTx tx = pwalletMain->CreateZerocoinSpendTransactionV3(recipients, fee, selected, changes);\n \n-    BOOST_TEST(tx.vin.size() == 2);\n+    BOOST_CHECK(tx.vin.size() == 2);\n \n     // 2 outputs to recipients 5 + 10 xzc\n     // 9 mints as changes, 1 * 4 + 0.5 * 1 + 0.1 * 4 xzc\n-    BOOST_TEST(tx.vout.size() == 11);\n-    BOOST_TEST(fee > 0);\n+    BOOST_CHECK(tx.vout.size() == 11);\n+    BOOST_CHECK(fee > 0);\n \n-    BOOST_TEST(selected.size() == 2);\n-    BOOST_TEST(selected[0].get_denomination() == sigma::CoinDenominationV3::SIGMA_DENOM_10);\n-    BOOST_TEST(selected[1].get_denomination() == sigma::CoinDenominationV3::SIGMA_DENOM_10);\n+    BOOST_CHECK(selected.size() == 2);\n+    BOOST_CHECK(selected[0].get_denomination() == sigma::CoinDenominationV3::SIGMA_DENOM_10);\n+    BOOST_CHECK(selected[1].get_denomination() == sigma::CoinDenominationV3::SIGMA_DENOM_10);\n \n-    BOOST_TEST(CheckSpend(tx.vin[0], selected[0]));\n-    BOOST_TEST(CheckSpend(tx.vin[1], selected[1]));\n+    BOOST_CHECK(CheckSpend(tx.vin[0], selected[0]));\n+    BOOST_CHECK(CheckSpend(tx.vin[1], selected[1]));\n \n     BOOST_CHECK(ContainTxOut(tx.vout,\n         make_pair(GetScriptForDestination(randomAddr1.Get()), 5 * COIN ), 1));\n@@ -517,7 +540,7 @@ BOOST_AUTO_TEST_CASE(create_spend_with_coins_more_than_1)\n         return c + (v.scriptPubKey.IsZerocoinMintV3() ? v.nValue : 0);\n     });\n \n-    BOOST_TEST(remintsSum == 49 * COIN / 10);\n+    BOOST_CHECK(remintsSum == 49 * COIN / 10);\n \n     // check walletdb\n     std::list<CZerocoinEntryV3> coinList;\n@@ -525,22 +548,22 @@ BOOST_AUTO_TEST_CASE(create_spend_with_coins_more_than_1)\n     CWalletDB db(pwalletMain->strWalletFile);\n \n     db.ListPubCoinV3(coinList);\n-    BOOST_TEST(coinList.size() == 2);\n+    BOOST_CHECK(coinList.size() == 2);\n \n     db.ListCoinSpendSerial(spends);\n-    BOOST_TEST(spends.empty());\n+    BOOST_CHECK(spends.empty());\n \n     pwalletMain->SpendZerocoinV3(recipients, tx, fee);\n \n     coinList.clear();\n     db.ListPubCoinV3(coinList);\n-    BOOST_TEST(coinList.size() == 11);\n-    BOOST_TEST(std::count_if(coinList.begin(), coinList.end(),\n+    BOOST_CHECK(coinList.size() == 11);\n+    BOOST_CHECK(std::count_if(coinList.begin(), coinList.end(),\n         [](const CZerocoinEntryV3& coin){return !coin.IsUsed;}) == 9);\n \n     spends.clear();\n     db.ListCoinSpendSerial(spends);\n-    BOOST_TEST(spends.size() == 2);\n+    BOOST_CHECK(spends.size() == 2);\n }\n \n BOOST_AUTO_TEST_CASE(spend)\n@@ -550,11 +573,7 @@ BOOST_AUTO_TEST_CASE(spend)\n     std::vector<CRecipient> recipients;\n \n     GenerateBlockWithCoins({ std::make_pair(sigma::CoinDenominationV3::SIGMA_DENOM_10, 2) });\n-    GenerateBlockWithCoins({});\n-    GenerateBlockWithCoins({});\n-    GenerateBlockWithCoins({});\n-    GenerateBlockWithCoins({});\n-    GenerateBlockWithCoins({});\n+    GenerateEmptyBlocks(5);\n \n     recipients.push_back(CRecipient{\n         .scriptPubKey = GetScriptForDestination(randomAddr1.Get()),\n@@ -572,18 +591,18 @@ BOOST_AUTO_TEST_CASE(spend)\n     std::list<CZerocoinEntryV3> coins;\n     db.ListPubCoinV3(coins);\n \n-    BOOST_TEST(selected.size() == 1);\n-    BOOST_TEST(selected[0].get_denomination() == sigma::CoinDenominationV3::SIGMA_DENOM_10);\n-    BOOST_TEST(selected[0].id == 1);\n-    BOOST_TEST(selected[0].IsUsed);\n-    BOOST_TEST(selected[0].nHeight == 1);\n+    BOOST_CHECK(selected.size() == 1);\n+    BOOST_CHECK(selected[0].get_denomination() == sigma::CoinDenominationV3::SIGMA_DENOM_10);\n+    BOOST_CHECK(selected[0].id == 1);\n+    BOOST_CHECK(selected[0].IsUsed);\n+    BOOST_CHECK(selected[0].nHeight == 1);\n \n-    BOOST_TEST(spends.size() == 1);\n-    BOOST_TEST(spends.front().coinSerial == selected[0].serialNumber);\n-    BOOST_TEST((spends.front().hashTx == tx.GetHash()));\n-    BOOST_TEST(spends.front().pubCoin == selected[0].value);\n-    BOOST_TEST(spends.front().id == selected[0].id);\n-    BOOST_TEST(spends.front().get_denomination() == selected[0].get_denomination());\n+    BOOST_CHECK(spends.size() == 1);\n+    BOOST_CHECK(spends.front().coinSerial == selected[0].serialNumber);\n+    BOOST_CHECK((spends.front().hashTx == tx.GetHash()));\n+    BOOST_CHECK(spends.front().pubCoin == selected[0].value);\n+    BOOST_CHECK(spends.front().id == selected[0].id);\n+    BOOST_CHECK(spends.front().get_denomination() == selected[0].get_denomination());\n \n     for (auto& coin : coins) {\n         if (std::find_if(\n@@ -593,9 +612,9 @@ BOOST_AUTO_TEST_CASE(spend)\n             continue;\n         }\n \n-        BOOST_TEST(coin.IsUsed == false);\n-        BOOST_TEST(coin.id == -1);\n-        BOOST_TEST(coin.nHeight == -1);\n+        BOOST_CHECK(coin.IsUsed == false);\n+        BOOST_CHECK(coin.id == -1);\n+        BOOST_CHECK(coin.nHeight == -1);\n     }\n }\n \ndiff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp\nindex adc066ee3..68d544827 100644\n--- a/src/wallet/wallet.cpp\n+++ b/src/wallet/wallet.cpp\n@@ -1985,6 +1985,34 @@ static CAmount SelectSpendCoinsForAmount(\n \n } // end of unnamed namespace.\n \n+std::list<CZerocoinEntryV3> CWallet::GetAvailableCoins() const {\n+    std::list<CZerocoinEntryV3> coins;\n+    CWalletDB(strWalletFile).ListPubCoinV3(coins);\n+\n+    // Filter out coins which are not confirmed, I.E. do not have at least 6 blocks\n+    // above them, after they were minted.\n+    // Also filter out used coins.\n+    coins.remove_if([](const CZerocoinEntryV3& coin) {\n+        CZerocoinStateV3* zerocoinState = CZerocoinStateV3::GetZerocoinState();\n+        if (coin.IsUsed)\n+            return true;\n+\n+        int coinHeight =  zerocoinState->GetMintedCoinHeightAndId(\n+            PublicCoinV3(coin.value, coin.get_denomination())).first;\n+\n+        if (coinHeight == -1) {\n+            throw std::runtime_error("Unable to determine the coin height.\\n");\n+        }\n+        if (coinHeight + (ZC_MINT_CONFIRMATIONS - 1) > chainActive.Height()) {\n+            // Remove the coin from the candidates list, since it does not have the \n+            // required number of confirmations.\n+            return true;\n+        }\n+        return false;\n+    });\n+    return coins;\n+}\n+\n bool CWallet::GetCoinsToSpend(\n         CAmount required,\n         std::vector<CZerocoinEntryV3>& coinsToSpend_out,\n@@ -2007,8 +2035,7 @@ bool CWallet::GetCoinsToSpend(\n         required /= zeros;\n     }\n \n-    std::list<CZerocoinEntryV3> coins;\n-    CWalletDB(strWalletFile).ListPubCoinV3(coins);\n+    std::list<CZerocoinEntryV3> coins = GetAvailableCoins();\n     if (coins.empty())\n         return false;\n \n@@ -2041,8 +2068,6 @@ bool CWallet::GetCoinsToSpend(\n     ++coinIt;\n \n     for(; coinIt != coins.rend(); coinIt++) {\n-        if (coinIt->IsUsed)\n-            continue;\n         std::swap(prev_row, next_row);\n         CAmount denom_i = coinIt->get_denomination_value() / zeros;\n         for(int j = 1; j <= val; j++) {\n@@ -5244,7 +5269,7 @@ bool CWallet::CreateMultipleZerocoinSpendTransactionV3(\n             vector<TempStorage> tempStorages;\n \n             // object storing coins being used for this spend (to avoid duplicates being considered)\n-            unordered_set<GroupElement, GroupElement::hasher> tempCoinsToUse;\n+            unordered_set<GroupElement> tempCoinsToUse;\n \n             // Total value of all inputs. Iteritively created in the following loop\n             // The value is in multiples of COIN = 100 mln.\ndiff --git a/src/wallet/wallet.h b/src/wallet/wallet.h\nindex 91d93e663..f2a0c1fae 100644\n--- a/src/wallet/wallet.h\n+++ b/src/wallet/wallet.h\n@@ -827,6 +827,10 @@ public:\n     CAmount GetNeedsToBeAnonymizedBalance(CAmount nMinBalance = 0) const;\n     CAmount GetDenominatedBalance(bool unconfirmed=false) const;\n \n+    // Returns a list of unspent and verified coins, I.E. coins which are ready \n+    // to be spent.\n+    std::list<CZerocoinEntryV3> GetAvailableCoins() const;\n+\n     /** \\brief Selects coins to spend, and coins to re-mint based on the required amount to spend, provided by the user. As the lower denomination now is 0.1 zcoin, user\'s request will be rounded up to the nearest 0.1. This difference between the user\'s requested value, and the actually spent value will be left to the miners as a fee.\n      * \\param[in] required Required amount to spend.\n      * \\param[out] coinsToSpend_out Coins which user needs to spend.\ndiff --git a/src/zerocoin_v3.cpp b/src/zerocoin_v3.cpp\nindex 7f041fa83..fa5937cfb 100644\n--- a/src/zerocoin_v3.cpp\n+++ b/src/zerocoin_v3.cpp\n@@ -20,6 +20,8 @@\n \n #include <boost/foreach.hpp>\n \n+#include <ios>\n+\n using namespace std;\n \n // Set up the Zerocoin Params object\n@@ -28,7 +30,7 @@ sigma::ParamsV3* ZCParamsV3 = sigma::ParamsV3::get_default();\n static CZerocoinStateV3 zerocoinStateV3;\n \n static bool CheckZerocoinSpendSerialV3(\n-\t\tCValidationState &state, \n+\t\tCValidationState &state,\n \t\tCZerocoinTxInfoV3 *zerocoinTxInfoV3,\n \t\tconst Scalar &serial,\n \t\tint nHeight,\n@@ -49,7 +51,7 @@ static bool CheckZerocoinSpendSerialV3(\n \treturn true;\n }\n \n-// This function will not report an error only if the transaction is zerocoin spend V3. \n+// This function will not report an error only if the transaction is zerocoin spend V3.\n // Will return false for V1, V1.5 and V2 spends.\n // Mixing V2 and V3 spends into the same transaction will fail.\n bool CheckSpendZcoinTransactionV3(\n@@ -89,7 +91,7 @@ bool CheckSpendZcoinTransactionV3(\n \t\t\t\t\t"CheckSpendZcoinTransactionV3: invalid spend transaction");\n \n \t\t// Deserialize the CoinSpend into a fresh object\n-        // NOTE(martun): +1 on the next line stands for 1 byte in which the opcode of \n+        // NOTE(martun): +1 on the next line stands for 1 byte in which the opcode of\n         // OP_ZEROCOINSPENDV3 is written. In zerocoin you will see +4 instead,\n         // because the size of serialized spend is also written, probably in 3 bytes.\n \t\tCDataStream serializedCoinSpend((const char *)&*(txin.scriptSig.begin() + 1),\n@@ -115,13 +117,14 @@ bool CheckSpendZcoinTransactionV3(\n \t\t\t}\n \t\t}\n \t\ttxHashForMetadata = txTemp.GetHash();\n+\n \t\tLogPrintf("CheckSpendZcoinTransactionV3: tx version=%d, tx metadata hash=%s, serial=%s\\n",\n \t\t\t\tnewSpend.getVersion(), txHashForMetadata.ToString(),\n \t\t\t\tnewSpend.getCoinSerialNumber().tostring());\n \n \t\tCZerocoinStateV3::CoinGroupInfoV3 coinGroup;\n \t\tif (!zerocoinStateV3.GetCoinGroupInfo(targetDenominations[vinIndex], pubcoinId, coinGroup))\n-\t\t\treturn state.DoS(100, false, NO_MINT_ZEROCOIN, \n+\t\t\treturn state.DoS(100, false, NO_MINT_ZEROCOIN,\n \t\t\t\t\t"CheckSpendZcoinTransactionV3: Error: no coins were minted with such parameters");\n \n \t\tbool passVerify = false;\n@@ -146,7 +149,7 @@ bool CheckSpendZcoinTransactionV3(\n \t\t// This list of public coins is required by function "Verify" of CoinSpendV3.\n \t\tstd::vector<PublicCoinV3> anonymity_set;\n         while(true) {\n-\t\t\tBOOST_FOREACH(const sigma::PublicCoinV3& pubCoinValue, \n+\t\t\tBOOST_FOREACH(const sigma::PublicCoinV3& pubCoinValue,\n \t\t\t\t\tindex->mintedPubCoinsV3[denominationAndId]) {\n \t\t\t\tanonymity_set.push_back(pubCoinValue);\n \t\t\t}\n@@ -239,7 +242,7 @@ bool CheckMintZcoinTransactionV3(\n \t\t//                 false,\n \t\t//                 PUBCOIN_NOT_VALIDATE,\n \t\t//                 "CheckZerocoinTransaction: duplicate mint");\n-\t\tLogPrintf("CheckMintZerocoinTransactionV3: double mint, tx=%s\\n", \n+\t\tLogPrintf("CheckMintZerocoinTransactionV3: double mint, tx=%s\\n",\n \t\t\t\ttxout.GetHash().ToString());\n \t}\n \n@@ -336,9 +339,9 @@ Scalar ZerocoinGetSpendSerialNumberV3(const CTransaction &tx, const CTxIn &txin)\n \t\treturn Scalar(uint64_t(0));\n \n \ttry {\n-        // NOTE(martun): +1 on the next line stands for 1 byte in which the opcode of \n+        // NOTE(martun): +1 on the next line stands for 1 byte in which the opcode of\n         // OP_ZEROCOINSPENDV3 is written. In zerocoin you will see +4 instead,\n-        // because the size of serialized spend is also written, probably in 3 bytes.\t\n+        // because the size of serialized spend is also written, probably in 3 bytes.\n \t\tCDataStream serializedCoinSpend(\n \t\t\t\t(const char *)&*(txin.scriptSig.begin() + 1),\n \t\t\t\t(const char *)&*txin.scriptSig.end(),\n@@ -346,7 +349,7 @@ Scalar ZerocoinGetSpendSerialNumberV3(const CTransaction &tx, const CTxIn &txin)\n \t\tsigma::CoinSpendV3 spend(ZCParamsV3, serializedCoinSpend);\n \t\treturn spend.getCoinSerialNumber();\n \t}\n-\tcatch (const std::runtime_error &) {\n+\tcatch (const std::ios_base::failure &) {\n \t\treturn Scalar(uint64_t(0));\n \t}\n }\n@@ -404,10 +407,10 @@ bool ConnectBlockZCV3(\n \n \t\tBOOST_FOREACH(auto& serial, pblock->zerocoinTxInfoV3->spentSerials) {\n \t\t\tif (!CheckZerocoinSpendSerialV3(\n-\t\t\t\t\tstate, \n-\t\t\t\t\tpblock->zerocoinTxInfoV3.get(), \n-\t\t\t\t\tserial.first, \n-\t\t\t\t\tpindexNew->nHeight, \n+\t\t\t\t\tstate,\n+\t\t\t\t\tpblock->zerocoinTxInfoV3.get(),\n+\t\t\t\t\tserial.first,\n+\t\t\t\t\tpindexNew->nHeight,\n \t\t\t\t\ttrue /* fConnectTip */\n \t\t\t\t\t)) {\n \t\t\t\treturn false;\n@@ -422,20 +425,20 @@ bool ConnectBlockZCV3(\n         bool V3MintsAllowed = (pindexNew->nHeight >= Params().nMintV3SigmaStartBlock);\n \n         // If V3 mints are not allowed in this block, but some client tries to mint.\n-        if (!V3MintsAllowed && !pblock->zerocoinTxInfoV3->mints.empty()) \n+        if (!V3MintsAllowed && !pblock->zerocoinTxInfoV3->mints.empty())\n \t\t    return state.DoS(0, error("ConnectBlockZCV3 : V3 sigma mints not allowed until a given block"));\n \t\tif (fJustCheck)\n \t\t\treturn true;\n \n \t\t// Update pindexNew.mintedPubCoinsV3\n \t\tBOOST_FOREACH(const PublicCoinV3& mint, pblock->zerocoinTxInfoV3->mints) {\n-\t\t\tCoinDenominationV3 denomination = mint.getDenomination();            \n+\t\t\tCoinDenominationV3 denomination = mint.getDenomination();\n \t\t\tint mintId = zerocoinStateV3.AddMint(pindexNew,\tmint);\n \n \t\t\tLogPrintf("ConnectTipZC: mint added denomination=%d, id=%d\\n", denomination, mintId);\n \t\t\tpair<CoinDenominationV3, int> denomAndId = make_pair(denomination, mintId);\n \t\t\tpindexNew->mintedPubCoinsV3[denomAndId].push_back(mint);\n-\t\t}               \n+\t\t}\n \t}\n \telse if (!fJustCheck) { // TODO(martun): not sure if this else is necessary here. Check again later.\n \t\tzerocoinStateV3.AddBlock(pindexNew);\n@@ -484,7 +487,7 @@ CZerocoinStateV3::CZerocoinStateV3() {\n }\n \n int CZerocoinStateV3::AddMint(\n-\t\tCBlockIndex *index, \n+\t\tCBlockIndex *index,\n \t\tconst PublicCoinV3 &pubCoin) {\n \tsigma::CoinDenominationV3 denomination = pubCoin.getDenomination();\n \n@@ -493,7 +496,7 @@ int CZerocoinStateV3::AddMint(\n     int\tmintCoinGroupId = latestCoinIds[denomination];\n \n     // ZC_SPEND_V3_COINSPERID = 15.000, yet the actual limit of coins per accumlator is 16.000.\n-    // We need to cut at 15.000, such that we always have enough space for new mints. Mints for \n+    // We need to cut at 15.000, such that we always have enough space for new mints. Mints for\n     // each block will end up in the same accumulator.\n \tCoinGroupInfoV3 &coinGroup = coinGroups[make_pair(denomination, mintCoinGroupId)];\n \tint coinsPerId = ZC_SPEND_V3_COINSPERID;\n@@ -557,7 +560,7 @@ void CZerocoinStateV3::AddBlock(CBlockIndex *index) {\n void CZerocoinStateV3::RemoveBlock(CBlockIndex *index) {\n \t// roll back accumulator updates\n \tBOOST_FOREACH(\n-        const PAIRTYPE(PAIRTYPE(sigma::CoinDenominationV3, int),vector<PublicCoinV3>) &coin, \n+        const PAIRTYPE(PAIRTYPE(sigma::CoinDenominationV3, int),vector<PublicCoinV3>) &coin,\n         index->mintedPubCoinsV3)\n \t{\n \t\tCoinGroupInfoV3   &coinGroup = coinGroups[coin.first];\n@@ -581,12 +584,12 @@ void CZerocoinStateV3::RemoveBlock(CBlockIndex *index) {\n \t}\n \n \t// roll back mints\n-\tBOOST_FOREACH(const PAIRTYPE(PAIRTYPE(CoinDenominationV3, int),vector<PublicCoinV3>) &pubCoins, \n+\tBOOST_FOREACH(const PAIRTYPE(PAIRTYPE(CoinDenominationV3, int),vector<PublicCoinV3>) &pubCoins,\n                   index->mintedPubCoinsV3) {\n \t\tBOOST_FOREACH(const PublicCoinV3 &coin, pubCoins.second) {\n \t\t\tauto coins = mintedPubCoins.equal_range(coin);\n \t\t\tauto coinIt = find_if(\n-                coins.first, coins.second, \n+                coins.first, coins.second,\n                 [=](const decltype(mintedPubCoins)::value_type &v) {\n \t\t\t\t\treturn v.second.denomination == pubCoins.first.first &&\n \t\t\t\t\t    v.second.id == pubCoins.first.second;\n@@ -605,7 +608,7 @@ bool CZerocoinStateV3::GetCoinGroupInfo(\n         sigma::CoinDenominationV3 denomination,\n         int group_id,\n         CoinGroupInfoV3& result) {\n-\tstd::pair<sigma::CoinDenominationV3, int> key = \n+\tstd::pair<sigma::CoinDenominationV3, int> key =\n         std::make_pair(denomination, group_id);\n \tif (coinGroups.count(key) == 0)\n \t\treturn false;\n@@ -649,7 +652,7 @@ int CZerocoinStateV3::GetCoinSetForSpend(\n \t\t\t\t\tblockHash_out = block->GetBlockHash();\n \t\t\t\t}\n \t\t\t\tnumberOfCoins += block->mintedPubCoinsV3[denomAndId].size();\n-\t\t\t\tcoins_out.insert(coins_out.end(), \n+\t\t\t\tcoins_out.insert(coins_out.end(),\n \t\t\t\t\t\tblock->mintedPubCoinsV3[denomAndId].begin(),\n \t\t\t\t\t\tblock->mintedPubCoinsV3[denomAndId].end());\n \t\t\t}\n', 'commit_subject': 'Applied review comments', 'repo_name': 'zcoinofficial/zcoin', 'committer': {'name': 'martun', 'email': '36fad7a3a2df08eb50d47caaa519a80878dafd24@gmail.com', 'time_sec': '1552776710', 'tz_offset': '240', 'date': {'seconds': '1552776710'}}, 'commit_tree': 'd319e63d3f91932ec257c7465c9378ce74921415', 'commit_message': 'Applied review comments\n', 'language_name': 'C++', 'license': 'mit', 'hunks': "@@ -827,6 +827,10 @@ public:\n     CAmount GetNeedsToBeAnonymizedBalance(CAmount nMinBalance = 0) const;\n     CAmount GetDenominatedBalance(bool unconfirmed=false) const;\n \n+    // Returns a list of unspent and verified coins, I.E. coins which are ready \n+    // to be spent.\n+    std::list<CZerocoinEntryV3> GetAvailableCoins() const;\n+\n     /** \\brief Selects coins to spend, and coins to re-mint based on the required amount to spend, provided by the user. As the lower denomination now is 0.1 zcoin, user's request will be rounded up to the nearest 0.1. This difference between the user's requested value, and the actually spent value will be left to the miners as a fee.\n      * \\param[in] required Required amount to spend.\n      * \\param[out] coinsToSpend_out Coins which user needs to spend.\n", 'addition_count': 4, 'deletion_count': 0, 'src_file': 'a/src/wallet/wallet.h', 'tgt_file': 'b/src/wallet/wallet.h', 'file_extension': '.h', 'before_file': '// Copyright (c) 2009-2010 Satoshi Nakamoto\n// Copyright (c) 2009-2016 The Bitcoin Core developers\n// Distributed under the MIT software license, see the accompanying\n// file COPYING or http://www.opensource.org/licenses/mit-license.php.\n\n#ifndef BITCOIN_WALLET_WALLET_H\n#define BITCOIN_WALLET_WALLET_H\n\n#include "amount.h"\n#include "../sigma/coin.h"\n#include "../liblelantus/coin.h"\n#include "streams.h"\n#include "tinyformat.h"\n#include "ui_interface.h"\n#include "utilstrencodings.h"\n#include "validationinterface.h"\n#include "script/ismine.h"\n#include "script/sign.h"\n#include "wallet/crypter.h"\n#include "wallet/walletdb.h"\n#include "wallet/rpcwallet.h"\n#include "wallet/mnemoniccontainer.h"\n#include "../base58.h"\n#include "firo_params.h"\n#include "univalue.h"\n\n#include "hdmint/tracker.h"\n#include "hdmint/wallet.h"\n\n#include "primitives/mint_spend.h"\n\n#include "bip47/paymentcode.h"\n\n\n#include <algorithm>\n#include <atomic>\n#include <map>\n#include <set>\n#include <stdexcept>\n#include <stdint.h>\n#include <string>\n#include <utility>\n#include <vector>\n\n#include <boost/shared_ptr.hpp>\n#include <boost/thread.hpp>\n\nextern CWallet* pwalletMain;\n\n/**\n * Settings\n */\nextern CFeeRate payTxFee;\nextern unsigned int nTxConfirmTarget;\nextern bool bSpendZeroConfChange;\nextern bool fSendFreeTransactions;\nextern bool fWalletRbf;\n\nstatic const unsigned int DEFAULT_KEYPOOL_SIZE = 100;\n//! -paytxfee default\nstatic const CAmount DEFAULT_TRANSACTION_FEE = 0;\n//! -fallbackfee default\nstatic const CAmount DEFAULT_FALLBACK_FEE = 20000;\n//! -mintxfee default\nstatic const CAmount DEFAULT_TRANSACTION_MINFEE = 1000;\n//! minimum recommended increment for BIP 125 replacement txs\nstatic const CAmount WALLET_INCREMENTAL_RELAY_FEE = 5000;\n//! target minimum change amount\nstatic const CAmount MIN_CHANGE = CENT;\n//! final minimum change amount after paying for fees\nstatic const CAmount MIN_FINAL_CHANGE = MIN_CHANGE/2;\n//! Default for -spendzeroconfchange\nstatic const bool DEFAULT_SPEND_ZEROCONF_CHANGE = true;\n//! Default for -sendfreetransactions\nstatic const bool DEFAULT_SEND_FREE_TRANSACTIONS = false;\n//! Default for -walletrejectlongchains\nstatic const bool DEFAULT_WALLET_REJECT_LONG_CHAINS = false;\n//! -txconfirmtarget default\nstatic const unsigned int DEFAULT_TX_CONFIRM_TARGET = 6;\n//! -walletrbf default\nstatic const bool DEFAULT_WALLET_RBF = false;\n//! Largest (in bytes) free transaction we\'re willing to create\nstatic const unsigned int MAX_FREE_TRANSACTION_CREATE_SIZE = 1000;\nstatic const bool DEFAULT_WALLETBROADCAST = true;\nstatic const bool DEFAULT_DISABLE_WALLET = false;\n\nstatic const bool DEFAULT_UPGRADE_CHAIN = false;\n\n//! if set, all keys will be derived by using BIP32\nstatic const bool DEFAULT_USE_HD_WALLET = true;\n\n//! if set, all keys will be derived by using BIP39\nstatic const bool DEFAULT_USE_MNEMONIC = true;\n\nextern const char * DEFAULT_WALLET_DAT;\n\nconst uint32_t BIP32_HARDENED_KEY_LIMIT = 0x80000000;\nconst uint32_t BIP44_INDEX = 0x2C;\nconst uint32_t BIP44_TEST_INDEX = 0x1;   // https://github.com/satoshilabs/slips/blob/master/slip-0044.md#registered-coin-types\nconst uint32_t BIP44_FIRO_INDEX = 0x88; // https://github.com/satoshilabs/slips/blob/master/slip-0044.md#registered-coin-types\nconst uint32_t BIP44_MINT_INDEX = 0x2;\n#ifdef ENABLE_ELYSIUM\nconst uint32_t BIP44_ELYSIUM_MINT_INDEX_V0 = 0x3;\nconst uint32_t BIP44_ELYSIUM_MINT_INDEX_V1 = 0x4;\n#endif\nconst uint32_t BIP44_MINT_VALUE_INDEX = 0x5;\n\nclass CBlockIndex;\nclass CCoinControl;\nclass COutput;\nclass CReserveKey;\nclass CScript;\nclass CTxMemPool;\nclass CWalletTx;\nnamespace bip47 {\nclass CPaymentChannel;\n}\n\n\nnamespace bip47 {\n    class CPaymentCode;\n    class CWallet;\n}\n\n/** (client) version numbers for particular wallet features */\nenum WalletFeature\n{\n    FEATURE_BASE = 10500, // the earliest version new wallets supports (only useful for getinfo\'s clientversion output)\n\n    FEATURE_WALLETCRYPT = 40000, // wallet encryption\n    FEATURE_COMPRPUBKEY = 60000, // compressed public keys\n\n    FEATURE_HD = 130000, // Hierarchical key derivation after BIP32 (HD Wallet)\n    FEATURE_LATEST = FEATURE_COMPRPUBKEY // HD is optional, use FEATURE_COMPRPUBKEY as latest version\n};\n\nstruct CompactTallyItem\n{\n    CBitcoinAddress address;\n    CAmount nAmount;\n    std::vector<CTxIn> vecTxIn;\n    CompactTallyItem()\n    {\n        nAmount = 0;\n    }\n};\n\n\n/** A key pool entry */\nclass CKeyPool\n{\npublic:\n    int64_t nTime;\n    CPubKey vchPubKey;\n\n    CKeyPool();\n    CKeyPool(const CPubKey& vchPubKeyIn);\n\n    ADD_SERIALIZE_METHODS;\n\n    template <typename Stream, typename Operation>\n    inline void SerializationOp(Stream& s, Operation ser_action) {\n        int nVersion = s.GetVersion();\n        if (!(s.GetType() & SER_GETHASH))\n            READWRITE(nVersion);\n        READWRITE(nTime);\n        READWRITE(vchPubKey);\n    }\n};\n\n/** Address book data */\nclass CAddressBookData\n{\npublic:\n    std::string name;\n    std::string purpose;\n\n    CAddressBookData()\n    {\n        purpose = "unknown";\n    }\n\n    typedef std::map<std::string, std::string> StringMap;\n    StringMap destdata;\n};\n\nstruct CRecipient\n{\n    CScript scriptPubKey;\n    CAmount nAmount;\n    bool fSubtractFeeFromAmount;\n};\n\ntypedef std::map<std::string, std::string> mapValue_t;\n\n\nstatic inline void ReadOrderPos(int64_t& nOrderPos, mapValue_t& mapValue)\n{\n    if (!mapValue.count("n"))\n    {\n        nOrderPos = -1; // TODO: calculate elsewhere\n        return;\n    }\n    nOrderPos = atoi64(mapValue["n"].c_str());\n}\n\n\nstatic inline void WriteOrderPos(const int64_t& nOrderPos, mapValue_t& mapValue)\n{\n    if (nOrderPos == -1)\n        return;\n    mapValue["n"] = i64tostr(nOrderPos);\n}\n\nstruct COutputEntry\n{\n    CTxDestination destination;\n    CAmount amount;\n    int vout;\n};\n\n/** A transaction with a merkle branch linking it to the block chain. */\nclass CMerkleTx\n{\nprivate:\n  /** Constant used in hashBlock to indicate tx has been abandoned */\n    static const uint256 ABANDON_HASH;\n\npublic:\n    CTransactionRef tx;\n    uint256 hashBlock;\n\n    /* An nIndex == -1 means that hashBlock (in nonzero) refers to the earliest\n     * block in the chain we know this or any in-wallet dependency conflicts\n     * with. Older clients interpret nIndex == -1 as unconfirmed for backward\n     * compatibility.\n     */\n    int nIndex;\n\n    CMerkleTx()\n    {\n        SetTx(MakeTransactionRef());\n        Init();\n    }\n\n    CMerkleTx(CTransactionRef arg)\n    {\n        SetTx(std::move(arg));\n        Init();\n    }\n\n    /** Helper conversion operator to allow passing CMerkleTx where CTransaction is expected.\n     *  TODO: adapt callers and remove this operator. */\n    operator const CTransaction&() const { return *tx; }\n\n    void Init()\n    {\n        hashBlock = uint256();\n        nIndex = -1;\n    }\n\n    void SetTx(CTransactionRef arg)\n    {\n        tx = std::move(arg);\n    }\n\n    ADD_SERIALIZE_METHODS;\n\n    template <typename Stream, typename Operation>\n    inline void SerializationOp(Stream& s, Operation ser_action) {\n        std::vector<uint256> vMerkleBranch; // For compatibility with older versions.\n        READWRITE(tx);\n        READWRITE(hashBlock);\n        READWRITE(vMerkleBranch);\n        READWRITE(nIndex);\n    }\n\n    void SetMerkleBranch(const CBlockIndex* pIndex, int posInBlock);\n\n    /**\n     * Return depth of transaction in blockchain:\n     * <0  : conflicts with a transaction this deep in the blockchain\n     *  0  : in memory pool, waiting to be included in a block\n     * >=1 : this many blocks deep in the main chain\n     */\n    int GetDepthInMainChain(const CBlockIndex* &pindexRet) const;\n    int GetDepthInMainChain() const { const CBlockIndex *pindexRet; return GetDepthInMainChain(pindexRet); }\n\n    int GetDepthInMainChain(const CBlockIndex* &pindexRet, bool enableIX) const;\n    int GetDepthInMainChain(bool enableIX) const { const CBlockIndex *pindexRet; return GetDepthInMainChain(pindexRet, enableIX); }\n\n    bool IsInMainChain() const { const CBlockIndex *pindexRet; return GetDepthInMainChain(pindexRet) > 0; }\n    bool IsLockedByLLMQInstantSend() const;\n    bool IsChainLocked() const;\n    int GetBlocksToMaturity() const;\n\n    bool AcceptToMemoryPool(const CAmount& nAbsurdFee, CValidationState& state);\n    bool hashUnset() const { return (hashBlock.IsNull() || hashBlock == ABANDON_HASH); }\n    bool isAbandoned() const { return (hashBlock == ABANDON_HASH); }\n    void setAbandoned() { hashBlock = ABANDON_HASH; }\n\n    const uint256& GetHash() const { return tx->GetHash(); }\n    bool IsCoinBase() const { return tx->IsCoinBase(); }\n};\n\n/**\n * A transaction with a bunch of additional info that only the owner cares about.\n * It includes any unrecorded transactions needed to link it back to the block chain.\n */\nclass CWalletTx : public CMerkleTx\n{\nprivate:\n    const CWallet* pwallet;\n\npublic:\n    mapValue_t mapValue;\n    std::vector<std::pair<std::string, std::string> > vOrderForm;\n    unsigned int fTimeReceivedIsTxTime;\n    unsigned int nTimeReceived; //!< time received by this node\n    unsigned int nTimeSmart;\n    /**\n     * From me flag is set to 1 for transactions that were created by the wallet\n     * on this bitcoin node, and set to 0 for transactions that were created\n     * externally and came in through the network or sendrawtransaction RPC.\n     */\n    char fFromMe;\n    std::string strFromAccount;\n    int64_t nOrderPos; //!< position in ordered transaction list\n    std::unordered_set<uint32_t> changes; //!< positions of changes in vout\n\n    // memory only\n    mutable bool fDebitCached;\n    mutable bool fCreditCached;\n    mutable bool fImmatureCreditCached;\n    mutable bool fAvailableCreditCached;\n    mutable bool fWatchDebitCached;\n    mutable bool fWatchCreditCached;\n    mutable bool fImmatureWatchCreditCached;\n    mutable bool fAvailableWatchCreditCached;\n    mutable bool fChangeCached;\n    mutable CAmount nDebitCached;\n    mutable CAmount nCreditCached;\n    mutable CAmount nImmatureCreditCached;\n    mutable CAmount nAvailableCreditCached;\n    mutable CAmount nWatchDebitCached;\n    mutable CAmount nWatchCreditCached;\n    mutable CAmount nImmatureWatchCreditCached;\n    mutable CAmount nAvailableWatchCreditCached;\n    mutable CAmount nChangeCached;\n\n    CWalletTx()\n    {\n        Init(NULL);\n    }\n\n    CWalletTx(const CWallet* pwalletIn, CTransactionRef arg) : CMerkleTx(std::move(arg))\n    {\n        Init(pwalletIn);\n    }\n\n    void Init(const CWallet* pwalletIn)\n    {\n        pwallet = pwalletIn;\n        mapValue.clear();\n        vOrderForm.clear();\n        fTimeReceivedIsTxTime = false;\n        nTimeReceived = 0;\n        nTimeSmart = 0;\n        fFromMe = false;\n        strFromAccount.clear();\n        fDebitCached = false;\n        fCreditCached = false;\n        fImmatureCreditCached = false;\n        fAvailableCreditCached = false;\n        fWatchDebitCached = false;\n        fWatchCreditCached = false;\n        fImmatureWatchCreditCached = false;\n        fAvailableWatchCreditCached = false;\n        fChangeCached = false;\n        nDebitCached = 0;\n        nCreditCached = 0;\n        nImmatureCreditCached = 0;\n        nAvailableCreditCached = 0;\n        nWatchDebitCached = 0;\n        nWatchCreditCached = 0;\n        nAvailableWatchCreditCached = 0;\n        nImmatureWatchCreditCached = 0;\n        nChangeCached = 0;\n        nOrderPos = -1;\n        changes.clear();\n    }\n\n    ADD_SERIALIZE_METHODS;\n\n    template <typename Stream, typename Operation>\n    inline void SerializationOp(Stream& s, Operation ser_action) {\n        constexpr uint32_t FLAG_WITH_CHANGES = 0x00000001;\n\n        if (ser_action.ForRead())\n            Init(NULL);\n\n        char fSpent = false;\n        uint32_t flags = 0;\n\n        if (!ser_action.ForRead())\n        {\n            flags = FLAG_WITH_CHANGES;\n\n            mapValue["fromaccount"] = strFromAccount;\n            mapValue["flags"] = strprintf("0x%x", flags);\n\n            WriteOrderPos(nOrderPos, mapValue);\n\n            if (nTimeSmart)\n                mapValue["timesmart"] = strprintf("%u", nTimeSmart);\n        }\n\n        READWRITE(*(CMerkleTx*)this);\n        std::vector<CMerkleTx> vUnused; //!< Used to be vtxPrev\n        READWRITE(vUnused);\n        READWRITE(mapValue);\n        READWRITE(vOrderForm);\n        READWRITE(fTimeReceivedIsTxTime);\n        READWRITE(nTimeReceived);\n        READWRITE(fFromMe);\n        READWRITE(fSpent);\n\n        if (ser_action.ForRead())\n        {\n            strFromAccount = mapValue["fromaccount"];\n\n            ReadOrderPos(nOrderPos, mapValue);\n\n            nTimeSmart = mapValue.count("timesmart") ? (unsigned int)atoi64(mapValue["timesmart"]) : 0;\n\n            auto it = mapValue.find("flags");\n            if (it != mapValue.end()) {\n                flags = static_cast<uint32_t>(std::strtoul(it->second.c_str(), nullptr, 0));\n            }\n        }\n\n        if (flags & FLAG_WITH_CHANGES) {\n            READWRITE(changes);\n        }\n\n        mapValue.erase("fromaccount");\n        mapValue.erase("version");\n        mapValue.erase("spent");\n        mapValue.erase("n");\n        mapValue.erase("timesmart");\n        mapValue.erase("flags");\n    }\n\n    //! make sure balances are recalculated\n    void MarkDirty()\n    {\n        fCreditCached = false;\n        fAvailableCreditCached = false;\n        fImmatureCreditCached = false;\n        fWatchDebitCached = false;\n        fWatchCreditCached = false;\n        fAvailableWatchCreditCached = false;\n        fImmatureWatchCreditCached = false;\n        fDebitCached = false;\n        fChangeCached = false;\n    }\n\n    void BindWallet(CWallet *pwalletIn)\n    {\n        pwallet = pwalletIn;\n        MarkDirty();\n    }\n\n    //! filter decides which addresses will count towards the debit\n    CAmount GetDebit(const isminefilter& filter) const;\n    CAmount GetCredit(const isminefilter& filter) const;\n    CAmount GetImmatureCredit(bool fUseCache=true) const;\n    CAmount GetAvailableCredit(bool fUseCache=true, bool fExcludeLocked = false) const;\n    CAmount GetImmatureWatchOnlyCredit(const bool& fUseCache=true) const;\n    CAmount GetAvailableWatchOnlyCredit(const bool& fUseCache=true) const;\n    CAmount GetAnonymizedCredit(bool fUseCache=true) const;\n    CAmount GetChange() const;\n\n    void GetAmounts(std::list<COutputEntry>& listReceived,\n                    std::list<COutputEntry>& listSent, CAmount& nFee, std::string& strSentAccount, const isminefilter& filter) const;\n\n    bool IsFromMe(const isminefilter& filter) const\n    {\n        return (GetDebit(filter) > 0);\n    }\n\n    // True if only scriptSigs are different\n    bool IsEquivalentTo(const CWalletTx& tx) const;\n\n    bool InMempool() const;\n    bool InStempool() const;\n    bool IsTrusted() const;\n\n    bool IsChange(uint32_t out) const;\n    bool IsChange(const CTxOut& out) const;\n\n    int64_t GetTxTime() const;\n    int GetRequestCount() const;\n\n    bool RelayWalletTransaction(CConnman* connman);\n\n    std::set<uint256> GetConflicts() const;\n};\n\n\n\n\nclass COutput\n{\npublic:\n    const CWalletTx *tx;\n    int i;\n    int nDepth;\n    bool fSpendable;\n    bool fSolvable;\n\n    COutput(const CWalletTx *txIn, int iIn, int nDepthIn, bool fSpendableIn, bool fSolvableIn)\n    {\n        tx = txIn; i = iIn; nDepth = nDepthIn; fSpendable = fSpendableIn; fSolvable = fSolvableIn;\n    }\n\n    std::string ToString() const;\n};\n\n\n\n\n/** Private key that includes an expiration date in case it never gets used. */\nclass CWalletKey\n{\npublic:\n    CPrivKey vchPrivKey;\n    int64_t nTimeCreated;\n    int64_t nTimeExpires;\n    std::string strComment;\n    //! todo: add something to note what created it (user, getnewaddress, change)\n    //!   maybe should have a map<string, string> property map\n\n    CWalletKey(int64_t nExpires=0);\n\n    ADD_SERIALIZE_METHODS;\n\n    template <typename Stream, typename Operation>\n    inline void SerializationOp(Stream& s, Operation ser_action) {\n        int nVersion = s.GetVersion();\n        if (!(s.GetType() & SER_GETHASH))\n            READWRITE(nVersion);\n        READWRITE(vchPrivKey);\n        READWRITE(nTimeCreated);\n        READWRITE(nTimeExpires);\n        READWRITE(LIMITED_STRING(strComment, 65536));\n    }\n};\n\n/**\n * Internal transfers.\n * Database key is acentry<account><counter>.\n */\nclass CAccountingEntry\n{\npublic:\n    std::string strAccount;\n    CAmount nCreditDebit;\n    int64_t nTime;\n    std::string strOtherAccount;\n    std::string strComment;\n    mapValue_t mapValue;\n    int64_t nOrderPos; //!< position in ordered transaction list\n    uint64_t nEntryNo;\n\n    CAccountingEntry()\n    {\n        SetNull();\n    }\n\n    void SetNull()\n    {\n        nCreditDebit = 0;\n        nTime = 0;\n        strAccount.clear();\n        strOtherAccount.clear();\n        strComment.clear();\n        nOrderPos = -1;\n        nEntryNo = 0;\n    }\n\n    ADD_SERIALIZE_METHODS;\n\n    template <typename Stream, typename Operation>\n    inline void SerializationOp(Stream& s, Operation ser_action) {\n        int nVersion = s.GetVersion();\n        if (!(s.GetType() & SER_GETHASH))\n            READWRITE(nVersion);\n        //! Note: strAccount is serialized as part of the key, not here.\n        READWRITE(nCreditDebit);\n        READWRITE(nTime);\n        READWRITE(LIMITED_STRING(strOtherAccount, 65536));\n\n        if (!ser_action.ForRead())\n        {\n            WriteOrderPos(nOrderPos, mapValue);\n\n            if (!(mapValue.empty() && _ssExtra.empty()))\n            {\n                CDataStream ss(s.GetType(), s.GetVersion());\n                ss.insert(ss.begin(), \'\\0\');\n                ss << mapValue;\n                ss.insert(ss.end(), _ssExtra.begin(), _ssExtra.end());\n                strComment.append(ss.str());\n            }\n        }\n\n        READWRITE(LIMITED_STRING(strComment, 65536));\n\n        size_t nSepPos = strComment.find("\\0", 0, 1);\n        if (ser_action.ForRead())\n        {\n            mapValue.clear();\n            if (std::string::npos != nSepPos)\n            {\n                CDataStream ss(std::vector<char>(strComment.begin() + nSepPos + 1, strComment.end()), s.GetType(), s.GetVersion());\n                ss >> mapValue;\n                _ssExtra = std::vector<char>(ss.begin(), ss.end());\n            }\n            ReadOrderPos(nOrderPos, mapValue);\n        }\n        if (std::string::npos != nSepPos)\n            strComment.erase(nSepPos);\n\n        mapValue.erase("n");\n    }\n\nprivate:\n    std::vector<char> _ssExtra;\n};\n\nclass LelantusJoinSplitBuilder;\n\n/**\n * A CWallet is an extension of a keystore, which also maintains a set of transactions and balances,\n * and provides the ability to create new transactions.\n */\nclass CWallet : public CCryptoKeyStore, public CValidationInterface\n{\nprivate:\n    static std::atomic<bool> fFlushThreadRunning;\n\n    /**\n     * Select a set of coins such that nValueRet >= nTargetValue and at least\n     * all coins from coinControl are selected; Never select unconfirmed coins\n     * if they are not ours\n     */\n    bool SelectCoins(const std::vector<COutput>& vAvailableCoins, const CAmount& nTargetValue, std::set<std::pair<const CWalletTx*,unsigned int> >& setCoinsRet, CAmount& nValueRet, const CCoinControl *coinControl = NULL, bool fForUseInInstantSend = true) const;\n\n    CWalletDB *pwalletdbEncryption;\n\n    //! the current wallet version: clients below this version are not able to load the wallet\n    int nWalletVersion;\n\n    //! the maximum wallet format version: memory-only variable that specifies to what version this wallet may be upgraded\n    int nWalletMaxVersion;\n\n    int64_t nNextResend;\n    int64_t nLastResend;\n    bool fBroadcastTransactions;\n\n    mutable bool fAnonymizableTallyCached;\n    mutable std::vector<CompactTallyItem> vecAnonymizableTallyCached;\n    mutable bool fAnonymizableTallyCachedNonDenom;\n    mutable std::vector<CompactTallyItem> vecAnonymizableTallyCachedNonDenom;\n\n    /**\n     * Used to keep track of spent outpoints, and\n     * detect and report conflicts (double-spends or\n     * mutated transactions where the mutant gets mined).\n     */\n    typedef std::multimap<COutPoint, uint256> TxSpends;\n    TxSpends mapTxSpends;\n    void AddToSpends(const COutPoint& outpoint, const uint256& wtxid);\n    void AddToSpends(const uint256& wtxid);\n\n    std::set<COutPoint> setWalletUTXO;\n\n    /* Mark a transaction (and its in-wallet descendants) as conflicting with a particular block. */\n    void MarkConflicted(const uint256& hashBlock, const uint256& hashTx);\n\n    void SyncMetaData(std::pair<TxSpends::iterator, TxSpends::iterator>);\n\n    /* the HD chain data model (external chain counters) */\n    CHDChain hdChain;\n    MnemonicContainer mnemonicContainer;\n\n    bool fFileBacked;\n\n    std::set<int64_t> setKeyPool;\n\n    std::map<CKeyID, int64_t> m_pool_key_to_index;\n\n    int64_t nTimeFirstKey;\n\n    std::shared_ptr<bip47::CWallet> bip47wallet;\n\n    /**\n     * Private version of AddWatchOnly method which does not accept a\n     * timestamp, and which will reset the wallet\'s nTimeFirstKey value to 1 if\n     * the watch key did not previously have a timestamp associated with it.\n     * Because this is an inherited virtual method, it is accessible despite\n     * being marked private, but it is marked private anyway to encourage use\n     * of the other AddWatchOnly which accepts a timestamp and sets\n     * nTimeFirstKey more intelligently for more efficient rescans.\n     */\n    bool AddWatchOnly(const CScript& dest) override;\n\npublic:\n    /*\n     * Main wallet lock.\n     * This lock protects all the fields added by CWallet\n     *   except for:\n     *      fFileBacked (immutable after instantiation)\n     *      strWalletFile (immutable after instantiation)\n     */\n    mutable CCriticalSection cs_wallet;\n\n    const std::string strWalletFile;\n\n    void LoadKeyPool(int nIndex, const CKeyPool &keypool)\n    {\n        setKeyPool.insert(nIndex);\n\n        m_pool_key_to_index[keypool.vchPubKey.GetID()] = nIndex;\n        // If no metadata exists yet, create a default with the pool key\'s\n        // creation time. Note that this may be overwritten by actually\n        // stored metadata for that key later, which is fine.\n        CKeyID keyid = keypool.vchPubKey.GetID();\n        if (mapKeyMetadata.count(keyid) == 0)\n            mapKeyMetadata[keyid] = CKeyMetadata(keypool.nTime);\n    }\n\n    // Map from Key ID (for regular keys) or Script ID (for watch-only keys) to\n    // key metadata.\n    std::map<CTxDestination, CKeyMetadata> mapKeyMetadata;\n    //znode\n    int64_t nKeysLeftSinceAutoBackup;\n\n    typedef std::map<unsigned int, CMasterKey> MasterKeyMap;\n    MasterKeyMap mapMasterKeys;\n    unsigned int nMasterKeyMaxID;\n\n    std::unique_ptr<CHDMintWallet> zwallet;\n\n    CWallet()\n    {\n        SetNull();\n    }\n\n    CWallet(const std::string& strWalletFileIn) : strWalletFile(strWalletFileIn)\n    {\n        SetNull();\n        fFileBacked = true;\n    }\n\n    ~CWallet()\n    {\n        delete pwalletdbEncryption;\n        pwalletdbEncryption = NULL;\n    }\n\n    void SetNull()\n    {\n        nWalletVersion = FEATURE_BASE;\n        nWalletMaxVersion = FEATURE_BASE;\n        fFileBacked = false;\n        nMasterKeyMaxID = 0;\n        pwalletdbEncryption = NULL;\n        nOrderPosNext = 0;\n        nNextResend = 0;\n        nLastResend = 0;\n        nTimeFirstKey = 0;\n        fBroadcastTransactions = false;\n        fAnonymizableTallyCached = false;\n        fAnonymizableTallyCachedNonDenom = false;\n        vecAnonymizableTallyCached.clear();\n        vecAnonymizableTallyCachedNonDenom.clear();\n        zwallet = NULL;\n        bip47wallet.reset();\n    }\n\n    std::map<uint256, CWalletTx> mapWallet;\n    std::list<CAccountingEntry> laccentries;\n    bool EraseFromWallet(uint256 hash);\n    typedef std::pair<CWalletTx*, CAccountingEntry*> TxPair;\n    typedef std::multimap<int64_t, TxPair > TxItems;\n    TxItems wtxOrdered;\n\n    int64_t nOrderPosNext;\n    std::map<uint256, int> mapRequestCount;\n\n    std::map<CTxDestination, CAddressBookData> mapAddressBook;\n    std::multimap<std::string, std::string> mapCustomKeyValues;\n\n    CPubKey vchDefaultKey;\n\n    std::set<COutPoint> setLockedCoins;\n\n    const CWalletTx* GetWalletTx(const uint256& hash) const;\n\n    //! check whether we are allowed to upgrade (or already support) to the named feature\n    bool CanSupportFeature(enum WalletFeature wf) { AssertLockHeld(cs_wallet); return nWalletMaxVersion >= wf; }\n\n    /**\n     * populate vCoins with vector of available COutputs.\n     */\n    void AvailableCoins(std::vector<COutput>& vCoins, bool fOnlyConfirmed=true, const CCoinControl *coinControl = NULL, bool fIncludeZeroValue=false, bool fForUseInInstantSend = false) const;\n\n    void AvailableCoinsForLMint(std::vector<std::pair<CAmount, std::vector<COutput>>>& valueAndUTXO, const CCoinControl *coinControl) const;\n\n    bool IsHDSeedAvailable() { return !hdChain.masterKeyID.IsNull(); }\n\n    /**\n     * Shuffle and select coins until nTargetValue is reached while avoiding\n     * small change; This method is stochastic for some inputs and upon\n    CAmount GetNeedsToBeAnonymizedBalance(CAmount nMinBalance = 0) const;\n    CAmount GetDenominatedBalance(bool unconfirmed=false) const;\n\n    /** \\brief Selects coins to spend, and coins to re-mint based on the required amount to spend, provided by the user. As the lower denomination now is 0.1 zcoin, user\'s request will be rounded up to the nearest 0.1. This difference between the user\'s requested value, and the actually spent value will be left to the miners as a fee.\n     * \\param[in] required Required amount to spend.\n     * \\param[out] coinsToSpend_out Coins which user needs to spend.\n    void UnlockAllCoins();\n    void ListLockedCoins(std::vector<COutPoint>& vOutpts);\n    void ListProTxCoins(std::vector<COutPoint>& vOutpts);\n\n    bool HasMasternode();\n\n    // znode\n    /// Get 1000 FIRO output and keys which can be used for the Znode\n    bool GetZnodeVinAndKeys(CTxIn& txinRet, CPubKey& pubKeyRet, CKey& keyRet, std::string strTxHash = "", std::string strOutputIndex = "");\n    /// Extract txin information and keys from output\n    bool GetVinAndKeysFromOutput(COutput out, CTxIn& txinRet, CPubKey& pubKeyRet, CKey& keyRet);\n\n    CPubKey GetKeyFromKeypath(uint32_t nChange, uint32_t nChild, CKey& secret);\n    /**\n     * keystore implementation\n     * Generate a new key\n     */\n    CPubKey GenerateNewKey(uint32_t nChange=0, bool fWriteChain=true);\n    void DeriveNewChildKey(CKeyMetadata& metadata, CKey& secret);\n    //! Adds a key to the store, and saves it to disk.\n    bool AddKeyPubKey(const CKey& key, const CPubKey &pubkey) override;\n    //! Adds a key to the store, without saving it to disk (used by LoadWallet)\n    bool LoadKey(const CKey& key, const CPubKey &pubkey) { return CCryptoKeyStore::AddKeyPubKey(key, pubkey); }\n    //! Load metadata (used by LoadWallet)\n    bool LoadKeyMetadata(const CTxDestination& pubKey, const CKeyMetadata &metadata);\n\n    bool LoadMinVersion(int nVersion) { AssertLockHeld(cs_wallet); nWalletVersion = nVersion; nWalletMaxVersion = std::max(nWalletMaxVersion, nVersion); return true; }\n    void UpdateTimeFirstKey(int64_t nCreateTime);\n\n    //! Adds an encrypted key to the store, and saves it to disk.\n    bool AddCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret) override;\n    //! Adds an encrypted key to the store, without saving it to disk (used by LoadWallet)\n    bool LoadCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret);\n    bool AddCScript(const CScript& redeemScript) override;\n    bool LoadCScript(const CScript& redeemScript);\n\n    //! Adds a destination data tuple to the store, and saves it to disk\n    bool AddDestData(const CTxDestination &dest, const std::string &key, const std::string &value);\n    //! Erases a destination data tuple in the store and on disk\n    bool EraseDestData(const CTxDestination &dest, const std::string &key);\n    //! Adds a destination data tuple to the store, without saving it to disk\n    bool LoadDestData(const CTxDestination &dest, const std::string &key, const std::string &value);\n    //! Look up a destination data tuple in the store, return true if found false otherwise\n    bool GetDestData(const CTxDestination &dest, const std::string &key, std::string *value) const;\n\n    //! Adds a watch-only address to the store, and saves it to disk.\n    bool AddWatchOnly(const CScript& dest, int64_t nCreateTime);\n    bool RemoveWatchOnly(const CScript &dest) override;\n    //! Adds a watch-only address to the store, without saving it to disk (used by LoadWallet)\n    bool LoadWatchOnly(const CScript &dest);\n\n    //! Holds a timestamp at which point the wallet is scheduled (externally) to be relocked. Caller must arrange for actual relocking to occur via Lock().\n    int64_t nRelockTime;\n\n    bool Unlock(const SecureString& strWalletPassphrase, const bool& fFirstUnlock=false);\n    bool ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, const SecureString& strNewWalletPassphrase);\n    bool EncryptWallet(const SecureString& strWalletPassphrase);\n\n    void GetKeyBirthTimes(std::map<CTxDestination, int64_t> &mapKeyBirth) const;\n\n    /**\n     * Increment the next transaction order id\n     * @return next transaction order id\n     */\n    int64_t IncOrderPosNext(CWalletDB *pwalletdb = NULL);\n    DBErrors ReorderTransactions();\n    bool AccountMove(std::string strFrom, std::string strTo, CAmount nAmount, std::string strComment = "");\n    bool GetAccountPubkey(CPubKey &pubKey, std::string strAccount, bool bForceNew = false);\n\n    void MarkDirty();\n    bool AddToWallet(const CWalletTx& wtxIn, bool fFlushOnClose=true);\n    bool LoadToWallet(const CWalletTx& wtxIn);\n    void SyncTransaction(const CTransaction& tx, const CBlockIndex *pindex, int posInBlock) override;\n    bool AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlockIndex* pIndex, int posInBlock, bool fUpdate);\n    CBlockIndex* ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate = false, bool fRecoverMnemonic = false);\n    void ReacceptWalletTransactions();\n    void ResendWalletTransactions(int64_t nBestBlockTime, CConnman* connman) override;\n    std::vector<uint256> ResendWalletTransactionsBefore(int64_t nTime, CConnman* connman);\n    CAmount GetBalance(bool fExcludeLocked = false) const;\n    std::pair<CAmount, CAmount> GetPrivateBalance() const;\n    std::pair<CAmount, CAmount> GetPrivateBalance(size_t &confirmed, size_t &unconfirmed) const;\n    CAmount GetUnconfirmedBalance() const;\n    CAmount GetImmatureBalance() const;\n    CAmount GetWatchOnlyBalance() const;\n    CAmount GetUnconfirmedWatchOnlyBalance() const;\n    CAmount GetImmatureWatchOnlyBalance() const;\n    CAmount GetLegacyBalance(const isminefilter& filter, int minDepth, const std::string* account, bool fAddLocked = false) const;\n\n    static std::vector<CRecipient> CreateSigmaMintRecipients(\n        std::vector<sigma::PrivateCoin>& coins,\n        std::vector<CHDMint>& vDMints);\n\n    static CRecipient CreateLelantusMintRecipient(\n        lelantus::PrivateCoin& coin,\n        CHDMint& vDMint,\n        bool generate = true);\n\n    static int GetRequiredCoinCountForAmount(\n        const CAmount& required,\n        const std::vector<sigma::CoinDenomination>& denominations);\n\n    static CAmount SelectMintCoinsForAmount(\n        const CAmount& required,\n        const std::vector<sigma::CoinDenomination>& denominations,\n        std::vector<sigma::CoinDenomination>& coinsOut);\n\n    static CAmount SelectSpendCoinsForAmount(\n        const CAmount& required,\n        const std::list<CSigmaEntry>& coinsIn,\n        std::vector<CSigmaEntry>& coinsOut);\n\n    // Returns a list of unspent and verified coins, I.E. coins which are ready\n    // to be spent.\n    std::list<CSigmaEntry> GetAvailableCoins(const CCoinControl *coinControl = NULL, bool includeUnsafe = false, bool forEstimation = false) const;\n\n    std::list<CLelantusEntry> GetAvailableLelantusCoins(const CCoinControl *coinControl = NULL, bool includeUnsafe = false, bool forEstimation = false) const;\n\n    std::vector<unsigned char> EncryptMintAmount(uint64_t amount, const secp_primitives::GroupElement& pubcoin) const;\n\n    bool DecryptMintAmount(const std::vector<unsigned char>& encryptedValue, const secp_primitives::GroupElement& pubcoin, uint64_t& amount) const;\n\n\n    /** \\brief Selects coins to spend, and coins to re-mint based on the required amount to spend, provided by the user. As the lower denomination now is 0.1 firo, user\'s request will be rounded up to the nearest 0.1. This difference between the user\'s requested value, and the actually spent value will be left to the miners as a fee.\n     * \\param[in] required Required amount to spend.\n     * \\param[out] coinsToSpend_out Coins which user needs to spend.\n     * \\param[out] coinsToMint_out Coins which will be re-minted by the user to get the change back.\n     * \\returns true, if it was possible to spend exactly required(rounded up to 0.1 firo) amount using coins we have.\n     */\n    bool GetCoinsToSpend(\n        CAmount required,\n        std::vector<CSigmaEntry>& coinsToSpend_out,\n        std::vector<sigma::CoinDenomination>& coinsToMint_out,\n        std::list<CSigmaEntry>& coins,\n        const size_t coinsLimit = SIZE_MAX,\n        const CAmount amountLimit = MAX_MONEY,\n        const CCoinControl *coinControl = NULL) const;\n\n    bool GetCoinsToJoinSplit(\n            CAmount required,\n            std::vector<CLelantusEntry>& coinsToSpend_out,\n            CAmount& changeToMint,\n            std::list<CLelantusEntry> coins,\n            const size_t coinsToSpendLimit = SIZE_MAX,\n            const CAmount amountToSpendLimit = MAX_MONEY,\n            const CCoinControl *coinControl = NULL) const;\n\n    /**\n     * Insert additional inputs into the transaction by\n     * calling CreateTransaction();\n     */\n    bool FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, bool overrideEstimatedFeeRate, const CFeeRate& specificFeeRate, int& nChangePosInOut, std::string& strFailReason, bool includeWatching, bool lockUnspents, const std::set<int>& setSubtractFeeFromOutputs, bool keepReserveKey = true, const CTxDestination& destChange = CNoDestination());\n\n    /**\n     * Create a new transaction paying the recipients with a set of coins\n     * selected by SelectCoins(); Also create the change output, when needed\n     * @note passing nChangePosInOut as -1 will result in setting a random position\n     */\n    bool CreateTransaction(const std::vector<CRecipient>& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet, int& nChangePosInOut,\n                           std::string& strFailReason, const CCoinControl *coinControl = NULL, bool sign = true, int nExtraPayloadSize = 0, bool fUseInstantSend=false);\n\n    /**\n     * Add Mint and Spend functions\n     */\n    void ListAvailableSigmaMintCoins(std::vector <COutput> &vCoins, bool fOnlyConfirmed) const;\n    void ListAvailableLelantusMintCoins(std::vector<COutput> &vCoins, bool fOnlyConfirmed) const;\n\n    bool CreateMintTransaction(const std::vector<CRecipient>& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet, int& nChangePosInOut,\n                           std::string& strFailReason, const CCoinControl *coinControl = NULL, bool sign = true);\n    bool CreateMintTransaction(CScript pubCoin, int64_t nValue,\n                                       CWalletTx& wtxNew, CReserveKey& reservekey, int64_t& nFeeRet, std::string& strFailReason, const CCoinControl *coinControl=NULL);\n    bool CreateLelantusMintTransactions(CAmount valueToMint, std::vector<std::pair<CWalletTx, CAmount>>& wtxAndFee,\n                                        CAmount& nAllFeeRet, std::vector<CHDMint>& dMints,\n                                        std::list<CReserveKey>& reservekeys, int& nChangePosInOut,\n                                        std::string& strFailReason, const CCoinControl *coinControl, bool autoMintAll = false, bool sign = true);\n\n    CWalletTx CreateSigmaSpendTransaction(\n        const std::vector<CRecipient>& recipients,\n        CAmount& fee,\n        std::vector<CSigmaEntry>& selected,\n        std::vector<CHDMint>& changes,\n        bool& fChangeAddedToFee,\n        const CCoinControl *coinControl = NULL);\n\n    CWalletTx CreateLelantusJoinSplitTransaction(\n        const std::vector<CRecipient>& recipients,\n        CAmount& fee,\n        const std::vector<CAmount>& newMints,\n        std::vector<CLelantusEntry>& spendCoins,\n        std::vector<CSigmaEntry>& sigmaSpendCoins,\n        std::vector<CHDMint>& mintCoins,\n        const CCoinControl *coinControl = NULL,\n        std::function<void(CTxOut & , LelantusJoinSplitBuilder const &)> modifier = nullptr);\n\n    bool CommitSigmaTransaction(CWalletTx& wtxNew, std::vector<CSigmaEntry>& selectedCoins, std::vector<CHDMint>& changes);\n    bool CommitLelantusTransaction(CWalletTx& wtxNew, std::vector<CLelantusEntry>& spendCoins, std::vector<CSigmaEntry>& sigmaSpendCoins, std::vector<CHDMint>& mintCoins);\n    std::string SendMoney(CScript scriptPubKey, int64_t nValue, CWalletTx& wtxNew, bool fAskFee=false);\n    std::string SendMoneyToDestination(const CTxDestination &address, int64_t nValue, CWalletTx& wtxNew, bool fAskFee=false);\n\n    std::string MintAndStoreSigma(\n        const std::vector<CRecipient>& vecSend,\n        const std::vector<sigma::PrivateCoin>& privCoins,\n        std::vector<CHDMint> vDMints,\n        CWalletTx &wtxNew,\n        bool fAskFee=false,\n        const CCoinControl *coinControl = NULL);\n\n    std::string MintAndStoreLelantus(\n            const CAmount& value,\n            std::vector<std::pair<CWalletTx, CAmount>>& wtxAndFee,\n            std::vector<CHDMint>& mints,\n            bool autoMintAll = false,\n            bool fAskFee = false,\n            const CCoinControl *coinControl = NULL);\n\n    std::vector<CSigmaEntry> SpendSigma(const std::vector<CRecipient>& recipients, CWalletTx& result);\n    std::vector<CSigmaEntry> SpendSigma(const std::vector<CRecipient>& recipients, CWalletTx& result, CAmount& fee);\n\n    std::vector<CLelantusEntry> JoinSplitLelantus(const std::vector<CRecipient>& recipients, const std::vector<CAmount>& newMints, CWalletTx& result);\n\n    std::pair<CAmount, unsigned int> EstimateJoinSplitFee(CAmount required, bool subtractFeeFromAmount, std::list<CSigmaEntry> sigmaCoins, std::list<CLelantusEntry> coins, const CCoinControl *coinControl);\n\n    bool GetMint(const uint256& hashSerial, CSigmaEntry& sigmaEntry, bool forEstimation = false) const;\n\n    bool GetMint(const uint256& hashSerial, CLelantusEntry& mint, bool forEstimation = false) const;\n\n    bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey, CConnman* connman, CValidationState& state);\n\n\n    bool CreateCollateralTransaction(CMutableTransaction& txCollateral, std::string& strReason);\n    bool ConvertList(std::vector<CTxIn> vecTxIn, std::vector<CAmount>& vecAmounts);\n\n    void ListAccountCreditDebit(const std::string& strAccount, std::list<CAccountingEntry>& entries);\n    bool AddAccountingEntry(const CAccountingEntry&);\n    bool AddAccountingEntry(const CAccountingEntry&, CWalletDB *pwalletdb);\n    template <typename ContainerType>\n    bool DummySignTx(CMutableTransaction &txNew, const ContainerType &coins);\n\n    static CFeeRate minTxFee;\n    static CFeeRate fallbackFee;\n    /**\n     * Estimate the minimum fee considering user set parameters\n     * and the required fee\n     */\n    static CAmount GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool);\n    /**\n     * Estimate the minimum fee considering required fee and targetFee or if 0\n     * then fee estimation for nConfirmTarget\n     */\n    static CAmount GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool, CAmount targetFee);\n    /**\n     * Return the minimum required fee taking into account the\n     * floating relay fee and user set minimum transaction fee\n     */\n    static CAmount GetRequiredFee(unsigned int nTxBytes);\n\n    bool NewKeyPool();\n    bool TopUpKeyPool(unsigned int kpSize = 0);\n    void ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& keypool);\n    void KeepKey(int64_t nIndex);\n    void ReturnKey(int64_t nIndex, const CPubKey& pubkey);\n    bool GetKeyFromPool(CPubKey &key);\n    int64_t GetOldestKeyPoolTime();\n    /**\n     * Marks all keys in the keypool up to and including reserve_key as used.\n     */\n    void MarkReserveKeysAsUsed(int64_t keypool_id);\n    const std::map<CKeyID, int64_t>& GetAllReserveKeys() const { return m_pool_key_to_index; }\n\n    std::set< std::set<CTxDestination> > GetAddressGroupings();\n    std::map<CTxDestination, CAmount> GetAddressBalances();\n\n    std::set<CTxDestination> GetAccountAddresses(const std::string& strAccount) const;\n\n    isminetype IsMine(const CTxIn& txin, const CTransaction& tx) const;\n    /**\n     * Returns amount of debit if the input matches the\n     * filter, otherwise returns 0\n     */\n    CAmount GetDebit(const CTxIn& txin, const CTransaction&tx, const isminefilter& filter) const;\n    isminetype IsMine(const CTxOut& txout) const;\n    CAmount GetCredit(const CTxOut& txout, const isminefilter& filter) const;\n    bool IsChange(const uint256& tx, const CTxOut& txout) const;\n    CAmount GetChange(const uint256& tx, const CTxOut& txout) const;\n    bool IsMine(const CTransaction& tx) const;\n    /** should probably be renamed to IsRelevantToMe */\n    bool IsFromMe(const CTransaction& tx) const;\n    CAmount GetDebit(const CTransaction& tx, const isminefilter& filter) const;\n    /** Returns whether all of the inputs match the filter */\n    bool IsAllFromMe(const CTransaction& tx, const isminefilter& filter) const;\n    CAmount GetCredit(const CTransaction& tx, const isminefilter& filter) const;\n    CAmount GetChange(const CTransaction& tx) const;\n    void SetBestChain(const CBlockLocator& loc) override;\n\n    DBErrors LoadWallet(bool& fFirstRunRet);\n    void AutoLockMasternodeCollaterals();\n    DBErrors ZapWalletTx(std::vector<CWalletTx>& vWtx);\n    DBErrors ZapSelectTx(std::vector<uint256>& vHashIn, std::vector<uint256>& vHashOut);\n\n    // Remove all CSigmaEntry and CHDMint objects from WalletDB.\n    DBErrors ZapSigmaMints();\n    // Remove all Lelantus HDMint objects from WalletDB\n    DBErrors ZapLelantusMints();\n\n    bool SetAddressBook(const CTxDestination& address, const std::string& strName, const std::string& purpose);\n\n    bool DelAddressBook(const CTxDestination& address);\n\n    bool UpdatedTransaction(const uint256 &hashTx) override;\n    const std::string& GetAccountName(const CScript& scriptPubKey) const;\n\n    void Inventory(const uint256 &hash) override\n    {\n        {\n            LOCK(cs_wallet);\n            std::map<uint256, int>::iterator mi = mapRequestCount.find(hash);\n            if (mi != mapRequestCount.end())\n                (*mi).second++;\n        }\n    }\n\n    void GetScriptForMining(boost::shared_ptr<CReserveScript> &script) override;\n    void ResetRequestCount(const uint256 &hash) override\n    {\n        LOCK(cs_wallet);\n        mapRequestCount[hash] = 0;\n    };\n\n    unsigned int GetKeyPoolSize()\n    {\n        AssertLockHeld(cs_wallet); // setKeyPool\n        return setKeyPool.size();\n    }\n\n    bool SetDefaultKey(const CPubKey &vchPubKey);\n\n    //! signify that a particular wallet feature is now used. this may change nWalletVersion and nWalletMaxVersion if those are lower\n    bool SetMinVersion(enum WalletFeature, CWalletDB* pwalletdbIn = NULL, bool fExplicit = false);\n\n    //! change which version we\'re allowed to upgrade to (note that this does not immediately imply upgrading to that format)\n    bool SetMaxVersion(int nVersion);\n\n    //! get the current wallet format (the oldest client version guaranteed to understand this wallet)\n    int GetVersion() { LOCK(cs_wallet); return nWalletVersion; }\n\n    //! Get wallet transactions that conflict with given transaction (spend same outputs)\n    std::set<uint256> GetConflicts(const uint256& txid) const;\n\n    //! Check if a given transaction has any of its outputs spent by another transaction in the wallet\n    bool HasWalletSpend(const uint256& txid) const;\n\n    //! Flush wallet (bitdb flush)\n    void Flush(bool shutdown=false);\n\n    //! Verify the wallet database and perform salvage if required\n    static bool Verify();\n\n    /**\n     * Address book entry changed.\n     * @note called with lock cs_wallet held.\n     */\n    boost::signals2::signal<void (CWallet *wallet, const CTxDestination\n            &address, const std::string &label, bool isMine,\n            const std::string &purpose,\n            ChangeType status)> NotifyAddressBookChanged;\n\n    /**\n     * Wallet transaction added, removed or updated.\n     * @note called with lock cs_wallet held.\n     */\n    boost::signals2::signal<void (CWallet *wallet, const uint256 &hashTx,\n            ChangeType status)> NotifyTransactionChanged;\n    /**\n     * sigma/lelantus entry changed.\n     * @note called with lock cs_wallet held.\n     */\n    boost::signals2::signal<void (CWallet *wallet, const std::string &pubCoin, const std::string &isUsed, ChangeType status)> NotifyZerocoinChanged;\n\n\n    /** Show progress e.g. for rescan */\n    boost::signals2::signal<void (const std::string &title, int nProgress)> ShowProgress;\n\n    /** Watch-only address added */\n    boost::signals2::signal<void (bool fHaveWatchOnly)> NotifyWatchonlyChanged;\n\n    /** Payment code added */\n    boost::signals2::signal<void (bip47::CPaymentCodeDescription)> NotifyPcodeCreated;\n\n    /** Payment code labeled */\n    boost::signals2::signal<void (std::string pcode, std::string label, bool removed)> NotifyPcodeLabeled;\n\n    /** Unlock required (for example for adding a privkey to the wallet),  */\n    boost::signals2::signal<void (int receiverAccountNum, CBlockIndex* pBlockIndex)> NotifyBip47KeysChanged;\n\n    /** IS-lock received */\n    boost::signals2::signal<void ()> NotifyISLockReceived;\n\n    /** ChainLock received */\n    boost::signals2::signal<void (int height)> NotifyChainLockReceived;\n\n    /** Inquire whether this wallet broadcasts transactions. */\n    bool GetBroadcastTransactions() const { return fBroadcastTransactions; }\n    /** Set whether this wallet broadcasts transactions. */\n    void SetBroadcastTransactions(bool broadcast) { fBroadcastTransactions = broadcast; }\n\n    /* Mark a transaction (and it in-wallet descendants) as abandoned so its inputs may be respent. */\n    bool AbandonTransaction(const uint256& hashTx);\n\n    /** Mark a transaction as replaced by another transaction (e.g., BIP 125). */\n    bool MarkReplaced(const uint256& originalHash, const uint256& newHash);\n\n    /* Returns the wallets help message */\n    static std::string GetWalletHelpString(bool showDebug);\n\n    /* Initializes the wallet, returns a new CWallet instance or a null pointer in case of an error */\n    static CWallet* CreateWalletFromFile(const std::string walletFile);\n    static bool InitLoadWallet();\n\n    /**\n     * Wallet post-init setup\n     * Gives the wallet a chance to register repetitive tasks and complete post-init tasks\n     */\n    void postInitProcess(boost::thread_group& threadGroup);\n\n    /* Wallets parameter interaction */\n    static bool ParameterInteraction();\n\n    bool BackupWallet(const std::string& strDest);\n\n    /* Set the HD chain model (chain child index counters) */\n    bool SetHDChain(const CHDChain& chain, bool memonly, bool& upgradeChain, bool genNewKeyPool = true);\n    bool SetHDChain(const CHDChain& chain, bool memonly) { bool upgradeChain = DEFAULT_UPGRADE_CHAIN; return SetHDChain(chain, memonly, upgradeChain); }\n    const CHDChain& GetHDChain() { return hdChain; }\n\n    bool SetMnemonicContainer(const MnemonicContainer& mnContainer, bool memonly);\n    const MnemonicContainer& GetMnemonicContainer() { return mnemonicContainer; }\n\n    bool EncryptMnemonicContainer(const CKeyingMaterial& vMasterKeyIn);\n    bool DecryptMnemonicContainer(MnemonicContainer& mnContainer);\n\n    void GenerateNewMnemonic();\n\n    /* Returns true if HD is enabled */\n    bool IsHDEnabled();\n\n    /* Generates a new HD master key (will not be activated) */\n    CPubKey GenerateNewHDMasterKey();\n\n    /* Set the current HD master key (will reset the chain child index counters) */\n    bool SetHDMasterKey(const CPubKey& key, const int cHDChainVersion=CHDChain().CURRENT_VERSION);\n\n    /**************************************************************************/\n    /* bip47 */\n    /* Generates and strores a new payment code for receiving*/\n    bip47::CPaymentCode GeneratePcode(std::string const & label);\n\n    /*Prepares and sends a notification tx using Lelantus facilities*/\n    CWalletTx PrepareAndSendNotificationTx(bip47::CPaymentCode const & theirPcode);\n\n    /* Lists all receiving pcodes as tuples of (pcode, label, notification address) */\n    std::vector<bip47::CPaymentCodeDescription> ListPcodes();\n\n    /* Creates a payment channel for their payment code. */\n    bip47::CPaymentChannel & SetupPchannel(bip47::CPaymentCode const & theirPcode);\n\n    /* Stores the notification tx id into the wallet database */\n    void SetNotificationTxId(bip47::CPaymentCode const & theirPcode, uint256 const & txid);\n\n    /* Returns next unused address for their payment code. Throws if no payment channel was setup */\n    CBitcoinAddress GetTheirNextAddress(bip47::CPaymentCode const & theirPcode) const;\n\n    /* Returns and stores a next unused address for their payment code. Throws if no payment channel was setup */\n    CBitcoinAddress GenerateTheirNextAddress(bip47::CPaymentCode const & theirPcode);\n\n    /*Loads previously stored bip47 accounts */\n    void LoadBip47Wallet();\n\n    std::shared_ptr<bip47::CWallet const>  GetBip47Wallet() const;\n\n    boost::optional<bip47::CPaymentCodeDescription> FindPcode(bip47::CPaymentCode const & pcode) const;\n    boost::optional<bip47::CPaymentCodeDescription> FindPcode(CBitcoinAddress const & address) const;\n\n    /*Marks address as used for a receiving bip47 account. Returns the account if found*/\n    bip47::CAccountReceiver const * AddressUsed(CBitcoinAddress const & address);\n\n    /*Checks if this is a BIP47 transaction and handles it. May send an unlock request if wallet is locked.*/\n    void HandleBip47Transaction(CWalletTx const & wtx);\n\n    /*Attaches a new label to a sending payment code.*/\n    void LabelSendingPcode(bip47::CPaymentCode const & pcode, std::string const & label, bool remove = false);\n    std::string GetSendingPcodeLabel(bip47::CPaymentCode const & pcode) const;\n\n    /*Relabels an existing receiving payment code*/\n    void LabelReceivingPcode(bip47::CPaymentCode const & pcode, std::string const & label);\n\n    /*Sets used address number for a sending or receiving payment channel*/\n    size_t SetUsedAddressNumber(bip47::CPaymentCode const & pcode, size_t number);\n\n    void NotifyTransactionLock(const CTransaction &tx) override;\n    void NotifyChainLock(const CBlockIndex* pindexChainLock) override;\n};\n\n/** A key allocated from the key pool. */\nclass CReserveKey : public CReserveScript\n{\nprotected:\n    CWallet* pwallet;\n    int64_t nIndex;\n    CPubKey vchPubKey;\npublic:\n    CReserveKey(CWallet* pwalletIn)\n    {\n        nIndex = -1;\n        pwallet = pwalletIn;\n    }\n\n    ~CReserveKey()\n    {\n        ReturnKey();\n    }\n\n    void ReturnKey();\n    bool GetReservedKey(CPubKey &pubkey);\n    void KeepKey();\n    void KeepScript() { KeepKey(); }\n};\n\n\n/**\n * Account information.\n * Stored in wallet with key "acc"+string account name.\n */\nclass CAccount\n{\npublic:\n    CPubKey vchPubKey;\n\n    CAccount()\n    {\n        SetNull();\n    }\n\n    void SetNull()\n    {\n        vchPubKey = CPubKey();\n    }\n\n    ADD_SERIALIZE_METHODS;\n\n    template <typename Stream, typename Operation>\n    inline void SerializationOp(Stream& s, Operation ser_action) {\n        int nVersion = s.GetVersion();\n        if (!(s.GetType() & SER_GETHASH))\n            READWRITE(nVersion);\n        READWRITE(vchPubKey);\n    }\n};\n\nbool CompSigmaHeight(const CSigmaEntry& a, const CSigmaEntry& b);\nbool CompSigmaID(const CSigmaEntry& a, const CSigmaEntry& b);\n\n// Helper for producing a bunch of max-sized low-S signatures (eg 72 bytes)\n// ContainerType is meant to hold pair<CWalletTx *, int>, and be iterable\n// so that each entry corresponds to each vIn, in order.\ntemplate <typename ContainerType>\nbool CWallet::DummySignTx(CMutableTransaction &txNew, const ContainerType &coins)\n{\n    // Fill in dummy signatures for fee calculation.\n    int nIn = 0;\n    for (const auto& coin : coins)\n    {\n        const CScript& scriptPubKey = coin.first->tx->vout[coin.second].scriptPubKey;\n        SignatureData sigdata;\n\n        if (!ProduceSignature(DummySignatureCreator(this), scriptPubKey, sigdata))\n        {\n            return false;\n        } else {\n            UpdateTransaction(txNew, nIn, sigdata);\n        }\n\n        nIn++;\n    }\n    return true;\n}\n\nCWalletTx PrepareAndSendNotificationTx(CWallet* pwallet, bip47::CPaymentCode const & theirPcode);\n\n#endif // BITCOIN_WALLET_WALLET_H\n', 'message': 'Applied review comments\n', 'author_name': 'martun', 'lang': 'h'}