changeset 23730:838c1d5e80cf

Optimize the messaging for XTHINBLOCK requests No longer send a map of all tx's but instead just send a vector. This saves us 256bits per transaction for XTHINBLOCK and THINBLOCK responses.
author Peter Tschipper <peter.tschipper@gmailcom>
date Tue, 08 Mar 2016 10:32:53 -0800
parents aa9d6c8df05b
children a190df3a68eb
files src/main.cpp src/thinblock.cpp src/thinblock.h src/unlimited.cpp
diffstat 4 files changed, 36 insertions(+), 29 deletions(-) [+]
line wrap: on
line diff
--- a/src/main.cpp	Mon Mar 07 15:02:51 2016 -0800
+++ b/src/main.cpp	Tue Mar 08 10:32:53 2016 -0800
@@ -5128,10 +5128,21 @@
         pfrom->thinBlock.hashPrevBlock = thinBlock.header.hashPrevBlock;
         pfrom->xThinBlockHashes = thinBlock.vTxHashes;
 
+
         // Create a map of all 8 bytes tx hashes pointing to their full tx hash counterpart 
         // We need to check all transaction sources (orphan list, mempool, and new (incoming) transactions in this block) for a collision.
         bool collision = false;
         std::map<uint64_t, uint256> mapPartialTxHash;
+        // Create the mapMissingTx from all the supplied tx's in the xthinblock
+        std::map<uint256, CTransaction> mapMissingTx;
+        BOOST_FOREACH(CTransaction tx, thinBlock.vMissingTx) {
+            uint256 hash = tx.GetHash();
+            mapMissingTx[hash] = tx;
+            uint64_t cheapHash = hash.GetCheapHash();
+            if(mapPartialTxHash.count(cheapHash)) //Check for collisions
+                collision = true;
+            mapPartialTxHash[cheapHash] = hash;
+        }
         LOCK(cs_main);
         std::vector<uint256> memPoolHashes;
         mempool.queryHashes(memPoolHashes);
@@ -5141,12 +5152,6 @@
                 collision = true;
             mapPartialTxHash[cheapHash] = memPoolHashes[i];
         }
-        for (map<uint256, CTransaction>::iterator mi = thinBlock.mapMissingTx.begin(); mi != thinBlock.mapMissingTx.end(); ++mi) {
-            uint64_t cheapHash = (*mi).first.GetCheapHash();
-            if(mapPartialTxHash.count(cheapHash)) //Check for collisions
-                collision = true;
-            mapPartialTxHash[cheapHash] = (*mi).first;
-        }
         for (map<uint256, COrphanTx>::iterator mi = mapOrphanTransactions.begin(); mi != mapOrphanTransactions.end(); ++mi) {
             uint64_t cheapHash = (*mi).first.GetCheapHash();
             if(mapPartialTxHash.count(cheapHash)) //Check for collisions
@@ -5179,7 +5184,7 @@
             if (!hash.IsNull())
             {
                 bool inMemPool = mempool.lookup(hash, tx);
-                bool inMissingTx = thinBlock.mapMissingTx.count(hash) > 0;
+                bool inMissingTx = mapMissingTx.count(hash) > 0;
                 bool inOrphanCache = mapOrphanTransactions.count(hash) > 0;
 
                 if ((inMemPool && inMissingTx) || (inOrphanCache && inMissingTx))
@@ -5192,7 +5197,7 @@
                 else if (inMemPool && fXVal)
                     setPreVerifiedTxHash.insert(hash);
                 else if (inMissingTx)
-                    tx = thinBlock.mapMissingTx[hash];
+                    tx = mapMissingTx[hash];
             }
             if (tx.IsNull())
                 missingCount++;
@@ -5200,7 +5205,7 @@
             pfrom->thinBlock.vtx.push_back(tx);
         }
         pfrom->thinBlockWaitingForTxns = missingCount;
-        LogPrint("thin", "thinblock waiting for: %d, unnecessary: %d, txs: %d full: %d\n", pfrom->thinBlockWaitingForTxns, unnecessaryCount, pfrom->thinBlock.vtx.size(), thinBlock.mapMissingTx.size());
+        LogPrint("thin", "thinblock waiting for: %d, unnecessary: %d, txs: %d full: %d\n", pfrom->thinBlockWaitingForTxns, unnecessaryCount, pfrom->thinBlock.vtx.size(), mapMissingTx.size());
 
         if (pfrom->thinBlockWaitingForTxns == 0) {
             // We have all the transactions now that are in this block: try to reassemble and process.
@@ -5259,6 +5264,11 @@
         pfrom->thinBlock.hashPrevBlock = thinBlock.header.hashPrevBlock;
         pfrom->thinBlockHashes = thinBlock.vTxHashes;
 
+        // Create the mapMissingTx from all the supplied tx's in the xthinblock
+        std::map<uint256, CTransaction> mapMissingTx;
+        BOOST_FOREACH(CTransaction tx, thinBlock.vMissingTx) 
+            mapMissingTx[tx.GetHash()] = tx;
+
         LOCK(cs_main);
         int missingCount = 0;
         int unnecessaryCount = 0;
@@ -5272,7 +5282,7 @@
             if (!hash.IsNull())
             {
                 bool inMemPool = mempool.lookup(hash, tx);
-                bool inMissingTx = thinBlock.mapMissingTx.count(hash) > 0;
+                bool inMissingTx = mapMissingTx.count(hash) > 0;
                 bool inOrphanCache = mapOrphanTransactions.count(hash) > 0;
 
                 if ((inMemPool && inMissingTx) || (inOrphanCache && inMissingTx))
@@ -5285,7 +5295,7 @@
                 else if (inMemPool && fXVal)
                     setPreVerifiedTxHash.insert(hash);
                 else if (inMissingTx)
-                    tx = thinBlock.mapMissingTx[hash];
+                    tx = mapMissingTx[hash];
             }
             if (tx.IsNull())
                 missingCount++;
@@ -5293,7 +5303,7 @@
             pfrom->thinBlock.vtx.push_back(tx);
         }
         pfrom->thinBlockWaitingForTxns = missingCount;
