From 0d2699efdec4c44cda9a2f3bececad006175d14e Mon Sep 17 00:00:00 2001 From: Sylvain Ribstein Date: Thu, 15 Feb 2024 19:30:30 +0100 Subject: [PATCH 1/6] etherlink/kernel: add event for sequencer upgrade --- etherlink/kernel_evm/kernel/src/event.rs | 6 ++++++ etherlink/kernel_evm/kernel/src/inbox.rs | 2 +- etherlink/kernel_evm/kernel/src/upgrade.rs | 5 +++-- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/etherlink/kernel_evm/kernel/src/event.rs b/etherlink/kernel_evm/kernel/src/event.rs index b050efbe7dc3..5bbfee6e3063 100644 --- a/etherlink/kernel_evm/kernel/src/event.rs +++ b/etherlink/kernel_evm/kernel/src/event.rs @@ -7,10 +7,12 @@ use rlp::{Encodable, RlpStream}; use tezos_smart_rollup_host::runtime::Runtime; pub const UPGRADE_TAG: u8 = 0x01; +pub const SEQUENCER_UPGRADE_TAG: u8 = 0x02; #[derive(Debug, PartialEq, Clone)] pub enum Event { Upgrade(upgrade::KernelUpgrade), + SequencerUpgrade(upgrade::SequencerUpgrade), } impl Encodable for Event { @@ -21,6 +23,10 @@ impl Encodable for Event { stream.append(&UPGRADE_TAG); stream.append(upgrade); } + Event::SequencerUpgrade(sequencer_upgrade) => { + stream.append(&SEQUENCER_UPGRADE_TAG); + stream.append(sequencer_upgrade); + } } } } diff --git a/etherlink/kernel_evm/kernel/src/inbox.rs b/etherlink/kernel_evm/kernel/src/inbox.rs index 0ac9cccbbc74..208c8dc2f1c4 100644 --- a/etherlink/kernel_evm/kernel/src/inbox.rs +++ b/etherlink/kernel_evm/kernel/src/inbox.rs @@ -316,7 +316,7 @@ pub fn handle_input( } Input::Upgrade(kernel_upgrade) => store_kernel_upgrade(host, &kernel_upgrade)?, Input::SequencerUpgrade(sequencer_upgrade) => { - store_sequencer_upgrade(host, &sequencer_upgrade)? + store_sequencer_upgrade(host, sequencer_upgrade)? } Input::RemoveSequencer => remove_sequencer(host)?, Input::Info(info) => { diff --git a/etherlink/kernel_evm/kernel/src/upgrade.rs b/etherlink/kernel_evm/kernel/src/upgrade.rs index 81b236770b3f..01e005b881dd 100644 --- a/etherlink/kernel_evm/kernel/src/upgrade.rs +++ b/etherlink/kernel_evm/kernel/src/upgrade.rs @@ -166,7 +166,7 @@ impl Encodable for SequencerUpgrade { pub fn store_sequencer_upgrade( host: &mut Host, - sequencer_upgrade: &SequencerUpgrade, + sequencer_upgrade: SequencerUpgrade, ) -> anyhow::Result<()> { log!( host, @@ -175,8 +175,9 @@ pub fn store_sequencer_upgrade( sequencer_upgrade.sequencer.to_b58check(), sequencer_upgrade.activation_timestamp ); - let path = OwnedPath::from(SEQUENCER_UPGRADE); let bytes = &sequencer_upgrade.rlp_bytes(); + Event::SequencerUpgrade(sequencer_upgrade).store(host)?; + let path = OwnedPath::from(SEQUENCER_UPGRADE); host.store_write_all(&path, bytes) .context("Failed to store sequencer upgrade") } -- GitLab From cdff50f81afc51a1edd47c1b4b9bd51a8a3f6772 Mon Sep 17 00:00:00 2001 From: Sylvain Ribstein Date: Thu, 22 Feb 2024 14:40:30 +0100 Subject: [PATCH 2/6] etherlink/node: sequencer follows sequencer upgrade events --- etherlink/CHANGES_KERNEL.md | 3 + etherlink/CHANGES_NODE.md | 4 + .../bin_node/lib_dev/durable_storage_path.ml | 2 + .../bin_node/lib_dev/durable_storage_path.mli | 2 + .../lib_dev/encodings/ethereum_types.ml | 65 +++++++- .../bin_node/lib_dev/evm_events_follower.ml | 5 + etherlink/bin_node/lib_dev/observer.ml | 15 ++ etherlink/bin_node/lib_dev/rollup_node.ml | 2 + etherlink/bin_node/lib_dev/sequencer.ml | 15 ++ .../bin_node/lib_dev/services_backend_sig.ml | 8 + etherlink/tezt/lib/evm_node.ml | 13 +- etherlink/tezt/lib/evm_node.mli | 10 +- etherlink/tezt/lib/helpers.ml | 21 +++ etherlink/tezt/lib/helpers.mli | 13 ++ etherlink/tezt/tests/evm_sequencer.ml | 149 +++++++++++++++++- 15 files changed, 321 insertions(+), 6 deletions(-) diff --git a/etherlink/CHANGES_KERNEL.md b/etherlink/CHANGES_KERNEL.md index ee9d5bb62fe6..b2346dff29d5 100644 --- a/etherlink/CHANGES_KERNEL.md +++ b/etherlink/CHANGES_KERNEL.md @@ -4,6 +4,9 @@ ### Features +- Add an evm event when a sequencer upgrade is seen by the + kernel. (!12046) + - Da fee is sent to sequencer pool address. (!12113) ### Bug fixes diff --git a/etherlink/CHANGES_NODE.md b/etherlink/CHANGES_NODE.md index bd730730ca33..caecca9b6e98 100644 --- a/etherlink/CHANGES_NODE.md +++ b/etherlink/CHANGES_NODE.md @@ -4,6 +4,10 @@ ### Features +- Detect when a sequencer upgrade evm event is seen in the rollup node + kernel. The sequencer upgrade is applied to the sequencer local + storage. (!12046) + ### Bug fixes ### Breaking changes diff --git a/etherlink/bin_node/lib_dev/durable_storage_path.ml b/etherlink/bin_node/lib_dev/durable_storage_path.ml index fc7a261aefa7..da0bdea2e4c2 100644 --- a/etherlink/bin_node/lib_dev/durable_storage_path.ml +++ b/etherlink/bin_node/lib_dev/durable_storage_path.ml @@ -32,6 +32,8 @@ let kernel_version = EVM.make "/kernel_version" let kernel_upgrade = EVM.make "/kernel_upgrade" +let sequencer_upgrade = EVM.make "/sequencer_upgrade" + module Accounts = struct let accounts = World_state.make "/eth_accounts" diff --git a/etherlink/bin_node/lib_dev/durable_storage_path.mli b/etherlink/bin_node/lib_dev/durable_storage_path.mli index 829e20e7f4f3..c61cc5211675 100644 --- a/etherlink/bin_node/lib_dev/durable_storage_path.mli +++ b/etherlink/bin_node/lib_dev/durable_storage_path.mli @@ -20,6 +20,8 @@ val kernel_version : path val kernel_upgrade : path +val sequencer_upgrade : path + (** Paths related to accounts. *) module Accounts : sig (** Path to the account's balance. *) diff --git a/etherlink/bin_node/lib_dev/encodings/ethereum_types.ml b/etherlink/bin_node/lib_dev/encodings/ethereum_types.ml index 9abad215be0a..a3da347e84ff 100644 --- a/etherlink/bin_node/lib_dev/encodings/ethereum_types.ml +++ b/etherlink/bin_node/lib_dev/encodings/ethereum_types.ml @@ -171,10 +171,14 @@ let empty_hash = Hash (Hex "") let decode_hex bytes = Hex Hex.(of_bytes bytes |> show) +let encode_hex (Hex hex) = Hex.to_bytes_exn (`Hex hex) + let decode_block_hash bytes = Block_hash (decode_hex bytes) let decode_address bytes = Address (decode_hex bytes) +let encode_address (Address address) = encode_hex address + let decode_number bytes = Bytes.to_string bytes |> Z.of_bits |> quantity_of_z let encode_number (Qty v) = Z.to_bits v |> Bytes.of_string @@ -1278,8 +1282,42 @@ module Upgrade = struct (tup2 string Time.Protocol.encoding) end +module Sequencer_upgrade = struct + type t = {sequencer : Signature.public_key; timestamp : Time.Protocol.t} + + let of_rlp = function + | Rlp.List [Value sequencer; Value timestamp] -> + let sequencer = + Signature.Public_key.of_b58check_exn (String.of_bytes sequencer) + in + let timestamp = timestamp_of_bytes timestamp in + Some {sequencer; timestamp} + | _ -> None + + let to_rlp {sequencer; timestamp} = + let sequencer = + Signature.Public_key.to_b58check sequencer |> String.to_bytes + in + let timestamp = timestamp_to_bytes timestamp in + Rlp.List [Value sequencer; Value timestamp] + + let of_bytes bytes = + match bytes |> Rlp.decode with Ok rlp -> of_rlp rlp | _ -> None + + let to_bytes sequencer_upgrade = Rlp.encode @@ to_rlp sequencer_upgrade + + let encoding = + let open Data_encoding in + conv + (fun {sequencer; timestamp} -> (sequencer, timestamp)) + (fun (sequencer, timestamp) -> {sequencer; timestamp}) + (tup2 Signature.Public_key.encoding Time.Protocol.encoding) +end + module Evm_events = struct - type t = Upgrade_event of Upgrade.t + type t = + | Upgrade_event of Upgrade.t + | Sequencer_upgrade_event of Sequencer_upgrade.t let of_bytes bytes = match bytes |> Rlp.decode with @@ -1288,6 +1326,9 @@ module Evm_events = struct | "\x01" -> let upgrade = Upgrade.of_rlp rlp_content in Option.map (fun u -> Upgrade_event u) upgrade + | "\x02" -> + let sequencer_upgrade = Sequencer_upgrade.of_rlp rlp_content in + Option.map (fun u -> Sequencer_upgrade_event u) sequencer_upgrade | _ -> None) | _ -> None @@ -1300,6 +1341,14 @@ module Evm_events = struct hash Time.Protocol.pp_hum timestamp + | Sequencer_upgrade_event {sequencer; timestamp} -> + Format.fprintf + fmt + "Sequencer_upgrade:@ sequencer:@ %a,@ timestamp %a" + Signature.Public_key.pp + sequencer + Time.Protocol.pp_hum + timestamp let encoding = let open Data_encoding in @@ -1311,7 +1360,19 @@ module Evm_events = struct (Tag 0) (obj2 (req "kind" string) (req "event" Upgrade.encoding)) (function - | Upgrade_event upgrade -> Some ("kernel_upgrade", upgrade)) + | Upgrade_event upgrade -> Some ("kernel_upgrade", upgrade) + | _ -> None) (fun (_, upgrade) -> Upgrade_event upgrade)); + (let tag = "sequencer_upgrade" in + case + ~title:tag + (Tag 1) + (obj2 (req "kind" string) (req "event" Sequencer_upgrade.encoding)) + (function + | Sequencer_upgrade_event sequencer_upgrade -> + Some ("sequencer_upgrade", sequencer_upgrade) + | _ -> None) + (fun (_, sequencer_upgrade) -> + Sequencer_upgrade_event sequencer_upgrade)); ] end diff --git a/etherlink/bin_node/lib_dev/evm_events_follower.ml b/etherlink/bin_node/lib_dev/evm_events_follower.ml index 5e043b1c5dd0..251b5130e0c6 100644 --- a/etherlink/bin_node/lib_dev/evm_events_follower.ml +++ b/etherlink/bin_node/lib_dev/evm_events_follower.ml @@ -81,6 +81,11 @@ let on_new_event ({backend; _} : Types.state) event = | Evm_events.Upgrade_event upgrade -> let payload = Upgrade.to_bytes upgrade |> String.of_bytes in Backend.inject_kernel_upgrade ~payload + | Evm_events.Sequencer_upgrade_event sequencer_upgrade -> + let payload = + Sequencer_upgrade.to_bytes sequencer_upgrade |> String.of_bytes + in + Backend.inject_sequencer_upgrade ~payload let fetch_event ({rollup_node_endpoint; _} : Types.state) rollup_block_lvl event_index = diff --git a/etherlink/bin_node/lib_dev/observer.ml b/etherlink/bin_node/lib_dev/observer.ml index 14822fcd6c91..3078e071a99d 100644 --- a/etherlink/bin_node/lib_dev/observer.ml +++ b/etherlink/bin_node/lib_dev/observer.ml @@ -117,6 +117,21 @@ end) : Services_backend_sig.Backend = struct Evm_context.commit ~number:(Qty Z.(pred next)) Ctxt.ctxt evm_state in return_unit + + let inject_sequencer_upgrade ~payload = + let open Lwt_result_syntax in + let*! evm_state = Evm_context.evm_state Ctxt.ctxt in + let*! evm_state = + Evm_state.modify + ~key:Durable_storage_path.sequencer_upgrade + ~value:payload + evm_state + in + let (Qty next) = Ctxt.ctxt.next_blueprint_number in + let* () = + Evm_context.commit ~number:(Qty Z.(pred next)) Ctxt.ctxt evm_state + in + return_unit end let on_new_blueprint (ctxt : Evm_context.t) (blueprint : Blueprint_types.t) = diff --git a/etherlink/bin_node/lib_dev/rollup_node.ml b/etherlink/bin_node/lib_dev/rollup_node.ml index 672f93ce4c42..391555cc17eb 100644 --- a/etherlink/bin_node/lib_dev/rollup_node.ml +++ b/etherlink/bin_node/lib_dev/rollup_node.ml @@ -94,6 +94,8 @@ end) : Services_backend_sig.Backend = struct end let inject_kernel_upgrade ~payload:_ = Lwt_result_syntax.return_unit + + let inject_sequencer_upgrade ~payload:_ = Lwt_result_syntax.return_unit end module Make (Base : sig diff --git a/etherlink/bin_node/lib_dev/sequencer.ml b/etherlink/bin_node/lib_dev/sequencer.ml index 89f843c69d10..46636caf91ec 100644 --- a/etherlink/bin_node/lib_dev/sequencer.ml +++ b/etherlink/bin_node/lib_dev/sequencer.ml @@ -92,6 +92,21 @@ end) : Services_backend_sig.Backend = struct Evm_context.commit ~number:(Qty Z.(pred next)) Ctxt.ctxt evm_state in return_unit + + let inject_sequencer_upgrade ~payload = + let open Lwt_result_syntax in + let*! evm_state = Evm_context.evm_state Ctxt.ctxt in + let*! evm_state = + Evm_state.modify + ~key:Durable_storage_path.sequencer_upgrade + ~value:payload + evm_state + in + let (Qty next) = Ctxt.ctxt.next_blueprint_number in + let* () = + Evm_context.commit ~number:(Qty Z.(pred next)) Ctxt.ctxt evm_state + in + return_unit end module Make (Ctxt : sig diff --git a/etherlink/bin_node/lib_dev/services_backend_sig.ml b/etherlink/bin_node/lib_dev/services_backend_sig.ml index 856a4be470ae..f813a44d3a9d 100644 --- a/etherlink/bin_node/lib_dev/services_backend_sig.ml +++ b/etherlink/bin_node/lib_dev/services_backend_sig.ml @@ -111,6 +111,10 @@ module type S = sig (** [inject_kernel_upgrade ~payload] injects the kernel upgrade payload [payload] in the local state. *) val inject_kernel_upgrade : payload:string -> unit tzresult Lwt.t + + (** [inject_sequencer_upgrade ~payload] injects the sequencer + upgrade payload [payload] in the local state. *) + val inject_sequencer_upgrade : payload:string -> unit tzresult Lwt.t end module type Backend = sig @@ -123,6 +127,8 @@ module type Backend = sig module SimulatorBackend : Simulator.SimulationBackend val inject_kernel_upgrade : payload:string -> unit tzresult Lwt.t + + val inject_sequencer_upgrade : payload:string -> unit tzresult Lwt.t end module Make (Backend : Backend) : S = struct @@ -131,4 +137,6 @@ module Make (Backend : Backend) : S = struct include Simulator.Make (Backend.SimulatorBackend) let inject_kernel_upgrade = Backend.inject_kernel_upgrade + + let inject_sequencer_upgrade = Backend.inject_sequencer_upgrade end diff --git a/etherlink/tezt/lib/evm_node.ml b/etherlink/tezt/lib/evm_node.ml index 1316faddf581..44ea3a10622a 100644 --- a/etherlink/tezt/lib/evm_node.ml +++ b/etherlink/tezt/lib/evm_node.ml @@ -227,6 +227,15 @@ let wait_for_blueprint_applied ~timeout evm_node level = | Not_running | Running {session_state = {ready = false; _}; _} -> failwith "EVM node is not ready" +let wait_for_evm_event evm_node ~event_kind = + wait_for + evm_node + "evm_events_new_event.v0" + JSON.( + fun json -> + let found_event_kind = json |-> "kind" |> as_string in + if event_kind = found_event_kind then Some () else None) + let create ?name ?runner ?(mode = Proxy {devmode = false}) ?data_dir ?rpc_addr ?rpc_port endpoint = let arguments, rpc_addr, rpc_port = @@ -493,7 +502,8 @@ let transform_dump ~dump_json ~dump_rlp = let process = Process.spawn (Uses.path Constant.octez_evm_node) @@ args in Process.check process -let sequencer_upgrade_payload ?client ~public_key ~activation_timestamp () = +let sequencer_upgrade_payload ?(devmode = true) ?client ~public_key + ~activation_timestamp () = let args = [ "make"; @@ -515,6 +525,7 @@ let sequencer_upgrade_payload ?client ~public_key ~activation_timestamp () = "wallet-dir" Fun.id (Option.map Client.base_dir client) + @ Cli_arg.optional_switch "devmode" devmode in let* payload = Process.check_and_read_stdout process in return (String.trim payload) diff --git a/etherlink/tezt/lib/evm_node.mli b/etherlink/tezt/lib/evm_node.mli index b7716fab2c01..e77002096bce 100644 --- a/etherlink/tezt/lib/evm_node.mli +++ b/etherlink/tezt/lib/evm_node.mli @@ -130,6 +130,11 @@ val terminate : ?timeout:float -> t -> unit Lwt.t (** The same exact behavior as {!Sc_rollup_node.wait_for} but for the EVM node. *) val wait_for : ?where:string -> t -> string -> (JSON.t -> 'a option) -> 'a Lwt.t +(** [wait_for_evm_event evm_node ~event_kind] wait for the event + [evm_events_new_event.v0] using {!wait_for} where the event kind + is equal to [event_kind] (e.g. "sequencer_upgrade"). *) +val wait_for_evm_event : t -> event_kind:string -> unit Lwt.t + (** [endpoint ?private_ evm_node] returns the endpoint to communicate with the [evm_node]. If [private_] is true, the endpoint for the private RPC server is returned. *) @@ -175,12 +180,13 @@ val txpool_content : t -> (txpool_slot list * txpool_slot list) Lwt.t val upgrade_payload : root_hash:string -> activation_timestamp:string -> string Lwt.t -(** [sequencer_upgrade_payload ?client ~public_key +(** [sequencer_upgrade_payload ?devmode ?client ~public_key ~activation_timestamp ()] gives the sequencer upgrade payload to put in a upgrade message, it will upgrade the sequencer to [public_key] at the first l1 block after [activation_timestamp] - (in RFC3399 format). *) + (in RFC3399 format). [devmode] is true by default. *) val sequencer_upgrade_payload : + ?devmode:bool -> ?client:Client.t -> public_key:string -> activation_timestamp:string -> diff --git a/etherlink/tezt/lib/helpers.ml b/etherlink/tezt/lib/helpers.ml index 5e6816b53e0d..59349acdd8c0 100644 --- a/etherlink/tezt/lib/helpers.ml +++ b/etherlink/tezt/lib/helpers.ml @@ -136,3 +136,24 @@ let check_head_consistency ~left ~right ?error_msg () = let*@ right_head = Rpc.get_block_by_number ~block:"latest" right in Check.((left_head.hash = right_head.hash) string) ~error_msg ; unit + +let sequencer_upgrade ~sc_rollup_address ~sequencer_admin + ~sequencer_admin_contract ~client ~upgrade_to ~activation_timestamp = + let* payload = + Evm_node.sequencer_upgrade_payload + ~client + ~public_key:upgrade_to + ~activation_timestamp + () + in + (* Sends the upgrade to L1. *) + let* () = + Client.transfer + ~amount:Tez.zero + ~giver:sequencer_admin + ~receiver:sequencer_admin_contract + ~arg:(sf {|Pair "%s" 0x%s|} sc_rollup_address payload) + ~burn_cap:Tez.one + client + in + Client.bake_for_and_wait ~keys:[] client diff --git a/etherlink/tezt/lib/helpers.mli b/etherlink/tezt/lib/helpers.mli index f9eb9b5c1edb..80f976d8a672 100644 --- a/etherlink/tezt/lib/helpers.mli +++ b/etherlink/tezt/lib/helpers.mli @@ -101,3 +101,16 @@ val upgrade : are not with [error_msg] *) val check_head_consistency : left:Evm_node.t -> right:Evm_node.t -> ?error_msg:string -> unit -> unit Lwt.t + +(** [sequencer_upgrade ~sc_rollup_address ~sequencer_admin + ~sequencer_admin_contract ~client ~upgrade_to + ~activation_timestamp] prepares the sequencer upgrade payload and + sends it to the layer 1. *) +val sequencer_upgrade : + sc_rollup_address:string -> + sequencer_admin:string -> + sequencer_admin_contract:string -> + client:Client.t -> + upgrade_to:string -> + activation_timestamp:string -> + unit Lwt.t diff --git a/etherlink/tezt/tests/evm_sequencer.ml b/etherlink/tezt/tests/evm_sequencer.ml index f4e36316bc27..3e78909eeeb7 100644 --- a/etherlink/tezt/tests/evm_sequencer.ml +++ b/etherlink/tezt/tests/evm_sequencer.ml @@ -174,6 +174,7 @@ let setup_sequencer ?(devmode = true) ?config ?genesis_timestamp let* {output; _} = prepare_installer_kernel ~preimages_dir ?config kernel in let* sc_rollup_address = originate_sc_rollup + ~keys:[] ~kind:"wasm_2_0_0" ~boot_sector:("file:" ^ output) ~parameters_ty:Helpers.evm_type @@ -1717,6 +1718,151 @@ let test_migration_from_ghostnet = (* Final consistency check. *) check_head_consistency ~left:sequencer ~right:proxy () +(** This tests the situation where the kernel has an upgrade and the + sequencer upgrade by following the event of the kernel. *) +let test_sequencer_upgrade = + Protocol.register_test + ~__FILE__ + ~tags:["evm"; "sequencer"; "sequencer_upgrade"; "auto"; "sync"] + ~title: + "Rollup-node sequencer upgrade is applied to the sequencer local state." + ~uses + @@ fun protocol -> + let* { + sc_rollup_node; + l1_contracts; + sc_rollup_address; + client; + sequencer; + proxy; + node; + _; + } = + setup_sequencer + ~sequencer:Constant.bootstrap1 + ~time_between_blocks:Nothing + protocol + in + (* produce an initial block *) + let* _ = Rpc.produce_block sequencer in + let* () = + (* make sure rollup node saw it *) + repeat 4 (fun () -> + let* _ = next_rollup_node_level ~node ~client ~sc_rollup_node in + unit) + in + let* () = + check_head_consistency + ~left:proxy + ~right:sequencer + ~error_msg:"The head should be the same before the upgrade" + () + in + let*@ previous_proxy_head = Rpc.get_block_by_number ~block:"latest" proxy in + (* Sends the upgrade to L1. *) + Log.info "Sending the sequencer upgrade to the L1 contract" ; + let new_sequencer_key = Constant.bootstrap2.alias in + let* () = + Evm_node.wait_for_evm_event sequencer ~event_kind:"sequencer_upgrade" + and* () = + let* () = + sequencer_upgrade + ~sc_rollup_address + ~sequencer_admin:Constant.bootstrap2.alias + ~sequencer_admin_contract:l1_contracts.sequencer_admin + ~client + ~upgrade_to:new_sequencer_key + ~activation_timestamp:"0" + in + (* 2 block so the sequencer sees the event from the rollup + node. *) + repeat 2 (fun () -> + let* _ = next_rollup_node_level ~node ~client ~sc_rollup_node in + unit) + in + let* () = + check_head_consistency + ~left:proxy + ~right:sequencer + ~error_msg:"The head should be the same after the upgrade" + () + in + let nb_block = 10l in + let* () = + repeat (Int32.to_int nb_block) (fun () -> + let* _ = Rpc.produce_block sequencer in + unit) + in + let* () = + repeat 5 (fun () -> + let* _ = next_rollup_node_level ~node ~client ~sc_rollup_node in + unit) + in + let*@ proxy_head = Rpc.get_block_by_number ~block:"latest" proxy in + Check.((previous_proxy_head.hash = proxy_head.hash) string) + ~error_msg: + "The proxy should not have progessed because no block have been produced \ + by the current sequencer." ; + (* Check that even the evm-node sequencer itself refuses the blocks as they do + not respect the sequencer's signature. *) + let* () = + check_head_consistency + ~left:proxy + ~right:sequencer + ~error_msg: + "The head should be the same after the sequencer tried to produce \ + blocks, they are are disregarded." + () + in + Log.info + "Stopping current sequencer and starting a new one with new sequencer key" ; + let* () = Evm_node.terminate sequencer in + let new_sequencer = + let mode = + match Evm_node.mode sequencer with + | Sequencer config -> + Evm_node.Sequencer {config with sequencer = new_sequencer_key} + | _ -> Test.fail "impossible case, it's a sequencer" + in + Evm_node.create + ~name:"new-sequencer" + ~mode + (Sc_rollup_node.endpoint sc_rollup_node) + in + + let* () = + Evm_node.init_from_rollup_node_data_dir + ~devmode:true + new_sequencer + sc_rollup_node + in + let* () = Evm_node.run new_sequencer in + let* () = + repeat (Int32.to_int nb_block) (fun () -> + let* _ = Rpc.produce_block new_sequencer in + unit) + in + let* () = + repeat 5 (fun () -> + let* _ = next_rollup_node_level ~node ~client ~sc_rollup_node in + unit) + in + let previous_proxy_head = proxy_head in + let* () = + check_head_consistency + ~left:proxy + ~right:new_sequencer + ~error_msg: + "The head should be the same after blocks produced by the new sequencer" + () + in + let*@ proxy_head = Rpc.get_block_by_number ~block:"latest" proxy in + Check.( + (Int32.add previous_proxy_head.number nb_block = proxy_head.number) int32) + ~error_msg: + "The block number should have incremented (previous: %L, current: %R)" ; + unit + let () = test_remove_sequencer [Alpha] ; test_persistent_state [Alpha] ; @@ -1740,4 +1886,5 @@ let () = test_delayed_transfer_timeout_fails_l1_levels [Alpha] ; test_delayed_inbox_flushing [Alpha] ; test_no_automatic_block_production [Alpha] ; - test_migration_from_ghostnet [Alpha] + test_migration_from_ghostnet [Alpha] ; + test_sequencer_upgrade [Alpha] -- GitLab From 784c865dad1830c6e19927fe6c9c282b678fa9e7 Mon Sep 17 00:00:00 2001 From: Sylvain Ribstein Date: Thu, 22 Feb 2024 14:01:37 +0100 Subject: [PATCH 3/6] etherlink/test: uses newly added helper --- etherlink/tezt/tests/evm_rollup.ml | 39 +++++++++--------------------- 1 file changed, 12 insertions(+), 27 deletions(-) diff --git a/etherlink/tezt/tests/evm_rollup.ml b/etherlink/tezt/tests/evm_rollup.ml index 128c219a9889..1c7ae85cde1a 100644 --- a/etherlink/tezt/tests/evm_rollup.ml +++ b/etherlink/tezt/tests/evm_rollup.ml @@ -4480,23 +4480,15 @@ let test_migrate_proxy_to_sequencer_future = | Some contract -> contract | None -> Test.fail "missing sequencer admin contract" in - let* payload = - Evm_node.sequencer_upgrade_payload + let* () = + sequencer_upgrade + ~sc_rollup_address + ~sequencer_admin:sequencer_admin.alias + ~sequencer_admin_contract ~client - ~public_key:sequencer_key.alias + ~upgrade_to:sequencer_key.alias ~activation_timestamp - () in - let* () = - Client.transfer - ~amount:Tez.zero - ~giver:sequencer_admin.public_key_hash - ~receiver:sequencer_admin_contract - ~arg:(sf "Pair %S 0x%s" sc_rollup_address payload) - ~burn_cap:Tez.one - client - in - let* _ = next_evm_level ~evm_node:proxy_node ~sc_rollup_node ~node ~client in let sequencer_node = let mode = Evm_node.Sequencer @@ -4626,21 +4618,14 @@ let test_migrate_proxy_to_sequencer_past = | Some contract -> contract | None -> Test.fail "missing sequencer admin contract" in - let* payload = - Evm_node.sequencer_upgrade_payload + let* () = + sequencer_upgrade + ~sc_rollup_address + ~sequencer_admin:sequencer_admin.alias + ~sequencer_admin_contract ~client - ~public_key:sequencer_key.alias + ~upgrade_to:sequencer_key.alias ~activation_timestamp:"0" - () - in - let* () = - Client.transfer - ~amount:Tez.zero - ~giver:sequencer_admin.public_key_hash - ~receiver:sequencer_admin_contract - ~arg:(sf "Pair %S 0x%s" sc_rollup_address payload) - ~burn_cap:Tez.one - client in let* _ = next_evm_level ~evm_node:proxy_node ~sc_rollup_node ~node ~client in let sequencer_node = -- GitLab From b6a4de32d41468cab014d6c960dfcc57f2f1416b Mon Sep 17 00:00:00 2001 From: Sylvain Ribstein Date: Thu, 22 Feb 2024 15:09:17 +0100 Subject: [PATCH 4/6] etherlink/node: refactor cmd using newly added rlp fn --- etherlink/bin_node/main.ml | 29 ++++++++++------------------- 1 file changed, 10 insertions(+), 19 deletions(-) diff --git a/etherlink/bin_node/main.ml b/etherlink/bin_node/main.ml index 5fa7e57fb63b..84ef5ceafab3 100644 --- a/etherlink/bin_node/main.ml +++ b/etherlink/bin_node/main.ml @@ -1077,31 +1077,22 @@ let make_sequencer_upgrade_command = let* _pk_uri, sequencer_pk_opt = Client_keys.Public_key.parse_source_string wallet_ctxt sequencer_str in - let activation_timestamp = - if devmode then - Evm_node_lib_dev_encoding.Ethereum_types.timestamp_to_bytes - activation_timestamp - else - Evm_node_lib_prod_encoding.Ethereum_types.timestamp_to_bytes - activation_timestamp - in - let*? sequencer_pk = + let*? sequencer = Option.to_result ~none:[error_of_fmt "invalid format or unknown public key."] sequencer_pk_opt in - let sequencer_pk_bytes = - Signature.Public_key.to_b58check sequencer_pk |> String.to_bytes - in - let payload = + let* payload = if devmode then - Evm_node_lib_dev_encoding.Rlp.( - encode - @@ List [Value sequencer_pk_bytes; Value activation_timestamp]) + let open Evm_node_lib_dev_encoding.Ethereum_types in + let sequencer_upgrade = + Sequencer_upgrade.{sequencer; timestamp = activation_timestamp} + in + return @@ Sequencer_upgrade.to_bytes sequencer_upgrade else - Evm_node_lib_prod_encoding.Rlp.( - encode - @@ List [Value sequencer_pk_bytes; Value activation_timestamp]) + tzfail + (error_of_fmt + "devmode must be set for producing the sequencer upgrade") in Printf.printf "%s%!" Hex.(of_bytes payload |> show) ; return_unit) -- GitLab From b72269adf2b9747438e12a4477c6dd80eb3bbdce Mon Sep 17 00:00:00 2001 From: Sylvain Ribstein Date: Thu, 22 Feb 2024 15:34:44 +0100 Subject: [PATCH 5/6] etherlink/tezt: fix test where event was applied twice --- etherlink/tezt/tests/evm_rollup.ml | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/etherlink/tezt/tests/evm_rollup.ml b/etherlink/tezt/tests/evm_rollup.ml index 1c7ae85cde1a..b2e6525be6dd 100644 --- a/etherlink/tezt/tests/evm_rollup.ml +++ b/etherlink/tezt/tests/evm_rollup.ml @@ -4627,7 +4627,27 @@ let test_migrate_proxy_to_sequencer_past = ~upgrade_to:sequencer_key.alias ~activation_timestamp:"0" in - let* _ = next_evm_level ~evm_node:proxy_node ~sc_rollup_node ~node ~client in + let* () = + (* We need to bake 3 blocks, because otherwise the sequencer upgrade event + is re-received by the EVM node. This is because `init from rollup node` + reads the HEAD context of the rollup node, but the EVM node interacts + with the rollup node two blocks in the past. As a consequence, without + baking these blocks, the EVM node will virtually handle the sequencer + upgrade event twice. + + However, the EVM node does not deal with sequencer event gracefully + right now. It works for preventing the old sequencer to produce + blueprints, but not for the new sequencer to start producing blueprints. + + This is because of the blueprint deletion mechanism of the kernel. + When the sequencer upgrade is applied at the end of stage-1, the + pending blueprints are deleted. This means the bluperint currently + applied in `apply_blueprint` is deleted, meaning nothing is executed + in the stage-2. *) + repeat 3 (fun () -> + let* _ = next_rollup_node_level ~sc_rollup_node ~node ~client in + unit) + in let sequencer_node = let mode = Evm_node.Sequencer -- GitLab From 1761ddfa06cbabeb74a540bbd6c30b3cb8ab6449 Mon Sep 17 00:00:00 2001 From: Sylvain Ribstein Date: Thu, 22 Feb 2024 15:50:02 +0100 Subject: [PATCH 6/6] etherlink/node: fix typo --- etherlink/bin_node/lib_dev/evm_context.ml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/etherlink/bin_node/lib_dev/evm_context.ml b/etherlink/bin_node/lib_dev/evm_context.ml index 5e9cdd40a72f..066e60ea8ee6 100644 --- a/etherlink/bin_node/lib_dev/evm_context.ml +++ b/etherlink/bin_node/lib_dev/evm_context.ml @@ -75,13 +75,12 @@ let () = ~id:"evm_node_dev_cannot_apply_blueprint" ~title:"Cannot apply a blueprint" ~description: - "The EVM node could not apply apply a blueprint on top of its local EVM \ - state." + "The EVM node could not apply a blueprint on top of its local EVM state." ~pp:(fun ppf local_state_level -> Format.fprintf ppf - "The EVM node could not apply apply a blueprint on top of its local \ - EVM state at level %a." + "The EVM node could not apply a blueprint on top of its local EVM \ + state at level %a." Z.pp_print local_state_level) Data_encoding.(obj1 (req "current_state_level" n)) -- GitLab