Skip to content

Commit e7407fe

Browse files
blockifier_reexecution: allow custom chain id
1 parent 5b0310b commit e7407fe

File tree

5 files changed

+63
-14
lines changed

5 files changed

+63
-14
lines changed

crates/apollo_gateway/src/errors.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -436,7 +436,8 @@ fn convert_sn_api_error(err: StarknetApiError) -> StarknetError {
436436
| StarknetApiError::BlockHashVersion { .. }
437437
| StarknetApiError::ParseSierraVersionError(..)
438438
| StarknetApiError::ResourceHexToFeltConversion(..)
439-
| StarknetApiError::OutOfRange { .. } => StarknetError {
439+
| StarknetApiError::OutOfRange { .. }
440+
| StarknetApiError::InvalidChainIdHex(..) => StarknetError {
440441
code: StarknetErrorCode::KnownErrorCode(KnownStarknetErrorCode::MalformedRequest),
441442
message: err.to_string(),
442443
},

crates/blockifier_reexecution/README.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,29 @@ The blockier reexecution crate is intended to verify blockifier changes do not b
77
## CLI Commands
88
Using the different CLI commands, it is possible to run reexecution tests in different modes, to download (permisionless) files for offline reexecution from the GC bucket, and to upload (permissioned) files for offline reexecution to the GC bucket.
99

10+
### Chain ID Option
11+
Commands that use RPC (`rpc-test`, `reexecute-single-tx`, `write-to-file`) accept optional chain ID arguments. If not provided, the chain ID is guessed from the node URL.
12+
13+
There are two mutually exclusive options for specifying the chain ID:
14+
15+
**Option 1: `-c/--chain-id` (enum)**
16+
For standard chain IDs, use the `-c` flag with one of the supported values:
17+
- `mainnet` - Starknet Mainnet (SN_MAIN)
18+
- `testnet` - Sepolia testnet (SN_SEPOLIA)
19+
- `integration` - Integration Sepolia (SN_INTEGRATION_SEPOLIA)
20+
21+
```
22+
cargo run --bin blockifier_reexecution rpc-test -n <node_url> -b <block_number> -c mainnet
23+
```
24+
25+
**Option 2: `--custom-chain-id` (hex string)**
26+
For custom/private networks, use the `--custom-chain-id` flag with a hex-encoded chain ID string:
27+
```
28+
cargo run --bin blockifier_reexecution rpc-test -n <node_url> -b <block_number> --custom-chain-id 0x505249564154455f534e
29+
```
30+
Note: The hex string is the ASCII encoding of the chain ID name. For example, `0x534e5f4d41494e` decodes to `SN_MAIN`.
31+
32+
1033
### Reexecution Modes
1134

1235
Reexecution can be run via CLI in the following modes:

crates/blockifier_reexecution/src/state_reader/cli.rs

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use std::fs::read_to_string;
33

44
use clap::{Args, Parser, Subcommand};
55
use starknet_api::block::BlockNumber;
6-
use starknet_api::core::ChainId;
6+
use starknet_api::core::{chain_id_from_hex_str, ChainId};
77

88
use crate::state_reader::errors::{ReexecutionError, ReexecutionResult};
99

@@ -38,22 +38,34 @@ impl From<SupportedChainId> for ChainId {
3838
}
3939

4040
#[derive(Clone, Debug, Args)]
41+
#[clap(group(
42+
clap::ArgGroup::new("chain_id_group")
43+
.args(&["chain_id", "custom_chain_id"])
44+
))]
4145
pub struct RpcArgs {
4246
/// Node url.
4347
#[clap(long, short = 'n')]
4448
pub node_url: String,
4549

4650
/// Optional chain ID (if not provided, it will be guessed from the node url).
51+
/// Supported values: mainnet, testnet, integration.
4752
#[clap(long, short = 'c')]
4853
pub chain_id: Option<SupportedChainId>,
54+
55+
/// Optional custom chain ID as hex string (e.g., "0x534e5f4d41494e").
56+
#[clap(long)]
57+
pub custom_chain_id: Option<String>,
4958
}
5059

