Skip to content

Commit

Permalink
initial commit: test_code_oracle works
Browse files Browse the repository at this point in the history
  • Loading branch information
montekki committed Jun 14, 2024
1 parent 32d4268 commit e1b771c
Show file tree
Hide file tree
Showing 12 changed files with 173 additions and 13 deletions.
Binary file not shown.
Binary file removed afl-fuzz/in/return_calldata
Binary file not shown.
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,
pub code_key: U256,
pub is_initial: bool,
}

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();
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);
}

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] {
&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
16 changes: 14 additions & 2 deletions src/state.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::{
addressing_modes::Addressable,
callframe::Callframe,
decommit::u256_into_address,
fat_pointer::FatPointer,
heap::{Heaps, CALLDATA_HEAP, FIRST_AUX_HEAP, FIRST_HEAP},
predication::Flags,
Expand All @@ -10,7 +11,7 @@ use crate::{
};
use u256::{H160, U256};

#[derive(Clone, PartialEq, Debug)]
#[derive(Clone, PartialEq)]
pub struct State {
pub registers: [U256; 16],
pub(crate) register_pointer_flags: u16,
Expand All @@ -30,6 +31,17 @@ pub struct State {
pub(crate) context_u128: u128,
}

impl std::fmt::Debug for State {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("State")
.field("registers", &self.registers)
.field("register_pointer_flags", &self.register_pointer_flags)
.field("flags", &self.flags)
.field("callframe", &self.current_frame)
.finish()
}
}

impl State {
pub(crate) fn new(
address: H160,
Expand All @@ -40,7 +52,7 @@ impl State {
world_before_this_frame: Snapshot,
stack: Box<Stack>,
) -> Self {
let mut registers: [U256; 16] = Default::default();
let mut registers = [0.into(); 16];
registers[1] = FatPointer {
memory_page: CALLDATA_HEAP,
offset: 0,
Expand Down
1 change: 1 addition & 0 deletions src/vm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,7 @@ impl VirtualMachine {

#[cfg(feature = "trace")]
fn print_instruction(&self, instruction: *const Instruction) {
return;
print!("{:?}: ", unsafe {
instruction.offset_from(self.state.current_frame.program.instruction(0).unwrap())
});
Expand Down

0 comments on commit e1b771c

Please sign in to comment.