zksync_vm2/instruction_handlers/
decommit.rs1use primitive_types::U256;
2use zkevm_opcode_defs::{BlobSha256Format, ContractCodeSha256Format, VersionedHashLen32};
3use zksync_vm2_interface::{opcodes, Tracer};
4
5use super::common::boilerplate_ext;
6use crate::{
7 addressing_modes::{Arguments, Destination, Register1, Register2, Source},
8 decommit::materialize_decommit_page,
9 fat_pointer::FatPointer,
10 instruction::ExecutionStatus,
11 Instruction, VirtualMachine, World,
12};
13
14fn decommit<T: Tracer, W: World<T>>(
15 vm: &mut VirtualMachine<T, W>,
16 world: &mut W,
17 tracer: &mut T,
18) -> ExecutionStatus {
19 boilerplate_ext::<opcodes::Decommit, _, _>(vm, world, tracer, |vm, args, world, tracer| {
20 let code_hash = Register1::get(args, &mut vm.state);
21 let extra_cost = Register2::get(args, &mut vm.state).low_u32();
22
23 let mut buffer = [0u8; 32];
24 code_hash.to_big_endian(&mut buffer);
25
26 let preimage_len_in_bytes =
27 zkevm_opcode_defs::system_params::NEW_KERNEL_FRAME_MEMORY_STIPEND;
28
29 if vm.state.use_gas(extra_cost).is_err()
30 || (!ContractCodeSha256Format::is_valid(&buffer)
31 && !BlobSha256Format::is_valid(&buffer))
32 {
33 Register1::set(args, &mut vm.state, U256::zero());
34 return;
35 }
36
37 let (code, is_fresh) = vm.world_diff.decommit_opcode(world, tracer, code_hash);
38 if !is_fresh {
39 vm.state.current_frame.gas += extra_cost;
40 }
41
42 let heap = materialize_decommit_page(vm, code_hash, &code, vm.state.current_frame.heap);
43
44 let value = FatPointer {
45 offset: 0,
46 memory_page: heap,
47 start: 0,
48 length: preimage_len_in_bytes,
49 };
50 let value = value.into_u256();
51 Register1::set_fat_ptr(args, &mut vm.state, value);
52 })
53}
54
55impl<T: Tracer, W: World<T>> Instruction<T, W> {
56 pub fn from_decommit(
58 abi: Register1,
59 burn: Register2,
60 out: Register1,
61 arguments: Arguments,
62 ) -> Self {
63 Self {
64 arguments: arguments
65 .write_source(&abi)
66 .write_source(&burn)
67 .write_destination(&out),
68 handler: decommit,
69 }
70 }
71}