2016-12-31 19:01:21 +01:00
// Copyright (c) 2012-2016 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.
# include "coins.h"
2017-04-25 20:29:29 +02:00
# include "consensus/consensus.h"
2015-05-04 01:31:11 +02:00
# include "memusage.h"
2014-07-09 17:25:09 +02:00
# include "random.h"
2013-11-05 02:47:07 +01:00
# include <assert.h>
2017-05-31 02:58:54 +02:00
bool CCoinsView : : GetCoin ( const COutPoint & outpoint , Coin & coin ) const { return false ; }
bool CCoinsView : : HaveCoin ( const COutPoint & outpoint ) const { return false ; }
2014-12-15 09:11:16 +01:00
uint256 CCoinsView : : GetBestBlock ( ) const { return uint256 ( ) ; }
2014-08-24 02:08:05 +02:00
bool CCoinsView : : BatchWrite ( CCoinsMap & mapCoins , const uint256 & hashBlock ) { return false ; }
2016-03-28 18:18:30 +02:00
CCoinsViewCursor * CCoinsView : : Cursor ( ) const { return 0 ; }
2013-11-05 02:47:07 +01:00
2014-09-24 03:19:04 +02:00
CCoinsViewBacked : : CCoinsViewBacked ( CCoinsView * viewIn ) : base ( viewIn ) { }
2017-05-31 02:58:54 +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 ( ) ; }
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-03-28 18:18:30 +02:00
CCoinsViewCursor * CCoinsViewBacked : : Cursor ( ) const { return base - > Cursor ( ) ; }
2017-05-13 00:19:19 +02:00
size_t CCoinsViewBacked : : EstimateSize ( ) const { return base - > EstimateSize ( ) ; }
2013-11-05 02:47:07 +01:00
2017-04-25 20:29:39 +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-04-25 20:29:39 +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-05-31 02:58:54 +02:00
CCoinsMap : : iterator CCoinsViewCache : : FetchCoin ( const COutPoint & outpoint ) const {
2017-04-25 20:29:39 +02:00
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-04-25 20:29:39 +02:00
Coin tmp ;
2017-05-31 02:58:54 +02:00
if ( ! base - > GetCoin ( outpoint , tmp ) )
2013-11-05 02:47:07 +01:00
return cacheCoins . end ( ) ;
2017-04-25 20:29:39 +02:00
CCoinsMap : : iterator ret = cacheCoins . emplace ( std : : piecewise_construct , std : : forward_as_tuple ( outpoint ) , std : : forward_as_tuple ( std : : move ( tmp ) ) ) . first ;
2017-05-31 02:58:54 +02:00
if ( ret - > second . coin . IsSpent ( ) ) {
2017-04-25 20:29:39 +02:00
// 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-05-04 09:15:36 +02:00
cachedCoinsUsage + = ret - > second . coin . DynamicMemoryUsage ( ) ;
2013-11-05 02:47:07 +01:00
return ret ;
}
2017-05-31 02:58:54 +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-05-04 09:15:36 +02:00
coin = it - > second . coin ;
2014-09-03 09:37:47 +02:00
return true ;
}
return false ;
2014-07-19 16:42:48 +02:00
}
2017-04-25 20:29:29 +02:00
void CCoinsViewCache : : AddCoin ( const COutPoint & outpoint , Coin & & coin , bool possible_overwrite ) {
2017-05-31 02:58:54 +02:00
assert ( ! coin . IsSpent ( ) ) ;
2017-04-25 20:29:29 +02:00
if ( coin . out . scriptPubKey . IsUnspendable ( ) ) return ;
CCoinsMap : : iterator it ;
bool inserted ;
2017-04-25 20:29:39 +02:00
std : : tie ( it , inserted ) = cacheCoins . emplace ( std : : piecewise_construct , std : : forward_as_tuple ( outpoint ) , std : : tuple < > ( ) ) ;
2017-04-25 20:29:29 +02:00
bool fresh = false ;
if ( ! inserted ) {
2017-05-04 09:15:36 +02:00
cachedCoinsUsage - = it - > second . coin . DynamicMemoryUsage ( ) ;
2017-04-25 20:29:29 +02:00
}
if ( ! possible_overwrite ) {
2017-05-31 02:58:54 +02:00
if ( ! it - > second . coin . IsSpent ( ) ) {
2017-04-25 20:29:29 +02:00
throw std : : logic_error ( " Adding new coin that replaces non-pruned entry " ) ;
}
2017-04-25 20:29:39 +02:00
fresh = ! ( it - > second . flags & CCoinsCacheEntry : : DIRTY ) ;
2017-04-25 20:29:29 +02:00
}
2017-05-04 09:15:36 +02:00
it - > second . coin = std : : move ( coin ) ;
2017-04-25 20:29:29 +02:00
it - > second . flags | = CCoinsCacheEntry : : DIRTY | ( fresh ? CCoinsCacheEntry : : FRESH : 0 ) ;
2017-05-04 09:15:36 +02:00
cachedCoinsUsage + = it - > second . coin . DynamicMemoryUsage ( ) ;
2017-04-25 20:29:29 +02:00
}
void AddCoins ( CCoinsViewCache & cache , const CTransaction & tx , int nHeight ) {
bool fCoinbase = tx . IsCoinBase ( ) ;
const uint256 & txid = tx . GetHash ( ) ;
for ( size_t i = 0 ; i < tx . vout . size ( ) ; + + i ) {
// Pass fCoinbase as the possible_overwrite flag to AddCoin, in order to correctly
// deal with the pre-BIP30 occurrances of duplicate coinbase transactions.
cache . AddCoin ( COutPoint ( txid , i ) , Coin ( tx . vout [ i ] , nHeight , fCoinbase ) , fCoinbase ) ;
}
}
void CCoinsViewCache : : SpendCoin ( const COutPoint & outpoint , Coin * moveout ) {
2017-05-31 02:58:54 +02:00
CCoinsMap : : iterator it = FetchCoin ( outpoint ) ;
2017-04-25 20:29:29 +02:00
if ( it = = cacheCoins . end ( ) ) return ;
2017-05-04 09:15:36 +02:00
cachedCoinsUsage - = it - > second . coin . DynamicMemoryUsage ( ) ;
2017-04-25 20:29:39 +02:00
if ( moveout ) {
2017-05-04 09:15:36 +02:00
* moveout = std : : move ( it - > second . coin ) ;
2017-04-25 20:29:29 +02:00
}
2017-04-25 20:29:39 +02:00
if ( it - > second . flags & CCoinsCacheEntry : : FRESH ) {
2017-04-25 20:29:29 +02:00
cacheCoins . erase ( it ) ;
} else {
it - > second . flags | = CCoinsCacheEntry : : DIRTY ;
2017-05-04 09:15:36 +02:00
it - > second . coin . Clear ( ) ;
2014-09-02 21:21:15 +02:00
}
2014-07-19 16:42:48 +02:00
}
2017-04-25 20:29:29 +02:00
static const Coin coinEmpty ;
2017-04-25 20:29:39 +02:00
const Coin & CCoinsViewCache : : AccessCoin ( const COutPoint & outpoint ) const {
2017-05-31 02:58:54 +02:00
CCoinsMap : : const_iterator it = FetchCoin ( outpoint ) ;
2017-04-25 20:29:39 +02:00
if ( it = = cacheCoins . end ( ) ) {
2017-04-25 20:29:29 +02:00
return coinEmpty ;
} else {
2017-05-04 09:15:36 +02:00
return it - > second . coin ;
2017-04-25 20:29:29 +02:00
}
}
2017-05-31 02:58:54 +02:00
bool CCoinsViewCache : : HaveCoin ( const COutPoint & outpoint ) const {
CCoinsMap : : const_iterator it = FetchCoin ( outpoint ) ;
return ( it ! = cacheCoins . end ( ) & & ! it - > second . coin . IsSpent ( ) ) ;
2017-04-25 20:29:29 +02:00
}
2017-05-31 02:58:54 +02:00
bool CCoinsViewCache : : HaveCoinInCache ( const COutPoint & outpoint ) const {
2017-04-25 20:29:39 +02:00
CCoinsMap : : const_iterator it = cacheCoins . find ( outpoint ) ;
2015-10-23 00:49:53 +02:00
return it ! = cacheCoins . end ( ) ;
}
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 ) {
for ( CCoinsMap : : iterator it = mapCoins . begin ( ) ; it ! = mapCoins . end ( ) ; ) {
2014-09-03 09:37:47 +02:00
if ( it - > second . flags & CCoinsCacheEntry : : DIRTY ) { // Ignore non-dirty entries (optimization).
CCoinsMap : : iterator itUs = cacheCoins . find ( it - > first ) ;
if ( itUs = = cacheCoins . end ( ) ) {
2015-03-26 18:52:10 +01:00
// The parent cache does not have an entry, while the child does
// We can ignore it if it's both FRESH and pruned in the child
2017-05-31 02:58:54 +02:00
if ( ! ( it - > second . flags & CCoinsCacheEntry : : FRESH & & it - > second . coin . IsSpent ( ) ) ) {
2015-03-26 18:52:10 +01:00
// Otherwise we will need to create it in the parent
// and move the data up and mark it as dirty
2014-09-03 09:37:47 +02:00
CCoinsCacheEntry & entry = cacheCoins [ it - > first ] ;
2017-05-04 09:15:36 +02:00
entry . coin = std : : move ( it - > second . coin ) ;
cachedCoinsUsage + = entry . coin . DynamicMemoryUsage ( ) ;
2015-03-26 18:52:10 +01:00
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
}
} else {
2016-12-09 18:28:22 +01:00
// Assert that the child cache entry was not marked FRESH if the
// parent cache entry has unspent outputs. If this ever happens,
// it means the FRESH flag was misapplied and there is a logic
// error in the calling code.
2017-05-31 02:58:54 +02:00
if ( ( it - > second . flags & CCoinsCacheEntry : : FRESH ) & & ! itUs - > second . coin . IsSpent ( ) )
2016-12-09 18:28:22 +01:00
throw std : : logic_error ( " FRESH flag misapplied to cache entry for base transaction with spendable outputs " ) ;
2015-03-26 18:52:10 +01:00
// Found the entry in the parent cache
2017-05-31 02:58:54 +02:00
if ( ( itUs - > second . flags & CCoinsCacheEntry : : FRESH ) & & it - > second . coin . IsSpent ( ) ) {
2014-09-03 09:37:47 +02:00
// The grandparent does not have an entry, and the child is
// modified and being pruned. This means we can just delete
// it from the parent.
2017-05-04 09:15:36 +02:00
cachedCoinsUsage - = itUs - > second . coin . DynamicMemoryUsage ( ) ;
2014-09-03 09:37:47 +02:00
cacheCoins . erase ( itUs ) ;
} else {
// A normal modification.
2017-05-04 09:15:36 +02:00
cachedCoinsUsage - = itUs - > second . coin . DynamicMemoryUsage ( ) ;
itUs - > second . coin = std : : move ( it - > second . coin ) ;
cachedCoinsUsage + = itUs - > second . coin . DynamicMemoryUsage ( ) ;
2014-09-03 09:37:47 +02:00
itUs - > second . flags | = CCoinsCacheEntry : : DIRTY ;
2016-11-07 21:30:41 +01:00
// NOTE: It is possible the child has a FRESH flag here in
// the event the entry we found in the parent is pruned. But
// we must not copy that FRESH flag to the parent as that
// pruned state likely still needs to be communicated to the
// grandparent.
2014-09-03 09:37:47 +02:00
}
}
}
2014-08-24 02:08:05 +02:00
CCoinsMap : : iterator itOld = it + + ;
mapCoins . erase ( itOld ) ;
}
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-04-25 20:29:39 +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-05-04 09:15:36 +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-04-27 01:09:27 +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-05-31 02:58:54 +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
2017-04-25 20:29:29 +02:00
static const size_t MAX_OUTPUTS_PER_BLOCK = MAX_BLOCK_BASE_SIZE / : : GetSerializeSize ( CTxOut ( ) , SER_NETWORK , PROTOCOL_VERSION ) ; // TODO: merge with similar definition in undo.h.
2017-04-25 20:29:39 +02:00
const Coin & AccessByTxid ( const CCoinsViewCache & view , const uint256 & txid )
2017-04-25 20:29:29 +02:00
{
COutPoint iter ( txid , 0 ) ;
while ( iter . n < MAX_OUTPUTS_PER_BLOCK ) {
const Coin & alternate = view . AccessCoin ( iter ) ;
2017-05-31 02:58:54 +02:00
if ( ! alternate . IsSpent ( ) ) return alternate ;
2017-04-25 20:29:29 +02:00
+ + iter . n ;
}
return coinEmpty ;
}