Skip to content

Commit

Permalink
chore: restore DA hash test (#3191)
Browse files Browse the repository at this point in the history
## What ❔

Restore test + clean up

## Why ❔

<!-- Why are these changes done? What goal do they contribute to? What
are the principles behind them? -->
<!-- Example: PR templates ensure PR reviewers, observers, and future
iterators are in context about the evolution of repos. -->

## Checklist

<!-- Check your PR fulfills the following items. -->
<!-- For draft PRs check the boxes as you complete them. -->

- [ ] 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 `zkstack dev fmt` and `zkstack dev
lint`.
  • Loading branch information
perekopskiy authored Oct 29, 2024
1 parent 8d6de59 commit c291a2b
Show file tree
Hide file tree
Showing 15 changed files with 263 additions and 303 deletions.
50 changes: 0 additions & 50 deletions .github/scripts/gateway.sh

This file was deleted.

1 change: 0 additions & 1 deletion bin/last_chain_id

This file was deleted.

22 changes: 0 additions & 22 deletions bin/start_sync_layer_gateway.sh

This file was deleted.

30 changes: 0 additions & 30 deletions bin/start_sync_layer_l3_chain.sh

This file was deleted.

23 changes: 0 additions & 23 deletions core/lib/basic_types/src/vm_version.rs

This file was deleted.

40 changes: 34 additions & 6 deletions core/lib/multivm/src/versions/shadow/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
use std::{collections::HashSet, rc::Rc};

use zksync_types::{writes::StateDiffRecord, StorageKey, Transaction, H256, U256};
use zksync_vm_interface::pubdata::PubdataBuilder;
use zksync_vm_interface::pubdata::{PubdataBuilder, PubdataInput};

use super::ShadowedFastVm;
use crate::{
Expand Down Expand Up @@ -120,11 +120,30 @@ impl TestedVm for ShadowedFastVm {
});
}

fn push_transaction_with_refund(&mut self, tx: Transaction, refund: u64) {
self.get_mut("push_transaction_with_refund", |r| match r {
ShadowMut::Main(vm) => vm.push_transaction_with_refund(tx.clone(), refund),
ShadowMut::Shadow(vm) => vm.push_transaction_with_refund(tx.clone(), refund),
});
fn push_transaction_with_refund_and_compression(
&mut self,
tx: Transaction,
refund: u64,
compression: bool,
) {
self.get_mut(
"push_transaction_with_refund_and_compression",
|r| match r {
ShadowMut::Main(vm) => {
vm.push_transaction_with_refund_and_compression(tx.clone(), refund, compression)
}
ShadowMut::Shadow(vm) => {
vm.push_transaction_with_refund_and_compression(tx.clone(), refund, compression)
}
},
);
}

fn pubdata_input(&self) -> PubdataInput {
self.get("pubdata_input", |r| match r {
ShadowRef::Main(vm) => vm.pubdata_input(),
ShadowRef::Shadow(vm) => vm.pubdata_input(),
})
}
}

