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

Update of getBlockWithTxHashes and getStateUpdate #461

Merged
merged 12 commits into from
May 9, 2024
24 changes: 23 additions & 1 deletion crates/starknet-devnet-core/src/blocks/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ use starknet_api::stark_felt;
use starknet_rs_core::types::{BlockId, BlockTag};
use starknet_types::contract_address::ContractAddress;
use starknet_types::felt::{BlockHash, Felt, TransactionHash};
use starknet_types::rpc::block::{BlockHeader as TypesBlockHeader, ResourcePrice};
use starknet_types::rpc::block::{
BlockHeader as TypesBlockHeader, PendingBlockHeader as TypesPendingBlockHeader, ResourcePrice,
};
use starknet_types::traits::HashProducer;

use crate::constants::STARKNET_VERSION;
Expand Down Expand Up @@ -172,6 +174,26 @@ pub struct StarknetBlock {
pub(crate) status: BlockStatus,
}

impl From<&StarknetBlock> for TypesPendingBlockHeader {
FabijanC marked this conversation as resolved.
Show resolved Hide resolved
fn from(value: &StarknetBlock) -> Self {
Self {
parent_hash: value.parent_hash(),
sequencer_address: value.sequencer_address(),
timestamp: value.timestamp(),
starknet_version: STARKNET_VERSION.to_string(),
l1_gas_price: ResourcePrice {
price_in_fri: value.header.l1_gas_price.price_in_fri.0.into(),
price_in_wei: value.header.l1_gas_price.price_in_wei.0.into(),
},
l1_data_gas_price: ResourcePrice {
price_in_fri: value.header.l1_data_gas_price.price_in_fri.0.into(),
price_in_wei: value.header.l1_data_gas_price.price_in_wei.0.into(),
},
l1_da_mode: value.header.l1_da_mode,
}
}
}

