@@ -1070,12 +1070,13 @@ static void RelayAddress(const CAddress& addr, bool fReachable, CConnman* connma
10701070 connman->ForEachNodeThen (std::move (sortfunc), std::move (pushfunc));
10711071}
10721072
1073- void static ProcessGetBlockData (CNode* pfrom, const Consensus::Params& consensusParams , const CInv& inv, CConnman* connman, const std::atomic<bool >& interruptMsgProc)
1073+ void static ProcessGetBlockData (CNode* pfrom, const CChainParams& chainparams , const CInv& inv, CConnman* connman, const std::atomic<bool >& interruptMsgProc)
10741074{
10751075 bool send = false ;
10761076 std::shared_ptr<const CBlock> a_recent_block;
10771077 std::shared_ptr<const CBlockHeaderAndShortTxIDs> a_recent_compact_block;
10781078 bool fWitnessesPresentInARecentCompactBlock ;
1079+ const Consensus::Params& consensusParams = chainparams.GetConsensus ();
10791080 {
10801081 LOCK (cs_most_recent_block);
10811082 a_recent_block = most_recent_block;
@@ -1142,60 +1143,71 @@ void static ProcessGetBlockData(CNode* pfrom, const Consensus::Params& consensus
11421143 std::shared_ptr<const CBlock> pblock;
11431144 if (a_recent_block && a_recent_block->GetHash () == pindex->GetBlockHash ()) {
11441145 pblock = a_recent_block;
1146+ } else if (inv.type == MSG_WITNESS_BLOCK) {
1147+ // Fast-path: in this case it is possible to serve the block directly from disk,
1148+ // as the network format matches the format on disk
1149+ std::vector<uint8_t > block_data;
1150+ if (!ReadRawBlockFromDisk (block_data, pindex, chainparams.MessageStart ())) {
1151+ assert (!" cannot load block from disk" );
1152+ }
1153+ connman->PushMessage (pfrom, msgMaker.Make (NetMsgType::BLOCK, MakeSpan (block_data)));
1154+ // Don't set pblock as we've sent the block
11451155 } else {
11461156 // Send block from disk
11471157 std::shared_ptr<CBlock> pblockRead = std::make_shared<CBlock>();
11481158 if (!ReadBlockFromDisk (*pblockRead, pindex, consensusParams))
11491159 assert (!" cannot load block from disk" );
11501160 pblock = pblockRead;
11511161 }
1152- if (inv.type == MSG_BLOCK)
1153- connman->PushMessage (pfrom, msgMaker.Make (SERIALIZE_TRANSACTION_NO_WITNESS, NetMsgType::BLOCK, *pblock));
1154- else if (inv.type == MSG_WITNESS_BLOCK)
1155- connman->PushMessage (pfrom, msgMaker.Make (NetMsgType::BLOCK, *pblock));
1156- else if (inv.type == MSG_FILTERED_BLOCK)
1157- {
1158- bool sendMerkleBlock = false ;
1159- CMerkleBlock merkleBlock;
1162+ if (pblock) {
1163+ if (inv.type == MSG_BLOCK)
1164+ connman->PushMessage (pfrom, msgMaker.Make (SERIALIZE_TRANSACTION_NO_WITNESS, NetMsgType::BLOCK, *pblock));
1165+ else if (inv.type == MSG_WITNESS_BLOCK)
1166+ connman->PushMessage (pfrom, msgMaker.Make (NetMsgType::BLOCK, *pblock));
1167+ else if (inv.type == MSG_FILTERED_BLOCK)
11601168 {
1161- LOCK (pfrom->cs_filter );
1162- if (pfrom->pfilter ) {
1163- sendMerkleBlock = true ;
1164- merkleBlock = CMerkleBlock (*pblock, *pfrom->pfilter );
1169+ bool sendMerkleBlock = false ;
1170+ CMerkleBlock merkleBlock;
1171+ {
1172+ LOCK (pfrom->cs_filter );
1173+ if (pfrom->pfilter ) {
1174+ sendMerkleBlock = true ;
1175+ merkleBlock = CMerkleBlock (*pblock, *pfrom->pfilter );
1176+ }
1177+ }
1178+ if (sendMerkleBlock) {
1179+ connman->PushMessage (pfrom, msgMaker.Make (NetMsgType::MERKLEBLOCK, merkleBlock));
1180+ // CMerkleBlock just contains hashes, so also push any transactions in the block the client did not see
1181+ // This avoids hurting performance by pointlessly requiring a round-trip
1182+ // Note that there is currently no way for a node to request any single transactions we didn't send here -
1183+ // they must either disconnect and retry or request the full block.
1184+ // Thus, the protocol spec specified allows for us to provide duplicate txn here,
1185+ // however we MUST always provide at least what the remote peer needs
1186+ typedef std::pair<unsigned int , uint256> PairType;
1187+ for (PairType& pair : merkleBlock.vMatchedTxn )
1188+ connman->PushMessage (pfrom, msgMaker.Make (SERIALIZE_TRANSACTION_NO_WITNESS, NetMsgType::TX, *pblock->vtx [pair.first ]));
11651189 }
1190+ // else
1191+ // no response
11661192 }
1167- if (sendMerkleBlock) {
1168- connman->PushMessage (pfrom, msgMaker.Make (NetMsgType::MERKLEBLOCK, merkleBlock));
1169- // CMerkleBlock just contains hashes, so also push any transactions in the block the client did not see
1170- // This avoids hurting performance by pointlessly requiring a round-trip
1171- // Note that there is currently no way for a node to request any single transactions we didn't send here -
1172- // they must either disconnect and retry or request the full block.
1173- // Thus, the protocol spec specified allows for us to provide duplicate txn here,
1174- // however we MUST always provide at least what the remote peer needs
1175- typedef std::pair<unsigned int , uint256> PairType;
1176- for (PairType& pair : merkleBlock.vMatchedTxn )
1177- connman->PushMessage (pfrom, msgMaker.Make (SERIALIZE_TRANSACTION_NO_WITNESS, NetMsgType::TX, *pblock->vtx [pair.first ]));
1178- }
1179- // else
1180- // no response
1181- }
1182- else if (inv.type == MSG_CMPCT_BLOCK)
1183- {
1184- // If a peer is asking for old blocks, we're almost guaranteed
1185- // they won't have a useful mempool to match against a compact block,
1186- // and we don't feel like constructing the object for them, so
1187- // instead we respond with the full, non-compact block.
1188- bool fPeerWantsWitness = State (pfrom->GetId ())->fWantsCmpctWitness ;
1189- int nSendFlags = fPeerWantsWitness ? 0 : SERIALIZE_TRANSACTION_NO_WITNESS;
1190- if (CanDirectFetch (consensusParams) && pindex->nHeight >= chainActive.Height () - MAX_CMPCTBLOCK_DEPTH) {
1191- if ((fPeerWantsWitness || !fWitnessesPresentInARecentCompactBlock ) && a_recent_compact_block && a_recent_compact_block->header .GetHash () == pindex->GetBlockHash ()) {
1192- connman->PushMessage (pfrom, msgMaker.Make (nSendFlags, NetMsgType::CMPCTBLOCK, *a_recent_compact_block));
1193+ else if (inv.type == MSG_CMPCT_BLOCK)
1194+ {
1195+ // If a peer is asking for old blocks, we're almost guaranteed
1196+ // they won't have a useful mempool to match against a compact block,
1197+ // and we don't feel like constructing the object for them, so
1198+ // instead we respond with the full, non-compact block.
1199+ bool fPeerWantsWitness = State (pfrom->GetId ())->fWantsCmpctWitness ;
1200+ int nSendFlags = fPeerWantsWitness ? 0 : SERIALIZE_TRANSACTION_NO_WITNESS;
1201+ if (CanDirectFetch (consensusParams) && pindex->nHeight >= chainActive.Height () - MAX_CMPCTBLOCK_DEPTH) {
1202+ if ((fPeerWantsWitness || !fWitnessesPresentInARecentCompactBlock ) && a_recent_compact_block && a_recent_compact_block->header .GetHash () == pindex->GetBlockHash ()) {
1203+ connman->PushMessage (pfrom, msgMaker.Make (nSendFlags, NetMsgType::CMPCTBLOCK, *a_recent_compact_block));
1204+ } else {
1205+ CBlockHeaderAndShortTxIDs cmpctblock (*pblock, fPeerWantsWitness );
1206+ connman->PushMessage (pfrom, msgMaker.Make (nSendFlags, NetMsgType::CMPCTBLOCK, cmpctblock));
1207+ }
11931208 } else {
1194- CBlockHeaderAndShortTxIDs cmpctblock (*pblock, fPeerWantsWitness );
1195- connman->PushMessage (pfrom, msgMaker.Make (nSendFlags, NetMsgType::CMPCTBLOCK, cmpctblock));
1209+ connman->PushMessage (pfrom, msgMaker.Make (nSendFlags, NetMsgType::BLOCK, *pblock));
11961210 }
1197- } else {
1198- connman->PushMessage (pfrom, msgMaker.Make (nSendFlags, NetMsgType::BLOCK, *pblock));
11991211 }
12001212 }
12011213
@@ -1213,7 +1225,7 @@ void static ProcessGetBlockData(CNode* pfrom, const Consensus::Params& consensus
12131225 }
12141226}
12151227
1216- void static ProcessGetData (CNode* pfrom, const Consensus::Params& consensusParams , CConnman* connman, const std::atomic<bool >& interruptMsgProc)
1228+ void static ProcessGetData (CNode* pfrom, const CChainParams& chainparams , CConnman* connman, const std::atomic<bool >& interruptMsgProc)
12171229{
12181230 AssertLockNotHeld (cs_main);
12191231
@@ -1262,7 +1274,7 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
12621274 const CInv &inv = *it;
12631275 if (inv.type == MSG_BLOCK || inv.type == MSG_FILTERED_BLOCK || inv.type == MSG_CMPCT_BLOCK || inv.type == MSG_WITNESS_BLOCK) {
12641276 it++;
1265- ProcessGetBlockData (pfrom, consensusParams , inv, connman, interruptMsgProc);
1277+ ProcessGetBlockData (pfrom, chainparams , inv, connman, interruptMsgProc);
12661278 }
12671279 }
12681280
@@ -1971,7 +1983,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
19711983 }
19721984
19731985 pfrom->vRecvGetData .insert (pfrom->vRecvGetData .end (), vInv.begin (), vInv.end ());
1974- ProcessGetData (pfrom, chainparams. GetConsensus () , connman, interruptMsgProc);
1986+ ProcessGetData (pfrom, chainparams, connman, interruptMsgProc);
19751987 }
19761988
19771989
@@ -2941,7 +2953,7 @@ bool PeerLogicValidation::ProcessMessages(CNode* pfrom, std::atomic<bool>& inter
29412953 bool fMoreWork = false ;
29422954
29432955 if (!pfrom->vRecvGetData .empty ())
2944- ProcessGetData (pfrom, chainparams. GetConsensus () , connman, interruptMsgProc);
2956+ ProcessGetData (pfrom, chainparams, connman, interruptMsgProc);
29452957
29462958 if (pfrom->fDisconnect )
29472959 return false ;
0 commit comments