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

test(katana): feeder gateway tests #3038

Merged
merged 3 commits into from
Feb 17, 2025
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
3 changes: 3 additions & 0 deletions Cargo.lock

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

Original file line number Diff line number Diff line change
Expand Up @@ -681,7 +681,7 @@ fn to_execution_resources(
katana_primitives::trace::ExecutionResources {
n_steps: resources.n_steps,
n_memory_holes: resources.n_memory_holes,
builtin_instance_counter: resources.builtin_instance_counter,
builtin_instance_counter: resources.builtin_instance_counter.into(),
}
}

Expand Down
3 changes: 3 additions & 0 deletions crates/katana/feeder-gateway/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,7 @@ tracing.workspace = true
url.workspace = true

[dev-dependencies]
rstest.workspace = true
serde_json.workspace = true
similar-asserts.workspace = true
tokio.workspace = true
16 changes: 8 additions & 8 deletions crates/katana/feeder-gateway/src/types/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,23 +23,23 @@ pub use receipt::*;
pub use transaction::*;

/// The contract class type returns by `/get_class_by_hash` endpoint.
#[derive(Debug, Deserialize)]
#[derive(Debug, PartialEq, Eq, Deserialize)]
#[serde(untagged)]
pub enum ContractClass {
Class(RpcSierraContractClass),
Legacy(LegacyContractClass),
}

/// The state update type returns by `/get_state_update` endpoint.
#[derive(Debug, Deserialize)]
#[derive(Debug, PartialEq, Eq, Deserialize)]
pub struct StateUpdate {
pub block_hash: Option<Felt>,
pub new_root: Option<Felt>,
pub old_root: Felt,
pub state_diff: StateDiff,
}

