LCOV - code coverage report
Current view: top level - src - coins.h (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 48 49 98.0 %
Date: 2025-02-23 09:33:43 Functions: 2 5 40.0 %

          Line data    Source code
       1             : // Copyright (c) 2009-2010 Satoshi Nakamoto
       2             : // Copyright (c) 2009-2014 The Bitcoin developers
       3             : // Copyright (c) 2016-2021 The PIVX Core developers
       4             : // Distributed under the MIT software license, see the accompanying
       5             : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
       6             : 
       7             : #ifndef PIVX_COINS_H
       8             : #define PIVX_COINS_H
       9             : 
      10             : #include "compressor.h"
      11             : #include "consensus/consensus.h" // can be removed once policy/ established
      12             : #include "crypto/siphash.h"
      13             : #include "memusage.h"
      14             : #include "sapling/incrementalmerkletree.h"
      15             : #include "script/standard.h"
      16             : #include "serialize.h"
      17             : #include "uint256.h"
      18             : 
      19             : #include <assert.h>
      20             : #include <stdint.h>
      21             : 
      22             : #include <unordered_map>
      23             : 
      24             : /**
      25             :  * A UTXO entry.
      26             :  *
      27             :  * Serialized format:
      28             :  * - VARINT((coinbase ? 2 : 0) | (coinstake ? 1 : 0) | (height << 2))
      29             :  * - the non-spent CTxOut (via CTxOutCompressor)
      30             :  */
      31    74729637 : class Coin
      32             : {
      33             : public:
      34             :     //! whether the containing transaction was a coinbase
      35             :     bool fCoinBase;
      36             : 
      37             :     //! whether the containing transaction was a coinstake
      38             :     bool fCoinStake;
      39             : 
      40             :     //! unspent transaction output
      41             :     CTxOut out;
      42             : 
      43             :     //! at which height the containing transaction was included in the active block chain
      44             :     uint32_t nHeight;
      45             : 
      46             :     //! construct a Coin from a CTxOut and height/coinbase properties.
      47          27 :     Coin(CTxOut&& outIn, int nHeightIn, bool fCoinBaseIn, bool fCoinStakeIn) : fCoinBase(fCoinBaseIn), fCoinStake(fCoinStakeIn), out(std::move(outIn)), nHeight(nHeightIn) {}
      48     7146884 :     Coin(const CTxOut& outIn, int nHeightIn, bool fCoinBaseIn, bool fCoinStakeIn) : fCoinBase(fCoinBaseIn), fCoinStake(fCoinStakeIn), out(outIn), nHeight(nHeightIn) {}
      49             : 
      50     5330123 :     void Clear() {
      51     5330123 :         out.SetNull();
      52     5330123 :         fCoinBase = false;
      53     5330123 :         fCoinStake = false;
      54     5330123 :         nHeight = 0;
      55     5279879 :     }
      56             : 
      57             :     //! empty constructor
      58    46698310 :     Coin() : fCoinBase(false), fCoinStake(false), nHeight(0) { }
      59             : 
      60     6045025 :     bool IsCoinBase() const {
      61     6045025 :         return fCoinBase;
      62             :     }
      63             : 
      64     6021514 :     bool IsCoinStake() const {
      65     6021514 :         return fCoinStake;
      66             :     }
      67             : 
      68             :     template<typename Stream>
      69      695135 :     void Serialize(Stream &s) const {
      70      695135 :         assert(!IsSpent());
      71     2038173 :         uint32_t code = nHeight * 4 + (fCoinBase ? 2 : 0) + (fCoinStake ? 1 : 0);
      72      695135 :         ::Serialize(s, VARINT(code));
      73      695135 :         ::Serialize(s, Using<TxOutCompression>(out));
      74      695135 :     }
      75             : 
      76             :     template<typename Stream>
      77     6893133 :     void Unserialize(Stream &s) {
      78     6893133 :         uint32_t code = 0;
      79     6893133 :         ::Unserialize(s, VARINT(code));
      80     6893133 :         nHeight = code >> 2;
      81     6893133 :         fCoinBase = code & 2;
      82     6893133 :         fCoinStake = code & 1;
      83     6893133 :         ::Unserialize(s, Using<TxOutCompression>(out));
      84     6893131 :     }
      85             : 
      86    58466135 :     bool IsSpent() const {
      87    57772388 :         return out.IsNull();
      88             :     }
      89             : 
      90     1035872 :     size_t DynamicMemoryUsage() const {
      91    21732663 :         return memusage::DynamicUsage(out.scriptPubKey);
      92             :     }
      93             : };
      94             : 
      95             : class SaltedOutpointHasher
      96             : {
      97             : private:
      98             :     /** Salt */
      99             :     const uint64_t k0, k1;
     100             : 
     101             : public:
     102             :     SaltedOutpointHasher();
     103             : 
     104             :     /**
     105             :      * This *must* return size_t. With Boost 1.46 on 32-bit systems the
     106             :      * unordered_map will behave unpredictably if the custom hasher returns a
     107             :      * uint64_t, resulting in failures when syncing the chain (#4634).
     108             :      */
     109    76617192 :     size_t operator()(const COutPoint& id) const {
     110    76617192 :         return SipHashUint256Extra(k0, k1, id.hash, id.n);
     111             :     }
     112             : };
     113             : 
     114             : // Used on Sapling nullifiers, anchor maps and txmempool::mapTx: sorted by txid
     115             : class SaltedIdHasher
     116             : {
     117             : private:
     118             :     /** Salt */
     119             :     const uint64_t k0, k1;
     120             : 
     121             : public:
     122             :     SaltedIdHasher();
     123             : 
     124             :     /**
     125             :      * This *must* return size_t. With Boost 1.46 on 32-bit systems the
     126             :      * unordered_map will behave unpredictably if the custom hasher returns a
     127             :      * uint64_t, resulting in failures when syncing the chain (#4634).
     128             :      */
     129    20721656 :     size_t operator()(const uint256& txid) const {
     130    20721656 :         return SipHashUint256(k0, k1, txid);
     131             :     }
     132             : };
     133             : 
     134    15062562 : struct CCoinsCacheEntry {
     135             :     Coin coin; // The actual cached data.
     136             :     unsigned char flags;
     137             : 
     138             :     enum Flags {
     139             :         DIRTY = (1 << 0), // This cache entry is potentially different from the version in the parent view.
     140             :         FRESH = (1 << 1), // The parent view does not have this entry (or it is pruned).
     141             :     };
     142             : 
     143     8115984 :     CCoinsCacheEntry() : flags(0) {}
     144     6825780 :     explicit CCoinsCacheEntry(Coin&& coin_) : coin(std::move(coin_)), flags(0) {}
     145             : };
     146             : 
     147             : // Sapling
     148             : 
     149      287347 : struct CAnchorsSaplingCacheEntry
     150             : {
     151             :     bool entered; // This will be false if the anchor is removed from the cache
     152             :     SaplingMerkleTree tree; // The tree itself
     153             :     unsigned char flags;
     154             : 
     155             :     enum Flags {
     156             :         DIRTY = (1 << 0), // This cache entry is potentially different from the version in the parent view.
     157             :     };
     158             : 
     159       57383 :     CAnchorsSaplingCacheEntry() : entered(false), flags(0) {}
     160             : };
     161             : 
     162             : struct CNullifiersCacheEntry
     163             : {
     164             :     bool entered; // If the nullifier is spent or not
     165             :     unsigned char flags;
     166             : 
     167             :     enum Flags {
     168             :         DIRTY = (1 << 0), // This cache entry is potentially different from the version in the parent view.
     169             :     };
     170             : 
     171         939 :     CNullifiersCacheEntry() : entered(false), flags(0) {}
     172             : };
     173             : 
     174             : typedef std::unordered_map<uint256, CAnchorsSaplingCacheEntry, SaltedIdHasher> CAnchorsSaplingMap;
     175             : typedef std::unordered_map<uint256, CNullifiersCacheEntry, SaltedIdHasher> CNullifiersMap;
     176             : 
     177             : typedef std::unordered_map<COutPoint, CCoinsCacheEntry, SaltedOutpointHasher> CCoinsMap;
     178             : 
     179             : /** Cursor for iterating over CoinsView state */
     180             : class CCoinsViewCursor
     181             : {
     182             : public:
     183         518 :     CCoinsViewCursor(const uint256 &hashBlockIn): hashBlock(hashBlockIn) {}
     184         518 :     virtual ~CCoinsViewCursor() {}
     185             : 
     186             :     virtual bool GetKey(COutPoint& key) const = 0;
     187             :     virtual bool GetValue(Coin& coin) const = 0;
     188             :     virtual unsigned int GetValueSize() const = 0;
     189             : 
     190             :     virtual bool Valid() const = 0;
     191             :     virtual void Next() = 0;
     192             : 
     193             :     //! Get best block at the time this cursor was created
     194          49 :     const uint256 &GetBestBlock() const { return hashBlock; }
     195             : private:
     196             :     uint256 hashBlock;
     197             : };
     198             : 
     199             : /** Abstract view on the open txout dataset. */
     200      669772 : class CCoinsView
     201             : {
     202             : public:
     203             :     //! Retrieve the Coin (unspent transaction output) for a given outpoint.
     204             :     virtual bool GetCoin(const COutPoint& outpoint, Coin& coin) const;
     205             : 
     206             :     //! Just check whether we have data for a given outpoint.
     207             :     //! This may (but cannot always) return true for spent outputs.
     208             :     virtual bool HaveCoin(const COutPoint& outpoint) const;
     209             : 
     210             :     //! Retrieve the block hash whose state this CCoinsView currently represents
     211             :     virtual uint256 GetBestBlock() const;
     212             : 
     213             :     //! Retrieve the range of blocks that may have been only partially written.
     214             :     //! If the database is in a consistent state, the result is the empty vector.
     215             :     //! Otherwise, a two-element vector is returned consisting of the new and
     216             :     //! the old block hash, in that order.
     217             :     virtual std::vector<uint256> GetHeadBlocks() const;
     218             : 
     219             :     //! Do a bulk modification (multiple Coin changes + BestBlock change).
     220             :     //! The passed mapCoins can be modified.
     221             :     virtual bool BatchWrite(CCoinsMap& mapCoins,
     222             :                             const uint256& hashBlock,
     223             :                             const uint256& hashSaplingAnchor,
     224             :                             CAnchorsSaplingMap& mapSaplingAnchors,
     225             :                             CNullifiersMap& mapSaplingNullifiers);
     226             : 
     227             :     //! Get a cursor to iterate over the whole state
     228             :     virtual CCoinsViewCursor* Cursor() const;
     229             : 
     230             :     //! As we use CCoinsViews polymorphically, have a virtual destructor
     231      281001 :     virtual ~CCoinsView() {}
     232             : 
     233             :     //! Estimate database size (0 if not implemented)
     234           0 :     virtual size_t EstimateSize() const { return 0; }
     235             : 
     236             :     // Sapling
     237             :     //! Retrieve the tree (Sapling) at a particular anchored root in the chain
     238             :     virtual bool GetSaplingAnchorAt(const uint256 &rt, SaplingMerkleTree &tree) const;
     239             : 
     240             :     //! Determine whether a nullifier is spent or not
     241             :     virtual bool GetNullifier(const uint256 &nullifier) const;
     242             : 
     243             :     //! Get the current "tip" or the latest anchored tree root in the chain
     244             :     virtual uint256 GetBestAnchor() const;
     245             : };
     246             : 
     247             : 
     248             : /** CCoinsView backed by another CCoinsView */
     249      280826 : class CCoinsViewBacked : public CCoinsView
     250             : {
     251             : protected:
     252             :     CCoinsView* base;
     253             : 
     254             : public:
     255             :     CCoinsViewBacked(CCoinsView* viewIn);
     256             :     bool GetCoin(const COutPoint& outpoint, Coin& coin) const override;
     257             :     bool HaveCoin(const COutPoint& outpoint) const override;
     258             :     uint256 GetBestBlock() const override;
     259             :     std::vector<uint256> GetHeadBlocks() const override;
     260             :     void SetBackend(CCoinsView& viewIn);
     261             :     CCoinsViewCursor* Cursor() const override;
     262             :     size_t EstimateSize() const override;
     263             : 
     264             :     bool BatchWrite(CCoinsMap& mapCoins,
     265             :                     const uint256& hashBlock,
     266             :                     const uint256& hashSaplingAnchor,
     267             :                     CAnchorsSaplingMap& mapSaplingAnchors,
     268             :                     CNullifiersMap& mapSaplingNullifiers) override;
     269             : 
     270             :     // Sapling
     271             :     bool GetSaplingAnchorAt(const uint256 &rt, SaplingMerkleTree &tree) const override;
     272             :     bool GetNullifier(const uint256 &nullifier) const override;
     273             :     uint256 GetBestAnchor() const override;
     274             : };
     275             : 
     276             : 
     277             : /** Used as the flags parameter to sequence and nLocktime checks in non-consensus code. */
     278             : static const unsigned int STANDARD_LOCKTIME_VERIFY_FLAGS = LOCKTIME_VERIFY_SEQUENCE |
     279             :                                                            LOCKTIME_MEDIAN_TIME_PAST;
     280             : 
     281             : /** CCoinsView that adds a memory cache for transactions to another CCoinsView */
     282             : class CCoinsViewCache : public CCoinsViewBacked
     283             : {
     284             : protected:
     285             :     /**
     286             :      * Make mutable so that we can "fill the cache" even from Get-methods
     287             :      * declared as "const".
     288             :      */
     289             :     mutable uint256 hashBlock;
     290             :     mutable CCoinsMap cacheCoins;
     291             : 
     292             :     // Sapling
     293             :     mutable uint256 hashSaplingAnchor;
     294             :     mutable CAnchorsSaplingMap cacheSaplingAnchors;
     295             :     mutable CNullifiersMap cacheSaplingNullifiers;
     296             : 
     297             :     /* Cached dynamic memory usage for the inner Coin objects. */
     298             :     mutable size_t cachedCoinsUsage;
     299             : 
     300             : public:
     301             :     CCoinsViewCache(CCoinsView *baseIn);
     302             : 
     303             :     /**
     304             :      * By deleting the copy constructor, we prevent accidentally using it when one intends to create a cache on top of a base cache.
     305             :      */
     306             :     CCoinsViewCache(const CCoinsViewCache &) = delete;
     307             : 
     308             :     // Sapling methods
     309             :     bool GetSaplingAnchorAt(const uint256 &rt, SaplingMerkleTree &tree) const override;
     310             :     bool GetNullifier(const uint256 &nullifier) const override;
     311             :     uint256 GetBestAnchor() const override;
     312             : 
     313             :     // Adds the tree to mapSaplingAnchors
     314             :     // and sets the current commitment root to this root.
     315             :     template<typename Tree> void PushAnchor(const Tree &tree);
     316             : 
     317             :     // Removes the current commitment root from mapAnchors and sets
     318             :     // the new current root.
     319             :     void PopAnchor(const uint256 &rt);
     320             : 
     321             :     // Marks nullifiers for a given transaction as spent or not.
     322             :     void SetNullifiers(const CTransaction& tx, bool spent);
     323             : 
     324             :     //! Check whether all sapling spend requirements (anchors/nullifiers) are satisfied
     325             :     bool HaveShieldedRequirements(const CTransaction& tx) const;
     326             : 
     327             :     // Standard CCoinsView methods
     328             :     bool GetCoin(const COutPoint& outpoint, Coin& coin) const override;
     329             :     bool HaveCoin(const COutPoint& outpoint) const override;
     330             :     uint256 GetBestBlock() const override;
     331             :     void SetBestBlock(const uint256& hashBlock);
     332             : 
     333             :     //! Get the coin and check if it's spent
     334             :     bool GetUTXOCoin(const COutPoint& outpoint, Coin& coin) const;
     335             : 
     336             :     bool BatchWrite(CCoinsMap& mapCoins,
     337             :                     const uint256& hashBlock,
     338             :                     const uint256& hashSaplingAnchor,
     339             :                     CAnchorsSaplingMap& mapSaplingAnchors,
     340             :                     CNullifiersMap& mapSaplingNullifiers) override;
     341             : 
     342             :     /**
     343             :      * Check if we have the given utxo already loaded in this cache.
     344             :      * The semantics are the same as HaveCoin(), but no calls to
     345             :      * the backing CCoinsView are made.
     346             :      */
     347             :     bool HaveCoinInCache(const COutPoint& outpoint) const;
     348             : 
     349             :     /**
     350             :      * Return a reference to a Coin in the cache, or a pruned one if not found. This is
     351             :      * more efficient than GetCoin. Modifications to other cache entries are
     352             :      * allowed while accessing the returned pointer.
     353             :      */
     354             :     const Coin& AccessCoin(const COutPoint& output) const;
     355             : 
     356             :     /**
     357             :      * Add a coin. Set potential_overwrite to true if a non-pruned version may
     358             :      * already exist.
     359             :      */
     360             :     void AddCoin(const COutPoint& outpoint, Coin&& coin, bool potential_overwrite);
     361             : 
     362             :     /**
     363             :      * Spend a coin. Pass moveto in order to get the deleted data.
     364             :      * If no unspent output exists for the passed outpoint, this call
     365             :      * has no effect.
     366             :      */
     367             :     void SpendCoin(const COutPoint &outpoint, Coin* moveto = nullptr);
     368             : 
     369             :     /**
     370             :      * Push the modifications applied to this cache to its base.
     371             :      * Failure to call this method before destruction will cause the changes to be forgotten.
     372             :      * If false is returned, the state of this cache (and its backing view) will be undefined.
     373             :      */
     374             :     bool Flush();
     375             : 
     376             :     /**
     377             :      * Removes the UTXO with the given outpoint from the cache, if it is not modified.
     378             :      */
     379             :     void Uncache(const COutPoint &outpoint);
     380             : 
     381             :     //! Calculate the size of the cache (in number of transaction outputs)
     382             :     unsigned int GetCacheSize() const;
     383             : 
     384             :     //! Calculate the size of the cache (in bytes)
     385             :     size_t DynamicMemoryUsage() const;
     386             : 
     387             :     /**
     388             :      * Amount of pivx coming in to a transaction
     389             :      * Note that lightweight clients may not know anything besides the hash of previous transactions,
     390             :      * so may not be able to calculate this.
     391             :      *
     392             :      * @param[in] tx    transaction for which we are checking input total
     393             :      * @return  Sum of value of all inputs (scriptSigs)
     394             :      */
     395             :     CAmount GetValueIn(const CTransaction& tx) const;
     396             : 
     397             :     //! Check whether all prevouts of the transaction are present in the UTXO set represented by this view
     398             :     bool HaveInputs(const CTransaction& tx) const;
     399             : 
     400             :     /*
     401             :      * Return the depth of a coin at height nHeight, or -1 if not found
     402             :      */
     403             :     int GetCoinDepthAtHeight(const COutPoint& output, int nHeight) const;
     404             : 
     405             :     /*
     406             :      * Return the sum of the value of all transaction outputs
     407             :      */
     408             :     CAmount GetTotalAmount() const;
     409             : 
     410             :     /*
     411             :      * Prune zerocoin mints and frozen outputs - do it once, after initialization
     412             :      */
     413             :     bool PruneInvalidEntries();
     414             : 
     415             : 
     416             : private:
     417             :     CCoinsMap::iterator FetchCoin(const COutPoint& outpoint) const;
     418             : 
     419             :     //! Generalized interface for popping anchors
     420             :     template<typename Tree, typename Cache, typename CacheEntry>
     421             :     void AbstractPopAnchor(
     422             :             const uint256 &newrt,
     423             :             Cache &cacheAnchors,
     424             :             uint256 &hash
     425             :     );
     426             : 
     427             :     //! Generalized interface for pushing anchors
     428             :     template<typename Tree, typename Cache, typename CacheIterator, typename CacheEntry>
     429             :     void AbstractPushAnchor(
     430             :             const Tree &tree,
     431             :             Cache &cacheAnchors,
     432             :             uint256 &hash
     433             :     );
     434             : 
     435             :     //! Interface for bringing an anchor into the cache.
     436             :     template<typename Tree>
     437             :     void BringBestAnchorIntoCache(
     438             :             const uint256 &currentRoot,
     439             :             Tree &tree
     440             :     );
     441             : };
     442             : 
     443             : //! Utility function to add all of a transaction's outputs to a cache.
     444             : // PIVX: When check is false, this assumes that overwrites are never possible due to BIP34 always in effect
     445             : // When check is true, the underlying view may be queried to determine whether an addition is
     446             : // an overwrite.
     447             : // When fSkipInvalid is true, the invalid_out list is checked before adding the coin.
     448             : void AddCoins(CCoinsViewCache& cache, const CTransaction& tx, int nHeight, bool check = false, bool fSkipInvalid = false);
     449             : 
     450             : //! Utility function to find any unspent output with a given txid.
     451             : const Coin& AccessByTxid(const CCoinsViewCache& cache, const uint256& txid);
     452             : 
     453             : #endif // PIVX_COINS_H

Generated by: LCOV version 1.14