diff options
author | Matt Corallo <git@bluematt.me> | 2012-08-18 23:45:19 -0400 |
---|---|---|
committer | Matt Corallo <git@bluematt.me> | 2013-01-16 12:48:02 -0500 |
commit | b02ddbedcba4f9d86b1aabeb71fe18ec03f9a41a (patch) | |
tree | 95b8b58eb53300a67d47b2419f218a1269de1ca8 | |
parent | 2878c67cb5e19c6ea8a013b606e82339c8fb8209 (diff) |
Relay CMerkleBlocks when asked for MSG_FILTERED_BLOCK
-rw-r--r-- | src/main.cpp | 26 | ||||
-rw-r--r-- | src/protocol.cpp | 1 | ||||
-rw-r--r-- | src/protocol.h | 3 |
3 files changed, 28 insertions, 2 deletions
diff --git a/src/main.cpp b/src/main.cpp index bd5b2408a0..abb0174edd 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3068,7 +3068,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) if (fDebugNet || (vInv.size() == 1)) 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 map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(inv.hash); @@ -3076,7 +3076,29 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) { CBlock block; 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 if (inv.hash == pfrom->hashContinue) diff --git a/src/protocol.cpp b/src/protocol.cpp index 23969e5b97..7b42f5270b 100644 --- a/src/protocol.cpp +++ b/src/protocol.cpp @@ -17,6 +17,7 @@ static const char* ppszTypeName[] = "ERROR", "tx", "block", + "filtered block" }; CMessageHeader::CMessageHeader() diff --git a/src/protocol.h b/src/protocol.h index 96fd197ecd..f5c162054e 100644 --- a/src/protocol.h +++ b/src/protocol.h @@ -138,6 +138,9 @@ enum { MSG_TX = 1, 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__ |