@@ -1070,12 +1070,13 @@ static void RelayAddress(const CAddress& addr, bool fReachable, CConnman* connma
1070
1070
connman->ForEachNodeThen (std::move (sortfunc), std::move (pushfunc));
1071
1071
}
1072
1072
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)
1074
1074
{
1075
1075
bool send = false ;
1076
1076
std::shared_ptr<const CBlock> a_recent_block;
1077
1077
std::shared_ptr<const CBlockHeaderAndShortTxIDs> a_recent_compact_block;
1078
1078
bool fWitnessesPresentInARecentCompactBlock ;
1079
+ const Consensus::Params& consensusParams = chainparams.GetConsensus ();
1079
1080
{
1080
1081
LOCK (cs_most_recent_block);
1081
1082
a_recent_block = most_recent_block;
@@ -1142,60 +1143,71 @@ void static ProcessGetBlockData(CNode* pfrom, const Consensus::Params& consensus
1142
1143
std::shared_ptr<const CBlock> pblock;
1143
1144
if (a_recent_block && a_recent_block->GetHash () == pindex->GetBlockHash ()) {
1144
1145
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
1145
1155
} else {
1146
1156
// Send block from disk
1147
1157
std::shared_ptr<CBlock> pblockRead = std::make_shared<CBlock>();
1148
1158
if (!ReadBlockFromDisk (*pblockRead, pindex, consensusParams))
1149
1159
assert (!" cannot load block from disk" );
1150
1160
pblock = pblockRead;
1151
1161
}
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)
1160
1168
{
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 ]));
1165
1189
}
1190
+ // else
1191
+ // no response
1166
1192
}
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
+ }
1193
1208
} 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));
1196
1210
}
1197
- } else {
1198
- connman->PushMessage (pfrom, msgMaker.Make (nSendFlags, NetMsgType::BLOCK, *pblock));
1199
1211
}
1200
1212
}
1201
1213
@@ -1213,7 +1225,7 @@ void static ProcessGetBlockData(CNode* pfrom, const Consensus::Params& consensus
1213
1225
}
1214
1226
}
1215
1227
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)
1217
1229
{
1218
1230
AssertLockNotHeld (cs_main);
1219
1231
@@ -1262,7 +1274,7 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
1262
1274
const CInv &inv = *it;
1263
1275
if (inv.type == MSG_BLOCK || inv.type == MSG_FILTERED_BLOCK || inv.type == MSG_CMPCT_BLOCK || inv.type == MSG_WITNESS_BLOCK) {
1264
1276
it++;
1265
- ProcessGetBlockData (pfrom, consensusParams , inv, connman, interruptMsgProc);
1277
+ ProcessGetBlockData (pfrom, chainparams , inv, connman, interruptMsgProc);
1266
1278
}
1267
1279
}
1268
1280
@@ -1972,7 +1984,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
1972
1984
}
1973
1985
1974
1986
pfrom->vRecvGetData .insert (pfrom->vRecvGetData .end (), vInv.begin (), vInv.end ());
1975
- ProcessGetData (pfrom, chainparams. GetConsensus () , connman, interruptMsgProc);
1987
+ ProcessGetData (pfrom, chainparams, connman, interruptMsgProc);
1976
1988
}
1977
1989
1978
1990
@@ -2942,7 +2954,7 @@ bool PeerLogicValidation::ProcessMessages(CNode* pfrom, std::atomic<bool>& inter
2942
2954
bool fMoreWork = false ;
2943
2955
2944
2956
if (!pfrom->vRecvGetData .empty ())
2945
- ProcessGetData (pfrom, chainparams. GetConsensus () , connman, interruptMsgProc);
2957
+ ProcessGetData (pfrom, chainparams, connman, interruptMsgProc);
2946
2958
2947
2959
if (pfrom->fDisconnect )
2948
2960
return false ;
0 commit comments