Skip to content

Commit

Permalink
feat(starknet_l1_provider): add start_block
Browse files Browse the repository at this point in the history
- replace preivous API with the agreed upon `start_block`.
- added state setter for use of start_block; commit_block will have a
  different setter.
  • Loading branch information
Gilad Chase committed Jan 15, 2025
1 parent f737720 commit 0c97f87
Show file tree
Hide file tree
Showing 8 changed files with 57 additions and 73 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions crates/starknet_l1_provider/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ validator.workspace = true

[dev-dependencies]
assert_matches.workspace = true
itertools.workspace = true
pretty_assertions.workspace = true
starknet_api = { workspace = true, features = ["testing"] }

Expand Down
25 changes: 12 additions & 13 deletions crates/starknet_l1_provider/src/l1_provider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use starknet_api::block::BlockNumber;
use starknet_api::executable_transaction::L1HandlerTransaction;
use starknet_api::transaction::TransactionHash;
use starknet_l1_provider_types::errors::L1ProviderError;
use starknet_l1_provider_types::{Event, L1ProviderResult, ValidationStatus};
use starknet_l1_provider_types::{Event, L1ProviderResult, SessionState, ValidationStatus};
use starknet_sequencer_infra::component_definitions::ComponentStarter;

use crate::transaction_manager::TransactionManager;
Expand All @@ -23,6 +23,17 @@ impl L1Provider {
todo!("Init crawler in uninitialized_state from config, to initialize call `reset`.");
}

pub fn start_block(
&mut self,
height: BlockNumber,
state: SessionState,
) -> L1ProviderResult<()> {
self.validate_height(height)?;
self.state = state.into();
self.tx_manager.start_block();
Ok(())
}

/// Retrieves up to `n_txs` transactions that have yet to be proposed or accepted on L2.
pub fn get_txs(
&mut self,
Expand Down Expand Up @@ -65,22 +76,10 @@ impl L1Provider {
)
}

pub fn validation_start(&mut self, height: BlockNumber) -> L1ProviderResult<()> {
self.validate_height(height)?;
self.state = self.state.transition_to_validate()?;
Ok(())
}

pub fn process_l1_events(&mut self, _events: Vec<Event>) -> L1ProviderResult<()> {
todo!()
}

pub fn proposal_start(&mut self, height: BlockNumber) -> L1ProviderResult<()> {
self.validate_height(height)?;
self.state = self.state.transition_to_propose()?;
Ok(())
}