5160
impl RpcArgs {
5261
pub fn parse_chain_id(&self) -> ChainId {
53-
self.chain_id
54-
.clone()
55-
.map(ChainId::from)
56-
.unwrap_or(guess_chain_id_from_node_url(self.node_url.as_str()).unwrap())
62+
if let Some(chain_id) = &self.chain_id {
63+
return chain_id.clone().into();
64+
}
65+
if let Some(hex_str) = &self.custom_chain_id {
66+
return chain_id_from_hex_str(hex_str).expect("Failed to parse hex chain id");
67+
}
68+
guess_chain_id_from_node_url(self.node_url.as_str()).unwrap()
5769
}
5870
}
5971

crates/starknet_api/src/core.rs

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use crate::crypto::utils::PublicKey;
1818
use crate::hash::{PoseidonHash, StarkHash};
1919
use crate::serde_utils::{BytesAsHex, PrefixedBytesAsHex};
2020
use crate::transaction::fields::{Calldata, ContractAddressSalt};
21-
use crate::{impl_from_through_intermediate, StarknetApiError};
21+
use crate::{impl_from_through_intermediate, StarknetApiError, StarknetApiResult};
2222

2323
/// Felt.
2424
pub fn ascii_as_felt(ascii_str: &str) -> Result<Felt, StarknetApiError> {
@@ -87,20 +87,31 @@ impl ChainId {
8787
}
8888
}
8989

90-
pub fn deserialize_chain_id_from_hex<'de, D>(deserializer: D) -> Result<ChainId, D::Error>
91-
where
92-
D: Deserializer<'de>,
93-
{
94-
let hex_str = String::deserialize(deserializer)?;
90+
/// Parses a hex string (e.g., "0x534e5f4d41494e") into a ChainId.
91+
pub fn chain_id_from_hex_str(hex_str: &str) -> StarknetApiResult<ChainId> {
9592
let chain_id_str =
9693
std::str::from_utf8(&hex::decode(hex_str.trim_start_matches("0x")).map_err(|e| {
97-
D::Error::custom(format!("Failed to decode the hex string {hex_str}. Error: {e:?}"))
94+
StarknetApiError::InvalidChainIdHex(format!(
95+
"Failed to decode the hex string {hex_str}. Error: {e:?}"
96+
))
9897
})?)
99-
.map_err(|e| D::Error::custom(format!("Failed to convert to UTF-8 string. Error: {e:?}")))?
98+
.map_err(|e| {
99+
StarknetApiError::InvalidChainIdHex(format!(
100+
"Failed to convert to UTF-8 string. Error: {e}"
101+
))
102+
})?
100103
.to_string();
101104
Ok(ChainId::from(chain_id_str))
102105
}
103106

107+
pub fn deserialize_chain_id_from_hex<'de, D>(deserializer: D) -> Result<ChainId, D::Error>
108+
where
109+
D: Deserializer<'de>,
110+
{
111+
let hex_str = String::deserialize(deserializer)?;
112+
chain_id_from_hex_str(&hex_str).map_err(D::Error::custom)
113+
}
114+
104115
/// The address of a contract, used for example in [StateDiff](`crate::state::StateDiff`),
105116
/// [DeclareTransaction](`crate::transaction::DeclareTransaction`), and
106117
/// [BlockHeader](`crate::block::BlockHeader`).

crates/starknet_api/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,8 @@ pub enum StarknetApiError {
8888
version {cairo_version:?}.", **declare_version
8989
)]
9090
ContractClassVersionMismatch { declare_version: TransactionVersion, cairo_version: u64 },
91+
#[error("Failed to parse chain ID from hex: {0}")]
92+
InvalidChainIdHex(String),
9193
#[error("Failed to parse Sierra version: {0}")]
9294
ParseSierraVersionError(String),
9395
#[error("Unsupported transaction type: {0}")]

0 commit comments

Comments
 (0)