Continuously rate-limit free transactions.
authorGavin Andresen <gavinandresen@gmail.com>
Fri, 11 Mar 2011 16:50:16 +0000 (11:50 -0500)
committerGavin Andresen <gavinandresen@gmail.com>
Sun, 13 Mar 2011 17:38:09 +0000 (13:38 -0400)
Changed algorithm to use continuous exponential function instead of discrete 10-minute window.
Changed -limitfreerelay to be kilobytes-per-minute instead of boolean.

main.cpp

index c65cd72..5cb1342 100644 (file)
--- a/main.cpp
+++ b/main.cpp
@@ -738,19 +738,22 @@ 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;
-            }
-            if (nFreeCount > 150000 && !IsFromMe())
+        // Continuously rate-limit free transactions
+        if (nFees < CENT)
+        {
+            static double dFreeCount;
+            static int64 nLastTime;
+            int64 nNow = GetTime();
+            // 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");
-            nFreeCount += nSize;
+            if (fDebug)
+                printf("Rate limit dFreeCount: %g => %g\n", dFreeCount, dFreeCount+nSize);
+            dFreeCount += nSize;
         }
     }