Relay CMerkleBlocks when asked for MSG_FILTERED_BLOCK

This commit is contained in:
Matt Corallo 2012-08-18 23:45:19 -04:00
parent 2878c67cb5
commit b02ddbedcb
3 changed files with 28 additions and 2 deletions

View File

@ -3068,7 +3068,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
if (fDebugNet || (vInv.size() == 1)) if (fDebugNet || (vInv.size() == 1))
printf("received getdata for: %s\n", inv.ToString().c_str()); printf("received getdata for: %s\n", inv.ToString().c_str());
if (inv.type == MSG_BLOCK) if (inv.type == MSG_BLOCK || inv.type == MSG_FILTERED_BLOCK)
{ {
// Send block from disk // Send block from disk
map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(inv.hash); map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(inv.hash);
@ -3076,7 +3076,29 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
{ {
CBlock block; CBlock block;
block.ReadFromDisk((*mi).second); block.ReadFromDisk((*mi).second);
pfrom->PushMessage("block", block); if (inv.type == MSG_BLOCK)
pfrom->PushMessage("block", block);
else // MSG_FILTERED_BLOCK)
{
LOCK(pfrom->cs_filter);
if (pfrom->pfilter)
{
CMerkleBlock merkleBlock(block, *pfrom->pfilter);
typedef boost::tuple<unsigned int, uint256, std::vector<uint256> > TupleType;
// 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 didnt 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
BOOST_FOREACH(TupleType& tuple, merkleBlock.vtx)
if (!pfrom->setInventoryKnown.count(CInv(MSG_TX, get<1>(tuple))))
pfrom->PushMessage("tx", block.vtx[get<0>(tuple)]);
pfrom->PushMessage("merkleblock", merkleBlock);
}
// else
// no response
}
// Trigger them to send a getblocks request for the next batch of inventory // Trigger them to send a getblocks request for the next batch of inventory
if (inv.hash == pfrom->hashContinue) if (inv.hash == pfrom->hashContinue)

View File

@ -17,6 +17,7 @@ static const char* ppszTypeName[] =
"ERROR", "ERROR",
"tx", "tx",
"block", "block",
"filtered block"
}; };
CMessageHeader::CMessageHeader() CMessageHeader::CMessageHeader()

View File

@ -138,6 +138,9 @@ enum
{ {
MSG_TX = 1, MSG_TX = 1,
MSG_BLOCK, MSG_BLOCK,
// Nodes may always request a MSG_FILTERED_BLOCK in a getdata, however,
// MSG_FILTERED_BLOCK should not appear in any invs except as a part of getdata.
MSG_FILTERED_BLOCK,
}; };
#endif // __INCLUDED_PROTOCOL_H__ #endif // __INCLUDED_PROTOCOL_H__