From 6c0a5050cf8d133004340561fb96f11f609db00b Mon Sep 17 00:00:00 2001 From: Gilad Chase Date: Thu, 14 Nov 2024 13:12:18 +0200 Subject: [PATCH] feat(l1_provider): implement `proposal_start` --- Cargo.lock | 1 + crates/starknet_l1_provider/Cargo.toml | 3 ++ crates/starknet_l1_provider/src/errors.rs | 6 ++- .../src/l1_provider_tests.rs | 17 ++++++++ crates/starknet_l1_provider/src/lib.rs | 40 ++++++++++++++++--- 5 files changed, 60 insertions(+), 7 deletions(-) create mode 100644 crates/starknet_l1_provider/src/l1_provider_tests.rs diff --git a/Cargo.lock b/Cargo.lock index d3bea91a1f..8b7dd9f744 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10328,6 +10328,7 @@ dependencies = [ name = "starknet_l1_provider" version = "0.0.0" dependencies = [ + "assert_matches", "papyrus_base_layer", "starknet_api", "thiserror", diff --git a/crates/starknet_l1_provider/Cargo.toml b/crates/starknet_l1_provider/Cargo.toml index f9ac23e999..2340234fcb 100644 --- a/crates/starknet_l1_provider/Cargo.toml +++ b/crates/starknet_l1_provider/Cargo.toml @@ -10,5 +10,8 @@ papyrus_base_layer.workspace = true starknet_api.workspace = true thiserror.workspace = true +[dev-dependencies] +assert_matches.workspace = true + [lints] workspace = true diff --git a/crates/starknet_l1_provider/src/errors.rs b/crates/starknet_l1_provider/src/errors.rs index 487dc62696..9c319d71eb 100644 --- a/crates/starknet_l1_provider/src/errors.rs +++ b/crates/starknet_l1_provider/src/errors.rs @@ -1,6 +1,8 @@ use papyrus_base_layer::ethereum_base_layer_contract::EthereumBaseLayerError; use thiserror::Error; +use crate::ProviderState; + #[derive(Error, Debug)] pub enum L1ProviderError { #[error(transparent)] @@ -11,8 +13,8 @@ pub enum L1ProviderError { GetTransactionsInPendingState, #[error("`get_txs` while in validate state")] GetTransactionConsensusBug, - #[error("Can not set state: {0}")] - UnexpectedState(String), + #[error("Cannot transition from {from} to {to}")] + UnexpectedProviderState { from: ProviderState, to: ProviderState }, #[error("`validate_tx` called while in proposal state")] ValidateTransactionConsensusBug, } diff --git a/crates/starknet_l1_provider/src/l1_provider_tests.rs b/crates/starknet_l1_provider/src/l1_provider_tests.rs new file mode 100644 index 0000000000..0b9c5a3d2b --- /dev/null +++ b/crates/starknet_l1_provider/src/l1_provider_tests.rs @@ -0,0 +1,17 @@ +use assert_matches::assert_matches; + +use crate::errors::L1ProviderError::UnexpectedProviderState; +use crate::{L1Provider, ProviderState}; + +#[test] +fn proposal_start_errors() { + // Setup. + let mut l1_provider = L1Provider::default(); + + // Test + l1_provider.proposal_start().unwrap(); + assert_matches!( + l1_provider.proposal_start().unwrap_err(), + UnexpectedProviderState { from: ProviderState::Propose, to: ProviderState::Propose } + ); +} diff --git a/crates/starknet_l1_provider/src/lib.rs b/crates/starknet_l1_provider/src/lib.rs index 10fda6bf7c..3c2c7788c3 100644 --- a/crates/starknet_l1_provider/src/lib.rs +++ b/crates/starknet_l1_provider/src/lib.rs @@ -1,5 +1,7 @@ pub mod errors; +use std::fmt; + use starknet_api::executable_transaction::L1HandlerTransaction; use starknet_api::transaction::TransactionHash; @@ -7,8 +9,13 @@ use crate::errors::L1ProviderError; type L1ProviderResult = Result; +#[cfg(test)] +#[path = "l1_provider_tests.rs"] +pub mod l1_provider_tests; + // TODO: optimistic proposer support, will add later to keep things simple, but the design here // is compatible with it. +#[derive(Debug, Default)] pub struct L1Provider { unconsumed_l1_not_in_l2_block_txs: PendingMessagesFromL1, state: ProviderState, @@ -53,8 +60,9 @@ impl L1Provider { todo!("Sets internal state as validate, returns error if state is Pending.") } - pub fn proposal_start(&mut self) { - todo!("Similar to validation_start.") + pub fn proposal_start(&mut self) -> L1ProviderResult<()> { + self.state = self.state.transition_to_propose()?; + Ok(()) } /// Simple recovery from L1 and L2 reorgs by reseting the service, which rewinds L1 and L2 @@ -81,6 +89,7 @@ impl L1Provider { } } +#[derive(Debug, Default)] struct PendingMessagesFromL1; impl PendingMessagesFromL1 { @@ -90,7 +99,7 @@ impl PendingMessagesFromL1 { } /// Current state of the provider, where pending means: idle, between proposal/validation cycles. -#[derive(Debug, Default)] +#[derive(Debug, Default, Clone, Copy)] pub enum ProviderState { #[default] Pending, @@ -99,8 +108,14 @@ pub enum ProviderState { } impl ProviderState { - fn _transition_to_propose(self) -> L1ProviderResult { - todo!() + fn transition_to_propose(self) -> L1ProviderResult { + match self { + ProviderState::Pending => Ok(ProviderState::Propose), + _ => Err(L1ProviderError::UnexpectedProviderState { + from: self, + to: ProviderState::Propose, + }), + } } fn _transition_to_validate(self) -> L1ProviderResult { @@ -110,6 +125,21 @@ impl ProviderState { fn _transition_to_pending(self) -> L1ProviderResult { todo!() } + + pub fn as_str(&self) -> &str { + match self { + ProviderState::Pending => "Pending", + ProviderState::Propose => "Propose", + ProviderState::Validate => "Validate", + } + } +} + +impl fmt::Display for ProviderState { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_str(self.as_str()) + } } +#[derive(Debug)] pub struct L1ProviderConfig;