-        LogPrint("thin", "thinblock waiting for: %d, unnecessary: %d, txs: %d full: %d\n", pfrom->thinBlockWaitingForTxns, unnecessaryCount, pfrom->thinBlock.vtx.size(), thinBlock.mapMissingTx.size());
+        LogPrint("thin", "thinblock waiting for: %d, unnecessary: %d, txs: %d full: %d\n", pfrom->thinBlockWaitingForTxns, unnecessaryCount, pfrom->thinBlock.vtx.size(), mapMissingTx.size());
 
         if (pfrom->thinBlockWaitingForTxns == 0) {
             // We have all the transactions now that are in this block: try to reassemble and process.
--- a/src/thinblock.cpp	Mon Mar 07 15:02:51 2016 -0800
+++ b/src/thinblock.cpp	Tue Mar 08 10:32:53 2016 -0800
@@ -20,7 +20,7 @@
         // NOTE: We always add the first tx, the coinbase as it is the one
         //       most often missing.
         if (!filter.contains(hash) || i == 0)
-            mapMissingTx[hash] = block.vtx[i];
+            vMissingTx.push_back(block.vtx[i]);
     }
 }
 
@@ -47,7 +47,7 @@
         // NOTE: We always add the first tx, the coinbase as it is the one
         //       most often missing.
         if ((filter && !filter->contains(hash256)) || i == 0)
-            mapMissingTx[hash256] = block.vtx[i];
+            vMissingTx.push_back(block.vtx[i]);
     }
 }
 
@@ -72,12 +72,10 @@
 
         // We always add the first tx, the coinbase as it is the one
         // most often missing.
-        if (i == 0) mapMissingTx[hash256] = block.vtx[i];
+        if (i == 0) vMissingTx.push_back(block.vtx[i]);
     }
 }
 
-
-
 CXThinBlockTx::CXThinBlockTx(uint256 blockHash, std::vector<uint64_t>& vHashesToRequest)
 {
     blockhash = blockHash;
--- a/src/thinblock.h	Mon Mar 07 15:02:51 2016 -0800
+++ b/src/thinblock.h	Tue Mar 08 10:32:53 2016 -0800
@@ -17,7 +17,7 @@
 public:
     CBlockHeader header;
     std::vector<uint256> vTxHashes; // List of all transactions id's in the block
-    std::map<uint256, CTransaction> mapMissingTx; // map of transactions that did not match the bloom filter
+    std::vector<CTransaction> vMissingTx; // vector of transactions that did not match the bloom filter
 
 public:
     CThinBlock(const CBlock& block, CBloomFilter& filter);
@@ -29,7 +29,7 @@
     inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
         READWRITE(header);
         READWRITE(vTxHashes);
-        READWRITE(mapMissingTx);
+        READWRITE(vMissingTx);
     }
 };
 
@@ -38,7 +38,7 @@
 public:
     CBlockHeader header;
     std::vector<uint64_t> vTxHashes; // List of all transactions id's in the block
-    std::map<uint256, CTransaction> mapMissingTx; // map of transactions that did not match the bloom filter
+    std::vector<CTransaction> vMissingTx; // vector of transactions that did not match the bloom filter
     bool collision;
 
 public:
@@ -52,7 +52,7 @@
     inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
         READWRITE(header);
         READWRITE(vTxHashes);
-        READWRITE(mapMissingTx);
+        READWRITE(vMissingTx);
     }
 };
 