Expand Down Expand Up @@ -234,6 +253,15 @@ impl TestedVm for ShadowedFastVm {
// }
// }
//
// mod l1_messenger {
// use crate::versions::testonly::l1_messenger::*;
//
// #[test]
// fn rollup_da_output_hash_match() {
// test_rollup_da_output_hash_match::<super::ShadowedFastVm>();
// }
// }
//
// mod l1_tx_execution {
// use crate::versions::testonly::l1_tx_execution::*;
//
Expand Down
166 changes: 166 additions & 0 deletions core/lib/multivm/src/versions/testonly/l1_messenger.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
// TODO: move to shared tests

use std::rc::Rc;

use ethabi::Token;
use zksync_contracts::{l1_messenger_contract, l2_rollup_da_validator_bytecode};
use zksync_test_account::TxType;
use zksync_types::{
web3::keccak256, Address, Execute, ProtocolVersionId, L1_MESSENGER_ADDRESS, U256,
};
use zksync_utils::{address_to_h256, u256_to_h256};

use super::{read_test_contract, ContractToDeploy, TestedVm, VmTesterBuilder};
use crate::{
interface::{
pubdata::{PubdataBuilder, PubdataInput},
InspectExecutionMode, TxExecutionMode, VmInterfaceExt,
},
pubdata_builders::RollupPubdataBuilder,
vm_latest::constants::ZK_SYNC_BYTES_PER_BLOB,
};

const L2_DA_VALIDATOR_OUTPUT_HASH_KEY: usize = 5;
const USED_L2_DA_VALIDATOR_ADDRESS_KEY: usize = 6;

fn encoded_uncompressed_state_diffs(input: &PubdataInput) -> Vec<u8> {
let mut result = vec![];
for state_diff in input.state_diffs.iter() {
result.extend(state_diff.encode_padded());
}
result
}

fn compose_header_for_l1_commit_rollup(input: PubdataInput) -> Vec<u8> {
// The preimage under the hash `l2DAValidatorOutputHash` is expected to be in the following format:
// - First 32 bytes are the hash of the uncompressed state diff.
// - Then, there is a 32-byte hash of the full pubdata.
// - Then, there is the 1-byte number of blobs published.
// - Then, there are linear hashes of the published blobs, 32 bytes each.

let mut full_header = vec![];

let uncompressed_state_diffs = encoded_uncompressed_state_diffs(&input);
let uncompressed_state_diffs_hash = keccak256(&uncompressed_state_diffs);
full_header.extend(uncompressed_state_diffs_hash);

let pubdata_builder = RollupPubdataBuilder::new(Address::zero());
let mut full_pubdata =
pubdata_builder.settlement_layer_pubdata(&input, ProtocolVersionId::latest());
let full_pubdata_hash = keccak256(&full_pubdata);
full_header.extend(full_pubdata_hash);

// Now, we need to calculate the linear hashes of the blobs.
// Firstly, let's pad the pubdata to the size of the blob.
if full_pubdata.len() % ZK_SYNC_BYTES_PER_BLOB != 0 {
let padding =
vec![0u8; ZK_SYNC_BYTES_PER_BLOB - full_pubdata.len() % ZK_SYNC_BYTES_PER_BLOB];
full_pubdata.extend(padding);
}
full_header.push((full_pubdata.len() / ZK_SYNC_BYTES_PER_BLOB) as u8);

full_pubdata
.chunks(ZK_SYNC_BYTES_PER_BLOB)
.for_each(|chunk| {
full_header.extend(keccak256(chunk));
});

full_header
}

pub(crate) fn test_rollup_da_output_hash_match<VM: TestedVm>() {
// In this test, we check whether the L2 DA output hash is as expected.

let l2_da_validator_address = Address::repeat_byte(0x12);
let mut vm = VmTesterBuilder::new()
.with_empty_in_memory_storage()
.with_execution_mode(TxExecutionMode::VerifyExecute)
.with_rich_accounts(1)
.with_custom_contracts(vec![ContractToDeploy {
bytecode: l2_rollup_da_validator_bytecode(),
address: l2_da_validator_address,
is_account: false,
is_funded: false,
}])
.build::<VM>();

let account = &mut vm.rich_accounts[0];

// Firstly, deploy tx. It should publish the bytecode of the "test contract"
let counter = read_test_contract();

let tx = account.get_deploy_tx(&counter, None, TxType::L2).tx;
// We do not use compression here, to have the bytecode published in full.
vm.vm
.push_transaction_with_refund_and_compression(tx, 0, false);
let result = vm.vm.execute(InspectExecutionMode::OneTx);
assert!(!result.result.is_failed(), "Transaction wasn't successful");

// Then, we call the l1 messenger to also send an L2->L1 message.
let l1_messenger_contract = l1_messenger_contract();
let encoded_data = l1_messenger_contract
.function("sendToL1")
.unwrap()
.encode_input(&[Token::Bytes(vec![])])
.unwrap();

let tx = account.get_l2_tx_for_execute(
Execute {
contract_address: Some(L1_MESSENGER_ADDRESS),
calldata: encoded_data,
value: U256::zero(),
factory_deps: vec![],
},
None,
);
vm.vm.push_transaction(tx);
let result = vm.vm.execute(InspectExecutionMode::OneTx);
assert!(!result.result.is_failed(), "Transaction wasn't successful");

let pubdata_builder = RollupPubdataBuilder::new(l2_da_validator_address);
let batch_result = vm.vm.finish_batch(Rc::new(pubdata_builder));
assert!(
!batch_result.block_tip_execution_result.result.is_failed(),
"Transaction wasn't successful {:?}",
batch_result.block_tip_execution_result.result
);
let pubdata_input = vm.vm.pubdata_input();

// Just to double check that the test makes sense.
assert!(!pubdata_input.user_logs.is_empty());
assert!(!pubdata_input.l2_to_l1_messages.is_empty());
assert!(!pubdata_input.published_bytecodes.is_empty());
assert!(!pubdata_input.state_diffs.is_empty());

let expected_header: Vec<u8> = compose_header_for_l1_commit_rollup(pubdata_input);

let l2_da_validator_output_hash = batch_result
.block_tip_execution_result
.logs
.system_l2_to_l1_logs
.iter()
.find(|log| log.0.key == u256_to_h256(L2_DA_VALIDATOR_OUTPUT_HASH_KEY.into()))
.unwrap()
.0
.value;

assert_eq!(
l2_da_validator_output_hash,
keccak256(&expected_header).into()
);

let l2_used_da_validator_address = batch_result
.block_tip_execution_result
.logs
.system_l2_to_l1_logs
.iter()
.find(|log| log.0.key == u256_to_h256(USED_L2_DA_VALIDATOR_ADDRESS_KEY.into()))
.unwrap()
.0
.value;

assert_eq!(
l2_used_da_validator_address,
address_to_h256(&l2_da_validator_address)
);
}
1 change: 1 addition & 0 deletions core/lib/multivm/src/versions/testonly/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ pub(super) mod default_aa;
pub(super) mod gas_limit;
pub(super) mod get_used_contracts;
pub(super) mod is_write_initial;
pub(super) mod l1_messenger;
pub(super) mod l1_tx_execution;
pub(super) mod l2_blocks;
pub(super) mod nonce_holder;
Expand Down
9 changes: 6 additions & 3 deletions core/lib/multivm/src/versions/testonly/refunds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,11 @@ pub(crate) fn test_predetermined_refunded_gas<VM: TestedVm>() {
.build::<VM>();
assert_eq!(account.address(), vm.rich_accounts[0].address());

vm.vm
.push_transaction_with_refund(tx.clone(), result.refunds.gas_refunded);
vm.vm.push_transaction_with_refund_and_compression(
tx.clone(),
result.refunds.gas_refunded,
true,
);

let result_with_predefined_refunds = vm
.vm
Expand Down Expand Up @@ -112,7 +115,7 @@ pub(crate) fn test_predetermined_refunded_gas<VM: TestedVm>() {

let changed_operator_suggested_refund = result.refunds.gas_refunded + 1000;
vm.vm
.push_transaction_with_refund(tx, changed_operator_suggested_refund);
.push_transaction_with_refund_and_compression(tx, changed_operator_suggested_refund, true);
let result = vm
.vm
.finish_batch(default_pubdata_builder())
Expand Down
Loading

0 comments on commit c291a2b

Please sign in to comment.