Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(starknet_l1_provider): add start_block #3226

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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,
}
Loading