@ -774,10 +774,12 @@ void PeerLogicValidation::BlockConnected(const std::shared_ptr<const CBlock>& pb
@@ -774,10 +774,12 @@ void PeerLogicValidation::BlockConnected(const std::shared_ptr<const CBlock>& pb
}
}
// All of the following cache a recent block, and are protected by cs_most_recent_block
static CCriticalSection cs_most_recent_block ;
static std : : shared_ptr < const CBlock > most_recent_block ;
static std : : shared_ptr < const CBlockHeaderAndShortTxIDs > most_recent_compact_block ;
static uint256 most_recent_block_hash ;
static bool fWitnessesPresentInMostRecentCompactBlock ;
void PeerLogicValidation : : NewPoWValidBlock ( const CBlockIndex * pindex , const std : : shared_ptr < const CBlock > & pblock ) {
std : : shared_ptr < const CBlockHeaderAndShortTxIDs > pcmpctblock = std : : make_shared < const CBlockHeaderAndShortTxIDs > ( * pblock , true ) ;
@ -798,6 +800,7 @@ void PeerLogicValidation::NewPoWValidBlock(const CBlockIndex *pindex, const std:
@@ -798,6 +800,7 @@ void PeerLogicValidation::NewPoWValidBlock(const CBlockIndex *pindex, const std:
most_recent_block_hash = hashBlock ;
most_recent_block = pblock ;
most_recent_compact_block = pcmpctblock ;
fWitnessesPresentInMostRecentCompactBlock = fWitnessEnabled ;
}
connman - > ForEachNode ( [ this , & pcmpctblock , pindex , & msgMaker , fWitnessEnabled , & hashBlock ] ( CNode * pnode ) {
@ -990,6 +993,15 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
@@ -990,6 +993,15 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
{
bool send = false ;
BlockMap : : iterator mi = mapBlockIndex . find ( inv . hash ) ;
std : : shared_ptr < const CBlock > a_recent_block ;
std : : shared_ptr < const CBlockHeaderAndShortTxIDs > a_recent_compact_block ;
bool fWitnessesPresentInARecentCompactBlock ;
{
LOCK ( cs_most_recent_block ) ;
a_recent_block = most_recent_block ;
a_recent_compact_block = most_recent_compact_block ;
fWitnessesPresentInARecentCompactBlock = fWitnessesPresentInMostRecentCompactBlock ;
}
if ( mi ! = mapBlockIndex . end ( ) )
{
if ( mi - > second - > nChainTx & & ! mi - > second - > IsValid ( BLOCK_VALID_SCRIPTS ) & &
@ -999,11 +1011,6 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
@@ -999,11 +1011,6 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
// before ActivateBestChain but after AcceptBlock).
// In this case, we need to run ActivateBestChain prior to checking the relay
// conditions below.
std : : shared_ptr < const CBlock > a_recent_block ;
{
LOCK ( cs_most_recent_block ) ;
a_recent_block = most_recent_block ;
}
CValidationState dummy ;
ActivateBestChain ( dummy , Params ( ) , a_recent_block ) ;
}
@ -1037,14 +1044,20 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
@@ -1037,14 +1044,20 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
// it's available before trying to send.
if ( send & & ( mi - > second - > nStatus & BLOCK_HAVE_DATA ) )
{
// Send block from disk
CBlock block ;
if ( ! ReadBlockFromDisk ( block , ( * mi ) . second , consensusParams ) )
assert ( ! " cannot load block from disk " ) ;
std : : shared_ptr < const CBlock > pblock ;
if ( a_recent_block & & a_recent_block - > GetHash ( ) = = ( * mi ) . second - > GetBlockHash ( ) ) {
pblock = a_recent_block ;
} else {
// Send block from disk
std : : shared_ptr < CBlock > pblockRead = std : : make_shared < CBlock > ( ) ;
if ( ! ReadBlockFromDisk ( * pblockRead , ( * mi ) . second , consensusParams ) )
assert ( ! " cannot load block from disk " ) ;
pblock = pblockRead ;
}
if ( inv . type = = MSG_BLOCK )
connman . PushMessage ( pfrom , msgMaker . Make ( SERIALIZE_TRANSACTION_NO_WITNESS , NetMsgType : : BLOCK , block ) ) ;
connman . PushMessage ( pfrom , msgMaker . Make ( SERIALIZE_TRANSACTION_NO_WITNESS , NetMsgType : : BLOCK , * p block) ) ;
else if ( inv . type = = MSG_WITNESS_BLOCK )
connman . PushMessage ( pfrom , msgMaker . Make ( NetMsgType : : BLOCK , block ) ) ;
connman . PushMessage ( pfrom , msgMaker . Make ( NetMsgType : : BLOCK , * p block) ) ;
else if ( inv . type = = MSG_FILTERED_BLOCK )
{
bool sendMerkleBlock = false ;
@ -1053,7 +1066,7 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
@@ -1053,7 +1066,7 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
LOCK ( pfrom - > cs_filter ) ;
if ( pfrom - > pfilter ) {
sendMerkleBlock = true ;
merkleBlock = CMerkleBlock ( block , * pfrom - > pfilter ) ;
merkleBlock = CMerkleBlock ( * p block, * pfrom - > pfilter ) ;
}
}
if ( sendMerkleBlock ) {
@ -1066,7 +1079,7 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
@@ -1066,7 +1079,7 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
// however we MUST always provide at least what the remote peer needs
typedef std : : pair < unsigned int , uint256 > PairType ;
BOOST_FOREACH ( PairType & pair , merkleBlock . vMatchedTxn )
connman . PushMessage ( pfrom , msgMaker . Make ( SERIALIZE_TRANSACTION_NO_WITNESS , NetMsgType : : TX , * block . vtx [ pair . first ] ) ) ;
connman . PushMessage ( pfrom , msgMaker . Make ( SERIALIZE_TRANSACTION_NO_WITNESS , NetMsgType : : TX , * pblock - > vtx [ pair . first ] ) ) ;
}
// else
// no response
@ -1080,10 +1093,15 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
@@ -1080,10 +1093,15 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
bool fPeerWantsWitness = State ( pfrom - > GetId ( ) ) - > fWantsCmpctWitness ;
int nSendFlags = fPeerWantsWitness ? 0 : SERIALIZE_TRANSACTION_NO_WITNESS ;
if ( CanDirectFetch ( consensusParams ) & & mi - > second - > nHeight > = chainActive . Height ( ) - MAX_CMPCTBLOCK_DEPTH ) {
CBlockHeaderAndShortTxIDs cmpctblock ( block , fPeerWantsWitness ) ;
connman . PushMessage ( pfrom , msgMaker . Make ( nSendFlags , NetMsgType : : CMPCTBLOCK , cmpctblock ) ) ;
} else
connman . PushMessage ( pfrom , msgMaker . Make ( nSendFlags , NetMsgType : : BLOCK , block ) ) ;
if ( ( fPeerWantsWitness | | ! fWitnessesPresentInARecentCompactBlock ) & & a_recent_compact_block & & a_recent_compact_block - > header . GetHash ( ) = = mi - > second - > GetBlockHash ( ) ) {
connman . PushMessage ( pfrom , msgMaker . Make ( nSendFlags , NetMsgType : : CMPCTBLOCK , * a_recent_compact_block ) ) ;
} else {
CBlockHeaderAndShortTxIDs cmpctblock ( * pblock , fPeerWantsWitness ) ;
connman . PushMessage ( pfrom , msgMaker . Make ( nSendFlags , NetMsgType : : CMPCTBLOCK , cmpctblock ) ) ;
}
} else {
connman . PushMessage ( pfrom , msgMaker . Make ( nSendFlags , NetMsgType : : BLOCK , * pblock ) ) ;
}
}
// Trigger the peer node to send a getblocks request for the next batch of inventory
@ -2974,7 +2992,7 @@ bool SendMessages(CNode* pto, CConnman& connman, const std::atomic<bool>& interr
@@ -2974,7 +2992,7 @@ bool SendMessages(CNode* pto, CConnman& connman, const std::atomic<bool>& interr
{
LOCK ( cs_most_recent_block ) ;
if ( most_recent_block_hash = = pBestIndex - > GetBlockHash ( ) ) {
if ( state . fWantsCmpctWitness )
if ( state . fWantsCmpctWitness | | ! fWitnessesPresentInMostRecentCompactBlock )
connman . PushMessage ( pto , msgMaker . Make ( nSendFlags , NetMsgType : : CMPCTBLOCK , * most_recent_compact_block ) ) ;
else {
CBlockHeaderAndShortTxIDs cmpctblock ( * most_recent_block , state . fWantsCmpctWitness ) ;