/// Simple recovery from L1 and L2 reorgs by reseting the service, which rewinds L1 and L2
/// information.
pub async fn handle_reorg(&mut self) -> L1ProviderResult<()> {
Expand Down
59 changes: 21 additions & 38 deletions crates/starknet_l1_provider/src/l1_provider_tests.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
use assert_matches::assert_matches;
use itertools::Itertools;
use pretty_assertions::assert_eq;
use starknet_api::block::BlockNumber;
use starknet_api::test_utils::l1_handler::executable_l1_handler_tx;
use starknet_api::transaction::TransactionHash;
use starknet_api::{l1_handler_tx_args, tx_hash};
use starknet_l1_provider_types::errors::L1ProviderError;
use starknet_l1_provider_types::SessionState::{
self,
Propose as ProposeSession,
Validate as ValidateSession,
};
use starknet_l1_provider_types::ValidationStatus;

use crate::l1_provider::L1Provider;
use crate::test_utils::L1ProviderContentBuilder;
use crate::ProviderState::{Pending, Propose, Uninitialized, Validate};
use crate::ProviderState;

macro_rules! tx {
(tx_hash: $tx_hash:expr) => {{
Expand All @@ -27,7 +33,7 @@ fn get_txs_happy_flow() {
let txs = [tx!(tx_hash: 0), tx!(tx_hash: 1), tx!(tx_hash: 2)];
let mut l1_provider = L1ProviderContentBuilder::new()
.with_txs(txs.clone())
.with_state(Propose)
.with_state(ProviderState::Propose)
.build_into_l1_provider();

// Test.
Expand All @@ -43,7 +49,7 @@ fn validate_happy_flow() {
let mut l1_provider = L1ProviderContentBuilder::new()
.with_txs([tx!(tx_hash: 1)])
.with_committed([tx_hash!(2)])
.with_state(Validate)
.with_state(ProviderState::Validate)
.build_into_l1_provider();

// Test.
Expand All @@ -70,7 +76,7 @@ fn validate_happy_flow() {
fn pending_state_errors() {
// Setup.
let mut l1_provider = L1ProviderContentBuilder::new()
.with_state(Pending)
.with_state(ProviderState::Pending)
.with_txs([tx!(tx_hash: 1)])
.build_into_l1_provider();

Expand All @@ -90,7 +96,7 @@ fn pending_state_errors() {
#[should_panic(expected = "Uninitialized L1 provider")]
fn uninitialized_get_txs() {
let mut uninitialized_l1_provider = L1Provider::default();
assert_eq!(uninitialized_l1_provider.state, Uninitialized);
assert_eq!(uninitialized_l1_provider.state, ProviderState::Uninitialized);

uninitialized_l1_provider.get_txs(1, BlockNumber(1)).unwrap();
}
Expand All @@ -99,44 +105,21 @@ fn uninitialized_get_txs() {
#[should_panic(expected = "Uninitialized L1 provider")]
fn uninitialized_validate() {
let mut uninitialized_l1_provider = L1Provider::default();
assert_eq!(uninitialized_l1_provider.state, Uninitialized);
assert_eq!(uninitialized_l1_provider.state, ProviderState::Uninitialized);

uninitialized_l1_provider.validate(TransactionHash::default(), BlockNumber(1)).unwrap();
}

#[test]
fn proposal_start_errors() {
fn proposal_start_multiple_proposals_same_height() {
// Setup.
let mut l1_provider =
L1ProviderContentBuilder::new().with_state(Pending).build_into_l1_provider();
// Test.
l1_provider.proposal_start(BlockNumber(1)).unwrap();

assert_eq!(
l1_provider.proposal_start(BlockNumber(1)).unwrap_err(),
L1ProviderError::unexpected_transition(Propose, Propose)
);
assert_eq!(
l1_provider.validation_start(BlockNumber(1)).unwrap_err(),
L1ProviderError::unexpected_transition(Propose, Validate)
);
}

#[test]
fn validation_start_errors() {
// Setup.
let mut l1_provider =
L1ProviderContentBuilder::new().with_state(Pending).build_into_l1_provider();

// Test.
l1_provider.validation_start(BlockNumber(1)).unwrap();

assert_eq!(
l1_provider.validation_start(BlockNumber(1)).unwrap_err(),
L1ProviderError::unexpected_transition(Validate, Validate)
);
assert_eq!(
l1_provider.proposal_start(BlockNumber(1)).unwrap_err(),
L1ProviderError::unexpected_transition(Validate, Propose)
);
L1ProviderContentBuilder::new().with_state(ProviderState::Pending).build_into_l1_provider();

// Test all single-height combinations.
const SESSION_TYPES: [SessionState; 2] = [ProposeSession, ValidateSession];
for (session_1, session_2) in SESSION_TYPES.into_iter().cartesian_product(SESSION_TYPES) {
l1_provider.start_block(BlockNumber(1), session_1).unwrap();
l1_provider.start_block(BlockNumber(1), session_2).unwrap();
}
}
30 changes: 10 additions & 20 deletions crates/starknet_l1_provider/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,7 @@ use papyrus_config::converters::deserialize_milliseconds_to_duration;
use papyrus_config::dumping::{ser_param, SerializeConfig};
use papyrus_config::{ParamPath, ParamPrivacyInput, SerializedParam};
use serde::{Deserialize, Serialize};
use starknet_l1_provider_types::errors::L1ProviderError;
use starknet_l1_provider_types::L1ProviderResult;
use starknet_l1_provider_types::SessionState;
use validator::Validate;

#[cfg(test)]
Expand All @@ -42,24 +41,6 @@ pub enum ProviderState {
}

impl ProviderState {
fn transition_to_propose(self) -> L1ProviderResult<Self> {
match self {
ProviderState::Pending => Ok(ProviderState::Propose),
_ => Err(L1ProviderError::unexpected_transition(self, ProviderState::Propose)),
}
}

fn transition_to_validate(self) -> L1ProviderResult<Self> {
match self {
ProviderState::Pending => Ok(ProviderState::Validate),
_ => Err(L1ProviderError::unexpected_transition(self, ProviderState::Validate)),
}
}

fn _transition_to_pending(self) -> L1ProviderResult<Self> {
todo!()
}

pub fn as_str(&self) -> &str {
match self {
ProviderState::Pending => "Pending",
Expand All @@ -70,6 +51,15 @@ impl ProviderState {
}
}

impl From<SessionState> for ProviderState {
fn from(state: SessionState) -> Self {
match state {
SessionState::Propose => ProviderState::Propose,
SessionState::Validate => ProviderState::Validate,
}
}
}

impl std::fmt::Display for ProviderState {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(self.as_str())
Expand Down
4 changes: 2 additions & 2 deletions crates/starknet_l1_provider/src/soft_delete_index_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ impl SoftDeleteIndexMap {
// every new tx is inserted to the map with key counter++ and the counter is not reduced
// when removing entries. Once the counter reaches u32::MAX/2 we recreate the DS in Theta(n).
pub fn _commit(&mut self, tx_hashes: &[TransactionHash]) -> Vec<L1HandlerTransaction> {
self._rollback_staging();
self.rollback_staging();
let tx_hashes: HashSet<_> = tx_hashes.iter().copied().collect();
if tx_hashes.is_empty() {
return Vec::new();
Expand All @@ -84,7 +84,7 @@ impl SoftDeleteIndexMap {
}

/// Rolls back all staged transactions, converting them to unstaged.
pub fn _rollback_staging(&mut self) {
pub fn rollback_staging(&mut self) {
for tx_hash in self.staged_txs.drain() {
self.txs.entry(tx_hash).and_modify(|entry| entry.set_state(TxState::Unstaged));
}
Expand Down
4 changes: 4 additions & 0 deletions crates/starknet_l1_provider/src/transaction_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ pub struct TransactionManager {
}

impl TransactionManager {
pub fn start_block(&mut self) {
self.txs.rollback_staging();
}

pub fn get_txs(&mut self, n_txs: usize) -> Vec<L1HandlerTransaction> {
let mut txs = Vec::with_capacity(n_txs);

Expand Down
6 changes: 6 additions & 0 deletions crates/starknet_l1_provider_types/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,3 +108,9 @@ pub enum Event {
TransactionCancellationStarted(L1Event),
TransactionConsumed(L1Event),
}

#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
pub enum SessionState {
Propose,
Validate,
}

0 comments on commit 0c97f87

Please sign in to comment.