Skip to content

Commit eab00d9

Browse files
committed
Merge #9665: Use cached [compact] blocks to respond to getdata messages
b49ad44 Add comment about cs_most_recent_block coverage (Matt Corallo) c47f5b7 Cache witness-enabled state with recent-compact-block-cache (Matt Corallo) efc135f Use cached [compact] blocks to respond to getdata messages (Matt Corallo) Tree-SHA512: ffc478bddbf14b8ed304a3041f47746520ce545bdeffa9652eff2ccb25c8b0d5194abe72568c10f9c1b246ee361176ba217767af834752a2ca7263d292005e87
2 parents cf8a8b1 + b49ad44 commit eab00d9

File tree

1 file changed

+36
-18
lines changed

1 file changed

+36
-18
lines changed

src/net_processing.cpp

Lines changed: 36 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -774,10 +774,12 @@ void PeerLogicValidation::BlockConnected(const std::shared_ptr<const CBlock>& pb
774774
}
775775
}
776776

777+
// All of the following cache a recent block, and are protected by cs_most_recent_block
777778
static CCriticalSection cs_most_recent_block;
778779
static std::shared_ptr<const CBlock> most_recent_block;
779780
static std::shared_ptr<const CBlockHeaderAndShortTxIDs> most_recent_compact_block;
780781
static uint256 most_recent_block_hash;
782+
static bool fWitnessesPresentInMostRecentCompactBlock;
781783

782784
void PeerLogicValidation::NewPoWValidBlock(const CBlockIndex *pindex, const std::shared_ptr<const CBlock>& pblock) {
783785
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:
798800
most_recent_block_hash = hashBlock;
799801
most_recent_block = pblock;
800802
most_recent_compact_block = pcmpctblock;
803+
fWitnessesPresentInMostRecentCompactBlock = fWitnessEnabled;
801804
}
802805

