Skip to content

Commit 4b6f5f4

Browse files
committed
feat: wip logic in batcher
1 parent 15bf1af commit 4b6f5f4

File tree

3 files changed

+189
-6
lines changed

3 files changed

+189
-6
lines changed

batcher/aligned-batcher/src/eth/utils.rs

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@ use crate::{
88
retry_function,
99
},
1010
};
11-
use aligned_sdk::core::constants::{
11+
use aligned_sdk::core::{constants::{
1212
ETHEREUM_CALL_BACKOFF_FACTOR, ETHEREUM_CALL_MAX_RETRIES, ETHEREUM_CALL_MAX_RETRY_DELAY,
1313
ETHEREUM_CALL_MIN_RETRY_DELAY, GAS_PRICE_INCREMENT_PERCENTAGE_PER_ITERATION,
1414
OVERRIDE_GAS_PRICE_PERCENTAGE_MULTIPLIER, PERCENTAGE_DIVIDER,
15-
};
15+
}, errors::BumpError, types::BumpUnit};
1616
use ethers::prelude::*;
1717
use ethers::providers::{Http, Provider};
1818
use log::error;
@@ -103,6 +103,40 @@ pub async fn get_gas_price(
103103
e.inner()
104104
})
105105
}
106+
107+
pub async fn calculate_bumped_proof_cost(
108+
current_gas_price: U256,
109+
bump_unit: BumpUnit,
110+
amount: U256,
111+
) -> Result<U256, BumpError> {
112+
let new_max_fee = match bump_unit {
113+
BumpUnit::NewMaxFee => {
114+
amount
115+
}
116+
BumpUnit::Wei => {
117+
current_gas_price + amount
118+
}
119+
BumpUnit::Gwei => {
120+
current_gas_price + (amount * U256::from(1_000_000_000))
121+
}
122+
BumpUnit::Eth => {
123+
current_gas_price + (amount * U256::from(1_000_000_000_000_000_000))
124+
}
125+
BumpUnit::Percentage => {
126+
current_gas_price + (current_gas_price * amount / U256::from(PERCENTAGE_DIVIDER))
127+
}
128+
// TODO once Pats pr is done:
129+
// BumpUnit::BatchSize => {
130+
131+
// }
132+
_ => {
133+
warn!("Invalid bump unit: {bump_unit:?}");
134+
return Err(BumpError::InvalidBumpUnit);
135+
}
136+
};
137+
Ok(new_max_fee)
138+
}
139+
106140
#[cfg(test)]
107141
mod tests {
108142
use super::*;

batcher/aligned-batcher/src/lib.rs

Lines changed: 87 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,7 @@ use aligned_sdk::core::constants::{
3131
RESPOND_TO_TASK_FEE_LIMIT_PERCENTAGE_MULTIPLIER,
3232
};
3333
use aligned_sdk::core::types::{
34-
ClientMessage, GetNonceResponseMessage, NoncedVerificationData, ProofInvalidReason,
35-
ProvingSystemId, SubmitProofMessage, SubmitProofResponseMessage, VerificationCommitmentBatch,
36-
VerificationData, VerificationDataCommitment,
34+
BumpFeeResponseMessage, BumpUnit, ClientMessage, GetNonceResponseMessage, NoncedVerificationData, ProofInvalidReason, ProvingSystemId, SubmitProofMessage, SubmitProofResponseMessage, VerificationCommitmentBatch, VerificationData, VerificationDataCommitment
3735
};
3836

3937
use aws_sdk_s3::client::Client as S3Client;
@@ -473,6 +471,11 @@ impl Batcher {
473471
.handle_submit_proof_msg(msg, ws_conn_sink)
474472
.await
475473
}
474+
ClientMessage::BumpFee(bump_unit, amout, proof_qty) => {
475+
self.clone()
476+
.handle_bump_fee_msg(bump_unit, amout, proof_qty, ws_conn_sink)
477+
.await
478+
}
476479
}
477480
}
478481

