Skip to content

Commit

Permalink
chore: merge main (#547)
Browse files Browse the repository at this point in the history
* refactor: reduce usage of `ForkStorage` outside `inner` module (#539)

* reduce usage of `ForkStorage` outside `inner` module

* adapt for zkos

* fix destination path (#541)

* fix: anvil-zksync able to start even if the port is busy (#542)

* fix: closes #512 - start instance even if port is busy

* chore: apply make lint:fix

* chore: refactor test to make use of anvil-zksync instance

* chore: remove no longer needed deps

* chore: remove no longer needed deps

* chore: bump actions/upload-artifact: v3 to v4 due to CI fail

* chore: bump actions/upload-artifact / download: v3 to v4 due to CI fail

* compilation fixes

---------

Co-authored-by: Daniyar Itegulov <[email protected]>
Co-authored-by: Nisheeth Barthwal <[email protected]>
Co-authored-by: Dustin Brickwood <[email protected]>
  • Loading branch information
4 people authored Jan 17, 2025
1 parent b38e6dc commit daa0b80
Show file tree
Hide file tree
Showing 28 changed files with 477 additions and 197 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/checks.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
name: lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Install Rust
uses: actions-rust-lang/setup-rust-toolchain@v1
with:
Expand All @@ -39,7 +39,7 @@ jobs:
matrix:
os: [ubuntu-latest, macos-latest]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4

- name: Install Rust
uses: actions-rust-lang/setup-rust-toolchain@v1
Expand All @@ -55,7 +55,7 @@ jobs:
tar -czf anvil-zksync-${{ matrix.os }}.tar.gz ./anvil-zksync*
- name: Upload artifact
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: anvil-zksync-${{ matrix.os }}.tar.gz
path: ./target/release/anvil-zksync-${{ matrix.os }}.tar.gz
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/e2e-docker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:

steps:
- name: Checkout code
uses: actions/checkout@v3
uses: actions/checkout@v4

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/e2e-rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ jobs:
os: [ ubuntu-latest, macos-latest ]
name: e2e-rust
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Download artifacts
uses: actions/download-artifact@v3
uses: actions/download-artifact@v4
with:
name: anvil-zksync-${{ matrix.os }}.tar.gz

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ jobs:
cache-dependency-path: 'e2e-tests/yarn.lock'

- name: Download artifacts
uses: actions/download-artifact@v3
uses: actions/download-artifact@v4
with:
name: anvil-zksync-${{ matrix.os }}.tar.gz

Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ jobs:
needs: [extract-version]
steps:
- name: Checkout sources
uses: actions/checkout@v3
uses: actions/checkout@v4

- name: Install Rust
uses: actions-rust-lang/setup-rust-toolchain@v1
Expand Down Expand Up @@ -99,7 +99,7 @@ jobs:
# This is required to share artifacts between different jobs
# =======================================================================
- name: Upload artifact
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: anvil-zksync-${{ needs.extract-version.outputs.VERSION }}-${{ matrix.arch }}.tar.gz
path: anvil-zksync-${{ needs.extract-version.outputs.VERSION }}-${{ matrix.arch }}.tar.gz
Expand All @@ -121,15 +121,15 @@ jobs:
steps:
# This is necessary for generating the changelog. It has to come before "Download Artifacts" or else it deletes the artifacts.
- name: Checkout sources
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
fetch-depth: 0

# ==============================
# Download artifacts
# ==============================
- name: Download artifacts
uses: actions/download-artifact@v3
uses: actions/download-artifact@v4

# ==============================
# Create release draft
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/spec.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ jobs:
runs-on: ubuntu-latest
name: spec
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
submodules: "recursive"

- name: Download artifacts
uses: actions/download-artifact@v3
uses: actions/download-artifact@v4
with:
name: anvil-zksync-ubuntu-latest.tar.gz

Expand Down
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ lint-fix:
cd e2e-tests && yarn && yarn lint:fix && yarn fmt:fix
cargo clippy --fix
cargo fmt
cd e2e-tests-rust && cargo fmt --all
cd e2e-tests-rust && cargo clippy --fix
cd spec-tests && cargo fmt --all
cd spec-tests && cargo clippy --fix

# Run unit tests for Rust code
test:
Expand Down
18 changes: 15 additions & 3 deletions crates/api_server/src/impls/anvil.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,11 +155,19 @@ impl AnvilNamespaceServer for AnvilNamespace {
}

async fn set_balance(&self, address: Address, balance: U256) -> RpcResult<bool> {
Ok(self.node.set_balance(address, balance).await)
Ok(self
.node
.set_balance(address, balance)
.await
.map_err(RpcError::from)?)
}

async fn set_nonce(&self, address: Address, nonce: U256) -> RpcResult<bool> {
Ok(self.node.set_nonce(address, nonce).await)
Ok(self
.node
.set_nonce(address, nonce)
.await
.map_err(RpcError::from)?)
}

async fn anvil_mine(&self, num_blocks: Option<U64>, interval: Option<U64>) -> RpcResult<()> {
Expand Down Expand Up @@ -203,7 +211,11 @@ impl AnvilNamespaceServer for AnvilNamespace {
}

async fn set_storage_at(&self, address: Address, slot: U256, value: U256) -> RpcResult<bool> {
Ok(self.node.set_storage_at(address, slot, value).await)
Ok(self
.node
.set_storage_at(address, slot, value)
.await
.map_err(RpcError::from)?)
}

async fn set_chain_id(&self, id: u32) -> RpcResult<()> {
Expand Down
22 changes: 13 additions & 9 deletions crates/api_server/src/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ impl NodeServerBuilder {
rpc
}

pub async fn build(self, addr: SocketAddr) -> NodeServer {
pub async fn build(self, addr: SocketAddr) -> Result<NodeServer, String> {
let cors_layers = tower::util::option_layer(self.cors_enabled.then(|| {
// `CorsLayer` adds CORS-specific headers to responses but does not do filtering by itself.
// CORS relies on browsers respecting server's access list response headers.
Expand All @@ -88,14 +88,18 @@ impl NodeServerBuilder {
)
.set_rpc_middleware(RpcServiceBuilder::new().rpc_logger(100));

let server = server_builder.build(addr).await.unwrap();
let local_addr = server.local_addr().unwrap();
let rpc = Self::default_rpc(self.node);
// `jsonrpsee` does `tokio::spawn` within `start` method, so we cannot invoke it here, as this method
// should only build the server. This way we delay the launch until the `NodeServer::run` is invoked.
NodeServer {
local_addr,
run_fn: Box::new(move || server.start(rpc)),
match server_builder.build(addr).await {
Ok(server) => {
let local_addr = server.local_addr().unwrap();
let rpc = Self::default_rpc(self.node);
// `jsonrpsee` does `tokio::spawn` within `start` method, so we cannot invoke it here, as this method
// should only build the server. This way we delay the launch until the `NodeServer::run` is invoked.
Ok(NodeServer {
local_addr,
run_fn: Box::new(move || server.start(rpc)),
})
}
Err(e) => Err(format!("Failed to bind to address {}: {}", addr, e)),
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion crates/cli/src/bytecode_override.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ pub async fn override_bytecodes(node: &InMemoryNode, bytecodes_dir: String) -> a
let bytecode = Vec::from_hex(contract.bytecode.object)
.with_context(|| format!("Failed to parse hex from {:?}", path))?;

node.override_bytecode(&address, &bytecode)
node.override_bytecode(address, bytecode)
.await
.expect("Failed to override bytecode");
tracing::info!("+++++ Replacing bytecode at address {:?} +++++", address);
Expand Down
60 changes: 52 additions & 8 deletions crates/cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use anvil_zksync_core::filters::EthFilters;
use anvil_zksync_core::node::fork::ForkDetails;
use anvil_zksync_core::node::{
BlockSealer, BlockSealerMode, ImpersonationManager, InMemoryNode, InMemoryNodeInner,
NodeExecutor, TestNodeFeeInputProvider, TxPool,
NodeExecutor, StorageKeyLayout, TestNodeFeeInputProvider, TxPool,
};
use anvil_zksync_core::observability::Observability;
use anvil_zksync_core::system_contracts::SystemContracts;
Expand Down Expand Up @@ -223,18 +223,27 @@ async fn main() -> anyhow::Result<()> {
config.use_evm_emulator,
config.zkos_config.clone(),
);
let storage_key_layout = if config.zkos_config.use_zkos {
StorageKeyLayout::ZkOs
} else {
StorageKeyLayout::ZkEra
};

let (node_inner, _fork_storage, blockchain, time) = InMemoryNodeInner::init(
let (node_inner, storage, blockchain, time) = InMemoryNodeInner::init(
fork_details,
fee_input_provider.clone(),
filters,
config.clone(),
impersonation.clone(),
system_contracts.clone(),
storage_key_layout,
);

let (node_executor, node_handle) =
NodeExecutor::new(node_inner.clone(), system_contracts.clone());
let (node_executor, node_handle) = NodeExecutor::new(
node_inner.clone(),
system_contracts.clone(),
storage_key_layout,
);
let sealing_mode = if config.no_mining {
BlockSealerMode::noop()
} else if let Some(block_time) = config.block_time {
Expand All @@ -248,13 +257,15 @@ async fn main() -> anyhow::Result<()> {
let node: InMemoryNode = InMemoryNode::new(
node_inner,
blockchain,
storage,
node_handle,
Some(observability),
time,
impersonation,
pool,
block_sealer_state,
system_contracts,
storage_key_layout,
);

if let Some(ref bytecodes_dir) = config.override_bytecodes_dir {
Expand Down Expand Up @@ -306,10 +317,43 @@ async fn main() -> anyhow::Result<()> {
}
let mut server_handles = Vec::with_capacity(config.host.len());
for host in &config.host {
let addr = SocketAddr::new(*host, config.port);
let server = server_builder.clone().build(addr).await;
config.port = server.local_addr().port();
server_handles.push(server.run());
let mut addr = SocketAddr::new(*host, config.port);

match server_builder.clone().build(addr).await {
Ok(server) => {
config.port = server.local_addr().port();
server_handles.push(server.run());
}
Err(err) => {
tracing::info!(
"Failed to bind to address {}:{}: {}. Retrying with a different port...",
host,
config.port,
err
);

// Attempt to bind to a dynamic port
addr.set_port(0);
match server_builder.clone().build(addr).await {
Ok(server) => {
config.port = server.local_addr().port();
tracing::info!(
"Successfully started server on port {} for host {}",
config.port,
host
);
server_handles.push(server.run());
}
Err(err) => {
return Err(anyhow!(
"Failed to start server on host {} with port: {}",
host,
err
));
}
}
}
}
}
let any_server_stopped =
futures::future::select_all(server_handles.into_iter().map(|h| Box::pin(h.stopped())));
Expand Down
2 changes: 1 addition & 1 deletion crates/core/src/node/debug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ impl InMemoryNode {
// update the enforced_base_fee within l1_batch_env to match the logic in zksync_core
l1_batch_env.enforced_base_fee = Some(l2_tx.common_data.fee.max_fee_per_gas.as_u64());
let system_env = inner.create_system_env(system_contracts.clone(), execution_mode);
let storage = StorageView::new(&inner.fork_storage).into_rc_ptr();
let storage = StorageView::new(inner.read_storage()).into_rc_ptr();
let mut vm: Vm<_, HistoryDisabled> = Vm::new(l1_batch_env, system_env, storage);

// We must inject *some* signature (otherwise bootloader code fails to generate hash).
Expand Down
33 changes: 10 additions & 23 deletions crates/core/src/node/eth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,6 @@ use crate::{
utils::{h256_to_u64, TransparentError},
};

use super::keys::StorageKeyLayout;

impl InMemoryNode {
pub async fn call_impl(
&self,
Expand Down Expand Up @@ -78,7 +76,7 @@ impl InMemoryNode {
}

pub async fn send_raw_transaction_impl(&self, tx_bytes: Bytes) -> Result<H256, Web3Error> {
let chain_id = self.inner.read().await.fork_storage.chain_id;
let chain_id = self.chain_id().await;

let (tx_req, hash) = TransactionRequest::from_bytes(&tx_bytes.0, chain_id)?;
let mut l2_tx =
Expand All @@ -102,10 +100,7 @@ impl InMemoryNode {
) -> Result<H256, Web3Error> {
let (chain_id, l2_gas_price) = {
let reader = self.inner.read().await;
(
reader.fork_storage.chain_id,
reader.fee_input_provider.gas_price(),
)
(self.chain_id().await, reader.fee_input_provider.gas_price())
};

let mut tx_req = TransactionRequest::from(tx.clone());
Expand Down Expand Up @@ -176,13 +171,10 @@ impl InMemoryNode {
// TODO: Support
_block: Option<BlockIdVariant>,
) -> anyhow::Result<U256> {
let balance_key = StorageKeyLayout::get_storage_key_for_base_token(
self.system_contracts.use_zkos(),
&address,
);

let inner_guard = self.inner.read().await;
match inner_guard.fork_storage.read_value_internal(&balance_key) {
let balance_key = self
.storage_key_layout
.get_storage_key_for_base_token(&address);
match self.storage.read_value_alt(&balance_key).await {
Ok(balance) => Ok(h256_to_u256(balance)),
Err(error) => Err(anyhow::anyhow!("failed to read account balance: {error}")),
}
Expand Down Expand Up @@ -251,12 +243,9 @@ impl InMemoryNode {
// TODO: Support
_block: Option<BlockIdVariant>,
) -> anyhow::Result<Bytes> {
let inner = self.inner.write().await;

let code_key = get_code_key(&address);

match inner.fork_storage.read_value_internal(&code_key) {
Ok(code_hash) => match inner.fork_storage.load_factory_dep_internal(code_hash) {
match self.storage.read_value_alt(&code_key).await {
Ok(code_hash) => match self.storage.load_factory_dep_alt(code_hash).await {
Ok(raw_code) => {
let code = raw_code.unwrap_or_default();
Ok(Bytes::from(code))
Expand All @@ -273,10 +262,8 @@ impl InMemoryNode {
// TODO: Support
_block: Option<BlockIdVariant>,
) -> anyhow::Result<U256> {
let inner = self.inner.read().await;
let nonce_key = StorageKeyLayout::get_nonce_key(self.system_contracts.use_zkos(), &address);

match inner.fork_storage.read_value_internal(&nonce_key) {
let nonce_key = self.storage_key_layout.get_nonce_key(&address);
match self.storage.read_value_alt(&nonce_key).await {
Ok(result) => Ok(h256_to_u64(result).into()),
Err(error) => Err(anyhow::anyhow!("failed to read nonce storage: {error}")),
}
Expand Down
Loading

0 comments on commit daa0b80

Please sign in to comment.