Use created time for rate limiter (#178)

* Use created time to rate limit based on last hour

* Delete commented lines in rate limiter
This commit is contained in:
Jonathan Zernik 2020-07-30 03:05:21 -07:00 committed by GitHub
parent 6ce7723c35
commit 7c4b84056b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 45 additions and 24 deletions

View file

@ -21,7 +21,7 @@ rpc_port=8774
[squeaknode]
price=1000
max_squeaks_per_block_per_address=2
max_squeaks_per_address_per_hour=2
[admin]
rpc_host=0.0.0.0

View file

@ -21,7 +21,7 @@ rpc_port=8774
[squeaknode]
price=1000
max_squeaks_per_block_per_address=5
max_squeaks_per_address_per_hour=5
[admin]
rpc_host=0.0.0.0

View file

@ -24,7 +24,7 @@ class SqueakNode:
lightning_client,
lightning_host_port,
price,
max_squeaks_per_block_per_address,
max_squeaks_per_address_per_hour,
):
self.postgres_db = postgres_db
self.blockchain_client = blockchain_client
@ -42,7 +42,7 @@ class SqueakNode:
postgres_db,
blockchain_client,
lightning_client,
max_squeaks_per_block_per_address,
max_squeaks_per_address_per_hour,
)
self.squeak_whitelist = SqueakWhitelist(
postgres_db,

View file

@ -7,35 +7,34 @@ from squeakserver.node.block_info import BlockInfo
logger = logging.getLogger(__name__)
HOUR_IN_SECONDS = 3600
class SqueakRateLimiter:
def __init__(self, postgres_db, blockchain_client, lightning_client, max_squeaks_per_block_per_address):
def __init__(self, postgres_db, blockchain_client, lightning_client, max_squeaks_per_address_per_hour):
self.postgres_db = postgres_db
self.blockchain_client = blockchain_client
self.lightning_client = lightning_client
self.max_squeaks_per_block_per_address = max_squeaks_per_block_per_address
self.max_squeaks_per_address_per_hour = max_squeaks_per_address_per_hour
def should_rate_limit_allow(self, squeak):
squeak_hash = get_hash(squeak)
logger.info("Checking rate limit for squeak: {}".format(squeak_hash))
current_squeak_count = self._get_current_squeak_count(squeak)
logger.info("Current squeak count: {}, limit: {}".format(current_squeak_count, self.max_squeaks_per_block_per_address))
return current_squeak_count < self.max_squeaks_per_block_per_address
logger.info("Current squeak count: {}, limit: {}".format(current_squeak_count, self.max_squeaks_per_address_per_hour))
return current_squeak_count < self.max_squeaks_per_address_per_hour
def _get_current_squeak_count(self, squeak):
current_block_info = self._get_latest_block()
current_block_height = current_block_info.block_height
squeak_address = self._get_squeak_address(squeak)
return self._get_num_squeaks_in_block(current_block_height, squeak_address)
return self._get_num_squeaks_in_last_hour(squeak_address)
def _get_latest_block(self):
get_info_response = self.lightning_client.get_info()
block_hash = bytes.fromhex(get_info_response.block_hash)
block_height = get_info_response.block_height
return BlockInfo(block_hash, block_height)
def _get_num_squeaks_in_block(self, block_height, squeak_address):
logger.info("Getting squeak count for block height: {}, squeak address: {}".format(block_height, squeak_address))
hashes = self.postgres_db.lookup_squeaks([squeak_address], block_height, block_height, include_unverified=True)
def _get_num_squeaks_in_last_hour(self, squeak_address):
logger.info("Getting squeak count for last hour for squeak address: {}".format(squeak_address))
hashes = self.postgres_db.lookup_squeaks_by_time(
[squeak_address],
HOUR_IN_SECONDS,
include_unverified=True,
)
return len(hashes)
def _get_squeak_address(self, squeak):

View file

@ -55,8 +55,8 @@ def load_price(config):
return int(config["squeaknode"]["price"])
def load_max_squeaks_per_block_per_address(config):
return int(config["squeaknode"]["max_squeaks_per_block_per_address"])
def load_max_squeaks_per_address_per_hour(config):
return int(config["squeaknode"]["max_squeaks_per_address_per_hour"])
def load_handler(squeak_node):
@ -152,7 +152,7 @@ def run_server(config):
price = load_price(config)
# load the max squeaks per block per address
max_squeaks_per_block_per_address = load_max_squeaks_per_block_per_address(config)
max_squeaks_per_address_per_hour = load_max_squeaks_per_address_per_hour(config)
# load the lightning client
lightning_client = load_lightning_client(config)
@ -163,7 +163,7 @@ def run_server(config):
# Create and start the squeak node
squeak_node = SqueakNode(
postgres_db, blockchain_client, lightning_client, lightning_host_port, price, max_squeaks_per_block_per_address
postgres_db, blockchain_client, lightning_client, lightning_host_port, price, max_squeaks_per_address_per_hour
)
squeak_node.start_running()

View file

@ -186,6 +186,28 @@ class PostgresDb:
hashes = [bytes.fromhex(row["hash"]) for row in rows]
return hashes
def lookup_squeaks_by_time(self, addresses, interval_seconds, include_unverified=False):
""" Lookup squeaks. """
sql = """
SELECT hash FROM squeak
WHERE author_address IN %s
AND created > now() - interval '%s seconds'
AND vch_decryption_key IS NOT NULL
AND ((block_header IS NOT NULL) OR %s);
"""
addresses_tuple = tuple(addresses)
if not addresses:
return []
with self.get_cursor() as curs:
# mogrify to debug.
# logger.info(curs.mogrify(sql, (addresses_tuple, min_block, max_block)))
curs.execute(sql, (addresses_tuple, interval_seconds, include_unverified))
rows = curs.fetchall()
hashes = [bytes.fromhex(row["hash"]) for row in rows]
return hashes
def insert_profile(self, squeak_profile):
""" Insert a new squeak profile. """
sql = """