aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatt Corallo <git@bluematt.me>2012-08-18 23:45:19 -0400
committerMatt Corallo <git@bluematt.me>2013-01-16 12:48:02 -0500
commitb02ddbedcba4f9d86b1aabeb71fe18ec03f9a41a (patch)
tree95b8b58eb53300a67d47b2419f218a1269de1ca8
parent2878c67cb5e19c6ea8a013b606e82339c8fb8209 (diff)
Relay CMerkleBlocks when asked for MSG_FILTERED_BLOCK
-rw-r--r--src/main.cpp26
-rw-r--r--src/protocol.cpp1
-rw-r--r--src/protocol.h3
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__