Skip to content

Commit b88aa2f

Browse files
committed
Fix deadlock in replacement message
1 parent 0c6159a commit b88aa2f

File tree

1 file changed

+4
-18
lines changed

1 file changed

+4
-18
lines changed

crates/batcher/src/lib.rs

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,6 @@ impl Batcher {
289289
.aggregator_fee_percentage_multiplier,
290290
aggregator_gas_cost: config.batcher.aggregator_gas_cost,
291291
posting_batch: Mutex::new(false),
292-
batch_processing_lock: RwLock::new(()),
293292
batch_state: Mutex::new(batch_state),
294293
user_states,
295294
disabled_verifiers: Mutex::new(disabled_verifiers),
@@ -866,14 +865,16 @@ impl Batcher {
866865
// In this case, the message might be a replacement one. If it is valid,
867866
// we replace the old entry with the new from the replacement message.
868867
// Notice this stops the normal flow of the handle_submit_proof.
869-
// locks will be taken inside this function
868+
// We pass the already-held user_state_guard to avoid double-locking
869+
// This will take the batch lock internally
870870
if expected_nonce > msg_nonce {
871871
info!("Possible replacement message received: Expected nonce {expected_nonce:?} - message nonce: {msg_nonce:?}");
872872
self.handle_replacement_message(
873873
nonced_verification_data,
874874
ws_conn_sink.clone(),
875875
client_msg.signature,
876876
addr,
877+
user_state_guard,
877878
)
878879
.await;
879880

@@ -1091,25 +1092,10 @@ impl Batcher {
10911092
ws_conn_sink: WsMessageSink,
10921093
signature: Signature,
10931094
addr: Address,
1095+
mut user_state_guard: tokio::sync::MutexGuard<'_, UserState>,
10941096
) {
10951097
let replacement_max_fee = nonced_verification_data.max_fee;
10961098
let nonce = nonced_verification_data.nonce;
1097-
1098-
// Take user state lock first to maintain proper lock ordering
1099-
let user_state = match self.user_states.get(&addr) {
1100-
Some(user_state) => user_state,
1101-
None => {
1102-
warn!("User state not found for address {addr} during replacement message");
1103-
send_message(
1104-
ws_conn_sink.clone(),
1105-
SubmitProofResponseMessage::InvalidNonce,
1106-
)
1107-
.await;
1108-
self.metrics.user_error(&["invalid_nonce", ""]);
1109-
return;
1110-
}
1111-
};
1112-
let mut user_state_guard = user_state.lock().await; // First: user lock
11131099
let mut batch_state_guard = self.batch_state.lock().await; // Second: batch lock
11141100
let Some(entry) = batch_state_guard.get_entry(addr, nonce) else {
11151101
drop(batch_state_guard);

0 commit comments

Comments
 (0)