#[derive(Debug, Deserialize)]
#[derive(Debug, PartialEq, Eq, Deserialize)]
pub struct StateDiff {
pub storage_diffs: BTreeMap<ContractAddress, Vec<StorageDiff>>,
pub deployed_contracts: Vec<DeployedContract>,
Expand All @@ -49,26 +49,26 @@ pub struct StateDiff {
pub replaced_classes: Vec<DeployedContract>,
}

#[derive(Debug, Deserialize)]
#[derive(Debug, PartialEq, Eq, Deserialize)]
pub struct StorageDiff {
pub key: StorageKey,
pub value: StorageValue,
}

#[derive(Debug, Deserialize)]
#[derive(Debug, PartialEq, Eq, Deserialize)]
pub struct DeployedContract {
pub address: ContractAddress,
pub class_hash: Felt,
}

#[derive(Debug, Deserialize)]
#[derive(Debug, PartialEq, Eq, Deserialize)]
pub struct DeclaredContract {
pub class_hash: ClassHash,
pub compiled_class_hash: CompiledClassHash,
}

/// The state update type returns by `/get_state_update` endpoint, with `includeBlock=true`.
#[derive(Debug, Deserialize)]
#[derive(Debug, PartialEq, Eq, Deserialize)]
pub struct StateUpdateWithBlock {
pub state_update: StateUpdate,
pub block: Block,
Expand All @@ -78,7 +78,7 @@ pub struct StateUpdateWithBlock {
// the serde impl is different. So for now, lets just use starknet-rs types. The type isn't
// that complex anyway so the conversion is simple. But if we can use the primitive types, we
// should.
#[derive(Debug, Deserialize)]
#[derive(Debug, PartialEq, Eq, Deserialize)]
pub struct Block {
#[serde(default)]
pub block_hash: Option<BlockHash>,
Expand Down
171 changes: 162 additions & 9 deletions crates/katana/feeder-gateway/src/types/receipt.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,175 @@
use std::collections::HashMap;

use katana_primitives::receipt::{Event, MessageToL1};
use katana_primitives::Felt;
use katana_primitives::trace::{self, BuiltinCounters, BuiltinName};
use katana_primitives::{eth, Felt};
use serde::Deserialize;
use starknet::providers::sequencer::models::{
ExecutionResources, L1ToL2Message, TransactionExecutionStatus,
};

#[derive(Debug, Deserialize)]
#[derive(Debug, PartialEq, Eq, Deserialize)]
pub struct ConfirmedReceipt {
pub transaction_hash: Felt,
pub transaction_index: u64,
#[serde(default)]
pub execution_status: Option<TransactionExecutionStatus>,
#[serde(default)]
pub execution_status: Option<ExecutionStatus>,
pub revert_error: Option<String>,
#[serde(default)]
pub execution_resources: Option<ExecutionResources>,
pub l1_to_l2_consumed_message: Option<L1ToL2Message>,
pub l2_to_l1_messages: Vec<MessageToL1>,
pub events: Vec<Event>,
pub actual_fee: Felt,
}

#[derive(Debug, PartialEq, Eq, Deserialize)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub enum ExecutionStatus {
Succeeded,
Reverted,
}

#[derive(Debug, PartialEq, Eq)]
pub struct ExecutionResources {
pub vm_resources: trace::ExecutionResources,
pub data_availability: Option<DataAvailabilityResources>,
}

#[derive(Debug, PartialEq, Eq, Deserialize)]
pub struct DataAvailabilityResources {
pub l1_gas: u64,
pub l1_data_gas: u64,
}

#[derive(Debug, PartialEq, Eq, Deserialize)]
pub struct L1ToL2Message {
/// The address of the Ethereum (L1) contract that sent the message.
pub from_address: eth::Address,
pub to_address: Felt,
pub selector: Felt,
pub payload: Vec<Felt>,
pub nonce: Option<Felt>,
}

// The reason why we implement `Deserialize` manually is because we want to avoid defining redundant
// types just because the format is different than the already existing types.
impl<'de> Deserialize<'de> for ExecutionResources {
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
struct BuiltinCounterHelper(BuiltinCounters);

impl<'de> Deserialize<'de> for BuiltinCounterHelper {
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
enum Field {
Ignore,
Valid(BuiltinName),
}

struct FieldVisitor;

impl<'de> serde::de::Visitor<'de> for FieldVisitor {
type Value = Field;

fn expecting(
&self,
formatter: &mut std::fmt::Formatter<'_>,
) -> std::fmt::Result {
write!(
formatter,
"a builtin type name: 'ecdsa_builtin', 'ec_op_builtin', \
'keccak_builtin', 'output_builtin', 'bitwise_builtin', \
'pedersen_builtin', 'poseidon_builtin', 'range_check_builtin', \
'segment_arena_builtin'"
)
}

Check warning on line 79 in crates/katana/feeder-gateway/src/types/receipt.rs

View check run for this annotation

Codecov / codecov/patch

crates/katana/feeder-gateway/src/types/receipt.rs#L68-L79

Added lines #L68 - L79 were not covered by tests

fn visit_str<E: serde::de::Error>(self, v: &str) -> Result<Self::Value, E> {
match v {
"ecdsa_builtin" => Ok(Field::Valid(BuiltinName::ecdsa)),
"ec_op_builtin" => Ok(Field::Valid(BuiltinName::ec_op)),
"keccak_builtin" => Ok(Field::Valid(BuiltinName::keccak)),
"output_builtin" => Ok(Field::Valid(BuiltinName::output)),
"bitwise_builtin" => Ok(Field::Valid(BuiltinName::bitwise)),
"pedersen_builtin" => Ok(Field::Valid(BuiltinName::pedersen)),
"poseidon_builtin" => Ok(Field::Valid(BuiltinName::poseidon)),
"range_check_builtin" => Ok(Field::Valid(BuiltinName::range_check)),
"segment_arena_builtin" => Ok(Field::Valid(BuiltinName::segment_arena)),
_ => Ok(Field::Ignore),
}
}
}

impl<'de> serde::Deserialize<'de> for Field {
#[inline]
fn deserialize<D: serde::Deserializer<'de>>(
deserializer: D,
) -> Result<Self, D::Error> {
serde::Deserializer::deserialize_identifier(deserializer, FieldVisitor)
}
}

struct Visitor;

impl<'de> serde::de::Visitor<'de> for Visitor {
type Value = BuiltinCounterHelper;

fn expecting(
&self,
formatter: &mut std::fmt::Formatter<'_>,
) -> std::fmt::Result {
write!(
formatter,
"an JSON object with builtin names as keys and instance counts as \
values"
)
}

Check warning on line 120 in crates/katana/feeder-gateway/src/types/receipt.rs

View check run for this annotation

Codecov / codecov/patch

crates/katana/feeder-gateway/src/types/receipt.rs#L111-L120

Added lines #L111 - L120 were not covered by tests

fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
where
A: serde::de::MapAccess<'de>,
{
let mut builtins: HashMap<BuiltinName, usize> = HashMap::new();
while let Some(key) = map.next_key::<Field>()? {
match key {
Field::Valid(builtin) => {
if builtins.contains_key(&builtin) {
return Err(
<A::Error as serde::de::Error>::duplicate_field(
builtin.to_str_with_suffix(),
),
);

Check warning on line 135 in crates/katana/feeder-gateway/src/types/receipt.rs

View check run for this annotation

Codecov / codecov/patch

crates/katana/feeder-gateway/src/types/receipt.rs#L131-L135

Added lines #L131 - L135 were not covered by tests
}

if let Some(counter) = map.next_value::<Option<u64>>()? {
builtins.insert(builtin, counter as usize);
}
}

Field::Ignore => {
let _ = map.next_value::<serde::de::IgnoredAny>()?;
}
}
}
Ok(BuiltinCounterHelper(BuiltinCounters::from(builtins)))
}
}

deserializer.deserialize_map(Visitor)
}
}

#[derive(Deserialize)]
pub struct Helper {
pub n_steps: usize,
pub n_memory_holes: usize,
pub builtin_instance_counter: BuiltinCounterHelper,
pub data_availability: Option<DataAvailabilityResources>,
}

let helper = Helper::deserialize(deserializer)?;

Ok(Self {
data_availability: helper.data_availability,
vm_resources: trace::ExecutionResources {
n_steps: helper.n_steps,
n_memory_holes: helper.n_memory_holes,
builtin_instance_counter: helper.builtin_instance_counter.0,
},
})
}
}
18 changes: 9 additions & 9 deletions crates/katana/feeder-gateway/src/types/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@
deserialize_optional_u128, deserialize_optional_u64, deserialize_u128, deserialize_u64,
};

