2015-09-24 07:15:28 +02:00
# include "claimtrie.h"
2015-11-25 18:04:32 +01:00
# include "coins.h"
# include "hash.h"
2015-02-05 20:24:09 +01:00
# include <boost/scoped_ptr.hpp>
2015-11-25 18:04:32 +01:00
# include <iostream>
# include <algorithm>
2015-02-03 02:57:53 +01:00
2015-12-06 03:55:23 +01:00
std : : vector < unsigned char > heightToVch ( int n )
{
std : : vector < unsigned char > vchHeight ;
vchHeight . resize ( 8 ) ;
vchHeight [ 0 ] = 0 ;
vchHeight [ 1 ] = 0 ;
vchHeight [ 2 ] = 0 ;
vchHeight [ 3 ] = 0 ;
vchHeight [ 4 ] = n > > 24 ;
vchHeight [ 5 ] = n > > 16 ;
vchHeight [ 6 ] = n > > 8 ;
vchHeight [ 7 ] = n ;
return vchHeight ;
}
2015-11-25 18:04:32 +01:00
uint256 CClaimValue : : GetHash ( ) const
2015-02-03 02:57:53 +01:00
{
2015-11-25 18:04:32 +01:00
CHash256 txHasher ;
2015-12-23 20:12:32 +01:00
txHasher . Write ( outPoint . hash . begin ( ) , outPoint . hash . size ( ) ) ;
2015-11-25 18:04:32 +01:00
std : : vector < unsigned char > vchtxHash ( txHasher . OUTPUT_SIZE ) ;
txHasher . Finalize ( & ( vchtxHash [ 0 ] ) ) ;
2015-03-26 03:10:05 +01:00
2015-11-25 18:04:32 +01:00
CHash256 nOutHasher ;
2015-02-03 02:57:53 +01:00
std : : stringstream ss ;
2015-12-23 20:12:32 +01:00
ss < < outPoint . n ;
2015-03-26 03:10:05 +01:00
std : : string snOut = ss . str ( ) ;
2015-11-25 18:04:32 +01:00
nOutHasher . Write ( ( unsigned char * ) snOut . data ( ) , snOut . size ( ) ) ;
std : : vector < unsigned char > vchnOutHash ( nOutHasher . OUTPUT_SIZE ) ;
nOutHasher . Finalize ( & ( vchnOutHash [ 0 ] ) ) ;
CHash256 hasher ;
hasher . Write ( vchtxHash . data ( ) , vchtxHash . size ( ) ) ;
hasher . Write ( vchnOutHash . data ( ) , vchnOutHash . size ( ) ) ;
std : : vector < unsigned char > vchHash ( hasher . OUTPUT_SIZE ) ;
hasher . Finalize ( & ( vchHash [ 0 ] ) ) ;
2015-03-26 03:10:05 +01:00
2015-11-25 18:04:32 +01:00
uint256 claimHash ( vchHash ) ;
return claimHash ;
2015-02-03 02:57:53 +01:00
}
2015-11-25 18:04:32 +01:00
bool CClaimTrieNode : : insertClaim ( CClaimValue claim )
2015-02-03 02:57:53 +01:00
{
2015-12-23 20:12:32 +01:00
LogPrintf ( " %s: Inserting %s:%d (amount: %d) into the claim trie \n " , __func__ , claim . outPoint . hash . ToString ( ) , claim . outPoint . n , claim . nAmount ) ;
2015-11-25 18:04:32 +01:00
claims . push_back ( claim ) ;
2015-02-03 02:57:53 +01:00
return true ;
}
2015-12-23 20:12:32 +01:00
bool CClaimTrieNode : : removeClaim ( const COutPoint & outPoint , CClaimValue & claim )
2015-02-03 02:57:53 +01:00
{
2015-12-23 20:12:32 +01:00
LogPrintf ( " %s: Removing txid: %s, nOut: %d from the claim trie \n " , __func__ , outPoint . hash . ToString ( ) , outPoint . n ) ;
2015-02-03 02:57:53 +01:00
2015-12-23 20:12:32 +01:00
std : : vector < CClaimValue > : : iterator itClaims ;
for ( itClaims = claims . begin ( ) ; itClaims ! = claims . end ( ) ; + + itClaims )
2015-03-17 06:16:37 +01:00
{
2015-12-23 20:12:32 +01:00
if ( itClaims - > outPoint = = outPoint )
2015-03-17 06:16:37 +01:00
{
2015-12-23 20:12:32 +01:00
std : : swap ( claim , * itClaims ) ;
2015-03-17 06:16:37 +01:00
break ;
}
}
2015-12-23 20:12:32 +01:00
if ( itClaims ! = claims . end ( ) )
{
claims . erase ( itClaims ) ;
}
2015-02-03 02:57:53 +01:00
else
{
2015-11-25 18:04:32 +01:00
LogPrintf ( " CClaimTrieNode::%s() : asked to remove a claim that doesn't exist \n " , __func__ ) ;
LogPrintf ( " CClaimTrieNode::%s() : claims that do exist: \n " , __func__ ) ;
for ( unsigned int i = 0 ; i < claims . size ( ) ; i + + )
2015-03-09 01:24:13 +01:00
{
2015-12-23 20:12:32 +01:00
LogPrintf ( " \t txhash: %s, nOut: %d: \n " , claims [ i ] . outPoint . hash . ToString ( ) , claims [ i ] . outPoint . n ) ;
2015-03-09 01:24:13 +01:00
}
2015-02-03 02:57:53 +01:00
return false ;
}
return true ;
}
2015-11-25 18:04:32 +01:00
bool CClaimTrieNode : : getBestClaim ( CClaimValue & claim ) const
2015-02-03 02:57:53 +01:00
{
2015-11-25 18:04:32 +01:00
if ( claims . empty ( ) )
2015-02-03 02:57:53 +01:00
return false ;
else
{
2015-11-25 18:04:32 +01:00
claim = claims . front ( ) ;
2015-02-03 02:57:53 +01:00
return true ;
}
}
2015-12-23 20:12:32 +01:00
bool CClaimTrieNode : : haveClaim ( const COutPoint & outPoint ) const
2015-03-19 22:16:35 +01:00
{
2015-11-25 18:04:32 +01:00
for ( std : : vector < CClaimValue > : : const_iterator itclaim = claims . begin ( ) ; itclaim ! = claims . end ( ) ; + + itclaim )
2015-12-23 20:12:32 +01:00
{
if ( itclaim - > outPoint = = outPoint )
2015-03-19 22:16:35 +01:00
return true ;
2015-12-23 20:12:32 +01:00
}
2015-03-19 22:16:35 +01:00
return false ;
}
2015-11-25 18:04:32 +01:00
void CClaimTrieNode : : reorderClaims ( supportMapEntryType & supports )
2015-09-25 23:09:21 +02:00
{
2015-11-25 18:04:32 +01:00
std : : vector < CClaimValue > : : iterator itclaim ;
2015-09-28 00:24:46 +02:00
2015-11-25 18:04:32 +01:00
for ( itclaim = claims . begin ( ) ; itclaim ! = claims . end ( ) ; + + itclaim )
2015-09-28 00:24:46 +02:00
{
2015-11-25 18:04:32 +01:00
itclaim - > nEffectiveAmount = itclaim - > nAmount ;
2015-09-28 00:24:46 +02:00
}
2015-11-25 18:04:32 +01:00
for ( supportMapEntryType : : iterator itsupport = supports . begin ( ) ; itsupport ! = supports . end ( ) ; + + itsupport )
2015-09-28 00:24:46 +02:00
{
2015-11-25 18:04:32 +01:00
for ( itclaim = claims . begin ( ) ; itclaim ! = claims . end ( ) ; + + itclaim )
2015-09-28 00:24:46 +02:00
{
2015-12-23 01:11:50 +01:00
if ( itsupport - > supportedClaimId = = itclaim - > claimId )
2015-09-28 00:24:46 +02:00
{
2015-11-25 18:04:32 +01:00
itclaim - > nEffectiveAmount + = itsupport - > nAmount ;
2015-09-28 00:24:46 +02:00
break ;
}
}
}
2015-11-25 18:04:32 +01:00
std : : make_heap ( claims . begin ( ) , claims . end ( ) ) ;
2015-09-25 23:09:21 +02:00
}
2015-09-24 07:15:28 +02:00
uint256 CClaimTrie : : getMerkleHash ( )
2015-02-03 02:57:53 +01:00
{
return root . hash ;
}
2015-09-24 07:15:28 +02:00
bool CClaimTrie : : empty ( ) const
2015-02-03 02:57:53 +01:00
{
return root . empty ( ) ;
}
2015-10-22 04:30:56 +02:00
template < typename K > bool CClaimTrie : : keyTypeEmpty ( char keyType , K & dummy ) const
2015-03-17 06:16:37 +01:00
{
2015-10-22 04:30:56 +02:00
boost : : scoped_ptr < CLevelDBIterator > pcursor ( const_cast < CLevelDBWrapper * > ( & db ) - > NewIterator ( ) ) ;
2015-05-21 19:50:40 +02:00
pcursor - > SeekToFirst ( ) ;
while ( pcursor - > Valid ( ) )
{
2015-10-22 04:30:56 +02:00
std : : pair < char , K > key ;
if ( pcursor - > GetKey ( key ) )
2015-05-21 19:50:40 +02:00
{
2015-10-22 04:30:56 +02:00
if ( key . first = = keyType )
2015-05-21 19:50:40 +02:00
{
return false ;
}
}
2015-10-22 04:30:56 +02:00
else
2015-05-21 19:50:40 +02:00
{
2015-10-22 04:30:56 +02:00
break ;
2015-05-21 19:50:40 +02:00
}
pcursor - > Next ( ) ;
}
return true ;
2015-03-17 06:16:37 +01:00
}
2015-09-25 23:09:21 +02:00
bool CClaimTrie : : queueEmpty ( ) const
{
2015-11-25 18:04:32 +01:00
for ( claimQueueType : : const_iterator itRow = dirtyQueueRows . begin ( ) ; itRow ! = dirtyQueueRows . end ( ) ; + + itRow )
2015-09-25 23:09:21 +02:00
{
if ( ! itRow - > second . empty ( ) )
return false ;
}
2015-10-22 04:30:56 +02:00
int dummy ;
2015-11-25 18:04:32 +01:00
return keyTypeEmpty ( CLAIM_QUEUE_ROW , dummy ) ;
2015-09-25 23:09:21 +02:00
}
2015-09-24 07:15:28 +02:00
bool CClaimTrie : : expirationQueueEmpty ( ) const
2015-05-27 23:53:12 +02:00
{
2016-01-05 01:04:55 +01:00
for ( expirationQueueType : : const_iterator itRow = dirtyExpirationQueueRows . begin ( ) ; itRow ! = dirtyExpirationQueueRows . end ( ) ; + + itRow )
2015-05-27 23:53:12 +02:00
{
if ( ! itRow - > second . empty ( ) )
return false ;
}
2015-10-22 04:30:56 +02:00
int dummy ;
return keyTypeEmpty ( EXP_QUEUE_ROW , dummy ) ;
2015-09-25 23:09:21 +02:00
}
2015-05-27 23:53:12 +02:00
2015-09-25 23:09:21 +02:00
bool CClaimTrie : : supportEmpty ( ) const
{
for ( supportMapType : : const_iterator itNode = dirtySupportNodes . begin ( ) ; itNode ! = dirtySupportNodes . end ( ) ; + + itNode )
2015-05-27 23:53:12 +02:00
{
2015-09-25 23:09:21 +02:00
if ( ! itNode - > second . empty ( ) )
return false ;
2015-05-27 23:53:12 +02:00
}
2015-10-22 04:30:56 +02:00
std : : string dummy ;
return keyTypeEmpty ( SUPPORT , dummy ) ;
2015-09-25 23:09:21 +02:00
}
bool CClaimTrie : : supportQueueEmpty ( ) const
{
2015-11-25 18:04:32 +01:00
for ( supportQueueType : : const_iterator itRow = dirtySupportQueueRows . begin ( ) ; itRow ! = dirtySupportQueueRows . end ( ) ; + + itRow )
2015-09-25 23:09:21 +02:00
{
if ( ! itRow - > second . empty ( ) )
return false ;
}
2015-10-22 04:30:56 +02:00
int dummy ;
2015-11-25 18:04:32 +01:00
return keyTypeEmpty ( SUPPORT_QUEUE_ROW , dummy ) ;
2015-05-27 23:53:12 +02:00
}
2015-09-24 07:15:28 +02:00
void CClaimTrie : : setExpirationTime ( int t )
2015-05-27 23:53:12 +02:00
{
nExpirationTime = t ;
}
2015-09-24 07:15:28 +02:00
void CClaimTrie : : clear ( )
2015-03-25 19:06:04 +01:00
{
clear ( & root ) ;
}
2015-09-24 07:15:28 +02:00
void CClaimTrie : : clear ( CClaimTrieNode * current )
2015-03-25 19:06:04 +01:00
{
for ( nodeMapType : : const_iterator itchildren = current - > children . begin ( ) ; itchildren ! = current - > children . end ( ) ; + + itchildren )
{
clear ( itchildren - > second ) ;
delete itchildren - > second ;
}
}
2015-12-23 20:12:32 +01:00
bool CClaimTrie : : haveClaim ( const std : : string & name , const COutPoint & outPoint ) const
2015-03-19 22:16:35 +01:00
{
2015-09-24 07:15:28 +02:00
const CClaimTrieNode * current = & root ;
2015-03-19 22:16:35 +01:00
for ( std : : string : : const_iterator itname = name . begin ( ) ; itname ! = name . end ( ) ; + + itname )
{
nodeMapType : : const_iterator itchildren = current - > children . find ( * itname ) ;
if ( itchildren = = current - > children . end ( ) )
return false ;
current = itchildren - > second ;
}
2015-12-23 20:12:32 +01:00
return current - > haveClaim ( outPoint ) ;
2015-03-19 22:16:35 +01:00
}
2015-12-23 20:12:32 +01:00
bool CClaimTrie : : haveSupport ( const std : : string & name , const COutPoint & outPoint ) const
2015-10-01 08:37:47 +02:00
{
2015-11-25 18:04:32 +01:00
supportMapEntryType node ;
2015-10-01 08:37:47 +02:00
if ( ! getSupportNode ( name , node ) )
{
return false ;
}
2015-11-25 18:04:32 +01:00
for ( supportMapEntryType : : const_iterator itnode = node . begin ( ) ; itnode ! = node . end ( ) ; + + itnode )
2015-10-01 08:37:47 +02:00
{
2015-12-23 20:12:32 +01:00
if ( itnode - > outPoint = = outPoint )
2015-10-01 08:37:47 +02:00
return true ;
}
return false ;
}
2015-12-23 20:12:32 +01:00
bool CClaimTrie : : haveClaimInQueue ( const std : : string & name , const COutPoint & outPoint , int & nValidAtHeight ) const
2015-10-27 21:37:09 +01:00
{
2016-01-05 01:04:55 +01:00
queueNameRowType nameRow ;
2015-11-25 18:04:32 +01:00
if ( ! getQueueNameRow ( name , nameRow ) )
2015-10-27 21:37:09 +01:00
{
2015-11-25 18:04:32 +01:00
return false ;
2015-10-27 21:37:09 +01:00
}
2016-01-05 01:04:55 +01:00
queueNameRowType : : const_iterator itNameRow ;
2015-11-25 18:04:32 +01:00
for ( itNameRow = nameRow . begin ( ) ; itNameRow ! = nameRow . end ( ) ; + + itNameRow )
2015-10-27 21:37:09 +01:00
{
2015-12-30 20:30:43 +01:00
if ( itNameRow - > outPoint = = outPoint )
2015-10-27 21:37:09 +01:00
{
2015-12-31 08:51:09 +01:00
nValidAtHeight = itNameRow - > nHeight ;
2015-11-25 18:04:32 +01:00
break ;
2015-10-27 21:37:09 +01:00
}
}
2015-11-25 18:04:32 +01:00
if ( itNameRow = = nameRow . end ( ) )
{
return false ;
}
claimQueueRowType row ;
if ( getQueueRow ( nValidAtHeight , row ) )
2015-10-27 21:37:09 +01:00
{
2015-11-25 18:04:32 +01:00
for ( claimQueueRowType : : const_iterator itRow = row . begin ( ) ; itRow ! = row . end ( ) ; + + itRow )
2015-10-27 21:37:09 +01:00
{
2015-12-23 20:12:32 +01:00
if ( itRow - > first = = name & & itRow - > second . outPoint = = outPoint )
2015-11-25 18:04:32 +01:00
{
if ( itRow - > second . nValidAtHeight ! = nValidAtHeight )
{
2015-12-23 20:12:32 +01:00
LogPrintf ( " %s: An inconsistency was found in the claim queue. Please report this to the developers: \n Different nValidAtHeight between named queue and height queue \n : name: %s, txid: %s, nOut: %d, nValidAtHeight in named queue: %d, nValidAtHeight in height queue: %d current height: %d \n " , __func__ , name , outPoint . hash . GetHex ( ) , outPoint . n , nValidAtHeight , itRow - > second . nValidAtHeight , nCurrentHeight ) ;
2015-11-25 18:04:32 +01:00
}
return true ;
}
2015-10-27 21:37:09 +01:00
}
}
2015-12-23 20:12:32 +01:00
LogPrintf ( " %s: An inconsistency was found in the claim queue. Please report this to the developers: \n Found in named queue but not in height queue: name: %s, txid: %s, nOut: %d, nValidAtHeight: %d, current height: %d \n " , __func__ , name , outPoint . hash . GetHex ( ) , outPoint . n , nValidAtHeight , nCurrentHeight ) ;
2015-12-29 22:21:09 +01:00
return false ;
2015-10-27 21:37:09 +01:00
}
2015-12-23 20:12:32 +01:00
bool CClaimTrie : : haveSupportInQueue ( const std : : string & name , const COutPoint & outPoint , int & nValidAtHeight ) const
2015-10-28 03:14:04 +01:00
{
2016-01-05 01:04:55 +01:00
queueNameRowType nameRow ;
2015-11-25 18:04:32 +01:00
if ( ! getSupportQueueNameRow ( name , nameRow ) )
{
return false ;
}
2016-01-05 01:04:55 +01:00
queueNameRowType : : const_iterator itNameRow ;
2015-11-25 18:04:32 +01:00
for ( itNameRow = nameRow . begin ( ) ; itNameRow ! = nameRow . end ( ) ; + + itNameRow )
2015-10-28 03:14:04 +01:00
{
2015-12-23 20:12:32 +01:00
if ( itNameRow - > outPoint = = outPoint )
2015-10-28 03:14:04 +01:00
{
2015-12-31 08:51:09 +01:00
nValidAtHeight = itNameRow - > nHeight ;
2015-11-25 18:04:32 +01:00
break ;
2015-10-28 03:14:04 +01:00
}
}
2015-11-25 18:04:32 +01:00
if ( itNameRow = = nameRow . end ( ) )
2015-10-28 03:14:04 +01:00
{
2015-11-25 18:04:32 +01:00
return false ;
2015-10-28 03:14:04 +01:00
}
2015-11-25 18:04:32 +01:00
supportQueueRowType row ;
2015-12-17 09:11:46 +01:00
if ( getSupportQueueRow ( nValidAtHeight , row ) )
2015-10-28 03:14:04 +01:00
{
2015-11-25 18:04:32 +01:00
for ( supportQueueRowType : : const_iterator itRow = row . begin ( ) ; itRow ! = row . end ( ) ; + + itRow )
2015-10-28 03:14:04 +01:00
{
2015-12-23 20:12:32 +01:00
if ( itRow - > first = = name & & itRow - > second . outPoint = = outPoint )
2015-11-25 18:04:32 +01:00
{
if ( itRow - > second . nValidAtHeight ! = nValidAtHeight )
{
2015-12-23 20:12:32 +01:00
LogPrintf ( " %s: An inconsistency was found in the support queue. Please report this to the developers: \n Different nValidAtHeight between named queue and height queue \n : name: %s, txid: %s, nOut: %d, nValidAtHeight in named queue: %d, nValidAtHeight in height queue: %d current height: %d \n " , __func__ , name , outPoint . hash . GetHex ( ) , outPoint . n , nValidAtHeight , itRow - > second . nValidAtHeight , nCurrentHeight ) ;
2015-11-25 18:04:32 +01:00
}
return true ;
}
2015-10-28 03:14:04 +01:00
}
}
2015-12-23 20:12:32 +01:00
LogPrintf ( " %s: An inconsistency was found in the claim queue. Please report this to the developers: \n Found in named queue but not in height queue: name: %s, txid: %s, nOut: %d, nValidAtHeight: %d, current height: %d \n " , __func__ , name , outPoint . hash . GetHex ( ) , outPoint . n , nValidAtHeight , nCurrentHeight ) ;
2015-10-28 03:14:04 +01:00
return false ;
}
2015-09-24 07:15:28 +02:00
unsigned int CClaimTrie : : getTotalNamesInTrie ( ) const
2015-04-10 22:50:50 +02:00
{
if ( empty ( ) )
return 0 ;
2015-09-24 07:15:28 +02:00
const CClaimTrieNode * current = & root ;
2015-04-10 22:50:50 +02:00
return getTotalNamesRecursive ( current ) ;
}
2015-09-24 07:15:28 +02:00
unsigned int CClaimTrie : : getTotalNamesRecursive ( const CClaimTrieNode * current ) const
2015-04-10 22:50:50 +02:00
{
unsigned int names_in_subtrie = 0 ;
2015-11-25 18:04:32 +01:00
if ( ! ( current - > claims . empty ( ) ) )
2015-04-10 22:50:50 +02:00
names_in_subtrie + = 1 ;
for ( nodeMapType : : const_iterator it = current - > children . begin ( ) ; it ! = current - > children . end ( ) ; + + it )
{
names_in_subtrie + = getTotalNamesRecursive ( it - > second ) ;
}
return names_in_subtrie ;
}
2015-09-24 07:15:28 +02:00
unsigned int CClaimTrie : : getTotalClaimsInTrie ( ) const
2015-04-10 22:50:50 +02:00
{
if ( empty ( ) )
return 0 ;
2015-09-24 07:15:28 +02:00
const CClaimTrieNode * current = & root ;
2015-04-10 22:50:50 +02:00
return getTotalClaimsRecursive ( current ) ;
}
2015-09-24 07:15:28 +02:00
unsigned int CClaimTrie : : getTotalClaimsRecursive ( const CClaimTrieNode * current ) const
2015-04-10 22:50:50 +02:00
{
2015-11-25 18:04:32 +01:00
unsigned int claims_in_subtrie = current - > claims . size ( ) ;
2015-04-10 22:50:50 +02:00
for ( nodeMapType : : const_iterator it = current - > children . begin ( ) ; it ! = current - > children . end ( ) ; + + it )
{
claims_in_subtrie + = getTotalClaimsRecursive ( it - > second ) ;
}
return claims_in_subtrie ;
}
2015-09-24 07:15:28 +02:00
CAmount CClaimTrie : : getTotalValueOfClaimsInTrie ( bool fControllingOnly ) const
2015-04-10 22:50:50 +02:00
{
if ( empty ( ) )
return 0 ;
2015-09-24 07:15:28 +02:00
const CClaimTrieNode * current = & root ;
2015-04-10 22:50:50 +02:00
return getTotalValueOfClaimsRecursive ( current , fControllingOnly ) ;
}
2015-09-24 07:15:28 +02:00
CAmount CClaimTrie : : getTotalValueOfClaimsRecursive ( const CClaimTrieNode * current , bool fControllingOnly ) const
2015-04-10 22:50:50 +02:00
{
CAmount value_in_subtrie = 0 ;
2015-11-25 18:04:32 +01:00
for ( std : : vector < CClaimValue > : : const_iterator itclaim = current - > claims . begin ( ) ; itclaim ! = current - > claims . end ( ) ; + + itclaim )
2015-04-10 22:50:50 +02:00
{
2015-11-25 18:04:32 +01:00
value_in_subtrie + = itclaim - > nAmount ;
2015-04-10 22:50:50 +02:00
if ( fControllingOnly )
break ;
}
for ( nodeMapType : : const_iterator itchild = current - > children . begin ( ) ; itchild ! = current - > children . end ( ) ; + + itchild )
{
value_in_subtrie + = getTotalValueOfClaimsRecursive ( itchild - > second , fControllingOnly ) ;
}
return value_in_subtrie ;
}
2015-09-24 07:15:28 +02:00
bool CClaimTrie : : recursiveFlattenTrie ( const std : : string & name , const CClaimTrieNode * current , std : : vector < namedNodeType > & nodes ) const
2015-02-07 18:32:05 +01:00
{
2015-06-12 04:55:12 +02:00
namedNodeType node ( name , * current ) ;
nodes . push_back ( node ) ;
2015-02-07 18:32:05 +01:00
for ( nodeMapType : : const_iterator it = current - > children . begin ( ) ; it ! = current - > children . end ( ) ; + + it )
{
std : : stringstream ss ;
ss < < name < < it - > first ;
2015-06-12 04:55:12 +02:00
if ( ! recursiveFlattenTrie ( ss . str ( ) , it - > second , nodes ) )
2015-02-07 18:32:05 +01:00
return false ;
}
return true ;
}
2015-09-24 07:15:28 +02:00
std : : vector < namedNodeType > CClaimTrie : : flattenTrie ( ) const
2015-02-07 18:32:05 +01:00
{
2015-06-12 04:55:12 +02:00
std : : vector < namedNodeType > nodes ;
if ( ! recursiveFlattenTrie ( " " , & root , nodes ) )
LogPrintf ( " %s: Something went wrong flattening the trie " , __func__ ) ;
return nodes ;
2015-02-07 18:32:05 +01:00
}
2015-12-06 03:55:23 +01:00
const CClaimTrieNode * CClaimTrie : : getNodeForName ( const std : : string & name ) const
2015-02-07 18:32:05 +01:00
{
2015-09-24 07:15:28 +02:00
const CClaimTrieNode * current = & root ;
2015-02-07 18:32:05 +01:00
for ( std : : string : : const_iterator itname = name . begin ( ) ; itname ! = name . end ( ) ; + + itname )
{
nodeMapType : : const_iterator itchildren = current - > children . find ( * itname ) ;
if ( itchildren = = current - > children . end ( ) )
2015-12-06 03:55:23 +01:00
return NULL ;
2015-02-07 18:32:05 +01:00
current = itchildren - > second ;
}
2015-12-06 03:55:23 +01:00
return current ;
}
bool CClaimTrie : : getInfoForName ( const std : : string & name , CClaimValue & claim ) const
{
const CClaimTrieNode * current = getNodeForName ( name ) ;
if ( current )
return current - > getBestClaim ( claim ) ;
return false ;
}
bool CClaimTrie : : getLastTakeoverForName ( const std : : string & name , int & lastTakeoverHeight ) const
{
const CClaimTrieNode * current = getNodeForName ( name ) ;
if ( current )
{
lastTakeoverHeight = current - > nHeightOfLastTakeover ;
return true ;
}
return false ;
2015-02-07 18:32:05 +01:00
}
2015-12-06 03:55:23 +01:00
bool CClaimTrie : : checkConsistency ( ) const
2015-02-03 02:57:53 +01:00
{
2015-02-05 20:24:09 +01:00
if ( empty ( ) )
return true ;
2015-02-03 02:57:53 +01:00
return recursiveCheckConsistency ( & root ) ;
}
2015-12-06 03:55:23 +01:00
bool CClaimTrie : : recursiveCheckConsistency ( const CClaimTrieNode * node ) const
2015-02-03 02:57:53 +01:00
{
2015-03-26 03:10:05 +01:00
std : : vector < unsigned char > vchToHash ;
2015-02-03 02:57:53 +01:00
2015-12-06 03:55:23 +01:00
for ( nodeMapType : : const_iterator it = node - > children . begin ( ) ; it ! = node - > children . end ( ) ; + + it )
2015-02-03 02:57:53 +01:00
{
if ( recursiveCheckConsistency ( it - > second ) )
{
2015-03-26 03:10:05 +01:00
vchToHash . push_back ( it - > first ) ;
vchToHash . insert ( vchToHash . end ( ) , it - > second - > hash . begin ( ) , it - > second - > hash . end ( ) ) ;
2015-02-03 02:57:53 +01:00
}
else
return false ;
}
2015-03-17 06:16:37 +01:00
2015-11-25 18:04:32 +01:00
CClaimValue claim ;
bool hasClaim = node - > getBestClaim ( claim ) ;
2015-02-23 23:51:52 +01:00
2015-11-25 18:04:32 +01:00
if ( hasClaim )
2015-02-23 23:51:52 +01:00
{
2015-11-25 18:04:32 +01:00
uint256 claimHash = claim . GetHash ( ) ;
vchToHash . insert ( vchToHash . end ( ) , claimHash . begin ( ) , claimHash . end ( ) ) ;
2015-12-06 03:55:23 +01:00
std : : vector < unsigned char > heightToHash = heightToVch ( node - > nHeightOfLastTakeover ) ;
vchToHash . insert ( vchToHash . end ( ) , heightToHash . begin ( ) , heightToHash . end ( ) ) ;
2015-02-23 23:51:52 +01:00
}
2015-02-03 02:57:53 +01:00
CHash256 hasher ;
std : : vector < unsigned char > vchHash ( hasher . OUTPUT_SIZE ) ;
2015-03-26 03:10:05 +01:00
hasher . Write ( vchToHash . data ( ) , vchToHash . size ( ) ) ;
2015-02-03 02:57:53 +01:00
hasher . Finalize ( & ( vchHash [ 0 ] ) ) ;
uint256 calculatedHash ( vchHash ) ;
return calculatedHash = = node - > hash ;
}
2015-11-25 18:04:32 +01:00
bool CClaimTrie : : getQueueRow ( int nHeight , claimQueueRowType & row ) const
2015-03-17 06:16:37 +01:00
{
2015-11-25 18:04:32 +01:00
claimQueueType : : const_iterator itQueueRow = dirtyQueueRows . find ( nHeight ) ;
2015-05-21 19:50:40 +02:00
if ( itQueueRow ! = dirtyQueueRows . end ( ) )
2015-03-17 06:16:37 +01:00
{
2015-05-21 19:50:40 +02:00
row = itQueueRow - > second ;
return true ;
2015-03-17 06:16:37 +01:00
}
2015-11-25 18:04:32 +01:00
return db . Read ( std : : make_pair ( CLAIM_QUEUE_ROW , nHeight ) , row ) ;
2015-03-17 06:16:37 +01:00
}
2016-01-05 01:04:55 +01:00
bool CClaimTrie : : getQueueNameRow ( const std : : string & name , queueNameRowType & row ) const
2015-05-27 23:53:12 +02:00
{
2016-01-05 01:04:55 +01:00
queueNameType : : const_iterator itQueueNameRow = dirtyQueueNameRows . find ( name ) ;
2015-11-25 18:04:32 +01:00
if ( itQueueNameRow ! = dirtyQueueNameRows . end ( ) )
{
row = itQueueNameRow - > second ;
return true ;
}
return db . Read ( std : : make_pair ( CLAIM_QUEUE_NAME_ROW , name ) , row ) ;
}
2016-01-05 01:04:55 +01:00
bool CClaimTrie : : getExpirationQueueRow ( int nHeight , expirationQueueRowType & row ) const
2015-11-25 18:04:32 +01:00
{
2016-01-05 01:04:55 +01:00
expirationQueueType : : const_iterator itQueueRow = dirtyExpirationQueueRows . find ( nHeight ) ;
2015-05-27 23:53:12 +02:00
if ( itQueueRow ! = dirtyExpirationQueueRows . end ( ) )
{
row = itQueueRow - > second ;
return true ;
}
2015-09-25 23:09:21 +02:00
return db . Read ( std : : make_pair ( EXP_QUEUE_ROW , nHeight ) , row ) ;
2015-05-27 23:53:12 +02:00
}
2015-11-25 18:04:32 +01:00
void CClaimTrie : : updateQueueRow ( int nHeight , claimQueueRowType & row )
2015-03-17 06:16:37 +01:00
{
2015-11-25 18:04:32 +01:00
claimQueueType : : iterator itQueueRow = dirtyQueueRows . find ( nHeight ) ;
2015-05-21 19:50:40 +02:00
if ( itQueueRow = = dirtyQueueRows . end ( ) )
2015-03-17 06:16:37 +01:00
{
2015-11-25 18:04:32 +01:00
claimQueueRowType newRow ;
std : : pair < claimQueueType : : iterator , bool > ret ;
ret = dirtyQueueRows . insert ( std : : pair < int , claimQueueRowType > ( nHeight , newRow ) ) ;
assert ( ret . second ) ;
itQueueRow = ret . first ;
}
itQueueRow - > second . swap ( row ) ;
}
2016-01-05 01:04:55 +01:00
void CClaimTrie : : updateQueueNameRow ( const std : : string & name , queueNameRowType & row )
2015-11-25 18:04:32 +01:00
{
2016-01-05 01:04:55 +01:00
queueNameType : : iterator itQueueRow = dirtyQueueNameRows . find ( name ) ;
2015-11-25 18:04:32 +01:00
if ( itQueueRow = = dirtyQueueNameRows . end ( ) )
{
2016-01-05 01:04:55 +01:00
queueNameRowType newRow ;
std : : pair < queueNameType : : iterator , bool > ret ;
ret = dirtyQueueNameRows . insert ( std : : pair < std : : string , queueNameRowType > ( name , newRow ) ) ;
2015-05-21 19:50:40 +02:00
assert ( ret . second ) ;
itQueueRow = ret . first ;
2015-03-17 06:16:37 +01:00
}
2015-05-21 19:50:40 +02:00
itQueueRow - > second . swap ( row ) ;
2015-03-17 06:16:37 +01:00
}
2016-01-05 01:04:55 +01:00
void CClaimTrie : : updateExpirationRow ( int nHeight , expirationQueueRowType & row )
2015-05-27 23:53:12 +02:00
{
2016-01-05 01:04:55 +01:00
expirationQueueType : : iterator itQueueRow = dirtyExpirationQueueRows . find ( nHeight ) ;
2015-05-27 23:53:12 +02:00
if ( itQueueRow = = dirtyExpirationQueueRows . end ( ) )
{
2016-01-05 01:04:55 +01:00
expirationQueueRowType newRow ;
std : : pair < expirationQueueType : : iterator , bool > ret ;
ret = dirtyExpirationQueueRows . insert ( std : : pair < int , expirationQueueRowType > ( nHeight , newRow ) ) ;
2015-05-27 23:53:12 +02:00
assert ( ret . second ) ;
itQueueRow = ret . first ;
}
itQueueRow - > second . swap ( row ) ;
}
2015-11-25 18:04:32 +01:00
void CClaimTrie : : updateSupportMap ( const std : : string & name , supportMapEntryType & node )
2015-09-25 23:09:21 +02:00
{
supportMapType : : iterator itNode = dirtySupportNodes . find ( name ) ;
if ( itNode = = dirtySupportNodes . end ( ) )
{
2015-11-25 18:04:32 +01:00
supportMapEntryType newNode ;
2015-09-25 23:09:21 +02:00
std : : pair < supportMapType : : iterator , bool > ret ;
2015-11-25 18:04:32 +01:00
ret = dirtySupportNodes . insert ( std : : pair < std : : string , supportMapEntryType > ( name , newNode ) ) ;
2015-09-25 23:09:21 +02:00
assert ( ret . second ) ;
itNode = ret . first ;
}
itNode - > second . swap ( node ) ;
}
2015-11-25 18:04:32 +01:00
void CClaimTrie : : updateSupportQueue ( int nHeight , supportQueueRowType & row )
2015-09-25 23:09:21 +02:00
{
2015-11-25 18:04:32 +01:00
supportQueueType : : iterator itQueueRow = dirtySupportQueueRows . find ( nHeight ) ;
2015-09-25 23:09:21 +02:00
if ( itQueueRow = = dirtySupportQueueRows . end ( ) )
{
2015-11-25 18:04:32 +01:00
supportQueueRowType newRow ;
std : : pair < supportQueueType : : iterator , bool > ret ;
ret = dirtySupportQueueRows . insert ( std : : pair < int , supportQueueRowType > ( nHeight , newRow ) ) ;
assert ( ret . second ) ;
itQueueRow = ret . first ;
}
itQueueRow - > second . swap ( row ) ;
}
2016-01-05 01:04:55 +01:00
void CClaimTrie : : updateSupportNameQueue ( const std : : string & name , queueNameRowType & row )
2015-11-25 18:04:32 +01:00
{
2016-01-05 01:04:55 +01:00
queueNameType : : iterator itQueueRow = dirtySupportQueueNameRows . find ( name ) ;
2015-11-25 18:04:32 +01:00
if ( itQueueRow = = dirtySupportQueueNameRows . end ( ) )
{
2016-01-05 01:04:55 +01:00
queueNameRowType newRow ;
std : : pair < queueNameType : : iterator , bool > ret ;
ret = dirtySupportQueueNameRows . insert ( std : : pair < std : : string , queueNameRowType > ( name , newRow ) ) ;
2015-09-25 23:09:21 +02:00
assert ( ret . second ) ;
itQueueRow = ret . first ;
}
itQueueRow - > second . swap ( row ) ;
}
2016-01-05 01:04:55 +01:00
void CClaimTrie : : updateSupportExpirationQueue ( int nHeight , expirationQueueRowType & row )
2015-12-29 19:50:11 +01:00
{
2016-01-05 01:04:55 +01:00
expirationQueueType : : iterator itQueueRow = dirtySupportExpirationQueueRows . find ( nHeight ) ;
2015-12-29 19:50:11 +01:00
if ( itQueueRow = = dirtySupportExpirationQueueRows . end ( ) )
{
2016-01-05 01:04:55 +01:00
expirationQueueRowType newRow ;
std : : pair < expirationQueueType : : iterator , bool > ret ;
ret = dirtySupportExpirationQueueRows . insert ( std : : pair < int , expirationQueueRowType > ( nHeight , newRow ) ) ;
2015-12-29 19:50:11 +01:00
assert ( ret . second ) ;
itQueueRow = ret . first ;
}
itQueueRow - > second . swap ( row ) ;
}
2015-11-25 18:04:32 +01:00
bool CClaimTrie : : getSupportNode ( std : : string name , supportMapEntryType & node ) const
2015-10-01 08:37:47 +02:00
{
supportMapType : : const_iterator itNode = dirtySupportNodes . find ( name ) ;
if ( itNode ! = dirtySupportNodes . end ( ) )
{
node = itNode - > second ;
return true ;
}
return db . Read ( std : : make_pair ( SUPPORT , name ) , node ) ;
}
2015-11-25 18:04:32 +01:00
bool CClaimTrie : : getSupportQueueRow ( int nHeight , supportQueueRowType & row ) const
2015-09-25 23:09:21 +02:00
{
2015-11-25 18:04:32 +01:00
supportQueueType : : const_iterator itQueueRow = dirtySupportQueueRows . find ( nHeight ) ;
2015-09-25 23:09:21 +02:00
if ( itQueueRow ! = dirtySupportQueueRows . end ( ) )
{
row = itQueueRow - > second ;
return true ;
}
2015-11-25 18:04:32 +01:00
return db . Read ( std : : make_pair ( SUPPORT_QUEUE_ROW , nHeight ) , row ) ;
}
2016-01-05 01:04:55 +01:00
bool CClaimTrie : : getSupportQueueNameRow ( const std : : string & name , queueNameRowType & row ) const
2015-11-25 18:04:32 +01:00
{
2016-01-05 01:04:55 +01:00
queueNameType : : const_iterator itQueueNameRow = dirtySupportQueueNameRows . find ( name ) ;
2015-11-25 18:04:32 +01:00
if ( itQueueNameRow ! = dirtySupportQueueNameRows . end ( ) )
{
row = itQueueNameRow - > second ;
return true ;
}
return db . Read ( std : : make_pair ( SUPPORT_QUEUE_NAME_ROW , name ) , row ) ;
2015-09-25 23:09:21 +02:00
}
2016-01-05 01:04:55 +01:00
bool CClaimTrie : : getSupportExpirationQueueRow ( int nHeight , expirationQueueRowType & row ) const
2015-12-29 19:50:11 +01:00
{
2016-01-05 01:04:55 +01:00
expirationQueueType : : const_iterator itQueueRow = dirtySupportExpirationQueueRows . find ( nHeight ) ;
2015-12-29 19:50:11 +01:00
if ( itQueueRow ! = dirtySupportExpirationQueueRows . end ( ) )
{
row = itQueueRow - > second ;
return true ;
}
return db . Read ( std : : make_pair ( SUPPORT_EXP_QUEUE_ROW , nHeight ) , row ) ;
}
2016-01-05 01:04:55 +01:00
bool CClaimTrie : : update ( nodeCacheType & cache , hashMapType & hashes , std : : map < std : : string , int > & takeoverHeights , const uint256 & hashBlockIn , claimQueueType & queueCache , queueNameType & queueNameCache , expirationQueueType & expirationQueueCache , int nNewHeight , supportMapType & supportCache , supportQueueType & supportQueueCache , queueNameType & supportQueueNameCache , expirationQueueType & supportExpirationQueueCache )
2015-02-03 02:57:53 +01:00
{
for ( nodeCacheType : : iterator itcache = cache . begin ( ) ; itcache ! = cache . end ( ) ; + + itcache )
{
2015-12-06 03:55:23 +01:00
if ( ! updateName ( itcache - > first , itcache - > second ) )
2015-02-03 02:57:53 +01:00
return false ;
}
for ( hashMapType : : iterator ithash = hashes . begin ( ) ; ithash ! = hashes . end ( ) ; + + ithash )
{
2015-12-06 03:55:23 +01:00
if ( ! updateHash ( ithash - > first , ithash - > second ) )
return false ;
}
for ( std : : map < std : : string , int > : : iterator itheight = takeoverHeights . begin ( ) ; itheight ! = takeoverHeights . end ( ) ; + + itheight )
{
if ( ! updateTakeoverHeight ( itheight - > first , itheight - > second ) )
2015-02-03 02:57:53 +01:00
return false ;
}
2015-11-25 18:04:32 +01:00
for ( claimQueueType : : iterator itQueueCacheRow = queueCache . begin ( ) ; itQueueCacheRow ! = queueCache . end ( ) ; + + itQueueCacheRow )
2015-03-17 06:16:37 +01:00
{
2015-05-21 19:50:40 +02:00
updateQueueRow ( itQueueCacheRow - > first , itQueueCacheRow - > second ) ;
2015-03-17 06:16:37 +01:00
}
2016-01-05 01:04:55 +01:00
for ( queueNameType : : iterator itQueueNameCacheRow = queueNameCache . begin ( ) ; itQueueNameCacheRow ! = queueNameCache . end ( ) ; + + itQueueNameCacheRow )
2015-11-25 18:04:32 +01:00
{
updateQueueNameRow ( itQueueNameCacheRow - > first , itQueueNameCacheRow - > second ) ;
}
2016-01-05 01:04:55 +01:00
for ( expirationQueueType : : iterator itExpirationRow = expirationQueueCache . begin ( ) ; itExpirationRow ! = expirationQueueCache . end ( ) ; + + itExpirationRow )
2015-05-27 23:53:12 +02:00
{
updateExpirationRow ( itExpirationRow - > first , itExpirationRow - > second ) ;
}
2015-09-25 23:09:21 +02:00
for ( supportMapType : : iterator itSupportCache = supportCache . begin ( ) ; itSupportCache ! = supportCache . end ( ) ; + + itSupportCache )
{
updateSupportMap ( itSupportCache - > first , itSupportCache - > second ) ;
}
2015-11-25 18:04:32 +01:00
for ( supportQueueType : : iterator itSupportQueue = supportQueueCache . begin ( ) ; itSupportQueue ! = supportQueueCache . end ( ) ; + + itSupportQueue )
2015-09-25 23:09:21 +02:00
{
updateSupportQueue ( itSupportQueue - > first , itSupportQueue - > second ) ;
}
2016-01-05 01:04:55 +01:00
for ( queueNameType : : iterator itSupportNameQueue = supportQueueNameCache . begin ( ) ; itSupportNameQueue ! = supportQueueNameCache . end ( ) ; + + itSupportNameQueue )
2015-11-25 18:04:32 +01:00
{
updateSupportNameQueue ( itSupportNameQueue - > first , itSupportNameQueue - > second ) ;
}
2016-01-05 01:04:55 +01:00
for ( expirationQueueType : : iterator itSupportExpirationQueue = supportExpirationQueueCache . begin ( ) ; itSupportExpirationQueue ! = supportExpirationQueueCache . end ( ) ; + + itSupportExpirationQueue )
2015-12-29 19:50:11 +01:00
{
updateSupportExpirationQueue ( itSupportExpirationQueue - > first , itSupportExpirationQueue - > second ) ;
}
2015-02-10 21:30:40 +01:00
hashBlock = hashBlockIn ;
2015-03-17 06:16:37 +01:00
nCurrentHeight = nNewHeight ;
2015-02-03 02:57:53 +01:00
return true ;
}
2015-09-24 07:15:28 +02:00
void CClaimTrie : : markNodeDirty ( const std : : string & name , CClaimTrieNode * node )
2015-03-23 19:51:29 +01:00
{
std : : pair < nodeCacheType : : iterator , bool > ret ;
2015-09-24 07:15:28 +02:00
ret = dirtyNodes . insert ( std : : pair < std : : string , CClaimTrieNode * > ( name , node ) ) ;
2015-03-23 19:51:29 +01:00
if ( ret . second = = false )
ret . first - > second = node ;
}
2015-09-24 07:15:28 +02:00
bool CClaimTrie : : updateName ( const std : : string & name , CClaimTrieNode * updatedNode )
2015-02-03 02:57:53 +01:00
{
2015-09-24 07:15:28 +02:00
CClaimTrieNode * current = & root ;
2015-02-03 02:57:53 +01:00
for ( std : : string : : const_iterator itname = name . begin ( ) ; itname ! = name . end ( ) ; + + itname )
{
nodeMapType : : iterator itchild = current - > children . find ( * itname ) ;
if ( itchild = = current - > children . end ( ) )
{
if ( itname + 1 = = name . end ( ) )
{
2015-09-24 07:15:28 +02:00
CClaimTrieNode * newNode = new CClaimTrieNode ( ) ;
2015-02-03 02:57:53 +01:00
current - > children [ * itname ] = newNode ;
current = newNode ;
}
else
return false ;
}
else
{
current = itchild - > second ;
}
}
assert ( current ! = NULL ) ;
2015-11-25 18:04:32 +01:00
current - > claims . swap ( updatedNode - > claims ) ;
2015-03-23 19:51:29 +01:00
markNodeDirty ( name , current ) ;
2015-02-03 02:57:53 +01:00
for ( nodeMapType : : iterator itchild = current - > children . begin ( ) ; itchild ! = current - > children . end ( ) ; )
{
nodeMapType : : iterator itupdatechild = updatedNode - > children . find ( itchild - > first ) ;
if ( itupdatechild = = updatedNode - > children . end ( ) )
{
// This character has apparently been deleted, so delete
// all descendents from this child.
std : : stringstream ss ;
ss < < name < < itchild - > first ;
std : : string newName = ss . str ( ) ;
2015-03-23 19:51:29 +01:00
if ( ! recursiveNullify ( itchild - > second , newName ) )
2015-02-03 02:57:53 +01:00
return false ;
current - > children . erase ( itchild + + ) ;
}
else
+ + itchild ;
}
return true ;
}
2015-09-24 07:15:28 +02:00
bool CClaimTrie : : recursiveNullify ( CClaimTrieNode * node , std : : string & name )
2015-02-03 02:57:53 +01:00
{
assert ( node ! = NULL ) ;
for ( nodeMapType : : iterator itchild = node - > children . begin ( ) ; itchild ! = node - > children . end ( ) ; + + itchild )
{
std : : stringstream ss ;
ss < < name < < itchild - > first ;
std : : string newName = ss . str ( ) ;
2015-03-23 19:51:29 +01:00
if ( ! recursiveNullify ( itchild - > second , newName ) )
2015-02-03 02:57:53 +01:00
return false ;
}
node - > children . clear ( ) ;
2015-03-23 19:51:29 +01:00
markNodeDirty ( name , NULL ) ;
2015-02-03 02:57:53 +01:00
delete node ;
return true ;
}
2015-09-24 07:15:28 +02:00
bool CClaimTrie : : updateHash ( const std : : string & name , uint256 & hash )
2015-02-03 02:57:53 +01:00
{
2015-09-24 07:15:28 +02:00
CClaimTrieNode * current = & root ;
2015-02-03 02:57:53 +01:00
for ( std : : string : : const_iterator itname = name . begin ( ) ; itname ! = name . end ( ) ; + + itname )
{
nodeMapType : : iterator itchild = current - > children . find ( * itname ) ;
if ( itchild = = current - > children . end ( ) )
return false ;
current = itchild - > second ;
}
assert ( current ! = NULL ) ;
current - > hash = hash ;
2015-03-23 19:51:29 +01:00
markNodeDirty ( name , current ) ;
2015-02-03 02:57:53 +01:00
return true ;
}
2015-12-06 03:55:23 +01:00
bool CClaimTrie : : updateTakeoverHeight ( const std : : string & name , int nTakeoverHeight )
{
CClaimTrieNode * current = & root ;
for ( std : : string : : const_iterator itname = name . begin ( ) ; itname ! = name . end ( ) ; + + itname )
{
nodeMapType : : iterator itchild = current - > children . find ( * itname ) ;
if ( itchild = = current - > children . end ( ) )
return false ;
current = itchild - > second ;
}
assert ( current ! = NULL ) ;
current - > nHeightOfLastTakeover = nTakeoverHeight ;
markNodeDirty ( name , current ) ;
return true ;
}
2015-09-24 07:15:28 +02:00
void CClaimTrie : : BatchWriteNode ( CLevelDBBatch & batch , const std : : string & name , const CClaimTrieNode * pNode ) const
2015-02-03 02:57:53 +01:00
{
2015-11-25 18:04:32 +01:00
uint32_t num_claims = 0 ;
2015-10-22 05:35:30 +02:00
if ( pNode )
2015-11-25 18:04:32 +01:00
num_claims = pNode - > claims . size ( ) ;
LogPrintf ( " %s: Writing %s to disk with %d claims \n " , __func__ , name , num_claims ) ;
2015-03-23 19:51:29 +01:00
if ( pNode )
2015-09-25 23:09:21 +02:00
batch . Write ( std : : make_pair ( TRIE_NODE , name ) , * pNode ) ;
2015-03-23 19:51:29 +01:00
else
2015-09-25 23:09:21 +02:00
batch . Erase ( std : : make_pair ( TRIE_NODE , name ) ) ;
2015-02-03 02:57:53 +01:00
}
2015-09-24 07:15:28 +02:00
void CClaimTrie : : BatchWriteQueueRows ( CLevelDBBatch & batch )
2015-03-17 06:16:37 +01:00
{
2015-11-25 18:04:32 +01:00
for ( claimQueueType : : iterator itQueue = dirtyQueueRows . begin ( ) ; itQueue ! = dirtyQueueRows . end ( ) ; + + itQueue )
2015-05-21 19:50:40 +02:00
{
if ( itQueue - > second . empty ( ) )
{
2015-11-25 18:04:32 +01:00
batch . Erase ( std : : make_pair ( CLAIM_QUEUE_ROW , itQueue - > first ) ) ;
2015-05-21 19:50:40 +02:00
}
else
{
2015-11-25 18:04:32 +01:00
batch . Write ( std : : make_pair ( CLAIM_QUEUE_ROW , itQueue - > first ) , itQueue - > second ) ;
}
}
}
void CClaimTrie : : BatchWriteQueueNameRows ( CLevelDBBatch & batch )
{
2016-01-05 01:04:55 +01:00
for ( queueNameType : : iterator itQueue = dirtyQueueNameRows . begin ( ) ; itQueue ! = dirtyQueueNameRows . end ( ) ; + + itQueue )
2015-11-25 18:04:32 +01:00
{
if ( itQueue - > second . empty ( ) )
{
batch . Erase ( std : : make_pair ( CLAIM_QUEUE_NAME_ROW , itQueue - > first ) ) ;
}
else
{
batch . Write ( std : : make_pair ( CLAIM_QUEUE_NAME_ROW , itQueue - > first ) , itQueue - > second ) ;
2015-05-21 19:50:40 +02:00
}
}
2015-03-17 06:16:37 +01:00
}
2015-09-24 07:15:28 +02:00
void CClaimTrie : : BatchWriteExpirationQueueRows ( CLevelDBBatch & batch )
2015-05-27 23:53:12 +02:00
{
2016-01-05 01:04:55 +01:00
for ( expirationQueueType : : iterator itQueue = dirtyExpirationQueueRows . begin ( ) ; itQueue ! = dirtyExpirationQueueRows . end ( ) ; + + itQueue )
2015-05-27 23:53:12 +02:00
{
if ( itQueue - > second . empty ( ) )
{
2015-09-25 23:09:21 +02:00
batch . Erase ( std : : make_pair ( EXP_QUEUE_ROW , itQueue - > first ) ) ;
}
else
{
batch . Write ( std : : make_pair ( EXP_QUEUE_ROW , itQueue - > first ) , itQueue - > second ) ;
}
}
}
void CClaimTrie : : BatchWriteSupportNodes ( CLevelDBBatch & batch )
{
for ( supportMapType : : iterator itSupport = dirtySupportNodes . begin ( ) ; itSupport ! = dirtySupportNodes . end ( ) ; + + itSupport )
{
if ( itSupport - > second . empty ( ) )
{
batch . Erase ( std : : make_pair ( SUPPORT , itSupport - > first ) ) ;
2015-05-27 23:53:12 +02:00
}
else
{
2015-09-25 23:09:21 +02:00
batch . Write ( std : : make_pair ( SUPPORT , itSupport - > first ) , itSupport - > second ) ;
}
}
}
void CClaimTrie : : BatchWriteSupportQueueRows ( CLevelDBBatch & batch )
{
2015-11-25 18:04:32 +01:00
for ( supportQueueType : : iterator itQueue = dirtySupportQueueRows . begin ( ) ; itQueue ! = dirtySupportQueueRows . end ( ) ; + + itQueue )
2015-09-25 23:09:21 +02:00
{
if ( itQueue - > second . empty ( ) )
{
2015-11-25 18:04:32 +01:00
batch . Erase ( std : : make_pair ( SUPPORT_QUEUE_ROW , itQueue - > first ) ) ;
2015-09-25 23:09:21 +02:00
}
else
{
2015-11-25 18:04:32 +01:00
batch . Write ( std : : make_pair ( SUPPORT_QUEUE_ROW , itQueue - > first ) , itQueue - > second ) ;
}
}
}
void CClaimTrie : : BatchWriteSupportQueueNameRows ( CLevelDBBatch & batch )
{
2016-01-05 01:04:55 +01:00
for ( queueNameType : : iterator itQueue = dirtySupportQueueNameRows . begin ( ) ; itQueue ! = dirtySupportQueueNameRows . end ( ) ; + + itQueue )
2015-11-25 18:04:32 +01:00
{
if ( itQueue - > second . empty ( ) )
{
batch . Erase ( std : : make_pair ( SUPPORT_QUEUE_NAME_ROW , itQueue - > first ) ) ;
}
else
{
batch . Write ( std : : make_pair ( SUPPORT_QUEUE_NAME_ROW , itQueue - > first ) , itQueue - > second ) ;
2015-05-27 23:53:12 +02:00
}
}
}
2015-12-29 19:50:11 +01:00
void CClaimTrie : : BatchWriteSupportExpirationQueueRows ( CLevelDBBatch & batch )
{
2016-01-05 01:04:55 +01:00
for ( expirationQueueType : : iterator itQueue = dirtySupportExpirationQueueRows . begin ( ) ; itQueue ! = dirtySupportExpirationQueueRows . end ( ) ; + + itQueue )
2015-12-29 19:50:11 +01:00
{
if ( itQueue - > second . empty ( ) )
{
batch . Erase ( std : : make_pair ( SUPPORT_EXP_QUEUE_ROW , itQueue - > first ) ) ;
}
else
{
batch . Write ( std : : make_pair ( SUPPORT_EXP_QUEUE_ROW , itQueue - > first ) , itQueue - > second ) ;
}
}
}
2015-09-24 07:15:28 +02:00
bool CClaimTrie : : WriteToDisk ( )
2015-02-03 02:57:53 +01:00
{
2015-10-22 04:30:56 +02:00
CLevelDBBatch batch ( & db . GetObfuscateKey ( ) ) ;
2015-03-23 19:51:29 +01:00
for ( nodeCacheType : : iterator itcache = dirtyNodes . begin ( ) ; itcache ! = dirtyNodes . end ( ) ; + + itcache )
2015-02-03 02:57:53 +01:00
BatchWriteNode ( batch , itcache - > first , itcache - > second ) ;
2015-03-23 19:51:29 +01:00
dirtyNodes . clear ( ) ;
2015-05-21 19:50:40 +02:00
BatchWriteQueueRows ( batch ) ;
dirtyQueueRows . clear ( ) ;
2015-11-25 18:04:32 +01:00
BatchWriteQueueNameRows ( batch ) ;
dirtyQueueNameRows . clear ( ) ;
2015-05-27 23:53:12 +02:00
BatchWriteExpirationQueueRows ( batch ) ;
dirtyExpirationQueueRows . clear ( ) ;
2015-09-25 23:09:21 +02:00
BatchWriteSupportNodes ( batch ) ;
dirtySupportNodes . clear ( ) ;
BatchWriteSupportQueueRows ( batch ) ;
dirtySupportQueueRows . clear ( ) ;
2015-11-25 18:04:32 +01:00
BatchWriteSupportQueueNameRows ( batch ) ;
dirtySupportQueueNameRows . clear ( ) ;
2016-01-05 01:04:55 +01:00
BatchWriteSupportExpirationQueueRows ( batch ) ;
dirtySupportExpirationQueueRows . clear ( ) ;
2015-09-25 23:09:21 +02:00
batch . Write ( HASH_BLOCK , hashBlock ) ;
batch . Write ( CURRENT_HEIGHT , nCurrentHeight ) ;
2015-02-03 02:57:53 +01:00
return db . WriteBatch ( batch ) ;
}
2015-09-24 07:15:28 +02:00
bool CClaimTrie : : InsertFromDisk ( const std : : string & name , CClaimTrieNode * node )
2015-02-05 20:24:09 +01:00
{
if ( name . size ( ) = = 0 )
2015-02-10 17:19:41 +01:00
{
2015-02-05 20:24:09 +01:00
root = * node ;
return true ;
2015-02-10 17:19:41 +01:00
}
2015-09-24 07:15:28 +02:00
CClaimTrieNode * current = & root ;
2015-02-05 20:24:09 +01:00
for ( std : : string : : const_iterator itname = name . begin ( ) ; itname + 1 ! = name . end ( ) ; + + itname )
{
nodeMapType : : iterator itchild = current - > children . find ( * itname ) ;
if ( itchild = = current - > children . end ( ) )
return false ;
current = itchild - > second ;
}
current - > children [ name [ name . size ( ) - 1 ] ] = node ;
return true ;
}
2015-09-24 07:15:28 +02:00
bool CClaimTrie : : ReadFromDisk ( bool check )
2015-02-05 20:24:09 +01:00
{
2015-09-25 23:09:21 +02:00
if ( ! db . Read ( HASH_BLOCK , hashBlock ) )
2015-02-10 21:30:40 +01:00
LogPrintf ( " %s: Couldn't read the best block's hash \n " , __func__ ) ;
2015-09-25 23:09:21 +02:00
if ( ! db . Read ( CURRENT_HEIGHT , nCurrentHeight ) )
2015-03-19 17:57:56 +01:00
LogPrintf ( " %s: Couldn't read the current height \n " , __func__ ) ;
2015-10-22 04:30:56 +02:00
boost : : scoped_ptr < CLevelDBIterator > pcursor ( const_cast < CLevelDBWrapper * > ( & db ) - > NewIterator ( ) ) ;
2015-02-05 20:24:09 +01:00
pcursor - > SeekToFirst ( ) ;
while ( pcursor - > Valid ( ) )
{
2015-10-22 04:30:56 +02:00
std : : pair < char , std : : string > key ;
if ( pcursor - > GetKey ( key ) )
2015-02-05 20:24:09 +01:00
{
2015-10-22 04:30:56 +02:00
if ( key . first = = TRIE_NODE )
2015-02-05 20:24:09 +01:00
{
2015-09-24 07:15:28 +02:00
CClaimTrieNode * node = new CClaimTrieNode ( ) ;
2015-10-22 04:30:56 +02:00
if ( pcursor - > GetValue ( * node ) )
{
if ( ! InsertFromDisk ( key . second , node ) )
{
return error ( " %s() : error restoring claim trie from disk " , __func__) ;
}
}
else
{
return error ( " %s() : error reading claim trie from disk " , __func__) ;
}
2015-02-05 20:24:09 +01:00
}
2015-02-10 17:19:41 +01:00
}
2015-10-22 04:30:56 +02:00
pcursor - > Next ( ) ;
2015-02-05 20:24:09 +01:00
}
if ( check )
2015-02-10 17:19:41 +01:00
{
2015-09-24 07:15:28 +02:00
LogPrintf ( " Checking Claim trie consistency... " ) ;
2015-03-17 06:16:37 +01:00
if ( checkConsistency ( ) )
2015-02-10 17:19:41 +01:00
{
LogPrintf ( " consistent \n " ) ;
return true ;
}
LogPrintf ( " inconsistent! \n " ) ;
return false ;
}
2015-02-05 20:24:09 +01:00
return true ;
}
2015-09-24 07:15:28 +02:00
bool CClaimTrieCache : : recursiveComputeMerkleHash ( CClaimTrieNode * tnCurrent , std : : string sPos ) const
2015-02-03 02:57:53 +01:00
{
2015-02-10 17:19:41 +01:00
if ( sPos = = " " & & tnCurrent - > empty ( ) )
{
cacheHashes [ " " ] = uint256S ( " 0000000000000000000000000000000000000000000000000000000000000001 " ) ;
return true ;
}
2015-03-26 03:10:05 +01:00
std : : vector < unsigned char > vchToHash ;
2015-02-03 02:57:53 +01:00
nodeCacheType : : iterator cachedNode ;
for ( nodeMapType : : iterator it = tnCurrent - > children . begin ( ) ; it ! = tnCurrent - > children . end ( ) ; + + it )
{
std : : stringstream ss ;
ss < < it - > first ;
std : : string sNextPos = sPos + ss . str ( ) ;
if ( dirtyHashes . count ( sNextPos ) ! = 0 )
{
// the child might be in the cache, so look for it there
cachedNode = cache . find ( sNextPos ) ;
if ( cachedNode ! = cache . end ( ) )
recursiveComputeMerkleHash ( cachedNode - > second , sNextPos ) ;
else
recursiveComputeMerkleHash ( it - > second , sNextPos ) ;
}
2015-03-26 03:10:05 +01:00
vchToHash . push_back ( it - > first ) ;
2015-02-03 02:57:53 +01:00
hashMapType : : iterator ithash = cacheHashes . find ( sNextPos ) ;
if ( ithash ! = cacheHashes . end ( ) )
2015-03-26 03:10:05 +01:00
{
vchToHash . insert ( vchToHash . end ( ) , ithash - > second . begin ( ) , ithash - > second . end ( ) ) ;
}
2015-02-03 02:57:53 +01:00
else
2015-03-26 03:10:05 +01:00
{
vchToHash . insert ( vchToHash . end ( ) , it - > second - > hash . begin ( ) , it - > second - > hash . end ( ) ) ;
}
2015-02-03 02:57:53 +01:00
}
2015-02-23 23:51:52 +01:00
2015-11-25 18:04:32 +01:00
CClaimValue claim ;
bool hasClaim = tnCurrent - > getBestClaim ( claim ) ;
2015-02-23 23:51:52 +01:00
2015-11-25 18:04:32 +01:00
if ( hasClaim )
2015-02-23 23:51:52 +01:00
{
2015-11-25 18:04:32 +01:00
uint256 claimHash = claim . GetHash ( ) ;
vchToHash . insert ( vchToHash . end ( ) , claimHash . begin ( ) , claimHash . end ( ) ) ;
2015-12-06 03:55:23 +01:00
int nHeightOfLastTakeover ;
assert ( getLastTakeoverForName ( sPos , nHeightOfLastTakeover ) ) ;
std : : vector < unsigned char > heightToHash = heightToVch ( nHeightOfLastTakeover ) ;
vchToHash . insert ( vchToHash . end ( ) , heightToHash . begin ( ) , heightToHash . end ( ) ) ;
2015-02-23 23:51:52 +01:00
}
2015-02-03 02:57:53 +01:00
CHash256 hasher ;
std : : vector < unsigned char > vchHash ( hasher . OUTPUT_SIZE ) ;
2015-03-26 03:10:05 +01:00
hasher . Write ( vchToHash . data ( ) , vchToHash . size ( ) ) ;
2015-02-03 02:57:53 +01:00
hasher . Finalize ( & ( vchHash [ 0 ] ) ) ;
cacheHashes [ sPos ] = uint256 ( vchHash ) ;
std : : set < std : : string > : : iterator itDirty = dirtyHashes . find ( sPos ) ;
if ( itDirty ! = dirtyHashes . end ( ) )
dirtyHashes . erase ( itDirty ) ;
return true ;
}
2015-09-24 07:15:28 +02:00
uint256 CClaimTrieCache : : getMerkleHash ( ) const
2015-02-03 02:57:53 +01:00
{
if ( empty ( ) )
{
uint256 one ( uint256S ( " 0000000000000000000000000000000000000000000000000000000000000001 " ) ) ;
return one ;
}
if ( dirty ( ) )
{
nodeCacheType : : iterator cachedNode = cache . find ( " " ) ;
if ( cachedNode ! = cache . end ( ) )
recursiveComputeMerkleHash ( cachedNode - > second , " " ) ;
else
recursiveComputeMerkleHash ( & ( base - > root ) , " " ) ;
}
hashMapType : : iterator ithash = cacheHashes . find ( " " ) ;
if ( ithash ! = cacheHashes . end ( ) )
return ithash - > second ;
else
return base - > root . hash ;
}
2015-09-24 07:15:28 +02:00
bool CClaimTrieCache : : empty ( ) const
2015-02-03 02:57:53 +01:00
{
2015-02-10 21:30:40 +01:00
return base - > empty ( ) & & cache . empty ( ) ;
2015-02-03 02:57:53 +01:00
}
2015-12-23 20:12:32 +01:00
bool CClaimTrieCache : : insertClaimIntoTrie ( const std : : string & name , CClaimValue claim , bool fCheckTakeover ) const
2015-02-03 02:57:53 +01:00
{
2015-02-05 20:24:09 +01:00
assert ( base ) ;
2015-09-24 07:15:28 +02:00
CClaimTrieNode * currentNode = & ( base - > root ) ;
2015-02-03 02:57:53 +01:00
nodeCacheType : : iterator cachedNode ;
cachedNode = cache . find ( " " ) ;
if ( cachedNode ! = cache . end ( ) )
currentNode = cachedNode - > second ;
if ( currentNode = = NULL )
{
2015-09-24 07:15:28 +02:00
currentNode = new CClaimTrieNode ( ) ;
2015-02-03 02:57:53 +01:00
cache [ " " ] = currentNode ;
}
for ( std : : string : : const_iterator itCur = name . begin ( ) ; itCur ! = name . end ( ) ; + + itCur )
{
std : : string sCurrentSubstring ( name . begin ( ) , itCur ) ;
std : : string sNextSubstring ( name . begin ( ) , itCur + 1 ) ;
cachedNode = cache . find ( sNextSubstring ) ;
if ( cachedNode ! = cache . end ( ) )
{
currentNode = cachedNode - > second ;
continue ;
}
nodeMapType : : iterator childNode = currentNode - > children . find ( * itCur ) ;
if ( childNode ! = currentNode - > children . end ( ) )
{
currentNode = childNode - > second ;
continue ;
}
// This next substring doesn't exist in the cache and the next
// character doesn't exist in current node's children, so check
// if the current node is in the cache, and if it's not, copy
// it and stick it in the cache, and then create a new node as
// its child and stick that in the cache. We have to have both
// this node and its child in the cache so that the current
// node's child map will contain the next letter, which will be
// used to find the child in the cache. This is necessary in
// order to calculate the merkle hash.
cachedNode = cache . find ( sCurrentSubstring ) ;
if ( cachedNode ! = cache . end ( ) )
{
assert ( cachedNode - > second = = currentNode ) ;
}
else
{
2015-09-24 07:15:28 +02:00
currentNode = new CClaimTrieNode ( * currentNode ) ;
2015-02-03 02:57:53 +01:00
cache [ sCurrentSubstring ] = currentNode ;
}
2015-09-24 07:15:28 +02:00
CClaimTrieNode * newNode = new CClaimTrieNode ( ) ;
2015-02-03 02:57:53 +01:00
currentNode - > children [ * itCur ] = newNode ;
cache [ sNextSubstring ] = newNode ;
currentNode = newNode ;
}
cachedNode = cache . find ( name ) ;
if ( cachedNode ! = cache . end ( ) )
{
assert ( cachedNode - > second = = currentNode ) ;
}
else
{
2015-09-24 07:15:28 +02:00
currentNode = new CClaimTrieNode ( * currentNode ) ;
2015-02-03 02:57:53 +01:00
cache [ name ] = currentNode ;
}
bool fChanged = false ;
2015-11-25 18:04:32 +01:00
if ( currentNode - > claims . empty ( ) )
2015-09-25 23:09:21 +02:00
{
fChanged = true ;
2015-11-25 18:04:32 +01:00
currentNode - > insertClaim ( claim ) ;
2015-09-25 23:09:21 +02:00
}
else
{
2015-11-25 18:04:32 +01:00
CClaimValue currentTop = currentNode - > claims . front ( ) ;
currentNode - > insertClaim ( claim ) ;
supportMapEntryType node ;
2015-09-28 00:24:46 +02:00
getSupportsForName ( name , node ) ;
2015-11-25 18:04:32 +01:00
currentNode - > reorderClaims ( node ) ;
if ( currentTop ! = currentNode - > claims . front ( ) )
2015-09-25 23:09:21 +02:00
fChanged = true ;
}
2015-02-03 02:57:53 +01:00
if ( fChanged )
{
for ( std : : string : : const_iterator itCur = name . begin ( ) ; itCur ! = name . end ( ) ; + + itCur )
{
std : : string sub ( name . begin ( ) , itCur ) ;
dirtyHashes . insert ( sub ) ;
}
dirtyHashes . insert ( name ) ;
2015-12-06 03:55:23 +01:00
if ( fCheckTakeover )
namesToCheckForTakeover . insert ( name ) ;
2015-02-03 02:57:53 +01:00
}
return true ;
}
2015-12-23 20:12:32 +01:00
bool CClaimTrieCache : : removeClaimFromTrie ( const std : : string & name , const COutPoint & outPoint , CClaimValue & claim , bool fCheckTakeover ) const
2015-02-03 02:57:53 +01:00
{
2015-02-05 20:24:09 +01:00
assert ( base ) ;
2015-09-24 07:15:28 +02:00
CClaimTrieNode * currentNode = & ( base - > root ) ;
2015-02-05 20:24:09 +01:00
nodeCacheType : : iterator cachedNode ;
cachedNode = cache . find ( " " ) ;
if ( cachedNode ! = cache . end ( ) )
currentNode = cachedNode - > second ;
assert ( currentNode ! = NULL ) ; // If there is no root in either the trie or the cache, how can there be any names to remove?
for ( std : : string : : const_iterator itCur = name . begin ( ) ; itCur ! = name . end ( ) ; + + itCur )
2015-02-03 02:57:53 +01:00
{
std : : string sCurrentSubstring ( name . begin ( ) , itCur ) ;
std : : string sNextSubstring ( name . begin ( ) , itCur + 1 ) ;
cachedNode = cache . find ( sNextSubstring ) ;
if ( cachedNode ! = cache . end ( ) )
{
currentNode = cachedNode - > second ;
continue ;
}
nodeMapType : : iterator childNode = currentNode - > children . find ( * itCur ) ;
if ( childNode ! = currentNode - > children . end ( ) )
{
currentNode = childNode - > second ;
continue ;
}
2015-02-10 17:19:41 +01:00
LogPrintf ( " %s: The name %s does not exist in the trie \n " , __func__ , name . c_str ( ) ) ;
2015-02-03 02:57:53 +01:00
return false ;
}
cachedNode = cache . find ( name ) ;
if ( cachedNode ! = cache . end ( ) )
assert ( cachedNode - > second = = currentNode ) ;
else
{
2015-09-24 07:15:28 +02:00
currentNode = new CClaimTrieNode ( * currentNode ) ;
2015-02-03 02:57:53 +01:00
cache [ name ] = currentNode ;
}
bool fChanged = false ;
assert ( currentNode ! = NULL ) ;
2015-09-25 23:09:21 +02:00
bool success = false ;
2015-11-25 18:04:32 +01:00
if ( currentNode - > claims . empty ( ) )
2015-09-25 23:09:21 +02:00
{
2015-11-25 18:04:32 +01:00
LogPrintf ( " %s: Asked to remove claim from node without claims \n " , __func__ ) ;
2015-09-25 23:09:21 +02:00
return false ;
}
2015-11-25 18:04:32 +01:00
CClaimValue currentTop = currentNode - > claims . front ( ) ;
2015-09-25 23:09:21 +02:00
2015-12-23 20:12:32 +01:00
success = currentNode - > removeClaim ( outPoint , claim ) ;
2015-09-25 23:09:21 +02:00
2015-11-25 18:04:32 +01:00
if ( ! currentNode - > claims . empty ( ) )
2015-09-25 23:09:21 +02:00
{
2015-11-25 18:04:32 +01:00
supportMapEntryType node ;
2015-09-28 00:24:46 +02:00
getSupportsForName ( name , node ) ;
2015-11-25 18:04:32 +01:00
currentNode - > reorderClaims ( node ) ;
if ( currentTop ! = currentNode - > claims . front ( ) )
2015-09-25 23:09:21 +02:00
fChanged = true ;
}
else
fChanged = true ;
2015-03-09 01:24:13 +01:00
if ( ! success )
{
2015-12-23 20:12:32 +01:00
LogPrintf ( " %s: Removing a claim was unsuccessful. name = %s, txhash = %s, nOut = %d " , __func__ , name . c_str ( ) , outPoint . hash . GetHex ( ) , outPoint . n ) ;
2015-12-10 05:37:16 +01:00
return false ;
2015-03-09 01:24:13 +01:00
}
2015-12-23 20:12:32 +01:00
2015-02-03 02:57:53 +01:00
if ( fChanged )
{
for ( std : : string : : const_iterator itCur = name . begin ( ) ; itCur ! = name . end ( ) ; + + itCur )
{
std : : string sub ( name . begin ( ) , itCur ) ;
dirtyHashes . insert ( sub ) ;
}
dirtyHashes . insert ( name ) ;
2015-12-06 03:55:23 +01:00
if ( fCheckTakeover )
namesToCheckForTakeover . insert ( name ) ;
2015-02-03 02:57:53 +01:00
}
2015-09-24 07:15:28 +02:00
CClaimTrieNode * rootNode = & ( base - > root ) ;
2015-02-03 02:57:53 +01:00
cachedNode = cache . find ( " " ) ;
if ( cachedNode ! = cache . end ( ) )
rootNode = cachedNode - > second ;
return recursivePruneName ( rootNode , 0 , name ) ;
}
2015-09-24 07:15:28 +02:00
bool CClaimTrieCache : : recursivePruneName ( CClaimTrieNode * tnCurrent , unsigned int nPos , std : : string sName , bool * pfNullified ) const
2015-02-03 02:57:53 +01:00
{
bool fNullified = false ;
std : : string sCurrentSubstring = sName . substr ( 0 , nPos ) ;
if ( nPos < sName . size ( ) )
{
std : : string sNextSubstring = sName . substr ( 0 , nPos + 1 ) ;
unsigned char cNext = sName . at ( nPos ) ;
2015-09-24 07:15:28 +02:00
CClaimTrieNode * tnNext = NULL ;
2015-02-03 02:57:53 +01:00
nodeCacheType : : iterator cachedNode = cache . find ( sNextSubstring ) ;
if ( cachedNode ! = cache . end ( ) )
tnNext = cachedNode - > second ;
else
{
nodeMapType : : iterator childNode = tnCurrent - > children . find ( cNext ) ;
if ( childNode ! = tnCurrent - > children . end ( ) )
tnNext = childNode - > second ;
}
if ( tnNext = = NULL )
return false ;
bool fChildNullified = false ;
if ( ! recursivePruneName ( tnNext , nPos + 1 , sName , & fChildNullified ) )
return false ;
if ( fChildNullified )
{
// If the child nullified itself, the child should already be
// out of the cache, and the character must now be removed
// from the current node's map of child nodes to ensure that
// it isn't found when calculating the merkle hash. But
// tnCurrent isn't necessarily in the cache. If it's not, it
// has to be added to the cache, so nothing is changed in the
// trie. If the current node is added to the cache, however,
// that does not imply that the parent node must be altered to
// reflect that its child is now in the cache, since it
// already has a character in its child map which will be used
// when calculating the merkle root.
// First, find out if this node is in the cache.
cachedNode = cache . find ( sCurrentSubstring ) ;
if ( cachedNode = = cache . end ( ) )
{
// it isn't, so make a copy, stick it in the cache,
// and make it the new current node
2015-09-24 07:15:28 +02:00
tnCurrent = new CClaimTrieNode ( * tnCurrent ) ;
2015-02-03 02:57:53 +01:00
cache [ sCurrentSubstring ] = tnCurrent ;
}
// erase the character from the current node, which is
// now guaranteed to be in the cache
nodeMapType : : iterator childNode = tnCurrent - > children . find ( cNext ) ;
if ( childNode ! = tnCurrent - > children . end ( ) )
tnCurrent - > children . erase ( childNode ) ;
else
return false ;
}
}
if ( sCurrentSubstring . size ( ) ! = 0 & & tnCurrent - > empty ( ) )
{
// If the current node is in the cache, remove it from there
nodeCacheType : : iterator cachedNode = cache . find ( sCurrentSubstring ) ;
if ( cachedNode ! = cache . end ( ) )
{
assert ( tnCurrent = = cachedNode - > second ) ;
delete tnCurrent ;
cache . erase ( cachedNode ) ;
}
fNullified = true ;
}
if ( pfNullified )
* pfNullified = fNullified ;
return true ;
}
2015-11-25 18:04:32 +01:00
claimQueueType : : iterator CClaimTrieCache : : getQueueCacheRow ( int nHeight , bool createIfNotExists ) const
2015-03-17 06:16:37 +01:00
{
2015-11-25 18:04:32 +01:00
claimQueueType : : iterator itQueueRow = claimQueueCache . find ( nHeight ) ;
if ( itQueueRow = = claimQueueCache . end ( ) )
2015-03-17 06:16:37 +01:00
{
// Have to make a new row it put in the cache, if createIfNotExists is true
2015-11-25 18:04:32 +01:00
claimQueueRowType queueRow ;
// If the row exists in the base, copy its claims into the new row.
2015-05-21 19:50:40 +02:00
bool exists = base - > getQueueRow ( nHeight , queueRow ) ;
if ( ! exists )
2015-03-17 06:16:37 +01:00
if ( ! createIfNotExists )
return itQueueRow ;
// Stick the new row in the cache
2015-11-25 18:04:32 +01:00
std : : pair < claimQueueType : : iterator , bool > ret ;
ret = claimQueueCache . insert ( std : : pair < int , claimQueueRowType > ( nHeight , queueRow ) ) ;
2015-03-17 06:16:37 +01:00
assert ( ret . second ) ;
itQueueRow = ret . first ;
}
return itQueueRow ;
}
2016-01-05 01:04:55 +01:00
queueNameType : : iterator CClaimTrieCache : : getQueueCacheNameRow ( const std : : string & name , bool createIfNotExists ) const
2015-11-25 18:04:32 +01:00
{
2016-01-05 01:04:55 +01:00
queueNameType : : iterator itQueueNameRow = claimQueueNameCache . find ( name ) ;
2015-11-25 18:04:32 +01:00
if ( itQueueNameRow = = claimQueueNameCache . end ( ) )
{
// Have to make a new name row and put it in the cache, if createIfNotExists is true
2016-01-05 01:04:55 +01:00
queueNameRowType queueNameRow ;
2015-11-25 18:04:32 +01:00
// If the row exists in the base, copy its claims into the new row.
bool exists = base - > getQueueNameRow ( name , queueNameRow ) ;
if ( ! exists )
if ( ! createIfNotExists )
return itQueueNameRow ;
// Stick the new row in the cache
2016-01-05 01:04:55 +01:00
std : : pair < queueNameType : : iterator , bool > ret ;
ret = claimQueueNameCache . insert ( std : : pair < std : : string , queueNameRowType > ( name , queueNameRow ) ) ;
2015-11-25 18:04:32 +01:00
assert ( ret . second ) ;
itQueueNameRow = ret . first ;
}
return itQueueNameRow ;
}
2015-12-23 20:12:32 +01:00
bool CClaimTrieCache : : addClaim ( const std : : string & name , const COutPoint & outPoint , uint160 claimId , CAmount nAmount , int nHeight ) const
2015-03-17 06:16:37 +01:00
{
2015-12-23 20:12:32 +01:00
LogPrintf ( " %s: name: %s, txhash: %s, nOut: %d, claimId: %s, nAmount: %d, nHeight: %d, nCurrentHeight: %d \n " , __func__ , name , outPoint . hash . GetHex ( ) , outPoint . n , claimId . GetHex ( ) , nAmount , nHeight , nCurrentHeight ) ;
2015-03-17 06:16:37 +01:00
assert ( nHeight = = nCurrentHeight ) ;
2015-12-06 03:55:23 +01:00
CClaimValue currentClaim ;
2015-12-23 01:11:50 +01:00
int delayForClaim ;
if ( base - > getInfoForName ( name , currentClaim ) & & currentClaim . claimId = = claimId )
2015-03-17 06:16:37 +01:00
{
2015-12-23 01:11:50 +01:00
LogPrintf ( " %s: This is an update to a best claim. \n " , __func__ ) ;
delayForClaim = 0 ;
2015-03-17 06:16:37 +01:00
}
2015-12-23 01:11:50 +01:00
else
{
delayForClaim = getDelayForName ( name ) ;
}
2015-12-23 20:12:32 +01:00
CClaimValue newClaim ( outPoint , claimId , nAmount , nHeight , nHeight + delayForClaim ) ;
2015-12-23 01:11:50 +01:00
return addClaimToQueues ( name , newClaim ) ;
2015-03-17 06:16:37 +01:00
}
2015-12-23 20:12:32 +01:00
bool CClaimTrieCache : : undoSpendClaim ( const std : : string & name , const COutPoint & outPoint , uint160 claimId , CAmount nAmount , int nHeight , int nValidAtHeight ) const
2015-03-17 06:16:37 +01:00
{
2015-12-23 20:12:32 +01:00
LogPrintf ( " %s: name: %s, txhash: %s, nOut: %d, claimId: %s, nAmount: %d, nHeight: %d, nValidAtHeight: %d, nCurrentHeight: %d \n " , __func__ , name , outPoint . hash . GetHex ( ) , outPoint . n , claimId . GetHex ( ) , nAmount , nHeight , nValidAtHeight , nCurrentHeight ) ;
CClaimValue claim ( outPoint , claimId , nAmount , nHeight , nValidAtHeight ) ;
2015-03-17 06:16:37 +01:00
if ( nValidAtHeight < nCurrentHeight )
{
2016-01-05 01:04:55 +01:00
nameOutPointType entry ( name , claim . outPoint ) ;
addToExpirationQueue ( claim . nHeight + base - > nExpirationTime , entry ) ;
2015-12-06 03:55:23 +01:00
return insertClaimIntoTrie ( name , claim , false ) ;
2015-03-17 06:16:37 +01:00
}
else
{
2015-12-06 03:55:23 +01:00
return addClaimToQueues ( name , claim ) ;
2015-03-17 06:16:37 +01:00
}
}
2015-12-23 20:12:32 +01:00
bool CClaimTrieCache : : addClaimToQueues ( const std : : string & name , CClaimValue & claim ) const
2015-03-17 06:16:37 +01:00
{
2015-12-06 03:55:23 +01:00
LogPrintf ( " %s: nValidAtHeight: %d \n " , __func__ , claim . nValidAtHeight ) ;
2015-11-25 18:04:32 +01:00
claimQueueEntryType entry ( name , claim ) ;
2015-12-06 03:55:23 +01:00
claimQueueType : : iterator itQueueRow = getQueueCacheRow ( claim . nValidAtHeight , true ) ;
2016-01-05 01:04:55 +01:00
queueNameType : : iterator itQueueNameRow = getQueueCacheNameRow ( name , true ) ;
2015-03-17 06:16:37 +01:00
itQueueRow - > second . push_back ( entry ) ;
2015-12-31 08:51:09 +01:00
itQueueNameRow - > second . push_back ( outPointHeightType ( claim . outPoint , claim . nValidAtHeight ) ) ;
2016-01-05 01:04:55 +01:00
nameOutPointType expireEntry ( name , claim . outPoint ) ;
addToExpirationQueue ( claim . nHeight + base - > nExpirationTime , expireEntry ) ;
2015-03-17 06:16:37 +01:00
return true ;
}
2015-12-23 20:12:32 +01:00
bool CClaimTrieCache : : removeClaimFromQueue ( const std : : string & name , const COutPoint & outPoint , CClaimValue & claim ) const
2015-03-17 06:16:37 +01:00
{
2016-01-05 01:04:55 +01:00
queueNameType : : iterator itQueueNameRow = getQueueCacheNameRow ( name , false ) ;
2015-11-25 18:04:32 +01:00
if ( itQueueNameRow = = claimQueueNameCache . end ( ) )
2015-03-17 06:16:37 +01:00
{
return false ;
}
2016-01-05 01:04:55 +01:00
queueNameRowType : : iterator itQueueName ;
2015-11-25 18:04:32 +01:00
for ( itQueueName = itQueueNameRow - > second . begin ( ) ; itQueueName ! = itQueueNameRow - > second . end ( ) ; + + itQueueName )
2015-03-17 06:16:37 +01:00
{
2015-12-30 20:30:43 +01:00
if ( itQueueName - > outPoint = = outPoint )
2015-03-17 06:16:37 +01:00
{
break ;
}
}
2015-11-25 18:04:32 +01:00
if ( itQueueName = = itQueueNameRow - > second . end ( ) )
2015-03-17 06:16:37 +01:00
{
2015-11-25 18:04:32 +01:00
return false ;
2015-03-17 06:16:37 +01:00
}
2015-12-31 08:51:09 +01:00
claimQueueType : : iterator itQueueRow = getQueueCacheRow ( itQueueName - > nHeight , false ) ;
2015-11-25 18:04:32 +01:00
if ( itQueueRow ! = claimQueueCache . end ( ) )
{
claimQueueRowType : : iterator itQueue ;
for ( itQueue = itQueueRow - > second . begin ( ) ; itQueue ! = itQueueRow - > second . end ( ) ; + + itQueue )
{
2015-12-23 20:12:32 +01:00
if ( name = = itQueue - > first & & itQueue - > second . outPoint = = outPoint )
2015-11-25 18:04:32 +01:00
{
break ;
}
}
if ( itQueue ! = itQueueRow - > second . end ( ) )
{
2015-12-23 20:12:32 +01:00
std : : swap ( claim , itQueue - > second ) ;
2015-11-25 18:04:32 +01:00
itQueueNameRow - > second . erase ( itQueueName ) ;
itQueueRow - > second . erase ( itQueue ) ;
return true ;
}
}
2015-12-31 08:51:09 +01:00
LogPrintf ( " %s: An inconsistency was found in the claim queue. Please report this to the developers: \n Found in named queue but not in height queue: name: %s, txid: %s, nOut: %d, nValidAtHeight: %d, current height: %d \n " , __func__ , name , outPoint . hash . GetHex ( ) , outPoint . n , itQueueName - > nHeight , nCurrentHeight ) ;
2015-03-17 06:16:37 +01:00
return false ;
}
2015-12-23 20:12:32 +01:00
bool CClaimTrieCache : : undoAddClaim ( const std : : string & name , const COutPoint & outPoint , int nHeight ) const
2015-03-17 06:16:37 +01:00
{
int throwaway ;
2015-12-23 20:12:32 +01:00
return removeClaim ( name , outPoint , nHeight , throwaway , false ) ;
2015-03-17 06:16:37 +01:00
}
2015-12-23 20:12:32 +01:00
bool CClaimTrieCache : : spendClaim ( const std : : string & name , const COutPoint & outPoint , int nHeight , int & nValidAtHeight ) const
2015-03-17 06:16:37 +01:00
{
2015-12-23 20:12:32 +01:00
return removeClaim ( name , outPoint , nHeight , nValidAtHeight , true ) ;
2015-03-17 06:16:37 +01:00
}
2015-12-23 20:12:32 +01:00
bool CClaimTrieCache : : removeClaim ( const std : : string & name , const COutPoint & outPoint , int nHeight , int & nValidAtHeight , bool fCheckTakeover ) const
2015-03-17 06:16:37 +01:00
{
2015-12-23 20:12:32 +01:00
LogPrintf ( " %s: name: %s, txhash: %s, nOut: %s, nHeight: %s, nCurrentHeight: %s \n " , __func__ , name , outPoint . hash . GetHex ( ) , outPoint . n , nHeight , nCurrentHeight ) ;
2015-05-27 23:53:12 +02:00
bool removed = false ;
2015-12-23 20:12:32 +01:00
CClaimValue claim ;
if ( removeClaimFromQueue ( name , outPoint , claim ) )
{
2015-11-25 18:04:32 +01:00
removed = true ;
2015-12-23 20:12:32 +01:00
}
if ( removed = = false & & removeClaimFromTrie ( name , outPoint , claim , fCheckTakeover ) )
{
2015-05-27 23:53:12 +02:00
removed = true ;
2015-12-23 20:12:32 +01:00
}
2015-05-27 23:53:12 +02:00
if ( removed = = true )
2015-12-23 20:12:32 +01:00
{
nValidAtHeight = claim . nValidAtHeight ;
removeFromExpirationQueue ( name , outPoint , nHeight ) ;
}
2015-05-27 23:53:12 +02:00
return removed ;
}
2016-01-05 01:04:55 +01:00
void CClaimTrieCache : : addToExpirationQueue ( int nExpirationHeight , nameOutPointType & entry ) const
2015-05-27 23:53:12 +02:00
{
2016-01-05 01:04:55 +01:00
expirationQueueType : : iterator itQueueRow = getExpirationQueueCacheRow ( nExpirationHeight , true ) ;
2015-05-27 23:53:12 +02:00
itQueueRow - > second . push_back ( entry ) ;
}
2015-12-23 20:12:32 +01:00
void CClaimTrieCache : : removeFromExpirationQueue ( const std : : string & name , const COutPoint & outPoint , int nHeight ) const
2015-05-27 23:53:12 +02:00
{
int expirationHeight = nHeight + base - > nExpirationTime ;
2016-01-05 01:04:55 +01:00
expirationQueueType : : iterator itQueueRow = getExpirationQueueCacheRow ( expirationHeight , false ) ;
expirationQueueRowType : : iterator itQueue ;
if ( itQueueRow ! = expirationQueueCache . end ( ) )
2015-05-27 23:53:12 +02:00
{
for ( itQueue = itQueueRow - > second . begin ( ) ; itQueue ! = itQueueRow - > second . end ( ) ; + + itQueue )
{
2016-01-05 01:04:55 +01:00
if ( name = = itQueue - > name & & outPoint = = itQueue - > outPoint )
2015-05-27 23:53:12 +02:00
break ;
}
}
if ( itQueue ! = itQueueRow - > second . end ( ) )
{
itQueueRow - > second . erase ( itQueue ) ;
2015-03-17 06:16:37 +01:00
}
}
2016-01-05 01:04:55 +01:00
expirationQueueType : : iterator CClaimTrieCache : : getExpirationQueueCacheRow ( int nHeight , bool createIfNotExists ) const
2015-05-27 23:53:12 +02:00
{
2016-01-05 01:04:55 +01:00
expirationQueueType : : iterator itQueueRow = expirationQueueCache . find ( nHeight ) ;
2015-05-27 23:53:12 +02:00
if ( itQueueRow = = expirationQueueCache . end ( ) )
{
// Have to make a new row it put in the cache, if createIfNotExists is true
2016-01-05 01:04:55 +01:00
expirationQueueRowType queueRow ;
2015-11-25 18:04:32 +01:00
// If the row exists in the base, copy its claims into the new row.
2015-05-27 23:53:12 +02:00
bool exists = base - > getExpirationQueueRow ( nHeight , queueRow ) ;
if ( ! exists )
if ( ! createIfNotExists )
return itQueueRow ;
// Stick the new row in the cache
2016-01-05 01:04:55 +01:00
std : : pair < expirationQueueType : : iterator , bool > ret ;
ret = expirationQueueCache . insert ( std : : pair < int , expirationQueueRowType > ( nHeight , queueRow ) ) ;
2015-05-27 23:53:12 +02:00
assert ( ret . second ) ;
itQueueRow = ret . first ;
}
return itQueueRow ;
}
2015-12-23 20:12:32 +01:00
bool CClaimTrieCache : : reorderTrieNode ( const std : : string & name , bool fCheckTakeover ) const
2015-09-25 23:09:21 +02:00
{
assert ( base ) ;
nodeCacheType : : iterator cachedNode ;
2015-09-28 23:57:17 +02:00
cachedNode = cache . find ( name ) ;
2015-09-25 23:09:21 +02:00
if ( cachedNode = = cache . end ( ) )
{
CClaimTrieNode * currentNode = & ( base - > root ) ;
for ( std : : string : : const_iterator itCur = name . begin ( ) ; itCur ! = name . end ( ) ; + + itCur )
{
std : : string sCurrentSubstring ( name . begin ( ) , itCur ) ;
std : : string sNextSubstring ( name . begin ( ) , itCur + 1 ) ;
cachedNode = cache . find ( sNextSubstring ) ;
if ( cachedNode ! = cache . end ( ) )
{
currentNode = cachedNode - > second ;
continue ;
}
nodeMapType : : iterator childNode = currentNode - > children . find ( * itCur ) ;
if ( childNode ! = currentNode - > children . end ( ) )
{
currentNode = childNode - > second ;
continue ;
}
// The node doesn't exist, so it can't be reordered.
return true ;
}
currentNode = new CClaimTrieNode ( * currentNode ) ;
std : : pair < nodeCacheType : : iterator , bool > ret ;
ret = cache . insert ( std : : pair < std : : string , CClaimTrieNode * > ( name , currentNode ) ) ;
assert ( ret . second ) ;
cachedNode = ret . first ;
}
bool fChanged = false ;
2015-11-25 18:04:32 +01:00
if ( cachedNode - > second - > claims . empty ( ) )
2015-09-25 23:09:21 +02:00
{
// Nothing in there to reorder
return true ;
}
else
{
2015-11-25 18:04:32 +01:00
CClaimValue currentTop = cachedNode - > second - > claims . front ( ) ;
supportMapEntryType node ;
2015-09-28 00:24:46 +02:00
getSupportsForName ( name , node ) ;
2015-11-25 18:04:32 +01:00
cachedNode - > second - > reorderClaims ( node ) ;
if ( cachedNode - > second - > claims . front ( ) ! = currentTop )
2015-09-25 23:09:21 +02:00
fChanged = true ;
}
if ( fChanged )
{
for ( std : : string : : const_iterator itCur = name . begin ( ) ; itCur ! = name . end ( ) ; + + itCur )
{
std : : string sub ( name . begin ( ) , itCur ) ;
dirtyHashes . insert ( sub ) ;
}
dirtyHashes . insert ( name ) ;
2015-12-06 03:55:23 +01:00
if ( fCheckTakeover )
namesToCheckForTakeover . insert ( name ) ;
2015-09-25 23:09:21 +02:00
}
return true ;
}
2015-12-23 20:12:32 +01:00
bool CClaimTrieCache : : getSupportsForName ( const std : : string & name , supportMapEntryType & node ) const
2015-09-28 00:24:46 +02:00
{
supportMapType : : iterator cachedNode ;
cachedNode = supportCache . find ( name ) ;
if ( cachedNode ! = supportCache . end ( ) )
{
node = cachedNode - > second ;
return true ;
}
else
{
return base - > getSupportNode ( name , node ) ;
}
}
2015-12-23 20:12:32 +01:00
bool CClaimTrieCache : : insertSupportIntoMap ( const std : : string & name , CSupportValue support , bool fCheckTakeover ) const
2015-09-25 23:09:21 +02:00
{
supportMapType : : iterator cachedNode ;
// If this node is already in the cache, use that
cachedNode = supportCache . find ( name ) ;
// If not, copy the one from base if it exists, and use that
if ( cachedNode = = supportCache . end ( ) )
{
2015-11-25 18:04:32 +01:00
supportMapEntryType node ;
2015-09-25 23:09:21 +02:00
base - > getSupportNode ( name , node ) ;
std : : pair < supportMapType : : iterator , bool > ret ;
2015-11-25 18:04:32 +01:00
ret = supportCache . insert ( std : : pair < std : : string , supportMapEntryType > ( name , node ) ) ;
2015-09-25 23:09:21 +02:00
assert ( ret . second ) ;
cachedNode = ret . first ;
}
2015-11-25 18:04:32 +01:00
cachedNode - > second . push_back ( support ) ;
2015-09-25 23:09:21 +02:00
// See if this changed the biggest bid
2015-12-06 03:55:23 +01:00
return reorderTrieNode ( name , fCheckTakeover ) ;
2015-09-25 23:09:21 +02:00
}
2015-12-23 20:12:32 +01:00
bool CClaimTrieCache : : removeSupportFromMap ( const std : : string & name , const COutPoint & outPoint , CSupportValue & support , bool fCheckTakeover ) const
2015-09-25 23:09:21 +02:00
{
supportMapType : : iterator cachedNode ;
cachedNode = supportCache . find ( name ) ;
if ( cachedNode = = supportCache . end ( ) )
{
2015-11-25 18:04:32 +01:00
supportMapEntryType node ;
2015-09-25 23:09:21 +02:00
if ( ! base - > getSupportNode ( name , node ) )
{
// clearly, this support does not exist
return false ;
}
std : : pair < supportMapType : : iterator , bool > ret ;
2015-11-25 18:04:32 +01:00
ret = supportCache . insert ( std : : pair < std : : string , supportMapEntryType > ( name , node ) ) ;
2015-09-25 23:09:21 +02:00
assert ( ret . second ) ;
cachedNode = ret . first ;
}
2015-11-25 18:04:32 +01:00
supportMapEntryType : : iterator itSupport ;
2015-09-28 23:57:17 +02:00
for ( itSupport = cachedNode - > second . begin ( ) ; itSupport ! = cachedNode - > second . end ( ) ; + + itSupport )
2015-09-25 23:09:21 +02:00
{
2015-12-23 20:12:32 +01:00
if ( itSupport - > outPoint = = outPoint )
2015-09-25 23:09:21 +02:00
{
2015-09-28 23:57:17 +02:00
break ;
2015-09-25 23:09:21 +02:00
}
}
2015-09-28 23:57:17 +02:00
if ( itSupport ! = cachedNode - > second . end ( ) )
{
2015-12-23 20:12:32 +01:00
std : : swap ( support , * itSupport ) ;
2015-09-28 23:57:17 +02:00
cachedNode - > second . erase ( itSupport ) ;
2015-12-06 03:55:23 +01:00
return reorderTrieNode ( name , fCheckTakeover ) ;
2015-09-28 23:57:17 +02:00
}
else
{
LogPrintf ( " CClaimTrieCache::%s() : asked to remove a support that doesn't exist \n " , __func__ ) ;
return false ;
}
2015-09-25 23:09:21 +02:00
}
2015-11-25 18:04:32 +01:00
supportQueueType : : iterator CClaimTrieCache : : getSupportQueueCacheRow ( int nHeight , bool createIfNotExists ) const
2015-09-25 23:09:21 +02:00
{
2015-11-25 18:04:32 +01:00
supportQueueType : : iterator itQueueRow = supportQueueCache . find ( nHeight ) ;
2015-09-25 23:09:21 +02:00
if ( itQueueRow = = supportQueueCache . end ( ) )
{
2015-11-25 18:04:32 +01:00
supportQueueRowType queueRow ;
2015-09-25 23:09:21 +02:00
bool exists = base - > getSupportQueueRow ( nHeight , queueRow ) ;
if ( ! exists )
if ( ! createIfNotExists )
return itQueueRow ;
// Stick the new row in the cache
2015-11-25 18:04:32 +01:00
std : : pair < supportQueueType : : iterator , bool > ret ;
ret = supportQueueCache . insert ( std : : pair < int , supportQueueRowType > ( nHeight , queueRow ) ) ;
2015-09-25 23:09:21 +02:00
assert ( ret . second ) ;
itQueueRow = ret . first ;
}
return itQueueRow ;
}
2016-01-05 01:04:55 +01:00
queueNameType : : iterator CClaimTrieCache : : getSupportQueueCacheNameRow ( const std : : string & name , bool createIfNotExists ) const
2015-11-25 18:04:32 +01:00
{
2016-01-05 01:04:55 +01:00
queueNameType : : iterator itQueueNameRow = supportQueueNameCache . find ( name ) ;
2015-11-25 18:04:32 +01:00
if ( itQueueNameRow = = supportQueueNameCache . end ( ) )
{
2016-01-05 01:04:55 +01:00
queueNameRowType queueNameRow ;
2015-11-25 18:04:32 +01:00
bool exists = base - > getSupportQueueNameRow ( name , queueNameRow ) ;
if ( ! exists )
if ( ! createIfNotExists )
return itQueueNameRow ;
// Stick the new row in the name cache
2016-01-05 01:04:55 +01:00
std : : pair < queueNameType : : iterator , bool > ret ;
ret = supportQueueNameCache . insert ( std : : pair < std : : string , queueNameRowType > ( name , queueNameRow ) ) ;
2015-11-25 18:04:32 +01:00
assert ( ret . second ) ;
itQueueNameRow = ret . first ;
}
return itQueueNameRow ;
}
2015-12-23 20:12:32 +01:00
bool CClaimTrieCache : : addSupportToQueues ( const std : : string & name , CSupportValue & support ) const
2015-09-25 23:09:21 +02:00
{
2015-12-23 20:12:32 +01:00
LogPrintf ( " %s: nValidAtHeight: %d \n " , __func__ , support . nValidAtHeight ) ;
2015-11-25 18:04:32 +01:00
supportQueueEntryType entry ( name , support ) ;
2015-12-23 20:12:32 +01:00
supportQueueType : : iterator itQueueRow = getSupportQueueCacheRow ( support . nValidAtHeight , true ) ;
2016-01-05 01:04:55 +01:00
queueNameType : : iterator itQueueNameRow = getSupportQueueCacheNameRow ( name , true ) ;
2015-09-25 23:09:21 +02:00
itQueueRow - > second . push_back ( entry ) ;
2015-12-31 08:51:09 +01:00
itQueueNameRow - > second . push_back ( outPointHeightType ( support . outPoint , support . nValidAtHeight ) ) ;
2016-01-05 01:04:55 +01:00
nameOutPointType expireEntry ( name , support . outPoint ) ;
addSupportToExpirationQueue ( support . nHeight + base - > nExpirationTime , expireEntry ) ;
2015-09-25 23:09:21 +02:00
return true ;
}
2015-12-23 20:12:32 +01:00
bool CClaimTrieCache : : removeSupportFromQueue ( const std : : string & name , const COutPoint & outPoint , CSupportValue & support ) const
2015-09-25 23:09:21 +02:00
{
2016-01-05 01:04:55 +01:00
queueNameType : : iterator itQueueNameRow = getSupportQueueCacheNameRow ( name , false ) ;
2015-11-25 18:04:32 +01:00
if ( itQueueNameRow = = supportQueueNameCache . end ( ) )
2015-09-25 23:09:21 +02:00
{
return false ;
}
2016-01-05 01:04:55 +01:00
queueNameRowType : : iterator itQueueName ;
2015-11-25 18:04:32 +01:00
for ( itQueueName = itQueueNameRow - > second . begin ( ) ; itQueueName ! = itQueueNameRow - > second . end ( ) ; + + itQueueName )
2015-09-25 23:09:21 +02:00
{
2015-12-23 20:12:32 +01:00
if ( itQueueName - > outPoint = = outPoint )
2015-11-25 18:04:32 +01:00
{
break ;
}
2015-09-25 23:09:21 +02:00
}
2015-11-25 18:04:32 +01:00
if ( itQueueName = = itQueueNameRow - > second . end ( ) )
2015-09-25 23:09:21 +02:00
{
2015-11-25 18:04:32 +01:00
return false ;
}
2015-12-31 08:51:09 +01:00
supportQueueType : : iterator itQueueRow = getSupportQueueCacheRow ( itQueueName - > nHeight , false ) ;
2015-11-25 18:04:32 +01:00
if ( itQueueRow ! = supportQueueCache . end ( ) )
{
supportQueueRowType : : iterator itQueue ;
for ( itQueue = itQueueRow - > second . begin ( ) ; itQueue ! = itQueueRow - > second . end ( ) ; + + itQueue )
{
CSupportValue & support = itQueue - > second ;
2015-12-23 20:12:32 +01:00
if ( name = = itQueue - > first & & support . outPoint = = outPoint )
2015-11-25 18:04:32 +01:00
{
break ;
}
}
if ( itQueue ! = itQueueRow - > second . end ( ) )
{
2015-12-23 20:12:32 +01:00
std : : swap ( support , itQueue - > second ) ;
2015-11-25 18:04:32 +01:00
itQueueNameRow - > second . erase ( itQueueName ) ;
itQueueRow - > second . erase ( itQueue ) ;
return true ;
}
2015-09-25 23:09:21 +02:00
}
2015-12-31 08:51:09 +01:00
LogPrintf ( " %s: An inconsistency was found in the claim queue. Please report this to the developers: \n Found in named support queue but not in height support queue: name: %s, txid: %s, nOut: %d, nValidAtHeight: %d, current height: %d \n " , __func__ , name , outPoint . hash . GetHex ( ) , outPoint . n , itQueueName - > nHeight , nCurrentHeight ) ;
2015-09-25 23:09:21 +02:00
return false ;
}
2015-12-23 20:12:32 +01:00
bool CClaimTrieCache : : addSupport ( const std : : string & name , const COutPoint & outPoint , CAmount nAmount , uint160 supportedClaimId , int nHeight ) const
2015-09-25 23:09:21 +02:00
{
2015-12-23 20:12:32 +01:00
LogPrintf ( " %s: name: %s, txhash: %s, nOut: %d, nAmount: %d, supportedClaimId: %s, nHeight: %d, nCurrentHeight: %d \n " , __func__ , name , outPoint . hash . GetHex ( ) , outPoint . n , nAmount , supportedClaimId . GetHex ( ) , nHeight , nCurrentHeight ) ;
2015-09-25 23:09:21 +02:00
assert ( nHeight = = nCurrentHeight ) ;
2015-11-25 18:04:32 +01:00
CClaimValue claim ;
2015-12-23 20:12:32 +01:00
int delayForSupport ;
if ( base - > getInfoForName ( name , claim ) & & claim . claimId = = supportedClaimId )
2015-09-25 23:09:21 +02:00
{
2015-12-23 20:12:32 +01:00
LogPrintf ( " %s: This is a support to a best claim. \n " , __func__ ) ;
delayForSupport = 0 ;
2015-09-25 23:09:21 +02:00
}
2015-12-23 20:12:32 +01:00
else
{
delayForSupport = getDelayForName ( name ) ;
}
CSupportValue support ( outPoint , supportedClaimId , nAmount , nHeight , nHeight + delayForSupport ) ;
return addSupportToQueues ( name , support ) ;
2015-09-25 23:09:21 +02:00
}
2015-12-23 20:12:32 +01:00
bool CClaimTrieCache : : undoSpendSupport ( const std : : string & name , const COutPoint & outPoint , uint160 supportedClaimId , CAmount nAmount , int nHeight , int nValidAtHeight ) const
2015-09-25 23:09:21 +02:00
{
2015-12-23 20:12:32 +01:00
LogPrintf ( " %s: name: %s, txhash: %s, nOut: %d, nAmount: %d, supportedClaimId: %s, nHeight: %d, nCurrentHeight: %d \n " , __func__ , name , outPoint . hash . GetHex ( ) , outPoint . n , nAmount , supportedClaimId . GetHex ( ) , nHeight , nCurrentHeight ) ;
CSupportValue support ( outPoint , supportedClaimId , nAmount , nHeight , nValidAtHeight ) ;
2015-09-25 23:09:21 +02:00
if ( nValidAtHeight < nCurrentHeight )
{
2016-01-05 01:04:55 +01:00
nameOutPointType entry ( name , support . outPoint ) ;
addSupportToExpirationQueue ( support . nHeight + base - > nExpirationTime , entry ) ;
2015-12-06 03:55:23 +01:00
return insertSupportIntoMap ( name , support , false ) ;
2015-09-25 23:09:21 +02:00
}
else
{
2015-12-23 20:12:32 +01:00
return addSupportToQueues ( name , support ) ;
2015-09-25 23:09:21 +02:00
}
}
2015-12-23 20:12:32 +01:00
bool CClaimTrieCache : : removeSupport ( const std : : string & name , const COutPoint & outPoint , int nHeight , int & nValidAtHeight , bool fCheckTakeover ) const
2015-09-25 23:09:21 +02:00
{
bool removed = false ;
2015-12-23 20:12:32 +01:00
CSupportValue support ;
if ( removeSupportFromQueue ( name , outPoint , support ) )
2015-11-25 18:04:32 +01:00
removed = true ;
2015-12-23 20:12:32 +01:00
if ( removed = = false & & removeSupportFromMap ( name , outPoint , support , fCheckTakeover ) )
2015-09-25 23:09:21 +02:00
removed = true ;
2015-12-23 20:12:32 +01:00
if ( removed )
2015-12-29 19:50:11 +01:00
{
removeSupportFromExpirationQueue ( name , outPoint , nHeight ) ;
2015-12-23 20:12:32 +01:00
nValidAtHeight = support . nValidAtHeight ;
2015-12-29 19:50:11 +01:00
}
2015-09-25 23:09:21 +02:00
return removed ;
}
2016-01-05 01:04:55 +01:00
void CClaimTrieCache : : addSupportToExpirationQueue ( int nExpirationHeight , nameOutPointType & entry ) const
2015-09-25 23:09:21 +02:00
{
2016-01-05 01:04:55 +01:00
expirationQueueType : : iterator itQueueRow = getSupportExpirationQueueCacheRow ( nExpirationHeight , true ) ;
2015-12-23 20:12:32 +01:00
itQueueRow - > second . push_back ( entry ) ;
2015-12-29 19:50:11 +01:00
}
2015-12-23 20:12:32 +01:00
2015-12-29 19:50:11 +01:00
void CClaimTrieCache : : removeSupportFromExpirationQueue ( const std : : string & name , const COutPoint & outPoint , int nHeight ) const
2015-12-23 20:12:32 +01:00
{
int expirationHeight = nHeight + base - > nExpirationTime ;
2016-01-05 01:04:55 +01:00
expirationQueueType : : iterator itQueueRow = getSupportExpirationQueueCacheRow ( expirationHeight , false ) ;
expirationQueueRowType : : iterator itQueue ;
2015-12-23 20:12:32 +01:00
if ( itQueueRow ! = supportExpirationQueueCache . end ( ) )
{
for ( itQueue = itQueueRow - > second . begin ( ) ; itQueue ! = itQueueRow - > second . end ( ) ; + + itQueue )
{
2016-01-05 01:04:55 +01:00
if ( name = = itQueue - > name & & outPoint = = itQueue - > outPoint )
2015-12-23 20:12:32 +01:00
break ;
}
}
if ( itQueue ! = itQueueRow - > second . end ( ) )
{
itQueueRow - > second . erase ( itQueue ) ;
}
2015-12-29 19:50:11 +01:00
}
2015-12-23 20:12:32 +01:00
2016-01-05 01:04:55 +01:00
expirationQueueType : : iterator CClaimTrieCache : : getSupportExpirationQueueCacheRow ( int nHeight , bool createIfNotExists ) const
2015-12-23 20:12:32 +01:00
{
2016-01-05 01:04:55 +01:00
expirationQueueType : : iterator itQueueRow = supportExpirationQueueCache . find ( nHeight ) ;
2015-12-23 20:12:32 +01:00
if ( itQueueRow = = supportExpirationQueueCache . end ( ) )
{
// Have to make a new row it put in the cache, if createIfNotExists is true
2016-01-05 01:04:55 +01:00
expirationQueueRowType queueRow ;
2015-12-23 20:12:32 +01:00
// If the row exists in the base, copy its claims into the new row.
bool exists = base - > getSupportExpirationQueueRow ( nHeight , queueRow ) ;
if ( ! exists )
if ( ! createIfNotExists )
return itQueueRow ;
// Stick the new row in the cache
2016-01-05 01:04:55 +01:00
std : : pair < expirationQueueType : : iterator , bool > ret ;
ret = supportExpirationQueueCache . insert ( std : : pair < int , expirationQueueRowType > ( nHeight , queueRow ) ) ;
2015-12-23 20:12:32 +01:00
assert ( ret . second ) ;
itQueueRow = ret . first ;
}
return itQueueRow ;
2015-12-29 19:50:11 +01:00
}
2015-12-23 20:12:32 +01:00
bool CClaimTrieCache : : undoAddSupport ( const std : : string & name , const COutPoint & outPoint , int nHeight ) const
{
LogPrintf ( " %s: name: %s, txhash: %s, nOut: %d, nHeight: %d, nCurrentHeight: %d \n " , __func__ , name , outPoint . hash . GetHex ( ) , outPoint . n , nHeight , nCurrentHeight ) ;
2015-09-25 23:09:21 +02:00
int throwaway ;
2015-12-23 20:12:32 +01:00
return removeSupport ( name , outPoint , nHeight , throwaway , false ) ;
2015-09-25 23:09:21 +02:00
}
2015-12-23 20:12:32 +01:00
bool CClaimTrieCache : : spendSupport ( const std : : string & name , const COutPoint & outPoint , int nHeight , int & nValidAtHeight ) const
2015-09-25 23:09:21 +02:00
{
2015-12-23 20:12:32 +01:00
LogPrintf ( " %s: name: %s, txhash: %s, nOut: %d, nHeight: %d, nCurrentHeight: %d \n " , __func__ , name , outPoint . hash . GetHex ( ) , outPoint . n , nHeight , nCurrentHeight ) ;
return removeSupport ( name , outPoint , nHeight , nValidAtHeight , true ) ;
2015-09-25 23:09:21 +02:00
}
2016-01-05 01:04:55 +01:00
bool CClaimTrieCache : : incrementBlock ( insertUndoType & insertUndo , claimQueueRowType & expireUndo , insertUndoType & insertSupportUndo , supportQueueRowType & expireSupportUndo , std : : vector < std : : pair < std : : string , int > > & takeoverHeightUndo ) const
2015-03-17 06:16:37 +01:00
{
2015-03-19 17:57:56 +01:00
LogPrintf ( " %s: nCurrentHeight (before increment): %d \n " , __func__ , nCurrentHeight ) ;
2015-11-25 18:04:32 +01:00
claimQueueType : : iterator itQueueRow = getQueueCacheRow ( nCurrentHeight , false ) ;
if ( itQueueRow ! = claimQueueCache . end ( ) )
2015-03-17 06:16:37 +01:00
{
2015-11-25 18:04:32 +01:00
for ( claimQueueRowType : : iterator itEntry = itQueueRow - > second . begin ( ) ; itEntry ! = itQueueRow - > second . end ( ) ; + + itEntry )
2015-05-27 23:53:12 +02:00
{
2015-11-25 18:04:32 +01:00
bool found = false ;
2016-01-05 01:04:55 +01:00
queueNameType : : iterator itQueueNameRow = getQueueCacheNameRow ( itEntry - > first , false ) ;
2015-11-25 18:04:32 +01:00
if ( itQueueNameRow ! = claimQueueNameCache . end ( ) )
{
2016-01-05 01:04:55 +01:00
for ( queueNameRowType : : iterator itQueueName = itQueueNameRow - > second . begin ( ) ; itQueueName ! = itQueueNameRow - > second . end ( ) ; + + itQueueName )
2015-11-25 18:04:32 +01:00
{
2015-12-31 08:51:09 +01:00
if ( itQueueName - > outPoint = = itEntry - > second . outPoint & & itQueueName - > nHeight = = nCurrentHeight )
2015-11-25 18:04:32 +01:00
{
found = true ;
itQueueNameRow - > second . erase ( itQueueName ) ;
break ;
}
}
}
if ( ! found )
{
2015-12-23 20:12:32 +01:00
LogPrintf ( " %s: An inconsistency was found in the claim queue. Please report this to the developers: \n Found in height queue but not in named queue: name: %s, txid: %s, nOut: %d, nValidAtHeight: %d, current height: %d \n " , __func__ , itEntry - > first , itEntry - > second . outPoint . hash . GetHex ( ) , itEntry - > second . outPoint . n , itEntry - > second . nValidAtHeight , nCurrentHeight ) ;
2015-11-25 18:04:32 +01:00
if ( itQueueNameRow ! = claimQueueNameCache . end ( ) )
{
LogPrintf ( " Claims found for that name: \n " ) ;
2016-01-05 01:04:55 +01:00
for ( queueNameRowType : : iterator itQueueName = itQueueNameRow - > second . begin ( ) ; itQueueName ! = itQueueNameRow - > second . end ( ) ; + + itQueueName )
2015-11-25 18:04:32 +01:00
{
2015-12-31 08:51:09 +01:00
LogPrintf ( " \t txid: %s, nOut: %d, nValidAtHeight: %d \n " , itQueueName - > outPoint . hash . GetHex ( ) , itQueueName - > outPoint . n , itQueueName - > nHeight ) ;
2015-11-25 18:04:32 +01:00
}
}
else
{
LogPrintf ( " No claims found for that name \n " ) ;
}
}
2015-12-29 22:21:09 +01:00
assert ( found ) ;
2015-12-06 03:55:23 +01:00
insertClaimIntoTrie ( itEntry - > first , itEntry - > second , true ) ;
2015-12-31 08:51:09 +01:00
insertUndo . push_back ( nameOutPointHeightType ( itEntry - > first , itEntry - > second . outPoint , itEntry - > second . nValidAtHeight ) ) ;
2015-05-27 23:53:12 +02:00
}
itQueueRow - > second . clear ( ) ;
2015-03-17 06:16:37 +01:00
}
2016-01-05 01:04:55 +01:00
expirationQueueType : : iterator itExpirationRow = getExpirationQueueCacheRow ( nCurrentHeight , false ) ;
2015-05-27 23:53:12 +02:00
if ( itExpirationRow ! = expirationQueueCache . end ( ) )
2015-03-17 06:16:37 +01:00
{
2016-01-05 01:04:55 +01:00
for ( expirationQueueRowType : : iterator itEntry = itExpirationRow - > second . begin ( ) ; itEntry ! = itExpirationRow - > second . end ( ) ; + + itEntry )
2015-05-27 23:53:12 +02:00
{
2015-12-23 20:12:32 +01:00
CClaimValue claim ;
2016-01-05 01:04:55 +01:00
assert ( removeClaimFromTrie ( itEntry - > name , itEntry - > outPoint , claim , true ) ) ;
expireUndo . push_back ( std : : make_pair ( itEntry - > name , claim ) ) ;
2015-05-27 23:53:12 +02:00
}
itExpirationRow - > second . clear ( ) ;
2015-03-17 06:16:37 +01:00
}
2015-11-25 18:04:32 +01:00
supportQueueType : : iterator itSupportRow = getSupportQueueCacheRow ( nCurrentHeight , false ) ;
2015-09-25 23:09:21 +02:00
if ( itSupportRow ! = supportQueueCache . end ( ) )
{
2015-11-25 18:04:32 +01:00
for ( supportQueueRowType : : iterator itSupport = itSupportRow - > second . begin ( ) ; itSupport ! = itSupportRow - > second . end ( ) ; + + itSupport )
2015-09-25 23:09:21 +02:00
{
2015-11-25 18:04:32 +01:00
bool found = false ;
2016-01-05 01:04:55 +01:00
queueNameType : : iterator itSupportNameRow = getSupportQueueCacheNameRow ( itSupport - > first , false ) ;
2015-11-25 18:04:32 +01:00
if ( itSupportNameRow ! = supportQueueNameCache . end ( ) )
{
2016-01-05 01:04:55 +01:00
for ( queueNameRowType : : iterator itSupportName = itSupportNameRow - > second . begin ( ) ; itSupportName ! = itSupportNameRow - > second . end ( ) ; + + itSupportName )
2015-11-25 18:04:32 +01:00
{
2015-12-31 08:51:09 +01:00
if ( itSupportName - > outPoint = = itSupport - > second . outPoint & & itSupportName - > nHeight = = itSupport - > second . nValidAtHeight )
2015-11-25 18:04:32 +01:00
{
found = true ;
itSupportNameRow - > second . erase ( itSupportName ) ;
break ;
}
}
}
if ( ! found )
{
2015-12-23 20:12:32 +01:00
LogPrintf ( " %s: An inconsistency was found in the support queue. Please report this to the developers: \n Found in height queue but not in named queue: %s, txid: %s, nOut: %d, nValidAtHeight: %d, current height: %d \n " , __func__ , itSupport - > first , itSupport - > second . outPoint . hash . GetHex ( ) , itSupport - > second . outPoint . n , itSupport - > second . nValidAtHeight , nCurrentHeight ) ;
2015-11-25 18:04:32 +01:00
if ( itSupportNameRow ! = supportQueueNameCache . end ( ) )
{
LogPrintf ( " Supports found for that name: \n " ) ;
2016-01-05 01:04:55 +01:00
for ( queueNameRowType : : iterator itSupportName = itSupportNameRow - > second . begin ( ) ; itSupportName ! = itSupportNameRow - > second . end ( ) ; + + itSupportName )
2015-11-25 18:04:32 +01:00
{
2015-12-31 08:51:09 +01:00
LogPrintf ( " \t txid: %s, nOut: %d, nValidAtHeight: %d \n " , itSupportName - > outPoint . hash . GetHex ( ) , itSupportName - > outPoint . n , itSupportName - > nHeight ) ;
2015-11-25 18:04:32 +01:00
}
}
else
{
LogPrintf ( " No support found for that name \n " ) ;
}
}
2015-12-06 03:55:23 +01:00
insertSupportIntoMap ( itSupport - > first , itSupport - > second , true ) ;
2015-12-31 08:51:09 +01:00
insertSupportUndo . push_back ( nameOutPointHeightType ( itSupport - > first , itSupport - > second . outPoint , itSupport - > second . nValidAtHeight ) ) ;
2015-09-25 23:09:21 +02:00
}
itSupportRow - > second . clear ( ) ;
}
2016-01-05 01:04:55 +01:00
expirationQueueType : : iterator itSupportExpirationRow = getSupportExpirationQueueCacheRow ( nCurrentHeight , false ) ;
2015-12-23 20:12:32 +01:00
if ( itSupportExpirationRow ! = supportExpirationQueueCache . end ( ) )
{
2016-01-05 01:04:55 +01:00
for ( expirationQueueRowType : : iterator itEntry = itSupportExpirationRow - > second . begin ( ) ; itEntry ! = itSupportExpirationRow - > second . end ( ) ; + + itEntry )
2015-12-23 20:12:32 +01:00
{
2015-12-29 19:50:11 +01:00
CSupportValue support ;
2016-01-05 01:04:55 +01:00
assert ( removeSupportFromMap ( itEntry - > name , itEntry - > outPoint , support , true ) ) ;
expireSupportUndo . push_back ( std : : make_pair ( itEntry - > name , support ) ) ;
2015-12-23 20:12:32 +01:00
}
2015-12-29 19:50:11 +01:00
itSupportExpirationRow - > second . clear ( ) ;
}
2015-12-06 03:55:23 +01:00
// check each potentially taken over name to see if a takeover occurred.
// if it did, then check the claim and support insertion queues for
// the names that have been taken over, immediately insert all claim and
// supports for those names, and stick them in the insertUndo or
// insertSupportUndo vectors, with the nValidAtHeight they had prior to
2015-12-23 20:12:32 +01:00
// this block.
2015-12-06 03:55:23 +01:00
// Run through all names that have been taken over
for ( std : : set < std : : string > : : iterator itNamesToCheck = namesToCheckForTakeover . begin ( ) ; itNamesToCheck ! = namesToCheckForTakeover . end ( ) ; + + itNamesToCheck )
{
// Check if a takeover has occurred
nodeCacheType : : iterator itCachedNode = cache . find ( * itNamesToCheck ) ;
// many possibilities
// if this node is new, don't put it into the undo -- there will be nothing to restore, after all
// if all of this node's claims were deleted, it should be put into the undo -- there could be
// claims in the queue for that name and the takeover height should be the current height
// if the node is not in the cache, or getbestclaim fails, that means all of its claims were
// deleted
// if base->getInfoForName returns false, that means it's new and shouldn't go into the undo
// if both exist, and the current best claim is not the same as or the parent to the new best
// claim, then ownership has changed and the current height of last takeover should go into
// the queue
CClaimValue claimInCache ;
CClaimValue claimInTrie ;
bool haveClaimInCache ;
bool haveClaimInTrie ;
if ( itCachedNode = = cache . end ( ) )
{
haveClaimInCache = false ;
}
else
{
haveClaimInCache = itCachedNode - > second - > getBestClaim ( claimInCache ) ;
}
haveClaimInTrie = base - > getInfoForName ( * itNamesToCheck , claimInTrie ) ;
bool takeoverHappened = false ;
if ( ! haveClaimInTrie )
{
takeoverHappened = true ;
}
else if ( ! haveClaimInCache )
{
takeoverHappened = true ;
}
else if ( claimInCache ! = claimInTrie )
{
2015-12-23 01:11:50 +01:00
if ( claimInCache . claimId ! = claimInTrie . claimId )
2015-12-06 03:55:23 +01:00
{
takeoverHappened = true ;
}
}
2015-12-17 09:11:46 +01:00
if ( takeoverHappened )
2015-12-06 03:55:23 +01:00
{
// Get all claims in the queue for that name
2016-01-05 01:04:55 +01:00
queueNameType : : iterator itQueueNameRow = getQueueCacheNameRow ( * itNamesToCheck , false ) ;
2015-12-06 03:55:23 +01:00
if ( itQueueNameRow ! = claimQueueNameCache . end ( ) )
{
2016-01-05 01:04:55 +01:00
for ( queueNameRowType : : iterator itQueueName = itQueueNameRow - > second . begin ( ) ; itQueueName ! = itQueueNameRow - > second . end ( ) ; + + itQueueName )
2015-12-06 03:55:23 +01:00
{
2015-12-29 22:21:09 +01:00
bool found = false ;
2015-12-06 03:55:23 +01:00
// Pull those claims out of the height-based queue
2015-12-31 08:51:09 +01:00
claimQueueType : : iterator itQueueRow = getQueueCacheRow ( itQueueName - > nHeight , false ) ;
2015-12-29 22:21:09 +01:00
claimQueueRowType : : iterator itQueue ;
2015-12-06 03:55:23 +01:00
if ( itQueueRow ! = claimQueueCache . end ( ) )
{
for ( itQueue = itQueueRow - > second . begin ( ) ; itQueue ! = itQueueRow - > second . end ( ) ; + + itQueue )
{
2015-12-31 08:51:09 +01:00
if ( * itNamesToCheck = = itQueue - > first & & itQueue - > second . outPoint = = itQueueName - > outPoint & & itQueue - > second . nValidAtHeight = = itQueueName - > nHeight )
2015-12-06 03:55:23 +01:00
{
2015-12-29 22:21:09 +01:00
found = true ;
2015-12-06 03:55:23 +01:00
break ;
}
}
2015-12-29 22:21:09 +01:00
}
if ( found )
{
// Insert them into the queue undo with their previous nValidAtHeight
2015-12-31 08:51:09 +01:00
insertUndo . push_back ( nameOutPointHeightType ( itQueue - > first , itQueue - > second . outPoint , itQueue - > second . nValidAtHeight ) ) ;
2015-12-29 22:21:09 +01:00
// Insert them into the name trie with the new nValidAtHeight
itQueue - > second . nValidAtHeight = nCurrentHeight ;
insertClaimIntoTrie ( itQueue - > first , itQueue - > second , false ) ;
// Delete them from the height-based queue
itQueueRow - > second . erase ( itQueue ) ;
2015-12-06 03:55:23 +01:00
}
else
{
2015-12-31 08:51:09 +01:00
LogPrintf ( " %s(): An inconsistency was found in the claim queue. Please report this to the developers: \n Claim found in name queue but not in height based queue: \n name: %s, txid: %s, nOut: %d, nValidAtHeight in name based queue: %d, current height: %d \n " , __func__ , * itNamesToCheck , itQueueName - > outPoint . hash . GetHex ( ) , itQueueName - > outPoint . n , itQueueName - > nHeight , nCurrentHeight ) ;
2015-12-06 03:55:23 +01:00
}
2015-12-29 22:21:09 +01:00
assert ( found ) ;
2015-12-06 03:55:23 +01:00
}
// remove all claims from the queue for that name
itQueueNameRow - > second . clear ( ) ;
}
//
// Then, get all supports in the queue for that name
2016-01-05 01:04:55 +01:00
queueNameType : : iterator itSupportQueueNameRow = getSupportQueueCacheNameRow ( * itNamesToCheck , false ) ;
2015-12-06 03:55:23 +01:00
if ( itSupportQueueNameRow ! = supportQueueNameCache . end ( ) )
{
2016-01-05 01:04:55 +01:00
for ( queueNameRowType : : iterator itSupportQueueName = itSupportQueueNameRow - > second . begin ( ) ; itSupportQueueName ! = itSupportQueueNameRow - > second . end ( ) ; + + itSupportQueueName )
2015-12-06 03:55:23 +01:00
{
// Pull those supports out of the height-based queue
2015-12-31 08:51:09 +01:00
supportQueueType : : iterator itSupportQueueRow = getSupportQueueCacheRow ( itSupportQueueName - > nHeight , false ) ;
2015-12-06 03:55:23 +01:00
if ( itSupportQueueRow ! = supportQueueCache . end ( ) )
{
supportQueueRowType : : iterator itSupportQueue ;
for ( itSupportQueue = itSupportQueueRow - > second . begin ( ) ; itSupportQueue ! = itSupportQueueRow - > second . end ( ) ; + + itSupportQueue )
{
2015-12-31 08:51:09 +01:00
if ( * itNamesToCheck = = itSupportQueue - > first & & itSupportQueue - > second . outPoint = = itSupportQueueName - > outPoint & & itSupportQueue - > second . nValidAtHeight = = itSupportQueueName - > nHeight )
2015-12-06 03:55:23 +01:00
{
break ;
}
}
if ( itSupportQueue ! = itSupportQueueRow - > second . end ( ) )
{
// Insert them into the support queue undo with the previous nValidAtHeight
2015-12-31 08:51:09 +01:00
insertSupportUndo . push_back ( nameOutPointHeightType ( itSupportQueue - > first , itSupportQueue - > second . outPoint , itSupportQueue - > second . nValidAtHeight ) ) ;
2015-12-06 03:55:23 +01:00
// Insert them into the support map with the new nValidAtHeight
itSupportQueue - > second . nValidAtHeight = nCurrentHeight ;
insertSupportIntoMap ( itSupportQueue - > first , itSupportQueue - > second , false ) ;
// Delete them from the height-based queue
itSupportQueueRow - > second . erase ( itSupportQueue ) ;
}
else
{
2015-12-31 08:51:09 +01:00
// here be problems TODO: show error, assert false
2015-12-06 03:55:23 +01:00
}
}
else
{
// here be problems
}
}
// remove all supports from the queue for that name
itSupportQueueNameRow - > second . clear ( ) ;
}
2015-12-17 09:11:46 +01:00
2015-12-06 03:55:23 +01:00
// save the old last height so that it can be restored if the block is undone
if ( haveClaimInTrie )
{
int nHeightOfLastTakeover ;
assert ( getLastTakeoverForName ( * itNamesToCheck , nHeightOfLastTakeover ) ) ;
takeoverHeightUndo . push_back ( std : : make_pair ( * itNamesToCheck , nHeightOfLastTakeover ) ) ;
}
itCachedNode = cache . find ( * itNamesToCheck ) ;
if ( itCachedNode ! = cache . end ( ) )
{
cacheTakeoverHeights [ * itNamesToCheck ] = nCurrentHeight ;
}
}
}
namesToCheckForTakeover . clear ( ) ;
2015-05-27 23:53:12 +02:00
nCurrentHeight + + ;
2015-03-17 06:16:37 +01:00
return true ;
}
2016-01-05 01:04:55 +01:00
bool CClaimTrieCache : : decrementBlock ( insertUndoType & insertUndo , claimQueueRowType & expireUndo , insertUndoType & insertSupportUndo , supportQueueRowType & expireSupportUndo , std : : vector < std : : pair < std : : string , int > > & takeoverHeightUndo ) const
2015-03-17 06:16:37 +01:00
{
2015-03-19 17:57:56 +01:00
LogPrintf ( " %s: nCurrentHeight (before decrement): %d \n " , __func__ , nCurrentHeight ) ;
2015-03-17 06:16:37 +01:00
nCurrentHeight - - ;
2015-12-29 22:36:06 +01:00
if ( expireSupportUndo . begin ( ) ! = expireSupportUndo . end ( ) )
2015-05-27 23:53:12 +02:00
{
2016-01-05 01:04:55 +01:00
expirationQueueType : : iterator itSupportExpireRow = getSupportExpirationQueueCacheRow ( nCurrentHeight , true ) ;
2015-12-29 22:36:06 +01:00
for ( supportQueueRowType : : iterator itSupportExpireUndo = expireSupportUndo . begin ( ) ; itSupportExpireUndo ! = expireSupportUndo . end ( ) ; + + itSupportExpireUndo )
2015-05-27 23:53:12 +02:00
{
2015-12-29 22:36:06 +01:00
insertSupportIntoMap ( itSupportExpireUndo - > first , itSupportExpireUndo - > second , false ) ;
2016-01-05 01:04:55 +01:00
itSupportExpireRow - > second . push_back ( nameOutPointType ( itSupportExpireUndo - > first , itSupportExpireUndo - > second . outPoint ) ) ;
2015-05-21 19:50:40 +02:00
}
2015-03-17 06:16:37 +01:00
}
2015-12-29 22:36:06 +01:00
2016-01-05 01:04:55 +01:00
for ( insertUndoType : : iterator itSupportUndo = insertSupportUndo . begin ( ) ; itSupportUndo ! = insertSupportUndo . end ( ) ; + + itSupportUndo )
2015-12-06 03:55:23 +01:00
{
2015-12-31 08:51:09 +01:00
supportQueueType : : iterator itSupportRow = getSupportQueueCacheRow ( itSupportUndo - > nHeight , true ) ;
2015-12-23 20:12:32 +01:00
CSupportValue support ;
2015-12-31 08:51:09 +01:00
assert ( removeSupportFromMap ( itSupportUndo - > name , itSupportUndo - > outPoint , support , false ) ) ;
2016-01-05 01:04:55 +01:00
queueNameType : : iterator itSupportNameRow = getSupportQueueCacheNameRow ( itSupportUndo - > name , true ) ;
2015-12-31 08:51:09 +01:00
itSupportRow - > second . push_back ( std : : make_pair ( itSupportUndo - > name , support ) ) ;
itSupportNameRow - > second . push_back ( outPointHeightType ( support . outPoint , support . nValidAtHeight ) ) ;
2015-12-06 03:55:23 +01:00
}
2015-12-29 22:36:06 +01:00
if ( expireUndo . begin ( ) ! = expireUndo . end ( ) )
2015-12-29 19:50:11 +01:00
{
2016-01-05 01:04:55 +01:00
expirationQueueType : : iterator itExpireRow = getExpirationQueueCacheRow ( nCurrentHeight , true ) ;
2015-12-29 22:36:06 +01:00
for ( claimQueueRowType : : iterator itExpireUndo = expireUndo . begin ( ) ; itExpireUndo ! = expireUndo . end ( ) ; + + itExpireUndo )
2015-12-29 19:50:11 +01:00
{
2015-12-29 22:36:06 +01:00
insertClaimIntoTrie ( itExpireUndo - > first , itExpireUndo - > second , false ) ;
2016-01-05 01:04:55 +01:00
itExpireRow - > second . push_back ( nameOutPointType ( itExpireUndo - > first , itExpireUndo - > second . outPoint ) ) ;
2015-12-29 19:50:11 +01:00
}
}
2015-12-06 03:55:23 +01:00
2016-01-05 01:04:55 +01:00
for ( insertUndoType : : iterator itInsertUndo = insertUndo . begin ( ) ; itInsertUndo ! = insertUndo . end ( ) ; + + itInsertUndo )
2015-12-29 22:36:06 +01:00
{
2015-12-31 08:51:09 +01:00
claimQueueType : : iterator itQueueRow = getQueueCacheRow ( itInsertUndo - > nHeight , true ) ;
2015-12-29 22:36:06 +01:00
CClaimValue claim ;
2015-12-30 20:30:43 +01:00
assert ( removeClaimFromTrie ( itInsertUndo - > name , itInsertUndo - > outPoint , claim , false ) ) ;
2016-01-05 01:04:55 +01:00
queueNameType : : iterator itQueueNameRow = getQueueCacheNameRow ( itInsertUndo - > name , true ) ;
2015-12-30 20:30:43 +01:00
itQueueRow - > second . push_back ( std : : make_pair ( itInsertUndo - > name , claim ) ) ;
2015-12-31 08:51:09 +01:00
itQueueNameRow - > second . push_back ( outPointHeightType ( itInsertUndo - > outPoint , itInsertUndo - > nHeight ) ) ;
2015-12-29 22:36:06 +01:00
}
2015-12-06 03:55:23 +01:00
for ( std : : vector < std : : pair < std : : string , int > > : : iterator itTakeoverHeightUndo = takeoverHeightUndo . begin ( ) ; itTakeoverHeightUndo ! = takeoverHeightUndo . end ( ) ; + + itTakeoverHeightUndo )
{
cacheTakeoverHeights [ itTakeoverHeightUndo - > first ] = itTakeoverHeightUndo - > second ;
}
return true ;
}
bool CClaimTrieCache : : getLastTakeoverForName ( const std : : string & name , int & lastTakeoverHeight ) const
{
std : : map < std : : string , int > : : iterator itHeights = cacheTakeoverHeights . find ( name ) ;
if ( itHeights = = cacheTakeoverHeights . end ( ) )
2015-09-25 23:09:21 +02:00
{
2015-12-06 03:55:23 +01:00
if ( base - > getLastTakeoverForName ( name , lastTakeoverHeight ) )
2015-09-25 23:09:21 +02:00
{
2015-12-06 03:55:23 +01:00
return true ;
}
else
{
if ( fRequireTakeoverHeights )
{
return false ;
}
else
{
lastTakeoverHeight = 0 ;
return true ;
}
2015-09-25 23:09:21 +02:00
}
}
2015-12-06 03:55:23 +01:00
lastTakeoverHeight = itHeights - > second ;
2015-03-17 06:16:37 +01:00
return true ;
}
2015-12-17 09:11:46 +01:00
int CClaimTrieCache : : getDelayForName ( const std : : string & name ) const
2015-11-25 18:04:32 +01:00
{
2015-12-17 09:11:46 +01:00
int nHeightOfLastTakeover ;
if ( getLastTakeoverForName ( name , nHeightOfLastTakeover ) )
2015-11-25 18:04:32 +01:00
{
2015-12-17 18:05:20 +01:00
return std : : min ( ( nCurrentHeight - nHeightOfLastTakeover ) / base - > nProportionalDelayFactor , 4032 ) ;
2015-11-25 18:04:32 +01:00
}
2015-12-06 03:55:23 +01:00
else
{
2015-12-17 09:11:46 +01:00
return 0 ;
2015-12-06 03:55:23 +01:00
}
2015-11-25 18:04:32 +01:00
}
2015-09-24 07:15:28 +02:00
uint256 CClaimTrieCache : : getBestBlock ( )
2015-02-10 21:30:40 +01:00
{
if ( hashBlock . IsNull ( ) )
if ( base ! = NULL )
hashBlock = base - > hashBlock ;
return hashBlock ;
}
2015-09-24 07:15:28 +02:00
void CClaimTrieCache : : setBestBlock ( const uint256 & hashBlockIn )
2015-02-10 21:30:40 +01:00
{
hashBlock = hashBlockIn ;
}
2015-09-24 07:15:28 +02:00
bool CClaimTrieCache : : clear ( ) const
2015-02-03 02:57:53 +01:00
{
for ( nodeCacheType : : iterator itcache = cache . begin ( ) ; itcache ! = cache . end ( ) ; + + itcache )
{
delete itcache - > second ;
}
cache . clear ( ) ;
dirtyHashes . clear ( ) ;
cacheHashes . clear ( ) ;
2015-11-25 18:04:32 +01:00
claimQueueCache . clear ( ) ;
claimQueueNameCache . clear ( ) ;
2015-09-25 23:09:21 +02:00
expirationQueueCache . clear ( ) ;
supportCache . clear ( ) ;
supportQueueCache . clear ( ) ;
2015-11-25 18:04:32 +01:00
supportQueueNameCache . clear ( ) ;
2015-12-06 03:55:23 +01:00
namesToCheckForTakeover . clear ( ) ;
cacheTakeoverHeights . clear ( ) ;
2015-02-03 02:57:53 +01:00
return true ;
}
2015-09-24 07:15:28 +02:00
bool CClaimTrieCache : : flush ( )
2015-02-03 02:57:53 +01:00
{
if ( dirty ( ) )
getMerkleHash ( ) ;
2015-12-29 19:50:11 +01:00
bool success = base - > update ( cache , cacheHashes , cacheTakeoverHeights , getBestBlock ( ) , claimQueueCache , claimQueueNameCache , expirationQueueCache , nCurrentHeight , supportCache , supportQueueCache , supportQueueNameCache , supportExpirationQueueCache ) ;
2015-02-03 02:57:53 +01:00
if ( success )
{
success = clear ( ) ;
}
return success ;
}