Skip to content

Commit 55a0f9a

Browse files
giladchaseGilad Chase
andauthored
feat(starknet_l1_provider): add start_block (#3226)
- replace preivous API with the agreed upon `start_block`. - added state setter for use of start_block; commit_block will have a different setter. Co-authored-by: Gilad Chase <gilad@starkware.com>
1 parent 67dc49e commit 55a0f9a

File tree

8 files changed

+57
-73
lines changed

8 files changed

+57
-73
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/starknet_l1_provider/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ validator.workspace = true
2626
alloy-node-bindings.workspace = true
2727
alloy-primitives.workspace = true
2828
assert_matches.workspace = true
29+
itertools.workspace = true
2930
pretty_assertions.workspace = true
3031
starknet_api = { workspace = true, features = ["testing"] }
3132

crates/starknet_l1_provider/src/l1_provider.rs

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use starknet_api::block::BlockNumber;
22
use starknet_api::executable_transaction::L1HandlerTransaction;
33
use starknet_api::transaction::TransactionHash;
44
use starknet_l1_provider_types::errors::L1ProviderError;
5-
use starknet_l1_provider_types::{Event, L1ProviderResult, ValidationStatus};
5+
use starknet_l1_provider_types::{Event, L1ProviderResult, SessionState, ValidationStatus};
66
use starknet_sequencer_infra::component_definitions::ComponentStarter;
77

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

26+
pub fn start_block(
27+
&mut self,
28+
height: BlockNumber,
29+
state: SessionState,
30+
) -> L1ProviderResult<()> {
31+
self.validate_height(height)?;
32+
self.state = state.into();
33+
self.tx_manager.start_block();
34+
Ok(())
35+
}
36+
2637
/// Retrieves up to `n_txs` transactions that have yet to be proposed or accepted on L2.
2738
pub fn get_txs(
2839
&mut self,
@@ -65,22 +76,10 @@ impl L1Provider {
6576
)
6677
}
6778

68-
pub fn validation_start(&mut self, height: BlockNumber) -> L1ProviderResult<()> {
69-
self.validate_height(height)?;
70-
self.state = self.state.transition_to_validate()?;
71-
Ok(())
72-
}
73-
7479
pub fn process_l1_events(&mut self, _events: Vec<Event>) -> L1ProviderResult<()> {
7580
todo!()
7681
}
7782

78-
pub fn proposal_start(&mut self, height: BlockNumber) -> L1ProviderResult<()> {
79-
self.validate_height(height)?;
80-
self.state = self.state.transition_to_propose()?;
81-
Ok(())
82-
}
83-
8483
/// Simple recovery from L1 and L2 reorgs by reseting the service, which rewinds L1 and L2
8584
/// information.
8685
pub async fn handle_reorg(&mut self) -> L1ProviderResult<()> {

crates/starknet_l1_provider/src/l1_provider_tests.rs

Lines changed: 21 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,21 @@
11
use assert_matches::assert_matches;
2+
use itertools::Itertools;
23
use pretty_assertions::assert_eq;
34
use starknet_api::block::BlockNumber;
45
use starknet_api::test_utils::l1_handler::executable_l1_handler_tx;
56
use starknet_api::transaction::TransactionHash;
67
use starknet_api::{l1_handler_tx_args, tx_hash};
78
use starknet_l1_provider_types::errors::L1ProviderError;
9+
use starknet_l1_provider_types::SessionState::{
10+
self,
11+
Propose as ProposeSession,
12+
Validate as ValidateSession,
13+
};
814
use starknet_l1_provider_types::ValidationStatus;
915

1016
use crate::l1_provider::L1Provider;
1117
use crate::test_utils::L1ProviderContentBuilder;
12-
use crate::ProviderState::{Pending, Propose, Uninitialized, Validate};
18+
use crate::ProviderState;
1319

1420
macro_rules! tx {
1521
(tx_hash: $tx_hash:expr) => {{
@@ -27,7 +33,7 @@ fn get_txs_happy_flow() {
2733
let txs = [tx!(tx_hash: 0), tx!(tx_hash: 1), tx!(tx_hash: 2)];
2834
let mut l1_provider = L1ProviderContentBuilder::new()
2935
.with_txs(txs.clone())
30-
.with_state(Propose)
36+
.with_state(ProviderState::Propose)
3137
.build_into_l1_provider();
3238

3339
// Test.
@@ -43,7 +49,7 @@ fn validate_happy_flow() {
4349
let mut l1_provider = L1ProviderContentBuilder::new()
4450
.with_txs([tx!(tx_hash: 1)])
4551
.with_committed([tx_hash!(2)])
46-
.with_state(Validate)
52+
.with_state(ProviderState::Validate)
4753
.build_into_l1_provider();
4854

4955
// Test.
@@ -70,7 +76,7 @@ fn validate_happy_flow() {
7076
fn pending_state_errors() {
7177
// Setup.
7278
let mut l1_provider = L1ProviderContentBuilder::new()
73-
.with_state(Pending)
79+
.with_state(ProviderState::Pending)
7480
.with_txs([tx!(tx_hash: 1)])
7581
.build_into_l1_provider();
7682

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

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

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

107113
#[test]
108-
fn proposal_start_errors() {
114+
fn proposal_start_multiple_proposals_same_height() {
109115
// Setup.
110116
let mut l1_provider =
111-
L1ProviderContentBuilder::new().with_state(Pending).build_into_l1_provider();
112-
// Test.
113-
l1_provider.proposal_start(BlockNumber(1)).unwrap();
114-
115-
assert_eq!(
116-
l1_provider.proposal_start(BlockNumber(1)).unwrap_err(),
117-
L1ProviderError::unexpected_transition(Propose, Propose)
118-
);
119-
assert_eq!(
120-
l1_provider.validation_start(BlockNumber(1)).unwrap_err(),
121-
L1ProviderError::unexpected_transition(Propose, Validate)
122-
);
123-
}
124-
125-
#[test]
126-
fn validation_start_errors() {
127-
// Setup.
128-
let mut l1_provider =
129-
L1ProviderContentBuilder::new().with_state(Pending).build_into_l1_provider();
130-
131-
// Test.
132-
l1_provider.validation_start(BlockNumber(1)).unwrap();
133-
134-
assert_eq!(
135-
l1_provider.validation_start(BlockNumber(1)).unwrap_err(),
136-
L1ProviderError::unexpected_transition(Validate, Validate)
137-
);
138-
assert_eq!(
139-
l1_provider.proposal_start(BlockNumber(1)).unwrap_err(),
140-
L1ProviderError::unexpected_transition(Validate, Propose)
141-
);
117+
L1ProviderContentBuilder::new().with_state(ProviderState::Pending).build_into_l1_provider();
118+
119+
// Test all single-height combinations.
120+
const SESSION_TYPES: [SessionState; 2] = [ProposeSession, ValidateSession];
121+
for (session_1, session_2) in SESSION_TYPES.into_iter().cartesian_product(SESSION_TYPES) {
122+
l1_provider.start_block(BlockNumber(1), session_1).unwrap();
123+
l1_provider.start_block(BlockNumber(1), session_2).unwrap();
124+
}
142125
}

crates/starknet_l1_provider/src/lib.rs

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,7 @@ use papyrus_config::converters::deserialize_milliseconds_to_duration;
2323
use papyrus_config::dumping::{ser_param, SerializeConfig};
2424
use papyrus_config::{ParamPath, ParamPrivacyInput, SerializedParam};
2525
use serde::{Deserialize, Serialize};
26-
use starknet_l1_provider_types::errors::L1ProviderError;
27-
use starknet_l1_provider_types::L1ProviderResult;
26+
use starknet_l1_provider_types::SessionState;
2827
use validator::Validate;
2928

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

4443
impl ProviderState {
45-
fn transition_to_propose(self) -> L1ProviderResult<Self> {
46-
match self {
47-
ProviderState::Pending => Ok(ProviderState::Propose),
48-
_ => Err(L1ProviderError::unexpected_transition(self, ProviderState::Propose)),
49-
}
50-
}
51-
52-
fn transition_to_validate(self) -> L1ProviderResult<Self> {
53-
match self {
54-
ProviderState::Pending => Ok(ProviderState::Validate),
55-
_ => Err(L1ProviderError::unexpected_transition(self, ProviderState::Validate)),
56-
}
57-
}
58-
59-
fn _transition_to_pending(self) -> L1ProviderResult<Self> {
60-
todo!()
61-
}
62-
6344
pub fn as_str(&self) -> &str {
6445
match self {
6546
ProviderState::Pending => "Pending",
@@ -70,6 +51,15 @@ impl ProviderState {
7051
}
7152
}
7253

54+
impl From<SessionState> for ProviderState {
55+
fn from(state: SessionState) -> Self {
56+
match state {
57+
SessionState::Propose => ProviderState::Propose,
58+
SessionState::Validate => ProviderState::Validate,
59+
}
60+
}
61+
}
62+
7363
impl std::fmt::Display for ProviderState {
7464
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
7565
f.write_str(self.as_str())

crates/starknet_l1_provider/src/soft_delete_index_map.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ impl SoftDeleteIndexMap {
6969
// every new tx is inserted to the map with key counter++ and the counter is not reduced
7070
// when removing entries. Once the counter reaches u32::MAX/2 we recreate the DS in Theta(n).
7171
pub fn _commit(&mut self, tx_hashes: &[TransactionHash]) -> Vec<L1HandlerTransaction> {
72-
self._rollback_staging();
72+
self.rollback_staging();
7373
let tx_hashes: HashSet<_> = tx_hashes.iter().copied().collect();
7474
if tx_hashes.is_empty() {
7575
return Vec::new();
@@ -84,7 +84,7 @@ impl SoftDeleteIndexMap {
8484
}
8585

8686
/// Rolls back all staged transactions, converting them to unstaged.
87-
pub fn _rollback_staging(&mut self) {
87+
pub fn rollback_staging(&mut self) {
8888
for tx_hash in self.staged_txs.drain() {
8989
self.txs.entry(tx_hash).and_modify(|entry| entry.set_state(TxState::Unstaged));
9090
}

crates/starknet_l1_provider/src/transaction_manager.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ pub struct TransactionManager {
1212
}
1313

1414
impl TransactionManager {
15+
pub fn start_block(&mut self) {
16+
self.txs.rollback_staging();
17+
}
18+
1519
pub fn get_txs(&mut self, n_txs: usize) -> Vec<L1HandlerTransaction> {
1620
let mut txs = Vec::with_capacity(n_txs);
1721

crates/starknet_l1_provider_types/src/lib.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,3 +108,9 @@ pub enum Event {
108108
TransactionCancellationStarted(L1Event),
109109
TransactionConsumed(L1Event),
110110
}
111+
112+
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
113+
pub enum SessionState {
114+
Propose,
115+
Validate,
116+
}

0 commit comments

Comments
 (0)