Skip to content
Merged
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
4 changes: 3 additions & 1 deletion crates/gateway/gateway-types/src/conversion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ use crate::{
impl From<katana_rpc_types::StateUpdate> for StateUpdate {
fn from(value: katana_rpc_types::StateUpdate) -> Self {
match value {
katana_rpc_types::StateUpdate::Update(update) => StateUpdate::Confirmed(update.into()),
katana_rpc_types::StateUpdate::Confirmed(update) => {
StateUpdate::Confirmed(update.into())
}
katana_rpc_types::StateUpdate::PreConfirmed(pre_confirmed) => {
StateUpdate::PreConfirmed(pre_confirmed.into())
}
Expand Down
9 changes: 5 additions & 4 deletions crates/gateway/gateway-types/src/state_update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ pub enum StateUpdate {
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct PreConfirmedStateUpdate {
/// The previous global state root
pub old_root: Felt,
pub old_root: Option<Felt>,
/// State diff
pub state_diff: StateDiff,
}
Expand Down Expand Up @@ -272,20 +272,21 @@ impl<'de> Deserialize<'de> for StateUpdate {
}
}

let old_root =
old_root.ok_or_else(|| serde::de::Error::missing_field("old_root"))?;
let state_diff =
state_diff.ok_or_else(|| serde::de::Error::missing_field("state_diff"))?;

// If block_hash and new_root are not present, deserialize as
// PreConfirmedStateUpdate
match (block_hash, new_root) {
(None, None) => Ok(StateUpdate::PreConfirmed(PreConfirmedStateUpdate {
(None, None, ..) => Ok(StateUpdate::PreConfirmed(PreConfirmedStateUpdate {
old_root,
state_diff,
})),

(Some(block_hash), Some(new_root)) => {
let old_root =
old_root.ok_or_else(|| serde::de::Error::missing_field("old_root"))?;

Ok(StateUpdate::Confirmed(ConfirmedStateUpdate {
block_hash,
new_root,
Expand Down
6 changes: 1 addition & 5 deletions crates/node/src/full/pending/provider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ use katana_gateway_types::TxTryFromError;
use katana_primitives::block::FinalityStatus;
use katana_primitives::fee::PriceUnit;
use katana_primitives::transaction::{TxHash, TxNumber, TxType, TxWithHash};
use katana_primitives::Felt;
use katana_provider::api::state::StateProvider;
use katana_rpc_server::starknet::{PendingBlockProvider, StarknetApiResult};
use katana_rpc_types::{
Expand Down Expand Up @@ -151,10 +150,7 @@ impl PendingBlockProvider for PreconfStateFactory {
&self,
) -> StarknetApiResult<Option<katana_rpc_types::PreConfirmedStateUpdate>> {
if let Some(state_diff) = self.state_updates() {
Ok(Some(PreConfirmedStateUpdate {
old_root: Felt::ZERO,
state_diff: state_diff.into(),
}))
Ok(Some(PreConfirmedStateUpdate { old_root: None, state_diff: state_diff.into() }))
} else {
Ok(None)
}
Expand Down
2 changes: 1 addition & 1 deletion crates/rpc/rpc-server/src/starknet/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -771,7 +771,7 @@ where
let state_update =
katana_rpc_types_builder::StateUpdateBuilder::new(block_id, provider)
.build()?
.map(StateUpdate::Update);
.map(StateUpdate::Confirmed);

StarknetApiResult::Ok(state_update)
})
Expand Down
50 changes: 28 additions & 22 deletions crates/rpc/rpc-server/src/utils/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,15 +97,15 @@ pub fn fetch_pending_events(

// process individual transactions in the block.
// the iterator will start with txn index == cursor.txn.idx
for (tx_idx, (tx_hash, events)) in pending_block
for (tx_idx, (tx_hash, tx_events)) in pending_block
.transactions
.iter()
.map(|receipt| (receipt.receipt.transaction_hash, receipt.receipt.receipt.events()))
.enumerate()
.skip(cursor.txn.idx)
{
if tx_idx == cursor.txn.idx {
match events.len().cmp(&cursor.txn.event) {
match tx_events.len().cmp(&cursor.txn.event) {
Ordering::Equal | Ordering::Greater => {}
Ordering::Less => continue,
}
Expand All @@ -119,7 +119,7 @@ pub fn fetch_pending_events(
None,
tx_idx,
tx_hash,
events,
tx_events,
filter,
chunk_size as usize,
buffer,
Expand Down Expand Up @@ -222,24 +222,24 @@ pub fn fetch_events_at_blocks(
Ok(None)
}

/// An iterator that yields events that match the given filters.
/// An iterator that yields events (with their original indices) that match the given filters.
#[derive(Debug)]
struct FilteredEvents<'a, I: Iterator<Item = &'a Event>> {
struct FilteredEvents<'a, I: Iterator<Item = (usize, &'a Event)>> {
iter: I,
filter: &'a Filter,
}

impl<'a, I: Iterator<Item = &'a Event>> FilteredEvents<'a, I> {
impl<'a, I: Iterator<Item = (usize, &'a Event)>> FilteredEvents<'a, I> {
fn new(iter: I, filter: &'a Filter) -> Self {
Self { iter, filter }
}
}

impl<'a, I: Iterator<Item = &'a Event>> Iterator for FilteredEvents<'a, I> {
type Item = &'a Event;
impl<'a, I: Iterator<Item = (usize, &'a Event)>> Iterator for FilteredEvents<'a, I> {
type Item = (usize, &'a Event);

fn next(&mut self) -> Option<Self::Item> {
for event in self.iter.by_ref() {
for (idx, event) in self.iter.by_ref() {
// Skip this event if there is an address filter but doesn't match the address of the
// event.
if self.filter.address.is_some_and(|addr| addr != event.from_address) {
Expand Down Expand Up @@ -271,7 +271,7 @@ impl<'a, I: Iterator<Item = &'a Event>> Iterator for FilteredEvents<'a, I> {
};

if is_matched {
return Some(event);
return Some((idx, event));
}
}

Expand Down Expand Up @@ -303,7 +303,7 @@ fn fetch_tx_events(
block_hash: Option<BlockHash>,
tx_idx: usize,
tx_hash: TxHash,
events: &[Event],
tx_events: &[Event],
filter: &Filter,
chunk_size: usize,
buffer: &mut Vec<EmittedEvent>,
Expand All @@ -312,18 +312,24 @@ fn fetch_tx_events(
// number of events we have taken.
let total_can_take = chunk_size.saturating_sub(buffer.len());

// Enumerate events first to preserve original indices, then filter.
// skip events according to the continuation token.
let filtered = FilteredEvents::new(events.iter(), filter)
.map(|e| EmittedEvent {
block_hash,
block_number,
keys: e.keys.clone(),
data: e.data.clone(),
transaction_hash: tx_hash,
from_address: e.from_address,
let filtered = FilteredEvents::new(tx_events.iter().enumerate(), filter)
.map(|(event_idx, e)| {
(
event_idx,
EmittedEvent {
block_hash,
block_number,
keys: e.keys.clone(),
data: e.data.clone(),
transaction_hash: tx_hash,
from_address: e.from_address,
transaction_index: Some(tx_idx as u64),
event_index: Some(event_idx as u64),
},
)
})
// enumerate so that we can keep track of the event's index in the transaction
.enumerate()
.skip(next_event_idx)
.take(total_can_take)
.collect::<Vec<_>>();
Expand All @@ -349,7 +355,7 @@ fn fetch_tx_events(
};

// if there are still more events that we haven't fetched yet for this tx.
if new_last_event < events.len() {
if new_last_event < tx_events.len() {
return Ok(Some(PartialCursor { idx: tx_idx, event: new_last_event }));
}
}
Expand Down
2 changes: 1 addition & 1 deletion crates/rpc/rpc-server/tests/forking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use url::Url;

mod common;

const SEPOLIA_URL: &str = "https://api.cartridge.gg/x/starknet/sepolia";
const SEPOLIA_URL: &str = "https://api.cartridge.gg/x/starknet/sepolia/rpc/v0_10";
const FORK_BLOCK_NUMBER: BlockNumber = 268_471;
const FORK_BLOCK_HASH: BlockHash =
felt!("0x208950cfcbba73ecbda1c14e4d58d66a8d60655ea1b9dcf07c16014ae8a93cd");
Expand Down
2 changes: 1 addition & 1 deletion crates/rpc/rpc-server/tests/starknet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ async fn declare_and_deploy_contract() {
// check state update includes class in declared_classes
let state_update = provider.get_state_update(BlockIdOrTag::Latest).await.unwrap();
match state_update {
StateUpdate::Update(update) => {
StateUpdate::Confirmed(update) => {
similar_asserts::assert_eq!(
update.state_diff.declared_classes,
BTreeMap::from_iter([(class_hash, compiled_class_hash)])
Expand Down
19 changes: 16 additions & 3 deletions crates/rpc/rpc-types/src/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ pub struct EventFilter {
#[serde(skip_serializing_if = "Option::is_none")]
pub address: Option<ContractAddress>,
/// The keys to filter over
///
/// Per key (by position), designate the possible values to be matched for events to be
/// returned. Empty array designates 'any' value
#[serde(skip_serializing_if = "Option::is_none")]
pub keys: Option<Vec<Vec<Felt>>>,
}
Expand Down Expand Up @@ -63,12 +66,22 @@ pub struct GetEventsResponse {
/// of transaction execution.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct EmittedEvent {
pub from_address: ContractAddress,
pub keys: Vec<Felt>,
pub data: Vec<Felt>,
/// The hash of the block in which the event was emitted.
#[serde(skip_serializing_if = "Option::is_none")]
pub block_hash: Option<BlockHash>,
/// The number of the block in which the event was emitted.
#[serde(skip_serializing_if = "Option::is_none")]
pub block_number: Option<BlockNumber>,
/// The hash of the transaction where the event was emitted.
pub transaction_hash: TxHash,
/// The index of the transaction in the block.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub transaction_index: Option<u64>,
/// The index of the event within the transaction.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub event_index: Option<u64>,
/// The address of the contract that emitted the event.
pub from_address: ContractAddress,
pub keys: Vec<Felt>,
pub data: Vec<Felt>,
}
4 changes: 2 additions & 2 deletions crates/rpc/rpc-types/src/state_update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@ use serde::{Deserialize, Deserializer, Serialize, Serializer};
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum StateUpdate {
Update(ConfirmedStateUpdate),
Confirmed(ConfirmedStateUpdate),
PreConfirmed(PreConfirmedStateUpdate),
}

/// State update of a pre-confirmed block.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct PreConfirmedStateUpdate {
/// The previous global state root
pub old_root: Felt,
pub old_root: Option<Felt>,
/// State diff
pub state_diff: StateDiff,
}
Expand Down
6 changes: 3 additions & 3 deletions crates/rpc/rpc-types/tests/state_update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ fn preconfirmed_state_update() {
let PreConfirmedStateUpdate { old_root, ref state_diff } = state_update;
assert_eq!(
old_root,
felt!("0x6a59de5353d4050a800fd240020d014653d950df357ffa14319ee809a65427a")
Some(felt!("0x6a59de5353d4050a800fd240020d014653d950df357ffa14319ee809a65427a"))
);
assert_eq!(state_diff.deprecated_declared_classes, BTreeSet::new());
assert_eq!(state_diff.replaced_classes, map!());
Expand Down Expand Up @@ -75,7 +75,7 @@ fn confirmed_state_update() {

let state_update: ConfirmedStateUpdate = serde_json::from_value(json.clone()).unwrap();
let as_enum: StateUpdate = serde_json::from_value(json.clone()).unwrap();
assert_matches!(as_enum, StateUpdate::Update(as_enum_update) => {
assert_matches!(as_enum, StateUpdate::Confirmed(as_enum_update) => {
similar_asserts::assert_eq!(as_enum_update, state_update);
});

Expand Down Expand Up @@ -143,7 +143,7 @@ fn v0_10_0_confirmed_state_update() {

let state_update: ConfirmedStateUpdate = serde_json::from_value(json.clone()).unwrap();
let as_enum: StateUpdate = serde_json::from_value(json.clone()).unwrap();
assert_matches!(as_enum, StateUpdate::Update(as_enum_update) => {
assert_matches!(as_enum, StateUpdate::Confirmed(as_enum_update) => {
similar_asserts::assert_eq!(as_enum_update, state_update);
});

Expand Down
2 changes: 1 addition & 1 deletion crates/storage/provider/provider/src/providers/fork/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ impl ForkedDb {
};

let state_update = self.backend.get_state_update(block_id)?.unwrap(); // should exist if block exist
let StateUpdate::Update(state_update) = state_update else { unreachable!() };
let StateUpdate::Confirmed(state_update) = state_update else { unreachable!() };

let header = Header {
parent_hash: block.parent_hash,
Expand Down
Loading