From 93545ed64f83096f1912471c3f6f11520fdb0652 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Date: Wed, 7 Jun 2023 12:13:22 +0200 Subject: [PATCH 1/6] kernel/sequencer: add dependencies --- src/kernel_sequencer/Cargo.lock | 3 +++ src/kernel_sequencer/Cargo.toml | 15 ++++++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/kernel_sequencer/Cargo.lock b/src/kernel_sequencer/Cargo.lock index 8cf1fc043b19..ec9b9d95b25b 100644 --- a/src/kernel_sequencer/Cargo.lock +++ b/src/kernel_sequencer/Cargo.lock @@ -346,11 +346,14 @@ checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" name = "kernel-sequencer" version = "0.1.0" dependencies = [ + "nom", "tezos-smart-rollup-core", "tezos-smart-rollup-encoding", "tezos-smart-rollup-host", "tezos-smart-rollup-mock", "tezos_crypto_rs", + "tezos_data_encoding", + "tezos_data_encoding_derive", ] [[package]] diff --git a/src/kernel_sequencer/Cargo.toml b/src/kernel_sequencer/Cargo.toml index df8606dadd14..6a9a8784a239 100644 --- a/src/kernel_sequencer/Cargo.toml +++ b/src/kernel_sequencer/Cargo.toml @@ -25,7 +25,20 @@ version = "0.2.0" path = "../kernel_sdk/mock" version = "0.2.0" -[dev-dependencies.tezos-smart-rollup-encoding] +[dependencies.tezos_data_encoding] +version = "0.5" + +[dependencies.tezos_data_encoding_derive] +version = "0.5" + +[dependencies.nom] +version = "7.1" + +[dependencies.tezos_crypto_rs] +version = "0.5.0" +default-features = false + +[dependencies.tezos-smart-rollup-encoding] path = "../kernel_sdk/encoding" version = "0.2.0" -- GitLab From db9aa69ca45eda510f29f013451386c0ffa272eb Mon Sep 17 00:00:00 2001 From: Pierre-Louis Date: Fri, 19 May 2023 11:00:49 +0200 Subject: [PATCH 2/6] kernel/sequencer: add framing protocol --- src/kernel_sequencer/src/lib.rs | 1 + src/kernel_sequencer/src/message.rs | 60 +++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 src/kernel_sequencer/src/message.rs diff --git a/src/kernel_sequencer/src/lib.rs b/src/kernel_sequencer/src/lib.rs index d3dbac3fdb12..1ed998f3d2c3 100644 --- a/src/kernel_sequencer/src/lib.rs +++ b/src/kernel_sequencer/src/lib.rs @@ -3,6 +3,7 @@ // SPDX-License-Identifier: MIT mod delayed_inbox; +mod message; pub mod routing; mod sequencer_macro; pub mod sequencer_runtime; diff --git a/src/kernel_sequencer/src/message.rs b/src/kernel_sequencer/src/message.rs new file mode 100644 index 000000000000..a092360ddf01 --- /dev/null +++ b/src/kernel_sequencer/src/message.rs @@ -0,0 +1,60 @@ +// SPDX-FileCopyrightText: 2023 Marigold +// +// SPDX-License-Identifier: MIT + +use nom::{bytes::complete::tag, sequence::preceded}; +use tezos_data_encoding::{ + enc::{self, BinResult, BinWriter}, + nom::{NomReader, NomResult}, +}; +use tezos_smart_rollup_encoding::smart_rollup::SmartRollupAddress; + +/// Framing protocol v0 +/// +/// The framing protocol starts with a 0, then the address of the rollup, then the message +/// The message should start by a tag, provided by the Tag trait +/// +/// [0x00, smart rollup address, tag, message] +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct Framed

{ + pub destination: SmartRollupAddress, + pub payload: P, +} +impl

NomReader for Framed