803806
connman->ForEachNode([this, &pcmpctblock, pindex, &msgMaker, fWitnessEnabled, &hashBlock](CNode* pnode) {
@@ -990,6 +993,15 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
990993
{
991994
bool send = false;
992995
BlockMap::iterator mi = mapBlockIndex.find(inv.hash);
996+
std::shared_ptr<const CBlock> a_recent_block;
997+
std::shared_ptr<const CBlockHeaderAndShortTxIDs> a_recent_compact_block;
998+
bool fWitnessesPresentInARecentCompactBlock;
999+
{
1000+
LOCK(cs_most_recent_block);
1001+
a_recent_block = most_recent_block;
1002+
a_recent_compact_block = most_recent_compact_block;
1003+
fWitnessesPresentInARecentCompactBlock = fWitnessesPresentInMostRecentCompactBlock;
1004+
}
9931005
if (mi != mapBlockIndex.end())
9941006
{
9951007
if (mi->second->nChainTx && !mi->second->IsValid(BLOCK_VALID_SCRIPTS) &&
@@ -999,11 +1011,6 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
9991011
// before ActivateBestChain but after AcceptBlock).
10001012
// In this case, we need to run ActivateBestChain prior to checking the relay
10011013
// conditions below.
1002-
std::shared_ptr<const CBlock> a_recent_block;
1003-
{
1004-
LOCK(cs_most_recent_block);
1005-
a_recent_block = most_recent_block;
1006-
}
10071014
CValidationState dummy;
10081015
ActivateBestChain(dummy, Params(), a_recent_block);
10091016
}
@@ -1037,14 +1044,20 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
10371044
// it's available before trying to send.
10381045
if (send && (mi->second->nStatus & BLOCK_HAVE_DATA))
10391046
{
1040-
// Send block from disk
1041-
CBlock block;
1042-
if (!ReadBlockFromDisk(block, (*mi).second, consensusParams))
1043-
assert(!"cannot load block from disk");
1047+
std::shared_ptr<const CBlock> pblock;
1048+
if (a_recent_block && a_recent_block->GetHash() == (*mi).second->GetBlockHash()) {
1049+
pblock = a_recent_block;
1050+
} else {
1051+
// Send block from disk
1052+
std::shared_ptr<CBlock> pblockRead = std::make_shared<CBlock>();
1053+
if (!ReadBlockFromDisk(*pblockRead, (*mi).second, consensusParams))
1054+
assert(!"cannot load block from disk");
1055+
pblock = pblockRead;
1056+
}
10441057
if (inv.type == MSG_BLOCK)
1045-
connman.PushMessage(pfrom, msgMaker.Make(SERIALIZE_TRANSACTION_NO_WITNESS, NetMsgType::BLOCK, block));
1058+
connman.PushMessage(pfrom, msgMaker.Make(SERIALIZE_TRANSACTION_NO_WITNESS, NetMsgType::BLOCK, *pblock));
10461059
else if (inv.type == MSG_WITNESS_BLOCK)
1047-
connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::BLOCK, block));
1060+
connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::BLOCK, *pblock));
10481061
else if (inv.type == MSG_FILTERED_BLOCK)
10491062
{
10501063
bool sendMerkleBlock = false;
@@ -1053,7 +1066,7 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
10531066
LOCK(pfrom->cs_filter);
10541067
if (pfrom->pfilter) {
10551068
sendMerkleBlock = true;
1056-
merkleBlock = CMerkleBlock(block, *pfrom->pfilter);
1069+
merkleBlock = CMerkleBlock(*pblock, *pfrom->pfilter);
10571070
}
10581071
}
10591072
if (sendMerkleBlock) {
@@ -1066,7 +1079,7 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
10661079
// however we MUST always provide at least what the remote peer needs
10671080
typedef std::pair<unsigned int, uint256> PairType;
10681081
BOOST_FOREACH(PairType& pair, merkleBlock.vMatchedTxn)
1069-
connman.PushMessage(pfrom, msgMaker.Make(SERIALIZE_TRANSACTION_NO_WITNESS, NetMsgType::TX, *block.vtx[pair.first]));
1082+
connman.PushMessage(pfrom, msgMaker.Make(SERIALIZE_TRANSACTION_NO_WITNESS, NetMsgType::TX, *pblock->vtx[pair.first]));
10701083
}
10711084
// else
10721085
// no response
@@ -1080,10 +1093,15 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
10801093
bool fPeerWantsWitness = State(pfrom->GetId())->fWantsCmpctWitness;
10811094
int nSendFlags = fPeerWantsWitness ? 0 : SERIALIZE_TRANSACTION_NO_WITNESS;
10821095
if (CanDirectFetch(consensusParams) && mi->second->nHeight >= chainActive.Height() - MAX_CMPCTBLOCK_DEPTH) {
1083-
CBlockHeaderAndShortTxIDs cmpctblock(block, fPeerWantsWitness);
1084-
connman.PushMessage(pfrom, msgMaker.Make(nSendFlags, NetMsgType::CMPCTBLOCK, cmpctblock));
1085-
} else
1086-
connman.PushMessage(pfrom, msgMaker.Make(nSendFlags, NetMsgType::BLOCK, block));
1096+
if ((fPeerWantsWitness || !fWitnessesPresentInARecentCompactBlock) && a_recent_compact_block && a_recent_compact_block->header.GetHash() == mi->second->GetBlockHash()) {
1097+
connman.PushMessage(pfrom, msgMaker.Make(nSendFlags, NetMsgType::CMPCTBLOCK, *a_recent_compact_block));
1098+
} else {
1099+
CBlockHeaderAndShortTxIDs cmpctblock(*pblock, fPeerWantsWitness);
1100+
connman.PushMessage(pfrom, msgMaker.Make(nSendFlags, NetMsgType::CMPCTBLOCK, cmpctblock));
1101+
}
1102+
} else {
1103+
connman.PushMessage(pfrom, msgMaker.Make(nSendFlags, NetMsgType::BLOCK, *pblock));
1104+
}
10871105
}
10881106

10891107
// 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
29742992
{
29752993
LOCK(cs_most_recent_block);
29762994
if (most_recent_block_hash == pBestIndex->GetBlockHash()) {
2977-
if (state.fWantsCmpctWitness)
2995+
if (state.fWantsCmpctWitness || !fWitnessesPresentInMostRecentCompactBlock)
29782996
connman.PushMessage(pto, msgMaker.Make(nSendFlags, NetMsgType::CMPCTBLOCK, *most_recent_compact_block));
29792997
else {
29802998
CBlockHeaderAndShortTxIDs cmpctblock(*most_recent_block, state.fWantsCmpctWitness);

0 commit comments

Comments
 (0)