Skip to content

Commit d4981dd

Browse files
committed
feat: move constants to config file
1 parent a029194 commit d4981dd

File tree

5 files changed

+51
-21
lines changed

5 files changed

+51
-21
lines changed

config-files/config-batcher-docker.yaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,10 @@ batcher:
3131
non_paying:
3232
address: '0xa0Ee7A142d267C1f36714E4a8F75612F20a79720' # Anvil address 9
3333
replacement_private_key: ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 # Anvil address 1
34+
# When validating if the msg covers the minimum max fee
35+
# A batch of how many proofs should it cover
36+
proofs_to_cover_in_min_max_fee: 32,
37+
# When replacing the message, how much higher should the max fee in comparison to the original one
38+
# The calculation is replacement_max_fee >= original_max_fee + original_max_fee * min_bump_percentage / 100
39+
min_bump_percentage: 10,
40+

config-files/config-batcher-ethereum-package.yaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,10 @@ batcher:
2929
non_paying:
3030
address: '0xa0Ee7A142d267C1f36714E4a8F75612F20a79720' # Anvil address 9
3131
replacement_private_key: ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 # Anvil address 1
32+
# When validating if the msg covers the minimum max fee
33+
# A batch of how many proofs should it cover
34+
proofs_to_cover_in_min_max_fee: 32,
35+
# When replacing the message, how much higher should the max fee in comparison to the original one
36+
# The calculation is replacement_max_fee >= original_max_fee + original_max_fee * min_bump_percentage / 100
37+
min_bump_percentage: 10,
38+

config-files/config-batcher.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,9 @@ batcher:
3131
non_paying:
3232
address: '0xa0Ee7A142d267C1f36714E4a8F75612F20a79720' # Anvil address 9
3333
replacement_private_key: ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 # Anvil address 1
34+
# When validating if the msg covers the minimum max fee
35+
# A batch of how many proofs should it cover
36+
proofs_to_cover_in_min_max_fee: 32,
37+
# When replacing the message, how much higher should the max fee in comparison to the original one
38+
# The calculation is replacement_max_fee >= original_max_fee + original_max_fee * min_bump_percentage / 100
39+
min_bump_percentage: 10,

crates/batcher/src/config/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ pub struct BatcherConfigFromYaml {
5151
pub metrics_port: u16,
5252
pub telemetry_ip_port_address: String,
5353
pub non_paying: Option<NonPayingConfigFromYaml>,
54+
pub proofs_to_cover_in_min_max_fee: usize,
55+
pub min_bump_percentage: u64,
5456
}
5557

5658
#[derive(Debug, Deserialize)]

crates/batcher/src/lib.rs

Lines changed: 29 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,8 @@ pub struct Batcher {
9898
aggregator_fee_percentage_multiplier: u128,
9999
aggregator_gas_cost: u128,
100100
latest_block_gas_price: RwLock<U256>,
101+
proofs_to_cover_in_min_max_fee: usize,
102+
min_bump_percentage: U256,
101103
pub metrics: metrics::BatcherMetrics,
102104
pub telemetry: TelemetrySender,
103105
}
@@ -267,6 +269,8 @@ impl Batcher {
267269
max_proof_size: config.batcher.max_proof_size,
268270
max_batch_byte_size: config.batcher.max_batch_byte_size,
269271
max_batch_proof_qty: config.batcher.max_batch_proof_qty,
272+
proofs_to_cover_in_min_max_fee: config.batcher.proofs_to_cover_in_min_max_fee,
273+
min_bump_percentage: U256::from(config.batcher.min_bump_percentage),
270274
last_uploaded_batch_block: Mutex::new(last_uploaded_batch_block),
271275
pre_verification_is_enabled: config.batcher.pre_verification_is_enabled,
272276
non_paying_config,
@@ -664,6 +668,19 @@ impl Batcher {
664668
nonced_verification_data = aux_verification_data
665669
}
666670

671+
// Before moving on to process the message, verify that the max fee covers the
672+
// minimum max fee allowed. This prevents users from spamming with very low max fees
673+
// the min max fee is enforced by checking if it can cover a batch of [`proofs_to_cover_in_min_max_fee`]
674+
let msg_max_fee = nonced_verification_data.max_fee;
675+
if !self.msg_covers_minimum_max_fee(msg_max_fee).await {
676+
send_message(
677+
ws_conn_sink.clone(),
678+
SubmitProofResponseMessage::UnderpricedProof,
679+
)
680+
.await;
681+
return Ok(());
682+
};
683+
667684
// When pre-verification is enabled, batcher will verify proofs for faster feedback with clients
668685
if self.pre_verification_is_enabled {
669686
let verification_data = &nonced_verification_data.verification_data;
@@ -768,23 +785,6 @@ impl Batcher {
768785

769786
let mut batch_state_lock = self.batch_state.lock().await;
770787

771-
let msg_max_fee = nonced_verification_data.max_fee;
772-
773-
// Verify that the max fee is enough to cover a batch of 32 proofs at least
774-
// TODO move number to config file
775-
let gas_price = *self.latest_block_gas_price.read().await;
776-
let min_max_fee_per_proof =
777-
aligned_sdk::verification_layer::compute_fee_per_proof_formula(32, gas_price);
778-
if msg_max_fee < min_max_fee_per_proof {
779-
std::mem::drop(batch_state_lock);
780-
send_message(
781-
ws_conn_sink.clone(),
782-
SubmitProofResponseMessage::UnderpricedProof,
783-
)
784-
.await;
785-
return Ok(());
786-
}
787-
788788
let Some(user_last_max_fee_limit) =
789789
batch_state_lock.get_user_last_max_fee_limit(&addr).await
790790
else {
@@ -1007,12 +1007,11 @@ impl Batcher {
10071007
return;
10081008
};
10091009

1010-
// the replacement max fee bump must be at least 10 percent higher
1011-
// TODO: move this to a config file
1010+
// Validate that the max fee is at least higher or equal to the original fee + a [`min_bump_percentage`]
10121011
let original_max_fee = entry.nonced_verification_data.max_fee;
1013-
let bump_factor_percentage = 10;
10141012
let min_bump = original_max_fee
1015-
+ (original_max_fee * U256::from(bump_factor_percentage)) / U256::from(100);
1013+
+ (original_max_fee * U256::from(self.min_bump_percentage)) / U256::from(100);
1014+
10161015
if replacement_max_fee < min_bump {
10171016
std::mem::drop(batch_state_lock);
10181017
warn!("Invalid replacement message for address {addr}, had max fee: {original_max_fee:?}, received fee: {replacement_max_fee:?}");
@@ -2046,6 +2045,15 @@ impl Batcher {
20462045
true
20472046
}
20482047

2048+
async fn msg_covers_minimum_max_fee(&self, msg_max_fee: U256) -> bool {
2049+
let gas_price = *self.latest_block_gas_price.read().await;
2050+
let min_max_fee_per_proof = aligned_sdk::verification_layer::compute_fee_per_proof_formula(
2051+
self.proofs_to_cover_in_min_max_fee,
2052+
gas_price,
2053+
);
2054+
msg_max_fee >= min_max_fee_per_proof
2055+
}
2056+
20492057
/// Checks if the user's balance is unlocked
20502058
/// Returns false if balance is unlocked, logs the error,
20512059
/// and sends it to the metrics server

0 commit comments

Comments
 (0)