24 const uint256& hashSaplingAnchor,
44 const uint256& hashSaplingAnchor,
47 {
return base->
BatchWrite(mapCoins, hashBlock, hashSaplingAnchor, mapSaplingAnchors, mapSaplingNullifiers); }
68 CCoinsMap::iterator it =
cacheCoins.find(outpoint);
74 CCoinsMap::iterator ret =
cacheCoins.emplace(std::piecewise_construct, std::forward_as_tuple(outpoint), std::forward_as_tuple(std::move(tmp))).first;
75 if (ret->second.coin.IsSpent()) {
86 CCoinsMap::const_iterator it =
FetchCoin(outpoint);
88 coin = it->second.coin;
95 assert(!coin.IsSpent());
96 if (coin.out.scriptPubKey.IsUnspendable())
return;
97 if (coin.out.IsZerocoinMint())
return;
98 CCoinsMap::iterator it;
100 std::tie(it, inserted) =
cacheCoins.emplace(std::piecewise_construct, std::forward_as_tuple(outpoint), std::tuple<>());
105 if (!possible_overwrite) {
106 if (!it->second.coin.IsSpent()) {
107 throw std::logic_error(
"Adding new coin that replaces non-pruned entry");
111 it->second.coin = std::move(coin);
121 for (
size_t i = 0; i < tx.
vout.size(); ++i) {
128 bool overwrite = check && cache.
HaveCoin(out);
129 cache.
AddCoin(out,
Coin(tx.
vout[i], nHeight, fCoinbase, fCoinstake), overwrite);
135 CCoinsMap::iterator it =
FetchCoin(outpoint);
139 *moveout = std::move(it->second.coin);
145 it->second.coin.Clear();
149 static const Coin coinEmpty;
153 CCoinsMap::const_iterator it =
FetchCoin(outpoint);
157 return it->second.coin;
163 CCoinsMap::const_iterator it =
FetchCoin(outpoint);
164 return (it !=
cacheCoins.end() && !it->second.coin.IsSpent());
169 CCoinsMap::const_iterator it =
cacheCoins.find(outpoint);
185 template<
typename Map,
typename MapIterator,
typename MapEntry>
189 size_t &cachedCoinsUsage
192 for (MapIterator child_it = mapAnchors.begin(); child_it != mapAnchors.end();)
194 if (child_it->second.flags & MapEntry::DIRTY) {
195 MapIterator parent_it = cacheAnchors.find(child_it->first);
197 if (parent_it == cacheAnchors.end()) {
198 MapEntry& entry = cacheAnchors[child_it->first];
199 entry.entered = child_it->second.entered;
200 entry.tree = child_it->second.tree;
201 entry.flags = MapEntry::DIRTY;
203 cachedCoinsUsage += entry.tree.DynamicMemoryUsage();
205 if (parent_it->second.entered != child_it->second.entered) {
207 parent_it->second.entered = child_it->second.entered;
208 parent_it->second.flags |= MapEntry::DIRTY;
213 MapIterator itOld = child_it++;
214 mapAnchors.erase(itOld);
220 for (CNullifiersMap::iterator child_it = mapNullifiers.begin(); child_it != mapNullifiers.end();) {
222 CNullifiersMap::iterator parent_it = cacheNullifiers.find(child_it->first);
224 if (parent_it == cacheNullifiers.end()) {
226 entry.
entered = child_it->second.entered;
229 if (parent_it->second.entered != child_it->second.entered) {
230 parent_it->second.entered = child_it->second.entered;
235 CNullifiersMap::iterator itOld = child_it++;
236 mapNullifiers.erase(itOld);
242 const uint256 &hashSaplingAnchorIn,
246 for (CCoinsMap::iterator it = mapCoins.begin(); it != mapCoins.end(); it = mapCoins.erase(it)) {
251 CCoinsMap::iterator itUs =
cacheCoins.find(it->first);
259 entry.
coin = std::move(it->second.coin);
275 throw std::logic_error(
"FRESH flag misapplied to cache entry for base transaction with spendable outputs");
288 itUs->second.coin = std::move(it->second.coin);
325 CCoinsMap::iterator it =
cacheCoins.find(outpoint);
326 if (it !=
cacheCoins.end() && it->second.flags == 0) {
360 for (
unsigned int i = 0; i < tx.
vin.size(); i++) {
373 return nHeight - coin.
nHeight + 1;
381 std::unique_ptr<CCoinsViewCursor> pcursor(
Cursor());
382 while (pcursor->Valid()) {
384 if (pcursor->GetValue(coin) && !coin.
IsSpent()) {
400 LogPrintf(
"Pruning invalid output %s\n", out.ToString());
407 static const size_t MAX_OUTPUTS_PER_BLOCK = MAX_BLOCK_SIZE_CURRENT /
::GetSerializeSize(
CTxOut(), PROTOCOL_VERSION);
412 while (iter.
n < MAX_OUTPUTS_PER_BLOCK) {
414 if (!alternate.
IsSpent())
return alternate;
426 if (it->second.entered) {
427 tree = it->second.tree;
439 ret->second.entered =
true;
440 ret->second.tree = tree;
448 CNullifiersMap::iterator it = cacheToUse->find(nullifier);
449 if (it != cacheToUse->end())
450 return it->second.entered;
456 cacheToUse->insert(std::make_pair(nullifier, entry));
460 template<
typename Tree,
typename Cache,
typename CacheIterator,
typename CacheEntry>
476 if (currentRoot != newrt) {
477 auto insertRet = cacheAnchors.insert(std::make_pair(newrt, CacheEntry()));
478 CacheIterator ret = insertRet.first;
480 ret->second.entered =
true;
481 ret->second.tree = tree;
482 ret->second.flags = CacheEntry::DIRTY;
484 if (insertRet.second) {
495 AbstractPushAnchor<SaplingMerkleTree, CAnchorsSaplingMap, CAnchorsSaplingMap::iterator, CAnchorsSaplingCacheEntry>(
511 template<
typename Tree,
typename Cache,
typename CacheEntry>
523 if (currentRoot != newrt) {
532 cacheAnchors[currentRoot].entered =
false;
535 cacheAnchors[currentRoot].flags = CacheEntry::DIRTY;
543 AbstractPopAnchor<SaplingMerkleTree, CAnchorsSaplingMap, CAnchorsSaplingCacheEntry>(
555 ret.first->second.entered = spent;
int64_t CAmount
Amount in PIV (Can be negative)
CCoinsView backed by another CCoinsView.
bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock, const uint256 &hashSaplingAnchor, CAnchorsSaplingMap &mapSaplingAnchors, CNullifiersMap &mapSaplingNullifiers) override
Do a bulk modification (multiple Coin changes + BestBlock change).
bool HaveCoin(const COutPoint &outpoint) const override
Just check whether we have data for a given outpoint.
bool GetNullifier(const uint256 &nullifier) const override
Determine whether a nullifier is spent or not.
CCoinsViewCursor * Cursor() const override
Get a cursor to iterate over the whole state.
bool GetCoin(const COutPoint &outpoint, Coin &coin) const override
Retrieve the Coin (unspent transaction output) for a given outpoint.
size_t EstimateSize() const override
Estimate database size (0 if not implemented)
uint256 GetBestBlock() const override
Retrieve the block hash whose state this CCoinsView currently represents.
uint256 GetBestAnchor() const override
Get the current "tip" or the latest anchored tree root in the chain.
bool GetSaplingAnchorAt(const uint256 &rt, SaplingMerkleTree &tree) const override
Retrieve the tree (Sapling) at a particular anchored root in the chain.
void SetBackend(CCoinsView &viewIn)
std::vector< uint256 > GetHeadBlocks() const override
Retrieve the range of blocks that may have been only partially written.
CCoinsViewBacked(CCoinsView *viewIn)
CCoinsView that adds a memory cache for transactions to another CCoinsView.
bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock, const uint256 &hashSaplingAnchor, CAnchorsSaplingMap &mapSaplingAnchors, CNullifiersMap &mapSaplingNullifiers) override
Do a bulk modification (multiple Coin changes + BestBlock change).
void SpendCoin(const COutPoint &outpoint, Coin *moveto=nullptr)
Spend a coin.
uint256 hashSaplingAnchor
CAmount GetValueIn(const CTransaction &tx) const
Amount of pivx coming in to a transaction Note that lightweight clients may not know anything besides...
uint256 hashBlock
Make mutable so that we can "fill the cache" even from Get-methods declared as "const".
void Uncache(const COutPoint &outpoint)
Removes the UTXO with the given outpoint from the cache, if it is not modified.
CCoinsViewCache(CCoinsView *baseIn)
bool HaveInputs(const CTransaction &tx) const
Check whether all prevouts of the transaction are present in the UTXO set represented by this view.
void BringBestAnchorIntoCache(const uint256 ¤tRoot, Tree &tree)
Interface for bringing an anchor into the cache.
CAnchorsSaplingMap cacheSaplingAnchors
void SetNullifiers(const CTransaction &tx, bool spent)
void PushAnchor(const Tree &tree)
bool PruneInvalidEntries()
CNullifiersMap cacheSaplingNullifiers
void PopAnchor(const uint256 &rt)
void AddCoin(const COutPoint &outpoint, Coin &&coin, bool potential_overwrite)
Add a coin.
void AbstractPopAnchor(const uint256 &newrt, Cache &cacheAnchors, uint256 &hash)
Generalized interface for popping anchors.
unsigned int GetCacheSize() const
Calculate the size of the cache (in number of transaction outputs)
bool GetSaplingAnchorAt(const uint256 &rt, SaplingMerkleTree &tree) const override
Retrieve the tree (Sapling) at a particular anchored root in the chain.
uint256 GetBestBlock() const override
Retrieve the block hash whose state this CCoinsView currently represents.
uint256 GetBestAnchor() const override
Get the current "tip" or the latest anchored tree root in the chain.
void SetBestBlock(const uint256 &hashBlock)
CCoinsMap::iterator FetchCoin(const COutPoint &outpoint) const
bool GetCoin(const COutPoint &outpoint, Coin &coin) const override
Retrieve the Coin (unspent transaction output) for a given outpoint.
bool GetUTXOCoin(const COutPoint &outpoint, Coin &coin) const
Get the coin and check if it's spent.
bool HaveCoinInCache(const COutPoint &outpoint) const
Check if we have the given utxo already loaded in this cache.
bool GetNullifier(const uint256 &nullifier) const override
Determine whether a nullifier is spent or not.
int GetCoinDepthAtHeight(const COutPoint &output, int nHeight) const
bool Flush()
Push the modifications applied to this cache to its base.
size_t DynamicMemoryUsage() const
Calculate the size of the cache (in bytes)
bool HaveShieldedRequirements(const CTransaction &tx) const
Check whether all sapling spend requirements (anchors/nullifiers) are satisfied.
CAmount GetTotalAmount() const
bool HaveCoin(const COutPoint &outpoint) const override
Just check whether we have data for a given outpoint.
void AbstractPushAnchor(const Tree &tree, Cache &cacheAnchors, uint256 &hash)
Generalized interface for pushing anchors.
const Coin & AccessCoin(const COutPoint &output) const
Return a reference to a Coin in the cache, or a pruned one if not found.
Cursor for iterating over CoinsView state.
Abstract view on the open txout dataset.
virtual bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock, const uint256 &hashSaplingAnchor, CAnchorsSaplingMap &mapSaplingAnchors, CNullifiersMap &mapSaplingNullifiers)
Do a bulk modification (multiple Coin changes + BestBlock change).
virtual bool GetCoin(const COutPoint &outpoint, Coin &coin) const
Retrieve the Coin (unspent transaction output) for a given outpoint.
virtual bool GetNullifier(const uint256 &nullifier) const
Determine whether a nullifier is spent or not.
virtual uint256 GetBestAnchor() const
Get the current "tip" or the latest anchored tree root in the chain.
virtual CCoinsViewCursor * Cursor() const
Get a cursor to iterate over the whole state.
virtual std::vector< uint256 > GetHeadBlocks() const
Retrieve the range of blocks that may have been only partially written.
virtual bool GetSaplingAnchorAt(const uint256 &rt, SaplingMerkleTree &tree) const
Retrieve the tree (Sapling) at a particular anchored root in the chain.
virtual bool HaveCoin(const COutPoint &outpoint) const
Just check whether we have data for a given outpoint.
virtual size_t EstimateSize() const
Estimate database size (0 if not implemented)
virtual uint256 GetBestBlock() const
Retrieve the block hash whose state this CCoinsView currently represents.
An outpoint - a combination of a transaction hash and an index n into its vout.
The basic transaction that is broadcasted on the network and contained in blocks.
bool HasZerocoinSpendInputs() const
bool IsShieldedTx() const
const uint256 & GetHash() const
CAmount GetShieldedValueIn() const
Optional< SaplingTxData > sapData
std::vector< CTxOut > vout
An input of a transaction.
bool IsZerocoinSpend() const
bool IsZerocoinPublicSpend() const
An output of a transaction.
CTxOut out
unspent transaction output
uint32_t nHeight
at which height the containing transaction was included in the active block chain
A shielded input to a transaction.
uint256 anchor
A Merkle root of the Sapling note commitment tree at some block height in the past.
uint256 nullifier
The nullifier of the input note.
void AddCoins(CCoinsViewCache &cache, const CTransaction &tx, int nHeight, bool check, bool fSkipInvalid)
Utility function to add all of a transaction's outputs to a cache.
void BatchWriteAnchors(Map &mapAnchors, Map &cacheAnchors, size_t &cachedCoinsUsage)
const Coin & AccessByTxid(const CCoinsViewCache &view, const uint256 &txid)
Utility function to find any unspent output with a given txid.
void BatchWriteNullifiers(CNullifiersMap &mapNullifiers, CNullifiersMap &cacheNullifiers)
std::unordered_map< uint256, CAnchorsSaplingCacheEntry, SaltedIdHasher > CAnchorsSaplingMap
std::unordered_map< COutPoint, CCoinsCacheEntry, SaltedOutpointHasher > CCoinsMap
std::unordered_map< uint256, CNullifiersCacheEntry, SaltedIdHasher > CNullifiersMap
std::set< COutPoint > setInvalidOutPoints
bool ContainsOutPoint(const COutPoint &out)
uint64_t GetRand(uint64_t nMax) noexcept
unsigned int GetSerializeSize(const std::array< T, N > &item)
array
const uint256 UINT256_ZERO
constant uint256 instances