From 92619c1b2834199e9a4720e58ac4da8e42f4b0ea Mon Sep 17 00:00:00 2001 From: Valentin Chaboche Date: Wed, 3 Jan 2024 18:31:22 +0100 Subject: [PATCH 1/9] EVM/Kernel: store sequencer's public key instead of flag --- etherlink/kernel_evm/kernel/src/lib.rs | 44 +++++++++++--------- etherlink/kernel_evm/kernel/src/stage_one.rs | 3 ++ etherlink/kernel_evm/kernel/src/storage.rs | 15 +++++-- 3 files changed, 39 insertions(+), 23 deletions(-) diff --git a/etherlink/kernel_evm/kernel/src/lib.rs b/etherlink/kernel_evm/kernel/src/lib.rs index e068501d3e33..fe3339af4323 100644 --- a/etherlink/kernel_evm/kernel/src/lib.rs +++ b/etherlink/kernel_evm/kernel/src/lib.rs @@ -21,11 +21,11 @@ use evm_execution::Config; use migration::MigrationStatus; use primitive_types::U256; use storage::{ - is_sequencer, read_admin, read_base_fee_per_gas, read_chain_id, - read_delayed_transaction_bridge, read_kernel_version, - read_last_info_per_level_timestamp, read_last_info_per_level_timestamp_stats, - read_ticketer, store_base_fee_per_gas, store_chain_id, store_kernel_version, - store_storage_version, STORAGE_VERSION, STORAGE_VERSION_PATH, + read_admin, read_base_fee_per_gas, read_chain_id, read_delayed_transaction_bridge, + read_kernel_version, read_last_info_per_level_timestamp, + read_last_info_per_level_timestamp_stats, read_ticketer, sequencer, + store_base_fee_per_gas, store_chain_id, store_kernel_version, store_storage_version, + STORAGE_VERSION, STORAGE_VERSION_PATH, }; use tezos_crypto_rs::hash::ContractKt1Hash; use tezos_evm_logging::{log, Level::*}; @@ -211,22 +211,26 @@ fn retrieve_base_fee_per_gas(host: &mut Host) -> Result(host: &mut Host) -> anyhow::Result { - let is_sequencer = is_sequencer(host)?; - if is_sequencer { - let delayed_bridge = read_delayed_transaction_bridge(host) - // The sequencer must declare a delayed transaction bridge. This - // default value is only to facilitate the testing. - .unwrap_or_else(|| { - ContractKt1Hash::from_base58_check("KT18amZmM5W7qDWVt2pH6uj7sCEd3kbzLrHT") + let sequencer = sequencer(host)?; + match sequencer { + Some(sequencer) => { + let delayed_bridge = read_delayed_transaction_bridge(host) + // The sequencer must declare a delayed transaction bridge. This + // default value is only to facilitate the testing. + .unwrap_or_else(|| { + ContractKt1Hash::from_base58_check( + "KT18amZmM5W7qDWVt2pH6uj7sCEd3kbzLrHT", + ) .unwrap() - }); - let delayed_inbox = Box::new(DelayedInbox::new(host)?); - Ok(Configuration::Sequencer { - delayed_bridge, - delayed_inbox, - }) - } else { - Ok(Configuration::Proxy) + }); + let delayed_inbox = Box::new(DelayedInbox::new(host)?); + Ok(Configuration::Sequencer { + delayed_bridge, + delayed_inbox, + sequencer, + }) + } + None => Ok(Configuration::Proxy), } } diff --git a/etherlink/kernel_evm/kernel/src/stage_one.rs b/etherlink/kernel_evm/kernel/src/stage_one.rs index bc5206e2f480..8cfb4951ac0c 100644 --- a/etherlink/kernel_evm/kernel/src/stage_one.rs +++ b/etherlink/kernel_evm/kernel/src/stage_one.rs @@ -12,6 +12,7 @@ use crate::storage::store_kernel_upgrade; use anyhow::Ok; use tezos_crypto_rs::hash::ContractKt1Hash; use tezos_evm_logging::{log, Level::*}; +use tezos_smart_rollup_encoding::public_key::PublicKey; use tezos_smart_rollup_host::metadata::RAW_ROLLUP_ADDRESS_SIZE; use tezos_smart_rollup_host::runtime::Runtime; @@ -21,6 +22,7 @@ pub enum Configuration { Sequencer { delayed_bridge: ContractKt1Hash, delayed_inbox: Box, + sequencer: PublicKey, }, } @@ -105,6 +107,7 @@ pub fn fetch( Configuration::Sequencer { delayed_bridge, delayed_inbox, + sequencer: _, } => fetch_sequencer_blueprints( host, smart_rollup_address, diff --git a/etherlink/kernel_evm/kernel/src/storage.rs b/etherlink/kernel_evm/kernel/src/storage.rs index b333904ea3c5..97ee31cfc7fb 100644 --- a/etherlink/kernel_evm/kernel/src/storage.rs +++ b/etherlink/kernel_evm/kernel/src/storage.rs @@ -12,6 +12,7 @@ use evm_execution::account_storage::EthereumAccount; use tezos_crypto_rs::hash::{ContractKt1Hash, HashTrait}; use tezos_evm_logging::{log, Level::*}; use tezos_smart_rollup_core::MAX_FILE_CHUNK_SIZE; +use tezos_smart_rollup_encoding::public_key::PublicKey; use tezos_smart_rollup_encoding::timestamp::Timestamp; use tezos_smart_rollup_host::path::*; use tezos_smart_rollup_host::runtime::{Runtime, ValueType}; @@ -90,7 +91,8 @@ pub const WORD_SIZE: usize = 32usize; const KERNEL_UPGRADE: RefPath = RefPath::assert_from(b"/kernel_upgrade"); -// Path to the flag denoting whether the kernel is in sequencer mode or not. +// Path to the tz1 administrating the sequencer. If there is nothing +// at this path, the kernel is in proxy mode. const SEQUENCER: RefPath = RefPath::assert_from(b"/sequencer"); pub fn store_read_slice( @@ -832,8 +834,15 @@ pub fn delete_kernel_upgrade(host: &mut Host) -> anyhow::Result<( .context("Failed to delete kernel upgrade") } -pub fn is_sequencer(host: &Host) -> Result { - Ok(host.store_has(&SEQUENCER)?.is_some()) +pub fn sequencer(host: &Host) -> anyhow::Result> { + if host.store_has(&SEQUENCER)?.is_some() { + let bytes = host.store_read_all(&SEQUENCER)?; + let Ok(tz1_b58) = String::from_utf8(bytes) else { return Ok(None) }; + let Ok(tz1) = PublicKey::from_b58check(&tz1_b58) else { return Ok(None)}; + Ok(Some(tz1)) + } else { + Ok(None) + } } #[cfg(test)] -- GitLab From 176db0de096342c8d2129f71516dd09ae9d6d02b Mon Sep 17 00:00:00 2001 From: Valentin Chaboche Date: Wed, 3 Jan 2024 18:32:18 +0100 Subject: [PATCH 2/9] EVM/Kernel: split unsigned/signed blueprints --- .../kernel/src/blueprint_storage.rs | 8 +-- .../kernel/src/sequencer_blueprint.rs | 58 ++++++++++++++++--- etherlink/kernel_evm/kernel/src/stage_one.rs | 4 +- 3 files changed, 55 insertions(+), 15 deletions(-) diff --git a/etherlink/kernel_evm/kernel/src/blueprint_storage.rs b/etherlink/kernel_evm/kernel/src/blueprint_storage.rs index f4533ce10a34..58f0aee04a71 100644 --- a/etherlink/kernel_evm/kernel/src/blueprint_storage.rs +++ b/etherlink/kernel_evm/kernel/src/blueprint_storage.rs @@ -159,11 +159,11 @@ pub fn store_sequencer_blueprint( host: &mut Host, blueprint: SequencerBlueprint, ) -> Result<(), Error> { - let blueprint_path = blueprint_path(blueprint.number)?; - store_blueprint_nb_chunks(host, &blueprint_path, blueprint.nb_chunks)?; + let blueprint_path = blueprint_path(blueprint.blueprint.number)?; + store_blueprint_nb_chunks(host, &blueprint_path, blueprint.blueprint.nb_chunks)?; let blueprint_chunk_path = - blueprint_chunk_path(&blueprint_path, blueprint.chunk_index)?; - let store_blueprint = StoreBlueprint::SequencerChunk(blueprint.chunk); + blueprint_chunk_path(&blueprint_path, blueprint.blueprint.chunk_index)?; + let store_blueprint = StoreBlueprint::SequencerChunk(blueprint.blueprint.chunk); store_rlp(&store_blueprint, host, &blueprint_chunk_path) } diff --git a/etherlink/kernel_evm/kernel/src/sequencer_blueprint.rs b/etherlink/kernel_evm/kernel/src/sequencer_blueprint.rs index 0b0a8355d660..12ac3fbd6f36 100644 --- a/etherlink/kernel_evm/kernel/src/sequencer_blueprint.rs +++ b/etherlink/kernel_evm/kernel/src/sequencer_blueprint.rs @@ -4,19 +4,32 @@ use primitive_types::U256; use rlp::{Decodable, DecoderError, Encodable}; +use tezos_crypto_rs::hash::Signature; use tezos_ethereum::rlp_helpers::{ self, append_u16_le, append_u256_le, decode_field_u16_le, decode_field_u256_le, }; #[derive(PartialEq, Debug, Clone)] -pub struct SequencerBlueprint { +pub struct UnsignedSequencerBlueprint { pub chunk: Vec, pub number: U256, pub nb_chunks: u16, pub chunk_index: u16, } -impl Encodable for SequencerBlueprint { +#[derive(PartialEq, Debug, Clone)] +pub struct SequencerBlueprint { + pub blueprint: UnsignedSequencerBlueprint, + pub signature: Signature, +} + +impl From<&SequencerBlueprint> for UnsignedSequencerBlueprint { + fn from(val: &SequencerBlueprint) -> UnsignedSequencerBlueprint { + val.blueprint.clone() + } +} + +impl Encodable for UnsignedSequencerBlueprint { fn rlp_append(&self, stream: &mut rlp::RlpStream) { stream.begin_list(4); stream.append(&self.chunk); @@ -26,12 +39,23 @@ impl Encodable for SequencerBlueprint { } } +impl Encodable for SequencerBlueprint { + fn rlp_append(&self, stream: &mut rlp::RlpStream) { + stream.begin_list(5); + stream.append(&self.blueprint.chunk); + append_u256_le(stream, &self.blueprint.number); + append_u16_le(stream, &self.blueprint.nb_chunks); + append_u16_le(stream, &self.blueprint.chunk_index); + stream.append(&self.signature.0); + } +} + impl Decodable for SequencerBlueprint { fn decode(decoder: &rlp::Rlp) -> Result { if !decoder.is_list() { return Err(DecoderError::RlpExpectedToBeList); } - if decoder.item_count()? != 4 { + if decoder.item_count()? != 5 { return Err(DecoderError::RlpIncorrectListLen); } let mut it = decoder.iter(); @@ -40,23 +64,32 @@ impl Decodable for SequencerBlueprint { let nb_chunks = decode_field_u16_le(&rlp_helpers::next(&mut it)?, "nb_chunks")?; let chunk_index = decode_field_u16_le(&rlp_helpers::next(&mut it)?, "chunk_index")?; - Ok(Self { + let bytes: Vec = + rlp_helpers::decode_field(&rlp_helpers::next(&mut it)?, "signature")?; + let signature = Signature::try_from(bytes.as_slice()) + .map_err(|_| DecoderError::Custom("Invalid signature encoding"))?; + let blueprint = UnsignedSequencerBlueprint { chunk, number, nb_chunks, chunk_index, + }; + Ok(Self { + blueprint, + signature, }) } } #[cfg(test)] mod tests { - use super::SequencerBlueprint; + use super::{SequencerBlueprint, UnsignedSequencerBlueprint}; use crate::blueprint::Blueprint; use crate::inbox::Transaction; use crate::inbox::TransactionContent::Ethereum; use primitive_types::{H160, U256}; use rlp::Encodable; + use tezos_crypto_rs::hash::Signature; use tezos_ethereum::rlp_helpers::FromRlpBytes; use tezos_ethereum::{ transaction::TRANSACTION_HASH_SIZE, tx_common::EthereumTransactionCommon, @@ -106,11 +139,18 @@ mod tests { transactions, }; let chunk = rlp::Encodable::rlp_bytes(&blueprint); + let signature = Signature::from_base58_check( + "sigdGBG68q2vskMuac4AzyNb1xCJTfuU8MiMbQtmZLUCYydYrtTd5Lessn1EFLTDJzjXoYxRasZxXbx6tHnirbEJtikcMHt3" + ).expect("signature decoding should work"); + SequencerBlueprint { - chunk: chunk.into(), - number: U256::from(42), - nb_chunks: 1u16, - chunk_index: 0u16, + blueprint: UnsignedSequencerBlueprint { + chunk: chunk.into(), + number: U256::from(42), + nb_chunks: 1u16, + chunk_index: 0u16, + }, + signature, } } diff --git a/etherlink/kernel_evm/kernel/src/stage_one.rs b/etherlink/kernel_evm/kernel/src/stage_one.rs index 8cfb4951ac0c..0e2cfd2774c1 100644 --- a/etherlink/kernel_evm/kernel/src/stage_one.rs +++ b/etherlink/kernel_evm/kernel/src/stage_one.rs @@ -83,8 +83,8 @@ fn fetch_sequencer_blueprints( host, Debug, "Storing chunk {} of sequencer blueprint number {}", - seq_blueprint.chunk_index, - seq_blueprint.number + seq_blueprint.blueprint.chunk_index, + seq_blueprint.blueprint.number ); store_sequencer_blueprint(host, seq_blueprint)? } -- GitLab From d57fff3fe5b0558898194b25252b2132624041ec Mon Sep 17 00:00:00 2001 From: Valentin Chaboche Date: Wed, 3 Jan 2024 18:43:17 +0100 Subject: [PATCH 3/9] EVM/Kernel: verify blueprints' signature at parsing --- etherlink/kernel_evm/kernel/src/inbox.rs | 57 ++++++++++++-------- etherlink/kernel_evm/kernel/src/parsing.rs | 47 ++++++++++++---- etherlink/kernel_evm/kernel/src/stage_one.rs | 7 ++- 3 files changed, 77 insertions(+), 34 deletions(-) diff --git a/etherlink/kernel_evm/kernel/src/inbox.rs b/etherlink/kernel_evm/kernel/src/inbox.rs index c58017650304..039b692b8a3e 100644 --- a/etherlink/kernel_evm/kernel/src/inbox.rs +++ b/etherlink/kernel_evm/kernel/src/inbox.rs @@ -24,6 +24,7 @@ use tezos_ethereum::transaction::{TransactionHash, TRANSACTION_HASH_SIZE}; use tezos_ethereum::tx_common::EthereumTransactionCommon; use tezos_evm_logging::{log, Level::*}; use tezos_smart_rollup_core::PREIMAGE_HASH_SIZE; +use tezos_smart_rollup_encoding::public_key::PublicKey; use tezos_smart_rollup_host::runtime::Runtime; #[derive(Debug, PartialEq, Clone)] @@ -182,6 +183,7 @@ pub fn read_input( admin: &Option, inbox_is_empty: &mut bool, delayed_bridge: &Option, + sequencer: &Option, ) -> Result { let input = host.read_input()?; @@ -195,6 +197,7 @@ pub fn read_input( ticketer, admin, delayed_bridge, + sequencer, )) } None => Ok(InputResult::NoInput), @@ -286,6 +289,7 @@ pub fn read_inbox( ticketer: Option, admin: Option, delayed_bridge: Option, + sequencer: Option, ) -> Result, anyhow::Error> { let mut res = InboxContent { kernel_upgrade: None, @@ -305,6 +309,7 @@ pub fn read_inbox( &admin, &mut inbox_is_empty, &delayed_bridge, + &sequencer, )? { InputResult::NoInput => { if inbox_is_empty { @@ -489,9 +494,10 @@ mod tests { host.add_external(Bytes::from(input_to_bytes(SMART_ROLLUP_ADDRESS, input))); - let inbox_content = read_inbox(&mut host, SMART_ROLLUP_ADDRESS, None, None, None) - .unwrap() - .unwrap(); + let inbox_content = + read_inbox(&mut host, SMART_ROLLUP_ADDRESS, None, None, None, None) + .unwrap() + .unwrap(); let expected_transactions = vec![Transaction { tx_hash, content: Ethereum(tx), @@ -513,9 +519,10 @@ mod tests { host.add_external(Bytes::from(input_to_bytes(SMART_ROLLUP_ADDRESS, input))) } - let inbox_content = read_inbox(&mut host, SMART_ROLLUP_ADDRESS, None, None, None) - .unwrap() - .unwrap(); + let inbox_content = + read_inbox(&mut host, SMART_ROLLUP_ADDRESS, None, None, None, None) + .unwrap() + .unwrap(); let expected_transactions = vec![Transaction { tx_hash, content: Ethereum(tx), @@ -553,9 +560,10 @@ mod tests { let transfer_metadata = TransferMetadata::new(sender.clone(), source); host.add_transfer(payload, &transfer_metadata); - let inbox_content = read_inbox(&mut host, [0; 20], None, Some(sender), None) - .unwrap() - .unwrap(); + let inbox_content = + read_inbox(&mut host, [0; 20], None, Some(sender), None, None) + .unwrap() + .unwrap(); let expected_upgrade = Some(KernelUpgrade { preimage_hash }); assert_eq!(inbox_content.kernel_upgrade, expected_upgrade); } @@ -589,7 +597,7 @@ mod tests { ))); let _inbox_content = - read_inbox(&mut host, SMART_ROLLUP_ADDRESS, None, None, None).unwrap(); + read_inbox(&mut host, SMART_ROLLUP_ADDRESS, None, None, None, None).unwrap(); let num_chunks = chunked_transaction_num_chunks(&mut host, &tx_hash) .expect("The number of chunks should exist"); @@ -632,7 +640,7 @@ mod tests { host.add_external(Bytes::from(input_to_bytes(SMART_ROLLUP_ADDRESS, chunk))); let _inbox_content = - read_inbox(&mut host, SMART_ROLLUP_ADDRESS, None, None, None).unwrap(); + read_inbox(&mut host, SMART_ROLLUP_ADDRESS, None, None, None, None).unwrap(); // The out of bounds chunk should not exist. let chunked_transaction_path = chunked_transaction_path(&tx_hash).unwrap(); @@ -664,7 +672,7 @@ mod tests { host.add_external(Bytes::from(input_to_bytes(SMART_ROLLUP_ADDRESS, chunk))); let _inbox_content = - read_inbox(&mut host, SMART_ROLLUP_ADDRESS, None, None, None).unwrap(); + read_inbox(&mut host, SMART_ROLLUP_ADDRESS, None, None, None, None).unwrap(); // The unknown chunk should not exist. let chunked_transaction_path = chunked_transaction_path(&tx_hash).unwrap(); @@ -711,9 +719,10 @@ mod tests { host.add_external(Bytes::from(input_to_bytes(SMART_ROLLUP_ADDRESS, chunk0))); - let inbox_content = read_inbox(&mut host, SMART_ROLLUP_ADDRESS, None, None, None) - .unwrap() - .unwrap(); + let inbox_content = + read_inbox(&mut host, SMART_ROLLUP_ADDRESS, None, None, None, None) + .unwrap() + .unwrap(); assert_eq!( inbox_content, InboxContent { @@ -727,9 +736,10 @@ mod tests { for input in inputs { host.add_external(Bytes::from(input_to_bytes(SMART_ROLLUP_ADDRESS, input))) } - let inbox_content = read_inbox(&mut host, SMART_ROLLUP_ADDRESS, None, None, None) - .unwrap() - .unwrap(); + let inbox_content = + read_inbox(&mut host, SMART_ROLLUP_ADDRESS, None, None, None, None) + .unwrap() + .unwrap(); let expected_transactions = vec![Transaction { tx_hash, @@ -782,9 +792,10 @@ mod tests { host.add_external(framed); - let inbox_content = read_inbox(&mut host, SMART_ROLLUP_ADDRESS, None, None, None) - .unwrap() - .unwrap(); + let inbox_content = + read_inbox(&mut host, SMART_ROLLUP_ADDRESS, None, None, None, None) + .unwrap() + .unwrap(); let expected_transactions = vec![Transaction { tx_hash, content: Ethereum(tx), @@ -801,12 +812,12 @@ mod tests { // in the inbox, we mock it by adding a single input. host.add_external(Bytes::from(vec![])); let inbox_content = - read_inbox(&mut host, SMART_ROLLUP_ADDRESS, None, None, None).unwrap(); + read_inbox(&mut host, SMART_ROLLUP_ADDRESS, None, None, None, None).unwrap(); assert!(inbox_content.is_some()); // Reading again the inbox returns no inbox content at all. let inbox_content = - read_inbox(&mut host, SMART_ROLLUP_ADDRESS, None, None, None).unwrap(); + read_inbox(&mut host, SMART_ROLLUP_ADDRESS, None, None, None, None).unwrap(); assert!(inbox_content.is_none()); } } diff --git a/etherlink/kernel_evm/kernel/src/parsing.rs b/etherlink/kernel_evm/kernel/src/parsing.rs index 88beeee96ade..65c7d6a865c5 100644 --- a/etherlink/kernel_evm/kernel/src/parsing.rs +++ b/etherlink/kernel_evm/kernel/src/parsing.rs @@ -7,11 +7,12 @@ use crate::{ inbox::{Deposit, KernelUpgrade, Transaction, TransactionContent}, - sequencer_blueprint::SequencerBlueprint, + sequencer_blueprint::{SequencerBlueprint, UnsignedSequencerBlueprint}, }; use primitive_types::{H160, U256}; +use rlp::Encodable; use sha3::{Digest, Keccak256}; -use tezos_crypto_rs::hash::ContractKt1Hash; +use tezos_crypto_rs::{hash::ContractKt1Hash, PublicKeySignatureVerifier}; use tezos_ethereum::{ rlp_helpers::FromRlpBytes, transaction::{TransactionHash, TRANSACTION_HASH_SIZE}, @@ -26,6 +27,7 @@ use tezos_smart_rollup_encoding::{ ExternalMessageFrame, InboxMessage, InfoPerLevel, InternalInboxMessage, Transfer, }, michelson::{ticket::FA2_1Ticket, MichelsonBytes, MichelsonOr, MichelsonPair}, + public_key::PublicKey, }; use tezos_smart_rollup_host::input::Message; use tezos_smart_rollup_host::runtime::Runtime; @@ -201,10 +203,26 @@ impl InputResult { } } - fn parse_sequencer_blueprint_input(bytes: &[u8]) -> Self { + fn parse_sequencer_blueprint_input(sequencer: &PublicKey, bytes: &[u8]) -> Self { + // Parse the sequencer blueprint let seq_blueprint: SequencerBlueprint = parsable!(FromRlpBytes::from_rlp_bytes(bytes).ok()); - InputResult::Input(Input::SequencerBlueprint(seq_blueprint)) + + // Creates and encodes the unsigned blueprint: + let unsigned_seq_blueprint: UnsignedSequencerBlueprint = (&seq_blueprint).into(); + let bytes = unsigned_seq_blueprint.rlp_bytes().to_vec(); + // The sequencer signs the hash of the blueprint. + let msg = tezos_crypto_rs::blake2b::digest_256(&bytes).unwrap(); + + let correctly_signed = sequencer + .verify_signature(&seq_blueprint.signature, &msg) + .unwrap_or(false); + + if correctly_signed { + InputResult::Input(Input::SequencerBlueprint(seq_blueprint)) + } else { + InputResult::Unparsable + } } /// Parses transactions that come from the delayed inbox. @@ -230,9 +248,13 @@ impl InputResult { /// Parses an external message /// - /// External message structure : - /// EXTERNAL_TAG 1B / FRAMING_PROTOCOL_TARGETTED 21B / MESSAGE_TAG 1B / DATA - fn parse_external(input: &[u8], smart_rollup_address: &[u8]) -> Self { + // External message structure : + // EXTERNAL_TAG 1B / FRAMING_PROTOCOL_TARGETTED 21B / MESSAGE_TAG 1B / DATA + fn parse_external( + input: &[u8], + smart_rollup_address: &[u8], + sequencer: &Option, + ) -> Self { // Compatibility with framing protocol for external messages let remaining = match ExternalMessageFrame::parse(input) { Ok(ExternalMessageFrame::Targetted { address, contents }) @@ -248,7 +270,12 @@ impl InputResult { SIMPLE_TRANSACTION_TAG => Self::parse_simple_transaction(remaining), NEW_CHUNKED_TRANSACTION_TAG => Self::parse_new_chunked_transaction(remaining), TRANSACTION_CHUNK_TAG => Self::parse_transaction_chunk(remaining), - SEQUENCER_BLUEPRINT_TAG => Self::parse_sequencer_blueprint_input(remaining), + SEQUENCER_BLUEPRINT_TAG if sequencer.is_some() => { + Self::parse_sequencer_blueprint_input( + sequencer.as_ref().unwrap(), + remaining, + ) + } _ => InputResult::Unparsable, } } @@ -370,6 +397,7 @@ impl InputResult { ticketer: &Option, admin: &Option, delayed_bridge: &Option, + sequencer: &Option, ) -> Self { let bytes = Message::as_ref(&input); let (input_tag, remaining) = parsable!(bytes.split_first()); @@ -380,7 +408,7 @@ impl InputResult { match InboxMessage::::parse(bytes) { Ok((_remaing, message)) => match message { InboxMessage::External(message) => { - Self::parse_external(message, &smart_rollup_address) + Self::parse_external(message, &smart_rollup_address, sequencer) } InboxMessage::Internal(message) => Self::parse_internal( host, @@ -416,6 +444,7 @@ mod tests { ZERO_SMART_ROLLUP_ADDRESS, &None, &None, + &None, &None ), InputResult::Unparsable diff --git a/etherlink/kernel_evm/kernel/src/stage_one.rs b/etherlink/kernel_evm/kernel/src/stage_one.rs index 0e2cfd2774c1..4cd574b9a5e0 100644 --- a/etherlink/kernel_evm/kernel/src/stage_one.rs +++ b/etherlink/kernel_evm/kernel/src/stage_one.rs @@ -36,7 +36,7 @@ pub fn fetch_inbox_blueprints( kernel_upgrade, transactions, sequencer_blueprints: _, - }) = read_inbox(host, smart_rollup_address, ticketer, admin, None)? + }) = read_inbox(host, smart_rollup_address, ticketer, admin, None, None)? { let timestamp = current_timestamp(host); let blueprint = Blueprint { @@ -60,6 +60,7 @@ fn fetch_sequencer_blueprints( admin: Option, delayed_bridge: ContractKt1Hash, delayed_inbox: &mut DelayedInbox, + sequencer: PublicKey, ) -> Result<(), anyhow::Error> { if let Some(InboxContent { kernel_upgrade, @@ -71,6 +72,7 @@ fn fetch_sequencer_blueprints( ticketer, admin, Some(delayed_bridge), + Some(sequencer), )? { // Store the transactions in the delayed inbox. for transaction in transactions { @@ -107,7 +109,7 @@ pub fn fetch( Configuration::Sequencer { delayed_bridge, delayed_inbox, - sequencer: _, + sequencer, } => fetch_sequencer_blueprints( host, smart_rollup_address, @@ -115,6 +117,7 @@ pub fn fetch( admin, delayed_bridge.clone(), delayed_inbox, + sequencer.clone(), ), Configuration::Proxy => { fetch_inbox_blueprints(host, smart_rollup_address, ticketer, admin) -- GitLab From 39166f636d8bdd4da12e27fa46451da89a5b4283 Mon Sep 17 00:00:00 2001 From: Valentin Chaboche Date: Thu, 4 Jan 2024 13:58:38 +0100 Subject: [PATCH 4/9] EVM/Sequencer: put unencrypted secret key as parameter --- .../bin_evm_node/config/configuration.ml | 35 +++++++++++++----- .../bin_evm_node/config/configuration.mli | 4 +++ etherlink/bin_evm_node/evm_node.ml | 36 +++++++++++++------ 3 files changed, 56 insertions(+), 19 deletions(-) diff --git a/etherlink/bin_evm_node/config/configuration.ml b/etherlink/bin_evm_node/config/configuration.ml index b4cef7a87921..79b46f0c467a 100644 --- a/etherlink/bin_evm_node/config/configuration.ml +++ b/etherlink/bin_evm_node/config/configuration.ml @@ -21,6 +21,7 @@ type sequencer = { preimages : string; time_between_blocks : time_between_blocks; private_rpc_port : int; + sequencer : Signature.secret_key; } type 'a t = { @@ -68,6 +69,9 @@ let default_sequencer = rollup_node_endpoint = Uri.empty; time_between_blocks = Time_between_blocks 5.; private_rpc_port = default_private_rpc_port; + sequencer = + Signature.Secret_key.of_b58check_exn + "edsk422LGdmDnai4Cya6csM6oFmgHpDQKUhatTURJRAY4h7NHNz9sz"; } let log_filter_config_encoding : log_filter_config Data_encoding.t = @@ -111,25 +115,29 @@ let encoding_sequencer = rollup_node_endpoint; time_between_blocks; private_rpc_port; + sequencer; } -> ( kernel, preimages, Uri.to_string rollup_node_endpoint, time_between_blocks, - private_rpc_port )) + private_rpc_port, + sequencer )) (fun ( kernel, preimages, rollup_node_endpoint, time_between_blocks, - private_rpc_port ) -> + private_rpc_port, + sequencer ) -> { kernel; preimages; rollup_node_endpoint = Uri.of_string rollup_node_endpoint; time_between_blocks; private_rpc_port; + sequencer; }) - (obj5 + (obj6 (dft "kernel" string default_sequencer.kernel) (dft "preimages" string default_sequencer.preimages) (dft @@ -144,7 +152,11 @@ let encoding_sequencer = "private-rpc-port" ~description:"RPC port for private server" uint16 - default_private_rpc_port)) + default_private_rpc_port) + (dft + "sequencer" + Signature.Secret_key.encoding + default_sequencer.sequencer)) let encoding ~default_mode mode_encoding = let open Data_encoding in @@ -260,7 +272,7 @@ module Cli = struct let create_sequencer ?private_rpc_port ~devmode ?rpc_addr ?rpc_port ?cors_origins ?cors_headers ?log_filter ~verbose ?rollup_node_endpoint - ?kernel ?preimages ?time_between_blocks = + ?kernel ?preimages ?time_between_blocks ~sequencer = let mode = { rollup_node_endpoint = @@ -277,6 +289,7 @@ module Cli = struct Option.value ~default:default_sequencer.private_rpc_port private_rpc_port; + sequencer; } in create @@ -326,7 +339,7 @@ module Cli = struct let patch_sequencer_configuration_from_args ?private_rpc_port ~devmode ?rpc_addr ?rpc_port ?cors_origins ?cors_headers ?log_filter ~verbose ?rollup_node_endpoint ?kernel ?preimages ?time_between_blocks - configuration = + configuration ~sequencer = let mode = { rollup_node_endpoint = @@ -343,6 +356,7 @@ module Cli = struct Option.value ~default:default_sequencer.private_rpc_port private_rpc_port; + sequencer; } in patch_configuration_from_args @@ -427,7 +441,8 @@ module Cli = struct let create_or_read_sequencer_config ~data_dir ~devmode ?rpc_addr ?rpc_port ?private_rpc_port ?cors_origins ?cors_headers ?log_filter ~verbose - ?rollup_node_endpoint ?kernel ?preimages ?time_between_blocks () = + ?rollup_node_endpoint ?kernel ?preimages ?time_between_blocks ~sequencer + () = create_or_read_config ~data_dir ~devmode @@ -444,12 +459,14 @@ module Cli = struct ?rollup_node_endpoint ?kernel ?preimages - ?time_between_blocks) + ?time_between_blocks + ~sequencer) ~create: (create_sequencer ?rollup_node_endpoint ?kernel ?preimages - ?time_between_blocks) + ?time_between_blocks + ~sequencer) () end diff --git a/etherlink/bin_evm_node/config/configuration.mli b/etherlink/bin_evm_node/config/configuration.mli index 19b7e7c22e0c..caff31c355a2 100644 --- a/etherlink/bin_evm_node/config/configuration.mli +++ b/etherlink/bin_evm_node/config/configuration.mli @@ -32,6 +32,8 @@ type sequencer = { preimages : string; (** Path to the preimages directory. *) time_between_blocks : time_between_blocks; (** See {!time_between_blocks}. *) private_rpc_port : int; (** Port for internal RPC services *) + sequencer : Signature.secret_key; + (** The secret key used to sign the blueprints. *) } type 'a t = { @@ -93,6 +95,7 @@ module Cli : sig ?kernel:string -> ?preimages:string -> ?time_between_blocks:time_between_blocks -> + sequencer:Signature.secret_key -> unit -> sequencer t @@ -123,6 +126,7 @@ module Cli : sig ?kernel:string -> ?preimages:string -> ?time_between_blocks:time_between_blocks -> + sequencer:Signature.secret_key -> unit -> sequencer t tzresult Lwt.t end diff --git a/etherlink/bin_evm_node/evm_node.ml b/etherlink/bin_evm_node/evm_node.ml index ee912902a5f4..b3db1fd6ddde 100644 --- a/etherlink/bin_evm_node/evm_node.ml +++ b/etherlink/bin_evm_node/evm_node.ml @@ -302,6 +302,10 @@ module Params = struct let rollup_node_endpoint = Tezos_clic.parameter (fun _ uri -> Lwt.return_ok (Uri.of_string uri)) + let secret_key : (Signature.secret_key, unit) Tezos_clic.parameter = + Tezos_clic.parameter (fun _ sk -> + Lwt.return_ok (Signature.Secret_key.of_b58check_exn sk)) + let string_list = Tezos_clic.parameter (fun _ s -> let list = String.split ',' s in @@ -373,14 +377,6 @@ let data_dir_arg = ~default Params.string -let rollup_node_endpoint_param = - Tezos_clic.param - ~name:"rollup-node-endpoint" - ~desc: - "The smart rollup node endpoint address (as ADDR:PORT) the node will \ - communicate with." - Params.rollup_node_endpoint - let rollup_address_arg = let open Lwt_result_syntax in let open Tezos_clic in @@ -454,7 +450,13 @@ let proxy_command = verbose_arg keep_alive_arg) (prefixes ["run"; "proxy"; "with"; "endpoint"] - @@ rollup_node_endpoint_param @@ stop) + @@ param + ~name:"rollup-node-endpoint" + ~desc: + "The smart rollup node endpoint address (as ADDR:PORT) the node \ + will communicate with." + Params.rollup_node_endpoint + @@ stop) (fun ( data_dir, devmode, rpc_addr, @@ -561,7 +563,19 @@ let sequencer_command = preimages_arg time_between_blocks_arg) (prefixes ["run"; "sequencer"; "with"; "endpoint"] - @@ rollup_node_endpoint_param @@ stop) + @@ param + ~name:"rollup-node-endpoint" + ~desc: + "The smart rollup node endpoint address (as ADDR:PORT) the node \ + will communicate with." + Params.rollup_node_endpoint + @@ prefixes ["signing"; "with"] + @@ param + ~name:"secret-key" + ~desc: + "The tezos secret key used to sign the blueprints published to L1" + Params.secret_key + @@ stop) (fun ( data_dir, rpc_addr, rpc_port, @@ -573,6 +587,7 @@ let sequencer_command = preimages, time_between_blocks ) rollup_node_endpoint + sequencer () -> let*! () = Tezos_base_unix.Internal_event_unix.init () in let*! () = Internal_event.Simple.emit Event.event_starting "sequencer" in @@ -590,6 +605,7 @@ let sequencer_command = ?kernel ?preimages ?time_between_blocks + ~sequencer () in let* () = Configuration.save_sequencer ~force:true ~data_dir config in -- GitLab From 74d65da41409357321e2fdee516d211620a02a1e Mon Sep 17 00:00:00 2001 From: Valentin Chaboche Date: Thu, 4 Jan 2024 14:09:40 +0100 Subject: [PATCH 5/9] EVM/Sequencer: sign blueprints --- etherlink/bin_evm_node/evm_node.ml | 8 +++++- etherlink/bin_evm_node/lib_dev/sequencer.ml | 5 ++++ .../lib_dev/sequencer_blueprint.ml | 25 +++++++++++++++---- .../lib_dev/sequencer_blueprint.mli | 7 +++--- .../bin_evm_node/lib_dev/sequencer_state.ml | 3 ++- .../bin_evm_node/lib_dev/sequencer_state.mli | 3 ++- 6 files changed, 40 insertions(+), 11 deletions(-) diff --git a/etherlink/bin_evm_node/evm_node.ml b/etherlink/bin_evm_node/evm_node.ml index b3db1fd6ddde..e8426cc23abf 100644 --- a/etherlink/bin_evm_node/evm_node.ml +++ b/etherlink/bin_evm_node/evm_node.ml @@ -623,12 +623,18 @@ let sequencer_command = let* ctxt = if loaded then return ctxt else - Sequencer_state.init ~rollup_node_endpoint ~smart_rollup_address ctxt + Sequencer_state.init + ~secret_key:sequencer + ~rollup_node_endpoint + ~smart_rollup_address + ctxt in let module Sequencer = Sequencer.Make (struct let ctxt = ctxt let rollup_node_endpoint = rollup_node_endpoint + + let secret_key = sequencer end) in (* Ignore the smart rollup address for now. *) let* () = diff --git a/etherlink/bin_evm_node/lib_dev/sequencer.ml b/etherlink/bin_evm_node/lib_dev/sequencer.ml index 41bde1bdbda1..60b2f132f122 100644 --- a/etherlink/bin_evm_node/lib_dev/sequencer.ml +++ b/etherlink/bin_evm_node/lib_dev/sequencer.ml @@ -9,6 +9,8 @@ module MakeBackend (Ctxt : sig val ctxt : Sequencer_context.t val rollup_node_endpoint : Uri.t + + val secret_key : Signature.secret_key end) : Services_backend_sig.Backend = struct module READER = struct let read path = @@ -38,6 +40,7 @@ end) : Services_backend_sig.Backend = struct let (Ethereum_types.(Qty next) as number) = ctxt.next_blueprint_number in let inputs = Sequencer_blueprint.create + ~secret_key:Ctxt.secret_key ~timestamp ~smart_rollup_address ~transactions:messages @@ -74,5 +77,7 @@ module Make (Ctxt : sig val ctxt : Sequencer_context.t val rollup_node_endpoint : Uri.t + + val secret_key : Signature.secret_key end) = Services_backend_sig.Make (MakeBackend (Ctxt)) diff --git a/etherlink/bin_evm_node/lib_dev/sequencer_blueprint.ml b/etherlink/bin_evm_node/lib_dev/sequencer_blueprint.ml index 7088b7fd82d2..8d0f6538ca9a 100644 --- a/etherlink/bin_evm_node/lib_dev/sequencer_blueprint.ml +++ b/etherlink/bin_evm_node/lib_dev/sequencer_blueprint.ml @@ -18,6 +18,9 @@ let chunk_index_size = 2 let blueprint_tag_size = 1 +(* ED25519 *) +let signature_size = 64 + (* Tags added by RLP encoding for the sequencer blueprint. The sequencer blueprint follows the format: [ chunk, <- max size around 4kb, requires tag of 3 bytes @@ -35,7 +38,7 @@ let max_chunk_size = (* max_input_size already considers the external tag *) max_input_size - framing_protocol_tag_size - smart_rollup_address_size - blueprint_tag_size - blueprint_number_size - nb_chunks_size - - chunk_index_size - rlp_tags_size + - chunk_index_size - rlp_tags_size - signature_size let make_blueprint_chunks ~timestamp ~transactions = let open Rlp in @@ -70,17 +73,29 @@ let encode_u16_le i = Bytes.set_uint16_le bytes 0 i ; bytes -let create ~timestamp ~smart_rollup_address ~number ~transactions = +let create ~secret_key ~timestamp ~smart_rollup_address ~number ~transactions = let open Rlp in let number = Value (encode_u256_le number) in let chunks = make_blueprint_chunks ~timestamp ~transactions in - let nb_chunks = Rlp.Value (encode_u16_le @@ List.length chunks) in + let nb_chunks = Value (encode_u16_le @@ List.length chunks) in let message_from_chunk chunk_index chunk = - let chunk_index = Rlp.Value (encode_u16_le chunk_index) in + let chunk_index = Value (encode_u16_le chunk_index) in + let value = Value (Bytes.of_string chunk) in + + (* Takes the blueprints fields and sign them. *) + let rlp_unsigned_blueprint = + List [value; number; nb_chunks; chunk_index] |> encode + in + let signature = + Signature.(sign secret_key rlp_unsigned_blueprint |> to_bytes) + in + + (* Encode the blueprints fields and its signature. *) let rlp_sequencer_blueprint = - List [Value (Bytes.of_string chunk); number; nb_chunks; chunk_index] + List [value; number; nb_chunks; chunk_index; Value signature] |> encode |> Bytes.to_string in + `External ("\000" (* Framed protocol *) ^ smart_rollup_address ^ "\003" diff --git a/etherlink/bin_evm_node/lib_dev/sequencer_blueprint.mli b/etherlink/bin_evm_node/lib_dev/sequencer_blueprint.mli index e3f0cf49cc37..520e4b7277ab 100644 --- a/etherlink/bin_evm_node/lib_dev/sequencer_blueprint.mli +++ b/etherlink/bin_evm_node/lib_dev/sequencer_blueprint.mli @@ -5,12 +5,13 @@ (* *) (*****************************************************************************) -(** [create ~timestamp ~smart_rollup_address ~number ~transactions] +(** [create ~secret_key ~timestamp ~smart_rollup_address ~number ~transactions] creates a sequencer blueprint at [timestamp] with a given [number] - containing [transactions]. Returns valid payload of external - messages inputs to put in the inbox. + containing [transactions], signed with [secret_key]. Returns + valid list of external messages inputs to put in the inbox. *) val create : + secret_key:Signature.secret_key -> timestamp:Time.Protocol.t -> smart_rollup_address:string -> number:Ethereum_types.quantity -> diff --git a/etherlink/bin_evm_node/lib_dev/sequencer_state.ml b/etherlink/bin_evm_node/lib_dev/sequencer_state.ml index 8131af386d7c..bc988904f0d8 100644 --- a/etherlink/bin_evm_node/lib_dev/sequencer_state.ml +++ b/etherlink/bin_evm_node/lib_dev/sequencer_state.ml @@ -29,7 +29,7 @@ let execute ?(commit = false) ctxt inbox = in return (ctxt, evm_state) -let init ~smart_rollup_address ~rollup_node_endpoint ctxt = +let init ~secret_key ~smart_rollup_address ~rollup_node_endpoint ctxt = let open Lwt_result_syntax in let* evm_state = Wasm.start @@ -43,6 +43,7 @@ let init ~smart_rollup_address ~rollup_node_endpoint ctxt = (* Create the first empty block. *) let inputs = Sequencer_blueprint.create + ~secret_key ~timestamp:(Helpers.now ()) ~smart_rollup_address ~transactions:[] diff --git a/etherlink/bin_evm_node/lib_dev/sequencer_state.mli b/etherlink/bin_evm_node/lib_dev/sequencer_state.mli index ff90ce82425f..e77d58a8e974 100644 --- a/etherlink/bin_evm_node/lib_dev/sequencer_state.mli +++ b/etherlink/bin_evm_node/lib_dev/sequencer_state.mli @@ -14,10 +14,11 @@ val execute : [< `Input of string] list -> (Sequencer_context.t * Sequencer_context.evm_state) tzresult Lwt.t -(** [init ~smart_rollup_address ~rollup_node_endpoint ctxt] +(** [init ~secret_key ~smart_rollup_address ~rollup_node_endpoint ctxt] initializes the local state in [ctxt], produces and publishes the genesis block. *) val init : + secret_key:Signature.secret_key -> smart_rollup_address:string -> rollup_node_endpoint:Uri.t -> Sequencer_context.t -> -- GitLab From 817b0bff787e7824687c7a0d916637eb94820f30 Mon Sep 17 00:00:00 2001 From: Valentin Chaboche Date: Thu, 4 Jan 2024 15:20:33 +0100 Subject: [PATCH 6/9] EVM/Kernel: log configuration during stage one --- etherlink/kernel_evm/kernel/src/lib.rs | 1 + etherlink/kernel_evm/kernel/src/stage_one.rs | 17 +++++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/etherlink/kernel_evm/kernel/src/lib.rs b/etherlink/kernel_evm/kernel/src/lib.rs index fe3339af4323..6203b66866ce 100644 --- a/etherlink/kernel_evm/kernel/src/lib.rs +++ b/etherlink/kernel_evm/kernel/src/lib.rs @@ -104,6 +104,7 @@ pub fn stage_one( ticketer, admin ); + log!(host, Info, "Configuration: {}", configuration); fetch(host, smart_rollup_address, ticketer, admin, configuration) } diff --git a/etherlink/kernel_evm/kernel/src/stage_one.rs b/etherlink/kernel_evm/kernel/src/stage_one.rs index 4cd574b9a5e0..eb3f78c4f5f7 100644 --- a/etherlink/kernel_evm/kernel/src/stage_one.rs +++ b/etherlink/kernel_evm/kernel/src/stage_one.rs @@ -26,6 +26,23 @@ pub enum Configuration { }, } +impl std::fmt::Display for Configuration { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Configuration::Proxy => write!(f, "Proxy"), + Configuration::Sequencer { + delayed_bridge, + delayed_inbox: _, // Ignoring delayed_inbox + sequencer, + } => write!( + f, + "Sequencer {{ delayed_bridge: {:?}, sequencer: {:?} }}", + delayed_bridge, sequencer + ), + } + } +} + pub fn fetch_inbox_blueprints( host: &mut Host, smart_rollup_address: [u8; RAW_ROLLUP_ADDRESS_SIZE], -- GitLab From 7798df6b9e39d12b4a92d58889630579b57b22ef Mon Sep 17 00:00:00 2001 From: Valentin Chaboche Date: Thu, 4 Jan 2024 14:36:43 +0100 Subject: [PATCH 7/9] EVM/Tezt: run sequencer with secret key --- tezt/lib_ethereum/configuration.ml | 12 ++++++--- tezt/lib_ethereum/configuration.mli | 2 +- tezt/lib_tezos/evm_node.ml | 8 +++++- tezt/lib_tezos/evm_node.mli | 1 + tezt/tests/evm_rollup.ml | 38 +++++++++++++++-------------- tezt/tests/evm_sequencer.ml | 11 +++++++-- 6 files changed, 46 insertions(+), 26 deletions(-) diff --git a/tezt/lib_ethereum/configuration.ml b/tezt/lib_ethereum/configuration.ml index 7d7cdef571af..182b53a899ff 100644 --- a/tezt/lib_ethereum/configuration.ml +++ b/tezt/lib_ethereum/configuration.ml @@ -7,8 +7,8 @@ let default_bootstrap_account_balance = Wei.of_eth_int 9999 -let make_config ?bootstrap_accounts ?ticketer ?administrator - ?(sequencer = false) ?delayed_bridge () = +let make_config ?bootstrap_accounts ?ticketer ?administrator ?sequencer + ?delayed_bridge () = let open Sc_rollup_helpers.Installer_kernel_config in let ticketer = Option.fold @@ -44,9 +44,13 @@ let make_config ?bootstrap_accounts ?ticketer ?administrator administrator in let sequencer = - if sequencer then [Set {value = "00"; to_ = Durable_storage_path.sequencer}] - else [] + match sequencer with + | Some secret_key -> + let value = Hex.(of_string secret_key |> show) in + [Set {value; to_ = Durable_storage_path.sequencer}] + | None -> [] in + let delayed_bridge = Option.fold ~some:(fun delayed_bridge -> diff --git a/tezt/lib_ethereum/configuration.mli b/tezt/lib_ethereum/configuration.mli index 70171437d303..f553e0da20b6 100644 --- a/tezt/lib_ethereum/configuration.mli +++ b/tezt/lib_ethereum/configuration.mli @@ -15,7 +15,7 @@ val make_config : ?bootstrap_accounts:Eth_account.t array -> ?ticketer:string -> ?administrator:string -> - ?sequencer:bool -> + ?sequencer:string -> ?delayed_bridge:string -> unit -> [> `Config of Sc_rollup_helpers.Installer_kernel_config.instr list] option diff --git a/tezt/lib_tezos/evm_node.ml b/tezt/lib_tezos/evm_node.ml index 9e863bbca201..d69d277fc2b4 100644 --- a/tezt/lib_tezos/evm_node.ml +++ b/tezt/lib_tezos/evm_node.ml @@ -33,6 +33,7 @@ type mode = preimage_dir : string; private_rpc_port : int; time_between_blocks : time_between_blocks option; + sequencer : string; } | Proxy of {devmode : bool} @@ -149,13 +150,18 @@ let run_args evm_node = evm_node.persistent_state.rollup_node_endpoint; ] @ Cli_arg.optional_switch "devmode" devmode - | Sequencer {kernel; preimage_dir; private_rpc_port; time_between_blocks} -> + | Sequencer + {kernel; preimage_dir; private_rpc_port; time_between_blocks; sequencer} + -> [ "run"; "sequencer"; "with"; "endpoint"; evm_node.persistent_state.rollup_node_endpoint; + "signing"; + "with"; + sequencer; "--kernel"; kernel; "--preimage-dir"; diff --git a/tezt/lib_tezos/evm_node.mli b/tezt/lib_tezos/evm_node.mli index 2811dd0d698d..2d51d816dbc9 100644 --- a/tezt/lib_tezos/evm_node.mli +++ b/tezt/lib_tezos/evm_node.mli @@ -44,6 +44,7 @@ type mode = time_between_blocks : time_between_blocks option; (** See {!time_between_blocks}, if the value is not provided, the sequencer uses it default value. *) + sequencer : string; (** Secret key used to sign the blueprints. *) } | Proxy of {devmode : bool (** --devmode flag. *)} diff --git a/tezt/tests/evm_rollup.ml b/tezt/tests/evm_rollup.ml index ea0dba135ae4..a3cac6a9f767 100644 --- a/tezt/tests/evm_rollup.ml +++ b/tezt/tests/evm_rollup.ml @@ -255,6 +255,7 @@ type kernel_installee = {base_installee : string; installee : string} type setup_mode = | Setup_sequencer of { time_between_blocks : Evm_node.time_between_blocks option; + sequencer : Account.key; } | Setup_proxy of {devmode : bool} @@ -283,13 +284,15 @@ let setup_evm_kernel ?config ?kernel_installee else None in let sequencer = - match setup_mode with Setup_proxy _ -> false | Setup_sequencer _ -> true + match setup_mode with + | Setup_proxy _ -> None + | Setup_sequencer {sequencer; _} -> Some sequencer.public_key in Configuration.make_config ~bootstrap_accounts ?ticketer ?administrator - ~sequencer + ?sequencer () in let config = @@ -309,18 +312,16 @@ let setup_evm_kernel ?config ?kernel_installee ~default_operator:rollup_operator_key in (* Start a rollup node *) + let preimages_dir = + Filename.concat (Sc_rollup_node.data_dir sc_rollup_node) "wasm_2_0_0" + in let* {output; _} = let base_installee, installee = match kernel_installee with | Some {base_installee; installee} -> (base_installee, installee) | None -> ("./", "evm_kernel") in - prepare_installer_kernel - ~base_installee - ~preimages_dir: - (Filename.concat (Sc_rollup_node.data_dir sc_rollup_node) "wasm_2_0_0") - ?config - installee + prepare_installer_kernel ~base_installee ~preimages_dir ?config installee in let* sc_rollup_address = originate_sc_rollup @@ -340,16 +341,14 @@ let setup_evm_kernel ?config ?kernel_installee let* mode = match setup_mode with | Setup_proxy {devmode} -> return (Evm_node.Proxy {devmode}) - | Setup_sequencer {time_between_blocks} -> - let preimages_dir = Temp.dir "preimages" in - let* {output; _} = - prepare_installer_kernel - ~base_installee:"./" - ~preimages_dir - ?config - "evm_kernel" - in + | Setup_sequencer {time_between_blocks; sequencer} -> let private_rpc_port = Port.fresh () in + let sequencer = + match sequencer.secret_key with + | Unencrypted sk -> sk + | Encrypted _ -> + Test.fail "Provide an unencrypted key for the sequencer" + in return (Evm_node.Sequencer { @@ -357,6 +356,7 @@ let setup_evm_kernel ?config ?kernel_installee preimage_dir = preimages_dir; private_rpc_port; time_between_blocks; + sequencer; }) in let* evm_node = @@ -482,7 +482,9 @@ let register_both ~title ~tags ?uses ?admin ?commitment_period ?challenge_window ~past_genesis in register ~setup_mode:(Setup_proxy {devmode = true}) ; - register ~setup_mode:(Setup_sequencer {time_between_blocks}) + register + ~setup_mode: + (Setup_sequencer {time_between_blocks; sequencer = Constant.bootstrap1}) type contract = {label : string; abi : string; bin : string} diff --git a/tezt/tests/evm_sequencer.ml b/tezt/tests/evm_sequencer.ml index c16ede45c645..14025ba87def 100644 --- a/tezt/tests/evm_sequencer.ml +++ b/tezt/tests/evm_sequencer.ml @@ -72,7 +72,8 @@ let setup_l1_contracts client = return {delayed_transaction_bridge; exchanger; bridge} let setup_sequencer ?time_between_blocks - ?(bootstrap_accounts = Eth_account.bootstrap_accounts) protocol = + ?(bootstrap_accounts = Eth_account.bootstrap_accounts) + ?(sequencer = Constant.bootstrap1) protocol = let* node, client = setup_l1 protocol in let* l1_contracts = setup_l1_contracts client in let sc_rollup_node = @@ -86,7 +87,7 @@ let setup_sequencer ?time_between_blocks let config = Configuration.make_config ~bootstrap_accounts - ~sequencer:true + ~sequencer:sequencer.public_key ~delayed_bridge:l1_contracts.delayed_transaction_bridge ~ticketer:l1_contracts.exchanger () @@ -110,12 +111,18 @@ let setup_sequencer ?time_between_blocks in let private_rpc_port = Port.fresh () in let mode = + let sequencer = + match sequencer.secret_key with + | Unencrypted sk -> sk + | Encrypted _ -> Test.fail "Provide an unencrypted key for the sequencer" + in Evm_node.Sequencer { kernel = output; preimage_dir = preimages_dir; private_rpc_port; time_between_blocks; + sequencer; } in let* evm_node = -- GitLab From fac4a1f8bdf2b121f4c5c3979ee26edf5537943f Mon Sep 17 00:00:00 2001 From: Valentin Chaboche Date: Tue, 16 Jan 2024 11:24:00 +0100 Subject: [PATCH 8/9] EVM/Node: remove default mode --- .../bin_evm_node/config/configuration.ml | 100 +++++++----------- 1 file changed, 41 insertions(+), 59 deletions(-) diff --git a/etherlink/bin_evm_node/config/configuration.ml b/etherlink/bin_evm_node/config/configuration.ml index 79b46f0c467a..8e8d94c862ed 100644 --- a/etherlink/bin_evm_node/config/configuration.ml +++ b/etherlink/bin_evm_node/config/configuration.ml @@ -46,33 +46,25 @@ let default_rpc_addr = "127.0.0.1" let default_rpc_port = 8545 -let default_private_rpc_port = 8546 +let default_devmode = false + +let default_cors_origins = [] -let default default_mode = - { - rpc_addr = default_rpc_addr; - rpc_port = default_rpc_port; - devmode = false; - cors_origins = []; - cors_headers = []; - verbose = false; - log_filter = default_filter_config; - mode = default_mode; - } +let default_cors_headers = [] + +let default_verbose = false let default_proxy = {rollup_node_endpoint = Uri.empty} -let default_sequencer = - { - kernel = "sequencer.wasm"; - preimages = "_evm_installer_preimages"; - rollup_node_endpoint = Uri.empty; - time_between_blocks = Time_between_blocks 5.; - private_rpc_port = default_private_rpc_port; - sequencer = - Signature.Secret_key.of_b58check_exn - "edsk422LGdmDnai4Cya6csM6oFmgHpDQKUhatTURJRAY4h7NHNz9sz"; - } +let default_kernel = "sequencer.wasm" + +let default_preimages = "_evm_installer_preimages" + +let default_rollup_node_endpoint = Uri.empty + +let default_time_between_blocks = Time_between_blocks 5. + +let default_private_rpc_port = 8546 let log_filter_config_encoding : log_filter_config Data_encoding.t = let open Data_encoding in @@ -138,29 +130,26 @@ let encoding_sequencer = sequencer; }) (obj6 - (dft "kernel" string default_sequencer.kernel) - (dft "preimages" string default_sequencer.preimages) + (dft "kernel" string default_kernel) + (dft "preimages" string default_preimages) (dft "rollup_node_endpoint" string - (Uri.to_string default_proxy.rollup_node_endpoint)) + (Uri.to_string default_rollup_node_endpoint)) (dft "time_between_blocks" encoding_time_between_blocks - default_sequencer.time_between_blocks) + default_time_between_blocks) (dft "private-rpc-port" ~description:"RPC port for private server" uint16 default_private_rpc_port) - (dft - "sequencer" - Signature.Secret_key.encoding - default_sequencer.sequencer)) + (req "sequencer" Signature.Secret_key.encoding)) -let encoding ~default_mode mode_encoding = +let encoding : type a. a Data_encoding.t -> a t Data_encoding.t = + fun mode_encoding -> let open Data_encoding in - let default = default default_mode in conv (fun { rpc_addr; @@ -201,12 +190,12 @@ let encoding ~default_mode mode_encoding = ((obj8 (dft "rpc-addr" ~description:"RPC address" string default_rpc_addr) (dft "rpc-port" ~description:"RPC port" uint16 default_rpc_port) - (dft "devmode" bool default.devmode) - (dft "cors_origins" (list string) default.cors_origins) - (dft "cors_headers" (list string) default.cors_headers) - (dft "verbose" bool default.verbose) + (dft "devmode" bool default_devmode) + (dft "cors_origins" (list string) default_cors_origins) + (dft "cors_headers" (list string) default_cors_headers) + (dft "verbose" bool default_verbose) (dft "log_filter" log_filter_config_encoding default_filter_config)) - (dft "mode" mode_encoding default_mode)) + (req "mode" mode_encoding)) let save ~force ~data_dir encoding config = let open Lwt_result_syntax in @@ -222,11 +211,11 @@ let save ~force ~data_dir encoding config = Lwt_utils_unix.Json.write_file config_file json let save_proxy ~force ~data_dir config = - let encoding = encoding ~default_mode:default_proxy encoding_proxy in + let encoding = encoding encoding_proxy in save ~force ~data_dir encoding config let save_sequencer ~force ~data_dir config = - let encoding = encoding ~default_mode:default_sequencer encoding_sequencer in + let encoding = encoding encoding_sequencer in save ~force ~data_dir encoding config let load ~data_dir encoding = @@ -236,23 +225,22 @@ let load ~data_dir encoding = config let load_proxy ~data_dir = - let encoding = encoding ~default_mode:default_proxy encoding_proxy in + let encoding = encoding encoding_proxy in load ~data_dir encoding let load_sequencer ~data_dir = - let encoding = encoding ~default_mode:default_sequencer encoding_sequencer in + let encoding = encoding encoding_sequencer in load ~data_dir encoding module Cli = struct let create ~devmode ?rpc_addr ?rpc_port ?cors_origins ?cors_headers ?log_filter ~verbose ~mode () = - let default = default mode in { - rpc_addr = Option.value ~default:default.rpc_addr rpc_addr; - rpc_port = Option.value ~default:default.rpc_port rpc_port; + rpc_addr = Option.value ~default:default_rpc_addr rpc_addr; + rpc_port = Option.value ~default:default_rpc_port rpc_port; devmode; - cors_origins = Option.value ~default:default.cors_origins cors_origins; - cors_headers = Option.value ~default:default.cors_headers cors_headers; + cors_origins = Option.value ~default:default_cors_origins cors_origins; + cors_headers = Option.value ~default:default_cors_headers cors_headers; verbose; log_filter = Option.value ~default:default_filter_config log_filter; mode; @@ -277,18 +265,14 @@ module Cli = struct { rollup_node_endpoint = Option.value - ~default:default_sequencer.rollup_node_endpoint + ~default:default_rollup_node_endpoint rollup_node_endpoint; - kernel = Option.value ~default:default_sequencer.kernel kernel; - preimages = Option.value ~default:default_sequencer.preimages preimages; + kernel = Option.value ~default:default_kernel kernel; + preimages = Option.value ~default:default_preimages preimages; time_between_blocks = - Option.value - ~default:default_sequencer.time_between_blocks - time_between_blocks; + Option.value ~default:default_time_between_blocks time_between_blocks; private_rpc_port = - Option.value - ~default:default_sequencer.private_rpc_port - private_rpc_port; + Option.value ~default:default_private_rpc_port private_rpc_port; sequencer; } in @@ -353,9 +337,7 @@ module Cli = struct ~default:configuration.mode.time_between_blocks time_between_blocks; private_rpc_port = - Option.value - ~default:default_sequencer.private_rpc_port - private_rpc_port; + Option.value ~default:default_private_rpc_port private_rpc_port; sequencer; } in -- GitLab From 071291b63919cc7390a3bfa151c80beed95d7575 Mon Sep 17 00:00:00 2001 From: Valentin Chaboche Date: Tue, 16 Jan 2024 11:28:17 +0100 Subject: [PATCH 9/9] EVM/Node: mention secret keys issue --- etherlink/bin_evm_node/config/configuration.ml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/etherlink/bin_evm_node/config/configuration.ml b/etherlink/bin_evm_node/config/configuration.ml index 8e8d94c862ed..69f98de4d9e6 100644 --- a/etherlink/bin_evm_node/config/configuration.ml +++ b/etherlink/bin_evm_node/config/configuration.ml @@ -15,6 +15,8 @@ type proxy = {rollup_node_endpoint : Uri.t} type time_between_blocks = Nothing | Time_between_blocks of float +(** TODO https://gitlab.com/tezos/tezos/-/issues/6811 + We need to properly handle the secrets in the node. *) type sequencer = { rollup_node_endpoint : Uri.t; kernel : string; -- GitLab