@ -61,6 +61,14 @@ static std::vector<std::pair<uint256, CTransactionRef>> vExtraTxnForCompact GUAR
static const uint64_t RANDOMIZER_ID_ADDRESS_RELAY = 0x3cac0035b5866b90ULL ; // SHA256("main address relay")[0:8]
static const uint64_t RANDOMIZER_ID_ADDRESS_RELAY = 0x3cac0035b5866b90ULL ; // SHA256("main address relay")[0:8]
/// Age after which a stale block will no longer be served if requested as
/// protection against fingerprinting. Set to one month, denominated in seconds.
static const int STALE_RELAY_AGE_LIMIT = 30 * 24 * 60 * 60 ;
/// Age after which a block is considered historical for purposes of rate
/// limiting block relay. Set to one week, denominated in seconds.
static const int HISTORICAL_BLOCK_AGE = 7 * 24 * 60 * 60 ;
// Internal stuff
// Internal stuff
namespace {
namespace {
/** Number of nodes with fSyncStarted. */
/** Number of nodes with fSyncStarted. */
@ -706,6 +714,17 @@ void Misbehaving(NodeId pnode, int howmuch)
// blockchain -> download logic notification
// blockchain -> download logic notification
//
//
// To prevent fingerprinting attacks, only send blocks/headers outside of the
// active chain if they are no more than a month older (both in time, and in
// best equivalent proof of work) than the best header chain we know about.
static bool StaleBlockRequestAllowed ( const CBlockIndex * pindex , const Consensus : : Params & consensusParams )
{
AssertLockHeld ( cs_main ) ;
return ( pindexBestHeader ! = nullptr ) & &
( pindexBestHeader - > GetBlockTime ( ) - pindex - > GetBlockTime ( ) < STALE_RELAY_AGE_LIMIT ) & &
( GetBlockProofEquivalentTime ( * pindexBestHeader , * pindex , * pindexBestHeader , consensusParams ) < STALE_RELAY_AGE_LIMIT ) ;
}
PeerLogicValidation : : PeerLogicValidation ( CConnman * connmanIn ) : connman ( connmanIn ) {
PeerLogicValidation : : PeerLogicValidation ( CConnman * connmanIn ) : connman ( connmanIn ) {
// Initialize global variables that cannot be constructed at startup.
// Initialize global variables that cannot be constructed at startup.
recentRejects . reset ( new CRollingBloomFilter ( 120000 , 0.000001 ) ) ;
recentRejects . reset ( new CRollingBloomFilter ( 120000 , 0.000001 ) ) ;
@ -983,13 +1002,8 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
if ( chainActive . Contains ( mi - > second ) ) {
if ( chainActive . Contains ( mi - > second ) ) {
send = true ;
send = true ;
} else {
} else {
static const int nOneMonth = 30 * 24 * 60 * 60 ;
send = mi - > second - > IsValid ( BLOCK_VALID_SCRIPTS ) & &
// To prevent fingerprinting attacks, only send blocks outside of the active
StaleBlockRequestAllowed ( mi - > second , consensusParams ) ;
// chain if they are valid, and no more than a month older (both in time, and in
// best equivalent proof of work) than the best header chain we know about.
send = mi - > second - > IsValid ( BLOCK_VALID_SCRIPTS ) & & ( pindexBestHeader ! = nullptr ) & &
( pindexBestHeader - > GetBlockTime ( ) - mi - > second - > GetBlockTime ( ) < nOneMonth ) & &
( GetBlockProofEquivalentTime ( * pindexBestHeader , * mi - > second , * pindexBestHeader , consensusParams ) < nOneMonth ) ;
if ( ! send ) {
if ( ! send ) {
LogPrintf ( " %s: ignoring request from peer=%i for old block that isn't in the main chain \n " , __func__ , pfrom - > GetId ( ) ) ;
LogPrintf ( " %s: ignoring request from peer=%i for old block that isn't in the main chain \n " , __func__ , pfrom - > GetId ( ) ) ;
}
}
@ -997,8 +1011,7 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
}
}
// disconnect node in case we have reached the outbound limit for serving historical blocks
// disconnect node in case we have reached the outbound limit for serving historical blocks
// never disconnect whitelisted nodes
// never disconnect whitelisted nodes
static const int nOneWeek = 7 * 24 * 60 * 60 ; // assume > 1 week = historical
if ( send & & connman - > OutboundTargetReached ( true ) & & ( ( ( pindexBestHeader ! = nullptr ) & & ( pindexBestHeader - > GetBlockTime ( ) - mi - > second - > GetBlockTime ( ) > HISTORICAL_BLOCK_AGE ) ) | | inv . type = = MSG_FILTERED_BLOCK ) & & ! pfrom - > fWhitelisted )
if ( send & & connman - > OutboundTargetReached ( true ) & & ( ( ( pindexBestHeader ! = nullptr ) & & ( pindexBestHeader - > GetBlockTime ( ) - mi - > second - > GetBlockTime ( ) > nOneWeek ) ) | | inv . type = = MSG_FILTERED_BLOCK ) & & ! pfrom - > fWhitelisted )
{
{
LogPrint ( BCLog : : NET , " historical block serving limit reached, disconnect peer=%d \n " , pfrom - > GetId ( ) ) ;
LogPrint ( BCLog : : NET , " historical block serving limit reached, disconnect peer=%d \n " , pfrom - > GetId ( ) ) ;
@ -1723,6 +1736,12 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
if ( mi = = mapBlockIndex . end ( ) )
if ( mi = = mapBlockIndex . end ( ) )
return true ;
return true ;
pindex = ( * mi ) . second ;
pindex = ( * mi ) . second ;
if ( ! chainActive . Contains ( pindex ) & &
! StaleBlockRequestAllowed ( pindex , chainparams . GetConsensus ( ) ) ) {
LogPrintf ( " %s: ignoring request from peer=%i for old block header that isn't in the main chain \n " , __func__ , pfrom - > GetId ( ) ) ;
return true ;
}
}
}
else
else
{
{