Merge branch 'limitfree' of /Users/gavin/src/integration_btc
authorGavin Andresen <gavinandresen@gmail.com>
Sun, 13 Mar 2011 21:15:44 +0000 (17:15 -0400)
committerGavin Andresen <gavinandresen@gmail.com>
Sun, 13 Mar 2011 21:15:44 +0000 (17:15 -0400)
main.cpp

index 7ddb241..298e76e 100644 (file)
--- a/main.cpp
+++ b/main.cpp
@@ -742,19 +742,29 @@ bool CTransaction::AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs, bool* pfMi
         if (nFees < GetMinFee(1000))
             return error("AcceptToMemoryPool() : not enough fees");
 
-        // Limit free transactions per 10 minutes
-        if (nFees < CENT && GetBoolArg("-limitfreerelay"))
-        {
-            static int64 nNextReset;
-            static int64 nFreeCount;
-            if (GetTime() > nNextReset)
-            {
-                nNextReset = GetTime() + 10 * 60;
-                nFreeCount = 0;
+        // Continuously rate-limit free transactions
+        // This mitigates 'penny-flooding' -- sending thousands of free transactions just to
+        // be annoying or make other's transactions take longer to confirm.
+        if (nFees < CENT)
+        {
+            static CCriticalSection cs;
+            static double dFreeCount;
+            static int64 nLastTime;
+            int64 nNow = GetTime();
+
+            CRITICAL_BLOCK(cs)
+            {
+                // Use an exponentially decaying ~10-minute window:
+                dFreeCount *= pow(1.0 - 1.0/600.0, (double)(nNow - nLastTime));
+                nLastTime = nNow;
+                // -limitfreerelay unit is thousand-bytes-per-minute
+                // At default rate it would take over a month to fill 1GB
+                if (dFreeCount > GetArg("-limitfreerelay", 15)*10*1000 && !IsFromMe())
+                    return error("AcceptToMemoryPool() : free transaction rejected by rate limiter");
+                if (fDebug)
+                    printf("Rate limit dFreeCount: %g => %g\n", dFreeCount, dFreeCount+nSize);
+                dFreeCount += nSize;
             }
-            if (nFreeCount > 150000 && !IsFromMe())
-                return error("AcceptToMemoryPool() : free transaction rejected by rate limiter");
-            nFreeCount += nSize;
         }
     }