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

Merge main to extra features #370

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/release-please/manifest.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"core": "25.2.0",
"core": "25.3.0",
"prover": "17.1.1",
"zkstack_cli": "0.1.2"
}
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 22 additions & 0 deletions core/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,27 @@
# Changelog

## [25.3.0](https://github.com/matter-labs/zksync-era/compare/core-v25.2.0...core-v25.3.0) (2024-12-11)


### Features

* change seal criteria for gateway ([#3320](https://github.com/matter-labs/zksync-era/issues/3320)) ([a0a74aa](https://github.com/matter-labs/zksync-era/commit/a0a74aaeb42f076d20c4ae8a32925eff2de11d0c))
* **contract-verifier:** Download compilers from GH automatically ([#3291](https://github.com/matter-labs/zksync-era/issues/3291)) ([a10c4ba](https://github.com/matter-labs/zksync-era/commit/a10c4baa312f26ebac2a10115fb7bd314d18b9c1))
* integrate gateway changes for some components ([#3274](https://github.com/matter-labs/zksync-era/issues/3274)) ([cbc91e3](https://github.com/matter-labs/zksync-era/commit/cbc91e35f84d04f2e4c8e81028596db009e478d1))
* **proof-data-handler:** exclude batches without object file in GCS ([#2980](https://github.com/matter-labs/zksync-era/issues/2980)) ([3e309e0](https://github.com/matter-labs/zksync-era/commit/3e309e06b24649c74bfe120e8ca45247cb2b5628))
* **pruning:** Record L1 batch root hash in pruning logs ([#3266](https://github.com/matter-labs/zksync-era/issues/3266)) ([7b6e590](https://github.com/matter-labs/zksync-era/commit/7b6e59083cf0cafeaef5dd4b2dd39257ff91316d))
* **state-keeper:** mempool io opens batch if there is protocol upgrade tx ([#3360](https://github.com/matter-labs/zksync-era/issues/3360)) ([f6422cd](https://github.com/matter-labs/zksync-era/commit/f6422cd59dab2c105bb7c125c172f2621fe39464))
* **tee:** add error handling for unstable_getTeeProofs API endpoint ([#3321](https://github.com/matter-labs/zksync-era/issues/3321)) ([26f630c](https://github.com/matter-labs/zksync-era/commit/26f630cb75958c711d67d13bc77ddbb1117156c3))
* **zksync_cli:** Health checkpoint improvements ([#3193](https://github.com/matter-labs/zksync-era/issues/3193)) ([440fe8d](https://github.com/matter-labs/zksync-era/commit/440fe8d8afdf0fc2768692a1b40b0910873e2faf))


### Bug Fixes

* **api:** batch fee input scaling for `debug_traceCall` ([#3344](https://github.com/matter-labs/zksync-era/issues/3344)) ([7ace594](https://github.com/matter-labs/zksync-era/commit/7ace594fb3140212bd94ffd6bffcac99805cf4b1))
* **tee:** correct previous fix for race condition in batch locking ([#3358](https://github.com/matter-labs/zksync-era/issues/3358)) ([b12da8d](https://github.com/matter-labs/zksync-era/commit/b12da8d1fddc7870bf17d5e08312d20773815269))
* **tee:** fix race condition in batch locking ([#3342](https://github.com/matter-labs/zksync-era/issues/3342)) ([a7dc0ed](https://github.com/matter-labs/zksync-era/commit/a7dc0ed5007f6b2f789f4c61cb3d137843151860))
* **tracer:** adds vm error to flatCallTracer error field if exists ([#3374](https://github.com/matter-labs/zksync-era/issues/3374)) ([5d77727](https://github.com/matter-labs/zksync-era/commit/5d77727cd3ba5f4d84643fee1873f03656310b4d))

## [25.2.0](https://github.com/matter-labs/zksync-era/compare/core-v25.1.0...core-v25.2.0) (2024-11-19)


Expand Down
2 changes: 1 addition & 1 deletion core/bin/external_node/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "zksync_external_node"
description = "Non-validator ZKsync node"
version = "25.2.0" # x-release-please-version
version = "25.3.0" # x-release-please-version
edition.workspace = true
authors.workspace = true
homepage.workspace = true
Expand Down
16 changes: 11 additions & 5 deletions core/node/api_server/src/web3/namespaces/debug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,16 +96,22 @@ impl DebugNamespace {
CallType::NearCall => unreachable!("We have to filter our near calls before"),
};

let (result, error) = if let Some(error) = call.revert_reason {
(None, Some(error))
} else {
(
let (result, error) = match (call.revert_reason, call.error) {
(Some(revert_reason), _) => {
// If revert_reason exists, it takes priority over VM error
(None, Some(revert_reason))
}
(None, Some(vm_error)) => {
// If no revert_reason but VM error exists
(None, Some(vm_error))
}
(None, None) => (
Some(CallResult {
output: web3::Bytes::from(call.output),
gas_used: U256::from(call.gas_used),
}),
None,
)
),
};

calls.push(DebugCallFlat {
Expand Down
18 changes: 17 additions & 1 deletion core/node/state_keeper/src/io/mempool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,21 @@ impl StateKeeperIO for MempoolIO {
.protocol_version_id_by_timestamp(timestamp)
.await
.context("Failed loading protocol version")?;
let previous_protocol_version = storage
.blocks_dal()
.pending_protocol_version()
.await
.context("Failed loading previous protocol version")?;
let batch_with_upgrade_tx = if previous_protocol_version != protocol_version {
storage
.protocol_versions_dal()
.get_protocol_upgrade_tx(protocol_version)
.await
.context("Failed loading protocol upgrade tx")?
.is_some()
} else {
false
};
drop(storage);

// We create a new filter each time, since parameters may change and a previously
Expand All @@ -217,7 +232,8 @@ impl StateKeeperIO for MempoolIO {
.await
.context("failed creating L2 transaction filter")?;

if !self.mempool.has_next(&self.filter) {
// We do not populate mempool with upgrade tx so it should be checked separately.
if !batch_with_upgrade_tx && !self.mempool.has_next(&self.filter) {
tokio::time::sleep(self.delay_interval).await;
continue;
}
Expand Down
48 changes: 48 additions & 0 deletions core/node/state_keeper/src/io/tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ use zksync_types::{
commitment::{L1BatchCommitmentMode, PubdataParams},
fee_model::{BatchFeeInput, PubdataIndependentBatchFeeModelInput},
l2::L2Tx,
protocol_upgrade::ProtocolUpgradeTx,
protocol_version::ProtocolSemanticVersion,
AccountTreeId, Address, L1BatchNumber, L2BlockNumber, L2ChainId, ProtocolVersion,
ProtocolVersionId, StorageKey, TransactionTimeRangeConstraint, H256, U256,
};
Expand Down Expand Up @@ -848,6 +850,52 @@ async fn test_mempool_with_timestamp_assertion() {
);
}

#[tokio::test]
async fn test_batch_params_with_protocol_upgrade_tx() {
let connection_pool = ConnectionPool::<Core>::constrained_test_pool(2).await;
let tester = Tester::new(L1BatchCommitmentMode::Rollup);
// Genesis is needed for proper mempool initialization.
tester.genesis(&connection_pool).await;

let (mut mempool, _) = tester.create_test_mempool_io(connection_pool.clone()).await;
let (cursor, _) = mempool.initialize().await.unwrap();

// Check that new batch params are not returned when there is no tx to process.
let new_batch_params = mempool
.wait_for_new_batch_params(&cursor, Duration::from_millis(100))
.await
.unwrap();
assert!(new_batch_params.is_none());

// Insert protocol version with upgrade tx.
let protocol_upgrade_tx = ProtocolUpgradeTx {
execute: Default::default(),
common_data: Default::default(),
received_timestamp_ms: 0,
};
let version = ProtocolVersion {
version: ProtocolSemanticVersion {
minor: ProtocolVersionId::next(),
patch: 0.into(),
},
tx: Some(protocol_upgrade_tx),
..Default::default()
};
connection_pool
.connection()
.await
.unwrap()
.protocol_versions_dal()
.save_protocol_version_with_tx(&version)
.await
.unwrap();
let new_batch_params = mempool
.wait_for_new_batch_params(&cursor, Duration::from_millis(100))
.await
.unwrap();
assert!(new_batch_params.is_some());
}

async fn insert_l2_transaction(storage: &mut Connection<'_, Core>, tx: &L2Tx) {
storage
.transactions_dal()
Expand Down
4 changes: 2 additions & 2 deletions deny.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ feature-depth = 1
[advisories]
ignore = [
"RUSTSEC-2024-0375", # atty dependency being unmaintained, dependency of clap and criterion, we would need to update to newer major of dependencies
"RUSTSEC-2020-0168", # mach dependency being unmaintained, dependency in consensus, we should consider moving to mach2 fork
"RUSTSEC-2020-0168", # mach dependency being unmaintained, dependency in api server, we should consider moving to mach2 fork
"RUSTSEC-2024-0370", # `cs_derive` needs to be updated to not rely on `proc-macro-error`
# all below caused by StructOpt which we still use and we should move to clap v4 instead
"RUSTSEC-2021-0145",
Expand All @@ -24,7 +24,6 @@ allow = [
"ISC",
"Unlicense",
"MPL-2.0",
"Unicode-DFS-2016",
"CC0-1.0",
"BSD-2-Clause",
"BSD-3-Clause",
Expand All @@ -33,6 +32,7 @@ allow = [
"Apache-2.0 WITH LLVM-exception",
"0BSD",
"BSL-1.0",
"Unicode-3.0"
]
confidence-threshold = 0.8

Expand Down
Binary file modified docs/src/specs/img/verifyinteropmsg.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
37 changes: 16 additions & 21 deletions docs/src/specs/interop/interopmessages.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,9 @@ This `interopHash` serves as a globally unique identifier that can be used on an
#### How do I get the proof

You’ll notice that **verifyInteropMessage** has a second argument — a proof that you need to provide. This proof is a
Merkle tree proof (more details below). You can obtain it by querying the Settlement Layer (Gateway) or generating it
off-chain by examining the Gateway state on L1.
Merkle tree proof (more details below). You can obtain it by querying the
[chain](https://docs.zksync.io/build/api-reference/zks-rpc#zks_getl2tol1msgproof) , or generate it off-chain - by
looking at the chain's state on L1

#### How does the interop message differ from other layers (InteropTransactions, InteropCalls)

Expand Down Expand Up @@ -129,49 +130,43 @@ from them at the end of the batch, and sends this tree to the SettlementLayer (G

![sendtol1.png](../img/sendtol1.png)

The Gateway will verify the hashes of the messages to ensure it has received the correct preimages. Once the proof for
the batch is submitted (or more accurately, during the "execute" step), it will add the root of the Merkle tree to its
`globalRoot`.
The settlement layer receives the messages and once the proof for the batch is submitted (or more accurately, during the
"execute" step), it will add the root of the Merkle tree to its `messageRoot` (sometimes called `globalRoot`).

![globalroot.png](../img/globalroot.png)

The `globalRoot` is the root of the Merkle tree that includes all messages from all chains. Each chain regularly reads
the globalRoot value from the Gateway to stay synchronized.
The `messageRoot` is the root of the Merkle tree that includes all messages from all chains. Each chain regularly reads
the messageRoot value from the Gateway to stay synchronized.

![gateway.png](../img/gateway.png)

If a user wants to call `verifyInteropMessage` on a chain, they first need to query the Gateway for the Merkle path from
the batch they are interested in up to the `globalRoot`. Once they have this path, they can provide it as an argument
the batch they are interested in up to the `messageRoot`. Once they have this path, they can provide it as an argument
when calling a method on the destination chain (such as the `openSignup` method in our example).

![proofmerklepath.png](../img/proofmerklepath.png)

#### What if the Gateway doesn’t respond
#### What if Chain doesn’t provide the proof

If the Gateway doesn’t respond, users can manually re-create the Merkle proof using data available on L1. Every
If the chain doesn’t respond, users can manually re-create the Merkle proof using data available on L1. Every
interopMessage is also sent to L1.

#### Global roots change frequently
#### Message roots change frequently

Yes, global roots update continuously as new chains prove their blocks. However, chains retain historical global roots
Yes, message roots update continuously as new chains prove their blocks. However, chains retain historical message roots
for a reasonable period (around 24 hours) to ensure that recently generated Merkle paths remain valid.

#### Is this secure? Could a chain operator, like Chain D, use a different global root
#### Is this secure? Could a chain operator, like Chain D, use a different message root

Yes, it’s secure. If a malicious operator on Chain D attempted to use a different global root, they wouldn’t be able to
Yes, it’s secure. If a malicious operator on Chain D attempted to use a different message root, they wouldn’t be able to
submit the proof for their new batch to the Gateway. This is because the proof’s public inputs must include the valid
global root.

#### What if the Gateway is malicious

If the Gateway behaves maliciously, it wouldn’t be able to submit its batches to L1, as the proof would fail
verification. A separate section will cover interop transaction security in more detail.
message root.

### Other Features

#### Dependency Set

- In ElasticChain, this is implicitly handled by the Gateway. Any chain that is part of the global root can exchange
- In ElasticChain, this is implicitly handled by the Gateway. Any chain that is part of the message root can exchange
messages with any other chain, effectively forming an undirected graph.

#### Timestamps and Expiration
Expand Down
10 changes: 5 additions & 5 deletions docs/src/specs/interop/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,14 +112,14 @@ The step-by-step process and exact details will be covered in the next section.

## Technical Details

### How is Interop Different from a Bridge
### How does native bridging differ from a third party bridging

Bridges generally fall into two categories: Native and Third-Party.

#### 1. Native Bridges

Native bridges enable asset transfers “up and down” (from L2 to L1 and vice versa). In contrast, interop allows direct
transfers between different L2s.
Native bridges enable asset transfers “up and down” (from L2 to L1 and vice versa), but interop (which is also a form of
native bridging) allows you to move them between different L2s.

Instead of doing a "round trip" (L2 → L1 → another L2), interop lets you move assets directly between two L2s, saving
both time and cost.
Expand All @@ -129,8 +129,8 @@ both time and cost.
Third-party bridges enable transfers between two L2s, but they rely on their own liquidity. While you, as the user,
receive assets on the destination chain instantly, these assets come from the bridge’s liquidity pool.

Bridge operators then rebalance using native bridging, which requires maintaining token reserves on both sides. This
adds costs for the bridge operators, often resulting in higher fees for users.
Bridge operators then rebalance using native bridging, which requires maintaining token reserves on both sides. Without
interop this adds costs for the bridge operators, often resulting in higher fees for users.

The good news is that third-party bridges can use interop to improve their token transfers by utilizing the
**InteropMessage** layer.
Expand Down
Loading