impl From<&StarknetBlock> for TypesBlockHeader {
fn from(value: &StarknetBlock) -> Self {
Self {
Expand Down
81 changes: 52 additions & 29 deletions crates/starknet-devnet-server/src/api/json_rpc/endpoints.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use starknet_core::error::{Error, StateError};
use starknet_rs_core::types::{BlockId as ImportedBlockId, MsgFromL1};
use starknet_rs_core::types::{BlockId as ImportedBlockId, BlockTag, MsgFromL1};
use starknet_types::contract_address::ContractAddress;
use starknet_types::felt::{ClassHash, TransactionHash};
use starknet_types::patricia_key::PatriciaKey;
use starknet_types::rpc::block::{Block, BlockHeader, BlockId};
use starknet_types::rpc::state::StateUpdate;
use starknet_types::rpc::block::{Block, BlockHeader, BlockId, PendingBlock, PendingBlockHeader};
use starknet_types::rpc::state::{PendingStateUpdate, StateUpdate};
use starknet_types::rpc::transactions::{
BroadcastedTransaction, EventFilter, EventsChunk, FunctionCall, SimulationFlag,
};
Expand All @@ -24,21 +24,33 @@ impl JsonRpcHandler {

/// starknet_getBlockWithTxHashes
pub async fn get_block_with_tx_hashes(&self, block_id: BlockId) -> StrictRpcResult {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what about get_block_with_txs and get_block_with_receipts

let block =
self.api.starknet.read().await.get_block(block_id.as_ref()).map_err(
|err| match err {
Error::NoBlock => ApiError::BlockNotFound,
unknown_error => ApiError::StarknetDevnetError(unknown_error),
},
)?;
let starknet = self.api.starknet.read().await;

Ok(StarknetResponse::Block(Block {
status: *block.status(),
header: BlockHeader::from(&block),
transactions: starknet_types::rpc::transactions::Transactions::Hashes(
block.get_transactions().to_owned(),
),
}))
let block = starknet.get_block(block_id.as_ref()).map_err(|err| match err {
Error::NoBlock => ApiError::BlockNotFound,
unknown_error => ApiError::StarknetDevnetError(unknown_error),
})?;

// StarknetBlock needs to be mapped to PendingBlock response only in blocks_on_demand mode
// and when block_id is pending
if starknet.config.blocks_on_demand
mikiw marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this logic could be moved in Starknet-core project

&& block_id == ImportedBlockId::Tag(BlockTag::Pending).into()
{
Ok(StarknetResponse::PendingBlock(PendingBlock {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

StarknetResponse::Block can receive an enum as its inner property. For example:

enum StarknetResponse{
Block(Block)
}

enum Block {
Block,
PendingBlock
}

header: PendingBlockHeader::from(&block),
transactions: starknet_types::rpc::transactions::Transactions::Hashes(
block.get_transactions().to_owned(),
),
}))
} else {
Ok(StarknetResponse::Block(Block {
status: *block.status(),
header: BlockHeader::from(&block),
transactions: starknet_types::rpc::transactions::Transactions::Hashes(
block.get_transactions().to_owned(),
),
}))
}
}

/// starknet_getBlockWithTxs
Expand Down Expand Up @@ -71,22 +83,33 @@ impl JsonRpcHandler {

/// starknet_getStateUpdate
pub async fn get_state_update(&self, block_id: BlockId) -> StrictRpcResult {
let starknet = self.api.starknet.read().await;

let state_update =
self.api.starknet.read().await.block_state_update(block_id.as_ref()).map_err(
|err| match err {
Error::NoBlock => ApiError::BlockNotFound,
unknown_error => ApiError::StarknetDevnetError(unknown_error),
},
)?;
starknet.block_state_update(block_id.as_ref()).map_err(|err| match err {
Error::NoBlock => ApiError::BlockNotFound,
unknown_error => ApiError::StarknetDevnetError(unknown_error),
})?;

let state_diff = state_update.state_diff.into();

Ok(StarknetResponse::StateUpdate(StateUpdate {
block_hash: state_update.block_hash,
new_root: state_update.new_root,
old_root: state_update.old_root,
state_diff,
}))
// StateUpdate needs to be mapped to PendingStateUpdate response only in blocks_on_demand
// mode and when block_id is pending
if starknet.config.blocks_on_demand
mikiw marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the same here, can be moved into Starknet-devnet-core crate.

&& block_id == ImportedBlockId::Tag(BlockTag::Pending).into()
{
Ok(StarknetResponse::PendingStateUpdate(PendingStateUpdate {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

StarknetResponse::StateUpdate enum variant can receive an enum as its inner part, similar to StarknetResponse::TransactionTrace

old_root: state_update.old_root,
state_diff,
}))
} else {
Ok(StarknetResponse::StateUpdate(StateUpdate {
block_hash: state_update.block_hash,
new_root: state_update.new_root,
old_root: state_update.old_root,
state_diff,
}))
}
}

/// starknet_getStorageAt
Expand Down
6 changes: 4 additions & 2 deletions crates/starknet-devnet-server/src/api/json_rpc/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ use models::{
use serde::{Deserialize, Serialize};
use starknet_rs_core::types::ContractClass as CodegenContractClass;
use starknet_types::felt::Felt;
use starknet_types::rpc::block::Block;
use starknet_types::rpc::block::{Block, PendingBlock};
use starknet_types::rpc::estimate_message_fee::{
EstimateMessageFeeRequestWrapper, FeeEstimateWrapper,
};
use starknet_types::rpc::state::StateUpdate;
use starknet_types::rpc::state::{PendingStateUpdate, StateUpdate};
use starknet_types::rpc::transaction_receipt::TransactionReceipt;
use starknet_types::rpc::transactions::{
BlockTransactionTrace, EventsChunk, SimulatedTransaction, TransactionTrace, TransactionWithHash,
Expand Down Expand Up @@ -353,7 +353,9 @@ impl std::fmt::Display for StarknetRequest {
#[serde(untagged)]
pub enum StarknetResponse {
Block(Block),
PendingBlock(PendingBlock),
StateUpdate(StateUpdate),
PendingStateUpdate(PendingStateUpdate),
Felt(Felt),
Transaction(TransactionWithHash),
TransactionReceiptByTransactionHash(Box<TransactionReceipt>),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,10 @@ mod tests {
StarknetRequest::BlockWithTransactionHashes(_)
| StarknetRequest::BlockWithFullTransactions(_)
| StarknetRequest::BlockWithReceipts(_) => {
assert!(matches!(sn_response, StarknetResponse::Block(_)));
assert!(matches!(
sn_response,
StarknetResponse::Block(_) | StarknetResponse::PendingBlock(_)
));
}
StarknetRequest::BlockHashAndNumber => {
assert!(matches!(sn_response, StarknetResponse::BlockHashAndNumber(_)));
Expand Down Expand Up @@ -282,7 +285,11 @@ mod tests {
));
}
StarknetRequest::StateUpdate(_) => {
assert!(matches!(sn_response, StarknetResponse::StateUpdate(_)));
assert!(matches!(
sn_response,
StarknetResponse::StateUpdate(_)
| StarknetResponse::PendingStateUpdate(_)
));
}
StarknetRequest::Syncing => {
assert!(matches!(sn_response, StarknetResponse::Syncing(_)));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@
{
"title": "Block with transaction hashes",
"$ref": "#/components/schemas/BLOCK_WITH_TX_HASHES"
},
{
"title": "Pending block with transaction hashes",
"$ref": "#/components/schemas/PENDING_BLOCK_WITH_TX_HASHES"
}
]
}
Expand Down Expand Up @@ -77,6 +81,10 @@
{
"title": "Block with transactions",
"$ref": "#/components/schemas/BLOCK_WITH_TXS"
},
{
"title": "Pending block with transactions",
"$ref": "#/components/schemas/PENDING_BLOCK_WITH_TXS"
}
]
}
Expand Down Expand Up @@ -110,6 +118,10 @@
{
"title": "Block with transactions",
"$ref": "#/components/schemas/BLOCK_WITH_RECEIPTS"
},
{
"title": "Pending block with transactions",
"$ref": "#/components/schemas/PENDING_BLOCK_WITH_RECEIPTS"
}
]
}
Expand Down Expand Up @@ -143,6 +155,10 @@
{
"title": "State update",
"$ref": "#/components/schemas/STATE_UPDATE"
},
{
"title": "Pending state update",
"$ref": "#/components/schemas/PENDING_STATE_UPDATE"
}
]
}
Expand Down Expand Up @@ -1488,6 +1504,68 @@
"starknet_version"
]
},
"PENDING_BLOCK_HEADER": {
"title": "Pending block header",
"type": "object",
"properties": {
"parent_hash": {
"title": "Parent hash",
"description": "The hash of this block's parent",
"$ref": "#/components/schemas/BLOCK_HASH"
},
"timestamp": {
"title": "Timestamp",
"description": "The time in which the block was created, encoded in Unix time",
"type": "integer",
"minimum": 0
},
"sequencer_address": {
"title": "Sequencer address",
"description": "The StarkNet identity of the sequencer submitting this block",
"$ref": "#/components/schemas/FELT"
},
"l1_gas_price": {
"title": "L1 gas price",
"description": "The price of l1 gas in the block",
"$ref": "#/components/schemas/RESOURCE_PRICE"
},
"l1_data_gas_price": {
"title": "L1 data gas price",
"description": "The price of l1 data gas in the block",
"$ref": "#/components/schemas/RESOURCE_PRICE"
},
"l1_da_mode": {
"title": "L1 da mode",
"type": "string",
"description": "specifies whether the data of this block is published via blob data or calldata",
"enum": [
"BLOB",
"CALLDATA"
]
},
"starknet_version": {
"title": "Starknet version",
"description": "Semver of the current Starknet protocol",
"type": "string"
}
},
"required": [
"parent_hash",
"timestamp",
"sequencer_address",
"l1_gas_price",
"l1_data_gas_price",
"l1_da_mode",
"starknet_version"
],
"not": {
"required": [
"block_hash",
"block_number",
"new_root"
]
}
},
"BLOCK_WITH_TX_HASHES": {
"title": "Block with transaction hashes",
"description": "The block object",
Expand Down
19 changes: 19 additions & 0 deletions crates/starknet-devnet-types/src/rpc/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,14 @@ pub struct Block {
pub transactions: Transactions,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct PendingBlock {
#[serde(flatten)]
pub header: PendingBlockHeader,
pub transactions: Transactions,
}

#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct BlockHeader {
Expand All @@ -84,6 +92,17 @@ pub struct BlockHeader {
pub l1_da_mode: L1DataAvailabilityMode,
}

#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct PendingBlockHeader {
FabijanC marked this conversation as resolved.
Show resolved Hide resolved
pub parent_hash: BlockHash,
pub sequencer_address: ContractAddress,
pub timestamp: BlockTimestamp,
pub starknet_version: String,
pub l1_gas_price: ResourcePrice,
pub l1_data_gas_price: ResourcePrice,
pub l1_da_mode: L1DataAvailabilityMode,
}
#[derive(Debug, Clone, Eq, PartialEq, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct ResourcePrice {
Expand Down
7 changes: 7 additions & 0 deletions crates/starknet-devnet-types/src/rpc/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,13 @@ pub struct StateUpdate {
pub state_diff: ThinStateDiff,
}

#[derive(Debug, Clone, Eq, PartialEq, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct PendingStateUpdate {
pub old_root: GlobalRootHex,
pub state_diff: ThinStateDiff,
}

