anvil_zksync_l1_sidecar/contracts/
mod.rs1mod private {
3 use zksync_types::commitment::L1BatchWithMetadata;
4
5 alloy::sol!("src/contracts/sol/IExecutor.sol");
16 alloy::sol! {
18 struct PriorityOpsBatchInfo {
19 bytes32[] leftPath;
20 bytes32[] rightPath;
21 bytes32[] itemHashes;
22 }
23 }
24 alloy::sol!(IZKChain, "src/contracts/artifacts/IZKChain.json");
25
26 impl From<&L1BatchWithMetadata> for IExecutor::StoredBatchInfo {
27 fn from(value: &L1BatchWithMetadata) -> Self {
28 Self::from((
29 value.header.number.0 as u64,
30 alloy::primitives::FixedBytes::<32>::from(value.metadata.root_hash.0),
31 value.metadata.rollup_last_leaf_index,
32 alloy::primitives::U256::from(value.header.l1_tx_count),
33 alloy::primitives::FixedBytes::<32>::from(
34 value.header.priority_ops_onchain_data_hash().0,
35 ),
36 alloy::primitives::FixedBytes::<32>::from(value.metadata.l2_l1_merkle_root.0),
37 alloy::primitives::U256::from(value.header.timestamp),
38 alloy::primitives::FixedBytes::<32>::from(value.metadata.commitment.0),
39 ))
40 }
41 }
42}
43
44pub use self::private::IZKChain::NewPriorityRequest;
45use alloy::primitives::TxHash;
46
47use self::private::{IExecutor, PriorityOpsBatchInfo};
48use alloy::sol_types::{SolCall, SolValue};
49use zksync_mini_merkle_tree::MiniMerkleTree;
50use zksync_types::commitment::{serialize_commitments, L1BatchWithMetadata};
51use zksync_types::l1::L1Tx;
52use zksync_types::web3::keccak256;
53use zksync_types::{L2ChainId, H256};
54
55pub const SUPPORTED_ENCODING_VERSION: u8 = 0;
57
58pub fn commit_batches_shared_bridge_call(
62 l2_chain_id: L2ChainId,
63 last_committed_l1_batch: &L1BatchWithMetadata,
64 batch: &L1BatchWithMetadata,
65) -> impl SolCall {
66 IExecutor::commitBatchesSharedBridgeCall::new((
67 alloy::primitives::U256::from(l2_chain_id.as_u64()),
68 alloy::primitives::U256::from(last_committed_l1_batch.header.number.0 + 1),
69 alloy::primitives::U256::from(last_committed_l1_batch.header.number.0 + 1),
70 commit_calldata(last_committed_l1_batch, batch).into(),
71 ))
72}
73
74fn commit_calldata(
77 last_committed_l1_batch: &L1BatchWithMetadata,
78 batch: &L1BatchWithMetadata,
79) -> Vec<u8> {
80 let stored_batch_info = IExecutor::StoredBatchInfo::from(last_committed_l1_batch);
81 let last_batch_hash = H256(keccak256(stored_batch_info.abi_encode_params().as_slice()));
82 tracing::info!(?last_batch_hash, "preparing commit calldata");
83
84 let commit_batch_info = IExecutor::CommitBatchInfo::from((
85 batch.header.number.0 as u64,
86 batch.header.timestamp,
87 batch.metadata.rollup_last_leaf_index,
88 alloy::primitives::FixedBytes::<32>::from(batch.metadata.root_hash.0),
89 alloy::primitives::U256::from(batch.header.l1_tx_count),
90 alloy::primitives::FixedBytes::<32>::from(batch.header.priority_ops_onchain_data_hash().0),
91 alloy::primitives::FixedBytes::<32>::from(
92 batch
93 .metadata
94 .bootloader_initial_content_commitment
95 .unwrap()
96 .0,
97 ),
98 alloy::primitives::FixedBytes::<32>::from(
99 batch.metadata.events_queue_commitment.unwrap().0,
100 ),
101 alloy::primitives::Bytes::from(serialize_commitments(&batch.header.system_logs)),
102 alloy::primitives::Bytes::from(
104 batch
105 .metadata
106 .state_diff_hash
107 .expect("Failed to get state_diff_hash from metadata")
108 .0,
109 ),
110 ));
111 let encoded_data = (stored_batch_info, vec![commit_batch_info]).abi_encode_params();
112
113 [[SUPPORTED_ENCODING_VERSION].to_vec(), encoded_data]
115 .concat()
116 .to_vec()
117}
118
119pub fn prove_batches_shared_bridge_call(
123 l2_chain_id: L2ChainId,
124 last_proved_l1_batch: &L1BatchWithMetadata,
125 batch: &L1BatchWithMetadata,
126) -> impl SolCall {
127 IExecutor::proveBatchesSharedBridgeCall::new((
128 alloy::primitives::U256::from(l2_chain_id.as_u64()),
129 alloy::primitives::U256::from(last_proved_l1_batch.header.number.0 + 1),
130 alloy::primitives::U256::from(last_proved_l1_batch.header.number.0 + 1),
131 prove_calldata(last_proved_l1_batch, batch).into(),
132 ))
133}
134
135fn prove_calldata(
138 last_proved_l1_batch: &L1BatchWithMetadata,
139 batch: &L1BatchWithMetadata,
140) -> Vec<u8> {
141 let prev_l1_batch_info = IExecutor::StoredBatchInfo::from(last_proved_l1_batch);
142 let batches_arg = vec![IExecutor::StoredBatchInfo::from(batch)];
143 let proof_input = Vec::<alloy::primitives::U256>::new();
144 let encoded_data = (prev_l1_batch_info, batches_arg, proof_input).abi_encode_params();
145
146 [[SUPPORTED_ENCODING_VERSION].to_vec(), encoded_data]
148 .concat()
149 .to_vec()
150}
151
152pub fn execute_batches_shared_bridge_call(
154 l2_chain_id: L2ChainId,
155 batch: &L1BatchWithMetadata,
156 l1_tx_merkle_tree: &MiniMerkleTree<L1Tx>,
157) -> impl SolCall {
158 IExecutor::executeBatchesSharedBridgeCall::new((
159 alloy::primitives::U256::from(l2_chain_id.as_u64()),
160 alloy::primitives::U256::from(batch.header.number.0),
161 alloy::primitives::U256::from(batch.header.number.0),
162 execute_calldata(batch, l1_tx_merkle_tree).into(),
163 ))
164}
165
166fn execute_calldata(
169 batch: &L1BatchWithMetadata,
170 l1_tx_merkle_tree: &MiniMerkleTree<L1Tx>,
171) -> Vec<u8> {
172 let count = batch.header.l1_tx_count as usize;
173 let priority_ops_proofs = if count > 0 {
174 let (_, left, right) = l1_tx_merkle_tree.merkle_root_and_paths_for_range(..count);
175 let hashes = l1_tx_merkle_tree.hashes_prefix(count);
176 vec![PriorityOpsBatchInfo {
177 leftPath: left
178 .into_iter()
179 .map(Option::unwrap_or_default)
180 .map(|hash| TxHash::from(hash.0))
181 .collect(),
182 rightPath: right
183 .into_iter()
184 .map(Option::unwrap_or_default)
185 .map(|hash| TxHash::from(hash.0))
186 .collect(),
187 itemHashes: hashes
188 .into_iter()
189 .map(|hash| TxHash::from(hash.0))
190 .collect(),
191 }]
192 } else {
193 vec![PriorityOpsBatchInfo {
194 leftPath: vec![],
195 rightPath: vec![],
196 itemHashes: vec![],
197 }]
198 };
199 let batches_arg = vec![IExecutor::StoredBatchInfo::from(batch)];
200 let encoded_data = (batches_arg, priority_ops_proofs).abi_encode_params();
201
202 [[SUPPORTED_ENCODING_VERSION].to_vec(), encoded_data]
204 .concat()
205 .to_vec()
206}