From fc87630e3c8ea12505df086d8a3005400f59c33f Mon Sep 17 00:00:00 2001 From: Arvid Norberg Date: Tue, 26 Aug 2025 16:49:15 +0200 Subject: [PATCH 1/3] remove unused default_settings in rate limits --- chia/server/rate_limit_numbers.py | 2 -- chia/server/rate_limits.py | 5 +---- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/chia/server/rate_limit_numbers.py b/chia/server/rate_limit_numbers.py index b7eea59ae8c2..dc233a2b15e7 100644 --- a/chia/server/rate_limit_numbers.py +++ b/chia/server/rate_limit_numbers.py @@ -69,7 +69,6 @@ def compose_rate_limits(old_rate_limits: dict[str, Any], new_rate_limits: dict[s # Version 1 includes the original limits for chia software from versions 1.0 to 1.4. rate_limits = { 1: { - "default_settings": RLSettings(100, 1024 * 1024, 100 * 1024 * 1024), "non_tx_freq": 1000, # There is also a freq limit for many requests "non_tx_max_total_size": 100 * 1024 * 1024, # There is also a size limit for many requests # All transaction related apis also have an aggregate limit @@ -181,7 +180,6 @@ def compose_rate_limits(old_rate_limits: dict[str, Any], new_rate_limits: dict[s }, }, 2: { - "default_settings": RLSettings(100, 1024 * 1024, 100 * 1024 * 1024), "non_tx_freq": 1000, # There is also a freq limit for many requests "non_tx_max_total_size": 100 * 1024 * 1024, # There is also a size limit for many requests "rate_limits_tx": { diff --git a/chia/server/rate_limits.py b/chia/server/rate_limits.py index 685ed142517b..7ddf47d19978 100644 --- a/chia/server/rate_limits.py +++ b/chia/server/rate_limits.py @@ -110,10 +110,7 @@ def process_msg_and_check( ] ) else: # pragma: no cover - log.warning( - f"Message type {message_type} not found in rate limits (scale factor: {proportion_of_limit})", - ) - limits = rate_limits["default_settings"] + return f"(internal error) Message type {message_type} not found in rate limits" if isinstance(limits, Unlimited): # this message type is not rate limited. This is used for From 3e88de7e9fc65f7fc7ca3254c994811b1e7b8bb7 Mon Sep 17 00:00:00 2001 From: Arvid Norberg Date: Tue, 26 Aug 2025 18:30:52 +0200 Subject: [PATCH 2/3] simplify rate_limit_numbers by flattening the structure. just map message type -> rate limits --- chia/_tests/core/server/test_rate_limits.py | 84 ++---- chia/server/rate_limit_numbers.py | 307 +++++++++----------- chia/server/rate_limits.py | 57 ++-- 3 files changed, 187 insertions(+), 261 deletions(-) diff --git a/chia/_tests/core/server/test_rate_limits.py b/chia/_tests/core/server/test_rate_limits.py index bf4cef41c768..d15e53c29267 100644 --- a/chia/_tests/core/server/test_rate_limits.py +++ b/chia/_tests/core/server/test_rate_limits.py @@ -1,7 +1,7 @@ from __future__ import annotations from dataclasses import dataclass -from typing import Any, cast +from typing import Union import pytest from chia_rs.sized_ints import uint32 @@ -13,8 +13,7 @@ from chia.protocols.outbound_message import make_msg from chia.protocols.protocol_message_types import ProtocolMessageTypes from chia.protocols.shared_protocol import Capability -from chia.server.rate_limit_numbers import RLSettings, compose_rate_limits, get_rate_limits_to_use -from chia.server.rate_limit_numbers import rate_limits as rl_numbers +from chia.server.rate_limit_numbers import RLSettings, Unlimited, get_rate_limits_to_use from chia.server.rate_limits import RateLimiter from chia.server.server import ChiaServer from chia.server.ws_connection import WSChiaConnection @@ -66,39 +65,22 @@ async def test_limits_v2(incoming: bool, tx_msg: bool, limit_size: bool, monkeyp message_data = b"\0" * 1024 msg_type = ProtocolMessageTypes.new_transaction - limits: dict[str, Any] = {} + limits: dict[ProtocolMessageTypes, Union[RLSettings, Unlimited]] if limit_size: - limits.update( - { - # this is the rate limit across all (non-tx) messages - "non_tx_freq": count * 2, - # this is the byte size limit across all (non-tx) messages - "non_tx_max_total_size": count * len(message_data), - } - ) + agg_limit = RLSettings(False, count * 2, 1024, count * len(message_data)) else: - limits.update( - { - # this is the rate limit across all (non-tx) messages - "non_tx_freq": count, - # this is the byte size limit across all (non-tx) messages - "non_tx_max_total_size": count * 2 * len(message_data), - } - ) + agg_limit = RLSettings(False, count, 1024, count * 2 * len(message_data)) if limit_size: - rate_limit = {msg_type: RLSettings(count * 2, 1024, count * len(message_data))} + limits = {msg_type: RLSettings(not tx_msg, count * 2, 1024, count * len(message_data))} else: - rate_limit = {msg_type: RLSettings(count, 1024, count * 2 * len(message_data))} + limits = {msg_type: RLSettings(not tx_msg, count, 1024, count * 2 * len(message_data))} - if tx_msg: - limits.update({"rate_limits_tx": rate_limit, "rate_limits_other": {}}) - else: - limits.update({"rate_limits_other": rate_limit, "rate_limits_tx": {}}) - - def mock_get_limits(our_capabilities: list[Capability], peer_capabilities: list[Capability]) -> dict[str, Any]: - return limits + def mock_get_limits( + our_capabilities: list[Capability], peer_capabilities: list[Capability] + ) -> tuple[dict[ProtocolMessageTypes, Union[RLSettings, Unlimited]], RLSettings]: + return limits, agg_limit import chia.server.rate_limits @@ -326,18 +308,18 @@ async def test_too_many_outgoing_messages() -> None: # Too many messages r = RateLimiter(incoming=False, get_time=lambda: 0) new_peers_message = make_msg(ProtocolMessageTypes.respond_peers, bytes([1])) - non_tx_freq = get_rate_limits_to_use(rl_v2, rl_v2)["non_tx_freq"] + _, agg_limit = get_rate_limits_to_use(rl_v2, rl_v2) passed = 0 blocked = 0 - for i in range(non_tx_freq): + for i in range(agg_limit.frequency): if r.process_msg_and_check(new_peers_message, rl_v2, rl_v2) is None: passed += 1 else: blocked += 1 assert passed == 10 - assert blocked == non_tx_freq - passed + assert blocked == agg_limit.frequency - passed # ensure that *another* message type is not blocked because of this @@ -350,18 +332,18 @@ async def test_too_many_incoming_messages() -> None: # Too many messages r = RateLimiter(incoming=True, get_time=lambda: 0) new_peers_message = make_msg(ProtocolMessageTypes.respond_peers, bytes([1])) - non_tx_freq = get_rate_limits_to_use(rl_v2, rl_v2)["non_tx_freq"] + _, agg_limit = get_rate_limits_to_use(rl_v2, rl_v2) passed = 0 blocked = 0 - for i in range(non_tx_freq): + for i in range(agg_limit.frequency): if r.process_msg_and_check(new_peers_message, rl_v2, rl_v2) is None: passed += 1 else: blocked += 1 assert passed == 10 - assert blocked == non_tx_freq - passed + assert blocked == agg_limit.frequency - passed # ensure that other message types *are* blocked because of this @@ -435,43 +417,13 @@ async def test_different_versions( # The following code checks whether all of the runs resulted in the same number of items in "rate_limits_tx", # which would mean the same rate limits are always used. This should not happen, since two nodes with V2 # will use V2. - total_tx_msg_count = len( - get_rate_limits_to_use(a_con.local_capabilities, a_con.peer_capabilities)["rate_limits_tx"] - ) + total_tx_msg_count = len(get_rate_limits_to_use(a_con.local_capabilities, a_con.peer_capabilities)) test_different_versions_results.append(total_tx_msg_count) if len(test_different_versions_results) >= 4: assert len(set(test_different_versions_results)) >= 2 -@pytest.mark.anyio -async def test_compose() -> None: - rl_1 = rl_numbers[1] - rl_2 = rl_numbers[2] - rl_1_rate_limits_other = cast(dict[ProtocolMessageTypes, RLSettings], rl_1["rate_limits_other"]) - rl_2_rate_limits_other = cast(dict[ProtocolMessageTypes, RLSettings], rl_2["rate_limits_other"]) - rl_1_rate_limits_tx = cast(dict[ProtocolMessageTypes, RLSettings], rl_1["rate_limits_tx"]) - rl_2_rate_limits_tx = cast(dict[ProtocolMessageTypes, RLSettings], rl_2["rate_limits_tx"]) - assert ProtocolMessageTypes.respond_children in rl_1_rate_limits_other - assert ProtocolMessageTypes.respond_children not in rl_1_rate_limits_tx - assert ProtocolMessageTypes.respond_children not in rl_2_rate_limits_other - assert ProtocolMessageTypes.respond_children in rl_2_rate_limits_tx - - assert ProtocolMessageTypes.request_block in rl_1_rate_limits_other - assert ProtocolMessageTypes.request_block not in rl_1_rate_limits_tx - assert ProtocolMessageTypes.request_block not in rl_2_rate_limits_other - assert ProtocolMessageTypes.request_block not in rl_2_rate_limits_tx - - comps = compose_rate_limits(rl_1, rl_2) - # v2 limits are used if present - assert ProtocolMessageTypes.respond_children not in comps["rate_limits_other"] - assert ProtocolMessageTypes.respond_children in comps["rate_limits_tx"] - - # Otherwise, fall back to v1 - assert ProtocolMessageTypes.request_block in rl_1_rate_limits_other - assert ProtocolMessageTypes.request_block not in rl_1_rate_limits_tx - - @pytest.mark.anyio @pytest.mark.parametrize( "msg_type, size", diff --git a/chia/server/rate_limit_numbers.py b/chia/server/rate_limit_numbers.py index dc233a2b15e7..bce5ffbe79c0 100644 --- a/chia/server/rate_limit_numbers.py +++ b/chia/server/rate_limit_numbers.py @@ -3,19 +3,21 @@ import copy import dataclasses -import functools -from typing import Any, Optional +from typing import Optional, Union from chia.protocols.protocol_message_types import ProtocolMessageTypes from chia.protocols.shared_protocol import Capability -compose_rate_limits_cache: dict[int, dict[str, Any]] = {} +compose_rate_limits_cache: dict[int, dict[ProtocolMessageTypes, Union[RLSettings, Unlimited]]] = {} # this class is used to configure the *rate* limit for a message type. The # limits are counts and size per 60 seconds. @dataclasses.dataclass(frozen=True) class RLSettings: + # if true, messages affect and are limited by the per connection aggregate limiter, + # which affects messages across message types + aggregate_limit: bool frequency: int # Max request per time period (ie 1 min) max_size: int # Max size of each request max_total_size: Optional[int] = None # Max cumulative size of all requests in that period @@ -31,184 +33,159 @@ class Unlimited: max_size: int # Max size of each request -def get_rate_limits_to_use(our_capabilities: list[Capability], peer_capabilities: list[Capability]) -> dict[str, Any]: +aggregate_limit = RLSettings(False, 1000, 100 * 1024 * 1024 * 1024, 100 * 1024 * 1024 * 1024) + + +def get_rate_limits_to_use( + our_capabilities: list[Capability], peer_capabilities: list[Capability] +) -> tuple[dict[ProtocolMessageTypes, Union[RLSettings, Unlimited]], RLSettings]: # This will use the newest possible rate limits that both peers support. At this time there are only two # options, v1 and v2. if Capability.RATE_LIMITS_V2 in our_capabilities and Capability.RATE_LIMITS_V2 in peer_capabilities: # Use V2 rate limits if 2 in compose_rate_limits_cache: - return compose_rate_limits_cache[2] - composed = compose_rate_limits(rate_limits[1], rate_limits[2]) + return compose_rate_limits_cache[2], aggregate_limit + composed = copy.copy(rate_limits[1]) + composed.update(rate_limits[2]) compose_rate_limits_cache[2] = composed - return composed + return composed, aggregate_limit else: # Use V1 rate limits - return rate_limits[1] - - -def compose_rate_limits(old_rate_limits: dict[str, Any], new_rate_limits: dict[str, Any]) -> dict[str, Any]: - # Composes two rate limits dicts, so that the newer values override the older values - final_rate_limits: dict[str, Any] = copy.deepcopy(new_rate_limits) - categories: list[str] = ["rate_limits_tx", "rate_limits_other"] - all_new_msgs_lists: list[list[ProtocolMessageTypes]] = [ - list(new_rate_limits[category].keys()) for category in categories - ] - all_new_msgs: list[ProtocolMessageTypes] = functools.reduce(lambda a, b: a + b, all_new_msgs_lists) - for old_cat, mapping in old_rate_limits.items(): - if old_cat in categories: - for old_protocol_msg, old_rate_limit_value in mapping.items(): - if old_protocol_msg not in all_new_msgs: - if old_cat not in final_rate_limits: - final_rate_limits[old_cat] = {} - final_rate_limits[old_cat][old_protocol_msg] = old_rate_limit_value - return final_rate_limits + return rate_limits[1], aggregate_limit # Each number in this dict corresponds to a specific version of rate limits (1, 2, etc). # Version 1 includes the original limits for chia software from versions 1.0 to 1.4. -rate_limits = { +rate_limits: dict[int, dict[ProtocolMessageTypes, Union[RLSettings, Unlimited]]] = { 1: { - "non_tx_freq": 1000, # There is also a freq limit for many requests - "non_tx_max_total_size": 100 * 1024 * 1024, # There is also a size limit for many requests - # All transaction related apis also have an aggregate limit - "rate_limits_tx": { - ProtocolMessageTypes.new_transaction: RLSettings(5000, 100, 5000 * 100), - ProtocolMessageTypes.request_transaction: RLSettings(5000, 100, 5000 * 100), - ProtocolMessageTypes.respond_transaction: RLSettings( - 5000, 1 * 1024 * 1024, 20 * 1024 * 1024 - ), # TODO: check this - ProtocolMessageTypes.send_transaction: RLSettings(5000, 1024 * 1024), - ProtocolMessageTypes.transaction_ack: RLSettings(5000, 2048), - }, + ProtocolMessageTypes.new_transaction: RLSettings(False, 5000, 100, 5000 * 100), + ProtocolMessageTypes.request_transaction: RLSettings(False, 5000, 100, 5000 * 100), + # TODO: check this + ProtocolMessageTypes.respond_transaction: RLSettings(False, 5000, 1 * 1024 * 1024, 20 * 1024 * 1024), + ProtocolMessageTypes.send_transaction: RLSettings(False, 5000, 1024 * 1024), + ProtocolMessageTypes.transaction_ack: RLSettings(False, 5000, 2048), # All non-transaction apis also have an aggregate limit - "rate_limits_other": { - ProtocolMessageTypes.handshake: RLSettings(5, 10 * 1024, 5 * 10 * 1024), - ProtocolMessageTypes.harvester_handshake: RLSettings(5, 1024 * 1024), - ProtocolMessageTypes.new_signage_point_harvester: RLSettings(100, 4886), # Size with 100 pool list - ProtocolMessageTypes.new_proof_of_space: RLSettings(100, 2048), - ProtocolMessageTypes.request_signatures: RLSettings(100, 2048), - ProtocolMessageTypes.respond_signatures: RLSettings(100, 2048), - ProtocolMessageTypes.new_signage_point: RLSettings(200, 2048), - ProtocolMessageTypes.declare_proof_of_space: RLSettings(100, 10 * 1024), - ProtocolMessageTypes.request_signed_values: RLSettings(100, 10 * 1024), - ProtocolMessageTypes.farming_info: RLSettings(100, 1024), - ProtocolMessageTypes.signed_values: RLSettings(100, 1024), - ProtocolMessageTypes.new_peak_timelord: RLSettings(100, 20 * 1024), - ProtocolMessageTypes.new_unfinished_block_timelord: RLSettings(100, 10 * 1024), - ProtocolMessageTypes.new_signage_point_vdf: RLSettings(100, 100 * 1024), - ProtocolMessageTypes.new_infusion_point_vdf: RLSettings(100, 100 * 1024), - ProtocolMessageTypes.new_end_of_sub_slot_vdf: RLSettings(100, 100 * 1024), - ProtocolMessageTypes.request_compact_proof_of_time: RLSettings(100, 10 * 1024), - ProtocolMessageTypes.respond_compact_proof_of_time: RLSettings(100, 100 * 1024), - ProtocolMessageTypes.new_peak: RLSettings(200, 512), - ProtocolMessageTypes.request_proof_of_weight: RLSettings(5, 100), - ProtocolMessageTypes.respond_proof_of_weight: RLSettings(5, 50 * 1024 * 1024, 100 * 1024 * 1024), - ProtocolMessageTypes.request_block: RLSettings(200, 100), - ProtocolMessageTypes.reject_block: Unlimited(100), - ProtocolMessageTypes.request_blocks: RLSettings(500, 100), - ProtocolMessageTypes.respond_blocks: Unlimited(50 * 1024 * 1024), - ProtocolMessageTypes.reject_blocks: Unlimited(100), - ProtocolMessageTypes.respond_block: Unlimited(2 * 1024 * 1024), - ProtocolMessageTypes.new_unfinished_block: RLSettings(200, 100), - ProtocolMessageTypes.request_unfinished_block: RLSettings(200, 100), - ProtocolMessageTypes.new_unfinished_block2: RLSettings(200, 100), - ProtocolMessageTypes.request_unfinished_block2: RLSettings(200, 100), - ProtocolMessageTypes.respond_unfinished_block: RLSettings(200, 2 * 1024 * 1024, 10 * 2 * 1024 * 1024), - ProtocolMessageTypes.new_signage_point_or_end_of_sub_slot: RLSettings(200, 200), - ProtocolMessageTypes.request_signage_point_or_end_of_sub_slot: RLSettings(200, 200), - ProtocolMessageTypes.respond_signage_point: RLSettings(200, 50 * 1024), - ProtocolMessageTypes.respond_end_of_sub_slot: RLSettings(100, 50 * 1024), - ProtocolMessageTypes.request_mempool_transactions: RLSettings(5, 1024 * 1024), - ProtocolMessageTypes.request_compact_vdf: RLSettings(200, 1024), - ProtocolMessageTypes.respond_compact_vdf: RLSettings(200, 100 * 1024), - ProtocolMessageTypes.new_compact_vdf: RLSettings(100, 1024), - ProtocolMessageTypes.request_peers: RLSettings(10, 100), - ProtocolMessageTypes.respond_peers: RLSettings(10, 1 * 1024 * 1024), - ProtocolMessageTypes.request_puzzle_solution: RLSettings(1000, 100), - ProtocolMessageTypes.respond_puzzle_solution: RLSettings(1000, 1024 * 1024), - ProtocolMessageTypes.reject_puzzle_solution: RLSettings(1000, 100), - ProtocolMessageTypes.new_peak_wallet: RLSettings(200, 300), - ProtocolMessageTypes.request_block_header: RLSettings(500, 100), - ProtocolMessageTypes.respond_block_header: RLSettings(500, 500 * 1024), - ProtocolMessageTypes.reject_header_request: RLSettings(500, 100), - ProtocolMessageTypes.request_removals: RLSettings(500, 50 * 1024, 10 * 1024 * 1024), - ProtocolMessageTypes.respond_removals: RLSettings(500, 1024 * 1024, 10 * 1024 * 1024), - ProtocolMessageTypes.reject_removals_request: RLSettings(500, 100), - ProtocolMessageTypes.request_additions: RLSettings(500, 1024 * 1024, 10 * 1024 * 1024), - ProtocolMessageTypes.respond_additions: RLSettings(500, 1024 * 1024, 10 * 1024 * 1024), - ProtocolMessageTypes.reject_additions_request: RLSettings(500, 100), - ProtocolMessageTypes.request_header_blocks: RLSettings(500, 100), - ProtocolMessageTypes.reject_header_blocks: RLSettings(100, 100), - ProtocolMessageTypes.respond_header_blocks: RLSettings(500, 2 * 1024 * 1024, 100 * 1024 * 1024), - ProtocolMessageTypes.request_peers_introducer: RLSettings(100, 100), - ProtocolMessageTypes.respond_peers_introducer: RLSettings(100, 1024 * 1024), - ProtocolMessageTypes.farm_new_block: RLSettings(200, 200), - ProtocolMessageTypes.request_plots: RLSettings(10, 10 * 1024 * 1024), - ProtocolMessageTypes.respond_plots: RLSettings(10, 100 * 1024 * 1024), - ProtocolMessageTypes.plot_sync_start: RLSettings(1000, 100 * 1024 * 1024), - ProtocolMessageTypes.plot_sync_loaded: RLSettings(1000, 100 * 1024 * 1024), - ProtocolMessageTypes.plot_sync_removed: RLSettings(1000, 100 * 1024 * 1024), - ProtocolMessageTypes.plot_sync_invalid: RLSettings(1000, 100 * 1024 * 1024), - ProtocolMessageTypes.plot_sync_keys_missing: RLSettings(1000, 100 * 1024 * 1024), - ProtocolMessageTypes.plot_sync_duplicates: RLSettings(1000, 100 * 1024 * 1024), - ProtocolMessageTypes.plot_sync_done: RLSettings(1000, 100 * 1024 * 1024), - ProtocolMessageTypes.plot_sync_response: RLSettings(3000, 100 * 1024 * 1024), - ProtocolMessageTypes.coin_state_update: RLSettings(1000, 100 * 1024 * 1024), - ProtocolMessageTypes.register_for_ph_updates: RLSettings(1000, 100 * 1024 * 1024), - ProtocolMessageTypes.respond_to_ph_updates: RLSettings(1000, 100 * 1024 * 1024), - ProtocolMessageTypes.register_for_coin_updates: RLSettings(1000, 100 * 1024 * 1024), - ProtocolMessageTypes.respond_to_coin_updates: RLSettings(1000, 100 * 1024 * 1024), - ProtocolMessageTypes.request_remove_puzzle_subscriptions: RLSettings(1000, 100 * 1024 * 1024), - ProtocolMessageTypes.respond_remove_puzzle_subscriptions: RLSettings(1000, 100 * 1024 * 1024), - ProtocolMessageTypes.request_remove_coin_subscriptions: RLSettings(1000, 100 * 1024 * 1024), - ProtocolMessageTypes.respond_remove_coin_subscriptions: RLSettings(1000, 100 * 1024 * 1024), - ProtocolMessageTypes.request_puzzle_state: RLSettings(1000, 100 * 1024 * 1024), - ProtocolMessageTypes.respond_puzzle_state: RLSettings(1000, 100 * 1024 * 1024), - ProtocolMessageTypes.reject_puzzle_state: RLSettings(200, 100), - ProtocolMessageTypes.request_coin_state: RLSettings(1000, 100 * 1024 * 1024), - ProtocolMessageTypes.respond_coin_state: RLSettings(1000, 100 * 1024 * 1024), - ProtocolMessageTypes.reject_coin_state: RLSettings(200, 100), - ProtocolMessageTypes.mempool_items_added: RLSettings(1000, 100 * 1024 * 1024), - ProtocolMessageTypes.mempool_items_removed: RLSettings(1000, 100 * 1024 * 1024), - ProtocolMessageTypes.request_cost_info: RLSettings(1000, 100), - ProtocolMessageTypes.respond_cost_info: RLSettings(1000, 1024), - ProtocolMessageTypes.request_ses_hashes: RLSettings(2000, 1 * 1024 * 1024), - ProtocolMessageTypes.respond_ses_hashes: RLSettings(2000, 1 * 1024 * 1024), - ProtocolMessageTypes.request_children: RLSettings(2000, 1024 * 1024), - ProtocolMessageTypes.respond_children: RLSettings(2000, 1 * 1024 * 1024), - }, + ProtocolMessageTypes.handshake: RLSettings(True, 5, 10 * 1024, 5 * 10 * 1024), + ProtocolMessageTypes.harvester_handshake: RLSettings(True, 5, 1024 * 1024), + ProtocolMessageTypes.new_signage_point_harvester: RLSettings(True, 100, 4886), # Size with 100 pool list + ProtocolMessageTypes.new_proof_of_space: RLSettings(True, 100, 2048), + ProtocolMessageTypes.request_signatures: RLSettings(True, 100, 2048), + ProtocolMessageTypes.respond_signatures: RLSettings(True, 100, 2048), + ProtocolMessageTypes.new_signage_point: RLSettings(True, 200, 2048), + ProtocolMessageTypes.declare_proof_of_space: RLSettings(True, 100, 10 * 1024), + ProtocolMessageTypes.request_signed_values: RLSettings(True, 100, 10 * 1024), + ProtocolMessageTypes.farming_info: RLSettings(True, 100, 1024), + ProtocolMessageTypes.signed_values: RLSettings(True, 100, 1024), + ProtocolMessageTypes.new_peak_timelord: RLSettings(True, 100, 20 * 1024), + ProtocolMessageTypes.new_unfinished_block_timelord: RLSettings(True, 100, 10 * 1024), + ProtocolMessageTypes.new_signage_point_vdf: RLSettings(True, 100, 100 * 1024), + ProtocolMessageTypes.new_infusion_point_vdf: RLSettings(True, 100, 100 * 1024), + ProtocolMessageTypes.new_end_of_sub_slot_vdf: RLSettings(True, 100, 100 * 1024), + ProtocolMessageTypes.request_compact_proof_of_time: RLSettings(True, 100, 10 * 1024), + ProtocolMessageTypes.respond_compact_proof_of_time: RLSettings(True, 100, 100 * 1024), + ProtocolMessageTypes.new_peak: RLSettings(True, 200, 512), + ProtocolMessageTypes.request_proof_of_weight: RLSettings(True, 5, 100), + ProtocolMessageTypes.respond_proof_of_weight: RLSettings(True, 5, 50 * 1024 * 1024, 100 * 1024 * 1024), + ProtocolMessageTypes.request_block: RLSettings(True, 200, 100), + ProtocolMessageTypes.reject_block: Unlimited(100), + ProtocolMessageTypes.request_blocks: RLSettings(True, 500, 100), + ProtocolMessageTypes.respond_blocks: Unlimited(50 * 1024 * 1024), + ProtocolMessageTypes.reject_blocks: Unlimited(100), + ProtocolMessageTypes.respond_block: Unlimited(2 * 1024 * 1024), + ProtocolMessageTypes.new_unfinished_block: RLSettings(True, 200, 100), + ProtocolMessageTypes.request_unfinished_block: RLSettings(True, 200, 100), + ProtocolMessageTypes.new_unfinished_block2: RLSettings(True, 200, 100), + ProtocolMessageTypes.request_unfinished_block2: RLSettings(True, 200, 100), + ProtocolMessageTypes.respond_unfinished_block: RLSettings(True, 200, 2 * 1024 * 1024, 10 * 2 * 1024 * 1024), + ProtocolMessageTypes.new_signage_point_or_end_of_sub_slot: RLSettings(True, 200, 200), + ProtocolMessageTypes.request_signage_point_or_end_of_sub_slot: RLSettings(True, 200, 200), + ProtocolMessageTypes.respond_signage_point: RLSettings(True, 200, 50 * 1024), + ProtocolMessageTypes.respond_end_of_sub_slot: RLSettings(True, 100, 50 * 1024), + ProtocolMessageTypes.request_mempool_transactions: RLSettings(True, 5, 1024 * 1024), + ProtocolMessageTypes.request_compact_vdf: RLSettings(True, 200, 1024), + ProtocolMessageTypes.respond_compact_vdf: RLSettings(True, 200, 100 * 1024), + ProtocolMessageTypes.new_compact_vdf: RLSettings(True, 100, 1024), + ProtocolMessageTypes.request_peers: RLSettings(True, 10, 100), + ProtocolMessageTypes.respond_peers: RLSettings(True, 10, 1 * 1024 * 1024), + ProtocolMessageTypes.request_puzzle_solution: RLSettings(True, 1000, 100), + ProtocolMessageTypes.respond_puzzle_solution: RLSettings(True, 1000, 1024 * 1024), + ProtocolMessageTypes.reject_puzzle_solution: RLSettings(True, 1000, 100), + ProtocolMessageTypes.new_peak_wallet: RLSettings(True, 200, 300), + ProtocolMessageTypes.request_block_header: RLSettings(True, 500, 100), + ProtocolMessageTypes.respond_block_header: RLSettings(True, 500, 500 * 1024), + ProtocolMessageTypes.reject_header_request: RLSettings(True, 500, 100), + ProtocolMessageTypes.request_removals: RLSettings(True, 500, 50 * 1024, 10 * 1024 * 1024), + ProtocolMessageTypes.respond_removals: RLSettings(True, 500, 1024 * 1024, 10 * 1024 * 1024), + ProtocolMessageTypes.reject_removals_request: RLSettings(True, 500, 100), + ProtocolMessageTypes.request_additions: RLSettings(True, 500, 1024 * 1024, 10 * 1024 * 1024), + ProtocolMessageTypes.respond_additions: RLSettings(True, 500, 1024 * 1024, 10 * 1024 * 1024), + ProtocolMessageTypes.reject_additions_request: RLSettings(True, 500, 100), + ProtocolMessageTypes.request_header_blocks: RLSettings(True, 500, 100), + ProtocolMessageTypes.reject_header_blocks: RLSettings(True, 100, 100), + ProtocolMessageTypes.respond_header_blocks: RLSettings(True, 500, 2 * 1024 * 1024, 100 * 1024 * 1024), + ProtocolMessageTypes.request_peers_introducer: RLSettings(True, 100, 100), + ProtocolMessageTypes.respond_peers_introducer: RLSettings(True, 100, 1024 * 1024), + ProtocolMessageTypes.farm_new_block: RLSettings(True, 200, 200), + ProtocolMessageTypes.request_plots: RLSettings(True, 10, 10 * 1024 * 1024), + ProtocolMessageTypes.respond_plots: RLSettings(True, 10, 100 * 1024 * 1024), + ProtocolMessageTypes.plot_sync_start: RLSettings(True, 1000, 100 * 1024 * 1024), + ProtocolMessageTypes.plot_sync_loaded: RLSettings(True, 1000, 100 * 1024 * 1024), + ProtocolMessageTypes.plot_sync_removed: RLSettings(True, 1000, 100 * 1024 * 1024), + ProtocolMessageTypes.plot_sync_invalid: RLSettings(True, 1000, 100 * 1024 * 1024), + ProtocolMessageTypes.plot_sync_keys_missing: RLSettings(True, 1000, 100 * 1024 * 1024), + ProtocolMessageTypes.plot_sync_duplicates: RLSettings(True, 1000, 100 * 1024 * 1024), + ProtocolMessageTypes.plot_sync_done: RLSettings(True, 1000, 100 * 1024 * 1024), + ProtocolMessageTypes.plot_sync_response: RLSettings(True, 3000, 100 * 1024 * 1024), + ProtocolMessageTypes.coin_state_update: RLSettings(True, 1000, 100 * 1024 * 1024), + ProtocolMessageTypes.register_for_ph_updates: RLSettings(True, 1000, 100 * 1024 * 1024), + ProtocolMessageTypes.respond_to_ph_updates: RLSettings(True, 1000, 100 * 1024 * 1024), + ProtocolMessageTypes.register_for_coin_updates: RLSettings(True, 1000, 100 * 1024 * 1024), + ProtocolMessageTypes.respond_to_coin_updates: RLSettings(True, 1000, 100 * 1024 * 1024), + ProtocolMessageTypes.request_remove_puzzle_subscriptions: RLSettings(True, 1000, 100 * 1024 * 1024), + ProtocolMessageTypes.respond_remove_puzzle_subscriptions: RLSettings(True, 1000, 100 * 1024 * 1024), + ProtocolMessageTypes.request_remove_coin_subscriptions: RLSettings(True, 1000, 100 * 1024 * 1024), + ProtocolMessageTypes.respond_remove_coin_subscriptions: RLSettings(True, 1000, 100 * 1024 * 1024), + ProtocolMessageTypes.request_puzzle_state: RLSettings(True, 1000, 100 * 1024 * 1024), + ProtocolMessageTypes.respond_puzzle_state: RLSettings(True, 1000, 100 * 1024 * 1024), + ProtocolMessageTypes.reject_puzzle_state: RLSettings(True, 200, 100), + ProtocolMessageTypes.request_coin_state: RLSettings(True, 1000, 100 * 1024 * 1024), + ProtocolMessageTypes.respond_coin_state: RLSettings(True, 1000, 100 * 1024 * 1024), + ProtocolMessageTypes.reject_coin_state: RLSettings(True, 200, 100), + ProtocolMessageTypes.mempool_items_added: RLSettings(True, 1000, 100 * 1024 * 1024), + ProtocolMessageTypes.mempool_items_removed: RLSettings(True, 1000, 100 * 1024 * 1024), + ProtocolMessageTypes.request_cost_info: RLSettings(True, 1000, 100), + ProtocolMessageTypes.respond_cost_info: RLSettings(True, 1000, 1024), + ProtocolMessageTypes.request_ses_hashes: RLSettings(True, 2000, 1 * 1024 * 1024), + ProtocolMessageTypes.respond_ses_hashes: RLSettings(True, 2000, 1 * 1024 * 1024), + ProtocolMessageTypes.request_children: RLSettings(True, 2000, 1024 * 1024), + ProtocolMessageTypes.respond_children: RLSettings(True, 2000, 1 * 1024 * 1024), }, 2: { - "non_tx_freq": 1000, # There is also a freq limit for many requests - "non_tx_max_total_size": 100 * 1024 * 1024, # There is also a size limit for many requests - "rate_limits_tx": { - ProtocolMessageTypes.request_block_header: RLSettings(500, 100), - ProtocolMessageTypes.respond_block_header: RLSettings(500, 500 * 1024), - ProtocolMessageTypes.reject_header_request: RLSettings(500, 100), - ProtocolMessageTypes.request_removals: RLSettings(5000, 50 * 1024, 10 * 1024 * 1024), - ProtocolMessageTypes.respond_removals: RLSettings(5000, 1024 * 1024, 10 * 1024 * 1024), - ProtocolMessageTypes.reject_removals_request: RLSettings(500, 100), - ProtocolMessageTypes.request_additions: RLSettings(50000, 100 * 1024 * 1024), - ProtocolMessageTypes.respond_additions: RLSettings(50000, 100 * 1024 * 1024), - ProtocolMessageTypes.reject_additions_request: RLSettings(500, 100), - ProtocolMessageTypes.reject_header_blocks: RLSettings(1000, 100), - ProtocolMessageTypes.respond_header_blocks: RLSettings(5000, 2 * 1024 * 1024), - ProtocolMessageTypes.request_block_headers: RLSettings(5000, 100), - ProtocolMessageTypes.reject_block_headers: RLSettings(1000, 100), - ProtocolMessageTypes.respond_block_headers: RLSettings(5000, 2 * 1024 * 1024), - ProtocolMessageTypes.request_ses_hashes: RLSettings(2000, 1 * 1024 * 1024), - ProtocolMessageTypes.respond_ses_hashes: RLSettings(2000, 1 * 1024 * 1024), - ProtocolMessageTypes.request_children: RLSettings(2000, 1024 * 1024), - ProtocolMessageTypes.respond_children: RLSettings(2000, 1 * 1024 * 1024), - ProtocolMessageTypes.request_puzzle_solution: RLSettings(5000, 100), - ProtocolMessageTypes.respond_puzzle_solution: RLSettings(5000, 1024 * 1024), - ProtocolMessageTypes.reject_puzzle_solution: RLSettings(5000, 100), - ProtocolMessageTypes.none_response: RLSettings(500, 100), - ProtocolMessageTypes.error: RLSettings(50000, 100), - }, - "rate_limits_other": { # These will have a lower cap since they don't scale with high TPS (NON_TX_FREQ) - ProtocolMessageTypes.request_header_blocks: RLSettings(5000, 100), - }, + ProtocolMessageTypes.request_block_header: RLSettings(False, 500, 100), + ProtocolMessageTypes.respond_block_header: RLSettings(False, 500, 500 * 1024), + ProtocolMessageTypes.reject_header_request: RLSettings(False, 500, 100), + ProtocolMessageTypes.request_removals: RLSettings(False, 5000, 50 * 1024, 10 * 1024 * 1024), + ProtocolMessageTypes.respond_removals: RLSettings(False, 5000, 1024 * 1024, 10 * 1024 * 1024), + ProtocolMessageTypes.reject_removals_request: RLSettings(False, 500, 100), + ProtocolMessageTypes.request_additions: RLSettings(False, 50000, 100 * 1024 * 1024), + ProtocolMessageTypes.respond_additions: RLSettings(False, 50000, 100 * 1024 * 1024), + ProtocolMessageTypes.reject_additions_request: RLSettings(False, 500, 100), + ProtocolMessageTypes.reject_header_blocks: RLSettings(False, 1000, 100), + ProtocolMessageTypes.respond_header_blocks: RLSettings(False, 5000, 2 * 1024 * 1024), + ProtocolMessageTypes.request_block_headers: RLSettings(False, 5000, 100), + ProtocolMessageTypes.reject_block_headers: RLSettings(False, 1000, 100), + ProtocolMessageTypes.respond_block_headers: RLSettings(False, 5000, 2 * 1024 * 1024), + ProtocolMessageTypes.request_ses_hashes: RLSettings(False, 2000, 1 * 1024 * 1024), + ProtocolMessageTypes.respond_ses_hashes: RLSettings(False, 2000, 1 * 1024 * 1024), + ProtocolMessageTypes.request_children: RLSettings(False, 2000, 1024 * 1024), + ProtocolMessageTypes.respond_children: RLSettings(False, 2000, 1 * 1024 * 1024), + ProtocolMessageTypes.request_puzzle_solution: RLSettings(False, 5000, 100), + ProtocolMessageTypes.respond_puzzle_solution: RLSettings(False, 5000, 1024 * 1024), + ProtocolMessageTypes.reject_puzzle_solution: RLSettings(False, 5000, 100), + ProtocolMessageTypes.none_response: RLSettings(False, 500, 100), + ProtocolMessageTypes.error: RLSettings(False, 50000, 100), + # These will have a lower cap since they don't scale with high TPS (NON_TX_FREQ) + ProtocolMessageTypes.request_header_blocks: RLSettings(True, 5000, 100), }, } diff --git a/chia/server/rate_limits.py b/chia/server/rate_limits.py index 7ddf47d19978..c3a6fdb677c6 100644 --- a/chia/server/rate_limits.py +++ b/chia/server/rate_limits.py @@ -4,7 +4,7 @@ import logging import time from collections import Counter -from typing import Callable, Optional +from typing import Callable, Optional, Union from chia.protocols.outbound_message import Message from chia.protocols.protocol_message_types import ProtocolMessageTypes @@ -80,37 +80,34 @@ def process_msg_and_check( proportion_of_limit: float = self.percentage_of_limit / 100 ret: bool = False - rate_limits = get_rate_limits_to_use(our_capabilities, peer_capabilities) + rate_limits: dict[ProtocolMessageTypes, Union[RLSettings, Unlimited]] + rate_limits, agg_limit = get_rate_limits_to_use(our_capabilities, peer_capabilities) try: - limits: RLSettings - if message_type in rate_limits["rate_limits_tx"]: - limits = rate_limits["rate_limits_tx"][message_type] - elif message_type in rate_limits["rate_limits_other"]: - limits = rate_limits["rate_limits_other"][message_type] - if isinstance(limits, RLSettings): - non_tx_freq = rate_limits["non_tx_freq"] - non_tx_max_total_size = rate_limits["non_tx_max_total_size"] - new_non_tx_count = self.non_tx_message_counts + 1 - new_non_tx_size = self.non_tx_cumulative_size + len(message.data) - if new_non_tx_count > non_tx_freq * proportion_of_limit: - return " ".join( - [ - f"non-tx count: {new_non_tx_count}", - f"> {non_tx_freq * proportion_of_limit}", - f"(scale factor: {proportion_of_limit})", - ] - ) - if new_non_tx_size > non_tx_max_total_size * proportion_of_limit: - return " ".join( - [ - f"non-tx size: {new_non_tx_size}", - f"> {non_tx_max_total_size * proportion_of_limit}", - f"(scale factor: {proportion_of_limit})", - ] - ) - else: # pragma: no cover - return f"(internal error) Message type {message_type} not found in rate limits" + limits: Union[RLSettings, Unlimited] + limits = rate_limits[message_type] + if isinstance(limits, RLSettings) and limits.aggregate_limit: + non_tx_freq = agg_limit.frequency + assert agg_limit.max_total_size + non_tx_max_total_size = agg_limit.max_total_size + new_non_tx_count = self.non_tx_message_counts + 1 + new_non_tx_size = self.non_tx_cumulative_size + len(message.data) + if new_non_tx_count > non_tx_freq * proportion_of_limit: + return " ".join( + [ + f"non-tx count: {new_non_tx_count}", + f"> {non_tx_freq * proportion_of_limit}", + f"(scale factor: {proportion_of_limit})", + ] + ) + if new_non_tx_size > non_tx_max_total_size * proportion_of_limit: + return " ".join( + [ + f"non-tx size: {new_non_tx_size}", + f"> {non_tx_max_total_size * proportion_of_limit}", + f"(scale factor: {proportion_of_limit})", + ] + ) if isinstance(limits, Unlimited): # this message type is not rate limited. This is used for From ee1beb5edddd07eebe784d5ffe6982aa3599418b Mon Sep 17 00:00:00 2001 From: Arvid Norberg Date: Mon, 8 Sep 2025 20:40:13 +0200 Subject: [PATCH 3/3] review comments --- chia/_tests/core/server/test_rate_limits.py | 8 ++--- .../_tests/util/test_network_protocol_test.py | 18 +++++++++++ chia/server/rate_limit_numbers.py | 30 +++++++++++++------ chia/server/rate_limits.py | 5 ++-- 4 files changed, 45 insertions(+), 16 deletions(-) diff --git a/chia/_tests/core/server/test_rate_limits.py b/chia/_tests/core/server/test_rate_limits.py index d15e53c29267..080d5d0c9c5c 100644 --- a/chia/_tests/core/server/test_rate_limits.py +++ b/chia/_tests/core/server/test_rate_limits.py @@ -68,14 +68,14 @@ async def test_limits_v2(incoming: bool, tx_msg: bool, limit_size: bool, monkeyp limits: dict[ProtocolMessageTypes, Union[RLSettings, Unlimited]] if limit_size: - agg_limit = RLSettings(False, count * 2, 1024, count * len(message_data)) + agg_limit = RLSettings(False, count * 2, len(message_data), count * len(message_data)) else: - agg_limit = RLSettings(False, count, 1024, count * 2 * len(message_data)) + agg_limit = RLSettings(False, count, len(message_data), count * 2 * len(message_data)) if limit_size: - limits = {msg_type: RLSettings(not tx_msg, count * 2, 1024, count * len(message_data))} + limits = {msg_type: RLSettings(not tx_msg, count * 2, len(message_data), count * len(message_data))} else: - limits = {msg_type: RLSettings(not tx_msg, count, 1024, count * 2 * len(message_data))} + limits = {msg_type: RLSettings(not tx_msg, count, len(message_data), count * 2 * len(message_data))} def mock_get_limits( our_capabilities: list[Capability], peer_capabilities: list[Capability] diff --git a/chia/_tests/util/test_network_protocol_test.py b/chia/_tests/util/test_network_protocol_test.py index 0adb46afa5e6..289f2383caf3 100644 --- a/chia/_tests/util/test_network_protocol_test.py +++ b/chia/_tests/util/test_network_protocol_test.py @@ -4,6 +4,8 @@ import inspect from typing import Any, cast +import pytest + from chia.protocols import ( farmer_protocol, full_node_protocol, @@ -264,3 +266,19 @@ def test_missing_messages() -> None: assert types_in_module(shared_protocol) == shared_msgs, ( f"message types were added or removed from shared_protocol. {STANDARD_ADVICE}" ) + + +@pytest.mark.parametrize("version", [1, 2]) +def test_rate_limits_complete(version: int) -> None: + from chia.protocols.protocol_message_types import ProtocolMessageTypes + from chia.server.rate_limit_numbers import rate_limits + + if version == 1: + composed = rate_limits[1] + elif version == 2: + composed = { + **rate_limits[1], + **rate_limits[2], + } + + assert set(composed.keys()) == set(ProtocolMessageTypes) diff --git a/chia/server/rate_limit_numbers.py b/chia/server/rate_limit_numbers.py index bce5ffbe79c0..16b7c4265f60 100644 --- a/chia/server/rate_limit_numbers.py +++ b/chia/server/rate_limit_numbers.py @@ -1,7 +1,6 @@ # All of these rate limits scale with the number of transactions so the aggregate amounts are higher from __future__ import annotations -import copy import dataclasses from typing import Optional, Union @@ -33,7 +32,13 @@ class Unlimited: max_size: int # Max size of each request -aggregate_limit = RLSettings(False, 1000, 100 * 1024 * 1024 * 1024, 100 * 1024 * 1024 * 1024) +# for the aggregate limit, not all fields of RLSettings are used. Only "frequency" and "max_total_size" +aggregate_limit = RLSettings( + aggregate_limit=False, + frequency=1000, + max_size=0, + max_total_size=100 * 1024 * 1024, +) def get_rate_limits_to_use( @@ -46,8 +51,10 @@ def get_rate_limits_to_use( # Use V2 rate limits if 2 in compose_rate_limits_cache: return compose_rate_limits_cache[2], aggregate_limit - composed = copy.copy(rate_limits[1]) - composed.update(rate_limits[2]) + composed = { + **rate_limits[1], + **rate_limits[2], + } compose_rate_limits_cache[2] = composed return composed, aggregate_limit else: @@ -111,10 +118,14 @@ def get_rate_limits_to_use( ProtocolMessageTypes.request_puzzle_solution: RLSettings(True, 1000, 100), ProtocolMessageTypes.respond_puzzle_solution: RLSettings(True, 1000, 1024 * 1024), ProtocolMessageTypes.reject_puzzle_solution: RLSettings(True, 1000, 100), + ProtocolMessageTypes.none_response: RLSettings(False, 500, 100), ProtocolMessageTypes.new_peak_wallet: RLSettings(True, 200, 300), ProtocolMessageTypes.request_block_header: RLSettings(True, 500, 100), ProtocolMessageTypes.respond_block_header: RLSettings(True, 500, 500 * 1024), ProtocolMessageTypes.reject_header_request: RLSettings(True, 500, 100), + ProtocolMessageTypes.request_block_headers: RLSettings(False, 5000, 100), + ProtocolMessageTypes.reject_block_headers: RLSettings(False, 1000, 100), + ProtocolMessageTypes.respond_block_headers: RLSettings(False, 5000, 2 * 1024 * 1024), ProtocolMessageTypes.request_removals: RLSettings(True, 500, 50 * 1024, 10 * 1024 * 1024), ProtocolMessageTypes.respond_removals: RLSettings(True, 500, 1024 * 1024, 10 * 1024 * 1024), ProtocolMessageTypes.reject_removals_request: RLSettings(True, 500, 100), @@ -160,6 +171,12 @@ def get_rate_limits_to_use( ProtocolMessageTypes.respond_ses_hashes: RLSettings(True, 2000, 1 * 1024 * 1024), ProtocolMessageTypes.request_children: RLSettings(True, 2000, 1024 * 1024), ProtocolMessageTypes.respond_children: RLSettings(True, 2000, 1 * 1024 * 1024), + ProtocolMessageTypes.error: RLSettings(False, 50000, 100), + ProtocolMessageTypes.request_fee_estimates: RLSettings(True, 10, 100), + ProtocolMessageTypes.respond_fee_estimates: RLSettings(True, 10, 100), + ProtocolMessageTypes.solve: RLSettings(False, 120, 1024), + ProtocolMessageTypes.solution_response: RLSettings(False, 120, 1024), + ProtocolMessageTypes.partial_proofs: RLSettings(False, 120, 3 * 1024), }, 2: { ProtocolMessageTypes.request_block_header: RLSettings(False, 500, 100), @@ -173,9 +190,6 @@ def get_rate_limits_to_use( ProtocolMessageTypes.reject_additions_request: RLSettings(False, 500, 100), ProtocolMessageTypes.reject_header_blocks: RLSettings(False, 1000, 100), ProtocolMessageTypes.respond_header_blocks: RLSettings(False, 5000, 2 * 1024 * 1024), - ProtocolMessageTypes.request_block_headers: RLSettings(False, 5000, 100), - ProtocolMessageTypes.reject_block_headers: RLSettings(False, 1000, 100), - ProtocolMessageTypes.respond_block_headers: RLSettings(False, 5000, 2 * 1024 * 1024), ProtocolMessageTypes.request_ses_hashes: RLSettings(False, 2000, 1 * 1024 * 1024), ProtocolMessageTypes.respond_ses_hashes: RLSettings(False, 2000, 1 * 1024 * 1024), ProtocolMessageTypes.request_children: RLSettings(False, 2000, 1024 * 1024), @@ -183,8 +197,6 @@ def get_rate_limits_to_use( ProtocolMessageTypes.request_puzzle_solution: RLSettings(False, 5000, 100), ProtocolMessageTypes.respond_puzzle_solution: RLSettings(False, 5000, 1024 * 1024), ProtocolMessageTypes.reject_puzzle_solution: RLSettings(False, 5000, 100), - ProtocolMessageTypes.none_response: RLSettings(False, 500, 100), - ProtocolMessageTypes.error: RLSettings(False, 50000, 100), # These will have a lower cap since they don't scale with high TPS (NON_TX_FREQ) ProtocolMessageTypes.request_header_blocks: RLSettings(True, 5000, 100), }, diff --git a/chia/server/rate_limits.py b/chia/server/rate_limits.py index c3a6fdb677c6..ac5aa2210277 100644 --- a/chia/server/rate_limits.py +++ b/chia/server/rate_limits.py @@ -84,11 +84,10 @@ def process_msg_and_check( rate_limits, agg_limit = get_rate_limits_to_use(our_capabilities, peer_capabilities) try: - limits: Union[RLSettings, Unlimited] - limits = rate_limits[message_type] + limits: Union[RLSettings, Unlimited] = rate_limits[message_type] if isinstance(limits, RLSettings) and limits.aggregate_limit: non_tx_freq = agg_limit.frequency - assert agg_limit.max_total_size + assert agg_limit.max_total_size is not None non_tx_max_total_size = agg_limit.max_total_size new_non_tx_count = self.non_tx_message_counts + 1 new_non_tx_size = self.non_tx_cumulative_size + len(message.data)