text: // 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 VITALCOIN_COINS_H
  #define VITALCOIN_COINS_H
  
  #include "compressor.h"
  #include "core_memusage.h"
  #include "hash.h"
  #include "memusage.h"
  #include "primitives/transaction.h"
  #include "serialize.h"
  #include "uint256.h"
  
  #include <assert.h>
  #include <stdint.h>
  
  #include <unordered_map>
  
  /**
   * A UTXO entry.
   *
   * Serialized format:
   * - VARINT((coinbase ? 1 : 0) | (height << 1))
   * - the non-spent CTxOut (via CTxOutCompressor)
   */
  class Coin {
  public:
    //! unspent transaction output
    CTxOut out;
  
    //! whether containing transaction was a coinbase
    unsigned int fCoinBase : 1;
  
    //! at which height this containing transaction was included in the active
    //! block chain
    uint32_t nHeight : 31;
  
    //! construct a Coin from a CTxOut and height/coinbase information.
    Coin(CTxOut &&outIn, int nHeightIn, bool fCoinBaseIn)
        : out(std::move(outIn)), fCoinBase(fCoinBaseIn), nHeight(nHeightIn) {}
    Coin(const CTxOut &outIn, int nHeightIn, bool fCoinBaseIn)
        : out(outIn), fCoinBase(fCoinBaseIn), nHeight(nHeightIn) {}
  
    void Clear() {
      out.SetNull();
      fCoinBase = false;
      nHeight = 0;
    }
  
    //! empty constructor
    Coin() : fCoinBase(false), nHeight(0) {}
  
    bool IsCoinBase() const { return fCoinBase; }
  
    template <typename Stream> void Serialize(Stream &s) const {
      assert(!IsSpent());
      uint32_t code = nHeight * 2 + fCoinBase;
      ::Serialize(s, VARINT(code));
      ::Serialize(s, CTxOutCompressor(REF(out)));
    }
  
    template <typename Stream> void Unserialize(Stream &s) {
      uint32_t code = 0;
      ::Unserialize(s, VARINT(code));
      nHeight = code >> 1;
      fCoinBase = code & 1;
      ::Unserialize(s, REF(CTxOutCompressor(out)));
    }
  
    bool IsSpent() const { return out.IsNull(); }
  
    size_t DynamicMemoryUsage() const {
      return memusage::DynamicUsage(out.scriptPubKey);
    }
  };
  
  class SaltedOutpointHasher {
  private:
    /** Salt */
    const uint64_t k0, k1;
  
  public:
    SaltedOutpointHasher();
  
    /**
     * This *must* return size_t. With Boost 1.46 on 32-bit systems the
     * unordered_map will behave unpredictably if the custom hasher returns a
     * uint64_t, resulting in failures when syncing the chain (#4634).
     */
    size_t operator()(const COutPoint &id) const {
      return SipHashUint256Extra(k0, k1, id.hash, id.n);
    }
  };
  
  struct CCoinsCacheEntry {
    Coin coin; // The actual cached data.
    unsigned char flags;
  
    enum Flags {
      DIRTY = (1 << 0), // This cache entry is potentially different from the
                        // version in the parent view.
      FRESH =
          (1 << 1), // The parent view does not have this entry (or it is pruned).
      /* Note that FRESH is a performance optimization with which we can
       * erase coins that are fully spent if we know we do not need to
       * flush the changes to the parent cache.  It is always safe to
       * not mark FRESH if that condition is not guaranteed.
       */
    };
  
    CCoinsCacheEntry() : flags(0) {}
    explicit CCoinsCacheEntry(Coin &&coin_) : coin(std::move(coin_)), flags(0) {}
  };
  
  typedef std::unordered_map<COutPoint, CCoinsCacheEntry, SaltedOutpointHasher>
      CCoinsMap;
  
  /** Cursor for iterating over CoinsView state */
  class CCoinsViewCursor {
  public:
    CCoinsViewCursor(const uint256 &hashBlockIn) : hashBlock(hashBlockIn) {}
    virtual ~CCoinsViewCursor() {}
  
    virtual bool GetKey(COutPoint &key) const = 0;
    virtual bool GetValue(Coin &coin) const = 0;
    virtual unsigned int GetValueSize() const = 0;
  
    virtual bool Valid() const = 0;
    virtual void Next() = 0;
  
    //! Get best block at the time this cursor was created
    const uint256 &GetBestBlock() const { return hashBlock; }
  
  private:
    uint256 hashBlock;
  };
  
  /** Abstract view on the open txout dataset. */
  class CCoinsView {
  public:
    /** Retrieve the Coin (unspent transaction output) for a given outpoint.
     *  Returns true only when an unspent coin was found, which is returned in
     * coin.
     *  When false is returned, coin's value is unspecified.
     */
    virtual bool GetCoin(const COutPoint &outpoint, Coin &coin) const;
  
    //! Just check whether a given outpoint is unspent.
    virtual bool HaveCoin(const COutPoint &outpoint) const;
  
    //! Retrieve the block hash whose state this CCoinsView currently represents
    virtual uint256 GetBestBlock() const;
  
    //! Retrieve the range of blocks that may have been only partially written.
    //! If the database is in a consistent state, the result is the empty vector.
    //! Otherwise, a two-element vector is returned consisting of the new and
    //! the old block hash, in that order.
    virtual std::vector<uint256> GetHeadBlocks() const;
  
    //! Do a bulk modification (multiple Coin changes + BestBlock change).
    //! The passed mapCoins can be modified.
    virtual bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock);
  
    //! Get a cursor to iterate over the whole state
    virtual CCoinsViewCursor *Cursor() const;
  
    //! As we use CCoinsViews polymorphically, have a virtual destructor
    virtual ~CCoinsView() {}
  
    //! Estimate database size (0 if not implemented)
    virtual size_t EstimateSize() const { return 0; }
  };
  
  /** CCoinsView backed by another CCoinsView */
  class CCoinsViewBacked : public CCoinsView {
  protected:
    CCoinsView *base;
  
  public:
    CCoinsViewBacked(CCoinsView *viewIn);
    bool GetCoin(const COutPoint &outpoint, Coin &coin) const override;
    bool HaveCoin(const COutPoint &outpoint) const override;
    uint256 GetBestBlock() const override;
    std::vector<uint256> GetHeadBlocks() const override;
    void SetBackend(CCoinsView &viewIn);
    bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) override;
    CCoinsViewCursor *Cursor() const override;
    size_t EstimateSize() const override;
  };
  
  /** CCoinsView that adds a memory cache for transactions to another CCoinsView
   */
  class CCoinsViewCache : public CCoinsViewBacked {
  protected:
    /**
     * Make mutable so that we can "fill the cache" even from Get-methods
     * declared as "const".
     */
    mutable uint256 hashBlock;
    mutable CCoinsMap cacheCoins;
  
    /* Cached dynamic memory usage for the inner Coin objects. */
    mutable size_t cachedCoinsUsage;
  
  public:
    CCoinsViewCache(CCoinsView *baseIn);
  
    // Standard CCoinsView methods
    bool GetCoin(const COutPoint &outpoint, Coin &coin) const override;
    bool HaveCoin(const COutPoint &outpoint) const override;
    uint256 GetBestBlock() const override;
    void SetBestBlock(const uint256 &hashBlock);
    bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) override;
    CCoinsViewCursor *Cursor() const override {
      throw std::logic_error("CCoinsViewCache cursor iteration not supported.");
    }
  
    /**
     * Check if we have the given utxo already loaded in this cache.
     * The semantics are the same as HaveCoin(), but no calls to
     * the backing CCoinsView are made.
     */
    bool HaveCoinInCache(const COutPoint &outpoint) const;
  
    /**
     * Return a reference to Coin in the cache, or a pruned one if not found. This
     * is
     * more efficient than GetCoin.
     *
     * Generally, do not hold the reference returned for more than a short scope.
     * While the current implementation allows for modifications to the contents
     * of the cache while holding the reference, this behavior should not be
     * relied
     * on! To be safe, best to not hold the returned reference through any other
     * calls to this cache.
     */
    const Coin &AccessCoin(const COutPoint &output) const;
  
    /**
     * Add a coin. Set potential_overwrite to true if a non-pruned version may
     * already exist.
     */
    void AddCoin(const COutPoint &outpoint, Coin &&coin,
                 bool potential_overwrite);
  
    /**
     * Spend a coin. Pass moveto in order to get the deleted data.
     * If no unspent output exists for the passed outpoint, this call
     * has no effect.
     */
    bool SpendCoin(const COutPoint &outpoint, Coin *moveto = nullptr);
  
    /**
     * Push the modifications applied to this cache to its base.
     * Failure to call this method before destruction will cause the changes to be
     * forgotten.
     * If false is returned, the state of this cache (and its backing view) will
     * be undefined.
     */
    bool Flush();
  
    /**
     * Removes the UTXO with the given outpoint from the cache, if it is
     * not modified.
     */
    void Uncache(const COutPoint &outpoint);
  
    //! Calculate the size of the cache (in number of transaction outputs)
    unsigned int GetCacheSize() const;
  
    //! Calculate the size of the cache (in bytes)
    size_t DynamicMemoryUsage() const;
  
    /**
     * Amount of vitalcoins coming in to a transaction
     * Note that lightweight clients may not know anything besides the hash of
     * previous transactions,
     * so may not be able to calculate this.
     *
     * @param[in] tx	transaction for which we are checking input total
     * @return	Sum of value of all inputs (scriptSigs)
     */
    CAmount GetValueIn(const CTransaction &tx) const;
  
    //! Check whether all prevouts of the transaction are present in the UTXO set
    //! represented by this view
    bool HaveInputs(const CTransaction &tx) const;
  
  private:
    CCoinsMap::iterator FetchCoin(const COutPoint &outpoint) const;
  
    /**
     * By making the copy constructor private, we prevent accidentally using it
     * when one intends to create a cache on top of a base cache.
     */
    CCoinsViewCache(const CCoinsViewCache &);
  };
  
  //! Utility function to add all of a transaction's outputs to a cache.
  // When check is false, this assumes that overwrites are only possible for
  // coinbase transactions.
  // When check is true, the underlying view may be queried to determine whether
  // an addition is
  // an overwrite.
  // TODO: pass in a boolean to limit these possible overwrites to known
  // (pre-BIP34) cases.
  void AddCoins(CCoinsViewCache &cache, const CTransaction &tx, int nHeight,
                bool check = false);
  
  //! Utility function to find any unspent output with a given txid.
  // This function can be quite expensive because in the event of a transaction
  // which is not found in the cache, it can cause up to MAX_OUTPUTS_PER_BLOCK
  // lookups to database, so it should be used with care.
  const Coin &AccessByTxid(const CCoinsViewCache &cache, const uint256 &txid);
  
  #endif // VITALCOIN_COINS_H
  