#[derive(Debug, Default, Clone, Eq, PartialEq, Deserialize, Serialize)]
pub struct ThinStateDiff {
pub deployed_contracts: Vec<DeployedContract>,
Expand Down
7 changes: 4 additions & 3 deletions crates/starknet-devnet/tests/common/background_devnet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ use lazy_static::lazy_static;
use serde_json::json;
use starknet_core::constants::ETH_ERC20_CONTRACT_ADDRESS;
use starknet_rs_core::types::{
BlockId, BlockTag, BlockWithTxHashes, FieldElement, FunctionCall, MaybePendingBlockWithTxHashes,
BlockId, BlockTag, BlockWithTxHashes, FieldElement, FunctionCall,
MaybePendingBlockWithTxHashes, PendingBlockWithTxHashes,
};
use starknet_rs_core::utils::get_selector_from_name;
use starknet_rs_providers::jsonrpc::HttpTransport;
Expand Down Expand Up @@ -328,9 +329,9 @@ impl BackgroundDevnet {

pub async fn get_pending_block_with_tx_hashes(
&self,
) -> Result<BlockWithTxHashes, anyhow::Error> {
) -> Result<PendingBlockWithTxHashes, anyhow::Error> {
match self.json_rpc_client.get_block_with_tx_hashes(BlockId::Tag(BlockTag::Pending)).await {
Ok(MaybePendingBlockWithTxHashes::Block(b)) => Ok(b),
Ok(MaybePendingBlockWithTxHashes::PendingBlock(b)) => Ok(b),
other => Err(anyhow::format_err!("Got unexpected block: {other:?}")),
}
}
Expand Down
Loading