From 91f3cdcdb4d6efd45c9233a492fd94abb780fb93 Mon Sep 17 00:00:00 2001 From: kelemeno <34402761+kelemeno@users.noreply.github.com> Date: Fri, 30 Aug 2024 14:55:28 +0100 Subject: [PATCH] chore: message-root-support (#2706) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## What ❔ ## Why ❔ ## Checklist - [ ] PR title corresponds to the body of PR (we generate changelog entries from PRs). - [ ] Tests for the changes have been added / updated. - [ ] Documentation comments have been added / updated. - [ ] Code has been formatted via `zk fmt` and `zk lint`. --------- Co-authored-by: Stanislav Breadless --- contracts | 2 +- .../src/versions/vm_latest/tests/constants.rs | 198 +++++------ .../src/versions/vm_latest/tests/utils.rs | 10 +- core/lib/types/src/api/mod.rs | 33 +- core/lib/types/src/storage/mod.rs | 20 +- .../api_server/src/web3/namespaces/zks.rs | 330 ++++++++++++------ core/node/commitment_generator/src/lib.rs | 4 +- etc/env/base/contracts.toml | 6 +- infrastructure/zk/src/init.ts | 11 + 9 files changed, 379 insertions(+), 235 deletions(-) diff --git a/contracts b/contracts index 10ec8ba28f3d..9d319e7b1ae8 160000 --- a/contracts +++ b/contracts @@ -1 +1 @@ -Subproject commit 10ec8ba28f3de36ab6d8f73d63496f59b37654e3 +Subproject commit 9d319e7b1ae80185b09444b97cdda1c9844860e1 diff --git a/core/lib/multivm/src/versions/vm_latest/tests/constants.rs b/core/lib/multivm/src/versions/vm_latest/tests/constants.rs index 7716557af429..682ee7c8c194 100644 --- a/core/lib/multivm/src/versions/vm_latest/tests/constants.rs +++ b/core/lib/multivm/src/versions/vm_latest/tests/constants.rs @@ -1,22 +1,22 @@ -use ethabi::Token; -use itertools::Itertools; -use zksync_types::{ - get_immutable_key, get_l2_message_root_init_logs, AccountTreeId, StorageKey, StorageLog, - StorageLogKind, H256, IMMUTABLE_SIMULATOR_STORAGE_ADDRESS, L2_BRIDGEHUB_ADDRESS, - L2_MESSAGE_ROOT_ADDRESS, -}; +// use ethabi::Token; +// use itertools::Itertools; +// use zksync_types::{ +// get_immutable_key, get_l2_message_root_init_logs, AccountTreeId, StorageKey, StorageLog, +// StorageLogKind, H256, IMMUTABLE_SIMULATOR_STORAGE_ADDRESS, L2_BRIDGEHUB_ADDRESS, +// L2_MESSAGE_ROOT_ADDRESS, +// }; -use crate::{ - interface::{TxExecutionMode, VmExecutionMode, VmInterface}, - vm_latest::{ - tests::{ - tester::{DeployContractsTx, TxType, VmTesterBuilder}, - utils::read_message_root, - }, - HistoryEnabled, - }, - vm_m5::storage::Storage, -}; +// use crate::{ +// // interface::{TxExecutionMode, VmExecutionMode, VmInterface}, +// vm_latest::{ +// tests::{ +// tester::{DeployContractsTx, TxType, VmTesterBuilder}, +// utils::read_message_root, +// }, +// HistoryEnabled, +// }, +// vm_m5::storage::Storage, +// }; /// Some of the constants of the system are implicitly calculated, but they may affect the code and so /// we added additional checks on them to keep any unwanted changes of those apparent. #[test] @@ -27,94 +27,94 @@ fn test_that_bootloader_encoding_space_is_large_enoguh() { assert!(encoding_space >= 330000, "Bootloader tx space is too small"); } -/// Test that checks that the initial logs for the L2 Message Root are correct -#[test] -fn test_l2_message_root_init_logs() { - let mut vm = VmTesterBuilder::new(HistoryEnabled) - .with_empty_in_memory_storage() - .with_execution_mode(TxExecutionMode::VerifyExecute) - .with_random_rich_accounts(1) - .build(); +// Test that checks that the initial logs for the L2 Message Root are correct +// #[test] +// fn test_l2_message_root_init_logs() { +// let mut vm = VmTesterBuilder::new(HistoryEnabled) +// .with_empty_in_memory_storage() +// .with_execution_mode(TxExecutionMode::VerifyExecute) +// .with_random_rich_accounts(1) +// .build(); - let message_root_bytecode = read_message_root(); - let account = &mut vm.rich_accounts[0]; - let DeployContractsTx { tx, address, .. } = account.get_deploy_tx( - &message_root_bytecode, - Some(&[Token::Address(L2_BRIDGEHUB_ADDRESS)]), - TxType::L2, - ); +// let message_root_bytecode = read_message_root(); +// let account = &mut vm.rich_accounts[0]; +// let DeployContractsTx { tx, address, .. } = account.get_deploy_tx( +// &message_root_bytecode, +// Some(&[Token::Address(L2_BRIDGEHUB_ADDRESS)]), +// TxType::L2, +// ); - vm.vm.push_transaction(tx); - let result = vm.vm.execute(VmExecutionMode::OneTx); - assert!(!result.result.is_failed(), "Transaction wasn't successful"); +// vm.vm.push_transaction(tx); +// let result = vm.vm.execute(VmExecutionMode::OneTx); +// assert!(!result.result.is_failed(), "Transaction wasn't successful"); - // That's the only key in the immutable simulator that should be changed. It depends on the address - // of the deployed contract, so we check that the way it was generated for a random deployed contract is the same. - let expected_change_immutable_key = get_immutable_key(&address, H256::zero()); - let expected_genesis_immutable_key = get_immutable_key(&L2_MESSAGE_ROOT_ADDRESS, H256::zero()); +// // That's the only key in the immutable simulator that should be changed. It depends on the address +// // of the deployed contract, so we check that the way it was generated for a random deployed contract is the same. +// let expected_change_immutable_key = get_immutable_key(&address, H256::zero()); +// let expected_genesis_immutable_key = get_immutable_key(&L2_MESSAGE_ROOT_ADDRESS, H256::zero()); - let mut expected_init_logs = get_l2_message_root_init_logs() - .into_iter() - .map(|x| StorageLog { - // We unify all the logs to all have the same kind - kind: StorageLogKind::InitialWrite, - key: x.key, - value: x.value, - }) - .collect::>(); +// let mut expected_init_logs = get_l2_message_root_init_logs() +// .into_iter() +// .map(|x| StorageLog { +// // We unify all the logs to all have the same kind +// kind: StorageLogKind::InitialWrite, +// key: x.key, +// value: x.value, +// }) +// .collect::>(); - let ordering = |a: &StorageLog, b: &StorageLog| match a.key.cmp(&b.key) { - std::cmp::Ordering::Equal => a.value.cmp(&b.value), - other => other, - }; +// let ordering = |a: &StorageLog, b: &StorageLog| match a.key.cmp(&b.key) { +// std::cmp::Ordering::Equal => a.value.cmp(&b.value), +// other => other, +// }; - expected_init_logs.sort_by(ordering); +// expected_init_logs.sort_by(ordering); - let correct_init_logs = vm - .vm - .storage - .borrow_mut() - .get_modified_storage_keys() - .iter() - .filter_map(|(&storage_key, &value)| { - if *storage_key.address() == address { - Some(StorageLog { - kind: StorageLogKind::InitialWrite, - key: StorageKey::new( - // Note, that it in the end we will compare those with the genesis logs that - // have the `L2_MESSAGE_ROOT_ADDRESS` as the address - AccountTreeId::new(L2_MESSAGE_ROOT_ADDRESS), - *storage_key.key(), - ), - value, - }) - } else if *storage_key.address() == IMMUTABLE_SIMULATOR_STORAGE_ADDRESS { - assert!( - *storage_key.key() == expected_change_immutable_key, - "Incorrect immutable key has been changed" - ); +// let correct_init_logs = vm +// .vm +// .storage +// .borrow_mut() +// .get_modified_storage_keys() +// .iter() +// .filter_map(|(&storage_key, &value)| { +// if *storage_key.address() == address { +// Some(StorageLog { +// kind: StorageLogKind::InitialWrite, +// key: StorageKey::new( +// // Note, that it in the end we will compare those with the genesis logs that +// // have the `L2_MESSAGE_ROOT_ADDRESS` as the address +// AccountTreeId::new(L2_MESSAGE_ROOT_ADDRESS), +// *storage_key.key(), +// ), +// value, +// }) +// } else if *storage_key.address() == IMMUTABLE_SIMULATOR_STORAGE_ADDRESS { +// assert!( +// *storage_key.key() == expected_change_immutable_key, +// "Incorrect immutable key has been changed" +// ); - Some(StorageLog { - kind: StorageLogKind::InitialWrite, - key: StorageKey::new( - AccountTreeId::new(IMMUTABLE_SIMULATOR_STORAGE_ADDRESS), - // For comparison to work, we replace the immutable key with the one that is used for genesis - expected_genesis_immutable_key, - ), - value, - }) - } else { - None - } - }) - .sorted_by(ordering) - .collect::>(); +// Some(StorageLog { +// kind: StorageLogKind::InitialWrite, +// key: StorageKey::new( +// AccountTreeId::new(IMMUTABLE_SIMULATOR_STORAGE_ADDRESS), +// // For comparison to work, we replace the immutable key with the one that is used for genesis +// expected_genesis_immutable_key, +// ), +// value, +// }) +// } else { +// None +// } +// }) +// .sorted_by(ordering) +// .collect::>(); - assert_eq!(expected_init_logs, correct_init_logs); +// assert_eq!(expected_init_logs, correct_init_logs); - let batch_result = vm.vm.execute(VmExecutionMode::Batch); - assert!( - !batch_result.result.is_failed(), - "Transaction wasn't successful" - ); -} +// let batch_result = vm.vm.execute(VmExecutionMode::Batch); +// assert!( +// !batch_result.result.is_failed(), +// "Transaction wasn't successful" +// ); +// } diff --git a/core/lib/multivm/src/versions/vm_latest/tests/utils.rs b/core/lib/multivm/src/versions/vm_latest/tests/utils.rs index c8e06b2c261a..9c9d48175884 100644 --- a/core/lib/multivm/src/versions/vm_latest/tests/utils.rs +++ b/core/lib/multivm/src/versions/vm_latest/tests/utils.rs @@ -75,11 +75,11 @@ pub(crate) fn read_nonce_holder_tester() -> Vec { read_bytecode("etc/contracts-test-data/artifacts-zk/contracts/custom-account/nonce-holder-test.sol/NonceHolderTest.json") } -pub(crate) fn read_message_root() -> Vec { - read_bytecode( - "contracts/l1-contracts/artifacts-zk/contracts/bridgehub/MessageRoot.sol/MessageRoot.json", - ) -} +// pub(crate) fn read_message_root() -> Vec { +// read_bytecode( +// "contracts/l1-contracts/artifacts-zk/contracts/bridgehub/MessageRoot.sol/MessageRoot.json", +// ) +// } pub(crate) fn read_error_contract() -> Vec { read_bytecode( diff --git a/core/lib/types/src/api/mod.rs b/core/lib/types/src/api/mod.rs index d72a84f465cc..eb86c4f0664e 100644 --- a/core/lib/types/src/api/mod.rs +++ b/core/lib/types/src/api/mod.rs @@ -195,13 +195,25 @@ pub struct L2ToL1LogProof { #[derive(Debug, Serialize, Deserialize, Clone)] #[serde(rename_all = "camelCase")] pub struct LeafAggProof { + pub leaf_chain_proof: LeafChainProof, + pub chain_agg_proof: ChainAggProof, + pub local_msg_root: H256, + pub sl_batch_number: U256, + pub sl_chain_id: U256, +} + +#[derive(Debug, Serialize, Deserialize, Clone)] +#[serde(rename_all = "camelCase")] +pub struct LeafChainProof { pub batch_leaf_proof: Vec, pub batch_leaf_proof_mask: U256, +} + +#[derive(Debug, Serialize, Deserialize, Clone)] +#[serde(rename_all = "camelCase")] +pub struct ChainAggProof { pub chain_id_leaf_proof: Vec, pub chain_id_leaf_proof_mask: U256, - pub local_msg_root: H256, - pub sl_batch_number: U256, - pub sl_chain_id: U256, } impl LeafAggProof { @@ -209,14 +221,23 @@ impl LeafAggProof { let mut encoded_result = vec![]; let LeafAggProof { - batch_leaf_proof, - batch_leaf_proof_mask, - chain_id_leaf_proof_mask, + leaf_chain_proof, + chain_agg_proof, sl_batch_number, sl_chain_id, .. } = self; + let LeafChainProof { + batch_leaf_proof, + batch_leaf_proof_mask, + } = leaf_chain_proof; + + let ChainAggProof { + chain_id_leaf_proof: _, + chain_id_leaf_proof_mask, + } = chain_agg_proof; + let batch_leaf_proof_len = batch_leaf_proof.len() as u32; encoded_result.push(u256_to_h256(batch_leaf_proof_mask)); diff --git a/core/lib/types/src/storage/mod.rs b/core/lib/types/src/storage/mod.rs index fdc915c130f7..9626a5515dc1 100644 --- a/core/lib/types/src/storage/mod.rs +++ b/core/lib/types/src/storage/mod.rs @@ -153,10 +153,10 @@ fn get_system_context_init_logs(chain_id: L2ChainId) -> Vec { /// and so for now the correctness of those values is tested in a unit tests within the multivm crate. pub fn get_l2_message_root_init_logs() -> Vec { let slots_values = vec![ - ( - "8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf4", - "0000000000000000000000000000000000000000000000000000000000000001", - ), + // ( + // "8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf4", + // "0000000000000000000000000000000000000000000000000000000000000001", + // ), ( "0000000000000000000000000000000000000000000000000000000000000007", "0000000000000000000000000000000000000000000000000000000000000001", @@ -199,11 +199,11 @@ pub fn get_l2_message_root_init_logs() -> Vec { } pub fn get_system_contracts_init_logs(chain_id: L2ChainId) -> Vec { - let system_context_init_logs = get_system_context_init_logs(chain_id); - let l2_message_root_init_logs = get_l2_message_root_init_logs(); + get_system_context_init_logs(chain_id) + // let l2_message_root_init_logs = get_l2_message_root_init_logs(); - system_context_init_logs - .into_iter() - .chain(l2_message_root_init_logs) - .collect() + // system_context_init_logs + // .into_iter() + // .chain(l2_message_root_init_logs) + // .collect() } diff --git a/core/node/api_server/src/web3/namespaces/zks.rs b/core/node/api_server/src/web3/namespaces/zks.rs index 9e038b3dfa33..b96dff2fff2f 100644 --- a/core/node/api_server/src/web3/namespaces/zks.rs +++ b/core/node/api_server/src/web3/namespaces/zks.rs @@ -10,9 +10,9 @@ use zksync_multivm::interface::VmExecutionResultAndLogs; use zksync_system_constants::DEFAULT_L2_TX_GAS_PER_PUBDATA_BYTE; use zksync_types::{ api::{ - state_override::StateOverride, BlockDetails, BridgeAddresses, GetLogsFilter, - L1BatchDetails, L2ToL1LogProof, LeafAggProof, Proof, ProtocolVersion, StorageProof, - TransactionDetails, + state_override::StateOverride, BlockDetails, BridgeAddresses, ChainAggProof, GetLogsFilter, + L1BatchDetails, L2ToL1LogProof, LeafAggProof, LeafChainProof, Proof, ProtocolVersion, + StorageProof, TransactionDetails, }, ethabi, fee::Fee, @@ -23,7 +23,7 @@ use zksync_types::{ tokens::ETHEREUM_ADDRESS, transaction_request::CallRequest, utils::storage_key_for_standard_token_balance, - web3::Bytes, + web3::{keccak256, Bytes}, AccountTreeId, L1BatchNumber, L2BlockNumber, L2ChainId, ProtocolVersionId, StorageKey, Transaction, L1_MESSENGER_ADDRESS, L2_BASE_TOKEN_ADDRESS, L2_MESSAGE_ROOT_ADDRESS, REQUIRED_L1_TO_L2_GAS_PER_PUBDATA_BYTE, U256, U64, @@ -41,13 +41,6 @@ use crate::{ web3::{backend_jsonrpsee::MethodTracer, metrics::API_METRICS, RpcState}, }; -pub static MESSAGE_ROOT_ADDED_CHAIN_EVENT: Lazy = Lazy::new(|| { - ethabi::long_signature( - "AddedChain", - &[ethabi::ParamType::Uint(256), ethabi::ParamType::Uint(256)], - ) -}); - pub static MESSAGE_ROOT_ADDED_CHAIN_BATCH_ROOT_EVENT: Lazy = Lazy::new(|| { ethabi::long_signature( "AppendedChainBatchRoot", @@ -402,7 +395,7 @@ impl ZksNamespace { println!("Proof: {:#?}", proof); if let Some(proof) = proof { - println!("Found proof for my own batch :{:#?}", proof); + println!("Found proof for my own batch"); log_leaf_proof.append_aggregation_layer(proof); } else { @@ -498,7 +491,6 @@ impl ZksNamespace { ) -> Result, Web3Error> { println!("heee"); let mut storage = self.state.acquire_connection().await?; - // Proofs only available for finalized batches let latest_sealed_block_number = storage .blocks_dal() @@ -534,23 +526,50 @@ impl ZksNamespace { return Ok(None); }; - // FIXME: move as api config - // Firstly, let's grab all events that correspond to batch being inserted into the chain_id tree. - let add_chain_logs = storage - .events_web3_dal() - .get_logs( - GetLogsFilter { - // FIXME: this is somewhat inefficient, better ways need to be created - from_block: 0.into(), - to_block: latest_sealed_block_number, - addresses: vec![message_root_addr], - topics: vec![(1, vec![*MESSAGE_ROOT_ADDED_CHAIN_EVENT])], - }, - self.state.api_config.req_entities_limit, + let batch_proof = self + .get_batch_inclusion_proof_impl( + message_root_addr, + searched_batch_number, + searched_chain_id, + latest_sealed_block_number, + l1_batch_number_with_agg_batch, ) - .await - .map_err(DalError::generalize)?; + .await?; + let Some((leaf_proof, batch_added_block_number)) = batch_proof else { + return Ok(None); + }; + let chain_proof = self + .get_chain_inclusion_proof_impl( + message_root_addr, + searched_chain_id, + batch_added_block_number, + local_msg_root, + ) + .await?; + let result = LeafAggProof { + leaf_chain_proof: leaf_proof, + chain_agg_proof: chain_proof.unwrap(), + local_msg_root, + sl_batch_number: l1_batch_number_with_agg_batch.into(), + // this is the settlement layer + sl_chain_id: self.state.api_config.l2_chain_id.0.into(), + }; + + Ok(Some(result)) + } + pub async fn get_batch_inclusion_proof_impl( + &self, + message_root_addr: Address, + searched_batch_number: L1BatchNumber, + searched_chain_id: u32, + latest_sealed_block_number: L2BlockNumber, + l1_batch_number_with_agg_batch: u32, + ) -> Result, Web3Error> { + let mut storage = self.state.acquire_connection().await?; + + // FIXME: move as api config + // Firstly, let's grab all events that correspond to batch being inserted into the chain_id tree. println!("hee4"); let add_batch_logs = storage .events_web3_dal() @@ -569,16 +588,15 @@ impl ZksNamespace { println!("Add batch logs: {:#?}", add_batch_logs); - let mut full_chain_merkle_tree = - MiniMerkleTree::<[u8; 96], KeccakHasher>::new(Vec::<[u8; 96]>::new().into_iter(), None); - - let mut batch_leaf_proof = vec![]; let mut batch_leaf_proof_mask = None; - let mut chain_id_leaf_proof_mask = None; + let mut chain_id_merkle_tree = + MiniMerkleTree::<[u8; 96], KeccakHasher>::new(Vec::<[u8; 96]>::new().into_iter(), None); + let mut cnt = 0; + let mut batch_added_block_number = None; - for (i, chain_add_log) in add_chain_logs.into_iter().enumerate() { - let Some(batch_num) = chain_add_log.l1_batch_number else { + for add_batch_log in add_batch_logs.iter() { + let Some(batch_num) = add_batch_log.l1_batch_number else { continue; }; let batch_num: u32 = batch_num.as_u32(); @@ -587,83 +605,114 @@ impl ZksNamespace { continue; }; - let chain_id = h256_to_u256(chain_add_log.topics[1]); - let index = h256_to_u256(chain_add_log.topics[2]); + let chain_id = h256_to_u256(add_batch_log.topics[1]); + let batch_number = h256_to_u256(add_batch_log.topics[2]); - if chain_id.as_u32() == searched_chain_id { - chain_id_leaf_proof_mask = Some(i); + if chain_id.as_u32() != searched_chain_id { + continue; } - // Double check index correctness - assert_eq!(U256::from(i), index); - - let mut chain_id_merkle_tree = MiniMerkleTree::<[u8; 96], KeccakHasher>::new( - Vec::<[u8; 96]>::new().into_iter(), - None, - ); - - let mut cnt = 0; + if batch_number.as_u32() == searched_batch_number.0 { + println!("relevant batch found! {:#?}", add_batch_log); + batch_leaf_proof_mask = Some(cnt); + batch_added_block_number = + Some(L2BlockNumber(add_batch_log.block_number.unwrap().as_u32())); + } - for add_batch_log in add_batch_logs.iter() { - let Some(batch_num) = add_batch_log.l1_batch_number else { - continue; - }; - let batch_num: u32 = batch_num.as_u32(); + println!("appended log: {:#?}", add_batch_log); - if batch_num > l1_batch_number_with_agg_batch { - continue; - }; + let batch_root = H256::from_slice(&add_batch_log.data.0); + chain_id_merkle_tree.push(Self::batch_leaf_preimage(batch_root, batch_number.as_u32())); - let chain_id = h256_to_u256(add_batch_log.topics[1]); - let batch_number = h256_to_u256(add_batch_log.topics[2]); + println!("new batch root = {:#?}", chain_id_merkle_tree.merkle_root()); - if chain_id.as_u32() != searched_chain_id { - continue; - } - - if batch_number.as_u32() == searched_batch_number.0 - && chain_id.as_u32() == searched_chain_id - { - println!("relevat batch found! {:#?}", add_batch_log); - batch_leaf_proof_mask = Some(cnt); - } + cnt += 1; + } + let Some(batch_leaf_proof_mask) = batch_leaf_proof_mask else { + return Ok(None); + }; - println!("appended log: {:#?}", add_batch_log); + let result = chain_id_merkle_tree.merkle_root_and_path(batch_leaf_proof_mask); + let root = result.0; + let batch_leaf_proof = result.1; - let batch_root = H256::from_slice(&add_batch_log.data.0); - chain_id_merkle_tree - .push(Self::batch_leaf_preimage(batch_root, batch_number.as_u32())); + println!( + "EXPECTED ROOT FOR {} / {} = {}", + searched_chain_id, batch_leaf_proof_mask, root + ); - println!("new batch root = {:#?}", chain_id_merkle_tree.merkle_root()); + if batch_added_block_number.is_none() { + return Ok(None); + } + Ok(Some(( + LeafChainProof { + batch_leaf_proof, + batch_leaf_proof_mask: batch_leaf_proof_mask.into(), + }, + batch_added_block_number.unwrap(), + ))) + } - cnt += 1; - } + pub async fn get_chain_inclusion_proof_impl( + &self, + message_root_addr: Address, + searched_chain_id: u32, + batch_added_block_number: L2BlockNumber, + local_msg_root: H256, + ) -> Result, Web3Error> { + let mut storage = self.state.acquire_connection().await?; + let storage_key_num = U256::zero(); // kl todo + let storage_key = StorageKey::new( + AccountTreeId::new(message_root_addr), + u256_to_h256(storage_key_num), + ); + let chain_count = storage + .storage_web3_dal() + .get_historical_value_unchecked(storage_key.hashed_key(), batch_added_block_number) + .await + .map_err(DalError::generalize)?; + let chain_count_integer = chain_count.0[31]; + println!("kl todo chain count = {:#?}", chain_count_integer); - if chain_id.as_u32() == searched_chain_id { - let Some(batch_leaf_proof_mask) = batch_leaf_proof_mask else { - return Ok(None); - }; + let mut full_chain_merkle_tree = + MiniMerkleTree::<[u8; 96], KeccakHasher>::new(Vec::<[u8; 96]>::new().into_iter(), None); + let mut chain_id_leaf_proof_mask = None; - let result = chain_id_merkle_tree.merkle_root_and_path(batch_leaf_proof_mask); - let root = result.0; - batch_leaf_proof = result.1; + for i in 0..chain_count_integer { + let chain_id = self + .get_chain_id_from_index_impl(i.into(), batch_added_block_number) + .await + .unwrap(); + let chain_root = self + .get_chain_root_from_id_impl(chain_id, batch_added_block_number) + .await + .unwrap(); + full_chain_merkle_tree.push(Self::chain_id_leaf_preimage(chain_root, chain_id)); - println!( - "EXPECTED ROOT FOR {} / {} = {}", - searched_chain_id, batch_leaf_proof_mask, root - ); + if h256_to_u256(chain_id).as_u32() == searched_chain_id { + chain_id_leaf_proof_mask = Some(i as usize); } - - full_chain_merkle_tree.push(Self::chain_id_leaf_preimage( - chain_id_merkle_tree.merkle_root(), - chain_id.as_u32(), - )); } let Some(chain_id_leaf_proof_mask) = chain_id_leaf_proof_mask else { return Ok(None); }; + let chain_id_leaf_proof = full_chain_merkle_tree + .merkle_root_and_path(chain_id_leaf_proof_mask) + .1; + + println!( + "kl todo 2 {:?}, {:?}", + chain_id_leaf_proof_mask, + chain_id_leaf_proof.len() + ); + + let full_agg_root = full_chain_merkle_tree.merkle_root(); + println!( + "\n\n FULL AGG ROOT FOR BATCH = {:#?}\n\n", + hex::encode(full_agg_root.0) + ); let mut chain_id_leaf_proof = full_chain_merkle_tree .merkle_root_and_path(chain_id_leaf_proof_mask) .1; @@ -672,25 +721,88 @@ impl ZksNamespace { let chain_id_leaf_proof_mask = chain_id_leaf_proof_mask | (1 << (chain_id_leaf_proof.len() - 1)); - let full_agg_root = full_chain_merkle_tree.merkle_root(); - - let result = LeafAggProof { - batch_leaf_proof, - batch_leaf_proof_mask: batch_leaf_proof_mask.unwrap().into(), + Ok(Some(ChainAggProof { chain_id_leaf_proof, chain_id_leaf_proof_mask: chain_id_leaf_proof_mask.into(), - local_msg_root, - sl_batch_number: l1_batch_number_with_agg_batch.into(), - // this is the settlement layer - sl_chain_id: self.state.api_config.l2_chain_id.0.into(), - }; + })) + } - println!( - "\n\n FULL AGG ROOT FOR BATCH = {:#?}\n\n", - hex::encode(full_agg_root.0) - ); + pub async fn get_chain_id_from_index_impl( + &self, + index: u32, + block_number: L2BlockNumber, + ) -> Result { + let mut storage = self.state.acquire_connection().await?; - Ok(Some(result)) + let chain_id_mapping_slot = U256::from(2); + let chain_id_index = H256::from_slice(&keccak256( + &[ + u256_to_h256(U256::from(index)).0, + u256_to_h256(chain_id_mapping_slot).to_fixed_bytes(), + ] + .concat(), + )); + println!("kl todo chain_id_index = {:#?}", chain_id_index); + + let storage_key = self.get_message_root_log_key(chain_id_index); + let chain_id = storage + .storage_web3_dal() + .get_historical_value_unchecked(storage_key.hashed_key(), block_number) + .await + .map_err(DalError::generalize)?; + println!("kl todo chain_id = {:#?}", chain_id); + Ok(chain_id) + } + + pub async fn get_chain_root_from_id_impl( + &self, + chain_id: H256, + block_number: L2BlockNumber, + ) -> Result { + let mut storage = self.state.acquire_connection().await?; + + let chain_tree_mapping_slot = U256::from(7); + let chain_tree_slot = H256::from_slice(&keccak256( + &[ + chain_id.0, + u256_to_h256(chain_tree_mapping_slot).to_fixed_bytes(), + ] + .concat(), + )); + println!("kl todo chain_tree_slot = {:#?}", chain_tree_slot); + + let chain_sides_slot = u256_to_h256(h256_to_u256(chain_tree_slot) + 1); + println!("kl todo chain_sides_slot = {:#?}", chain_sides_slot); + + let length_storage_key = self.get_message_root_log_key(chain_sides_slot); + let length_encoding = storage + .storage_web3_dal() + .get_historical_value_unchecked(length_storage_key.hashed_key(), block_number) + .await + .map_err(DalError::generalize)?; + + let length = length_encoding.0[31] / 2; + let chain_root_slot = H256::from_slice(&keccak256( + &[ + u256_to_h256(U256::from(length)).0, + chain_sides_slot.to_fixed_bytes(), + ] + .concat(), + )); + println!("kl todo length_encoding = {:#?}", length_encoding); + println!("kl todo chain_root_slot = {:#?}", chain_root_slot); + let chain_root = storage + .storage_web3_dal() + .get_historical_value_unchecked(chain_root_slot, block_number) + .await + .map_err(DalError::generalize)?; + println!("kl todo chain_root = {:#?}", chain_root); + Ok(chain_root) + } + + pub fn get_message_root_log_key(&self, key: H256) -> StorageKey { + let message_root = AccountTreeId::new(L2_MESSAGE_ROOT_ADDRESS); + StorageKey::new(message_root, key) } pub fn batch_leaf_preimage(batch_root: H256, batch_number: u32) -> [u8; 96] { @@ -706,7 +818,7 @@ impl ZksNamespace { full_preimage } - pub fn chain_id_leaf_preimage(chain_root: H256, chain_id: u32) -> [u8; 96] { + pub fn chain_id_leaf_preimage(chain_root: H256, chain_id: H256) -> [u8; 96] { let prefix = hex::decode("39bc69363bb9e26cf14240de4e22569e95cf175cfbcf1ade1a47a253b4bf7f61") .unwrap(); @@ -714,7 +826,7 @@ impl ZksNamespace { full_preimage[0..32].copy_from_slice(&prefix); full_preimage[32..64].copy_from_slice(&chain_root.0); - full_preimage[64..96].copy_from_slice(&u256_to_h256(chain_id.into()).0); + full_preimage[64..96].copy_from_slice(&chain_id.0); full_preimage } @@ -1021,7 +1133,7 @@ impl LogLeafProof { } pub fn append_aggregation_layer(&mut self, proof: LeafAggProof) { - let chain_id_leaf_proof = proof.chain_id_leaf_proof.clone(); + let chain_id_leaf_proof = proof.chain_agg_proof.chain_id_leaf_proof.clone(); self.agg_proofs.last_mut().unwrap().batch_leaf_proof = Some(proof); self.agg_proofs.push(TreeLeafProof { leaf_proof: chain_id_leaf_proof, diff --git a/core/node/commitment_generator/src/lib.rs b/core/node/commitment_generator/src/lib.rs index 146f45cfbfd2..cd7fbf294efa 100644 --- a/core/node/commitment_generator/src/lib.rs +++ b/core/node/commitment_generator/src/lib.rs @@ -298,8 +298,8 @@ impl CommitmentGenerator { println!("message_root_addr = {:#?}", message_root_addr); - const FULL_TREE_SLOT: usize = 4; - const NODES_SLOT: usize = 6; + const FULL_TREE_SLOT: usize = 3; + const NODES_SLOT: usize = 5; let agg_tree_height_slot = StorageKey::new( AccountTreeId::new(message_root_addr), diff --git a/etc/env/base/contracts.toml b/etc/env/base/contracts.toml index 244db08e6dbc..f0d28c75f89f 100644 --- a/etc/env/base/contracts.toml +++ b/etc/env/base/contracts.toml @@ -28,11 +28,10 @@ RECURSION_NODE_LEVEL_VK_HASH = "0x1186ec268d49f1905f8d9c1e9d39fc33e98c74f91d91a2 RECURSION_LEAF_LEVEL_VK_HASH = "0x101e08b00193e529145ee09823378ef51a3bc8966504064f1f6ba3f1ba863210" RECURSION_CIRCUITS_SET_VKS_HASH = "0x18c1639094f58177409186e8c48d9f577c9410901d2f1d486b3e7d6cf553ae4c" GENESIS_TX_HASH = "0xb99ebfea46cbe05a21cd80fe5597d97b204befc52a16303f579c607dc1ac2e2e" -GENESIS_ROOT = "0xdc891cfaf85ba2cab541db37d6deac74e35cdf4a7e6eacbce5c49d9fee4d059b" -GENESIS_BATCH_COMMITMENT = "0xe09426f45a55576aeafa378f9722c0c9ace5306a9e7a2d93f5a3592879571e65" +GENESIS_ROOT = "0x678995482c5d8906b1eb7186bbfa7c26f52219bfc313e71ded325a83d7fc3365" +GENESIS_BATCH_COMMITMENT = "0x06ab1b686a90472959e8fd4747f3ac1d9f7710bf9f6bcf1c6b74085b25dd256d" PRIORITY_TX_MAX_GAS_LIMIT = 72000000 DEPLOY_L2_BRIDGE_COUNTERPART_GAS_LIMIT = 10000000 -GENESIS_ROLLUP_LEAF_INDEX = "71" GENESIS_PROTOCOL_VERSION = "25" GENESIS_PROTOCOL_SEMANTIC_VERSION = "0.25.2" L1_WETH_BRIDGE_IMPL_ADDR = "0x5E6D086F5eC079ADFF4FB3774CDf3e8D6a34F7E9" @@ -42,6 +41,7 @@ L2_WETH_BRIDGE_ADDR = "0x5E6D086F5eC079ADFF4FB3774CDf3e8D6a34F7E9" L2_WETH_TOKEN_IMPL_ADDR = "0x5E6D086F5eC079ADFF4FB3774CDf3e8D6a34F7E9" L2_WETH_TOKEN_PROXY_ADDR = "0x5E6D086F5eC079ADFF4FB3774CDf3e8D6a34F7E9" BLOB_VERSIONED_HASH_RETRIEVER_ADDR = "0x0000000000000000000000000000000000000000" +GENESIS_ROLLUP_LEAF_INDEX = "64" # Ecosystem-wide params L1_ROLLUP_DA_VALIDATOR = "0x0000000000000000000000000000000000000000" diff --git a/infrastructure/zk/src/init.ts b/infrastructure/zk/src/init.ts index 7ca860004491..3a4e817dc3d3 100644 --- a/infrastructure/zk/src/init.ts +++ b/infrastructure/zk/src/init.ts @@ -256,6 +256,15 @@ export const initHyperCmdAction = async ({ }); }; +export const configCmdAction = async (): Promise => { + await Promise.all([ + announced('Building L1 L2 contracts', contract.build(false)), + announced('Compile L2 system contracts', compiler.compileAll()) + ]); + await initDatabase(true); + await announced('Running server genesis setup', server.genesisFromSources()); +}; + // ########################### Command Definitions ########################### export const initCommand = new Command('init') .option('--skip-submodules-checkout') @@ -295,3 +304,5 @@ initCommand .option('--validium-mode', 'deploy contracts in Validium mode') .option('--run-observability', 'run observability suite') .action(initHyperCmdAction); + +initCommand.command('config').action(configCmdAction);