@ -1567,7 +1567,7 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C
}
}
}
}
SyncWithWallets ( tx , NULL ) ;
GetMainSignals ( ) . SyncTransaction ( tx , NULL , CMainSignals : : SYNC_TRANSACTION_NOT_IN_BLOCK ) ;
return true ;
return true ;
}
}
@ -1882,17 +1882,6 @@ void static InvalidChainFound(CBlockIndex* pindexNew)
}
}
void static InvalidBlockFound ( CBlockIndex * pindex , const CValidationState & state ) {
void static InvalidBlockFound ( CBlockIndex * pindex , const CValidationState & state ) {
int nDoS = 0 ;
if ( state . IsInvalid ( nDoS ) ) {
std : : map < uint256 , NodeId > : : iterator it = mapBlockSource . find ( pindex - > GetBlockHash ( ) ) ;
if ( it ! = mapBlockSource . end ( ) & & State ( it - > second ) ) {
assert ( state . GetRejectCode ( ) < REJECT_INTERNAL ) ; // Blocks are never rejected with internal reject codes
CBlockReject reject = { ( unsigned char ) state . GetRejectCode ( ) , state . GetRejectReason ( ) . substr ( 0 , MAX_REJECT_MESSAGE_LENGTH ) , pindex - > GetBlockHash ( ) } ;
State ( it - > second ) - > rejects . push_back ( reject ) ;
if ( nDoS > 0 )
Misbehaving ( it - > second , nDoS ) ;
}
}
if ( ! state . CorruptionPossible ( ) ) {
if ( ! state . CorruptionPossible ( ) ) {
pindex - > nStatus | = BLOCK_FAILED_VALID ;
pindex - > nStatus | = BLOCK_FAILED_VALID ;
setDirtyBlockIndex . insert ( pindex ) ;
setDirtyBlockIndex . insert ( pindex ) ;
@ -2800,7 +2789,7 @@ bool static DisconnectTip(CValidationState& state, const CChainParams& chainpara
// Let wallets know transactions went from 1-confirmed to
// Let wallets know transactions went from 1-confirmed to
// 0-confirmed or conflicted:
// 0-confirmed or conflicted:
BOOST_FOREACH ( const CTransaction & tx , block . vtx ) {
BOOST_FOREACH ( const CTransaction & tx , block . vtx ) {
SyncWithWallets ( tx , pindexDelete - > pprev ) ;
GetMainSignals ( ) . SyncTransaction ( tx , pindexDelete - > pprev , CMainSignals : : SYNC_TRANSACTION_NOT_IN_BLOCK ) ;
}
}
return true ;
return true ;
}
}
@ -2839,7 +2828,6 @@ bool static ConnectTip(CValidationState& state, const CChainParams& chainparams,
InvalidBlockFound ( pindexNew , state ) ;
InvalidBlockFound ( pindexNew , state ) ;
return error ( " ConnectTip() : ConnectBlock % s failed " , pindexNew->GetBlockHash().ToString()) ;
return error ( " ConnectTip() : ConnectBlock % s failed " , pindexNew->GetBlockHash().ToString()) ;
}
}
mapBlockSource . erase ( pindexNew - > GetBlockHash ( ) ) ;
nTime3 = GetTimeMicros ( ) ; nTimeConnectTotal + = nTime3 - nTime2 ;
nTime3 = GetTimeMicros ( ) ; nTimeConnectTotal + = nTime3 - nTime2 ;
LogPrint ( " bench " , " - Connect total: %.2fms [%.2fs] \n " , ( nTime3 - nTime2 ) * 0.001 , nTimeConnectTotal * 0.000001 ) ;
LogPrint ( " bench " , " - Connect total: %.2fms [%.2fs] \n " , ( nTime3 - nTime2 ) * 0.001 , nTimeConnectTotal * 0.000001 ) ;
assert ( view . Flush ( ) ) ;
assert ( view . Flush ( ) ) ;
@ -3038,7 +3026,7 @@ static void NotifyHeaderTip() {
* or an activated best chain . pblock is either NULL or a pointer to a block
* or an activated best chain . pblock is either NULL or a pointer to a block
* that is already loaded ( to avoid loading it again from disk ) .
* that is already loaded ( to avoid loading it again from disk ) .
*/
*/
bool ActivateBestChain ( CValidationState & state , const CChainParams & chainparams , const CBlock * pblock , CConnman * connman ) {
bool ActivateBestChain ( CValidationState & state , const CChainParams & chainparams , const CBlock * pblock ) {
CBlockIndex * pindexMostWork = NULL ;
CBlockIndex * pindexMostWork = NULL ;
CBlockIndex * pindexNewTip = NULL ;
CBlockIndex * pindexNewTip = NULL ;
std : : vector < std : : tuple < CTransaction , CBlockIndex * , int > > txChanged ;
std : : vector < std : : tuple < CTransaction , CBlockIndex * , int > > txChanged ;
@ -3053,7 +3041,6 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams,
const CBlockIndex * pindexFork ;
const CBlockIndex * pindexFork ;
std : : list < CTransaction > txConflicted ;
std : : list < CTransaction > txConflicted ;
bool fInitialDownload ;
bool fInitialDownload ;
int nNewHeight ;
{
{
LOCK ( cs_main ) ;
LOCK ( cs_main ) ;
CBlockIndex * pindexOldTip = chainActive . Tip ( ) ;
CBlockIndex * pindexOldTip = chainActive . Tip ( ) ;
@ -3076,59 +3063,27 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams,
pindexNewTip = chainActive . Tip ( ) ;
pindexNewTip = chainActive . Tip ( ) ;
pindexFork = chainActive . FindFork ( pindexOldTip ) ;
pindexFork = chainActive . FindFork ( pindexOldTip ) ;
fInitialDownload = IsInitialBlockDownload ( ) ;
fInitialDownload = IsInitialBlockDownload ( ) ;
nNewHeight = chainActive . Height ( ) ;
}
}
// When we reach this point, we switched to a new tip (stored in pindexNewTip).
// When we reach this point, we switched to a new tip (stored in pindexNewTip).
// Notifications/callbacks that can run without cs_main
// Notifications/callbacks that can run without cs_main
if ( connman )
connman - > SetBestHeight ( nNewHeight ) ;
// throw all transactions though the signal-interface
// throw all transactions though the signal-interface
// while _not_ holding the cs_main lock
// while _not_ holding the cs_main lock
BOOST_FOREACH ( const CTransaction & tx , txConflicted )
BOOST_FOREACH ( const CTransaction & tx , txConflicted )
{
{
SyncWithWallets ( tx , pindexNewTip ) ;
GetMainSignals ( ) . SyncTransaction ( tx , pindexNewTip , CMainSignals : : SYNC_TRANSACTION_NOT_IN_BLOCK ) ;
}
}
// ... and about transactions that got confirmed:
// ... and about transactions that got confirmed:
for ( unsigned int i = 0 ; i < txChanged . size ( ) ; i + + )
for ( unsigned int i = 0 ; i < txChanged . size ( ) ; i + + )
SyncWithWallets ( std : : get < 0 > ( txChanged [ i ] ) , std : : get < 1 > ( txChanged [ i ] ) , std : : get < 2 > ( txChanged [ i ] ) ) ;
GetMainSignals ( ) . SyncTransaction ( std : : get < 0 > ( txChanged [ i ] ) , std : : get < 1 > ( txChanged [ i ] ) , std : : get < 2 > ( txChanged [ i ] ) ) ;
// Notify external listeners about the new tip.
GetMainSignals ( ) . UpdatedBlockTip ( pindexNewTip , pindexFork , fInitialDownload ) ;
// Always notify the UI if a new block tip was connected
// Always notify the UI if a new block tip was connected
if ( pindexFork ! = pindexNewTip ) {
if ( pindexFork ! = pindexNewTip ) {
uiInterface . NotifyBlockTip ( fInitialDownload , pindexNewTip ) ;
uiInterface . NotifyBlockTip ( fInitialDownload , pindexNewTip ) ;
if ( ! fInitialDownload ) {
// Find the hashes of all blocks that weren't previously in the best chain.
std : : vector < uint256 > vHashes ;
CBlockIndex * pindexToAnnounce = pindexNewTip ;
while ( pindexToAnnounce ! = pindexFork ) {
vHashes . push_back ( pindexToAnnounce - > GetBlockHash ( ) ) ;
pindexToAnnounce = pindexToAnnounce - > pprev ;
if ( vHashes . size ( ) = = MAX_BLOCKS_TO_ANNOUNCE ) {
// Limit announcements in case of a huge reorganization.
// Rely on the peer's synchronization mechanism in that case.
break ;
}
}
// Relay inventory, but don't relay old inventory during initial block download.
int nBlockEstimate = 0 ;
if ( fCheckpointsEnabled )
nBlockEstimate = Checkpoints : : GetTotalBlocksEstimate ( chainparams . Checkpoints ( ) ) ;
if ( connman ) {
connman - > ForEachNode ( [ nNewHeight , nBlockEstimate , & vHashes ] ( CNode * pnode ) {
if ( nNewHeight > ( pnode - > nStartingHeight ! = - 1 ? pnode - > nStartingHeight - 2000 : nBlockEstimate ) ) {
BOOST_REVERSE_FOREACH ( const uint256 & hash , vHashes ) {
pnode - > PushBlockHash ( hash ) ;
}
}
} ) ;
}
// Notify external listeners about the new tip.
if ( ! vHashes . empty ( ) ) {
GetMainSignals ( ) . UpdatedBlockTip ( pindexNewTip ) ;
}
}
}
}
} while ( pindexNewTip ! = pindexMostWork ) ;
} while ( pindexNewTip ! = pindexMostWork ) ;
CheckBlockIndex ( chainparams . GetConsensus ( ) ) ;
CheckBlockIndex ( chainparams . GetConsensus ( ) ) ;
@ -3787,7 +3742,7 @@ static bool AcceptBlock(const CBlock& block, CValidationState& state, const CCha
return true ;
return true ;
}
}
bool ProcessNewBlock ( CValidationState & state , const CChainParams & chainparams , CNode * pfrom , const CBlock * pblock , bool fForceProcessing , const CDiskBlockPos * dbp , CConnman * connman )
bool ProcessNewBlock ( CValidationState & state , const CChainParams & chainparams , CNode * pfrom , const CBlock * pblock , bool fForceProcessing , const CDiskBlockPos * dbp )
{
{
{
{
LOCK ( cs_main ) ;
LOCK ( cs_main ) ;
@ -3809,7 +3764,7 @@ bool ProcessNewBlock(CValidationState& state, const CChainParams& chainparams, C
NotifyHeaderTip ( ) ;
NotifyHeaderTip ( ) ;
if ( ! ActivateBestChain ( state , chainparams , pblock , connman ) )
if ( ! ActivateBestChain ( state , chainparams , pblock ) )
return error ( " %s: ActivateBestChain failed " , __func__ ) ;
return error ( " %s: ActivateBestChain failed " , __func__ ) ;
return true ;
return true ;
@ -4742,6 +4697,59 @@ std::string GetWarnings(const std::string& strFor)
//////////////////////////////////////////////////////////////////////////////
//
// blockchain -> download logic notification
//
void PeerLogicValidation : : UpdatedBlockTip ( const CBlockIndex * pindexNew , const CBlockIndex * pindexFork , bool fInitialDownload ) {
const int nNewHeight = pindexNew - > nHeight ;
connman - > SetBestHeight ( nNewHeight ) ;
if ( ! fInitialDownload ) {
// Find the hashes of all blocks that weren't previously in the best chain.
std : : vector < uint256 > vHashes ;
const CBlockIndex * pindexToAnnounce = pindexNew ;
while ( pindexToAnnounce ! = pindexFork ) {
vHashes . push_back ( pindexToAnnounce - > GetBlockHash ( ) ) ;
pindexToAnnounce = pindexToAnnounce - > pprev ;
if ( vHashes . size ( ) = = MAX_BLOCKS_TO_ANNOUNCE ) {
// Limit announcements in case of a huge reorganization.
// Rely on the peer's synchronization mechanism in that case.
break ;
}
}
// Relay inventory, but don't relay old inventory during initial block download.
connman - > ForEachNode ( [ nNewHeight , & vHashes ] ( CNode * pnode ) {
if ( nNewHeight > ( pnode - > nStartingHeight ! = - 1 ? pnode - > nStartingHeight - 2000 : 0 ) ) {
BOOST_REVERSE_FOREACH ( const uint256 & hash , vHashes ) {
pnode - > PushBlockHash ( hash ) ;
}
}
} ) ;
}
}
void PeerLogicValidation : : BlockChecked ( const CBlock & block , const CValidationState & state ) {
LOCK ( cs_main ) ;
const uint256 hash ( block . GetHash ( ) ) ;
std : : map < uint256 , NodeId > : : iterator it = mapBlockSource . find ( hash ) ;
int nDoS = 0 ;
if ( state . IsInvalid ( nDoS ) ) {
if ( it ! = mapBlockSource . end ( ) & & State ( it - > second ) ) {
assert ( state . GetRejectCode ( ) < REJECT_INTERNAL ) ; // Blocks are never rejected with internal reject codes
CBlockReject reject = { ( unsigned char ) state . GetRejectCode ( ) , state . GetRejectReason ( ) . substr ( 0 , MAX_REJECT_MESSAGE_LENGTH ) , hash } ;
State ( it - > second ) - > rejects . push_back ( reject ) ;
if ( nDoS > 0 )
Misbehaving ( it - > second , nDoS ) ;
}
}
if ( it ! = mapBlockSource . end ( ) )
mapBlockSource . erase ( it ) ;
}
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//
//
// Messages
// Messages
@ -5845,7 +5853,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
pfrom - > PushMessage ( NetMsgType : : GETDATA , invs ) ;
pfrom - > PushMessage ( NetMsgType : : GETDATA , invs ) ;
} else {
} else {
CValidationState state ;
CValidationState state ;
ProcessNewBlock ( state , chainparams , pfrom , & block , false , NULL , & connman ) ;
ProcessNewBlock ( state , chainparams , pfrom , & block , false , NULL ) ;
int nDoS ;
int nDoS ;
if ( state . IsInvalid ( nDoS ) ) {
if ( state . IsInvalid ( nDoS ) ) {
assert ( state . GetRejectCode ( ) < REJECT_INTERNAL ) ; // Blocks are never rejected with internal reject codes
assert ( state . GetRejectCode ( ) < REJECT_INTERNAL ) ; // Blocks are never rejected with internal reject codes
@ -6021,7 +6029,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
// Such an unrequested block may still be processed, subject to the
// Such an unrequested block may still be processed, subject to the
// conditions in AcceptBlock().
// conditions in AcceptBlock().
bool forceProcessing = pfrom - > fWhitelisted & & ! IsInitialBlockDownload ( ) ;
bool forceProcessing = pfrom - > fWhitelisted & & ! IsInitialBlockDownload ( ) ;
ProcessNewBlock ( state , chainparams , pfrom , & block , forceProcessing , NULL , & connman ) ;
ProcessNewBlock ( state , chainparams , pfrom , & block , forceProcessing , NULL ) ;
int nDoS ;
int nDoS ;
if ( state . IsInvalid ( nDoS ) ) {
if ( state . IsInvalid ( nDoS ) ) {
assert ( state . GetRejectCode ( ) < REJECT_INTERNAL ) ; // Blocks are never rejected with internal reject codes
assert ( state . GetRejectCode ( ) < REJECT_INTERNAL ) ; // Blocks are never rejected with internal reject codes