diff --git a/docs/ENV-NOTES b/docs/ENV-NOTES index f76af1c..1a30a2c 100644 --- a/docs/ENV-NOTES +++ b/docs/ENV-NOTES @@ -44,6 +44,17 @@ in ElectrumX are very cheap - they consume about 100 bytes of memory each and are processed efficiently. I feel the defaults are low and encourage you to raise them. +MAX_HIST - maximum number of historical transactions to serve for + a single address. The current Electrum protocol requires + address histories be served en-masse or not at all, + an obvious avenue for abuse. This limit is a + stop-gap until the protocol is improved to admit + incremental history requests. The default value is + 2,000 which should be ample for most legitimate + users. Increasing to around 10,000 is likely fine + but bear in mind one client can request multiple + addresses. I welcome your experiences and suggestions + for an appropriate value. MAX_SUBS - maximum number of address subscriptions across all sessions. Defaults to 250,000. MAX_SESSION_SUBS - maximum number of address subscriptions permitted to a diff --git a/docs/RELEASE-NOTES b/docs/RELEASE-NOTES index b57701a..38d013d 100644 --- a/docs/RELEASE-NOTES +++ b/docs/RELEASE-NOTES @@ -1,3 +1,11 @@ +version 0.7.7 +------------- + +- add MAX_HIST to throttle history requests; see docs/ENV-NOTES. One + provider of ElectrumX services was attacked by a loser requesting + long histories; this environment variable allows you to limit what + you attempt to serve. + version 0.7.6 ------------- diff --git a/server/env.py b/server/env.py index bfddcf6..b62b8fa 100644 --- a/server/env.py +++ b/server/env.py @@ -44,7 +44,8 @@ class Env(LoggedClass): # The electrum client takes the empty string as unspecified self.donation_address = self.default('DONATION_ADDRESS', '') self.db_engine = self.default('DB_ENGINE', 'leveldb') - # Subscription limits + # Server limits to help prevent DoS + self.max_hist = self.integer('MAX_HIST', 2000) self.max_subs = self.integer('MAX_SUBS', 250000) self.max_session_subs = self.integer('MAX_SESSION_SUBS', 50000) # IRC diff --git a/server/protocol.py b/server/protocol.py index c14e745..dcb9e63 100644 --- a/server/protocol.py +++ b/server/protocol.py @@ -674,9 +674,11 @@ class ElectrumX(Session): return self.bp.read_headers(start_height, count).hex() async def async_get_history(self, hash168): + # Apply DoS limit + limit = self.env.max_hist # Python 3.6: use async generators; update callers history = [] - for item in self.bp.get_history(hash168, limit=None): + for item in self.bp.get_history(hash168, limit=limit): history.append(item) if len(history) % 100 == 0: await asyncio.sleep(0) diff --git a/server/version.py b/server/version.py index 45a1387..62a884c 100644 --- a/server/version.py +++ b/server/version.py @@ -1 +1 @@ -VERSION = "ElectrumX 0.7.6" +VERSION = "ElectrumX 0.7.7"