Skip to content

Commit

Permalink
chore(refactor): update so forked networks chainID is used and rename…
Browse files Browse the repository at this point in the history
… `fork-at` to fork-block-number` (#372)

* feat: make use of forked network chainID unless explicitly set by --chain-id arg

* fix: update test to reflect changes

* chore(refactor): update fork-at to reflect anvils fork-block-number and respects chainID during forking

* fix: add alias for cli change
  • Loading branch information
dutterbutter authored Nov 4, 2024
1 parent 43fe551 commit 1cb9d6b
Show file tree
Hide file tree
Showing 7 changed files with 81 additions and 31 deletions.
4 changes: 2 additions & 2 deletions docs/rustbook/src/usage/fork.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ This command starts the node, forking it from the latest block on the zkSync Sep
You also have the option to specify a custom http endpoint and a custom forking height, like so:

```sh
# Usage: era_test_node fork --fork-at <FORK_AT> <NETWORK>
era_test_node fork --fork-at 7000000 mainnet http://172.17.0.3:3060
# Usage: era_test_node fork --fork-block-number <BLOCK> <NETWORK>
era_test_node fork --fork-block-number 7000000 mainnet http://172.17.0.3:3060
```

## Sending network calls
Expand Down
10 changes: 8 additions & 2 deletions src/config/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,10 +128,16 @@ pub struct ForkArgs {
/// - testnet
/// - http://XXX:YY
pub network: String,
#[arg(long)]
// Fork at a given L2 miniblock height.
// If not set - will use the current finalized block from the network.
pub fork_at: Option<u64>,
#[arg(
long,
value_name = "BLOCK",
long_help = "Fetch state from a specific block number over a remote endpoint.",
requires = "fork",
alias = "fork-at"
)]
pub fork_block_number: Option<u64>,
}

#[derive(Debug, Parser)]
Expand Down
42 changes: 28 additions & 14 deletions src/fork.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,12 +127,13 @@ impl<S: ForkSource> ForkStorage<S> {
use_evm_emulator: bool,
override_chain_id: Option<u32>,
) -> Self {
let chain_id = fork
.as_ref()
.and_then(|d| d.overwrite_chain_id)
.unwrap_or(L2ChainId::from(
override_chain_id.unwrap_or(TEST_NODE_NETWORK_ID),
));
let chain_id = if let Some(override_id) = override_chain_id {
L2ChainId::from(override_id)
} else {
fork.as_ref()
.and_then(|d| d.overwrite_chain_id)
.unwrap_or(L2ChainId::from(TEST_NODE_NETWORK_ID))
};
tracing::info!("Starting network with chain id: {:?}", chain_id);

ForkStorage {
Expand Down Expand Up @@ -398,6 +399,8 @@ pub trait ForkSource {
pub struct ForkDetails {
// Source of the fork data (for example HttpForkSource)
pub fork_source: Box<dyn ForkSource + Send + Sync>,
// Chain ID of fork
pub chain_id: L2ChainId,
// Block number at which we forked (the next block to create is l1_block + 1)
pub l1_block: L1BatchNumber,
// The actual L2 block
Expand Down Expand Up @@ -453,6 +456,7 @@ pub fn supported_versions_to_string() -> String {
impl fmt::Debug for ForkDetails {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("ForkDetails")
.field("chain_id", &self.chain_id)
.field("l1_block", &self.l1_block)
.field("l2_block", &self.l2_block)
.field("l2_miniblock", &self.l2_miniblock)
Expand Down Expand Up @@ -524,6 +528,7 @@ impl ForkDetails {

Ok(ForkDetails {
fork_source: Box::new(HttpForkSource::new(url.to_owned(), cache_config.clone())),
chain_id: chain_id.unwrap_or_else(|| L2ChainId::from(TEST_NODE_NETWORK_ID)),
l1_block: l1_batch_number,
l2_block: block,
block_timestamp: block_details.base.timestamp,
Expand All @@ -545,12 +550,15 @@ impl ForkDetails {
/// Create a fork from a given network at a given height.
pub async fn from_network(
fork: &str,
fork_at: Option<u64>,
fork_block_number: Option<u64>,
cache_config: CacheConfig,
) -> eyre::Result<Self> {
let (network, client) = Self::fork_network_and_client(fork)?;
let l2_miniblock = if let Some(fork_at) = fork_at {
fork_at
let chain_id_u64 = client.chain_id().await?;
let chain_id = L2ChainId::from(chain_id_u64.as_u32());

let l2_miniblock = if let Some(fork_block_number) = fork_block_number {
fork_block_number
} else {
match client.get_block_number().await {
Ok(bn) => bn.as_u64(),
Expand All @@ -559,11 +567,12 @@ impl ForkDetails {
}
}
};

Self::from_network_and_miniblock_and_chain(
network,
client,
l2_miniblock,
None,
chain_id.into(),
cache_config,
)
.await
Expand Down Expand Up @@ -604,16 +613,18 @@ impl ForkDetails {
/// Return URL and HTTP client for `hardhat_reset`.
pub fn from_url(
url: String,
fork_at: Option<u64>,
fork_block_number: Option<u64>,
cache_config: CacheConfig,
) -> eyre::Result<Self> {
let parsed_url = SensitiveUrl::from_str(&url)?;
let builder = Client::http(parsed_url).map_err(|error| eyre!(error))?;
let client = builder.build();

block_on(async move {
let l2_miniblock = if let Some(fork_at) = fork_at {
fork_at
let chain_id_u64 = client.chain_id().await?;
let chain_id = L2ChainId::from(chain_id_u64.as_u32());
let l2_miniblock = if let Some(fork_block_number) = fork_block_number {
fork_block_number
} else {
client.get_block_number().await?.as_u64()
};
Expand All @@ -622,7 +633,7 @@ impl ForkDetails {
ForkNetwork::Other(url),
client,
l2_miniblock,
None,
chain_id.into(),
cache_config,
)
.await
Expand Down Expand Up @@ -736,6 +747,7 @@ mod tests {
DEFAULT_ESTIMATE_GAS_PRICE_SCALE_FACTOR, DEFAULT_ESTIMATE_GAS_SCALE_FACTOR,
DEFAULT_FAIR_PUBDATA_PRICE, DEFAULT_L2_GAS_PRICE,
};
use crate::node::TEST_NODE_NETWORK_ID;
use crate::{deps::InMemoryStorage, system_contracts, testing};

use super::{ForkDetails, ForkStorage};
Expand All @@ -758,6 +770,7 @@ mod tests {

let fork_details = ForkDetails {
fork_source: Box::new(external_storage),
chain_id: TEST_NODE_NETWORK_ID.into(),
l1_block: L1BatchNumber(1),
l2_block: zksync_types::api::Block::<TransactionVariant>::default(),
l2_miniblock: 1,
Expand Down Expand Up @@ -793,6 +806,7 @@ mod tests {
fork_source: Box::new(testing::ExternalStorage {
raw_storage: InMemoryStorage::default(),
}),
chain_id: TEST_NODE_NETWORK_ID.into(),
l1_block: L1BatchNumber(0),
l2_block: zksync_types::api::Block::<TransactionVariant>::default(),
l2_miniblock: 0,
Expand Down
4 changes: 3 additions & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,9 @@ async fn main() -> anyhow::Result<()> {
let fork_details = match command {
Command::Run => None,
Command::Fork(fork) => {
match ForkDetails::from_network(&fork.network, fork.fork_at, config.cache).await {
match ForkDetails::from_network(&fork.network, fork.fork_block_number, config.cache)
.await
{
Ok(fd) => Some(fd),
Err(error) => {
tracing::error!("cannot fork: {:?}", error);
Expand Down
1 change: 1 addition & 0 deletions src/node/in_memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1932,6 +1932,7 @@ mod tests {
let node: InMemoryNode<testing::ExternalStorage> = InMemoryNode::new(
Some(ForkDetails {
fork_source: Box::new(mock_db),
chain_id: TEST_NODE_NETWORK_ID.into(),
l1_block: L1BatchNumber(1),
l2_block: Block::default(),
l2_miniblock: 2,
Expand Down
24 changes: 19 additions & 5 deletions src/node/zks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1165,6 +1165,19 @@ mod tests {
serde_json::json!({
"jsonrpc": "2.0",
"id": 0,
"method": "eth_chainId",
}),
serde_json::json!({
"jsonrpc": "2.0",
"id": 0,
"result": "0x104",
}),
);

mock_server.expect(
serde_json::json!({
"jsonrpc": "2.0",
"id": 1,
"method": "zks_getBlockDetails",
"params": [1]
}),
Expand Down Expand Up @@ -1193,13 +1206,13 @@ mod tests {
"status": "verified",
"timestamp": 1000
},
"id": 0
"id": 1
}),
);
mock_server.expect(
serde_json::json!({
"jsonrpc": "2.0",
"id": 1,
"id": 2,
"method": "eth_getBlockByHash",
"params": ["0xdaa77426c30c02a43d9fba4e841a6556c524d47030762eb14dc4af897e605d9b", true]
}),
Expand Down Expand Up @@ -1231,7 +1244,7 @@ mod tests {
"transactionsRoot": "0x0000000000000000000000000000000000000000000000000000000000000000",
"uncles": []
},
"id": 1
"id": 2
}),
);
mock_server.expect(
Expand All @@ -1258,7 +1271,7 @@ mod tests {
mock_server.expect(
serde_json::json!({
"jsonrpc": "2.0",
"id": 2,
"id": 3,
"method": "zks_getFeeParams",
}),
serde_json::json!({
Expand All @@ -1277,7 +1290,7 @@ mod tests {
"l1_pubdata_price": 100780475095u64
}
},
"id": 2
"id": 3
}),
);

Expand All @@ -1291,6 +1304,7 @@ mod tests {
Default::default(),
Default::default(),
);

{
let inner = node.get_inner();
let writer = inner.write().unwrap();
Expand Down
27 changes: 20 additions & 7 deletions src/testing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,24 +61,37 @@ impl MockServer {
Expectation::matching(request::body(json_decoded(eq(serde_json::json!({
"jsonrpc": "2.0",
"id": 0,
"method": "eth_blockNumber",
"method": "eth_chainId",
})))))
.respond_with(json_encoded(serde_json::json!({
"jsonrpc": "2.0",
"id": 0,
"result": format!("{:#x}", block_config.number),
"result": "0x104",
}))),
);

server.expect(
Expectation::matching(request::body(json_decoded(eq(serde_json::json!({
"jsonrpc": "2.0",
"id": 1,
"method": "eth_blockNumber",
})))))
.respond_with(json_encoded(serde_json::json!({
"jsonrpc": "2.0",
"id": 1,
"result": format!("{:#x}", block_config.number),
}))),
);
server.expect(
Expectation::matching(request::body(json_decoded(eq(serde_json::json!({
"jsonrpc": "2.0",
"id": 2,
"method": "zks_getBlockDetails",
"params": [ block_config.number ],
})))))
.respond_with(json_encoded(serde_json::json!({
"jsonrpc": "2.0",
"id": 1,
"id": 2,
"result": {
"number": block_config.number,
"l1BatchNumber": 1,
Expand Down Expand Up @@ -107,13 +120,13 @@ impl MockServer {
server.expect(
Expectation::matching(request::body(json_decoded(eq(serde_json::json!({
"jsonrpc": "2.0",
"id": 2,
"id": 3,
"method": "eth_getBlockByHash",
"params": [format!("{:#x}", block_config.hash), true],
}))))).times(0..)
.respond_with(json_encoded(serde_json::json!({
"jsonrpc": "2.0",
"id": 2,
"id": 3,
"result": {
"hash": format!("{:#x}", block_config.hash),
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
Expand Down Expand Up @@ -151,7 +164,7 @@ impl MockServer {
server.expect(
Expectation::matching(request::body(json_decoded(eq(serde_json::json!({
"jsonrpc": "2.0",
"id": 3,
"id": 4,
"method": "zks_getFeeParams",
})))))
.respond_with(json_encoded(serde_json::json!(
Expand All @@ -171,7 +184,7 @@ impl MockServer {
"l1_pubdata_price": 100780475095u64
}
},
"id": 3
"id": 4
}))),
);

Expand Down

0 comments on commit 1cb9d6b

Please sign in to comment.