--- a/src/unlimited.cpp	Mon Mar 07 15:02:51 2016 -0800
+++ b/src/unlimited.cpp	Tue Mar 08 10:32:53 2016 -0800
@@ -691,8 +691,7 @@
 {
     if (inv.type == MSG_XTHINBLOCK)
     {
-      CXThinBlock xThinBlock(block, pfrom->pfilter);
-      //CXThinBlock xThinBlock(block);
+        CXThinBlock xThinBlock(block, pfrom->pfilter);
         int nSizeBlock = ::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION);
         if (xThinBlock.collision == true) // If there is a cheapHash collision in this block then send a normal thinblock
         {
@@ -700,11 +699,11 @@
             int nSizeThinBlock = ::GetSerializeSize(xThinBlock, SER_NETWORK, PROTOCOL_VERSION);
             if (nSizeThinBlock < nSizeBlock) {
                 pfrom->PushMessage(NetMsgType::THINBLOCK, thinBlock);
-                LogPrint("thin", "TX HASH COLLISION: Sent thinblock - size: %d vs block size: %d => tx hashes: %d transactions: %d  peerid=%d\n", nSizeThinBlock, nSizeBlock, xThinBlock.vTxHashes.size(), xThinBlock.mapMissingTx.size(), pfrom->id);
+                LogPrint("thin", "TX HASH COLLISION: Sent thinblock - size: %d vs block size: %d => tx hashes: %d transactions: %d  peerid=%d\n", nSizeThinBlock, nSizeBlock, xThinBlock.vTxHashes.size(), xThinBlock.vMissingTx.size(), pfrom->id);
             }
             else {
                 pfrom->PushMessage(NetMsgType::BLOCK, block);
-                LogPrint("thin", "Sent regular block instead - xthinblock size: %d vs block size: %d => tx hashes: %d transactions: %d  peerid=%d\n", nSizeThinBlock, nSizeBlock, xThinBlock.vTxHashes.size(), xThinBlock.mapMissingTx.size(), pfrom->id);
+                LogPrint("thin", "Sent regular block instead - xthinblock size: %d vs block size: %d => tx hashes: %d transactions: %d  peerid=%d\n", nSizeThinBlock, nSizeBlock, xThinBlock.vTxHashes.size(), xThinBlock.vMissingTx.size(), pfrom->id);
             }
         }
         else // Send an xThinblock
@@ -713,11 +712,11 @@
             int nSizeThinBlock = ::GetSerializeSize(xThinBlock, SER_NETWORK, PROTOCOL_VERSION);
             if (nSizeThinBlock < nSizeBlock) {
                 pfrom->PushMessage(NetMsgType::XTHINBLOCK, xThinBlock);
-                LogPrint("thin", "Sent xthinblock - size: %d vs block size: %d => tx hashes: %d transactions: %d  peerid=%d\n", nSizeThinBlock, nSizeBlock, xThinBlock.vTxHashes.size(), xThinBlock.mapMissingTx.size(), pfrom->id);
+                LogPrint("thin", "Sent xthinblock - size: %d vs block size: %d => tx hashes: %d transactions: %d  peerid=%d\n", nSizeThinBlock, nSizeBlock, xThinBlock.vTxHashes.size(), xThinBlock.vMissingTx.size(), pfrom->id);
             }
             else {
                 pfrom->PushMessage(NetMsgType::BLOCK, block);
-                LogPrint("thin", "Sent regular block instead - xthinblock size: %d vs block size: %d => tx hashes: %d transactions: %d  peerid=%d\n", nSizeThinBlock, nSizeBlock, xThinBlock.vTxHashes.size(), xThinBlock.mapMissingTx.size(), pfrom->id);
+                LogPrint("thin", "Sent regular block instead - xthinblock size: %d vs block size: %d => tx hashes: %d transactions: %d  peerid=%d\n", nSizeThinBlock, nSizeBlock, xThinBlock.vTxHashes.size(), xThinBlock.vMissingTx.size(), pfrom->id);
             }
         }
     }
@@ -728,11 +727,11 @@
         int nSizeThinBlock = ::GetSerializeSize(thinBlock, SER_NETWORK, PROTOCOL_VERSION);
         if (nSizeThinBlock < nSizeBlock) { // Only send a thinblock if smaller than a regular block
             pfrom->PushMessage(NetMsgType::THINBLOCK, thinBlock);
-            LogPrint("thin", "Sent thinblock - size: %d vs block size: %d => tx hashes: %d transactions: %d  peerid=%d\n", nSizeThinBlock, nSizeBlock, thinBlock.vTxHashes.size(), thinBlock.mapMissingTx.size(), pfrom->id);
+            LogPrint("thin", "Sent thinblock - size: %d vs block size: %d => tx hashes: %d transactions: %d  peerid=%d\n", nSizeThinBlock, nSizeBlock, thinBlock.vTxHashes.size(), thinBlock.vMissingTx.size(), pfrom->id);
         }
         else {
             pfrom->PushMessage(NetMsgType::BLOCK, block);
-            LogPrint("thin", "Sent regular block instead - thinblock size: %d vs block size: %d => tx hashes: %d transactions: %d  peerid=%d\n", nSizeThinBlock, nSizeBlock, thinBlock.vTxHashes.size(), thinBlock.mapMissingTx.size(), pfrom->id);
+            LogPrint("thin", "Sent regular block instead - thinblock size: %d vs block size: %d => tx hashes: %d transactions: %d  peerid=%d\n", nSizeThinBlock, nSizeBlock, thinBlock.vTxHashes.size(), thinBlock.vMissingTx.size(), pfrom->id);
         }
     }
 }