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
This commit is contained in:
commit
eab00d96df
1 changed files with 36 additions and 18 deletions
|
@ -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 CCriticalSection cs_most_recent_block;
|
||||||
static std::shared_ptr<const CBlock> most_recent_block;
|
static std::shared_ptr<const CBlock> most_recent_block;
|
||||||
static std::shared_ptr<const CBlockHeaderAndShortTxIDs> most_recent_compact_block;
|
static std::shared_ptr<const CBlockHeaderAndShortTxIDs> most_recent_compact_block;
|
||||||
static uint256 most_recent_block_hash;
|
static uint256 most_recent_block_hash;
|
||||||
|
static bool fWitnessesPresentInMostRecentCompactBlock;
|
||||||
|
|
||||||
void PeerLogicValidation::NewPoWValidBlock(const CBlockIndex *pindex, const std::shared_ptr<const CBlock>& pblock) {
|
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);
|
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:
|
||||||
most_recent_block_hash = hashBlock;
|
most_recent_block_hash = hashBlock;
|
||||||
most_recent_block = pblock;
|
most_recent_block = pblock;
|
||||||
most_recent_compact_block = pcmpctblock;
|
most_recent_compact_block = pcmpctblock;
|
||||||
|
fWitnessesPresentInMostRecentCompactBlock = fWitnessEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
connman->ForEachNode([this, &pcmpctblock, pindex, &msgMaker, fWitnessEnabled, &hashBlock](CNode* pnode) {
|
connman->ForEachNode([this, &pcmpctblock, pindex, &msgMaker, fWitnessEnabled, &hashBlock](CNode* pnode) {
|
||||||
|
@ -990,6 +993,15 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
|
||||||
{
|
{
|
||||||
bool send = false;
|
bool send = false;
|
||||||
BlockMap::iterator mi = mapBlockIndex.find(inv.hash);
|
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 != mapBlockIndex.end())
|
||||||
{
|
{
|
||||||
if (mi->second->nChainTx && !mi->second->IsValid(BLOCK_VALID_SCRIPTS) &&
|
if (mi->second->nChainTx && !mi->second->IsValid(BLOCK_VALID_SCRIPTS) &&
|
||||||
|
@ -999,11 +1011,6 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
|
||||||
// before ActivateBestChain but after AcceptBlock).
|
// before ActivateBestChain but after AcceptBlock).
|
||||||
// In this case, we need to run ActivateBestChain prior to checking the relay
|
// In this case, we need to run ActivateBestChain prior to checking the relay
|
||||||
// conditions below.
|
// conditions below.
|
||||||
std::shared_ptr<const CBlock> a_recent_block;
|
|
||||||
{
|
|
||||||
LOCK(cs_most_recent_block);
|
|
||||||
a_recent_block = most_recent_block;
|
|
||||||
}
|
|
||||||
CValidationState dummy;
|
CValidationState dummy;
|
||||||
ActivateBestChain(dummy, Params(), a_recent_block);
|
ActivateBestChain(dummy, Params(), a_recent_block);
|
||||||
}
|
}
|
||||||
|
@ -1037,14 +1044,20 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
|
||||||
// it's available before trying to send.
|
// it's available before trying to send.
|
||||||
if (send && (mi->second->nStatus & BLOCK_HAVE_DATA))
|
if (send && (mi->second->nStatus & BLOCK_HAVE_DATA))
|
||||||
{
|
{
|
||||||
|
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
|
// Send block from disk
|
||||||
CBlock block;
|
std::shared_ptr<CBlock> pblockRead = std::make_shared<CBlock>();
|
||||||
if (!ReadBlockFromDisk(block, (*mi).second, consensusParams))
|
if (!ReadBlockFromDisk(*pblockRead, (*mi).second, consensusParams))
|
||||||
assert(!"cannot load block from disk");
|
assert(!"cannot load block from disk");
|
||||||
|
pblock = pblockRead;
|
||||||
|
}
|
||||||
if (inv.type == MSG_BLOCK)
|
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, *pblock));
|
||||||
else if (inv.type == MSG_WITNESS_BLOCK)
|
else if (inv.type == MSG_WITNESS_BLOCK)
|
||||||
connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::BLOCK, block));
|
connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::BLOCK, *pblock));
|
||||||
else if (inv.type == MSG_FILTERED_BLOCK)
|
else if (inv.type == MSG_FILTERED_BLOCK)
|
||||||
{
|
{
|
||||||
bool sendMerkleBlock = false;
|
bool sendMerkleBlock = false;
|
||||||
|
@ -1053,7 +1066,7 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
|
||||||
LOCK(pfrom->cs_filter);
|
LOCK(pfrom->cs_filter);
|
||||||
if (pfrom->pfilter) {
|
if (pfrom->pfilter) {
|
||||||
sendMerkleBlock = true;
|
sendMerkleBlock = true;
|
||||||
merkleBlock = CMerkleBlock(block, *pfrom->pfilter);
|
merkleBlock = CMerkleBlock(*pblock, *pfrom->pfilter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (sendMerkleBlock) {
|
if (sendMerkleBlock) {
|
||||||
|
@ -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
|
// however we MUST always provide at least what the remote peer needs
|
||||||
typedef std::pair<unsigned int, uint256> PairType;
|
typedef std::pair<unsigned int, uint256> PairType;
|
||||||
BOOST_FOREACH(PairType& pair, merkleBlock.vMatchedTxn)
|
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
|
// else
|
||||||
// no response
|
// no response
|
||||||
|
@ -1080,10 +1093,15 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
|
||||||
bool fPeerWantsWitness = State(pfrom->GetId())->fWantsCmpctWitness;
|
bool fPeerWantsWitness = State(pfrom->GetId())->fWantsCmpctWitness;
|
||||||
int nSendFlags = fPeerWantsWitness ? 0 : SERIALIZE_TRANSACTION_NO_WITNESS;
|
int nSendFlags = fPeerWantsWitness ? 0 : SERIALIZE_TRANSACTION_NO_WITNESS;
|
||||||
if (CanDirectFetch(consensusParams) && mi->second->nHeight >= chainActive.Height() - MAX_CMPCTBLOCK_DEPTH) {
|
if (CanDirectFetch(consensusParams) && mi->second->nHeight >= chainActive.Height() - MAX_CMPCTBLOCK_DEPTH) {
|
||||||
CBlockHeaderAndShortTxIDs cmpctblock(block, fPeerWantsWitness);
|
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));
|
connman.PushMessage(pfrom, msgMaker.Make(nSendFlags, NetMsgType::CMPCTBLOCK, cmpctblock));
|
||||||
} else
|
}
|
||||||
connman.PushMessage(pfrom, msgMaker.Make(nSendFlags, NetMsgType::BLOCK, block));
|
} 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
|
// 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
|
||||||
{
|
{
|
||||||
LOCK(cs_most_recent_block);
|
LOCK(cs_most_recent_block);
|
||||||
if (most_recent_block_hash == pBestIndex->GetBlockHash()) {
|
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));
|
connman.PushMessage(pto, msgMaker.Make(nSendFlags, NetMsgType::CMPCTBLOCK, *most_recent_compact_block));
|
||||||
else {
|
else {
|
||||||
CBlockHeaderAndShortTxIDs cmpctblock(*most_recent_block, state.fWantsCmpctWitness);
|
CBlockHeaderAndShortTxIDs cmpctblock(*most_recent_block, state.fWantsCmpctWitness);
|
||||||
|
|
Loading…
Reference in a new issue