Skip to main content

zksync_vm2/instruction_handlers/
decommit.rs

1use 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    /// Creates a [`Decommit`](opcodes::Decommit) instruction with the provided params.
57    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}