@@ -752,6 +752,10 @@ void PeerLogicValidation::SyncTransaction(const CTransaction& tx, const CBlockIn
752
752
}
753
753
}
754
754
755
+ static CCriticalSection cs_most_recent_block;
756
+ static std::shared_ptr<const CBlock> most_recent_block;
757
+ static uint256 most_recent_block_hash;
758
+
755
759
void PeerLogicValidation::NewPoWValidBlock (const CBlockIndex *pindex, const std::shared_ptr<const CBlock>& pblock) {
756
760
CBlockHeaderAndShortTxIDs cmpctblock (*pblock, true );
757
761
CNetMsgMaker msgMaker (PROTOCOL_VERSION);
@@ -766,6 +770,12 @@ void PeerLogicValidation::NewPoWValidBlock(const CBlockIndex *pindex, const std:
766
770
bool fWitnessEnabled = IsWitnessEnabled (pindex->pprev , Params ().GetConsensus ());
767
771
uint256 hashBlock (pblock->GetHash ());
768
772
773
+ {
774
+ LOCK (cs_most_recent_block);
775
+ most_recent_block_hash = hashBlock;
776
+ most_recent_block = pblock;
777
+ }
778
+
769
779
connman->ForEachNode ([this , &cmpctblock, pindex, &msgMaker, fWitnessEnabled , &hashBlock](CNode* pnode) {
770
780
// TODO: Avoid the repeated-serialization here
771
781
if (pnode->nVersion < INVALID_CB_NO_BAN_VERSION || pnode->fDisconnect )
@@ -1090,6 +1100,23 @@ uint32_t GetFetchFlags(CNode* pfrom, const CBlockIndex* pprev, const Consensus::
1090
1100
return nFetchFlags;
1091
1101
}
1092
1102
1103
+ inline void static SendBlockTransactions (const CBlock& block, const BlockTransactionsRequest& req, CNode* pfrom, CConnman& connman) {
1104
+ BlockTransactions resp (req);
1105
+ for (size_t i = 0 ; i < req.indexes .size (); i++) {
1106
+ if (req.indexes [i] >= block.vtx .size ()) {
1107
+ LOCK (cs_main);
1108
+ Misbehaving (pfrom->GetId (), 100 );
1109
+ LogPrintf (" Peer %d sent us a getblocktxn with out-of-bounds tx indices" , pfrom->id );
1110
+ return ;
1111
+ }
1112
+ resp.txn [i] = block.vtx [req.indexes [i]];
1113
+ }
1114
+ LOCK (cs_main);
1115
+ CNetMsgMaker msgMaker (pfrom->GetSendVersion ());
1116
+ int nSendFlags = State (pfrom->GetId ())->fWantsCmpctWitness ? 0 : SERIALIZE_TRANSACTION_NO_WITNESS;
1117
+ connman.PushMessage (pfrom, msgMaker.Make (nSendFlags, NetMsgType::BLOCKTXN, resp));
1118
+ }
1119
+
1093
1120
bool static ProcessMessage (CNode* pfrom, string strCommand, CDataStream& vRecv, int64_t nTimeReceived, const CChainParams& chainparams, CConnman& connman, std::atomic<bool >& interruptMsgProc)
1094
1121
{
1095
1122
unsigned int nMaxSendBufferSize = connman.GetSendBufferSize ();
@@ -1529,6 +1556,18 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
1529
1556
BlockTransactionsRequest req;
1530
1557
vRecv >> req;
1531
1558
1559
+ std::shared_ptr<const CBlock> recent_block;
1560
+ {
1561
+ LOCK (cs_most_recent_block);
1562
+ if (most_recent_block_hash == req.blockhash )
1563
+ recent_block = most_recent_block;
1564
+ // Unlock cs_most_recent_block to avoid cs_main lock inversion
1565
+ }
1566
+ if (recent_block) {
1567
+ SendBlockTransactions (*recent_block, req, pfrom, connman);
1568
+ return true ;
1569
+ }
1570
+
1532
1571
LOCK (cs_main);
1533
1572
1534
1573
BlockMap::iterator it = mapBlockIndex.find (req.blockhash );
@@ -1558,17 +1597,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
1558
1597
bool ret = ReadBlockFromDisk (block, it->second , chainparams.GetConsensus ());
1559
1598
assert (ret);
1560
1599
1561
- BlockTransactions resp (req);
1562
- for (size_t i = 0 ; i < req.indexes .size (); i++) {
1563
- if (req.indexes [i] >= block.vtx .size ()) {
1564
- Misbehaving (pfrom->GetId (), 100 );
1565
- LogPrintf (" Peer %d sent us a getblocktxn with out-of-bounds tx indices" , pfrom->id );
1566
- return true ;
1567
- }
1568
- resp.txn [i] = block.vtx [req.indexes [i]];
1569
- }
1570
- int nSendFlags = State (pfrom->GetId ())->fWantsCmpctWitness ? 0 : SERIALIZE_TRANSACTION_NO_WITNESS;
1571
- connman.PushMessage (pfrom, msgMaker.Make (nSendFlags, NetMsgType::BLOCKTXN, resp));
1600
+ SendBlockTransactions (block, req, pfrom, connman);
1572
1601
}
1573
1602
1574
1603
0 commit comments