From d084590c9446090685561aed35206c5d3455336b Mon Sep 17 00:00:00 2001 From: Valentin Chaboche Date: Fri, 31 May 2024 10:55:23 +0200 Subject: [PATCH 1/3] EVM/Kernel: fa bridge enable flag in configuration --- etherlink/CHANGES_KERNEL.md | 2 ++ .../kernel_evm/kernel/src/blueprint_storage.rs | 1 + .../kernel_evm/kernel/src/configuration.rs | 17 +++++++++++------ etherlink/kernel_evm/kernel/src/stage_one.rs | 2 ++ etherlink/kernel_evm/kernel/src/storage.rs | 12 ++++++++++++ 5 files changed, 28 insertions(+), 6 deletions(-) diff --git a/etherlink/CHANGES_KERNEL.md b/etherlink/CHANGES_KERNEL.md index 29f3cf619aa8..850d8feb0e6f 100644 --- a/etherlink/CHANGES_KERNEL.md +++ b/etherlink/CHANGES_KERNEL.md @@ -31,6 +31,8 @@ - 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) - Stop emitting an `Info` log when running an Ethereum transaction. (!13630) +- A FA bridge feature flag is added to the configuration. If the path has a value + in `/evm/feature_flags/enable_fa_bridge`, FA bridge related operations will be accepted. (!13535) ## Version b9f6c9138719220db83086f0548e49c5c4c8421f diff --git a/etherlink/kernel_evm/kernel/src/blueprint_storage.rs b/etherlink/kernel_evm/kernel/src/blueprint_storage.rs index bd8256700fd6..1cc42a03f2ec 100644 --- a/etherlink/kernel_evm/kernel/src/blueprint_storage.rs +++ b/etherlink/kernel_evm/kernel/src/blueprint_storage.rs @@ -470,6 +470,7 @@ mod tests { sequencer, }, limits: Limits::default(), + enable_fa_bridge: false, }; let dummy_tx_hash = Hash([0u8; TRANSACTION_HASH_SIZE]); diff --git a/etherlink/kernel_evm/kernel/src/configuration.rs b/etherlink/kernel_evm/kernel/src/configuration.rs index b0ee4e989209..2341d4c7c38f 100644 --- a/etherlink/kernel_evm/kernel/src/configuration.rs +++ b/etherlink/kernel_evm/kernel/src/configuration.rs @@ -1,10 +1,10 @@ use crate::{ delayed_inbox::DelayedInbox, storage::{ - read_admin, read_delayed_transaction_bridge, read_kernel_governance, - read_kernel_security_governance, read_maximum_allowed_ticks, - read_maximum_gas_per_transaction, read_sequencer_governance, read_ticketer, - sequencer, + is_enable_fa_bridge, read_admin, read_delayed_transaction_bridge, + read_kernel_governance, read_kernel_security_governance, + read_maximum_allowed_ticks, read_maximum_gas_per_transaction, + read_sequencer_governance, read_ticketer, sequencer, }, tick_model::constants::{MAXIMUM_GAS_LIMIT, MAX_ALLOWED_TICKS}, }; @@ -57,6 +57,7 @@ pub struct Configuration { pub tezos_contracts: TezosContracts, pub mode: ConfigurationMode, pub limits: Limits, + pub enable_fa_bridge: bool, } impl Default for Configuration { @@ -65,6 +66,7 @@ impl Default for Configuration { tezos_contracts: TezosContracts::default(), mode: ConfigurationMode::Proxy, limits: Limits::default(), + enable_fa_bridge: false, } } } @@ -73,8 +75,8 @@ impl std::fmt::Display for Configuration { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!( f, - "Tezos Contracts: {}, Mode: {}", - &self.tezos_contracts, &self.mode + "Tezos Contracts: {}, Mode: {}, Enable FA Bridge: {}", + &self.tezos_contracts, &self.mode, &self.enable_fa_bridge ) } } @@ -170,6 +172,7 @@ pub fn fetch_configuration(host: &mut Host) -> Configuration { let tezos_contracts = fetch_tezos_contracts(host); let limits = fetch_limits(host); let sequencer = sequencer(host).unwrap_or_default(); + let enable_fa_bridge = is_enable_fa_bridge(host).unwrap_or_default(); match sequencer { Some(sequencer) => { let delayed_bridge = read_delayed_transaction_bridge(host) @@ -190,6 +193,7 @@ pub fn fetch_configuration(host: &mut Host) -> Configuration { sequencer, }, limits, + enable_fa_bridge, }, Err(err) => { log!(host, Fatal, "The kernel failed to created the delayed inbox, reverting configuration to proxy ({:?})", err); @@ -204,6 +208,7 @@ pub fn fetch_configuration(host: &mut Host) -> Configuration { tezos_contracts, mode: ConfigurationMode::Proxy, limits, + enable_fa_bridge, }, } } diff --git a/etherlink/kernel_evm/kernel/src/stage_one.rs b/etherlink/kernel_evm/kernel/src/stage_one.rs index 699ebe7b6472..f1044ab6031f 100644 --- a/etherlink/kernel_evm/kernel/src/stage_one.rs +++ b/etherlink/kernel_evm/kernel/src/stage_one.rs @@ -175,6 +175,7 @@ mod tests { sequencer, }, limits: Limits::default(), + enable_fa_bridge: false, } } @@ -187,6 +188,7 @@ mod tests { }, mode: ConfigurationMode::Proxy, limits: Limits::default(), + enable_fa_bridge: false, } } diff --git a/etherlink/kernel_evm/kernel/src/storage.rs b/etherlink/kernel_evm/kernel/src/storage.rs index 9a66b41a4b9a..894d35d0ffda 100644 --- a/etherlink/kernel_evm/kernel/src/storage.rs +++ b/etherlink/kernel_evm/kernel/src/storage.rs @@ -142,6 +142,10 @@ pub const SEQUENCER: RefPath = RefPath::assert_from(b"/evm/sequencer"); // Path where the input for the tracer is stored by the sequencer. const TRACER_INPUT: RefPath = RefPath::assert_from(b"/evm/trace/input"); +// If this path contains a value, the fa bridge is enabled in the kernel. +const ENABLE_FA_BRIDGE: RefPath = + RefPath::assert_from(b"/evm/feature_flags/enable_fa_bridge"); + pub fn store_read_slice( host: &Host, path: &T, @@ -1086,6 +1090,14 @@ pub fn read_tracer_input( } } +pub fn is_enable_fa_bridge(host: &impl Runtime) -> anyhow::Result { + if let Some(ValueType::Value) = host.store_has(&ENABLE_FA_BRIDGE)? { + Ok(true) + } else { + Ok(false) + } +} + #[cfg(test)] mod internal_for_tests { use super::*; -- GitLab From 4abf113a63a0bf8a10947e529b06711e625b7861 Mon Sep 17 00:00:00 2001 From: Valentin Chaboche Date: Fri, 31 May 2024 11:13:16 +0200 Subject: [PATCH 2/3] EVM/Node: enable fa bridge in make configuration --- etherlink/bin_node/lib_dev/kernel_config.ml | 7 ++++++- etherlink/bin_node/lib_dev/kernel_config.mli | 1 + etherlink/bin_node/main.ml | 14 ++++++++++---- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/etherlink/bin_node/lib_dev/kernel_config.ml b/etherlink/bin_node/lib_dev/kernel_config.ml index bcaa3649b5db..32f95192a4f4 100644 --- a/etherlink/bin_node/lib_dev/kernel_config.ml +++ b/etherlink/bin_node/lib_dev/kernel_config.ml @@ -23,7 +23,7 @@ let make ~mainnet_compat ~boostrap_balance ?bootstrap_accounts ?kernel_root_hash ?kernel_governance ?kernel_security_governance ?minimum_base_fee_per_gas ?da_fee_per_byte ?delayed_inbox_timeout ?delayed_inbox_min_levels ?sequencer_pool_address ?maximum_allowed_ticks ?maximum_gas_per_transaction - ?remove_whitelist ~output () = + ?remove_whitelist ~enable_fa_bridge ~output () = let bootstrap_accounts = match bootstrap_accounts with | None -> [] @@ -37,6 +37,10 @@ let make ~mainnet_compat ~boostrap_balance ?bootstrap_accounts ?kernel_root_hash bootstrap_accounts |> List.flatten in + let enable_fa_bridge = + if enable_fa_bridge then Some ("feature_flags/enable_fa_bridge", "") + else None + in let le_int64_bytes i = let b = Bytes.make 8 '\000' in Bytes.set_int64_le b 0 (Int64.of_string i) ; @@ -74,5 +78,6 @@ let make ~mainnet_compat ~boostrap_balance ?bootstrap_accounts ?kernel_root_hash @ make_instr ~convert:le_int64_bytes maximum_gas_per_transaction @ bootstrap_accounts @ make_instr remove_whitelist + @ make_instr enable_fa_bridge in Installer_config.to_file instrs ~output diff --git a/etherlink/bin_node/lib_dev/kernel_config.mli b/etherlink/bin_node/lib_dev/kernel_config.mli index 4320a6e4a0ac..d23bdddbadbf 100644 --- a/etherlink/bin_node/lib_dev/kernel_config.mli +++ b/etherlink/bin_node/lib_dev/kernel_config.mli @@ -29,6 +29,7 @@ val make : ?maximum_allowed_ticks:string * string -> ?maximum_gas_per_transaction:string * string -> ?remove_whitelist:string * string -> + enable_fa_bridge:bool -> output:string -> unit -> unit tzresult Lwt.t diff --git a/etherlink/bin_node/main.ml b/etherlink/bin_node/main.ml index 3eabb0ac3115..19e48948cc35 100644 --- a/etherlink/bin_node/main.ml +++ b/etherlink/bin_node/main.ml @@ -1457,7 +1457,7 @@ let make_kernel_config_command = let open Lwt_result_syntax in command ~desc:"Transforms the JSON list of instructions to a RLP list" - (args20 + (args21 mainnet_compat_arg (config_key_arg ~name:"kernel_root_hash" ~placeholder:"root hash") (config_key_arg ~name:"chain_id" ~placeholder:"chain id") @@ -1484,9 +1484,13 @@ let make_kernel_config_command = ~default:"9999000000000000000000" ~placeholder:"9999000000000000000000" @@ Tezos_clic.parameter (fun _ s -> return @@ Z.of_string s)) - bootstrap_account_arg) + bootstrap_account_arg + (switch + ~doc:"Enable the FA bridge in the kernel" + ~long:"enable-fa-bridge" + ())) (prefixes ["make"; "kernel"; "installer"; "config"] - @@ Tezos_clic.param + @@ param ~name:"kernel config file" ~desc:"file path where the config will be written to" Params.string @@ -1510,7 +1514,8 @@ let make_kernel_config_command = maximum_gas_per_transaction, remove_whitelist, boostrap_balance, - bootstrap_accounts ) + bootstrap_accounts, + enable_fa_bridge ) output () -> Evm_node_lib_dev.Kernel_config.make @@ -1534,6 +1539,7 @@ let make_kernel_config_command = ?remove_whitelist ~boostrap_balance ?bootstrap_accounts + ~enable_fa_bridge ~output ()) -- GitLab From 6515fb0fa60987a407ad7854218bb840cae9d060 Mon Sep 17 00:00:00 2001 From: Valentin Chaboche Date: Tue, 11 Jun 2024 11:41:01 +0200 Subject: [PATCH 3/3] EVM/Tezt: test existence of feature flag in storage --- etherlink/tezt/lib/durable_storage_path.ml | 2 ++ etherlink/tezt/lib/durable_storage_path.mli | 3 ++ etherlink/tezt/lib/evm_node.ml | 4 ++- etherlink/tezt/lib/evm_node.mli | 1 + etherlink/tezt/lib/rpc.ml | 11 +++++++ etherlink/tezt/lib/rpc.mli | 3 ++ etherlink/tezt/tests/evm_sequencer.ml | 35 +++++++++++++++++---- 7 files changed, 52 insertions(+), 7 deletions(-) diff --git a/etherlink/tezt/lib/durable_storage_path.ml b/etherlink/tezt/lib/durable_storage_path.ml index 14b010b80733..5f53889ca252 100644 --- a/etherlink/tezt/lib/durable_storage_path.ml +++ b/etherlink/tezt/lib/durable_storage_path.ml @@ -85,6 +85,8 @@ let delayed_inbox_min_levels = evm "/delayed_inbox_min_levels" let reveal_config = "/__tmp/reveal_config" +let enable_fa_bridge = evm "/feature_flags/enable_fa_bridge" + module Ghostnet = struct let eth_accounts = evm "/eth_accounts" diff --git a/etherlink/tezt/lib/durable_storage_path.mli b/etherlink/tezt/lib/durable_storage_path.mli index 30e53116ae4a..5c23a2e13f08 100644 --- a/etherlink/tezt/lib/durable_storage_path.mli +++ b/etherlink/tezt/lib/durable_storage_path.mli @@ -101,6 +101,9 @@ val delayed_inbox_min_levels : path (** [reveal_config] is the path to the storage configuration. *) val reveal_config : path +(** [enable_fa_bridge] is the path to the feature flag to activate the FA bridge. *) +val enable_fa_bridge : path + module Ghostnet : sig val eth_accounts : path diff --git a/etherlink/tezt/lib/evm_node.ml b/etherlink/tezt/lib/evm_node.ml index 1f38d35203bb..382d2e5b5c3d 100644 --- a/etherlink/tezt/lib/evm_node.ml +++ b/etherlink/tezt/lib/evm_node.ml @@ -979,7 +979,8 @@ let make_kernel_installer_config ?(mainnet_compat = false) ?sequencer_governance ?kernel_governance ?kernel_security_governance ?minimum_base_fee_per_gas ?(da_fee_per_byte = Wei.zero) ?delayed_inbox_timeout ?delayed_inbox_min_levels ?sequencer_pool_address - ?maximum_allowed_ticks ?maximum_gas_per_transaction ~output () = + ?maximum_allowed_ticks ?maximum_gas_per_transaction + ?(enable_fa_bridge = false) ~output () = let cmd = ["make"; "kernel"; "installer"; "config"; output] @ Cli_arg.optional_switch "mainnet-compat" mainnet_compat @@ -1021,6 +1022,7 @@ let make_kernel_installer_config ?(mainnet_compat = false) "maximum-gas-per-transaction" Int64.to_string maximum_gas_per_transaction + @ Cli_arg.optional_switch "enable-fa-bridge" enable_fa_bridge @ Cli_arg.optional_arg "bootstrap-balance" Wei.to_string bootstrap_balance @ match bootstrap_accounts with diff --git a/etherlink/tezt/lib/evm_node.mli b/etherlink/tezt/lib/evm_node.mli index a622632eb01d..e860f48e92b2 100644 --- a/etherlink/tezt/lib/evm_node.mli +++ b/etherlink/tezt/lib/evm_node.mli @@ -374,6 +374,7 @@ val make_kernel_installer_config : ?sequencer_pool_address:string -> ?maximum_allowed_ticks:int64 -> ?maximum_gas_per_transaction:int64 -> + ?enable_fa_bridge:bool -> output:string -> unit -> (Process.t, unit) Runnable.t diff --git a/etherlink/tezt/lib/rpc.ml b/etherlink/tezt/lib/rpc.ml index 79ac0092e01c..3d5f43632688 100644 --- a/etherlink/tezt/lib/rpc.ml +++ b/etherlink/tezt/lib/rpc.ml @@ -76,6 +76,8 @@ module Request = struct in {method_ = "produceBlock"; parameters} + let stateValue path = {method_ = "stateValue"; parameters = `String path} + let eth_sendRawTransaction ~raw_tx = {method_ = "eth_sendRawTransaction"; parameters = `A [`String raw_tx]} @@ -260,6 +262,15 @@ let produce_block ?timestamp evm_node = (fun json -> Evm_node.extract_result json |> JSON.as_int) json +let state_value evm_node path = + let* json = + Evm_node.call_evm_rpc ~private_:true evm_node (Request.stateValue path) + in + return + @@ decode_or_error + (fun json -> Evm_node.extract_result json |> JSON.as_string_opt) + json + let send_raw_transaction ~raw_tx evm_node = let* response = Evm_node.call_evm_rpc evm_node (Request.eth_sendRawTransaction ~raw_tx) diff --git a/etherlink/tezt/lib/rpc.mli b/etherlink/tezt/lib/rpc.mli index 869d83888405..834398f6c544 100644 --- a/etherlink/tezt/lib/rpc.mli +++ b/etherlink/tezt/lib/rpc.mli @@ -94,6 +94,9 @@ end provided the block will have timestamp [timestamp] (in RFC3339) format. *) val produce_block : ?timestamp:string -> Evm_node.t -> (int, error) result Lwt.t +(** [state_value evm_node path] calls the private RPC [stateValue]. *) +val state_value : Evm_node.t -> string -> (string option, error) result Lwt.t + (** [send_raw_transaction ~raw_tx evm_node] calls [eth_sendRawTransaction] with [raw_tx] as argument. *) val send_raw_transaction : diff --git a/etherlink/tezt/tests/evm_sequencer.ml b/etherlink/tezt/tests/evm_sequencer.ml index 2deb1a15a980..6106ff960367 100644 --- a/etherlink/tezt/tests/evm_sequencer.ml +++ b/etherlink/tezt/tests/evm_sequencer.ml @@ -153,8 +153,9 @@ let setup_sequencer ~mainnet_compat ?genesis_timestamp ?time_between_blocks ?(sequencer = Constant.bootstrap1) ?sequencer_pool_address ?(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) ?history_mode protocol = + ?enable_fa_bridge ?(threshold_encryption = false) + ?(wal_sqlite_journal_mode = true) ?(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 = @@ -188,6 +189,7 @@ let setup_sequencer ~mainnet_compat ?genesis_timestamp ?time_between_blocks ?maximum_gas_per_transaction ~bootstrap_accounts ~output:output_config + ?enable_fa_bridge () in let* {output; _} = @@ -371,7 +373,7 @@ let register_test ~mainnet_compat ?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 + ?maximum_allowed_ticks ?maximum_gas_per_transaction ?enable_fa_bridge ?(threshold_encryption = false) ?(uses = uses) ?(additional_uses = []) ?history_mode body = let additional_uses = @@ -401,6 +403,7 @@ let register_test ~mainnet_compat ?genesis_timestamp ?time_between_blocks ?preimages_dir ?maximum_allowed_ticks ?maximum_gas_per_transaction + ?enable_fa_bridge ~threshold_encryption ?history_mode protocol @@ -418,8 +421,8 @@ let register_both ?genesis_timestamp ?time_between_blocks ?max_blueprints_lag ?delayed_inbox_timeout ?delayed_inbox_min_levels ?max_number_of_chunks ?bootstrap_accounts ?sequencer ?sequencer_pool_address ?(kernels = Kernel.all) ?da_fee ?minimum_base_fee_per_gas ?preimages_dir - ?maximum_allowed_ticks ?maximum_gas_per_transaction ?history_mode - ?additional_uses ~title ~tags body protocols = + ?maximum_allowed_ticks ?maximum_gas_per_transaction ?enable_fa_bridge + ?history_mode ?additional_uses ~title ~tags body protocols = let register ~kernel ~threshold_encryption = let _, kernel_use = Kernel.to_uses_and_tags kernel in register_test @@ -442,6 +445,7 @@ let register_both ?genesis_timestamp ?time_between_blocks ?max_blueprints_lag ?preimages_dir ?maximum_allowed_ticks ?maximum_gas_per_transaction + ?enable_fa_bridge ?additional_uses ~threshold_encryption ?history_mode @@ -3770,6 +3774,24 @@ let test_miner = "Viewed coinbase should be the sequencer pool address, expected %R got %L" ; unit +let test_fa_bridge_feature_flag = + register_both + ~tags:["fa_bridge"; "feature_flag"] + ~title:"FA bridge feature is set in storage" + ~enable_fa_bridge:true + @@ fun {sequencer; _} _protocol -> + (* We simply check that the flag is set in the storage. *) + let*@ flag = + Rpc.state_value sequencer Durable_storage_path.enable_fa_bridge + in + Check.is_true + (Option.is_some flag) + ~error_msg: + (sf + "Expected to have a value at %s" + Durable_storage_path.enable_fa_bridge) ; + unit + let protocols = Protocol.all let () = @@ -3822,4 +3844,5 @@ let () = test_trace_transaction protocols ; test_trace_transaction_on_invalid_transaction protocols ; test_trace_transaction_call protocols ; - test_miner protocols + test_miner protocols ; + test_fa_bridge_feature_flag protocols -- GitLab