1use std::{collections::HashMap, sync::LazyLock};
2
3use chia_protocol::ProtocolMessageTypes;
4
5#[derive(Debug, Clone)]
6pub struct RateLimits {
7 pub default_settings: RateLimit,
8 pub non_tx_frequency: f64,
9 pub non_tx_max_total_size: f64,
10 pub tx: HashMap<ProtocolMessageTypes, RateLimit>,
11 pub other: HashMap<ProtocolMessageTypes, RateLimit>,
12}
13
14impl RateLimits {
15 pub fn extend(&mut self, other: &Self) {
16 self.default_settings = other.default_settings;
17 self.non_tx_frequency = other.non_tx_frequency;
18 self.non_tx_max_total_size = other.non_tx_max_total_size;
19 self.tx.extend(other.tx.clone());
20 self.other.extend(other.other.clone());
21 }
22}
23
24#[derive(Debug, Clone, Copy)]
25pub struct RateLimit {
26 pub frequency: f64,
27 pub max_size: f64,
28 pub max_total_size: Option<f64>,
29}
30
31impl RateLimit {
32 pub fn new(frequency: f64, max_size: f64, max_total_size: Option<f64>) -> Self {
33 Self {
34 frequency,
35 max_size,
36 max_total_size,
37 }
38 }
39}
40
41macro_rules! settings {
42 ($($message:ident => $frequency:expr, $max_size:expr $(, $max_total_size:expr)? ;)*) => {
43 {
44 let mut settings = HashMap::new();
45 $(
46 #[allow(unused_mut, unused_assignments)]
47 let mut max_total_size = None;
48 $( max_total_size = Some($max_total_size); )?
49 settings.insert(
50 ProtocolMessageTypes::$message,
51 RateLimit::new(
52 $frequency.into(),
53 $max_size.into(),
54 max_total_size.map(|num: u32| num.into()),
55 )
56 );
57 )*
58 settings
59 }
60 };
61}
62
63pub static V1_RATE_LIMITS: LazyLock<RateLimits> = LazyLock::new(|| RateLimits {
65 default_settings: RateLimit::new(100.0, 1024.0 * 1024.0, Some(100.0 * 1024.0 * 1024.0)),
66 non_tx_frequency: 1000.0,
67 non_tx_max_total_size: 100.0 * 1024.0 * 1024.0,
68 tx: settings! {
69 NewTransaction => 5000, 100, 5000 * 100;
70 RequestTransaction => 5000, 100, 5000 * 100;
71 RespondTransaction => 5000, 1024 * 1024, 20 * 1024 * 1024;
72 SendTransaction => 5000, 1024 * 1024;
73 TransactionAck => 5000, 2048;
74 },
75 other: settings! {
76 Handshake => 5, 10 * 1024, 5 * 10 * 1024;
77 HarvesterHandshake => 5, 1024 * 1024;
78 NewSignagePointHarvester => 100, 4886;
79 NewProofOfSpace => 100, 2048;
80 RequestSignatures => 100, 2048;
81 RespondSignatures => 100, 2048;
82 NewSignagePoint => 200, 2048;
83 DeclareProofOfSpace => 100, 10 * 1024;
84 RequestSignedValues => 100, 10 * 1024;
85 FarmingInfo => 100, 1024;
86 SignedValues => 100, 1024;
87 NewPeakTimelord => 100, 20 * 1024;
88 NewUnfinishedBlockTimelord => 100, 10 * 1024;
89 NewSignagePointVdf => 100, 100 * 1024;
90 NewInfusionPointVdf => 100, 100 * 1024;
91 NewEndOfSubSlotVdf => 100, 100 * 1024;
92 RequestCompactProofOfTime => 100, 10 * 1024;
93 RespondCompactProofOfTime => 100, 100 * 1024;
94 NewPeak => 200, 512;
95 RequestProofOfWeight => 5, 100;
96 RespondProofOfWeight => 5, 50 * 1024 * 1024, 100 * 1024 * 1024;
97 RequestBlock => 200, 100;
98 RejectBlock => 200, 100;
99 RequestBlocks => 500, 100;
100 RespondBlocks => 100, 50 * 1024 * 1024, 5 * 50 * 1024 * 1024;
101 RejectBlocks => 100, 100;
102 RespondBlock => 200, 2 * 1024 * 1024, 10 * 2 * 1024 * 1024;
103 NewUnfinishedBlock => 200, 100;
104 RequestUnfinishedBlock => 200, 100;
105 NewUnfinishedBlock2 => 200, 100;
106 RequestUnfinishedBlock2 => 200, 100;
107 RespondUnfinishedBlock => 200, 2 * 1024 * 1024, 10 * 2 * 1024 * 1024;
108 NewSignagePointOrEndOfSubSlot => 200, 200;
109 RequestSignagePointOrEndOfSubSlot => 200, 200;
110 RespondSignagePoint => 200, 50 * 1024;
111 RespondEndOfSubSlot => 100, 50 * 1024;
112 RequestMempoolTransactions => 5, 1024 * 1024;
113 RequestCompactVDF => 200, 1024;
114 RespondCompactVDF => 200, 100 * 1024;
115 NewCompactVDF => 100, 1024;
116 RequestPeers => 10, 100;
117 RespondPeers => 10, 1024 * 1024;
118 RequestPuzzleSolution => 1000, 100;
119 RespondPuzzleSolution => 1000, 1024 * 1024;
120 RejectPuzzleSolution => 1000, 100;
121 NewPeakWallet => 200, 300;
122 RequestBlockHeader => 500, 100;
123 RespondBlockHeader => 500, 500 * 1024;
124 RejectHeaderRequest => 500, 100;
125 RequestRemovals => 500, 50 * 1024, 10 * 1024 * 1024;
126 RespondRemovals => 500, 1024 * 1024, 10 * 1024 * 1024;
127 RejectRemovalsRequest => 500, 100;
128 RequestAdditions => 500, 1024 * 1024, 10 * 1024 * 1024;
129 RespondAdditions => 500, 1024 * 1024, 10 * 1024 * 1024;
130 RejectAdditionsRequest => 500, 100;
131 RequestHeaderBlocks => 500, 100;
132 RejectHeaderBlocks => 100, 100;
133 RespondHeaderBlocks => 500, 2 * 1024 * 1024, 100 * 1024 * 1024;
134 RequestPeersIntroducer => 100, 100;
135 RespondPeersIntroducer => 100, 1024 * 1024;
136 FarmNewBlock => 200, 200;
137 RequestPlots => 10, 10 * 1024 * 1024;
138 RespondPlots => 10, 100 * 1024 * 1024;
139 PlotSyncStart => 1000, 100 * 1024 * 1024;
140 PlotSyncLoaded => 1000, 100 * 1024 * 1024;
141 PlotSyncRemoved => 1000, 100 * 1024 * 1024;
142 PlotSyncInvalid => 1000, 100 * 1024 * 1024;
143 PlotSyncKeysMissing => 1000, 100 * 1024 * 1024;
144 PlotSyncDuplicates => 1000, 100 * 1024 * 1024;
145 PlotSyncDone => 1000, 100 * 1024 * 1024;
146 PlotSyncResponse => 3000, 100 * 1024 * 1024;
147 CoinStateUpdate => 1000, 100 * 1024 * 1024;
148 RegisterForPhUpdates => 1000, 100 * 1024 * 1024;
149 RespondToPhUpdates => 1000, 100 * 1024 * 1024;
150 RegisterForCoinUpdates => 1000, 100 * 1024 * 1024;
151 RespondToCoinUpdates => 1000, 100 * 1024 * 1024;
152 RequestRemovePuzzleSubscriptions => 1000, 100 * 1024 * 1024;
153 RespondRemovePuzzleSubscriptions => 1000, 100 * 1024 * 1024;
154 RequestRemoveCoinSubscriptions => 1000, 100 * 1024 * 1024;
155 RespondRemoveCoinSubscriptions => 1000, 100 * 1024 * 1024;
156 RequestPuzzleState => 1000, 100 * 1024 * 1024;
157 RespondPuzzleState => 1000, 100 * 1024 * 1024;
158 RejectPuzzleState => 200, 100;
159 RequestCoinState => 1000, 100 * 1024 * 1024;
160 RespondCoinState => 1000, 100 * 1024 * 1024;
161 RejectCoinState => 200, 100;
162 RequestChildren => 2000, 1024 * 1024;
169 RespondChildren => 2000, 1024 * 1024;
170 },
171});
172
173static V2_RATE_LIMIT_CHANGES: LazyLock<RateLimits> = LazyLock::new(|| RateLimits {
176 default_settings: RateLimit::new(100.0, 1024.0 * 1024.0, Some(100.0 * 1024.0 * 1024.0)),
177 non_tx_frequency: 1000.0,
178 non_tx_max_total_size: 100.0 * 1024.0 * 1024.0,
179 tx: settings! {
180 RequestBlockHeader => 500, 100;
181 RespondBlockHeader => 500, 500 * 1024;
182 RejectHeaderRequest => 500, 100;
183 RequestRemovals => 5000, 50 * 1024, 10 * 1024 * 1024;
184 RespondRemovals => 5000, 1024 * 1024, 10 * 1024 * 1024;
185 RejectRemovalsRequest => 500, 100;
186 RequestAdditions => 50000, 100 * 1024 * 1024;
187 RespondAdditions => 50000, 100 * 1024 * 1024;
188 RejectAdditionsRequest => 500, 100;
189 RejectHeaderBlocks => 1000, 100;
190 RespondHeaderBlocks => 5000, 2 * 1024 * 1024;
191 RequestBlockHeaders => 5000, 100;
192 RejectBlockHeaders => 1000, 100;
193 RespondBlockHeaders => 5000, 2 * 1024 * 1024;
194 RequestChildren => 2000, 1024 * 1024;
197 RespondChildren => 2000, 1024 * 1024;
198 RequestPuzzleSolution => 5000, 100;
199 RespondPuzzleSolution => 5000, 1024 * 1024;
200 RejectPuzzleSolution => 5000, 100;
201 NoneResponse => 500, 100;
202 },
204 other: settings! {
205 RequestHeaderBlocks => 5000, 100;
206 },
207});
208
209pub static V2_RATE_LIMITS: LazyLock<RateLimits> = LazyLock::new(|| {
210 let mut rate_limits = V1_RATE_LIMITS.clone();
211 rate_limits.extend(&V2_RATE_LIMIT_CHANGES);
212 rate_limits
213});