+where + P: NomReader, +{ + fn nom_read(input: &[u8]) -> NomResult { + // Extract the rollup address from the framing protocol + // 0x00 is the version of the framing protocol + let (input, destination) = preceded(tag([0]), SmartRollupAddress::nom_read)(input)?; + + // Extract the payload + let (remaining, payload) = P::nom_read(input)?; + + Ok(( + remaining, + Framed { + destination, + payload, + }, + )) + } +} + +impl

BinWriter for Framed

+where + P: BinWriter, +{ + fn bin_write(&self, output: &mut Vec) -> BinResult { + // bytes of the framing protocol + // 0x00 is the version of the framing protocol + enc::put_byte(&0x00, output); + + // bytes of the rollup address + self.destination.bin_write(output)?; + + // bytes of the payload + self.payload.bin_write(output) + } +} -- GitLab From fd507f18327acb6614b50010d292b02f9ac4f495 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Date: Fri, 19 May 2023 11:51:12 +0200 Subject: [PATCH 3/6] kernel/sequencer: add sequence message --- src/kernel_sequencer/src/message.rs | 104 +++++++++++++++++++++++++++- 1 file changed, 103 insertions(+), 1 deletion(-) diff --git a/src/kernel_sequencer/src/message.rs b/src/kernel_sequencer/src/message.rs index a092360ddf01..a692c0a86791 100644 --- a/src/kernel_sequencer/src/message.rs +++ b/src/kernel_sequencer/src/message.rs @@ -2,7 +2,8 @@ // // SPDX-License-Identifier: MIT -use nom::{bytes::complete::tag, sequence::preceded}; +use nom::{bytes::complete::tag, combinator::map, sequence::preceded}; +use tezos_crypto_rs::hash::Signature; use tezos_data_encoding::{ enc::{self, BinResult, BinWriter}, nom::{NomReader, NomResult}, @@ -20,6 +21,36 @@ pub struct Framed

{ pub destination: SmartRollupAddress, pub payload: P, } + +/// Messages sent by the user to the sequencer +#[derive(NomReader, BinWriter, Clone, Debug, PartialEq, Eq)] +pub struct Bytes { + #[encoding(dynamic, list)] + inner: Vec, +} + +/// Sequence of messages sent by the sequencer +/// +/// The sequence contains the delayed messages and the messages sent by the user to the sequencer +#[derive(NomReader, BinWriter, Clone, Debug, PartialEq, Eq)] +pub struct Sequence { + nonce: u32, + delayed_messages: u32, + #[encoding(dynamic, list)] + messages: Vec, + signature: Signature, +} + +#[derive(NomReader, BinWriter, Debug, Clone, Eq, PartialEq)] +pub enum SequencerMsg { + Sequence(Sequence), +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum KernelMessage { + Sequencer(Framed), +} + impl

NomReader for Framed

where P: NomReader, @@ -58,3 +89,74 @@ where self.payload.bin_write(output) } } + +impl NomReader for KernelMessage { + fn nom_read(input: &[u8]) -> NomResult { + map( + preceded(tag([1]), Framed::::nom_read), + KernelMessage::Sequencer, + )(input) + } +} + +impl BinWriter for KernelMessage { + fn bin_write(&self, output: &mut Vec) -> enc::BinResult { + match self { + KernelMessage::Sequencer(sequencer_framed_msg) => { + // external message tag + enc::put_byte(&0x01, output); + sequencer_framed_msg.bin_write(output)?; + } + } + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use crate::message::{Framed, SequencerMsg}; + + use super::{KernelMessage, Sequence}; + use tezos_crypto_rs::hash::{SecretKeyEd25519, SeedEd25519}; + use tezos_data_encoding::enc::BinWriter; + use tezos_data_encoding::nom::NomReader; + use tezos_smart_rollup_encoding::public_key::PublicKey; + use tezos_smart_rollup_encoding::smart_rollup::SmartRollupAddress; + + /// Generate a public key and a secret key + fn key_pair(seed: &str) -> (PublicKey, SecretKeyEd25519) { + let (public_key, secret) = SeedEd25519::from_base58_check(seed) + .expect("seed parsing should work") + .keypair() + .expect("make key pair should work"); + + let public_key = PublicKey::Ed25519(public_key); + (public_key, secret) + } + + #[test] + fn test_sequence_serialization() { + let (_, secret) = key_pair("edsk3a5SDDdMWw3Q5hPiJwDXUosmZMTuKQkriPqY6UqtSfdLifpZbB"); + let signature = secret.sign([0x0]).expect("sign should work"); + + let sequence = KernelMessage::Sequencer(Framed { + destination: SmartRollupAddress::from_b58check("sr1EzLeJYWrvch2Mhvrk1nUVYrnjGQ8A4qdb") + .expect("decoding should work"), + payload: SequencerMsg::Sequence(Sequence { + nonce: 0, + delayed_messages: 0, + messages: Vec::default(), + signature, + }), + }); + + // Serializing + let mut bin: Vec = Vec::new(); + sequence.bin_write(&mut bin).unwrap(); + + // Deserializing + let (_, msg_read) = KernelMessage::nom_read(&bin).expect("deserialization should work"); + + assert_eq!(msg_read, sequence); + } +} -- GitLab From 26e4b8361d353d9a613f3f3e16e51663a42ade85 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Date: Fri, 19 May 2023 11:55:19 +0200 Subject: [PATCH 4/6] kernel/sequencer: add set sequencer msg definition --- src/kernel_sequencer/src/message.rs | 45 ++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/src/kernel_sequencer/src/message.rs b/src/kernel_sequencer/src/message.rs index a692c0a86791..eb27d9902ff2 100644 --- a/src/kernel_sequencer/src/message.rs +++ b/src/kernel_sequencer/src/message.rs @@ -8,7 +8,7 @@ use tezos_data_encoding::{ enc::{self, BinResult, BinWriter}, nom::{NomReader, NomResult}, }; -use tezos_smart_rollup_encoding::smart_rollup::SmartRollupAddress; +use tezos_smart_rollup_encoding::{public_key::PublicKey, smart_rollup::SmartRollupAddress}; /// Framing protocol v0 /// @@ -41,9 +41,22 @@ pub struct Sequence { signature: Signature, } +/// Message to set the appropriate sequencer +/// +/// This message should be sent by the admin public key +/// This admin key should sign the new sequencer public key +#[derive(NomReader, BinWriter, Clone, Debug, PartialEq, Eq)] +pub struct SetSequencer { + nonce: u32, + admin_public_key: PublicKey, + sequencer_public_key: PublicKey, + signature: Signature, +} + #[derive(NomReader, BinWriter, Debug, Clone, Eq, PartialEq)] pub enum SequencerMsg { Sequence(Sequence), + SetSequencer(SetSequencer), } #[derive(Debug, Clone, PartialEq, Eq)] @@ -117,6 +130,7 @@ mod tests { use crate::message::{Framed, SequencerMsg}; use super::{KernelMessage, Sequence}; + use crate::message::SetSequencer; use tezos_crypto_rs::hash::{SecretKeyEd25519, SeedEd25519}; use tezos_data_encoding::enc::BinWriter; use tezos_data_encoding::nom::NomReader; @@ -159,4 +173,33 @@ mod tests { assert_eq!(msg_read, sequence); } + + #[test] + fn test_set_sequencer_serialization() { + let (public_key, secret) = + key_pair("edsk3a5SDDdMWw3Q5hPiJwDXUosmZMTuKQkriPqY6UqtSfdLifpZbB"); + let signature = secret.sign([0x0]).expect("sign should work"); + + let sequence = KernelMessage::Sequencer(Framed { + destination: SmartRollupAddress::from_b58check("sr1EzLeJYWrvch2Mhvrk1nUVYrnjGQ8A4qdb") + .expect("decoding should work"), + payload: SequencerMsg::SetSequencer(SetSequencer { + nonce: 0, + admin_public_key: public_key.clone(), + sequencer_public_key: public_key, + signature, + }), + }); + + // Serializing + let mut bin: Vec = Vec::new(); + sequence.bin_write(&mut bin).unwrap(); + + println!("{:?}", bin); + + // Deserializing + let (_, msg_read) = KernelMessage::nom_read(&bin).expect("deserialization should work"); + + assert_eq!(msg_read, sequence); + } } -- GitLab From 4aa26908307e510bf9d3689c488e0dc3bdc07137 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Date: Thu, 8 Jun 2023 11:05:17 +0200 Subject: [PATCH 5/6] kernel/sequencer: add message definition --- src/kernel_sequencer/src/message.rs | 70 ++++++++++++++++++++++++++--- 1 file changed, 64 insertions(+), 6 deletions(-) diff --git a/src/kernel_sequencer/src/message.rs b/src/kernel_sequencer/src/message.rs index eb27d9902ff2..3f66b461da2e 100644 --- a/src/kernel_sequencer/src/message.rs +++ b/src/kernel_sequencer/src/message.rs @@ -2,7 +2,12 @@ // // SPDX-License-Identifier: MIT -use nom::{bytes::complete::tag, combinator::map, sequence::preceded}; +use nom::{ + branch::alt, + bytes::complete::tag, + combinator::{all_consuming, map}, + sequence::preceded, +}; use tezos_crypto_rs::hash::Signature; use tezos_data_encoding::{ enc::{self, BinResult, BinWriter}, @@ -62,6 +67,7 @@ pub enum SequencerMsg { #[derive(Debug, Clone, PartialEq, Eq)] pub enum KernelMessage { Sequencer(Framed), + DelayedMessage(Vec), } impl

NomReader for Framed

@@ -105,10 +111,16 @@ where impl NomReader for KernelMessage { fn nom_read(input: &[u8]) -> NomResult { - map( - preceded(tag([1]), Framed::::nom_read), - KernelMessage::Sequencer, - )(input) + all_consuming(alt(( + all_consuming(map( + preceded(tag([1]), Framed::::nom_read), + KernelMessage::Sequencer, + )), + map( + |bytes: &[u8]| Ok(([].as_slice(), bytes.to_vec())), + KernelMessage::DelayedMessage, + ), + )))(input) } } @@ -120,6 +132,7 @@ impl BinWriter for KernelMessage { enc::put_byte(&0x01, output); sequencer_framed_msg.bin_write(output)?; } + KernelMessage::DelayedMessage(message) => enc::put_bytes(message, output), } Ok(()) } @@ -132,7 +145,7 @@ mod tests { use super::{KernelMessage, Sequence}; use crate::message::SetSequencer; use tezos_crypto_rs::hash::{SecretKeyEd25519, SeedEd25519}; - use tezos_data_encoding::enc::BinWriter; + use tezos_data_encoding::enc::{self, BinWriter}; use tezos_data_encoding::nom::NomReader; use tezos_smart_rollup_encoding::public_key::PublicKey; use tezos_smart_rollup_encoding::smart_rollup::SmartRollupAddress; @@ -202,4 +215,49 @@ mod tests { assert_eq!(msg_read, sequence); } + + #[test] + fn test_user_message_serialization() { + let sequence = KernelMessage::DelayedMessage(vec![0x01, 0x0, 0x01, 0x02, 0x02]); + + // Serializing + let mut bin: Vec = Vec::new(); + sequence.bin_write(&mut bin).unwrap(); + + // Deserializing + let (_, msg_read) = KernelMessage::nom_read(&bin).expect("deserialization should work"); + + assert_eq!(msg_read, sequence); + } + + #[test] + fn test_message_default() { + let (_, secret) = key_pair("edsk3a5SDDdMWw3Q5hPiJwDXUosmZMTuKQkriPqY6UqtSfdLifpZbB"); + let signature = secret.sign([0x0]).expect("sign should work"); + + let sequence = KernelMessage::Sequencer(Framed { + destination: SmartRollupAddress::from_b58check("sr1EzLeJYWrvch2Mhvrk1nUVYrnjGQ8A4qdb") + .expect("decoding should work"), + payload: SequencerMsg::Sequence(Sequence { + nonce: 0, + signature, + delayed_messages: 5, + messages: Vec::default(), + }), + }); + + // Serializing + let mut bin: Vec = Vec::new(); + sequence.bin_write(&mut bin).unwrap(); + enc::put_bytes(&[0x01, 0x02, 0x03, 0x04], &mut bin); + + println!("{:?}", bin); + + // Deserializing + let (remaining, msg_read) = + KernelMessage::nom_read(&bin).expect("deserialization should work"); + + assert!(remaining.is_empty()); + assert_eq!(msg_read, KernelMessage::DelayedMessage(bin)) + } } -- GitLab From 0a595985289fcdf091670238ff93558fbf02e3fa Mon Sep 17 00:00:00 2001 From: Pierre-Louis Date: Tue, 16 May 2023 13:48:13 +0200 Subject: [PATCH 6/6] kernel/sequencer: handle the different messages --- src/kernel_sequencer/src/delayed_inbox.rs | 64 +++++++++++++++++++++-- src/kernel_sequencer/src/message.rs | 10 +++- 2 files changed, 68 insertions(+), 6 deletions(-) diff --git a/src/kernel_sequencer/src/delayed_inbox.rs b/src/kernel_sequencer/src/delayed_inbox.rs index 43a3c1f3ae2e..c545cda2befd 100644 --- a/src/kernel_sequencer/src/delayed_inbox.rs +++ b/src/kernel_sequencer/src/delayed_inbox.rs @@ -3,13 +3,18 @@ // // SPDX-License-Identifier: MIT +use tezos_data_encoding::nom::NomReader; +use tezos_smart_rollup_encoding::smart_rollup::SmartRollupAddress; use tezos_smart_rollup_host::{ input::Message, - metadata::RollupMetadata, + metadata::{RollupMetadata, RAW_ROLLUP_ADDRESS_SIZE}, runtime::{Runtime, RuntimeError}, }; -use crate::routing::FilterBehavior; +use crate::{ + message::{Framed, KernelMessage, Sequence, SequencerMsg, SetSequencer}, + routing::FilterBehavior, +}; /// Return a message from the inbox /// @@ -30,10 +35,61 @@ pub fn read_input( None => return Ok(None), // No more messages to be processed Some(msg) => { let payload = msg.as_ref(); - if filter_behavior.predicate(payload, &raw_rollup_address) { - return Ok(Some(msg)); // The message is needed by the kernel so it's returned + let message = KernelMessage::nom_read(payload); + match message { + Err(_) => {} + Ok((_, message)) => match message { + KernelMessage::Sequencer(Framed { + destination, + payload: SequencerMsg::Sequence(sequence), + }) => handle_sequence_message(sequence, destination, &raw_rollup_address), + KernelMessage::Sequencer(Framed { + destination, + payload: SequencerMsg::SetSequencer(set_sequence), + }) => handle_set_sequencer_message( + set_sequence, + destination, + &raw_rollup_address, + ), + KernelMessage::DelayedMessage(user_message) => { + handle_message(user_message, filter_behavior, &raw_rollup_address) + } + }, } } } } } + +/// Handle Sequence message +fn handle_sequence_message( + _sequence: Sequence, + destination: SmartRollupAddress, + rollup_address: &[u8; RAW_ROLLUP_ADDRESS_SIZE], +) { + if destination.hash().as_ref() == rollup_address { + // process the sequence + } +} + +fn handle_set_sequencer_message( + _set_sequencer: SetSequencer, + destination: SmartRollupAddress, + rollup_address: &[u8; RAW_ROLLUP_ADDRESS_SIZE], +) { + if destination.hash().as_ref() == rollup_address { + // process the set sequencer message + } +} + +/// Handle messages +fn handle_message( + user_message: Vec, + filter_behavior: FilterBehavior, + rollup_address: &[u8; RAW_ROLLUP_ADDRESS_SIZE], +) { + // Check if the message should be included in the delayed inbox + if filter_behavior.predicate(user_message.as_ref(), rollup_address) { + // add the message to the delayed inbox + } +} diff --git a/src/kernel_sequencer/src/message.rs b/src/kernel_sequencer/src/message.rs index 3f66b461da2e..18e96a878090 100644 --- a/src/kernel_sequencer/src/message.rs +++ b/src/kernel_sequencer/src/message.rs @@ -13,7 +13,8 @@ use tezos_data_encoding::{ enc::{self, BinResult, BinWriter}, nom::{NomReader, NomResult}, }; -use tezos_smart_rollup_encoding::{public_key::PublicKey, smart_rollup::SmartRollupAddress}; +use tezos_smart_rollup_encoding::public_key::PublicKey; +use tezos_smart_rollup_encoding::smart_rollup::SmartRollupAddress; /// Framing protocol v0 /// @@ -36,7 +37,12 @@ pub struct Bytes { /// Sequence of messages sent by the sequencer /// -/// The sequence contains the delayed messages and the messages sent by the user to the sequencer +/// The sequence contains the number of messages +/// that should be processed from the delayed inbox +/// and the messages from the sequencer +/// +/// The delayed messages will be processed first +/// And then the messages will be processed #[derive(NomReader, BinWriter, Clone, Debug, PartialEq, Eq)] pub struct Sequence { nonce: u32, -- GitLab