aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSuhas Daftuar <sdaftuar@gmail.com>2016-12-14 17:00:06 -0500
committerSuhas Daftuar <sdaftuar@gmail.com>2016-12-14 17:00:06 -0500
commit4ced31325699dc308571010ce004376d2915cd7e (patch)
tree75f3191e794c5e9deb1e94ea933a112af40fd113
parent0a4aa876230c602427aa40b47a84698a3fd28e85 (diff)
downloadbitcoin-4ced31325699dc308571010ce004376d2915cd7e.tar.xz
Allow compactblock reconstruction when block is in flight
-rw-r--r--src/main.cpp49
1 files changed, 49 insertions, 0 deletions
diff --git a/src/main.cpp b/src/main.cpp
index 191bcff4cc..976e130f1a 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -5657,6 +5657,11 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
CBlockHeaderAndShortTxIDs cmpctblock;
vRecv >> cmpctblock;
+ // Keep a CBlock for "optimistic" compactblock reconstructions (see
+ // below)
+ CBlock block;
+ bool fBlockReconstructed = false;
+
LOCK(cs_main);
if (mapBlockIndex.find(cmpctblock.header.hashPrevBlock) == mapBlockIndex.end()) {
@@ -5765,6 +5770,23 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
req.blockhash = pindex->GetBlockHash();
pfrom->PushMessage(NetMsgType::GETBLOCKTXN, req);
}
+ } else {
+ // This block is either already in flight from a different
+ // peer, or this peer has too many blocks outstanding to
+ // download from.
+ // Optimistically try to reconstruct anyway since we might be
+ // able to without any round trips.
+ PartiallyDownloadedBlock tempBlock(&mempool);
+ ReadStatus status = tempBlock.InitData(cmpctblock);
+ if (status != READ_STATUS_OK) {
+ // TODO: don't ignore failures
+ return true;
+ }
+ std::vector<CTransaction> dummy;
+ status = tempBlock.FillBlock(block, dummy);
+ if (status == READ_STATUS_OK) {
+ fBlockReconstructed = true;
+ }
}
} else {
if (fAlreadyInFlight) {
@@ -5785,6 +5807,33 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
}
}
+ if (fBlockReconstructed) {
+ // If we got here, we were able to optimistically reconstruct a
+ // block that is in flight from some other peer. However, this
+ // cmpctblock may be invalid. In particular, while we've checked
+ // that the block merkle root commits to the transaction ids, we
+ // haven't yet checked that tx witnesses are properly committed to
+ // in the coinbase witness commitment.
+ //
+ // ProcessNewBlock will call MarkBlockAsReceived(), which will
+ // clear any in-flight compact block state that might be present
+ // from some other peer. We don't want a malleated compact block
+ // request to interfere with block relay, so we don't want to call
+ // ProcessNewBlock until we've already checked that the witness
+ // commitment is correct.
+ {
+ LOCK(cs_main);
+ CValidationState dummy;
+ if (!ContextualCheckBlock(block, dummy, pindex->pprev)) {
+ // TODO: could send reject message to peer?
+ return true;
+ }
+ }
+ CValidationState state;
+ ProcessNewBlock(state, chainparams, pfrom, &block, true, NULL, false);
+ // TODO: could send reject message if block is invalid?
+ }
+
CheckBlockIndex(chainparams.GetConsensus());
}