From a2f9f8c61e1e5ef7923de20d4d6c899a015eb74d Mon Sep 17 00:00:00 2001 From: Vitaly Drogan Date: Sat, 26 Jun 2021 12:56:40 +0300 Subject: [PATCH 1/2] Add handling of priority queue gap in eth_watch --- core/bin/zksync_core/src/eth_watch/mod.rs | 26 ++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/core/bin/zksync_core/src/eth_watch/mod.rs b/core/bin/zksync_core/src/eth_watch/mod.rs index 0e07fa419b..63e7d664c9 100644 --- a/core/bin/zksync_core/src/eth_watch/mod.rs +++ b/core/bin/zksync_core/src/eth_watch/mod.rs @@ -149,13 +149,24 @@ impl EthWatch { // Extend the existing priority operations with the new ones. let mut priority_queue = sift_outdated_ops(self.eth_state.priority_queue()); - let new_priority_op_ids: Vec<_> = priority_queue.keys().cloned().collect(); - vlog::debug!("New priority ops added: {:?}", new_priority_op_ids); for (serial_id, op) in received_priority_queue { priority_queue.insert(serial_id, op); } + // Check for gaps in priority queue. If some event is missing we skip this `ETHState` update. + let mut priority_op_ids: Vec<_> = priority_queue.keys().cloned().collect(); + priority_op_ids.sort_unstable(); + for i in 0..priority_op_ids.len().saturating_sub(1) { + let gap = priority_op_ids[i + 1] - priority_op_ids[i]; + anyhow::ensure!( + gap == 1, + "Gap in priority op queue: gap={}, priority_op_before_gap={}", + gap, + priority_op_ids[i] + ); + } + let new_state = ETHState::new(last_ethereum_block, unconfirmed_queue, priority_queue); self.set_new_state(new_state); Ok(()) @@ -184,7 +195,7 @@ impl EthWatch { new_block_with_accepted_events.saturating_sub(unprocessed_blocks_amount); let unconfirmed_queue = self.get_unconfirmed_ops(current_ethereum_block).await?; - let priority_queue = self + let priority_queue: HashMap = self .client .get_priority_op_events( BlockNumber::Number(previous_block_with_accepted_events.into()), @@ -195,6 +206,15 @@ impl EthWatch { .map(|priority_op| (priority_op.serial_id, priority_op.into())) .collect(); + let mut new_priority_op_ids: Vec<_> = priority_queue.keys().cloned().collect(); + new_priority_op_ids.sort_unstable(); + vlog::debug!( + "Updating eth state: block_range=[{},{}], new_priority_ops={:?}", + previous_block_with_accepted_events, + new_block_with_accepted_events, + new_priority_op_ids + ); + Ok((unconfirmed_queue, priority_queue)) } From b088ccc12142901ba0a3736cad59b2d2547e9567 Mon Sep 17 00:00:00 2001 From: deniallugo Date: Wed, 14 Jul 2021 17:56:41 +0300 Subject: [PATCH 2/2] Add check about invalid target account Signed-off-by: deniallugo --- core/lib/state/src/handler/error.rs | 2 ++ core/lib/state/src/handler/forced_exit.rs | 8 +++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/core/lib/state/src/handler/error.rs b/core/lib/state/src/handler/error.rs index 911af012b3..fd2762de99 100644 --- a/core/lib/state/src/handler/error.rs +++ b/core/lib/state/src/handler/error.rs @@ -52,6 +52,8 @@ pub enum ForcedExitOpError { InvalidTokenId, #[error("Target account is not locked; forced exit is forbidden")] TargetAccountNotLocked, + #[error("Target account is invalid")] + InvalidTargetAccount, #[error("Nonce mismatch")] NonceMismatch, #[error("Initiator account: Not enough balance to cover fees")] diff --git a/core/lib/state/src/handler/forced_exit.rs b/core/lib/state/src/handler/forced_exit.rs index b27bd4d962..f820441781 100644 --- a/core/lib/state/src/handler/forced_exit.rs +++ b/core/lib/state/src/handler/forced_exit.rs @@ -1,6 +1,8 @@ use std::time::Instant; use zksync_crypto::params; -use zksync_types::{AccountUpdate, AccountUpdates, ForcedExit, ForcedExitOp, PubKeyHash, ZkSyncOp}; +use zksync_types::{ + AccountUpdate, AccountUpdates, Address, ForcedExit, ForcedExitOp, PubKeyHash, ZkSyncOp, +}; use zksync_utils::BigUintSerdeWrapper; use crate::{ @@ -37,6 +39,10 @@ impl TxHandler for ZkSyncState { account.pub_key_hash == PubKeyHash::default(), ForcedExitOpError::TargetAccountNotLocked ); + invariant!( + account.address != Address::default(), + ForcedExitOpError::InvalidTargetAccount + ); // Obtain the token balance to be withdrawn. let account_balance = self