When a node receives a cmpctblock
it has to verify to its check mempool in order to know whether it has all the required transactions to construct that block. If it doesn’t, it will send getblocktxn
to fetch the missing tx{s}.
PartiallyDownloadedBlock::InitData
shows we have to iterate the whole mempool in order to get the short id and do the verifications, see:
0for (size_t i = 0; i < pool->vTxHashes.size(); i++) {
1 uint64_t shortid = cmpctblock.GetShortID(pool->vTxHashes[i].first);
2 std::unordered_map<uint64_t, uint16_t>::iterator idit = shorttxids.find(shortid);
3 if (idit != shorttxids.end()) {
4 if (!have_txn[idit->second]) {
5 txn_available[idit->second] = pool->vTxHashes[i].second->GetSharedTx();
6 have_txn[idit->second] = true;
7 mempool_count++;
8 } else {
9 // If we find two mempool txn that match the short id, just request it.
10 // This should be rare enough that the extra bandwidth doesn't matter,
11 // but eating a round-trip due to FillBlock failure would be annoying
12 if (txn_available[idit->second]) {
13 txn_available[idit->second].reset();
14 mempool_count--;
15 }
16 }
17 }
18 // Though ideally we'd continue scanning for the two-txn-match-shortid case,
19 // the performance win of an early exit here is too good to pass up and worth
20 // the extra risk.
21 if (mempool_count == shorttxids.size())
22 break;
23}
This means that every time we receive a compact block we have to iterate the whole mempool and calculate the “short id"s all over again. Couldn’tCTxMemPool
have a hashmap where we could store the transactions’ short id right after joining the mempool and remove it once the tx gets confirmed/out of mempool?