#[derive(Debug, Deserialize)]
#[derive(Debug, PartialEq, Eq, Deserialize)]
pub struct ConfirmedTransaction {
#[serde(rename = "transaction_hash")]
pub hash: TxHash,
#[serde(flatten)]
pub tx: TypedTransaction,
}

#[derive(Debug, Deserialize)]
#[derive(Debug, PartialEq, Eq, Deserialize)]
#[serde(tag = "type", rename_all = "SCREAMING_SNAKE_CASE")]
pub enum TypedTransaction {
Deploy(DeployTx),
Expand All @@ -34,7 +34,7 @@
// different from the one in the `katana_primitives` crate. And changing the serde implementation in
// the `katana_primitives` crate would break the database format. So, we have to define the type
// again. But see if we can remove it once we're okay with breaking the database format.
#[derive(Debug)]
#[derive(Debug, PartialEq, Eq)]
pub enum DataAvailabilityMode {
L1,
L2,
Expand All @@ -58,22 +58,22 @@

// Same reason as `DataAvailabilityMode` above, this struct is also defined because the serde
// implementation of its primitive counterpart is different.
#[derive(Debug, Deserialize)]
#[derive(Debug, PartialEq, Eq, Deserialize)]

Check warning on line 61 in crates/katana/feeder-gateway/src/types/transaction.rs

View check run for this annotation

Codecov / codecov/patch

crates/katana/feeder-gateway/src/types/transaction.rs#L61

Added line #L61 was not covered by tests
pub struct ResourceBounds {
#[serde(deserialize_with = "deserialize_u64")]
pub max_amount: u64,
#[serde(deserialize_with = "deserialize_u128")]
pub max_price_per_unit: u128,
}

#[derive(Debug, Deserialize)]
#[derive(Debug, PartialEq, Eq, Deserialize)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub struct ResourceBoundsMapping {
pub l1_gas: ResourceBounds,
pub l2_gas: ResourceBounds,
}

#[derive(Debug, Deserialize)]
#[derive(Debug, PartialEq, Eq, Deserialize)]
pub struct RawL1HandlerTx {
/// The L1 to L2 message nonce.
pub nonce: Option<Nonce>,
Expand All @@ -87,7 +87,7 @@
pub entry_point_selector: Felt,
}

#[derive(Debug, Deserialize)]
#[derive(Debug, PartialEq, Eq, Deserialize)]

Check warning on line 90 in crates/katana/feeder-gateway/src/types/transaction.rs

View check run for this annotation

Codecov / codecov/patch

crates/katana/feeder-gateway/src/types/transaction.rs#L90

Added line #L90 was not covered by tests
pub struct RawInvokeTx {
// Alias for v0 transaction
#[serde(alias = "contract_address")]
Expand Down Expand Up @@ -118,7 +118,7 @@
pub version: Felt,
}

#[derive(Debug, Deserialize)]
#[derive(Debug, PartialEq, Eq, Deserialize)]

Check warning on line 121 in crates/katana/feeder-gateway/src/types/transaction.rs

View check run for this annotation

Codecov / codecov/patch

crates/katana/feeder-gateway/src/types/transaction.rs#L121

Added line #L121 was not covered by tests
pub struct RawDeclareTx {
pub sender_address: ContractAddress,
pub nonce: Felt,
Expand All @@ -144,7 +144,7 @@
pub version: Felt,
}

#[derive(Debug, Deserialize)]
#[derive(Debug, PartialEq, Eq, Deserialize)]

Check warning on line 147 in crates/katana/feeder-gateway/src/types/transaction.rs

View check run for this annotation

Codecov / codecov/patch

crates/katana/feeder-gateway/src/types/transaction.rs#L147

Added line #L147 was not covered by tests
pub struct RawDeployAccountTx {
pub nonce: Nonce,
pub signature: Vec<Felt>,
Expand Down
Loading
Loading