From aa6dd40dc05369b50bbe96f4f15008630a2719a8 Mon Sep 17 00:00:00 2001 From: Valentin Chaboche Date: Wed, 15 May 2024 10:40:07 +0200 Subject: [PATCH 1/3] EVM/Kernel: process at most one block if storage says so --- etherlink/CHANGES_KERNEL.md | 2 ++ etherlink/kernel_evm/kernel/src/block.rs | 28 +++++++++++++++++------- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/etherlink/CHANGES_KERNEL.md b/etherlink/CHANGES_KERNEL.md index 81212d5b6900..ed19aa96de6e 100644 --- a/etherlink/CHANGES_KERNEL.md +++ b/etherlink/CHANGES_KERNEL.md @@ -24,6 +24,8 @@ - Gas price is removed from internal structure block in progress. (!13220) - Refactor block creation to properly add the gas limit. (!13278) - Gas limit is no longer optional for blocks. (!13279) +- The kernel can limit the block production to at most one block per tezos level + if the file `/__at_most_one_block` exists in the storage. (!13202) ## Version b9f6c9138719220db83086f0548e49c5c4c8421f diff --git a/etherlink/kernel_evm/kernel/src/block.rs b/etherlink/kernel_evm/kernel/src/block.rs index 852c2e2f8111..c2b9279cf44d 100644 --- a/etherlink/kernel_evm/kernel/src/block.rs +++ b/etherlink/kernel_evm/kernel/src/block.rs @@ -32,7 +32,7 @@ use tezos_ethereum::block::BlockFees; use tezos_evm_logging::{log, Level::*}; use tezos_indexable_storage::IndexableStorage; use tezos_smart_rollup::outbox::OutboxQueue; -use tezos_smart_rollup_host::path::Path; +use tezos_smart_rollup_host::path::{Path, RefPath}; use tezos_smart_rollup_host::runtime::Runtime; use tick_model::estimate_remaining_ticks_for_transaction_execution; @@ -352,6 +352,8 @@ fn promote_block( Ok(()) } +const AT_MOST_ONE_BLOCK: RefPath = RefPath::assert_from(b"/__at_most_one_block"); + pub fn produce( host: &mut Host, chain_id: U256, @@ -389,6 +391,8 @@ pub fn produce( let mut tick_counter = TickCounter::new(0u64); let mut first_block_of_reboot = true; + let at_most_one_block = host.store_has(&AT_MOST_ONE_BLOCK)?.is_some(); + #[cfg(not(test))] let mut internal_storage = crate::internal_storage::InternalStorage(); #[cfg(test)] @@ -422,12 +426,17 @@ pub fn produce( &config.limits, &trace_input, ) { - Ok(ComputationResult::Finished) => promote_block( - &mut safe_host, - &outbox_queue, - true, - processed_blueprint, - )?, + Ok(ComputationResult::Finished) => { + promote_block( + &mut safe_host, + &outbox_queue, + true, + processed_blueprint, + )?; + if at_most_one_block { + return Ok(ComputationResult::Finished); + } + } Ok(ComputationResult::RebootNeeded) => { // The computation still needs to reboot, we do nothing. return Ok(ComputationResult::RebootNeeded); @@ -497,7 +506,10 @@ pub fn produce( &trace_input, ) { Ok(ComputationResult::Finished) => { - promote_block(&mut safe_host, &outbox_queue, false, processed_blueprint)? + promote_block(&mut safe_host, &outbox_queue, false, processed_blueprint)?; + if at_most_one_block { + return Ok(ComputationResult::Finished); + } } Ok(ComputationResult::RebootNeeded) => { // The computation will resume at next reboot, we leave the -- GitLab From 5cf45df58dd54949926e0dc1654a6cf1595336aa Mon Sep 17 00:00:00 2001 From: Valentin Chaboche Date: Tue, 14 May 2024 12:46:34 +0200 Subject: [PATCH 2/3] EVM/Node: possibility to reconstruct history in init --- etherlink/bin_node/lib_dev/evm_context.ml | 215 ++++++++++++++++-- etherlink/bin_node/lib_dev/evm_context.mli | 16 +- .../bin_node/lib_dev/rollup_node_storage.ml | 65 ++++++ etherlink/bin_node/main.ml | 18 +- 4 files changed, 294 insertions(+), 20 deletions(-) diff --git a/etherlink/bin_node/lib_dev/evm_context.ml b/etherlink/bin_node/lib_dev/evm_context.ml index 00e8f78b5898..3457813b775a 100644 --- a/etherlink/bin_node/lib_dev/evm_context.ml +++ b/etherlink/bin_node/lib_dev/evm_context.ml @@ -52,6 +52,14 @@ let session_to_head_info session = current_block_hash = session.current_block_hash; } +let pvm_config ctxt = + Config.config + ~preimage_directory:ctxt.preimages + ?preimage_endpoint:ctxt.preimages_endpoint + ~kernel_debug:true + ~destination:ctxt.smart_rollup_address + () + module Types = struct type state = t @@ -103,6 +111,15 @@ module Request = struct | Evm_state_after : block_request -> (Evm_state.t option, tztrace) t | Earliest_state : (Evm_state.t option, tztrace) t | Earliest_number : (Ethereum_types.quantity option, tztrace) t + | Reconstruct : { + reconstruct_from_boot_sector : string; + rollup_node_data_dir : string; + genesis_level : int32; + finalized_level : int32; + levels_to_hashes : [`Read] Rollup_node_storage.Levels_to_hashes.t; + l2_blocks : [`Read] Rollup_node_storage.L2_blocks.t; + } + -> (unit, tztrace) t type view = View : _ t -> view @@ -815,6 +832,138 @@ module State = struct Evm_store.Delayed_transactions.at_level ctxt.store level in return_some Blueprint_types.{delayed_transactions; blueprint} + + let messages_of_level ~levels_to_hashes ~l2_blocks ~messages level = + let open Lwt_result_syntax in + let open Rollup_node_storage in + let* hash = Levels_to_hashes.find levels_to_hashes level in + let*? hash = + Option.to_result + ~none:[error_of_fmt "Block hash is not found for level %ld" level] + hash + in + let* block = L2_blocks.read l2_blocks hash in + let*? _, header = + Option.to_result + ~none:[error_of_fmt "Block is not found for hash %a" Block_hash.pp hash] + block + in + let* messages = Messages.read messages header.inbox_witness in + let*? messages = + Option.to_result + ~none:[error_of_fmt "No messages found for block %a" Block_hash.pp hash] + messages + in + return (fst messages) + + (** [reconstruct_commit_blocks ~current_block_number ctxt execute + evm_state] loops on [execute evm_state] until no new block is + produced. We cannot (easily) know how many blocks an execution + is supposed to make, so we execute until no block is not + produced. If no new block is produced by this function, no + commits are produced. *) + let rec reconstruct_commit_blocks ~current_block_number ctxt execute evm_state + = + let open Lwt_result_syntax in + let* evm_state = execute evm_state in + let*! (Qty number) = Evm_state.current_block_height evm_state in + if number > current_block_number then ( + (* The kernel produced a new block, we commit the intermediate state. *) + let* context = + commit ctxt.store ctxt.session.context evm_state (Qty number) + in + ctxt.session.context <- context ; + reconstruct_commit_blocks + ~current_block_number:number + ctxt + execute + evm_state) + else + (* The kernel did not produce a new block. It either means the block + takes more than 1000 reboots to be processed, or no blueprints are + found in the storage. *) + return (current_block_number, evm_state) + + let reconstruct_history ctxt ~reconstruct_from_boot_sector + ~rollup_node_data_dir ~genesis_level ~finalized_level ~levels_to_hashes + ~l2_blocks = + let open Lwt_result_syntax in + (* Smart Rollups do not process messages of genesis level. *) + let first_level = Int32.succ genesis_level in + assert (finalized_level > first_level) ; + + let* messages = + Rollup_node_storage.load_messages ~rollup_node_data_dir () + in + + let messages_of_level = + messages_of_level ~levels_to_hashes ~l2_blocks ~messages + in + + let config = pvm_config ctxt in + let rec go ~current_block_number evm_state tezos_level = + if tezos_level > finalized_level then return_unit + else + let* messages = messages_of_level tezos_level in + (* For now we use the mocked sol, ipl and eol of the debugger. *) + let messages = + match messages with + | _sol :: _ipl :: rst -> + List.rev (Option.value ~default:[] @@ List.tl (List.rev rst)) + | _ -> assert false + in + (* Execute the PVM to replay the tezos level. *) + let* evm_state = + Evm_state.execute + ~data_dir:ctxt.data_dir + ~log_file:"reconstruct" + ~config + evm_state + (List.map (fun m -> `Input m) messages) + in + let*! (Qty number) = Evm_state.current_block_height evm_state in + let* current_block_number, evm_state = + if number > current_block_number then ( + (* The execution with messages produced a block. We commit to this block, + and loop in case of other blocks. *) + let* context = + commit ctxt.store ctxt.session.context evm_state (Qty number) + in + ctxt.session.context <- context ; + reconstruct_commit_blocks + ~current_block_number:number + ctxt + (fun evm_state -> + Evm_state.execute + ~data_dir:ctxt.data_dir + ~log_file:"reconstruct" + ~config + evm_state + []) + evm_state) + else + (* Otherwise just move to the next tezos level. *) + return (current_block_number, evm_state) + in + go ~current_block_number evm_state (Int32.succ tezos_level) + in + (* Create a fresh evm state where the blocks will be applied one by one. *) + let* fresh_evm_state = + Evm_state.init ~kernel:reconstruct_from_boot_sector + in + (* We perform a first reboot to reveal the kernel. *) + let* evm_state = + Evm_state.execute + ~data_dir:ctxt.data_dir + ~log_file:"reconstruct" + ~config + fresh_evm_state + [] + in + let*! evm_state = + Evm_state.modify ~key:"/__at_most_one_block" ~value:"" evm_state + in + go ~current_block_number:Z.(pred zero) evm_state first_level end module Worker = Worker.MakeSingle (Name) (Request) (Types) @@ -850,14 +999,7 @@ module Handlers = struct ~sqlite_journal_mode () in - Lwt.wakeup execution_config_waker - @@ ( ctxt.data_dir, - Config.config - ~preimage_directory:ctxt.preimages - ?preimage_endpoint:ctxt.preimages_endpoint - ~kernel_debug:true - ~destination:ctxt.smart_rollup_address - () ) ; + Lwt.wakeup execution_config_waker @@ (ctxt.data_dir, pvm_config ctxt) ; Lwt.wakeup init_status_waker status ; let first_head = ref (session_to_head_info ctxt.session) in Lwt.wakeup head_info_waker first_head ; @@ -933,6 +1075,24 @@ module Handlers = struct match checkpoint with | Some (level, _checkpoint) -> return_some level | None -> return_none) + | Reconstruct + { + reconstruct_from_boot_sector; + rollup_node_data_dir; + genesis_level; + finalized_level; + levels_to_hashes; + l2_blocks; + } -> + let ctxt = Worker.state self in + State.reconstruct_history + ctxt + ~reconstruct_from_boot_sector + ~rollup_node_data_dir + ~genesis_level + ~finalized_level + ~levels_to_hashes + ~l2_blocks let on_completion (type a err) _self (_r : (a, err) Request.t) (_res : a) _st = @@ -1085,7 +1245,7 @@ let init_context_from_rollup_node ~data_dir ~rollup_node_data_dir = Irmin_context.checkout_exn evm_node_index checkpoint in let*! evm_state = Irmin_context.PVMState.get evm_node_context in - return (evm_node_context, evm_state, final_level) + return (evm_node_context, evm_state, final_level, levels_to_hashes, l2_blocks) let init_store_from_rollup_node ~data_dir ~evm_state ~irmin_context = let open Lwt_result_syntax in @@ -1174,23 +1334,38 @@ let get_evm_events_from_rollup_node_state ~omit_delayed_tx_events evm_state = let apply_evm_events ?finalized_level events = worker_add_request ~request:(Apply_evm_events {finalized_level; events}) +let reconstruct ~reconstruct_from_boot_sector ~rollup_node_data_dir + ~genesis_level ~finalized_level ~levels_to_hashes ~l2_blocks = + worker_wait_for_request + (Reconstruct + { + reconstruct_from_boot_sector; + rollup_node_data_dir; + genesis_level; + finalized_level; + levels_to_hashes; + l2_blocks; + }) + let init_from_rollup_node ~omit_delayed_tx_events ~data_dir - ~rollup_node_data_dir = + ~rollup_node_data_dir ?reconstruct_from_boot_sector () = let open Lwt_result_syntax in - let* irmin_context, evm_state, finalized_level = + let* irmin_context, evm_state, finalized_level, levels_to_hashes, l2_blocks = init_context_from_rollup_node ~data_dir ~rollup_node_data_dir in let* evm_events = get_evm_events_from_rollup_node_state ~omit_delayed_tx_events evm_state in - let* smart_rollup_address = + let* smart_rollup_address, genesis_level = let* metadata = Metadata.Versioned.read_metadata_file ~dir:rollup_node_data_dir in match metadata with | None -> failwith "missing metadata in the rollup node data dir" - | Some (V0 {rollup_address; _}) | Some (V1 {rollup_address; _}) -> - return @@ Address.to_string rollup_address + | Some (V0 _) -> + failwith "metadata has version 0, we need at least version 1" + | Some (V1 {rollup_address; genesis_info = {level; _}; _}) -> + return (Address.to_string rollup_address, level) in let* () = init_store_from_rollup_node ~data_dir ~evm_state ~irmin_context in let* _loaded = @@ -1203,6 +1378,18 @@ let init_from_rollup_node ~omit_delayed_tx_events ~data_dir ~sqlite_journal_mode:`Identity () in + let* () = + match reconstruct_from_boot_sector with + | Some reconstruct_from_boot_sector -> + reconstruct + ~reconstruct_from_boot_sector + ~rollup_node_data_dir + ~genesis_level + ~finalized_level + ~levels_to_hashes + ~l2_blocks + | None -> return_unit + in apply_evm_events ~finalized_level evm_events let apply_blueprint timestamp payload delayed_transactions = diff --git a/etherlink/bin_node/lib_dev/evm_context.mli b/etherlink/bin_node/lib_dev/evm_context.mli index 97a40b932f78..65aafcdd458b 100644 --- a/etherlink/bin_node/lib_dev/evm_context.mli +++ b/etherlink/bin_node/lib_dev/evm_context.mli @@ -33,14 +33,22 @@ val start : init_status tzresult Lwt.t (** [init_from_rollup_node ~omit_delayed_tx_events ~data_dir - ~rollup_node_data_dir] initialises the irmin context and metadata - of the evm using the latest known evm state of the given rollup - node. if [omit_delayed_tx_events] dont populate the delayed tx - event from the state into the db. *) + ~rollup_node_data_dir ?reconstruct_from_boot_sector ()] + initialises the irmin context and metadata of the evm using the + latest known evm state of the given rollup node. if + [omit_delayed_tx_events] dont populate the delayed tx event from + the state into the db. + + + If [reconstruct_from_boot_sector] is provided all messages contained in + the [rollup_node_data_dir] will be replayed to produce intermediate states. +*) val init_from_rollup_node : omit_delayed_tx_events:bool -> data_dir:string -> rollup_node_data_dir:string -> + ?reconstruct_from_boot_sector:string -> + unit -> unit tzresult Lwt.t (** [reset ~data_dir ~l2_level] reset the sequencer storage to diff --git a/etherlink/bin_node/lib_dev/rollup_node_storage.ml b/etherlink/bin_node/lib_dev/rollup_node_storage.ml index 4d39441a7ac9..962aa7dd4cfd 100644 --- a/etherlink/bin_node/lib_dev/rollup_node_storage.ml +++ b/etherlink/bin_node/lib_dev/rollup_node_storage.ml @@ -83,6 +83,50 @@ module Levels_to_hashes = end)) (Block_key) +module Make_hash_index_key (H : Tezos_crypto.Intfs.HASH) = +Indexed_store.Make_index_key (struct + include Indexed_store.Make_fixed_encodable (H) + + let equal = H.equal +end) + +module Messages = + Indexed_store.Make_indexed_file + (struct + let name = "messages" + end) + (Make_hash_index_key (Merkelized_payload_hashes_hash)) + (struct + type t = string list + + let name = "messages_list" + + let encoding = Data_encoding.(list @@ dynamic_size (Variable.string' Hex)) + + module Header = struct + type t = Block_hash.t + + let name = "messages_block" + + let encoding = Block_hash.encoding + + let fixed_size = + WithExceptions.Option.get ~loc:__LOC__ + @@ Data_encoding.Binary.fixed_length encoding + end + end) + +type history_mode = Archive | Full + +module History_mode = Indexed_store.Make_singleton (struct + type t = history_mode + + let name = "history_mode" + + let encoding = + Data_encoding.string_enum [("archive", Archive); ("full", Full)] +end) + (** [load ~rollup_node_data_dir] load the needed storage from the rollup node: last_finalized_level, levels_to_hashes, and l2_blocks. default [index_buffer_size] is [10_000] an @@ -111,3 +155,24 @@ let load ?(index_buffer_size = 10_000) ?(cache_size = 300_000) ~path:(Filename.concat store "l2_blocks") in return (last_finalized_level, levels_to_hashes, l2_blocks) + +let load_messages ?(index_buffer_size = 10_000) ?(cache_size = 300_000) + ~rollup_node_data_dir () = + let open Lwt_result_syntax in + let store = Filename.Infix.(rollup_node_data_dir // "storage") in + let path name = Filename.concat store name in + (* We need an archive mode to reconstruct the history. *) + let* () = + let* history_mode_store = + History_mode.load Read_only ~path:(path "history_mode") + in + let* history_mode = History_mode.read history_mode_store in + match history_mode with + | Some Archive -> return_unit + | Some Full -> + failwith + "The history cannot be reconstructed from a full rollup node, it \ + needs an archive one." + | None -> failwith "The history mode of the rollup node cannot be found." + in + Messages.load ~index_buffer_size ~cache_size Read_only ~path:(path "messages") diff --git a/etherlink/bin_node/main.ml b/etherlink/bin_node/main.ml index 009f6bda3a5f..2a634b1e9d86 100644 --- a/etherlink/bin_node/main.ml +++ b/etherlink/bin_node/main.ml @@ -212,6 +212,13 @@ let keep_everything_arg = ~doc:"Do not filter out files outside of the `/evm` directory" () +let reconstruct_arg = + Tezos_clic.arg + ~long:"reconstruct" + ~placeholder:"boot-sector.wasm" + ~doc:{|/!\ DO NOT USE. /!\"|} + Params.string + let verbose_arg = Tezos_clic.switch ~short:'v' @@ -1237,15 +1244,22 @@ let init_from_rollup_node_command = command ~desc: "initialises the EVM node data-dir using the data-dir of a rollup node." - (args3 data_dir_arg devmode_arg omit_delayed_tx_events_arg) + (args4 data_dir_arg devmode_arg omit_delayed_tx_events_arg reconstruct_arg) (prefixes ["init"; "from"; "rollup"; "node"] @@ rollup_node_data_dir_param @@ stop) - (fun (data_dir, devmode, omit_delayed_tx_events) rollup_node_data_dir () -> + (fun ( data_dir, + devmode, + omit_delayed_tx_events, + reconstruct_from_boot_sector ) + rollup_node_data_dir + () -> if devmode then Evm_node_lib_dev.Evm_context.init_from_rollup_node ~omit_delayed_tx_events ~data_dir ~rollup_node_data_dir + ?reconstruct_from_boot_sector + () else Evm_node_lib_prod.Evm_context.init_from_rollup_node ~omit_delayed_tx_events -- GitLab From 7760372b830c79117d47f0707a726fbfee1a8769 Mon Sep 17 00:00:00 2001 From: Valentin Chaboche Date: Fri, 3 May 2024 11:09:57 +0200 Subject: [PATCH 3/3] EVM/Tezt: test reconstruct --- etherlink/tezt/lib/evm_node.ml | 6 ++-- etherlink/tezt/lib/evm_node.mli | 4 +-- etherlink/tezt/tests/evm_sequencer.ml | 40 +++++++++++++++++++++------ 3 files changed, 38 insertions(+), 12 deletions(-) diff --git a/etherlink/tezt/lib/evm_node.ml b/etherlink/tezt/lib/evm_node.ml index 943a46ed6b83..b0b3c7ffc5ff 100644 --- a/etherlink/tezt/lib/evm_node.ml +++ b/etherlink/tezt/lib/evm_node.ml @@ -828,14 +828,16 @@ let init ?patch_config ?name ?runner ?mode ?data_dir ?rpc_addr ?rpc_port let* () = run evm_node in return evm_node -let init_from_rollup_node_data_dir ?(devmode = false) evm_node rollup_node = +let init_from_rollup_node_data_dir ?(devmode = false) ?reconstruct evm_node + rollup_node = let rollup_node_data_dir = Sc_rollup_node.data_dir rollup_node in let process = spawn_command evm_node (["init"; "from"; "rollup"; "node"; rollup_node_data_dir] @ data_dir evm_node - @ Cli_arg.optional_switch "devmode" devmode) + @ Cli_arg.optional_switch "devmode" devmode + @ Cli_arg.optional_arg "reconstruct" Fun.id reconstruct) in Process.check process diff --git a/etherlink/tezt/lib/evm_node.mli b/etherlink/tezt/lib/evm_node.mli index 79ce9467f7c5..4fd719bb7a2c 100644 --- a/etherlink/tezt/lib/evm_node.mli +++ b/etherlink/tezt/lib/evm_node.mli @@ -324,11 +324,11 @@ val sequencer_upgrade_payload : unit -> string Lwt.t -(** [init_from_rollup_node_data_dir ?devmode evm_node rollup_node] +(** [init_from_rollup_node_data_dir ?devmode ?reconstruct evm_node rollup_node] initialises the data dir of the evm node by importing the evm state from a rollup node data dir. [devmode] is false by default. *) val init_from_rollup_node_data_dir : - ?devmode:bool -> t -> Sc_rollup_node.t -> unit Lwt.t + ?devmode:bool -> ?reconstruct:string -> t -> Sc_rollup_node.t -> unit Lwt.t (** [transform_dump ~dump_json ~dump_rlp] transforms a JSON list of instructions stored in [dump_json] to an RLP list, which is diff --git a/etherlink/tezt/tests/evm_sequencer.ml b/etherlink/tezt/tests/evm_sequencer.ml index 338babdd08c3..f0ad4cf1cd8d 100644 --- a/etherlink/tezt/tests/evm_sequencer.ml +++ b/etherlink/tezt/tests/evm_sequencer.ml @@ -81,6 +81,7 @@ type sequencer_setup = { sequencer : Evm_node.t; proxy : Evm_node.t; l1_contracts : l1_contracts; + boot_sector : string; } let setup_l1_contracts ?(dictator = Constant.bootstrap2) client = @@ -153,7 +154,7 @@ let setup_sequencer ?(devmode = true) ?genesis_timestamp ?time_between_blocks ?(kernel = Constant.WASM.evm_kernel) ?da_fee ?minimum_base_fee_per_gas ?preimages_dir ?maximum_allowed_ticks ?maximum_gas_per_transaction ?(threshold_encryption = false) ?(wal_sqlite_journal_mode = true) - ?(drop_duplicate_when_injection = true) protocol = + ?(drop_duplicate_when_injection = true) ?history_mode protocol = let* node, client = setup_l1 ?timestamp:genesis_timestamp protocol in let* l1_contracts = setup_l1_contracts client in let sc_rollup_node = @@ -162,6 +163,7 @@ let setup_sequencer ?(devmode = true) ?genesis_timestamp ?time_between_blocks Batcher node ~base_dir:(Client.base_dir client) + ?history_mode in let preimages_dir = Option.value @@ -312,6 +314,7 @@ let setup_sequencer ?(devmode = true) ?genesis_timestamp ?time_between_blocks l1_contracts; sc_rollup_address; sc_rollup_node; + boot_sector = output; } let send_transaction (transaction : unit -> 'a Lwt.t) sequencer : 'a Lwt.t = @@ -370,7 +373,7 @@ let register_test ?devmode ?genesis_timestamp ?time_between_blocks ?max_number_of_chunks ?bootstrap_accounts ?sequencer ?sequencer_pool_address ?kernel ?da_fee ?minimum_base_fee_per_gas ?preimages_dir ?maximum_allowed_ticks ?maximum_gas_per_transaction - ?(threshold_encryption = false) ?(uses = uses) body = + ?(threshold_encryption = false) ?(uses = uses) ?history_mode body = let uses = if threshold_encryption then fun p -> Constant.octez_dsn_node :: uses p else uses @@ -398,6 +401,7 @@ let register_test ?devmode ?genesis_timestamp ?time_between_blocks ?maximum_allowed_ticks ?maximum_gas_per_transaction ~threshold_encryption + ?history_mode protocol in body sequencer_setup protocol @@ -413,8 +417,8 @@ let register_both ?devmode ?genesis_timestamp ?time_between_blocks ?catchup_cooldown ?delayed_inbox_timeout ?delayed_inbox_min_levels ?max_number_of_chunks ?bootstrap_accounts ?sequencer ?sequencer_pool_address ?kernel ?da_fee ?minimum_base_fee_per_gas ?preimages_dir - ?maximum_allowed_ticks ?maximum_gas_per_transaction ?uses ~title ~tags body - protocols = + ?maximum_allowed_ticks ?maximum_gas_per_transaction ?history_mode ?uses + ~title ~tags body protocols = let register ~threshold_encryption = register_test ?devmode @@ -438,6 +442,7 @@ let register_both ?devmode ?genesis_timestamp ?time_between_blocks ?maximum_gas_per_transaction ?uses ~threshold_encryption + ?history_mode body protocols in @@ -1206,14 +1211,14 @@ let test_delayed_deposit_from_init_rollup_node = ~error_msg:"Expected a bigger balance" ; unit -(** test to initialise a sequencer data dir based on a rollup node - data dir *) +(** test to initialise a sequencer data dir based on a rollup node data dir *) let test_init_from_rollup_node_data_dir = register_both ~time_between_blocks:Nothing - ~tags:["evm"; "rollup_node"; "init"] + ~tags:["evm"; "rollup_node"; "init"; "reconstruct"] ~title:"Init evm node sequencer data dir from a rollup node data dir" - @@ fun {sc_rollup_node; sequencer; proxy; client; _} _protocol -> + ~history_mode:Archive + @@ fun {sc_rollup_node; sequencer; proxy; client; boot_sector; _} _protocol -> (* a sequencer is needed to produce an initial block *) let* () = repeat 5 (fun () -> @@ -1239,6 +1244,7 @@ let test_init_from_rollup_node_data_dir = let* () = Evm_node.init_from_rollup_node_data_dir ~devmode:true + ~reconstruct:boot_sector evm_node' sc_rollup_node in @@ -1253,6 +1259,21 @@ let test_init_from_rollup_node_data_dir = let* () = check_head_consistency ~left:evm_node' ~right:proxy () in + let*@ head = Rpc.block_number evm_node' in + + (* If the sequencer history has been reconstructed during the init, you can + make requests in the past. *) + let* () = + fold (Int32.to_int head) () (fun l () -> + let*@ _ = + Rpc.get_balance + ~address:"0xB7A97043983f24991398E5a82f63F4C58a417185" + ~block:(Number l) + evm_node' + in + unit) + in + unit let test_init_from_rollup_node_with_delayed_inbox = @@ -1962,6 +1983,7 @@ let test_delayed_transfer_timeout = sequencer; proxy; observer = _; + boot_sector = _; } _protocol -> (* Kill the sequencer *) @@ -2021,6 +2043,7 @@ let test_delayed_transfer_timeout_fails_l1_levels = sequencer; proxy; observer = _; + boot_sector = _; } _protocol -> (* Kill the sequencer *) @@ -2274,6 +2297,7 @@ let test_delayed_inbox_flushing = sequencer; proxy; observer = _; + boot_sector = _; } _protocol -> (* Kill the sequencer *) -- GitLab