mirror of
https://github.com/dashpay/dash.git
synced 2024-12-25 20:12:57 +01:00
Merge bitcoin#13151: net: Serve blocks directly from disk when possible (#3408)
* Merge #13151: net: Serve blocks directly from disk when possible 0bf431870e45d8e20c4671e51a782ebf97b75fac net: Serve blocks directly from disk when possible (Wladimir J. van der Laan) Pull request description: In `ProcessGetBlockData`, send the block data directly from disk if type MSG_WITNESS_BLOCK is requested. This is a valid shortcut as the on-disk format matches the network format. This is expected to increase performance because a deserialization and subsequent serialization roundtrip is avoided. Tree-SHA512: 9a9500b4c1354eaae1a6f1c6ef2416c1c1985029852589266f3a70e808f6c7482c135e9ab251a527566935378ab7c32dba4ed43ba5451e802d8e72b77d1ba472 Signed-off-by: Pasta <pasta@dashboost.org> # Conflicts: # src/net_processing.cpp # src/validation.cpp * fix extra bracket Signed-off-by: Pasta <pasta@dashboost.org> * remove read raw block from disk functions Signed-off-by: Pasta <pasta@dashboost.org> * correct `if (pblock)` scope Signed-off-by: Pasta <pasta@dashboost.org> Co-authored-by: Wladimir J. van der Laan <laanwj@gmail.com>
This commit is contained in:
parent
de931a25a3
commit
3d175aa2e5
@ -1375,11 +1375,12 @@ static void RelayAddress(const CAddress& addr, bool fReachable, CConnman* connma
|
||||
connman->ForEachNodeThen(std::move(sortfunc), std::move(pushfunc));
|
||||
}
|
||||
|
||||
void static ProcessGetBlockData(CNode* pfrom, const Consensus::Params& consensusParams, const CInv& inv, CConnman* connman, const std::atomic<bool>& interruptMsgProc)
|
||||
void static ProcessGetBlockData(CNode* pfrom, const CChainParams& chainparams, const CInv& inv, CConnman* connman, const std::atomic<bool>& interruptMsgProc)
|
||||
{
|
||||
bool send = false;
|
||||
std::shared_ptr<const CBlock> a_recent_block;
|
||||
std::shared_ptr<const CBlockHeaderAndShortTxIDs> a_recent_compact_block;
|
||||
const Consensus::Params& consensusParams = chainparams.GetConsensus();
|
||||
{
|
||||
LOCK(cs_most_recent_block);
|
||||
a_recent_block = most_recent_block;
|
||||
@ -1451,52 +1452,52 @@ void static ProcessGetBlockData(CNode* pfrom, const Consensus::Params& consensus
|
||||
assert(!"cannot load block from disk");
|
||||
pblock = pblockRead;
|
||||
}
|
||||
if (inv.type == MSG_BLOCK)
|
||||
connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::BLOCK, *pblock));
|
||||
else if (inv.type == MSG_FILTERED_BLOCK)
|
||||
{
|
||||
bool sendMerkleBlock = false;
|
||||
CMerkleBlock merkleBlock;
|
||||
{
|
||||
LOCK(pfrom->cs_filter);
|
||||
if (pfrom->pfilter) {
|
||||
sendMerkleBlock = true;
|
||||
merkleBlock = CMerkleBlock(*pblock, *pfrom->pfilter);
|
||||
}
|
||||
}
|
||||
if (sendMerkleBlock) {
|
||||
connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::MERKLEBLOCK, merkleBlock));
|
||||
// CMerkleBlock just contains hashes, so also push any transactions in the block the client did not see
|
||||
// This avoids hurting performance by pointlessly requiring a round-trip
|
||||
// Note that there is currently no way for a node to request any single transactions we didn't send here -
|
||||
// they must either disconnect and retry or request the full block.
|
||||
// Thus, the protocol spec specified allows for us to provide duplicate txn here,
|
||||
// however we MUST always provide at least what the remote peer needs
|
||||
typedef std::pair<unsigned int, uint256> PairType;
|
||||
for (PairType& pair : merkleBlock.vMatchedTxn)
|
||||
connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::TX, *pblock->vtx[pair.first]));
|
||||
}
|
||||
// else
|
||||
// no response
|
||||
}
|
||||
else if (inv.type == MSG_CMPCT_BLOCK)
|
||||
{
|
||||
// If a peer is asking for old blocks, we're almost guaranteed
|
||||
// they won't have a useful mempool to match against a compact block,
|
||||
// and we don't feel like constructing the object for them, so
|
||||
// instead we respond with the full, non-compact block.
|
||||
if (CanDirectFetch(consensusParams) && mi->second->nHeight >= chainActive.Height() - MAX_CMPCTBLOCK_DEPTH) {
|
||||
if (a_recent_compact_block && a_recent_compact_block->header.GetHash() == mi->second->GetBlockHash()) {
|
||||
connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::CMPCTBLOCK, *a_recent_compact_block));
|
||||
} else {
|
||||
CBlockHeaderAndShortTxIDs cmpctblock(*pblock);
|
||||
connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::CMPCTBLOCK, cmpctblock));
|
||||
}
|
||||
} else {
|
||||
if (pblock) {
|
||||
if (inv.type == MSG_BLOCK)
|
||||
connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::BLOCK, *pblock));
|
||||
else if (inv.type == MSG_FILTERED_BLOCK) {
|
||||
bool sendMerkleBlock = false;
|
||||
CMerkleBlock merkleBlock;
|
||||
{
|
||||
LOCK(pfrom->cs_filter);
|
||||
if (pfrom->pfilter) {
|
||||
sendMerkleBlock = true;
|
||||
merkleBlock = CMerkleBlock(*pblock, *pfrom->pfilter);
|
||||
}
|
||||
}
|
||||
if (sendMerkleBlock) {
|
||||
connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::MERKLEBLOCK, merkleBlock));
|
||||
// CMerkleBlock just contains hashes, so also push any transactions in the block the client did not see
|
||||
// This avoids hurting performance by pointlessly requiring a round-trip
|
||||
// Note that there is currently no way for a node to request any single transactions we didn't send here -
|
||||
// they must either disconnect and retry or request the full block.
|
||||
// Thus, the protocol spec specified allows for us to provide duplicate txn here,
|
||||
// however we MUST always provide at least what the remote peer needs
|
||||
typedef std::pair<unsigned int, uint256> PairType;
|
||||
for (PairType &pair : merkleBlock.vMatchedTxn)
|
||||
connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::TX, *pblock->vtx[pair.first]));
|
||||
}
|
||||
// else
|
||||
// no response
|
||||
} else if (inv.type == MSG_CMPCT_BLOCK) {
|
||||
// If a peer is asking for old blocks, we're almost guaranteed
|
||||
// they won't have a useful mempool to match against a compact block,
|
||||
// and we don't feel like constructing the object for them, so
|
||||
// instead we respond with the full, non-compact block.
|
||||
if (CanDirectFetch(consensusParams) &&
|
||||
mi->second->nHeight >= chainActive.Height() - MAX_CMPCTBLOCK_DEPTH) {
|
||||
if (a_recent_compact_block &&
|
||||
a_recent_compact_block->header.GetHash() == mi->second->GetBlockHash()) {
|
||||
connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::CMPCTBLOCK, *a_recent_compact_block));
|
||||
} else {
|
||||
CBlockHeaderAndShortTxIDs cmpctblock(*pblock);
|
||||
connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::CMPCTBLOCK, cmpctblock));
|
||||
}
|
||||
} else {
|
||||
connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::BLOCK, *pblock));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Trigger the peer node to send a getblocks request for the next batch of inventory
|
||||
if (inv.hash == pfrom->hashContinue)
|
||||
{
|
||||
@ -1511,7 +1512,7 @@ void static ProcessGetBlockData(CNode* pfrom, const Consensus::Params& consensus
|
||||
}
|
||||
}
|
||||
|
||||
void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParams, CConnman* connman, const std::atomic<bool>& interruptMsgProc)
|
||||
void static ProcessGetData(CNode* pfrom, const CChainParams& chainparams, CConnman* connman, const std::atomic<bool>& interruptMsgProc)
|
||||
{
|
||||
AssertLockNotHeld(cs_main);
|
||||
|
||||
@ -1681,7 +1682,7 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
|
||||
const CInv &inv = *it;
|
||||
if (inv.type == MSG_BLOCK || inv.type == MSG_FILTERED_BLOCK || inv.type == MSG_CMPCT_BLOCK) {
|
||||
it++;
|
||||
ProcessGetBlockData(pfrom, consensusParams, inv, connman, interruptMsgProc);
|
||||
ProcessGetBlockData(pfrom, chainparams, inv, connman, interruptMsgProc);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2520,7 +2521,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
|
||||
}
|
||||
|
||||
pfrom->vRecvGetData.insert(pfrom->vRecvGetData.end(), vInv.begin(), vInv.end());
|
||||
ProcessGetData(pfrom, chainparams.GetConsensus(), connman, interruptMsgProc);
|
||||
ProcessGetData(pfrom, chainparams, connman, interruptMsgProc);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -3542,7 +3543,7 @@ bool PeerLogicValidation::ProcessMessages(CNode* pfrom, std::atomic<bool>& inter
|
||||
fRetDidWork = false;
|
||||
|
||||
if (!pfrom->vRecvGetData.empty()) {
|
||||
ProcessGetData(pfrom, chainparams.GetConsensus(), connman, interruptMsgProc);
|
||||
ProcessGetData(pfrom, chainparams, connman, interruptMsgProc);
|
||||
fRetDidWork = true;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user