2015-12-13 14:51:43 +01:00
// Copyright (c) 2012-2015 The Bitcoin Core developers
2014-10-31 01:43:19 +01:00
// Distributed under the MIT software license, see the accompanying
2013-11-05 02:47:07 +01:00
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
2020-03-19 23:46:56 +01:00
# include <coins.h>
2013-11-05 02:47:07 +01:00
2020-03-19 23:46:56 +01:00
# include <consensus/consensus.h>
# include <random.h>
2021-06-26 12:37:06 +02:00
# include <version.h>
2014-07-09 17:25:09 +02:00
2017-06-02 00:47:58 +02:00
bool CCoinsView : : GetCoin ( const COutPoint & outpoint , Coin & coin ) const { return false ; }
2014-12-15 09:11:16 +01:00
uint256 CCoinsView : : GetBestBlock ( ) const { return uint256 ( ) ; }
2017-06-28 18:24:32 +02:00
std : : vector < uint256 > CCoinsView : : GetHeadBlocks ( ) const { return std : : vector < uint256 > ( ) ; }
2014-08-24 02:08:05 +02:00
bool CCoinsView : : BatchWrite ( CCoinsMap & mapCoins , const uint256 & hashBlock ) { return false ; }
2017-08-16 15:54:51 +02:00
CCoinsViewCursor * CCoinsView : : Cursor ( ) const { return nullptr ; }
2013-11-05 02:47:07 +01:00
2017-06-27 08:49:44 +02:00
bool CCoinsView : : HaveCoin ( const COutPoint & outpoint ) const
{
Coin coin ;
return GetCoin ( outpoint , coin ) ;
}
2013-11-05 02:47:07 +01:00
2014-09-24 03:19:04 +02:00
CCoinsViewBacked : : CCoinsViewBacked ( CCoinsView * viewIn ) : base ( viewIn ) { }
2017-06-02 00:47:58 +02:00
bool CCoinsViewBacked : : GetCoin ( const COutPoint & outpoint , Coin & coin ) const { return base - > GetCoin ( outpoint , coin ) ; }
bool CCoinsViewBacked : : HaveCoin ( const COutPoint & outpoint ) const { return base - > HaveCoin ( outpoint ) ; }
2014-07-19 16:42:48 +02:00
uint256 CCoinsViewBacked : : GetBestBlock ( ) const { return base - > GetBestBlock ( ) ; }
2017-06-28 18:24:32 +02:00
std : : vector < uint256 > CCoinsViewBacked : : GetHeadBlocks ( ) const { return base - > GetHeadBlocks ( ) ; }
2013-11-05 02:47:07 +01:00
void CCoinsViewBacked : : SetBackend ( CCoinsView & viewIn ) { base = & viewIn ; }
2014-08-24 02:08:05 +02:00
bool CCoinsViewBacked : : BatchWrite ( CCoinsMap & mapCoins , const uint256 & hashBlock ) { return base - > BatchWrite ( mapCoins , hashBlock ) ; }
2016-04-15 16:36:39 +02:00
CCoinsViewCursor * CCoinsViewBacked : : Cursor ( ) const { return base - > Cursor ( ) ; }
2017-06-02 00:47:58 +02:00
size_t CCoinsViewBacked : : EstimateSize ( ) const { return base - > EstimateSize ( ) ; }
2013-11-05 02:47:07 +01:00
2017-06-02 00:47:58 +02:00
SaltedOutpointHasher : : SaltedOutpointHasher ( ) : k0 ( GetRand ( std : : numeric_limits < uint64_t > : : max ( ) ) ) , k1 ( GetRand ( std : : numeric_limits < uint64_t > : : max ( ) ) ) { }
2014-07-09 17:25:09 +02:00
2017-06-02 00:47:58 +02:00
CCoinsViewCache : : CCoinsViewCache ( CCoinsView * baseIn ) : CCoinsViewBacked ( baseIn ) , cachedCoinsUsage ( 0 ) { }
2013-11-05 02:47:07 +01:00
2015-05-04 01:31:11 +02:00
size_t CCoinsViewCache : : DynamicMemoryUsage ( ) const {
return memusage : : DynamicUsage ( cacheCoins ) + cachedCoinsUsage ;
}
2017-06-02 00:47:58 +02:00
CCoinsMap : : iterator CCoinsViewCache : : FetchCoin ( const COutPoint & outpoint ) const {
CCoinsMap : : iterator it = cacheCoins . find ( outpoint ) ;
2014-07-09 17:25:09 +02:00
if ( it ! = cacheCoins . end ( ) )
2013-11-05 02:47:07 +01:00
return it ;
2017-06-02 00:47:58 +02:00
Coin tmp ;
if ( ! base - > GetCoin ( outpoint , tmp ) )
2013-11-05 02:47:07 +01:00
return cacheCoins . end ( ) ;
2017-06-02 00:47:58 +02:00
CCoinsMap : : iterator ret = cacheCoins . emplace ( std : : piecewise_construct , std : : forward_as_tuple ( outpoint ) , std : : forward_as_tuple ( std : : move ( tmp ) ) ) . first ;
if ( ret - > second . coin . IsSpent ( ) ) {
// The parent only has an empty entry for this outpoint; we can consider our
2014-09-03 09:37:47 +02:00
// version as fresh.
ret - > second . flags = CCoinsCacheEntry : : FRESH ;
}
2017-06-02 00:47:58 +02:00
cachedCoinsUsage + = ret - > second . coin . DynamicMemoryUsage ( ) ;
2013-11-05 02:47:07 +01:00
return ret ;
}
2017-06-02 00:47:58 +02:00
bool CCoinsViewCache : : GetCoin ( const COutPoint & outpoint , Coin & coin ) const {
CCoinsMap : : const_iterator it = FetchCoin ( outpoint ) ;
2014-09-03 09:37:47 +02:00
if ( it ! = cacheCoins . end ( ) ) {
2017-06-02 00:47:58 +02:00
coin = it - > second . coin ;
2017-06-27 08:49:44 +02:00
return ! coin . IsSpent ( ) ;
2014-09-03 09:37:47 +02:00
}
return false ;
2014-07-19 16:42:48 +02:00
}
2017-06-02 00:47:58 +02:00
void CCoinsViewCache : : AddCoin ( const COutPoint & outpoint , Coin & & coin , bool possible_overwrite ) {
assert ( ! coin . IsSpent ( ) ) ;
if ( coin . out . scriptPubKey . IsUnspendable ( ) ) return ;
CCoinsMap : : iterator it ;
bool inserted ;
std : : tie ( it , inserted ) = cacheCoins . emplace ( std : : piecewise_construct , std : : forward_as_tuple ( outpoint ) , std : : tuple < > ( ) ) ;
bool fresh = false ;
if ( ! inserted ) {
cachedCoinsUsage - = it - > second . coin . DynamicMemoryUsage ( ) ;
}
if ( ! possible_overwrite ) {
if ( ! it - > second . coin . IsSpent ( ) ) {
2020-04-22 14:23:10 +02:00
throw std : : logic_error ( " Attempted to overwrite an unspent coin (when possible_overwrite is false) " ) ;
2014-09-03 09:37:47 +02:00
}
2020-04-22 14:23:10 +02:00
// If the coin exists in this cache as a spent coin and is DIRTY, then
// its spentness hasn't been flushed to the parent cache. We're
// re-adding the coin to this cache now but we can't mark it as FRESH.
// If we mark it FRESH and then spend it before the cache is flushed
// we would remove it from this cache and would never flush spentness
// to the parent cache.
//
// Re-adding a spent coin can happen in the case of a re-org (the coin
// is 'spent' when the block adding it is disconnected and then
// re-added when it is also added in a newly connected block).
//
// If the coin doesn't exist in the current cache, or is spent but not
// DIRTY, then it can be marked FRESH.
2017-06-02 00:47:58 +02:00
fresh = ! ( it - > second . flags & CCoinsCacheEntry : : DIRTY ) ;
2014-09-03 09:01:24 +02:00
}
2017-06-02 00:47:58 +02:00
it - > second . coin = std : : move ( coin ) ;
it - > second . flags | = CCoinsCacheEntry : : DIRTY | ( fresh ? CCoinsCacheEntry : : FRESH : 0 ) ;
cachedCoinsUsage + = it - > second . coin . DynamicMemoryUsage ( ) ;
2013-11-05 02:47:07 +01:00
}
2020-04-22 14:23:10 +02:00
void AddCoins ( CCoinsViewCache & cache , const CTransaction & tx , int nHeight , bool check_for_overwrite ) {
2017-06-02 00:47:58 +02:00
bool fCoinbase = tx . IsCoinBase ( ) ;
const uint256 & txid = tx . GetHash ( ) ;
for ( size_t i = 0 ; i < tx . vout . size ( ) ; + + i ) {
2020-04-22 14:23:10 +02:00
bool overwrite = check_for_overwrite ? cache . HaveCoin ( COutPoint ( txid , i ) ) : fCoinbase ;
// Coinbase transactions can always be overwritten, in order to correctly
2017-06-06 23:46:16 +02:00
// deal with the pre-BIP30 occurrences of duplicate coinbase transactions.
2017-06-28 18:24:32 +02:00
cache . AddCoin ( COutPoint ( txid , i ) , Coin ( tx . vout [ i ] , nHeight , fCoinbase ) , overwrite ) ;
2016-01-22 14:15:45 +01:00
}
2015-11-03 03:27:15 +01:00
}
2017-06-21 03:18:09 +02:00
bool CCoinsViewCache : : SpendCoin ( const COutPoint & outpoint , Coin * moveout ) {
2017-06-02 00:47:58 +02:00
CCoinsMap : : iterator it = FetchCoin ( outpoint ) ;
2017-06-21 03:18:09 +02:00
if ( it = = cacheCoins . end ( ) ) return false ;
2017-06-02 00:47:58 +02:00
cachedCoinsUsage - = it - > second . coin . DynamicMemoryUsage ( ) ;
if ( moveout ) {
* moveout = std : : move ( it - > second . coin ) ;
}
if ( it - > second . flags & CCoinsCacheEntry : : FRESH ) {
cacheCoins . erase ( it ) ;
} else {
it - > second . flags | = CCoinsCacheEntry : : DIRTY ;
it - > second . coin . Clear ( ) ;
}
2017-06-21 03:18:09 +02:00
return true ;
2017-06-02 00:47:58 +02:00
}
static const Coin coinEmpty ;
const Coin & CCoinsViewCache : : AccessCoin ( const COutPoint & outpoint ) const {
CCoinsMap : : const_iterator it = FetchCoin ( outpoint ) ;
2014-09-02 21:21:15 +02:00
if ( it = = cacheCoins . end ( ) ) {
2017-06-02 00:47:58 +02:00
return coinEmpty ;
2014-09-02 21:21:15 +02:00
} else {
2017-06-02 00:47:58 +02:00
return it - > second . coin ;
2014-09-02 21:21:15 +02:00
}
2014-07-19 16:42:48 +02:00
}
2017-06-02 00:47:58 +02:00
bool CCoinsViewCache : : HaveCoin ( const COutPoint & outpoint ) const {
CCoinsMap : : const_iterator it = FetchCoin ( outpoint ) ;
return ( it ! = cacheCoins . end ( ) & & ! it - > second . coin . IsSpent ( ) ) ;
2013-11-05 02:47:07 +01:00
}
2017-06-02 00:47:58 +02:00
bool CCoinsViewCache : : HaveCoinInCache ( const COutPoint & outpoint ) const {
CCoinsMap : : const_iterator it = cacheCoins . find ( outpoint ) ;
2017-06-26 17:06:24 +02:00
return ( it ! = cacheCoins . end ( ) & & ! it - > second . coin . IsSpent ( ) ) ;
2015-10-23 00:49:53 +02:00
}
2014-07-19 16:42:48 +02:00
uint256 CCoinsViewCache : : GetBestBlock ( ) const {
2014-12-15 09:11:16 +01:00
if ( hashBlock . IsNull ( ) )
2013-11-05 02:47:07 +01:00
hashBlock = base - > GetBestBlock ( ) ;
return hashBlock ;
}
2014-09-03 09:25:32 +02:00
void CCoinsViewCache : : SetBestBlock ( const uint256 & hashBlockIn ) {
2013-11-05 02:47:07 +01:00
hashBlock = hashBlockIn ;
}
2014-08-24 02:08:05 +02:00
bool CCoinsViewCache : : BatchWrite ( CCoinsMap & mapCoins , const uint256 & hashBlockIn ) {
2017-11-10 20:22:36 +01:00
for ( CCoinsMap : : iterator it = mapCoins . begin ( ) ; it ! = mapCoins . end ( ) ; it = mapCoins . erase ( it ) ) {
// Ignore non-dirty entries (optimization).
if ( ! ( it - > second . flags & CCoinsCacheEntry : : DIRTY ) ) {
continue ;
}
CCoinsMap : : iterator itUs = cacheCoins . find ( it - > first ) ;
if ( itUs = = cacheCoins . end ( ) ) {
2020-04-22 14:23:10 +02:00
// The parent cache does not have an entry, while the child cache does.
// We can ignore it if it's both spent and FRESH in the child
2017-11-10 20:22:36 +01:00
if ( ! ( it - > second . flags & CCoinsCacheEntry : : FRESH & & it - > second . coin . IsSpent ( ) ) ) {
2020-04-22 14:23:10 +02:00
// Create the coin in the parent cache, move the data up
// and mark it as dirty.
2017-11-10 20:22:36 +01:00
CCoinsCacheEntry & entry = cacheCoins [ it - > first ] ;
entry . coin = std : : move ( it - > second . coin ) ;
cachedCoinsUsage + = entry . coin . DynamicMemoryUsage ( ) ;
entry . flags = CCoinsCacheEntry : : DIRTY ;
// We can mark it FRESH in the parent if it was FRESH in the child
// Otherwise it might have just been flushed from the parent's cache
// and already exist in the grandparent
if ( it - > second . flags & CCoinsCacheEntry : : FRESH ) {
entry . flags | = CCoinsCacheEntry : : FRESH ;
2014-09-03 09:37:47 +02:00
}
2017-11-10 20:22:36 +01:00
}
} else {
2020-04-22 14:23:10 +02:00
// Found the entry in the parent cache
2017-11-10 20:22:36 +01:00
if ( ( it - > second . flags & CCoinsCacheEntry : : FRESH ) & & ! itUs - > second . coin . IsSpent ( ) ) {
2020-04-22 14:23:10 +02:00
// The coin was marked FRESH in the child cache, but the coin
// exists in the parent cache. If this ever happens, it means
// the FRESH flag was misapplied and there is a logic error in
// the calling code.
throw std : : logic_error ( " FRESH flag misapplied to coin that exists in parent cache " ) ;
2017-11-10 20:22:36 +01:00
}
if ( ( itUs - > second . flags & CCoinsCacheEntry : : FRESH ) & & it - > second . coin . IsSpent ( ) ) {
2020-04-22 14:23:10 +02:00
// The grandparent cache does not have an entry, and the coin
// has been spent. We can just delete it from the parent cache.
2017-11-10 20:22:36 +01:00
cachedCoinsUsage - = itUs - > second . coin . DynamicMemoryUsage ( ) ;
cacheCoins . erase ( itUs ) ;
2014-09-03 09:37:47 +02:00
} else {
2017-11-10 20:22:36 +01:00
// A normal modification.
cachedCoinsUsage - = itUs - > second . coin . DynamicMemoryUsage ( ) ;
itUs - > second . coin = std : : move ( it - > second . coin ) ;
cachedCoinsUsage + = itUs - > second . coin . DynamicMemoryUsage ( ) ;
itUs - > second . flags | = CCoinsCacheEntry : : DIRTY ;
2020-04-22 14:23:10 +02:00
// NOTE: It isn't safe to mark the coin as FRESH in the parent
// cache. If it already existed and was spent in the parent
// cache then marking it FRESH would prevent that spentness
// from being flushed to the grandparent.
2014-09-03 09:37:47 +02:00
}
}
2014-08-24 02:08:05 +02:00
}
2013-11-05 02:47:07 +01:00
hashBlock = hashBlockIn ;
return true ;
}
bool CCoinsViewCache : : Flush ( ) {
bool fOk = base - > BatchWrite ( cacheCoins , hashBlock ) ;
2014-08-24 02:08:05 +02:00
cacheCoins . clear ( ) ;
2015-05-04 01:31:11 +02:00
cachedCoinsUsage = 0 ;
2013-11-05 02:47:07 +01:00
return fOk ;
}
2017-06-02 00:47:58 +02:00
void CCoinsViewCache : : Uncache ( const COutPoint & hash )
2015-10-22 02:41:40 +02:00
{
CCoinsMap : : iterator it = cacheCoins . find ( hash ) ;
if ( it ! = cacheCoins . end ( ) & & it - > second . flags = = 0 ) {
2017-06-02 00:47:58 +02:00
cachedCoinsUsage - = it - > second . coin . DynamicMemoryUsage ( ) ;
2015-10-22 02:41:40 +02:00
cacheCoins . erase ( it ) ;
}
}
2014-07-19 16:42:48 +02:00
unsigned int CCoinsViewCache : : GetCacheSize ( ) const {
2013-11-05 02:47:07 +01:00
return cacheCoins . size ( ) ;
}
2014-04-23 00:46:19 +02:00
CAmount CCoinsViewCache : : GetValueIn ( const CTransaction & tx ) const
2013-11-05 02:47:07 +01:00
{
if ( tx . IsCoinBase ( ) )
return 0 ;
2014-04-23 00:46:19 +02:00
CAmount nResult = 0 ;
2013-11-05 02:47:07 +01:00
for ( unsigned int i = 0 ; i < tx . vin . size ( ) ; i + + )
2017-06-02 00:47:58 +02:00
nResult + = AccessCoin ( tx . vin [ i ] . prevout ) . out . nValue ;
2013-11-05 02:47:07 +01:00
return nResult ;
}
2014-07-19 16:42:48 +02:00
bool CCoinsViewCache : : HaveInputs ( const CTransaction & tx ) const
2013-11-05 02:47:07 +01:00
{
if ( ! tx . IsCoinBase ( ) ) {
for ( unsigned int i = 0 ; i < tx . vin . size ( ) ; i + + ) {
2017-06-02 00:47:58 +02:00
if ( ! HaveCoin ( tx . vin [ i ] . prevout ) ) {
2013-11-05 02:47:07 +01:00
return false ;
2014-09-02 21:21:15 +02:00
}
2013-11-05 02:47:07 +01:00
}
}
return true ;
}
2013-11-11 08:35:14 +01:00
2020-12-15 22:54:51 +01:00
static const size_t MAX_OUTPUTS_PER_BLOCK = MaxBlockSize ( ) / : : GetSerializeSize ( CTxOut ( ) , SER_NETWORK , PROTOCOL_VERSION ) ; // TODO: merge with similar definition in undo.h.
2014-09-03 09:01:24 +02:00
2017-06-02 00:47:58 +02:00
const Coin & AccessByTxid ( const CCoinsViewCache & view , const uint256 & txid )
2014-09-03 09:37:47 +02:00
{
2017-06-02 00:47:58 +02:00
COutPoint iter ( txid , 0 ) ;
while ( iter . n < MAX_OUTPUTS_PER_BLOCK ) {
const Coin & alternate = view . AccessCoin ( iter ) ;
if ( ! alternate . IsSpent ( ) ) return alternate ;
+ + iter . n ;
2014-09-03 09:37:47 +02:00
}
2017-06-02 00:47:58 +02:00
return coinEmpty ;
2016-04-15 16:36:39 +02:00
}