Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: decommit opcode #44

Merged
merged 12 commits into from
Jun 18, 2024
Merged
7 changes: 6 additions & 1 deletion src/decode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,12 @@ pub(crate) fn decode(raw: u64, is_bootloader: bool) -> Instruction {
out.try_into().unwrap(),
arguments,
),
x => unimplemented_instruction(zkevm_opcode_defs::Opcode::Log(x)),
zkevm_opcode_defs::LogOpcode::Decommit => Instruction::from_decommit(
src1.try_into().unwrap(),
src2,
out.try_into().unwrap(),
arguments,
),
},
zkevm_opcode_defs::Opcode::UMA(x) => {
let increment = parsed.variant.flags[UMA_INCREMENT_FLAG_IDX];
Expand Down
32 changes: 27 additions & 5 deletions src/decommit.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
use crate::{program::Program, world_diff::WorldDiff, World};
use u256::{H160, U256};
use u256::{H160, H256, U256};
use zkevm_opcode_defs::{
ethereum_types::Address, system_params::DEPLOYER_SYSTEM_CONTRACT_ADDRESS_LOW,
};

pub fn u256_to_h256(num: U256) -> H256 {
let mut bytes = [0u8; 32];
num.to_big_endian(&mut bytes);
H256::from_slice(&bytes)
}

impl WorldDiff {
pub(crate) fn decommit(
&mut self,
Expand Down Expand Up @@ -67,14 +73,23 @@ impl WorldDiff {
code_info[1] = 0;
let code_key: U256 = U256::from_big_endian(&code_info);

let cost = if self.decommitted_hashes.as_ref().contains_key(&code_key) {
println!("code key {:?}", H256::from(code_info));
let is_initial = self.decommitted_hashes.as_ref().contains_key(&code_key);
let cost = if is_initial {
0
} else {
let code_length_in_words = u16::from_be_bytes([code_info[2], code_info[3]]);
code_length_in_words as u32 * zkevm_opcode_defs::ERGS_PER_CODE_WORD_DECOMMITTMENT
};

Some((UnpaidDecommit { cost, code_key }, is_evm))
Some((
UnpaidDecommit {
cost,
code_key,
is_initial,
},
is_evm,
))
}

pub(crate) fn pay_for_decommit(
Expand All @@ -94,8 +109,15 @@ impl WorldDiff {
}

pub(crate) struct UnpaidDecommit {
cost: u32,
code_key: U256,
pub cost: u32,
joonazan marked this conversation as resolved.
Show resolved Hide resolved
pub code_key: U256,
pub is_initial: bool,
montekki marked this conversation as resolved.
Show resolved Hide resolved
}

impl UnpaidDecommit {
pub fn is_initial(&self) -> bool {
self.is_initial
}
}

/// May be used to load code when the VM first starts up.
Expand Down
1 change: 1 addition & 0 deletions src/fat_pointer.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::heap::HeapId;
use u256::U256;

#[derive(Debug)]
#[repr(C)]
pub struct FatPointer {
pub offset: u32,
Expand Down
117 changes: 117 additions & 0 deletions src/instruction_handlers/decommit.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
use u256::{H256, U256};
use zkevm_opcode_defs::{
BlobSha256Format, ContractCodeSha256Format, VersionedHashHeader, VersionedHashLen32,
VersionedHashNormalizedPreimage,
};

use crate::{
addressing_modes::{Addressable, Arguments, Destination, Register1, Register2, Source},
decommit::UnpaidDecommit,
fat_pointer::FatPointer,
instruction::InstructionResult,
Instruction, VirtualMachine, World,
};

use super::{common::instruction_boilerplate_with_panic, HeapInterface};

pub fn u256_to_h256(num: U256) -> H256 {
let mut bytes = [0u8; 32];
num.to_big_endian(&mut bytes);
H256::from_slice(&bytes)
}

fn decommit(
vm: &mut VirtualMachine,
instruction: *const Instruction,
world: &mut dyn World,
) -> InstructionResult {
instruction_boilerplate_with_panic(
vm,
instruction,
world,
|vm, args, world, continue_normally| {
let extra_cost = Register2::get(args, &mut vm.state).low_u32();
let code_hash = Register1::get(args, &mut vm.state);

/*
let unpaid_decommit = vm.world_diff.decommit(
world,
CodeInfo::CodeHash(code_hash),
vm.settings.default_aa_code_hash,
vm.settings.evm_interpreter_code_hash,
vm.state.in_kernel_mode(),
);

if unpaid_decommit.as_ref().unwrap().0.is_initial() {
vm.state.current_frame.gas.saturating_sub(extra_cost);
}
*/

let unpaid_decommit = UnpaidDecommit {
cost: 1000,
code_key: code_hash,
is_initial: true,
};

let decommit_result = vm.world_diff.pay_for_decommit(
world,
unpaid_decommit,
&mut vm.state.current_frame.gas,
);

let heap = vm.state.heaps.allocate();
montekki marked this conversation as resolved.
Show resolved Hide resolved
let mut length = decommit_result
.as_ref()
.unwrap()
.code_page()
.as_ref()
.len()
.try_into()
.unwrap();

length *= 32;

for (i, word) in decommit_result
.unwrap()
.code_page()
.as_ref()
.iter()
.enumerate()
{
let mut bytes = [0; 32];
word.to_big_endian(&mut bytes);
let h: H256 = H256::from(bytes);

vm.state.heaps[heap].write_u256((i * 32) as u32, *word);
montekki marked this conversation as resolved.
Show resolved Hide resolved
}

let value = FatPointer {
offset: 0,
memory_page: heap,
start: 0,
length,
};
dbg!(&value);
let value = value.into_u256();
Register1::set_fat_ptr(args, &mut vm.state, value);

continue_normally
},
)
}
impl Instruction {
pub fn from_decommit(
abi: Register1,
burn: Register2,
out: Register1,
arguments: Arguments,
) -> Self {
Self {
arguments: arguments
.write_source(&abi)
.write_source(&burn)
.write_destination(&out),
handler: decommit,
}
}
}
1 change: 1 addition & 0 deletions src/instruction_handlers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ pub(crate) use ret::{free_panic, PANIC};
mod binop;
mod common;
mod context;
mod decommit;
mod event;
mod far_call;
mod heap_access;
Expand Down
4 changes: 4 additions & 0 deletions src/program.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ impl Program {
self.instructions.get::<usize>(n.into())
}

pub fn instructions(&self) -> &[Instruction] {
montekki marked this conversation as resolved.
Show resolved Hide resolved
&self.instructions
}

pub fn code_page(&self) -> &Arc<[U256]> {
&self.code_page
}
Expand Down
2 changes: 2 additions & 0 deletions src/single_instruction_test/heap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ impl HeapInterface for Heap {
self.write = Some((start_address, value));
}

fn memset(&mut self, mem: &[U256]) {}

fn read_range_big_endian(&self, _: std::ops::Range<u32>) -> Vec<u8> {
// This is wrong, but this method is only used to get the final return value.
vec![]
Expand Down
5 changes: 0 additions & 5 deletions src/single_instruction_test/vm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,6 @@ impl VirtualMachine {
}

pub fn instruction_is_not_precompile_call(&self) -> bool {
// TODO PLA-934 implement Decommit
if self.current_opcode() == 1093 {
return false;
}

// TODO PLA-972 implement StaticMemoryRead/Write
if (1096..=1103).contains(&self.current_opcode()) {
return false;
Expand Down
Loading