Skip to content

Commit

Permalink
chore: update to compatibility with latest version of vm2 (#9)
Browse files Browse the repository at this point in the history
Co-authored-by: Fedor Sakharov <[email protected]>
  • Loading branch information
joonazan and montekki authored May 23, 2024
1 parent d89a149 commit 7190031
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 59 deletions.
23 changes: 23 additions & 0 deletions Cargo.lock

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

2 changes: 1 addition & 1 deletion compiler_tester/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ zkevm-assembly = { git = "https://github.com/matter-labs/era-zkEVM-assembly", br
zkevm_opcode_defs = { git = "https://github.com/matter-labs/era-zkevm_opcode_defs", branch = "v1.5.0" }
zkevm_tester = { git = "https://github.com/matter-labs/era-zkevm_tester", branch = "v1.5.0" }

# vm2 = { git = "https://github.com/matter-labs/vm2", optional = true }
vm2 = { git = "https://github.com/matter-labs/vm2", optional = true }

era-compiler-common = { git = "https://github.com/matter-labs/era-compiler-common", branch = "main" }
era-compiler-llvm-context = { git = "https://github.com/matter-labs/era-compiler-llvm-context", branch = "main" }
Expand Down
147 changes: 89 additions & 58 deletions compiler_tester/src/vm/eravm/vm2_adapter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@
use std::collections::HashMap;

use web3::ethabi::Address;

use crate::vm::execution_result::ExecutionResult;
use anyhow::anyhow;
use vm2::initial_decommit;
use vm2::ExecutionEnd;
use vm2::Program;
use vm2::World;
use zkevm_assembly::zkevm_opcode_defs::Assembly;
use zkevm_assembly::Assembly;
use zkevm_opcode_defs::ethereum_types::{BigEndianHash, H256, U256};
use zkevm_tester::runners::compiler_tests::FullABIParams;
use zkevm_tester::runners::compiler_tests::StorageKey;
Expand All @@ -21,7 +23,6 @@ use crate::test::case::input::{
output::{event::Event, Output},
value::Value,
};
use crate::vm::eravm::execution_result::ExecutionResult;

pub fn run_vm(
contracts: HashMap<web3::ethabi::Address, Assembly>,
Expand Down Expand Up @@ -54,28 +55,34 @@ pub fn run_vm(
r5_value: None,
},
VmLaunchOption::ManualCallABI(abiparams) => abiparams,
x => return Err(anyhow::anyhow!("Unsupported launch option {x:?}")),
x => return Err(anyhow!("Unsupported launch option {x:?}")),
};

for (_, contract) in contracts {
let bytecode = contract.clone().compile_to_bytecode()?;
let hash = zkevm_assembly::zkevm_opcode_defs::bytecode_to_code_hash(&bytecode)?;
let hash = zkevm_assembly::zkevm_opcode_defs::bytecode_to_code_hash(&bytecode)
.map_err(|()| anyhow!("Failed to hash bytecode"))?;
known_contracts.insert(U256::from_big_endian(&hash), contract);
}

let context = context.unwrap_or_default();

let mut world = TestWorld {
storage,
contracts: known_contracts.clone(),
};
let initial_program = initial_decommit(&mut world, entry_address);

let mut vm = vm2::VirtualMachine::new(
Box::new(TestWorld {
storage,
contracts: known_contracts.clone(),
}),
entry_address,
initial_program,
context.msg_sender,
calldata.to_vec(),
u32::MAX,
// zkevm_tester subtracts this constant, I don't know why
u32::MAX - 0x80000000,
vm2::Settings {
default_aa_code_hash,
default_aa_code_hash: default_aa_code_hash.into(),
evm_interpreter_code_hash: evm_interpreter_code_hash.into(),
hook_address: 0,
},
);
Expand All @@ -90,48 +97,62 @@ pub fn run_vm(
vm.state.registers[4] = abi_params.r4_value.unwrap_or_default();
vm.state.registers[5] = abi_params.r5_value.unwrap_or_default();

let output = match vm.run() {
ExecutionEnd::ProgramFinished(return_value) => Output {
return_data: chunk_return_data(&return_value),
exception: false,
events: merge_events(vm.world.events()),
},
let mut storage_changes = HashMap::new();
let mut deployed_contracts = HashMap::new();

let output = match vm.run(&mut world) {
ExecutionEnd::ProgramFinished(return_value) => {
// Only successful transactions can have side effects
// The VM doesn't undo side effects done in the initial frame
// because that would mess with the bootloader.

storage_changes = vm
.world_diff
.get_storage_state()
.iter()
.map(|(&(address, key), value)| {
(StorageKey { address, key }, H256::from_uint(value))
})
.collect::<HashMap<_, _>>();
deployed_contracts = vm
.world_diff
.get_storage_state()
.iter()
.filter_map(|((address, key), value)| {
if *address == *zkevm_assembly::zkevm_opcode_defs::system_params::DEPLOYER_SYSTEM_CONTRACT_ADDRESS {
let mut buffer = [0u8; 32];
key.to_big_endian(&mut buffer);
let deployed_address = web3::ethabi::Address::from_slice(&buffer[12..]);
if let Some(code) = known_contracts.get(&value) {
Some((deployed_address, code.clone()))
} else {
None
}
} else {
None
}
})
.collect::<HashMap<_, _>>();

Output {
return_data: chunk_return_data(&return_value),
exception: false,
events: merge_events(vm.world_diff.events()),
}
}
ExecutionEnd::Reverted(return_value) => Output {
return_data: chunk_return_data(&return_value),
exception: true,
events: vec![],
},
_panic => Output {
ExecutionEnd::Panicked => Output {
return_data: vec![],
exception: true,
events: vec![],
},
ExecutionEnd::SuspendedOnHook { .. } => unreachable!(),
};

let storage_changes = vm
.world
.get_storage_changes()
.map(|((address, key), value)| (StorageKey { address, key }, H256::from_uint(&value)))
.collect::<HashMap<_, _>>();
let deployed_contracts = vm
.world
.get_storage_changes()
.filter_map(|((address, key), value)| {
if address == *zkevm_assembly::zkevm_opcode_defs::system_params::DEPLOYER_SYSTEM_CONTRACT_ADDRESS {
let mut buffer = [0u8; 32];
key.to_big_endian(&mut buffer);
let deployed_address = web3::ethabi::Address::from_slice(&buffer[12..]);
if let Some(code) = known_contracts.get(&value) {
Some((deployed_address, code.clone()))
} else {
None
}
} else {
None
}
})
.collect::<HashMap<_, _>>();

Ok((
ExecutionResult {
output,
Expand All @@ -150,17 +171,15 @@ struct TestWorld {
}

impl World for TestWorld {
fn decommit(
&mut self,
hash: U256,
) -> (std::sync::Arc<[vm2::Instruction]>, std::sync::Arc<[U256]>) {
let bytecode = self
fn decommit(&mut self, hash: U256) -> Program {
let Some(bytecode) = self
.contracts
.get(&hash)
.unwrap()
.clone()
.compile_to_bytecode()
.unwrap();
.map(|assembly| assembly.clone().compile_to_bytecode().unwrap())
else {
// This case only happens when a contract fails to deploy but the assumes it did deploy
return Program::new(vec![vm2::Instruction::from_invalid()], vec![]);
};
let instructions = bytecode
.iter()
.flat_map(|x| {
Expand All @@ -169,13 +188,12 @@ impl World for TestWorld {
})
.collect::<Vec<_>>();

(
vm2::decode::decode_program(&instructions, false).into(),
Program::new(
vm2::decode::decode_program(&instructions, false),
bytecode
.iter()
.map(|x| U256::from_big_endian(x))
.collect::<Vec<_>>()
.into(),
.collect::<Vec<_>>(),
)
}

Expand All @@ -193,8 +211,20 @@ impl World for TestWorld {
.unwrap_or(U256::zero())
}

fn handle_hook(&mut self, _: u32) {
unreachable!() // There is no bootloader
fn cost_of_writing_storage(
&mut self,
contract: web3::types::H160,
key: U256,
new_value: U256,
) -> u32 {
0
}

fn is_free_storage_slot(&self, contract: &web3::types::H160, key: &U256) -> bool {
self.storage.contains_key(&StorageKey {
address: *contract,
key: *key,
})
}
}

Expand Down Expand Up @@ -231,6 +261,7 @@ fn merge_events(events: &[vm2::Event]) -> Vec<Event> {
key,
value,
} = *message;
let tx_number = tx_number.into();

if !is_first {
if let Some((mut remaining_data_length, mut remaining_topics, mut event)) =
Expand Down

0 comments on commit 7190031

Please sign in to comment.