@@ -783,6 +786,9 @@ impl Batcher {
783786

784787
// In this case, the message might be a replacement one. If it is valid,
785788
// we replace the old entry with the new from the replacement message.
789+
790+
// TODO DISABLE THIS FUNCTIONALITY
791+
// IT IS BEING REPLACED WITH BumpFee()
786792
if expected_nonce > msg_nonce {
787793
info!("Possible replacement message received: Expected nonce {expected_nonce:?} - message nonce: {msg_nonce:?}");
788794
self.handle_replacement_message(
@@ -833,6 +839,84 @@ impl Batcher {
833839
Ok(())
834840
}
835841

842+
843+
// TODO add signature
844+
async fn handle_bump_fee_msg(
845+
bump_unit: BumpUnit,
846+
amount: U256,
847+
proof_qty: usize,
848+
signature: Signature, //TODO add this
849+
signature_content: Vec<u8>, //TODO add this
850+
ws_conn_sink: WsMessageSink,
851+
) -> Result<(), Error> {
852+
853+
// /// The signature of the message is verified, and when it correct, the
854+
// /// recovered address from the signature is returned.
855+
// pub fn verify_signature(&self) -> Result<Address, VerifySignatureError> {
856+
// // Recovers the address from the signed data
857+
// let recovered = self.signature.recover_typed_data(&self.verification_data)?;
858+
859+
// let hashed_data = self.verification_data.encode_eip712()?;
860+
861+
// self.signature.verify(hashed_data, recovered)?;
862+
// Ok(recovered)
863+
// }
864+
865+
info!("Verifying Bump Fee signature...");
866+
let Ok(addr) = verify_bump_signature(signature, signature_content) else {
867+
error!("Signature verification error");
868+
send_message(
869+
ws_conn_sink.clone(),
870+
BumpFeeResponseMessage::InvalidSignature,
871+
)
872+
.await;
873+
self.metrics.user_error(&["invalid_bump_fee_signature", ""]);
874+
return Ok(());
875+
};
876+
info!("Bump Fee signature verified");
877+
878+
879+
let from_proof_nonce = self.get_first_proof();
880+
let to_proof_nonce = from_proof_nonce + proof_qty; // exclusive
881+
882+
let batch_state_lock = self.batch_state.lock().await;
883+
let batch_queue_copy = batch_state_lock.batch_queue.clone();
884+
885+
// TODO check if user has enough funds
886+
while let Some((entry, _)) = batch_state_lock.batch_queue.peek() {
887+
let entry_nonce = entry.nonced_verification_data.nonce;
888+
if entry_nonce >= from_proof_nonce && entry_nonce < to_proof_nonce {
889+
if let Err(bumped_fee) = calculate_bumped_proof_cost(entry.nonced_verification_data.max_fee, bump_unit, amount) {
890+
send_message(
891+
ws_conn_sink.clone(),
892+
BumpFeeResponseMessage::InvalidBumpUnit,
893+
)
894+
.await;
895+
self.metrics.user_error(&["invalid_bump_fee_unit", ""]);
896+
return Ok(());
897+
}
898+
let new_entry = entry.clone();
899+
new_entry.nonced_verification_data.max_fee = bumped_fee;
900+
901+
batch_state_lock.update_user_total_fees_in_queue_of_replacement_message(sender_address, entry_nonce.clone(), bumped_fee).await?;
902+
batch_state_lock.replace_entry(entry, new_entry);
903+
}
904+
};
905+
return;
906+
907+
}
908+
909+
fn verify_bump_signature(
910+
&self,
911+
signature: Signature,
912+
bump_unit: BumpUnit,
913+
amount: U256,
914+
proof_qty: usize,
915+
) -> bool {
916+
// TODO
917+
true
918+
}
919+
836920
async fn is_verifier_disabled(&self, verifier: ProvingSystemId) -> bool {
837921
let disabled_verifiers = self.disabled_verifiers.lock().await;
838922
zk_utils::is_verifier_disabled(*disabled_verifiers, verifier)

batcher/aligned-sdk/src/core/types.rs

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use std::fmt;
22
use std::fmt::Display;
33
use std::fmt::Formatter;
44
use std::str::FromStr;
5+
use std::time::{SystemTime, UNIX_EPOCH};
56

67
use ethers::core::k256::ecdsa::SigningKey;
78
use ethers::signers::Signer;
@@ -231,7 +232,8 @@ pub enum ClientMessage {
231232
// Needs to be wrapped in box as the message is 3x bigger than the others
232233
// see https://rust-lang.github.io/rust-clippy/master/index.html#large_enum_variant
233234
SubmitProof(Box<SubmitProofMessage>),
234-
BumpFee(BumpUnit, U256, usize), // BumpUnit, value, proof_qty
235+
// BumpFee(BumpUnit, U256, usize), // BumpUnit, value, proof_qty
236+
BumpFee(BumpFeeMessage), // BumpUnit, value, proof_qty
235237
}
236238

237239
impl Display for ClientMessage {
@@ -398,11 +400,74 @@ pub enum GetNonceResponseMessage {
398400
InvalidRequest(String),
399401
}
400402

403+
pub struct BumpFeeMessage {
404+
pub conent: BumpFeeMessageContent,
405+
pub signature: Signature,
406+
}
407+
408+
pub struct BumpFeeMessageContent {
409+
pub bump_unit: BumpUnit,
410+
pub value: U256,
411+
pub proof_qty: usize,
412+
pub timestamp: u64,
413+
}
414+
415+
impl EIP712 for BumpFeeMessageContent {
416+
type Error = Eip712Error;
417+
fn domain(&self) -> Result<EIP712Domain, Self::Error> {
418+
Ok(EIP712Domain {
419+
name: Some("Aligned".into()),
420+
version: Some("1".into()),
421+
chain_id: Some(self.chain_id),
422+
verifying_contract: Some("0x00"),
423+
salt: None,
424+
})
425+
}
426+
fn type_hash() -> Result<[u8; 32], Self::Error> {
427+
let mut hasher = Keccak256::new();
428+
hasher.update(NONCED_VERIFICATION_DATA_TYPE);
429+
Ok(hasher.finalize().into())
430+
}
431+
432+
pub fn new(bump_unit: BumpUnit, value: U256, proof_qty: usize) -> Self {
433+
let now = SystemTime::now()
434+
.duration_since(UNIX_EPOCH)
435+
.expect("Time went backwards");
436+
let timestamp = now.as_secs(); // Seconds since UNIX_EPOCH
437+
438+
Self {
439+
bump_unit,
440+
value,
441+
proof_qty,
442+
timestamp,
443+
}
444+
}
445+
}
446+
447+
impl BumpFeeMessage {
448+
pub fn new(
449+
bump_unit: BumpUnit,
450+
value: U256,
451+
proof_qty: usize,
452+
wallet: Wallet<SigningKey>
453+
) -> Self {
454+
let signature = wallet.sign_typed_data(&BumpFeeMessageContent::new(bump_unit, value, proof_qty)).unwrap();
455+
456+
Self {
457+
bump_unit,
458+
value,
459+
proof_qty,
460+
timestamp,
461+
}
462+
}
463+
}
464+
401465
#[derive(Debug, Clone, Serialize, Deserialize)]
402466
pub enum BumpFeeResponseMessage {
403467
Ok(),
404468
EthRpcError(String),
405469
InvalidRequest(String),
470+
InvalidBumpUnit,
406471
}
407472

408473
#[derive(Debug, Serialize, Deserialize, Clone)]

0 commit comments

Comments
 (0)