@@ -3068,15 +3068,37 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
30683068 if (fDebugNet || (vInv.size () == 1 ))
30693069 printf (" received getdata for: %s\n " , inv.ToString ().c_str ());
30703070
3071- if (inv.type == MSG_BLOCK)
3071+ if (inv.type == MSG_BLOCK || inv. type == MSG_FILTERED_BLOCK )
30723072 {
30733073 // Send block from disk
30743074 map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find (inv.hash );
30753075 if (mi != mapBlockIndex.end ())
30763076 {
30773077 CBlock block;
30783078 block.ReadFromDisk ((*mi).second );
3079- pfrom->PushMessage (" block" , block);
3079+ if (inv.type == MSG_BLOCK)
3080+ pfrom->PushMessage (" block" , block);
3081+ else // MSG_FILTERED_BLOCK)
3082+ {
3083+ LOCK (pfrom->cs_filter );
3084+ if (pfrom->pfilter )
3085+ {
3086+ CMerkleBlock merkleBlock (block, *pfrom->pfilter );
3087+ typedef boost::tuple<unsigned int , uint256, std::vector<uint256> > TupleType;
3088+ // CMerkleBlock just contains hashes, so also push any transactions in the block the client did not see
3089+ // This avoids hurting performance by pointlessly requiring a round-trip
3090+ // Note that there is currently no way for a node to request any single transactions we didnt send here -
3091+ // they must either disconnect and retry or request the full block.
3092+ // Thus, the protocol spec specified allows for us to provide duplicate txn here,
3093+ // however we MUST always provide at least what the remote peer needs
3094+ BOOST_FOREACH (TupleType& tuple, merkleBlock.vtx )
3095+ if (!pfrom->setInventoryKnown .count (CInv (MSG_TX, get<1 >(tuple))))
3096+ pfrom->PushMessage (" tx" , block.vtx [get<0 >(tuple)]);
3097+ pfrom->PushMessage (" merkleblock" , merkleBlock);
3098+ }
3099+ // else
3100+ // no response
3101+ }
30803102
30813103 // Trigger them to send a getblocks request for the next batch of inventory
30823104 if (inv.hash == pfrom->hashContinue )
0 commit comments