From c378ed0c543654893ff9e04de07e517facc98476 Mon Sep 17 00:00:00 2001 From: Krisztian Kovacs Date: Fri, 31 Jan 2025 14:59:05 +0100 Subject: [PATCH] feat(rpc/v06): re-add block getters For `starknet_getBlockWithTxHashes` and `starknet_getBlockWithTxs` the only difference compared to v07 is that the block header and pending block header types are missing L1 data gas and L1 DA mode fields. This change also adds some rudimentary tests for testing the serialization of the block header for all the different JSON-RPC versions we're supporting. Closes: #2554 --- crates/rpc/src/dto/block.rs | 260 ++++++++++++++++++++++++++++++++---- crates/rpc/src/lib.rs | 2 - crates/rpc/src/v06.rs | 2 + 3 files changed, 234 insertions(+), 30 deletions(-) diff --git a/crates/rpc/src/dto/block.rs b/crates/rpc/src/dto/block.rs index 7f195b69e5..82a90a406b 100644 --- a/crates/rpc/src/dto/block.rs +++ b/crates/rpc/src/dto/block.rs @@ -52,13 +52,24 @@ impl crate::dto::SerializeForVersion for pathfinder_common::BlockHeader { }, )?; serializer.serialize_field("starknet_version", &self.starknet_version.to_string())?; - serializer.serialize_field( - "l1_data_gas_price", - &ResourcePrice { - price_in_wei: self.eth_l1_data_gas_price, - price_in_fri: self.strk_l1_data_gas_price, - }, - )?; + + if serializer.version >= RpcVersion::V07 { + serializer.serialize_field( + "l1_data_gas_price", + &ResourcePrice { + price_in_wei: self.eth_l1_data_gas_price, + price_in_fri: self.strk_l1_data_gas_price, + }, + )?; + serializer.serialize_field( + "l1_da_mode", + &match self.l1_da_mode { + L1DataAvailabilityMode::Blob => "BLOB", + L1DataAvailabilityMode::Calldata => "CALLDATA", + }, + )?; + } + if serializer.version == RpcVersion::V08 { serializer.serialize_field( "l2_gas_price", @@ -68,13 +79,7 @@ impl crate::dto::SerializeForVersion for pathfinder_common::BlockHeader { }, )?; } - serializer.serialize_field( - "l1_da_mode", - &match self.l1_da_mode { - L1DataAvailabilityMode::Blob => "BLOB", - L1DataAvailabilityMode::Calldata => "CALLDATA", - }, - )?; + serializer.end() } } @@ -96,13 +101,24 @@ impl crate::dto::SerializeForVersion for starknet_gateway_types::reply::PendingB }, )?; serializer.serialize_field("starknet_version", &self.starknet_version.to_string())?; - serializer.serialize_field( - "l1_data_gas_price", - &ResourcePrice { - price_in_wei: self.l1_data_gas_price.price_in_wei, - price_in_fri: self.l1_data_gas_price.price_in_fri, - }, - )?; + + if serializer.version >= RpcVersion::V07 { + serializer.serialize_field( + "l1_data_gas_price", + &ResourcePrice { + price_in_wei: self.l1_data_gas_price.price_in_wei, + price_in_fri: self.l1_data_gas_price.price_in_fri, + }, + )?; + serializer.serialize_field( + "l1_da_mode", + &match self.l1_da_mode { + starknet_gateway_types::reply::L1DataAvailabilityMode::Blob => "BLOB", + starknet_gateway_types::reply::L1DataAvailabilityMode::Calldata => "CALLDATA", + }, + )?; + } + if serializer.version == RpcVersion::V08 { serializer.serialize_field( "l2_gas_price", @@ -112,13 +128,7 @@ impl crate::dto::SerializeForVersion for starknet_gateway_types::reply::PendingB }, )?; } - serializer.serialize_field( - "l1_da_mode", - &match self.l1_da_mode { - starknet_gateway_types::reply::L1DataAvailabilityMode::Blob => "BLOB", - starknet_gateway_types::reply::L1DataAvailabilityMode::Calldata => "CALLDATA", - }, - )?; + serializer.end() } } @@ -154,3 +164,197 @@ impl crate::dto::SerializeForVersion for Reorg { serializer.end() } } + +#[cfg(test)] +mod tests { + use pathfinder_common::macro_prelude::*; + use pathfinder_common::{ + BlockHeader, + BlockNumber, + BlockTimestamp, + GasPrice, + SequencerAddress, + StarknetVersion, + }; + use serde_json::json; + use starknet_gateway_types::reply::{GasPrices, PendingBlock}; + + use crate::dto::{SerializeForVersion, Serializer}; + use crate::RpcVersion; + + #[test] + fn block_header() { + let header = BlockHeader::builder() + .number(BlockNumber::new_or_panic(1000000)) + .timestamp(BlockTimestamp::new_or_panic(1734728886)) + .sequencer_address(sequencer_address!( + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8" + )) + .state_commitment(state_commitment!( + "0x7bd9798e3b03e6dfc12db132d48e4a0dc75202aa6a9b57bc40e3796137bd617" + )) + .parent_hash(block_hash!( + "0x6084bda2cd3247aa11364404f7918001e82a7567cfe0b949fa6a7f3d4b4099f" + )) + .l1_da_mode(pathfinder_common::L1DataAvailabilityMode::Blob) + .eth_l1_gas_price(GasPrice(0x34795c87c)) + .strk_l1_gas_price(GasPrice(0x59425e9d6d3c)) + .eth_l1_data_gas_price(GasPrice(0x85257107)) + .strk_l1_data_gas_price(GasPrice(0xe27be612da1)) + .eth_l2_gas_price(GasPrice(0x12345678)) + .strk_l2_gas_price(GasPrice(0x23456789)) + .starknet_version(StarknetVersion::new(0, 13, 3, 0)) + .finalize_with_hash(block_hash!( + "0x7256dde30ae68f43f3def9ce2a4433dd3de11b630d4f84336891bad8fe4127e" + )); + + pretty_assertions_sorted::assert_eq!( + header.serialize(Serializer::new(RpcVersion::V06)).unwrap(), + json!({ + "block_hash": "0x7256dde30ae68f43f3def9ce2a4433dd3de11b630d4f84336891bad8fe4127e", + "block_number": 1000000, + "l1_gas_price": { + "price_in_fri": "0x59425e9d6d3c", + "price_in_wei": "0x34795c87c" + }, + "new_root": "0x7bd9798e3b03e6dfc12db132d48e4a0dc75202aa6a9b57bc40e3796137bd617", + "parent_hash": "0x6084bda2cd3247aa11364404f7918001e82a7567cfe0b949fa6a7f3d4b4099f", + "sequencer_address": "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "starknet_version": "0.13.3", + "timestamp": 1734728886, + }) + ); + + pretty_assertions_sorted::assert_eq!( + header.serialize(Serializer::new(RpcVersion::V07)).unwrap(), + json!({ + "block_hash": "0x7256dde30ae68f43f3def9ce2a4433dd3de11b630d4f84336891bad8fe4127e", + "block_number": 1000000, + "l1_da_mode": "BLOB", + "l1_data_gas_price": { + "price_in_fri": "0xe27be612da1", + "price_in_wei": "0x85257107" + }, + "l1_gas_price": { + "price_in_fri": "0x59425e9d6d3c", + "price_in_wei": "0x34795c87c" + }, + "new_root": "0x7bd9798e3b03e6dfc12db132d48e4a0dc75202aa6a9b57bc40e3796137bd617", + "parent_hash": "0x6084bda2cd3247aa11364404f7918001e82a7567cfe0b949fa6a7f3d4b4099f", + "sequencer_address": "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "starknet_version": "0.13.3", + "timestamp": 1734728886, + }) + ); + + pretty_assertions_sorted::assert_eq!( + header.serialize(Serializer::new(RpcVersion::V08)).unwrap(), + json!({ + "block_hash": "0x7256dde30ae68f43f3def9ce2a4433dd3de11b630d4f84336891bad8fe4127e", + "block_number": 1000000, + "l1_da_mode": "BLOB", + "l1_data_gas_price": { + "price_in_fri": "0xe27be612da1", + "price_in_wei": "0x85257107" + }, + "l1_gas_price": { + "price_in_fri": "0x59425e9d6d3c", + "price_in_wei": "0x34795c87c" + }, + "l2_gas_price": { + "price_in_fri": "0x23456789", + "price_in_wei": "0x12345678" + }, + "new_root": "0x7bd9798e3b03e6dfc12db132d48e4a0dc75202aa6a9b57bc40e3796137bd617", + "parent_hash": "0x6084bda2cd3247aa11364404f7918001e82a7567cfe0b949fa6a7f3d4b4099f", + "sequencer_address": "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "starknet_version": "0.13.3", + "timestamp": 1734728886, + }) + ); + } + + #[test] + fn pending_block() { + let pending = PendingBlock { + l1_gas_price: GasPrices { + price_in_wei: GasPrice(0x34795c87c), + price_in_fri: GasPrice(0x59425e9d6d3c), + }, + l1_data_gas_price: GasPrices { + price_in_wei: GasPrice(0x85257107), + price_in_fri: GasPrice(0xe27be612da1), + }, + l2_gas_price: GasPrices { + price_in_wei: GasPrice(0x12345678), + price_in_fri: GasPrice(0x23456789), + }, + parent_hash: block_hash!( + "0x6084bda2cd3247aa11364404f7918001e82a7567cfe0b949fa6a7f3d4b4099f" + ), + sequencer_address: sequencer_address!( + "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8" + ), + timestamp: BlockTimestamp::new_or_panic(1734728886), + starknet_version: StarknetVersion::new(0, 13, 3, 0), + l1_da_mode: starknet_gateway_types::reply::L1DataAvailabilityMode::Blob, + ..Default::default() + }; + + pretty_assertions_sorted::assert_eq!( + pending.serialize(Serializer::new(RpcVersion::V06)).unwrap(), + json!({ + "l1_gas_price": { + "price_in_fri": "0x59425e9d6d3c", + "price_in_wei": "0x34795c87c" + }, + "parent_hash": "0x6084bda2cd3247aa11364404f7918001e82a7567cfe0b949fa6a7f3d4b4099f", + "sequencer_address": "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "starknet_version": "0.13.3", + "timestamp": 1734728886, + }) + ); + + pretty_assertions_sorted::assert_eq!( + pending.serialize(Serializer::new(RpcVersion::V07)).unwrap(), + json!({ + "l1_da_mode": "BLOB", + "l1_data_gas_price": { + "price_in_fri": "0xe27be612da1", + "price_in_wei": "0x85257107" + }, + "l1_gas_price": { + "price_in_fri": "0x59425e9d6d3c", + "price_in_wei": "0x34795c87c" + }, + "parent_hash": "0x6084bda2cd3247aa11364404f7918001e82a7567cfe0b949fa6a7f3d4b4099f", + "sequencer_address": "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "starknet_version": "0.13.3", + "timestamp": 1734728886, + }) + ); + + pretty_assertions_sorted::assert_eq!( + pending.serialize(Serializer::new(RpcVersion::V08)).unwrap(), + json!({ + "l1_da_mode": "BLOB", + "l1_data_gas_price": { + "price_in_fri": "0xe27be612da1", + "price_in_wei": "0x85257107" + }, + "l1_gas_price": { + "price_in_fri": "0x59425e9d6d3c", + "price_in_wei": "0x34795c87c" + }, + "l2_gas_price": { + "price_in_fri": "0x23456789", + "price_in_wei": "0x12345678" + }, + "parent_hash": "0x6084bda2cd3247aa11364404f7918001e82a7567cfe0b949fa6a7f3d4b4099f", + "sequencer_address": "0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", + "starknet_version": "0.13.3", + "timestamp": 1734728886, + }) + ); + } +} diff --git a/crates/rpc/src/lib.rs b/crates/rpc/src/lib.rs index 8e1b67bba6..3a10de7492 100644 --- a/crates/rpc/src/lib.rs +++ b/crates/rpc/src/lib.rs @@ -966,8 +966,6 @@ mod tests { "/rpc/v0_6", "v06/starknet_api_openrpc.json", &[ - "starknet_getBlockWithTxHashes", - "starknet_getBlockWithTxs", "starknet_getStateUpdate", "starknet_getTransactionReceipt", "starknet_getTransactionStatus", diff --git a/crates/rpc/src/v06.rs b/crates/rpc/src/v06.rs index 2d0d53e0b0..8fdd5ce5e6 100644 --- a/crates/rpc/src/v06.rs +++ b/crates/rpc/src/v06.rs @@ -7,6 +7,8 @@ pub fn register_routes() -> RpcRouterBuilder { .register("starknet_blockHashAndNumber", crate::method::block_hash_and_number) .register("starknet_chainId", crate::method::chain_id) .register("starknet_getBlockTransactionCount", crate::method::get_block_transaction_count) + .register("starknet_getBlockWithTxHashes", crate::method::get_block_with_tx_hashes) + .register("starknet_getBlockWithTxs", crate::method::get_block_with_txs) .register("starknet_getClassHashAt", crate::method::get_class_hash_at) .register("starknet_getNonce", crate::method::get_nonce) .register("starknet_getStorageAt", crate::method::get_storage_at)