diff --git a/etherlink/CHANGES_NODE.md b/etherlink/CHANGES_NODE.md index c5b6e4354d2dfd6e5b2c648f7d3ac81909f82dba..501fa884a6cb399066a1d8cc4046c5863bd92419 100644 --- a/etherlink/CHANGES_NODE.md +++ b/etherlink/CHANGES_NODE.md @@ -7,6 +7,9 @@ ### Bug fixes - Default rollup node port is 8932, not 8937. (!15701) +- Reintroduces a safety guard removed in previous version, checks the L1 block + level provided by the rollup node, always ignore it if it was already + processed. (!15724) ### Internals diff --git a/etherlink/bin_node/lib_dev/evm_context.ml b/etherlink/bin_node/lib_dev/evm_context.ml index 0cf4e297f51098a0eab3057a16bebb84d1e16c31..e9ec6df836b1f0ebd865c683dfbcde4e7f71f92b 100644 --- a/etherlink/bin_node/lib_dev/evm_context.ml +++ b/etherlink/bin_node/lib_dev/evm_context.ml @@ -611,6 +611,34 @@ module State = struct let (Qty next_blueprint_number) = ctxt.session.next_blueprint_number in Ethereum_types.Qty (Z.pred next_blueprint_number) + let needs_process_l1_block ctxt rollup_block_level = + let open Lwt_result_syntax in + let* last_known_l1_block = + let* level = + Evm_store.use ctxt.store @@ fun conn -> + Evm_store.L1_l2_levels_relationships.find conn + in + match level with + | Some {l1_level; _} -> return_some l1_level + | None -> return_none + in + match last_known_l1_block with + | None -> return_true + | Some last_known_l1_block -> + let level_expected = Int32.succ last_known_l1_block in + if Int32.equal rollup_block_level level_expected then return_true + else if Compare.Int32.(rollup_block_level < level_expected) then + let*! () = + Evm_context_events.unexpected_l1_block + ~expected_level:level_expected + ~provided_level:rollup_block_level + in + return false + else + tzfail + (Node_error.Out_of_sync + {level_received = rollup_block_level; level_expected}) + let apply_evm_events ?finalized_level (ctxt : t) events = let open Lwt_result_syntax in let* needs_process = @@ -619,32 +647,7 @@ module State = struct (* We are not taking events from a rollup block, we don't need to check if it's the last known l1 block successor. *) return_true - | Some rollup_block_level -> ( - let* last_known_l1_block = - let* level = - Evm_store.use ctxt.store @@ fun conn -> - Evm_store.L1_l2_levels_relationships.find conn - in - match level with - | Some {l1_level; _} -> return_some l1_level - | None -> return_none - in - match last_known_l1_block with - | None -> return_true - | Some last_known_l1_block -> - let level_expected = Int32.succ last_known_l1_block in - if Int32.equal rollup_block_level level_expected then return_true - else if Compare.Int32.(rollup_block_level < level_expected) then - let*! () = - Evm_context_events.unexpected_l1_block - ~expected_level:level_expected - ~provided_level:rollup_block_level - in - return false - else - tzfail - (Node_error.Out_of_sync - {level_received = rollup_block_level; level_expected})) + | Some finalized_level -> needs_process_l1_block ctxt finalized_level in if needs_process then ( let* context, evm_state, on_success = @@ -1471,14 +1474,17 @@ module Handlers = struct | New_last_known_L1_level l1_level -> protect @@ fun () -> let ctxt = Worker.state self in - Evm_store.use ctxt.store @@ fun conn -> - let l2_level = State.current_blueprint_number ctxt in - let*! () = Evm_context_events.processed_l1_level l1_level in - Evm_store.L1_l2_levels_relationships.store - conn - ~latest_l2_level:l2_level - ~l1_level - ~finalized_l2_level:ctxt.session.finalized_number + let* needs_process = State.needs_process_l1_block ctxt l1_level in + if needs_process then + let*! () = Evm_context_events.processed_l1_level l1_level in + Evm_store.use ctxt.store @@ fun conn -> + let l2_level = State.current_blueprint_number ctxt in + Evm_store.L1_l2_levels_relationships.store + conn + ~latest_l2_level:l2_level + ~l1_level + ~finalized_l2_level:ctxt.session.finalized_number + else return_unit | Delayed_inbox_hashes -> protect @@ fun () -> let ctxt = Worker.state self in