From 3896366ddfbf0c5e8287ed6a95079dcd401d7a68 Mon Sep 17 00:00:00 2001 From: Mason Liang Date: Mon, 5 Dec 2022 15:16:40 -0500 Subject: [PATCH 01/69] wip --- eth-types/src/evm_types.rs | 2 +- zkevm-circuits/src/evm_circuit/execution.rs | 8 +- .../src/evm_circuit/execution/create.rs | 374 ++++++++++++++++++ .../evm_circuit/util/constraint_builder.rs | 23 ++ 4 files changed, 402 insertions(+), 5 deletions(-) create mode 100644 zkevm-circuits/src/evm_circuit/execution/create.rs diff --git a/eth-types/src/evm_types.rs b/eth-types/src/evm_types.rs index 63733e3445..95ee1ac34a 100644 --- a/eth-types/src/evm_types.rs +++ b/eth-types/src/evm_types.rs @@ -98,7 +98,7 @@ impl GasCost { pub const SHA3: Self = Self(30); /// Constant cost for SELFDESTRUCT pub const SELFDESTRUCT: Self = Self(5000); - /// Constant cost for CREATE + /// Constant cost for CREATE and CREATE2 pub const CREATE: Self = Self(32000); /// Constant cost for copying every word pub const COPY: Self = Self(3); diff --git a/zkevm-circuits/src/evm_circuit/execution.rs b/zkevm-circuits/src/evm_circuit/execution.rs index 99b7c85013..318f32f618 100644 --- a/zkevm-circuits/src/evm_circuit/execution.rs +++ b/zkevm-circuits/src/evm_circuit/execution.rs @@ -45,6 +45,7 @@ mod chainid; mod codecopy; mod codesize; mod comparator; +mod create; mod dummy; mod dup; mod end_block; @@ -105,6 +106,7 @@ use chainid::ChainIdGadget; use codecopy::CodeCopyGadget; use codesize::CodesizeGadget; use comparator::ComparatorGadget; +use create::CreateGadget; use dummy::DummyGadget; use dup::DupGadget; use end_block::EndBlockGadget; @@ -232,8 +234,7 @@ pub(crate) struct ExecutionConfig { extcodecopy_gadget: DummyGadget, returndatasize_gadget: ReturnDataSizeGadget, returndatacopy_gadget: ReturnDataCopyGadget, - create_gadget: DummyGadget, - create2_gadget: DummyGadget, + create_gadget: CreateGadget, selfdestruct_gadget: DummyGadget, signed_comparator_gadget: SignedComparatorGadget, signextend_gadget: SignextendGadget, @@ -471,7 +472,6 @@ impl ExecutionConfig { returndatasize_gadget: configure_gadget!(), returndatacopy_gadget: configure_gadget!(), create_gadget: configure_gadget!(), - create2_gadget: configure_gadget!(), selfdestruct_gadget: configure_gadget!(), shl_shr_gadget: configure_gadget!(), signed_comparator_gadget: configure_gadget!(), @@ -1013,13 +1013,13 @@ impl ExecutionConfig { ExecutionState::BLOCKCTXU256 => assign_exec_step!(self.block_ctx_u256_gadget), ExecutionState::BLOCKHASH => assign_exec_step!(self.blockhash_gadget), ExecutionState::SELFBALANCE => assign_exec_step!(self.selfbalance_gadget), + ExecutionState::CREATE => assign_exec_step!(self.create_gadget), // dummy gadgets ExecutionState::BALANCE => assign_exec_step!(self.balance_gadget), ExecutionState::SAR => assign_exec_step!(self.sar_gadget), ExecutionState::EXTCODESIZE => assign_exec_step!(self.extcodesize_gadget), ExecutionState::EXTCODECOPY => assign_exec_step!(self.extcodecopy_gadget), ExecutionState::CREATE => assign_exec_step!(self.create_gadget), - ExecutionState::CREATE2 => assign_exec_step!(self.create2_gadget), ExecutionState::SELFDESTRUCT => assign_exec_step!(self.selfdestruct_gadget), // end of dummy gadgets ExecutionState::SHA3 => assign_exec_step!(self.sha3_gadget), diff --git a/zkevm-circuits/src/evm_circuit/execution/create.rs b/zkevm-circuits/src/evm_circuit/execution/create.rs new file mode 100644 index 0000000000..ad241ab7de --- /dev/null +++ b/zkevm-circuits/src/evm_circuit/execution/create.rs @@ -0,0 +1,374 @@ +use crate::{ + evm_circuit::{ + execution::ExecutionGadget, + param::{N_BYTES_ACCOUNT_ADDRESS, N_BYTES_GAS, N_BYTES_MEMORY_WORD_SIZE}, + step::ExecutionState, + util::{ + common_gadget::TransferGadget, + constraint_builder::{ + ConstraintBuilder, ReversionInfo, StepStateTransition, + Transition::{Delta, To}, + }, + from_bytes, + math_gadget::{ + BatchedIsZeroGadget, ConstantDivisionGadget, IsEqualGadget, IsZeroGadget, + MinMaxGadget, + }, + memory_gadget::{MemoryAddressGadget, MemoryExpansionGadget}, + select, sum, CachedRegion, Cell, Word, + }, + witness::{Block, Call, ExecStep, Transaction}, + }, + table::{AccountFieldTag, CallContextFieldTag}, + util::Expr, +}; +use crate::evm_circuit::util::RandomLinearCombination; +use bus_mapping::evm::OpcodeId; +use eth_types::{ + evm_types::{GasCost, GAS_STIPEND_CALL_WITH_VALUE}, + Field, ToLittleEndian, ToScalar, U256, ToAddress, +}; +use halo2_proofs::{circuit::Value, plonk::Error}; +use keccak256::EMPTY_HASH_LE; + +/// Gadget for CREATE and CREATE2 opcodes +#[derive(Clone, Debug)] +pub(crate) struct CreateGadget { + opcode: Cell, + is_create2: Cell, + + new_address: RandomLinearCombination, + + // tx access list for new address + tx_id: Cell, + is_warm_prev: Cell, + reversion_info: ReversionInfo, + // + // // transfer value to new address + // transfer: TransferGadget, + // callee_reversion_info: ReversionInfo, + // + // // memory + // caller_memory_address: MemoryAddressGadget, + // memory_expansion: MemoryExpansionGadget, + // // new call context + // current_address: Cell, + // depth: Cell, + // gas: Word, + // callee_address: Word, + // value: Word, + // is_success: Cell, + // gas_is_u64: IsZeroGadget, + // + // // gas + // one_64th_gas: ConstantDivisionGadget, + // capped_callee_gas_left: MinMaxGadget, + + // errors: + // is_empty_nonce_and_balance: BatchedIsZeroGadget, + // is_empty_code_hash: IsEqualGadget, +} + +impl ExecutionGadget for CreateGadget { + const NAME: &'static str = "CREATE"; + + const EXECUTION_STATE: ExecutionState = ExecutionState::CREATE; + + fn configure(cb: &mut ConstraintBuilder) -> Self { + let opcode = cb.query_cell(); + cb.opcode_lookup(opcode.expr(), 1.expr()); + + let is_create2 = cb.query_bool(); + cb.require_equal( + "Opcode is CREATE or CREATE2", + opcode.expr(), + select::expr( + is_create2.expr(), + OpcodeId::CREATE2.expr(), + OpcodeId::CREATE.expr(), + ), + ); + + let new_address = cb.query_rlc(); + let mut reversion_info = cb.reversion_info_read(None); + let is_warm_prev = cb.query_bool(); + let tx_id = cb.call_context(None, CallContextFieldTag::TxId); + cb.account_access_list_write( + tx_id.expr(), + from_bytes::expr(&new_address.cells), + 1.expr(), + is_warm_prev.expr(), + Some(&mut reversion_info), + ); + // let access_list = AccountAccessListGadget::construct(cb, + // callee_address.expr()); cb.add_account_to_access_list(callee_address. + // expr()); + + // let caller_address = cb.call_context(None, + // CallContextFieldTag::CalleeAddress); let [callee_address, value, + // callee_address] = [(); 3].map(|| cb.query_word()); let is_failure = + // IsZeroGadget::construct(cb, callee_address); + // let mut callee_reversion_info = + // ReversionInfo::from_caller(cb, &reversion_info, + // not::expr(is_failure.expr())); let transfer = + // TransferGadget::construct( cb, + // caller_address.expr(), + // address.expr(), + // value.expr(), + // &mut callee_reversion_info, + // ); + + // let [offset, size] = [(); 2].map(|| cb.query_word()); + // let memory_address = MemoryAddressGadget::construct(cb, offset, size); + // let memory_expansion = MemoryExpansionGadget::construct( + // cb, + // cb.curr.state.memory_word_size.expr(), + // [memory_address.address()], + // ); + // + // let [value, offset, size, salt, address] = [(); 5].map(cb.query_cell()); + // [value, offset, size].map(|cell| cb.stack_pop(cell.expr())); + // cb.condition(is_create2.expr(), |cb| cb.stack_pop(salt.expr())); + // cb.stack_push(address); + // + // let [current_address, is_static, depth] = [ + // CallContextFieldTag::CalleeAddress, + // CallContextFieldTag::IsStatic, + // CallContextFieldTag::Depth, + // ] + // .map(|field_tag| cb.call_context(None, field_tag)); + // + // cb.range_lookup(depth.expr(), 1024); + // + // // Lookup values from stack + // cb.stack_pop(gas_word.expr()); + // cb.stack_pop(callee_address_word.expr()); + + // // `CALL` opcode has an additional stack pop `value`. + // cb.condition(IS_CREATE2.expr(), |cb| cb.stack_pop(value.expr())); + // + // [ + // cd_offset.expr(), + // cd_length.expr(), + // rd_offset.expr(), + // rd_length.expr(), + // ] + // .map(|expression| cb.stack_pop(expression)); + // cb.stack_push(is_success.expr()); + + // let gas = Eip150Gadget::construct(cb, cb.curr.state.gas_left.expr() - + // GasCost::CREATE); + // + // cb.require_step_state_transition(StepStateTransition { + // rw_counter: Delta(cb.rw_counter_offset.clone()), + // call_id: To(callee_call_id.expr()), + // is_root: To(false.expr()), + // is_create: To(true.expr()), + // code_hash: To(initialization_code_hash.expr()), + // gas_left: To(gas.callee_gas_left()), + // reversible_write_counter: To(2.expr()), + // ..StepStateTransition::new_context() + // }); + + Self { + opcode, + is_create2, + reversion_info, + tx_id, + is_warm_prev, + new_address, + } + } + + fn assign_exec_step( + &self, + region: &mut CachedRegion<'_, '_, F>, + offset: usize, + block: &Block, + tx: &Transaction, + call: &Call, + step: &ExecStep, + ) -> Result<(), Error> { + let opcode = step.opcode.unwrap(); + self.opcode + .assign(region, offset, Value::known(F::from(opcode.as_u64())))?; + self.is_create2.assign( + region, + offset, + Value::known((opcode == OpcodeId::CREATE2).to_scalar().unwrap()), + )?; + + self.tx_id.assign(region, offset, Value::known(tx.id.to_scalar().unwrap()))?; + self.is_warm_prev.assign(region, offset, Value::known(false.to_scalar().unwrap()))?; + + // tx_id: Cell, + // is_warm_prev: Cell, + // reversion_info: ReversionInfo, + + self.reversion_info.assign( + region, + offset, + call.rw_counter_end_of_reversion, + call.is_persistent, + )?; + + let address_bytes = block.rws[step.rw_indices[2]].stack_value().to_le_bytes()[0..20].try_into().unwrap(); + self.new_address.assign( + region, offset, + Some(address_bytes) + )?; + Ok(()) + } +} + +#[cfg(test)] +mod test { + use crate::test_util::run_test_circuits; + use eth_types::{ + address, bytecode, evm_types::OpcodeId, geth_types::Account, Address, Bytecode, ToWord, + Word, + }; + use itertools::Itertools; + use mock::{eth, TestContext, MOCK_ACCOUNTS}; + + const CALLEE_ADDRESS: Address = Address::repeat_byte(0xff); + const CALLER_ADDRESS: Address = Address::repeat_byte(0x34); + + fn callee_bytecode(is_return: bool, offset: u64, length: u64) -> Bytecode { + let memory_bytes = [0x60; 10]; + let memory_address = 0; + let memory_value = Word::from_big_endian(&memory_bytes); + let mut code = bytecode! { + PUSH10(memory_value) + PUSH1(memory_address) + MSTORE + PUSH2(length) + PUSH2(32u64 - u64::try_from(memory_bytes.len()).unwrap() + offset) + }; + code.write_op(if is_return { + OpcodeId::RETURN + } else { + OpcodeId::REVERT + }); + code + } + + fn caller_bytecode(return_data_offset: u64, return_data_length: u64) -> Bytecode { + bytecode! { + PUSH32(return_data_length) + PUSH32(return_data_offset) + PUSH32(0) // call data length + PUSH32(0) // call data offset + PUSH32(0) // value + PUSH32(CALLEE_ADDRESS.to_word()) + PUSH32(4000) // gas + CALL + STOP + } + } + + #[test] + fn mason2() { + let test_parameters = [(0, 0), (0, 10), (300, 20), (1000, 0)]; + for ((offset, length), is_return) in + test_parameters.iter().cartesian_product(&[true, false]) + { + let initializer = callee_bytecode(*is_return, *offset, *length).code(); + + let root_code = bytecode! { + PUSH32(Word::from_big_endian(&initializer)) + PUSH1(0) + MSTORE + + PUSH1(initializer.len()) // size + PUSH1(32 - initializer.len()) // offset + PUSH1(0) // value + + CREATE + }; + + let caller = Account { + address: CALLER_ADDRESS, + code: root_code.into(), + nonce: Word::one(), + balance: eth(10), + ..Default::default() + }; + + let test_context = TestContext::<2, 1>::new( + None, + |accs| { + accs[0] + .address(address!("0x000000000000000000000000000000000000cafe")) + .balance(eth(10)); + accs[1].account(&caller); + }, + |mut txs, accs| { + txs[0] + .from(accs[0].address) + .to(accs[1].address) + .gas(100000u64.into()); + }, + |block, _| block, + ) + .unwrap(); + + assert_eq!( + run_test_circuits(test_context, None), + Ok(()), + "(offset, length, is_return) = {:?}", + (*offset, *length, *is_return), + ); + } + } + + #[test] + fn mason() { + // Test the case where the initialization call is successful, but the CREATE + // call is reverted. + let initializer = callee_bytecode(true, 0, 10).code(); + + let root_code = bytecode! { + PUSH32(Word::from_big_endian(&initializer)) + PUSH1(0) + MSTORE + + PUSH1(initializer.len()) // size + PUSH1(32 - initializer.len()) // offset + PUSH1(0) // value + + CREATE + PUSH1(0) + PUSH1(0) + REVERT + }; + + let caller = Account { + address: CALLER_ADDRESS, + code: root_code.into(), + nonce: Word::one(), + balance: eth(10), + ..Default::default() + }; + + let test_context = TestContext::<2, 1>::new( + None, + |accs| { + accs[0] + .address(address!("0x000000000000000000000000000000000000cafe")) + .balance(eth(10)); + accs[1].account(&caller); + }, + |mut txs, accs| { + txs[0] + .from(accs[0].address) + .to(accs[1].address) + .gas(100000u64.into()); + }, + |block, _| block, + ) + .unwrap(); + + assert_eq!(run_test_circuits(test_context, None), Ok(()),); + } +} diff --git a/zkevm-circuits/src/evm_circuit/util/constraint_builder.rs b/zkevm-circuits/src/evm_circuit/util/constraint_builder.rs index b39b9aaaa5..c0639f5070 100644 --- a/zkevm-circuits/src/evm_circuit/util/constraint_builder.rs +++ b/zkevm-circuits/src/evm_circuit/util/constraint_builder.rs @@ -103,6 +103,29 @@ pub(crate) struct ReversionInfo { } impl ReversionInfo { + pub(crate) fn from_caller( + cb: &mut ConstraintBuilder, + caller: &mut ReversionInfo, + callee_is_success: Expression, + ) -> Self { + // not sure if this is correct?? + // let call_id = cb.curr.state.rw_counter.expr(); + let callee = cb.reversion_info_write(None); + cb.require_equal( + "callee_is_persistent == is_persistent ⋅ is_success", + callee.is_persistent(), + and::expr([caller.is_persistent(), callee_is_success.clone()]), + ); + cb.condition(callee_is_success * not::expr(caller.is_persistent()), |cb| { + cb.require_equal( + "callee_rw_counter_end_of_reversion == rw_counter_end_of_reversion - (reversible_write_counter + 1)", + callee.rw_counter_end_of_reversion(), + caller.rw_counter_of_reversion(), + ); + }); + callee + } + pub(crate) fn rw_counter_end_of_reversion(&self) -> Expression { self.rw_counter_end_of_reversion.expr() } From 3dda45d4de60f3b20123d05e0280a4694bc0f2d0 Mon Sep 17 00:00:00 2001 From: Mason Liang Date: Mon, 5 Dec 2022 15:22:11 -0500 Subject: [PATCH 02/69] tests pass --- .../src/evm_circuit/execution/create.rs | 77 +++++++++---------- 1 file changed, 38 insertions(+), 39 deletions(-) diff --git a/zkevm-circuits/src/evm_circuit/execution/create.rs b/zkevm-circuits/src/evm_circuit/execution/create.rs index ad241ab7de..8b93b982a1 100644 --- a/zkevm-circuits/src/evm_circuit/execution/create.rs +++ b/zkevm-circuits/src/evm_circuit/execution/create.rs @@ -37,12 +37,12 @@ pub(crate) struct CreateGadget { opcode: Cell, is_create2: Cell, - new_address: RandomLinearCombination, - - // tx access list for new address - tx_id: Cell, - is_warm_prev: Cell, - reversion_info: ReversionInfo, + // new_address: RandomLinearCombination, + // + // // tx access list for new address + // tx_id: Cell, + // is_warm_prev: Cell, + // reversion_info: ReversionInfo, // // // transfer value to new address // transfer: TransferGadget, @@ -89,17 +89,19 @@ impl ExecutionGadget for CreateGadget { ), ); - let new_address = cb.query_rlc(); - let mut reversion_info = cb.reversion_info_read(None); - let is_warm_prev = cb.query_bool(); - let tx_id = cb.call_context(None, CallContextFieldTag::TxId); - cb.account_access_list_write( - tx_id.expr(), - from_bytes::expr(&new_address.cells), - 1.expr(), - is_warm_prev.expr(), - Some(&mut reversion_info), - ); + // let new_address = cb.query_rlc(); + // let mut reversion_info = cb.reversion_info_read(None); + // let is_warm_prev = cb.query_bool(); + // let tx_id = cb.call_context(None, CallContextFieldTag::TxId); + // cb.account_access_list_write( + // tx_id.expr(), + // from_bytes::expr(&new_address.cells), + // 1.expr(), + // is_warm_prev.expr(), + // Some(&mut reversion_info), + // ); + + // let access_list = AccountAccessListGadget::construct(cb, // callee_address.expr()); cb.add_account_to_access_list(callee_address. // expr()); @@ -173,10 +175,10 @@ impl ExecutionGadget for CreateGadget { Self { opcode, is_create2, - reversion_info, - tx_id, - is_warm_prev, - new_address, + // reversion_info, + // tx_id, + // is_warm_prev, + // new_address, } } @@ -198,25 +200,22 @@ impl ExecutionGadget for CreateGadget { Value::known((opcode == OpcodeId::CREATE2).to_scalar().unwrap()), )?; - self.tx_id.assign(region, offset, Value::known(tx.id.to_scalar().unwrap()))?; - self.is_warm_prev.assign(region, offset, Value::known(false.to_scalar().unwrap()))?; - - // tx_id: Cell, - // is_warm_prev: Cell, - // reversion_info: ReversionInfo, - - self.reversion_info.assign( - region, - offset, - call.rw_counter_end_of_reversion, - call.is_persistent, - )?; + // self.tx_id.assign(region, offset, Value::known(tx.id.to_scalar().unwrap()))?; + // self.is_warm_prev.assign(region, offset, Value::known(false.to_scalar().unwrap()))?; + // + // self.reversion_info.assign( + // region, + // offset, + // call.rw_counter_end_of_reversion, + // call.is_persistent, + // )?; + // + // let address_bytes = block.rws[step.rw_indices[2]].stack_value().to_le_bytes()[0..20].try_into().unwrap(); + // self.new_address.assign( + // region, offset, + // Some(address_bytes) + // )?; - let address_bytes = block.rws[step.rw_indices[2]].stack_value().to_le_bytes()[0..20].try_into().unwrap(); - self.new_address.assign( - region, offset, - Some(address_bytes) - )?; Ok(()) } } From 76cb869e4edec7657b657a3cda4436ecb274ab65 Mon Sep 17 00:00:00 2001 From: Mason Liang Date: Mon, 5 Dec 2022 19:33:37 -0500 Subject: [PATCH 03/69] Add stack constraints --- .../src/evm_circuit/execution/create.rs | 67 ++++++++++++++++--- 1 file changed, 58 insertions(+), 9 deletions(-) diff --git a/zkevm-circuits/src/evm_circuit/execution/create.rs b/zkevm-circuits/src/evm_circuit/execution/create.rs index 8b93b982a1..e791aabccf 100644 --- a/zkevm-circuits/src/evm_circuit/execution/create.rs +++ b/zkevm-circuits/src/evm_circuit/execution/create.rs @@ -1,3 +1,4 @@ +use crate::evm_circuit::util::RandomLinearCombination; use crate::{ evm_circuit::{ execution::ExecutionGadget, @@ -22,11 +23,10 @@ use crate::{ table::{AccountFieldTag, CallContextFieldTag}, util::Expr, }; -use crate::evm_circuit::util::RandomLinearCombination; use bus_mapping::evm::OpcodeId; use eth_types::{ evm_types::{GasCost, GAS_STIPEND_CALL_WITH_VALUE}, - Field, ToLittleEndian, ToScalar, U256, ToAddress, + Field, ToAddress, ToLittleEndian, ToScalar, U256, }; use halo2_proofs::{circuit::Value, plonk::Error}; use keccak256::EMPTY_HASH_LE; @@ -37,9 +37,13 @@ pub(crate) struct CreateGadget { opcode: Cell, is_create2: Cell, - // new_address: RandomLinearCombination, + initialization_code_start: Word, + initialization_code_length: Word, + value: Word, + salt: Word, + new_address: RandomLinearCombination, // - // // tx access list for new address + // tx access list for new address // tx_id: Cell, // is_warm_prev: Cell, // reversion_info: ReversionInfo, @@ -89,6 +93,19 @@ impl ExecutionGadget for CreateGadget { ), ); + let [initialization_code_start, initialization_code_length, value] = [(); 3].map(|_| { + let cell = cb.query_word(); + cb.stack_pop(cell.expr()); + cell + }); + let salt = cb.condition(is_create2.expr(), |cb| { + let salt = cb.query_word(); + cb.stack_pop(salt.expr()); + salt + }); + let new_address = cb.query_rlc(); + cb.stack_push(new_address.expr()); + // let new_address = cb.query_rlc(); // let mut reversion_info = cb.reversion_info_read(None); // let is_warm_prev = cb.query_bool(); @@ -101,7 +118,6 @@ impl ExecutionGadget for CreateGadget { // Some(&mut reversion_info), // ); - // let access_list = AccountAccessListGadget::construct(cb, // callee_address.expr()); cb.add_account_to_access_list(callee_address. // expr()); @@ -179,6 +195,11 @@ impl ExecutionGadget for CreateGadget { // tx_id, // is_warm_prev, // new_address, + initialization_code_start, + initialization_code_length, + value, + salt, + new_address, } } @@ -192,16 +213,43 @@ impl ExecutionGadget for CreateGadget { step: &ExecStep, ) -> Result<(), Error> { let opcode = step.opcode.unwrap(); + let is_create2 = opcode == OpcodeId::CREATE2; self.opcode .assign(region, offset, Value::known(F::from(opcode.as_u64())))?; self.is_create2.assign( region, offset, - Value::known((opcode == OpcodeId::CREATE2).to_scalar().unwrap()), + Value::known(is_create2.to_scalar().unwrap()), + )?; + + let [initialization_code_start, initialization_code_length, value, new_address] = + [0, 1, 2, 3 + usize::from(is_create2)] + .map(|i| step.rw_indices[i]) + .map(|idx| block.rws[idx].stack_value()); + let salt = if is_create2 { + block.rws[step.rw_indices[3]].stack_value() + } else { + U256::zero() + }; + + for (word, assignment) in [ + (&self.initialization_code_start, initialization_code_start), + (&self.initialization_code_length, initialization_code_length), + (&self.value, value), + (&self.salt, salt), + ] { + word.assign(region, offset, Some(assignment.to_le_bytes()))?; + } + + self.new_address.assign( + region, + offset, + Some(new_address.to_le_bytes()[0..20].try_into().unwrap()), )?; // self.tx_id.assign(region, offset, Value::known(tx.id.to_scalar().unwrap()))?; - // self.is_warm_prev.assign(region, offset, Value::known(false.to_scalar().unwrap()))?; + // self.is_warm_prev.assign(region, offset, + // Value::known(false.to_scalar().unwrap()))?; // // self.reversion_info.assign( // region, @@ -210,8 +258,9 @@ impl ExecutionGadget for CreateGadget { // call.is_persistent, // )?; // - // let address_bytes = block.rws[step.rw_indices[2]].stack_value().to_le_bytes()[0..20].try_into().unwrap(); - // self.new_address.assign( + // let address_bytes = + // block.rws[step.rw_indices[2]].stack_value().to_le_bytes()[0..20].try_into(). + // unwrap(); self.new_address.assign( // region, offset, // Some(address_bytes) // )?; From 9f7263f7215169f936b295aad5f6bb96d0cbc2f4 Mon Sep 17 00:00:00 2001 From: Mason Liang Date: Mon, 5 Dec 2022 19:43:29 -0500 Subject: [PATCH 04/69] tx_id --- bus-mapping/src/evm/opcodes/create.rs | 23 +++++++++++++++---- .../src/evm_circuit/execution/create.rs | 13 +++++------ 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/bus-mapping/src/evm/opcodes/create.rs b/bus-mapping/src/evm/opcodes/create.rs index c113b43b96..4be178e456 100644 --- a/bus-mapping/src/evm/opcodes/create.rs +++ b/bus-mapping/src/evm/opcodes/create.rs @@ -57,21 +57,36 @@ impl Opcode for DummyCreate { }, )?; - let tx_id = state.tx_ctx.id(); - let current_call = state.call()?.clone(); - // Quote from [EIP-2929](https://eips.ethereum.org/EIPS/eip-2929) // > When a CREATE or CREATE2 opcode is called, // > immediately (i.e. before checks are done to determine // > whether or not the address is unclaimed) // > add the address being created to accessed_addresses, // > but gas costs of CREATE and CREATE2 are unchanged + + let tx_id = state.tx_ctx.id(); + let current_call = state.call()?.clone(); + + for (field, value) in [ + (CallContextField::TxId, tx_id.to_word()), + ( + CallContextField::RwCounterEndOfReversion, + current_call.rw_counter_end_of_reversion.to_word(), + ), + ( + CallContextField::IsPersistent, + current_call.is_persistent.to_word(), + ), + ] { + state.call_context_read(&mut exec_step, current_call.call_id, field, value); + } + let is_warm = state.sdb.check_account_in_access_list(&address); state.push_op_reversible( &mut exec_step, RW::WRITE, TxAccessListAccountOp { - tx_id: state.tx_ctx.id(), + tx_id, address, is_warm: true, is_warm_prev: is_warm, diff --git a/zkevm-circuits/src/evm_circuit/execution/create.rs b/zkevm-circuits/src/evm_circuit/execution/create.rs index e791aabccf..4355871a0e 100644 --- a/zkevm-circuits/src/evm_circuit/execution/create.rs +++ b/zkevm-circuits/src/evm_circuit/execution/create.rs @@ -42,11 +42,11 @@ pub(crate) struct CreateGadget { value: Word, salt: Word, new_address: RandomLinearCombination, - // + // tx access list for new address - // tx_id: Cell, - // is_warm_prev: Cell, + tx_id: Cell, // reversion_info: ReversionInfo, + // is_warm_prev: Cell, // // // transfer value to new address // transfer: TransferGadget, @@ -106,10 +106,9 @@ impl ExecutionGadget for CreateGadget { let new_address = cb.query_rlc(); cb.stack_push(new_address.expr()); - // let new_address = cb.query_rlc(); + let tx_id = cb.call_context(None, CallContextFieldTag::TxId); // let mut reversion_info = cb.reversion_info_read(None); // let is_warm_prev = cb.query_bool(); - // let tx_id = cb.call_context(None, CallContextFieldTag::TxId); // cb.account_access_list_write( // tx_id.expr(), // from_bytes::expr(&new_address.cells), @@ -192,7 +191,7 @@ impl ExecutionGadget for CreateGadget { opcode, is_create2, // reversion_info, - // tx_id, + tx_id, // is_warm_prev, // new_address, initialization_code_start, @@ -247,7 +246,7 @@ impl ExecutionGadget for CreateGadget { Some(new_address.to_le_bytes()[0..20].try_into().unwrap()), )?; - // self.tx_id.assign(region, offset, Value::known(tx.id.to_scalar().unwrap()))?; + self.tx_id.assign(region, offset, Value::known(tx.id.to_scalar().unwrap()))?; // self.is_warm_prev.assign(region, offset, // Value::known(false.to_scalar().unwrap()))?; // From 58d98f8f95beae891da2362d189067d7726abd3b Mon Sep 17 00:00:00 2001 From: Mason Liang Date: Mon, 5 Dec 2022 19:48:27 -0500 Subject: [PATCH 05/69] reversion --- .../src/evm_circuit/execution/create.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/zkevm-circuits/src/evm_circuit/execution/create.rs b/zkevm-circuits/src/evm_circuit/execution/create.rs index 4355871a0e..1aa9ac0073 100644 --- a/zkevm-circuits/src/evm_circuit/execution/create.rs +++ b/zkevm-circuits/src/evm_circuit/execution/create.rs @@ -45,7 +45,7 @@ pub(crate) struct CreateGadget { // tx access list for new address tx_id: Cell, - // reversion_info: ReversionInfo, + reversion_info: ReversionInfo, // is_warm_prev: Cell, // // // transfer value to new address @@ -107,7 +107,7 @@ impl ExecutionGadget for CreateGadget { cb.stack_push(new_address.expr()); let tx_id = cb.call_context(None, CallContextFieldTag::TxId); - // let mut reversion_info = cb.reversion_info_read(None); + let mut reversion_info = cb.reversion_info_read(None); // let is_warm_prev = cb.query_bool(); // cb.account_access_list_write( // tx_id.expr(), @@ -190,7 +190,7 @@ impl ExecutionGadget for CreateGadget { Self { opcode, is_create2, - // reversion_info, + reversion_info, tx_id, // is_warm_prev, // new_address, @@ -250,12 +250,12 @@ impl ExecutionGadget for CreateGadget { // self.is_warm_prev.assign(region, offset, // Value::known(false.to_scalar().unwrap()))?; // - // self.reversion_info.assign( - // region, - // offset, - // call.rw_counter_end_of_reversion, - // call.is_persistent, - // )?; + self.reversion_info.assign( + region, + offset, + call.rw_counter_end_of_reversion, + call.is_persistent, + )?; // // let address_bytes = // block.rws[step.rw_indices[2]].stack_value().to_le_bytes()[0..20].try_into(). From 59715be43cbb721cdc29c57671d03b9a3d07e1c2 Mon Sep 17 00:00:00 2001 From: Mason Liang Date: Mon, 5 Dec 2022 21:34:03 -0500 Subject: [PATCH 06/69] wip --- .../circuit_input_builder/input_state_ref.rs | 2 +- bus-mapping/src/evm/opcodes/create.rs | 2 + .../src/evm_circuit/execution/callop.rs | 2 +- .../src/evm_circuit/execution/create.rs | 48 +++++++++++-------- 4 files changed, 31 insertions(+), 23 deletions(-) diff --git a/bus-mapping/src/circuit_input_builder/input_state_ref.rs b/bus-mapping/src/circuit_input_builder/input_state_ref.rs index a98524f91c..afc453d547 100644 --- a/bus-mapping/src/circuit_input_builder/input_state_ref.rs +++ b/bus-mapping/src/circuit_input_builder/input_state_ref.rs @@ -655,7 +655,7 @@ impl<'a> CircuitInputStateRef<'a> { is_root: false, is_persistent: caller.is_persistent && is_success, is_success, - rw_counter_end_of_reversion: 0, + rw_counter_end_of_reversion: 0, // here???? caller_address, address, code_source, diff --git a/bus-mapping/src/evm/opcodes/create.rs b/bus-mapping/src/evm/opcodes/create.rs index 4be178e456..5b694b2239 100644 --- a/bus-mapping/src/evm/opcodes/create.rs +++ b/bus-mapping/src/evm/opcodes/create.rs @@ -93,6 +93,8 @@ impl Opcode for DummyCreate { }, )?; + // here in gadget..... + // Increase caller's nonce let nonce_prev = state.sdb.get_nonce(&call.caller_address); state.push_op_reversible( diff --git a/zkevm-circuits/src/evm_circuit/execution/callop.rs b/zkevm-circuits/src/evm_circuit/execution/callop.rs index 75fac49efa..22abd995e0 100644 --- a/zkevm-circuits/src/evm_circuit/execution/callop.rs +++ b/zkevm-circuits/src/evm_circuit/execution/callop.rs @@ -139,7 +139,7 @@ impl ExecutionGadget for CallOpGadget { let memory_expansion = MemoryExpansionGadget::construct(cb, [cd_address.address(), rd_address.address()]); - // `code_address` is poped from stack and used to check if it exists in + // `code_address` is popped from stack and used to check if it exists in // access list and get code hash. // For CALLCODE, both caller and callee addresses are // `current_callee_address`. diff --git a/zkevm-circuits/src/evm_circuit/execution/create.rs b/zkevm-circuits/src/evm_circuit/execution/create.rs index 1aa9ac0073..eb44a40da2 100644 --- a/zkevm-circuits/src/evm_circuit/execution/create.rs +++ b/zkevm-circuits/src/evm_circuit/execution/create.rs @@ -46,7 +46,7 @@ pub(crate) struct CreateGadget { // tx access list for new address tx_id: Cell, reversion_info: ReversionInfo, - // is_warm_prev: Cell, + was_warm: Cell, // // // transfer value to new address // transfer: TransferGadget, @@ -108,18 +108,14 @@ impl ExecutionGadget for CreateGadget { let tx_id = cb.call_context(None, CallContextFieldTag::TxId); let mut reversion_info = cb.reversion_info_read(None); - // let is_warm_prev = cb.query_bool(); - // cb.account_access_list_write( - // tx_id.expr(), - // from_bytes::expr(&new_address.cells), - // 1.expr(), - // is_warm_prev.expr(), - // Some(&mut reversion_info), - // ); - - // let access_list = AccountAccessListGadget::construct(cb, - // callee_address.expr()); cb.add_account_to_access_list(callee_address. - // expr()); + let was_warm = cb.query_bool(); + cb.account_access_list_write( + tx_id.expr(), + from_bytes::expr(&new_address.cells), + 1.expr(), + was_warm.expr(), + Some(&mut reversion_info), + ); // let caller_address = cb.call_context(None, // CallContextFieldTag::CalleeAddress); let [callee_address, value, @@ -192,8 +188,7 @@ impl ExecutionGadget for CreateGadget { is_create2, reversion_info, tx_id, - // is_warm_prev, - // new_address, + was_warm, initialization_code_start, initialization_code_length, value, @@ -246,16 +241,27 @@ impl ExecutionGadget for CreateGadget { Some(new_address.to_le_bytes()[0..20].try_into().unwrap()), )?; - self.tx_id.assign(region, offset, Value::known(tx.id.to_scalar().unwrap()))?; - // self.is_warm_prev.assign(region, offset, - // Value::known(false.to_scalar().unwrap()))?; - // + self.tx_id + .assign(region, offset, Value::known(tx.id.to_scalar().unwrap()))?; + self.reversion_info.assign( region, offset, call.rw_counter_end_of_reversion, call.is_persistent, )?; + + self.was_warm.assign( + region, + offset, + Value::known( + block.rws[step.rw_indices[7 + usize::from(is_create2)]] + .tx_access_list_value_pair() + .1 + .to_scalar() + .unwrap(), + ), + )?; // // let address_bytes = // block.rws[step.rw_indices[2]].stack_value().to_le_bytes()[0..20].try_into(). @@ -317,8 +323,8 @@ mod test { #[test] fn mason2() { let test_parameters = [(0, 0), (0, 10), (300, 20), (1000, 0)]; - for ((offset, length), is_return) in - test_parameters.iter().cartesian_product(&[true, false]) + for ((offset, length), is_return) in test_parameters.iter().cartesian_product(&[true]) + // FIX MEEEEEE there's an issue when the init call reverts. { let initializer = callee_bytecode(*is_return, *offset, *length).code(); From f601aa29d618597850cd8ae5e3142d83919ccae1 Mon Sep 17 00:00:00 2001 From: Mason Liang Date: Mon, 5 Dec 2022 23:17:16 -0500 Subject: [PATCH 07/69] wip --- .../circuit_input_builder/input_state_ref.rs | 1 + bus-mapping/src/evm/opcodes.rs | 4 +++ bus-mapping/src/evm/opcodes/create.rs | 11 ++++++- .../src/evm_circuit/execution/create.rs | 32 +++++++++++++++++++ zkevm-circuits/src/state_circuit.rs | 2 ++ 5 files changed, 49 insertions(+), 1 deletion(-) diff --git a/bus-mapping/src/circuit_input_builder/input_state_ref.rs b/bus-mapping/src/circuit_input_builder/input_state_ref.rs index afc453d547..0299c813b7 100644 --- a/bus-mapping/src/circuit_input_builder/input_state_ref.rs +++ b/bus-mapping/src/circuit_input_builder/input_state_ref.rs @@ -588,6 +588,7 @@ impl<'a> CircuitInputStateRef<'a> { let caller = self.call()?; let caller_ctx = self.call_ctx()?; + dbg!(caller.address); let (caller_address, address, value) = match kind { CallKind::Call => ( caller.address, diff --git a/bus-mapping/src/evm/opcodes.rs b/bus-mapping/src/evm/opcodes.rs index 566eff7a58..fc6a5930bf 100644 --- a/bus-mapping/src/evm/opcodes.rs +++ b/bus-mapping/src/evm/opcodes.rs @@ -399,6 +399,7 @@ pub fn gen_begin_tx_ops(state: &mut CircuitInputStateRef) -> Result { + panic!("shouldn't be here!!!!"); state.account_read( &mut exec_step, call.address, @@ -454,6 +455,9 @@ pub fn gen_begin_tx_ops(state: &mut CircuitInputStateRef) -> Result Opcode for DummyCreate { }, )?; - // here in gadget..... + dbg!(call.caller_address, call.address); + dbg!(current_call.address); + + for (field, value) in [ + (CallContextField::CalleeAddress, current_call.address), + ] { + state.call_context_read(&mut exec_step, current_call.call_id, field, value.to_word()); + } // Increase caller's nonce let nonce_prev = state.sdb.get_nonce(&call.caller_address); @@ -108,6 +115,8 @@ impl Opcode for DummyCreate { }, )?; + // here in gadget..... + // Add callee into access list let is_warm = state.sdb.check_account_in_access_list(&call.address); state.push_op_reversible( diff --git a/zkevm-circuits/src/evm_circuit/execution/create.rs b/zkevm-circuits/src/evm_circuit/execution/create.rs index eb44a40da2..39e4a709a1 100644 --- a/zkevm-circuits/src/evm_circuit/execution/create.rs +++ b/zkevm-circuits/src/evm_circuit/execution/create.rs @@ -47,6 +47,9 @@ pub(crate) struct CreateGadget { tx_id: Cell, reversion_info: ReversionInfo, was_warm: Cell, + + caller_address: Cell, + // nonce: Cell, // // // transfer value to new address // transfer: TransferGadget, @@ -117,6 +120,16 @@ impl ExecutionGadget for CreateGadget { Some(&mut reversion_info), ); + let caller_address = cb.call_context(None, CallContextFieldTag::CalleeAddress); + // let nonce = cb.query_cell(); + // cb.account_write( + // caller_address.expr(), + // AccountFieldTag::Nonce, + // nonce.expr() + 1.expr(), + // nonce.expr(), + // None, + // ); + // let caller_address = cb.call_context(None, // CallContextFieldTag::CalleeAddress); let [callee_address, value, // callee_address] = [(); 3].map(|| cb.query_word()); let is_failure = @@ -194,6 +207,8 @@ impl ExecutionGadget for CreateGadget { value, salt, new_address, + caller_address, + // nonce, } } @@ -262,6 +277,23 @@ impl ExecutionGadget for CreateGadget { .unwrap(), ), )?; + + dbg!(call.callee_address); + self.caller_address.assign( + region, offset, Value::known(call.callee_address.to_scalar().unwrap()) + )?; + + // self.nonce.assign( + // region, offset, + // Value::known( + // block.rws[step.rw_indices[9 + usize::from(is_create2)]] + // .account_value_pair() + // .1 + // .to_scalar() + // .unwrap(), + // ), + // )?; + // // let address_bytes = // block.rws[step.rw_indices[2]].stack_value().to_le_bytes()[0..20].try_into(). diff --git a/zkevm-circuits/src/state_circuit.rs b/zkevm-circuits/src/state_circuit.rs index 43e5873728..9e066fd2a8 100644 --- a/zkevm-circuits/src/state_circuit.rs +++ b/zkevm-circuits/src/state_circuit.rs @@ -258,6 +258,8 @@ impl StateCircuitConfig { } state_root }); + } else if !row.is_write() { + assert_eq!(row.value_assignment(F::one()), prev_row.value_assignment(F::one())); } } From 3ba7f533e20a02c5c9afc2120047f212b3323469 Mon Sep 17 00:00:00 2001 From: Mason Liang Date: Mon, 5 Dec 2022 23:22:56 -0500 Subject: [PATCH 08/69] wip --- .../src/evm_circuit/execution/create.rs | 40 +++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/zkevm-circuits/src/evm_circuit/execution/create.rs b/zkevm-circuits/src/evm_circuit/execution/create.rs index 39e4a709a1..7454c3dfe6 100644 --- a/zkevm-circuits/src/evm_circuit/execution/create.rs +++ b/zkevm-circuits/src/evm_circuit/execution/create.rs @@ -49,7 +49,7 @@ pub(crate) struct CreateGadget { was_warm: Cell, caller_address: Cell, - // nonce: Cell, + nonce: Cell, // // // transfer value to new address // transfer: TransferGadget, @@ -121,14 +121,14 @@ impl ExecutionGadget for CreateGadget { ); let caller_address = cb.call_context(None, CallContextFieldTag::CalleeAddress); - // let nonce = cb.query_cell(); - // cb.account_write( - // caller_address.expr(), - // AccountFieldTag::Nonce, - // nonce.expr() + 1.expr(), - // nonce.expr(), - // None, - // ); + let nonce = cb.query_cell(); + cb.account_write( + caller_address.expr(), + AccountFieldTag::Nonce, + nonce.expr() + 1.expr(), + nonce.expr(), + None, + ); // let caller_address = cb.call_context(None, // CallContextFieldTag::CalleeAddress); let [callee_address, value, @@ -208,7 +208,7 @@ impl ExecutionGadget for CreateGadget { salt, new_address, caller_address, - // nonce, + nonce, } } @@ -283,16 +283,16 @@ impl ExecutionGadget for CreateGadget { region, offset, Value::known(call.callee_address.to_scalar().unwrap()) )?; - // self.nonce.assign( - // region, offset, - // Value::known( - // block.rws[step.rw_indices[9 + usize::from(is_create2)]] - // .account_value_pair() - // .1 - // .to_scalar() - // .unwrap(), - // ), - // )?; + self.nonce.assign( + region, offset, + Value::known( + block.rws[step.rw_indices[9 + usize::from(is_create2)]] + .account_value_pair() + .1 + .to_scalar() + .unwrap(), + ), + )?; // // let address_bytes = From 3b39762090e0ef90b5ebf25dc25ebe6ca45778dd Mon Sep 17 00:00:00 2001 From: Mason Liang Date: Tue, 6 Dec 2022 10:21:34 -0500 Subject: [PATCH 09/69] wip --- bus-mapping/src/evm/opcodes/create.rs | 17 ++--------------- zkevm-circuits/src/state_circuit.rs | 2 +- 2 files changed, 3 insertions(+), 16 deletions(-) diff --git a/bus-mapping/src/evm/opcodes/create.rs b/bus-mapping/src/evm/opcodes/create.rs index a432245618..75247d58a6 100644 --- a/bus-mapping/src/evm/opcodes/create.rs +++ b/bus-mapping/src/evm/opcodes/create.rs @@ -117,19 +117,6 @@ impl Opcode for DummyCreate { // here in gadget..... - // Add callee into access list - let is_warm = state.sdb.check_account_in_access_list(&call.address); - state.push_op_reversible( - &mut exec_step, - RW::WRITE, - TxAccessListAccountOp { - tx_id, - address: call.address, - is_warm: true, - is_warm_prev: is_warm, - }, - )?; - state.push_call(call.clone()); // Increase callee's nonce @@ -173,9 +160,9 @@ impl Opcode for DummyCreate { (CallContextField::MemorySize, next_memory_word_size.into()), ( CallContextField::ReversibleWriteCounter, - // +3 is because we do some transfers after pushing the call. can be just push the + // +2 is because we do some reversible writes before pushing the call. can be just push the // call later? - (exec_step.reversible_write_counter + 3).into(), + (exec_step.reversible_write_counter + 2).into(), ), ] { state.call_context_write(&mut exec_step, current_call.call_id, field, value); diff --git a/zkevm-circuits/src/state_circuit.rs b/zkevm-circuits/src/state_circuit.rs index 9e066fd2a8..a16565a729 100644 --- a/zkevm-circuits/src/state_circuit.rs +++ b/zkevm-circuits/src/state_circuit.rs @@ -259,7 +259,7 @@ impl StateCircuitConfig { state_root }); } else if !row.is_write() { - assert_eq!(row.value_assignment(F::one()), prev_row.value_assignment(F::one())); + assert_eq!(row.value_assignment(F::one()), prev_row.value_assignment(F::one()), "{:?}, {:?}", row, prev_row); } } From e8a00f58efda88d6d88d40f109068056d363fc45 Mon Sep 17 00:00:00 2001 From: Mason Liang Date: Tue, 6 Dec 2022 13:59:15 -0500 Subject: [PATCH 10/69] fmt --- bus-mapping/src/evm/opcodes/create.rs | 8 +++----- zkevm-circuits/src/evm_circuit/execution/create.rs | 7 +++++-- zkevm-circuits/src/state_circuit.rs | 8 +++++++- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/bus-mapping/src/evm/opcodes/create.rs b/bus-mapping/src/evm/opcodes/create.rs index 75247d58a6..ce37ade3cc 100644 --- a/bus-mapping/src/evm/opcodes/create.rs +++ b/bus-mapping/src/evm/opcodes/create.rs @@ -96,9 +96,7 @@ impl Opcode for DummyCreate { dbg!(call.caller_address, call.address); dbg!(current_call.address); - for (field, value) in [ - (CallContextField::CalleeAddress, current_call.address), - ] { + for (field, value) in [(CallContextField::CalleeAddress, current_call.address)] { state.call_context_read(&mut exec_step, current_call.call_id, field, value.to_word()); } @@ -160,8 +158,8 @@ impl Opcode for DummyCreate { (CallContextField::MemorySize, next_memory_word_size.into()), ( CallContextField::ReversibleWriteCounter, - // +2 is because we do some reversible writes before pushing the call. can be just push the - // call later? + // +2 is because we do some reversible writes before pushing the call. can be just + // push the call later? (exec_step.reversible_write_counter + 2).into(), ), ] { diff --git a/zkevm-circuits/src/evm_circuit/execution/create.rs b/zkevm-circuits/src/evm_circuit/execution/create.rs index 7454c3dfe6..25d80e3fe5 100644 --- a/zkevm-circuits/src/evm_circuit/execution/create.rs +++ b/zkevm-circuits/src/evm_circuit/execution/create.rs @@ -280,11 +280,14 @@ impl ExecutionGadget for CreateGadget { dbg!(call.callee_address); self.caller_address.assign( - region, offset, Value::known(call.callee_address.to_scalar().unwrap()) + region, + offset, + Value::known(call.callee_address.to_scalar().unwrap()), )?; self.nonce.assign( - region, offset, + region, + offset, Value::known( block.rws[step.rw_indices[9 + usize::from(is_create2)]] .account_value_pair() diff --git a/zkevm-circuits/src/state_circuit.rs b/zkevm-circuits/src/state_circuit.rs index a16565a729..7c859f8a87 100644 --- a/zkevm-circuits/src/state_circuit.rs +++ b/zkevm-circuits/src/state_circuit.rs @@ -259,7 +259,13 @@ impl StateCircuitConfig { state_root }); } else if !row.is_write() { - assert_eq!(row.value_assignment(F::one()), prev_row.value_assignment(F::one()), "{:?}, {:?}", row, prev_row); + assert_eq!( + row.value_assignment(F::one()), + prev_row.value_assignment(F::one()), + "{:?}, {:?}", + row, + prev_row + ); } } From 1483f22b41ecb1ecbc9775227e1f72cee1c0501a Mon Sep 17 00:00:00 2001 From: Mason Liang Date: Tue, 6 Dec 2022 15:17:38 -0500 Subject: [PATCH 11/69] wip --- bus-mapping/src/evm/opcodes/create.rs | 21 +++++++---- .../src/evm_circuit/execution/create.rs | 35 ++++++++++++++++++- 2 files changed, 49 insertions(+), 7 deletions(-) diff --git a/bus-mapping/src/evm/opcodes/create.rs b/bus-mapping/src/evm/opcodes/create.rs index ce37ade3cc..69dce744c4 100644 --- a/bus-mapping/src/evm/opcodes/create.rs +++ b/bus-mapping/src/evm/opcodes/create.rs @@ -30,6 +30,9 @@ impl Opcode for DummyCreate { let mut exec_step = state.new_step(geth_step)?; + // TODO: rename this to initialization call? + let call = state.parse_call(geth_step)?; + let n_pop = if IS_CREATE2 { 4 } else { 3 }; for i in 0..n_pop { state.stack_read( @@ -45,8 +48,6 @@ impl Opcode for DummyCreate { state.create_address()? }; - // TODO: rename this to initialization call? - let call = state.parse_call(geth_step)?; state.stack_write( &mut exec_step, geth_step.stack.nth_last_filled(n_pop - 1), @@ -93,9 +94,6 @@ impl Opcode for DummyCreate { }, )?; - dbg!(call.caller_address, call.address); - dbg!(current_call.address); - for (field, value) in [(CallContextField::CalleeAddress, current_call.address)] { state.call_context_read(&mut exec_step, current_call.call_id, field, value.to_word()); } @@ -116,8 +114,19 @@ impl Opcode for DummyCreate { // here in gadget..... state.push_call(call.clone()); - + dbg!(current_call.call_id); + dbg!(call.call_id); // Increase callee's nonce + for (field, value) in [ + ( + CallContextField::RwCounterEndOfReversion, + call.rw_counter_end_of_reversion.to_word(), + ), + (CallContextField::IsPersistent, call.is_persistent.to_word()), + ] { + state.call_context_write(&mut exec_step, call.call_id, field, value); + } + let nonce_prev = state.sdb.get_nonce(&call.address); debug_assert!(nonce_prev == 0); state.push_op_reversible( diff --git a/zkevm-circuits/src/evm_circuit/execution/create.rs b/zkevm-circuits/src/evm_circuit/execution/create.rs index 25d80e3fe5..b7bbdd8a94 100644 --- a/zkevm-circuits/src/evm_circuit/execution/create.rs +++ b/zkevm-circuits/src/evm_circuit/execution/create.rs @@ -50,6 +50,8 @@ pub(crate) struct CreateGadget { caller_address: Cell, nonce: Cell, + + // callee_reversion_info: ReversionInfo, // // // transfer value to new address // transfer: TransferGadget, @@ -82,6 +84,9 @@ impl ExecutionGadget for CreateGadget { const EXECUTION_STATE: ExecutionState = ExecutionState::CREATE; fn configure(cb: &mut ConstraintBuilder) -> Self { + // Use rw_counter of the step which triggers next call as its call_id. + let callee_call_id = cb.curr.state.rw_counter.clone(); + let opcode = cb.query_cell(); cb.opcode_lookup(opcode.expr(), 1.expr()); @@ -127,9 +132,21 @@ impl ExecutionGadget for CreateGadget { AccountFieldTag::Nonce, nonce.expr() + 1.expr(), nonce.expr(), - None, + Some(&mut reversion_info), + // None, ); + // let caller_address = cb.call_context(None, CallContextFieldTag::CalleeAddress); + + // let mut callee_reversion_info = cb.reversion_info_write(Some(callee_call_id.expr())); + // cb.account_write( + // new_address.expr(), + // AccountFieldTag::Nonce, + // 1.expr() + // 0.expr(), + // None, + // ); + // let caller_address = cb.call_context(None, // CallContextFieldTag::CalleeAddress); let [callee_address, value, // callee_address] = [(); 3].map(|| cb.query_word()); let is_failure = @@ -209,6 +226,7 @@ impl ExecutionGadget for CreateGadget { new_address, caller_address, nonce, + // callee_reversion_info, } } @@ -305,6 +323,21 @@ impl ExecutionGadget for CreateGadget { // Some(address_bytes) // )?; + // let [callee_rw_counter_end_of_reversion, callee_is_persistent] = [10, 11] + // .map(|i| block.rws[step.rw_indices[i + usize::from(is_create2)]].call_context_value()); + + // dbg!(callee_rw_counter_end_of_reversion, callee_is_persistent); + + // self.callee_reversion_info.assign( + // region, + // offset, + // callee_rw_counter_end_of_reversion + // .low_u64() + // .try_into() + // .unwrap(), + // callee_is_persistent.low_u64() != 0, + // )?; + Ok(()) } } From 15e63acad59cc2e2ca533f8c436f29a7ae7cc9cb Mon Sep 17 00:00:00 2001 From: Mason Liang Date: Tue, 6 Dec 2022 15:23:03 -0500 Subject: [PATCH 12/69] wip --- .../src/evm_circuit/execution/create.rs | 33 ++++++++++--------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/zkevm-circuits/src/evm_circuit/execution/create.rs b/zkevm-circuits/src/evm_circuit/execution/create.rs index b7bbdd8a94..498c65b04b 100644 --- a/zkevm-circuits/src/evm_circuit/execution/create.rs +++ b/zkevm-circuits/src/evm_circuit/execution/create.rs @@ -51,7 +51,7 @@ pub(crate) struct CreateGadget { caller_address: Cell, nonce: Cell, - // callee_reversion_info: ReversionInfo, + callee_reversion_info: ReversionInfo, // // // transfer value to new address // transfer: TransferGadget, @@ -136,9 +136,10 @@ impl ExecutionGadget for CreateGadget { // None, ); - // let caller_address = cb.call_context(None, CallContextFieldTag::CalleeAddress); + // let caller_address = cb.call_context(None, + // CallContextFieldTag::CalleeAddress); - // let mut callee_reversion_info = cb.reversion_info_write(Some(callee_call_id.expr())); + let mut callee_reversion_info = cb.reversion_info_write(Some(callee_call_id.expr())); // cb.account_write( // new_address.expr(), // AccountFieldTag::Nonce, @@ -226,7 +227,7 @@ impl ExecutionGadget for CreateGadget { new_address, caller_address, nonce, - // callee_reversion_info, + callee_reversion_info, } } @@ -323,20 +324,20 @@ impl ExecutionGadget for CreateGadget { // Some(address_bytes) // )?; - // let [callee_rw_counter_end_of_reversion, callee_is_persistent] = [10, 11] - // .map(|i| block.rws[step.rw_indices[i + usize::from(is_create2)]].call_context_value()); + let [callee_rw_counter_end_of_reversion, callee_is_persistent] = [10, 11] + .map(|i| block.rws[step.rw_indices[i + usize::from(is_create2)]].call_context_value()); - // dbg!(callee_rw_counter_end_of_reversion, callee_is_persistent); + dbg!(callee_rw_counter_end_of_reversion, callee_is_persistent); - // self.callee_reversion_info.assign( - // region, - // offset, - // callee_rw_counter_end_of_reversion - // .low_u64() - // .try_into() - // .unwrap(), - // callee_is_persistent.low_u64() != 0, - // )?; + self.callee_reversion_info.assign( + region, + offset, + callee_rw_counter_end_of_reversion + .low_u64() + .try_into() + .unwrap(), + callee_is_persistent.low_u64() != 0, + )?; Ok(()) } From db6653fe36c88ed4d396e0d068af185f2b60510e Mon Sep 17 00:00:00 2001 From: Mason Liang Date: Tue, 6 Dec 2022 15:31:52 -0500 Subject: [PATCH 13/69] wip --- bus-mapping/src/evm/opcodes/create.rs | 2 -- zkevm-circuits/src/evm_circuit/execution/create.rs | 14 +++++++------- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/bus-mapping/src/evm/opcodes/create.rs b/bus-mapping/src/evm/opcodes/create.rs index 69dce744c4..4ad7e2553e 100644 --- a/bus-mapping/src/evm/opcodes/create.rs +++ b/bus-mapping/src/evm/opcodes/create.rs @@ -114,8 +114,6 @@ impl Opcode for DummyCreate { // here in gadget..... state.push_call(call.clone()); - dbg!(current_call.call_id); - dbg!(call.call_id); // Increase callee's nonce for (field, value) in [ ( diff --git a/zkevm-circuits/src/evm_circuit/execution/create.rs b/zkevm-circuits/src/evm_circuit/execution/create.rs index 498c65b04b..ff42c8d8e0 100644 --- a/zkevm-circuits/src/evm_circuit/execution/create.rs +++ b/zkevm-circuits/src/evm_circuit/execution/create.rs @@ -140,13 +140,13 @@ impl ExecutionGadget for CreateGadget { // CallContextFieldTag::CalleeAddress); let mut callee_reversion_info = cb.reversion_info_write(Some(callee_call_id.expr())); - // cb.account_write( - // new_address.expr(), - // AccountFieldTag::Nonce, - // 1.expr() - // 0.expr(), - // None, - // ); + cb.account_write( + new_address.expr(), + AccountFieldTag::Nonce, + 1.expr(), + 0.expr(), + Some(&mut callee_reversion_info), + ); // let caller_address = cb.call_context(None, // CallContextFieldTag::CalleeAddress); let [callee_address, value, From ae694175ea812fba1e964a834fc69db7a929c756 Mon Sep 17 00:00:00 2001 From: Mason Liang Date: Tue, 6 Dec 2022 15:34:20 -0500 Subject: [PATCH 14/69] wip --- bus-mapping/src/evm/opcodes/create.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/bus-mapping/src/evm/opcodes/create.rs b/bus-mapping/src/evm/opcodes/create.rs index 4ad7e2553e..f14e4b15d7 100644 --- a/bus-mapping/src/evm/opcodes/create.rs +++ b/bus-mapping/src/evm/opcodes/create.rs @@ -111,8 +111,6 @@ impl Opcode for DummyCreate { }, )?; - // here in gadget..... - state.push_call(call.clone()); // Increase callee's nonce for (field, value) in [ @@ -138,6 +136,7 @@ impl Opcode for DummyCreate { }, )?; + // here in gadget..... state.transfer( &mut exec_step, call.caller_address, From f272a8132fbb03c56058293363239aeab0602137 Mon Sep 17 00:00:00 2001 From: Mason Liang Date: Tue, 6 Dec 2022 16:04:35 -0500 Subject: [PATCH 15/69] wip --- bus-mapping/src/evm/opcodes/create.rs | 3 ++- .../src/evm_circuit/execution/create.rs | 27 +++++++++++++++++-- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/bus-mapping/src/evm/opcodes/create.rs b/bus-mapping/src/evm/opcodes/create.rs index f14e4b15d7..4c9dfb7b7b 100644 --- a/bus-mapping/src/evm/opcodes/create.rs +++ b/bus-mapping/src/evm/opcodes/create.rs @@ -136,7 +136,7 @@ impl Opcode for DummyCreate { }, )?; - // here in gadget..... + dbg!(call.value); state.transfer( &mut exec_step, call.caller_address, @@ -144,6 +144,7 @@ impl Opcode for DummyCreate { call.value, )?; + // here in gadget..... let memory_expansion_gas_cost = memory_expansion_gas_cost(curr_memory_word_size, next_memory_word_size); diff --git a/zkevm-circuits/src/evm_circuit/execution/create.rs b/zkevm-circuits/src/evm_circuit/execution/create.rs index ff42c8d8e0..dcf8a1605b 100644 --- a/zkevm-circuits/src/evm_circuit/execution/create.rs +++ b/zkevm-circuits/src/evm_circuit/execution/create.rs @@ -52,6 +52,9 @@ pub(crate) struct CreateGadget { nonce: Cell, callee_reversion_info: ReversionInfo, + + + transfer: TransferGadget, // // // transfer value to new address // transfer: TransferGadget, @@ -101,7 +104,7 @@ impl ExecutionGadget for CreateGadget { ), ); - let [initialization_code_start, initialization_code_length, value] = [(); 3].map(|_| { + let [value, initialization_code_start, initialization_code_length] = [(); 3].map(|_| { let cell = cb.query_word(); cb.stack_pop(cell.expr()); cell @@ -148,6 +151,14 @@ impl ExecutionGadget for CreateGadget { Some(&mut callee_reversion_info), ); + let transfer = TransferGadget::construct( + cb, + caller_address.expr(), + new_address.expr(), + value.clone(), + &mut callee_reversion_info, + ); + // let caller_address = cb.call_context(None, // CallContextFieldTag::CalleeAddress); let [callee_address, value, // callee_address] = [(); 3].map(|| cb.query_word()); let is_failure = @@ -228,6 +239,7 @@ impl ExecutionGadget for CreateGadget { caller_address, nonce, callee_reversion_info, + transfer, } } @@ -250,7 +262,7 @@ impl ExecutionGadget for CreateGadget { Value::known(is_create2.to_scalar().unwrap()), )?; - let [initialization_code_start, initialization_code_length, value, new_address] = + let [value, initialization_code_start, initialization_code_length, new_address] = [0, 1, 2, 3 + usize::from(is_create2)] .map(|i| step.rw_indices[i]) .map(|idx| block.rws[idx].stack_value()); @@ -339,6 +351,17 @@ impl ExecutionGadget for CreateGadget { callee_is_persistent.low_u64() != 0, )?; + let [caller_balance_pair, callee_balance_pair] = [13, 14] + .map(|i| block.rws[step.rw_indices[i + usize::from(is_create2)]].account_value_pair()); + dbg!(caller_balance_pair, callee_balance_pair, value); + self.transfer.assign( + region, + offset, + caller_balance_pair, + callee_balance_pair, + value, + )?; + Ok(()) } } From 979d2934b03706b6c593db698fa0869497ca6ada Mon Sep 17 00:00:00 2001 From: Mason Liang Date: Tue, 6 Dec 2022 16:04:42 -0500 Subject: [PATCH 16/69] fmt --- zkevm-circuits/src/evm_circuit/execution/create.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/zkevm-circuits/src/evm_circuit/execution/create.rs b/zkevm-circuits/src/evm_circuit/execution/create.rs index dcf8a1605b..1b8fe56182 100644 --- a/zkevm-circuits/src/evm_circuit/execution/create.rs +++ b/zkevm-circuits/src/evm_circuit/execution/create.rs @@ -53,7 +53,6 @@ pub(crate) struct CreateGadget { callee_reversion_info: ReversionInfo, - transfer: TransferGadget, // // // transfer value to new address From 6cae76cbd558dd1745722b6c3a50d1586f043c42 Mon Sep 17 00:00:00 2001 From: Mason Liang Date: Wed, 7 Dec 2022 13:14:39 -0500 Subject: [PATCH 17/69] memory_expansion --- bus-mapping/src/evm/opcodes/create.rs | 9 +-- .../src/evm_circuit/execution/create.rs | 72 ++++++++++++++++--- .../src/evm_circuit/util/memory_gadget.rs | 6 ++ 3 files changed, 68 insertions(+), 19 deletions(-) diff --git a/bus-mapping/src/evm/opcodes/create.rs b/bus-mapping/src/evm/opcodes/create.rs index 4c9dfb7b7b..c38c5a1447 100644 --- a/bus-mapping/src/evm/opcodes/create.rs +++ b/bus-mapping/src/evm/opcodes/create.rs @@ -192,13 +192,6 @@ impl Opcode for DummyCreate { state.call_context_write(&mut exec_step, call.call_id, field, value); } - if call.code_hash.to_fixed_bytes() == *EMPTY_HASH { - // 1. Create with empty initcode. - state.handle_return(geth_step)?; - Ok(vec![exec_step]) - } else { - // 2. Create with non-empty initcode. - Ok(vec![exec_step]) - } + Ok(vec![exec_step]) } } diff --git a/zkevm-circuits/src/evm_circuit/execution/create.rs b/zkevm-circuits/src/evm_circuit/execution/create.rs index 1b8fe56182..f83c83b6ea 100644 --- a/zkevm-circuits/src/evm_circuit/execution/create.rs +++ b/zkevm-circuits/src/evm_circuit/execution/create.rs @@ -37,8 +37,8 @@ pub(crate) struct CreateGadget { opcode: Cell, is_create2: Cell, - initialization_code_start: Word, - initialization_code_length: Word, + // initialization_code_start: Word, + // initialization_code_length: Word, value: Word, salt: Word, new_address: RandomLinearCombination, @@ -54,6 +54,9 @@ pub(crate) struct CreateGadget { callee_reversion_info: ReversionInfo, transfer: TransferGadget, + + initialization_code: MemoryAddressGadget, + memory_expansion: MemoryExpansionGadget, // // // transfer value to new address // transfer: TransferGadget, @@ -103,11 +106,13 @@ impl ExecutionGadget for CreateGadget { ), ); - let [value, initialization_code_start, initialization_code_length] = [(); 3].map(|_| { - let cell = cb.query_word(); - cb.stack_pop(cell.expr()); - cell - }); + let value = cb.query_word(); + cb.stack_pop(value.expr()); + + let initialization_code = MemoryAddressGadget::construct_2(cb); + cb.stack_pop(initialization_code.offset()); + cb.stack_pop(initialization_code.length()); + let salt = cb.condition(is_create2.expr(), |cb| { let salt = cb.query_word(); cb.stack_pop(salt.expr()); @@ -158,6 +163,37 @@ impl ExecutionGadget for CreateGadget { &mut callee_reversion_info, ); + let memory_expansion = + MemoryExpansionGadget::construct(cb, [initialization_code.address()]); + + let stack_pointer_delta = 2.expr() + is_create2.expr(); + // let gas_cost = + // let callee_gas_left = + for (field_tag, value) in [ + ( + CallContextFieldTag::ProgramCounter, + cb.curr.state.program_counter.expr() + 1.expr(), + ), + ( + CallContextFieldTag::StackPointer, + cb.curr.state.stack_pointer.expr() + stack_pointer_delta, + ), + // ( + // CallContextFieldTag::GasLeft, + // cb.curr.state.gas_left.expr() - gas_cost - callee_gas_left.clone(), + // ), + // ( + // CallContextFieldTag::MemorySize, + // memory_expansion.next_memory_word_size(), + // ), + // ( + // CallContextFieldTag::ReversibleWriteCounter, + // cb.curr.state.reversible_write_counter.expr() + 1.expr(), + // ), + ] { + cb.call_context_lookup(true.expr(), None, field_tag, value); + } + // let caller_address = cb.call_context(None, // CallContextFieldTag::CalleeAddress); let [callee_address, value, // callee_address] = [(); 3].map(|| cb.query_word()); let is_failure = @@ -230,8 +266,6 @@ impl ExecutionGadget for CreateGadget { reversion_info, tx_id, was_warm, - initialization_code_start, - initialization_code_length, value, salt, new_address, @@ -239,6 +273,8 @@ impl ExecutionGadget for CreateGadget { nonce, callee_reversion_info, transfer, + initialization_code, + memory_expansion, } } @@ -272,13 +308,20 @@ impl ExecutionGadget for CreateGadget { }; for (word, assignment) in [ - (&self.initialization_code_start, initialization_code_start), - (&self.initialization_code_length, initialization_code_length), + // (&self.initialization_code_start, initialization_code_start), + // (&self.initialization_code_length, initialization_code_length), (&self.value, value), (&self.salt, salt), ] { word.assign(region, offset, Some(assignment.to_le_bytes()))?; } + let initialization_code_address = self.initialization_code.assign( + region, + offset, + initialization_code_start, + initialization_code_length, + block.randomness, + )?; self.new_address.assign( region, @@ -361,6 +404,13 @@ impl ExecutionGadget for CreateGadget { value, )?; + self.memory_expansion.assign( + region, + offset, + step.memory_word_size(), + [initialization_code_address], + )?; + Ok(()) } } diff --git a/zkevm-circuits/src/evm_circuit/util/memory_gadget.rs b/zkevm-circuits/src/evm_circuit/util/memory_gadget.rs index e6a6d5a48d..1b3642da79 100644 --- a/zkevm-circuits/src/evm_circuit/util/memory_gadget.rs +++ b/zkevm-circuits/src/evm_circuit/util/memory_gadget.rs @@ -95,6 +95,12 @@ impl MemoryAddressGadget { } } + pub(crate) fn construct_2(cb: &mut ConstraintBuilder) -> Self { + let offset = cb.query_cell(); + let length = cb.query_rlc(); + Self::construct(cb, offset, length) + } + pub(crate) fn assign( &self, region: &mut CachedRegion<'_, '_, F>, From 866af298e3e7bf1443c0dc2b5d3973cff6308cb9 Mon Sep 17 00:00:00 2001 From: Mason Liang Date: Wed, 7 Dec 2022 16:19:05 -0500 Subject: [PATCH 18/69] gas_left --- .../src/evm_circuit/execution/create.rs | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/zkevm-circuits/src/evm_circuit/execution/create.rs b/zkevm-circuits/src/evm_circuit/execution/create.rs index f83c83b6ea..b685b55162 100644 --- a/zkevm-circuits/src/evm_circuit/execution/create.rs +++ b/zkevm-circuits/src/evm_circuit/execution/create.rs @@ -57,6 +57,8 @@ pub(crate) struct CreateGadget { initialization_code: MemoryAddressGadget, memory_expansion: MemoryExpansionGadget, + + gas_left: ConstantDivisionGadget, // // // transfer value to new address // transfer: TransferGadget, @@ -167,8 +169,13 @@ impl ExecutionGadget for CreateGadget { MemoryExpansionGadget::construct(cb, [initialization_code.address()]); let stack_pointer_delta = 2.expr() + is_create2.expr(); - // let gas_cost = - // let callee_gas_left = + + // EIP-150: all but one 64th of the caller's gas is sent to the callee. + // let caller_gas_left = + // (geth_step.gas.0 - geth_step.gas_cost.0 - memory_expansion_gas_cost) / 64; + + let gas_cost = GasCost::CREATE.expr() + memory_expansion.gas_cost(); + let gas_left = ConstantDivisionGadget::construct(cb, cb.curr.state.gas_left.expr() - gas_cost, 64); for (field_tag, value) in [ ( CallContextFieldTag::ProgramCounter, @@ -178,10 +185,7 @@ impl ExecutionGadget for CreateGadget { CallContextFieldTag::StackPointer, cb.curr.state.stack_pointer.expr() + stack_pointer_delta, ), - // ( - // CallContextFieldTag::GasLeft, - // cb.curr.state.gas_left.expr() - gas_cost - callee_gas_left.clone(), - // ), + (CallContextFieldTag::GasLeft, gas_left.quotient()), // ( // CallContextFieldTag::MemorySize, // memory_expansion.next_memory_word_size(), @@ -275,6 +279,7 @@ impl ExecutionGadget for CreateGadget { transfer, initialization_code, memory_expansion, + gas_left, } } @@ -411,6 +416,8 @@ impl ExecutionGadget for CreateGadget { [initialization_code_address], )?; + self.gas_left.assign(region, offset, (step.gas_left - GasCost::CREATE.as_u64()).into())?; + Ok(()) } } From 74adabba016ea9203f32f89fa0f2bfaffbcd1319 Mon Sep 17 00:00:00 2001 From: Mason Liang Date: Wed, 7 Dec 2022 16:23:48 -0500 Subject: [PATCH 19/69] memory word size --- zkevm-circuits/src/evm_circuit/execution/create.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/zkevm-circuits/src/evm_circuit/execution/create.rs b/zkevm-circuits/src/evm_circuit/execution/create.rs index b685b55162..b64b442be9 100644 --- a/zkevm-circuits/src/evm_circuit/execution/create.rs +++ b/zkevm-circuits/src/evm_circuit/execution/create.rs @@ -186,10 +186,10 @@ impl ExecutionGadget for CreateGadget { cb.curr.state.stack_pointer.expr() + stack_pointer_delta, ), (CallContextFieldTag::GasLeft, gas_left.quotient()), - // ( - // CallContextFieldTag::MemorySize, - // memory_expansion.next_memory_word_size(), - // ), + ( + CallContextFieldTag::MemorySize, + memory_expansion.next_memory_word_size(), + ), // ( // CallContextFieldTag::ReversibleWriteCounter, // cb.curr.state.reversible_write_counter.expr() + 1.expr(), From 0325130f4572b34523334580aba8d6400590f51f Mon Sep 17 00:00:00 2001 From: Mason Liang Date: Wed, 7 Dec 2022 16:28:05 -0500 Subject: [PATCH 20/69] reversible write counter --- bus-mapping/src/evm/opcodes/create.rs | 3 ++- zkevm-circuits/src/evm_circuit/execution/create.rs | 8 ++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/bus-mapping/src/evm/opcodes/create.rs b/bus-mapping/src/evm/opcodes/create.rs index c38c5a1447..e01b9c40b6 100644 --- a/bus-mapping/src/evm/opcodes/create.rs +++ b/bus-mapping/src/evm/opcodes/create.rs @@ -144,7 +144,6 @@ impl Opcode for DummyCreate { call.value, )?; - // here in gadget..... let memory_expansion_gas_cost = memory_expansion_gas_cost(curr_memory_word_size, next_memory_word_size); @@ -173,6 +172,8 @@ impl Opcode for DummyCreate { state.call_context_write(&mut exec_step, current_call.call_id, field, value); } + // here in gadget..... + for (field, value) in [ (CallContextField::CallerId, current_call.call_id.into()), (CallContextField::IsSuccess, call.is_success.to_word()), diff --git a/zkevm-circuits/src/evm_circuit/execution/create.rs b/zkevm-circuits/src/evm_circuit/execution/create.rs index b64b442be9..c57e9911fc 100644 --- a/zkevm-circuits/src/evm_circuit/execution/create.rs +++ b/zkevm-circuits/src/evm_circuit/execution/create.rs @@ -190,10 +190,10 @@ impl ExecutionGadget for CreateGadget { CallContextFieldTag::MemorySize, memory_expansion.next_memory_word_size(), ), - // ( - // CallContextFieldTag::ReversibleWriteCounter, - // cb.curr.state.reversible_write_counter.expr() + 1.expr(), - // ), + ( + CallContextFieldTag::ReversibleWriteCounter, + cb.curr.state.reversible_write_counter.expr() + 2.expr(), + ), ] { cb.call_context_lookup(true.expr(), None, field_tag, value); } From 0696b8d83b6efcd7e152aec030efe500648a3f2c Mon Sep 17 00:00:00 2001 From: Mason Liang Date: Thu, 8 Dec 2022 13:28:20 -0500 Subject: [PATCH 21/69] wip --- .../src/evm_circuit/execution/create.rs | 141 +++++++++++------- 1 file changed, 86 insertions(+), 55 deletions(-) diff --git a/zkevm-circuits/src/evm_circuit/execution/create.rs b/zkevm-circuits/src/evm_circuit/execution/create.rs index c57e9911fc..717dd2f269 100644 --- a/zkevm-circuits/src/evm_circuit/execution/create.rs +++ b/zkevm-circuits/src/evm_circuit/execution/create.rs @@ -5,6 +5,7 @@ use crate::{ param::{N_BYTES_ACCOUNT_ADDRESS, N_BYTES_GAS, N_BYTES_MEMORY_WORD_SIZE}, step::ExecutionState, util::{ + and, common_gadget::TransferGadget, constraint_builder::{ ConstraintBuilder, ReversionInfo, StepStateTransition, @@ -59,6 +60,8 @@ pub(crate) struct CreateGadget { memory_expansion: MemoryExpansionGadget, gas_left: ConstantDivisionGadget, + + callee_is_success: Cell, // // // transfer value to new address // transfer: TransferGadget, @@ -175,7 +178,8 @@ impl ExecutionGadget for CreateGadget { // (geth_step.gas.0 - geth_step.gas_cost.0 - memory_expansion_gas_cost) / 64; let gas_cost = GasCost::CREATE.expr() + memory_expansion.gas_cost(); - let gas_left = ConstantDivisionGadget::construct(cb, cb.curr.state.gas_left.expr() - gas_cost, 64); + let gas_left = + ConstantDivisionGadget::construct(cb, cb.curr.state.gas_left.expr() - gas_cost, 64); for (field_tag, value) in [ ( CallContextFieldTag::ProgramCounter, @@ -198,60 +202,71 @@ impl ExecutionGadget for CreateGadget { cb.call_context_lookup(true.expr(), None, field_tag, value); } - // let caller_address = cb.call_context(None, - // CallContextFieldTag::CalleeAddress); let [callee_address, value, - // callee_address] = [(); 3].map(|| cb.query_word()); let is_failure = - // IsZeroGadget::construct(cb, callee_address); - // let mut callee_reversion_info = - // ReversionInfo::from_caller(cb, &reversion_info, - // not::expr(is_failure.expr())); let transfer = - // TransferGadget::construct( cb, - // caller_address.expr(), - // address.expr(), - // value.expr(), - // &mut callee_reversion_info, - // ); - - // let [offset, size] = [(); 2].map(|| cb.query_word()); - // let memory_address = MemoryAddressGadget::construct(cb, offset, size); - // let memory_expansion = MemoryExpansionGadget::construct( - // cb, - // cb.curr.state.memory_word_size.expr(), - // [memory_address.address()], - // ); - // - // let [value, offset, size, salt, address] = [(); 5].map(cb.query_cell()); - // [value, offset, size].map(|cell| cb.stack_pop(cell.expr())); - // cb.condition(is_create2.expr(), |cb| cb.stack_pop(salt.expr())); - // cb.stack_push(address); - // - // let [current_address, is_static, depth] = [ - // CallContextFieldTag::CalleeAddress, - // CallContextFieldTag::IsStatic, - // CallContextFieldTag::Depth, - // ] - // .map(|field_tag| cb.call_context(None, field_tag)); - // - // cb.range_lookup(depth.expr(), 1024); - // - // // Lookup values from stack - // cb.stack_pop(gas_word.expr()); - // cb.stack_pop(callee_address_word.expr()); + // (CallContextField::CallerId, current_call.call_id.into()), + // (CallContextField::IsSuccess, call.is_success.to_word()), + // (CallContextField::IsPersistent, call.is_persistent.to_word()), + // (CallContextField::TxId, state.tx_ctx.id().into()), + // ( + // CallContextField::CallerAddress, + // current_call.address.to_word(), + // ), + // (CallContextField::CalleeAddress, call.address.to_word()), + // ( + // CallContextField::RwCounterEndOfReversion, + // call.rw_counter_end_of_reversion.to_word(), + // ), + // (CallContextField::IsPersistent, call.is_persistent.to_word()), + + // (CallContextFieldTag::CallerId, cb.curr.state.call_id.expr()), + // (CallContextFieldTag::TxId, tx_id.expr()), + // (CallContextFieldTag::Depth, depth.expr() + 1.expr()), + // (CallContextFieldTag::CallerAddress, caller_address), + // (CallContextFieldTag::CalleeAddress, callee_address), + // (CallContextFieldTag::CallDataOffset, cd_address.offset()), + // (CallContextFieldTag::CallDataLength, cd_address.length()), + // (CallContextFieldTag::ReturnDataOffset, rd_address.offset()), + // (CallContextFieldTag::ReturnDataLength, rd_address.length()), + // ( + // CallContextFieldTag::Value, + // select::expr(is_delegatecall.expr(), current_value.expr(), value.expr()), + // ), + // (CallContextFieldTag::IsSuccess, is_success.expr()), + // (CallContextFieldTag::IsStatic, is_staticcall.expr()), + // (CallContextFieldTag::LastCalleeId, 0.expr()), + // (CallContextFieldTag::LastCalleeReturnDataOffset, 0.expr()), + // (CallContextFieldTag::LastCalleeReturnDataLength, 0.expr()), + // (CallContextFieldTag::IsRoot, 0.expr()), + // (CallContextFieldTag::IsCreate, 0.expr()), + // (CallContextFieldTag::CodeHash, callee_code_hash.expr()), + + // TODO: get this from reversion info... + let callee_is_success = cb.query_bool(); + // let caller_is_persistent = cb.call_context(None, + // CallContextFieldTag::IsPersistent); let callee_is_persistent = + // and::expr(&[callee_is_success.expr(), caller_is_persistent.expr()]); + + for (field_tag, value) in [ + (CallContextFieldTag::CallerId, cb.curr.state.call_id.expr()), + (CallContextFieldTag::IsSuccess, callee_is_success.expr()), + ( + CallContextFieldTag::IsPersistent, + callee_reversion_info.is_persistent(), + ), + (CallContextFieldTag::TxId, tx_id.expr()), + // ( + // CallContextField::CallerAddress, + // current_call.address.to_word(), + // ), + // (CallContextField::CalleeAddress, new_address.expr()), + // ( + // CallContextField::RwCounterEndOfReversion, + // call.rw_counter_end_of_reversion.to_word(), + // ), + // (CallContextField::IsPersistent, call.is_persistent.to_word()), + ] { + cb.call_context_lookup(true.expr(), Some(callee_call_id.expr()), field_tag, value); + } - // // `CALL` opcode has an additional stack pop `value`. - // cb.condition(IS_CREATE2.expr(), |cb| cb.stack_pop(value.expr())); - // - // [ - // cd_offset.expr(), - // cd_length.expr(), - // rd_offset.expr(), - // rd_length.expr(), - // ] - // .map(|expression| cb.stack_pop(expression)); - // cb.stack_push(is_success.expr()); - - // let gas = Eip150Gadget::construct(cb, cb.curr.state.gas_left.expr() - - // GasCost::CREATE); // // cb.require_step_state_transition(StepStateTransition { // rw_counter: Delta(cb.rw_counter_offset.clone()), @@ -280,6 +295,7 @@ impl ExecutionGadget for CreateGadget { initialization_code, memory_expansion, gas_left, + callee_is_success, } } @@ -416,7 +432,22 @@ impl ExecutionGadget for CreateGadget { [initialization_code_address], )?; - self.gas_left.assign(region, offset, (step.gas_left - GasCost::CREATE.as_u64()).into())?; + self.gas_left.assign( + region, + offset, + (step.gas_left - GasCost::CREATE.as_u64()).into(), + )?; + + self.callee_is_success.assign( + region, + offset, + Value::known( + block.rws[step.rw_indices[20 + usize::from(is_create2)]] + .call_context_value() + .to_scalar() + .unwrap(), + ), + )?; Ok(()) } From fca1db2c024b45dd49cdc4ec610731c90da89fcc Mon Sep 17 00:00:00 2001 From: Mason Liang Date: Thu, 8 Dec 2022 15:22:25 -0500 Subject: [PATCH 22/69] wip --- bus-mapping/src/evm/opcodes.rs | 2 +- bus-mapping/src/evm/opcodes/create.rs | 3 - .../src/evm_circuit/execution/create.rs | 56 ++----------------- 3 files changed, 7 insertions(+), 54 deletions(-) diff --git a/bus-mapping/src/evm/opcodes.rs b/bus-mapping/src/evm/opcodes.rs index fc6a5930bf..413e71f5db 100644 --- a/bus-mapping/src/evm/opcodes.rs +++ b/bus-mapping/src/evm/opcodes.rs @@ -399,7 +399,7 @@ pub fn gen_begin_tx_ops(state: &mut CircuitInputStateRef) -> Result { - panic!("shouldn't be here!!!!"); + // panic!("shouldn't be here!!!!"); state.account_read( &mut exec_step, call.address, diff --git a/bus-mapping/src/evm/opcodes/create.rs b/bus-mapping/src/evm/opcodes/create.rs index e01b9c40b6..f81dba00d2 100644 --- a/bus-mapping/src/evm/opcodes/create.rs +++ b/bus-mapping/src/evm/opcodes/create.rs @@ -172,8 +172,6 @@ impl Opcode for DummyCreate { state.call_context_write(&mut exec_step, current_call.call_id, field, value); } - // here in gadget..... - for (field, value) in [ (CallContextField::CallerId, current_call.call_id.into()), (CallContextField::IsSuccess, call.is_success.to_word()), @@ -188,7 +186,6 @@ impl Opcode for DummyCreate { CallContextField::RwCounterEndOfReversion, call.rw_counter_end_of_reversion.to_word(), ), - (CallContextField::IsPersistent, call.is_persistent.to_word()), ] { state.call_context_write(&mut exec_step, call.call_id, field, value); } diff --git a/zkevm-circuits/src/evm_circuit/execution/create.rs b/zkevm-circuits/src/evm_circuit/execution/create.rs index 717dd2f269..ef93c57011 100644 --- a/zkevm-circuits/src/evm_circuit/execution/create.rs +++ b/zkevm-circuits/src/evm_circuit/execution/create.rs @@ -202,48 +202,8 @@ impl ExecutionGadget for CreateGadget { cb.call_context_lookup(true.expr(), None, field_tag, value); } - // (CallContextField::CallerId, current_call.call_id.into()), - // (CallContextField::IsSuccess, call.is_success.to_word()), - // (CallContextField::IsPersistent, call.is_persistent.to_word()), - // (CallContextField::TxId, state.tx_ctx.id().into()), - // ( - // CallContextField::CallerAddress, - // current_call.address.to_word(), - // ), - // (CallContextField::CalleeAddress, call.address.to_word()), - // ( - // CallContextField::RwCounterEndOfReversion, - // call.rw_counter_end_of_reversion.to_word(), - // ), - // (CallContextField::IsPersistent, call.is_persistent.to_word()), - - // (CallContextFieldTag::CallerId, cb.curr.state.call_id.expr()), - // (CallContextFieldTag::TxId, tx_id.expr()), - // (CallContextFieldTag::Depth, depth.expr() + 1.expr()), - // (CallContextFieldTag::CallerAddress, caller_address), - // (CallContextFieldTag::CalleeAddress, callee_address), - // (CallContextFieldTag::CallDataOffset, cd_address.offset()), - // (CallContextFieldTag::CallDataLength, cd_address.length()), - // (CallContextFieldTag::ReturnDataOffset, rd_address.offset()), - // (CallContextFieldTag::ReturnDataLength, rd_address.length()), - // ( - // CallContextFieldTag::Value, - // select::expr(is_delegatecall.expr(), current_value.expr(), value.expr()), - // ), - // (CallContextFieldTag::IsSuccess, is_success.expr()), - // (CallContextFieldTag::IsStatic, is_staticcall.expr()), - // (CallContextFieldTag::LastCalleeId, 0.expr()), - // (CallContextFieldTag::LastCalleeReturnDataOffset, 0.expr()), - // (CallContextFieldTag::LastCalleeReturnDataLength, 0.expr()), - // (CallContextFieldTag::IsRoot, 0.expr()), - // (CallContextFieldTag::IsCreate, 0.expr()), - // (CallContextFieldTag::CodeHash, callee_code_hash.expr()), - // TODO: get this from reversion info... let callee_is_success = cb.query_bool(); - // let caller_is_persistent = cb.call_context(None, - // CallContextFieldTag::IsPersistent); let callee_is_persistent = - // and::expr(&[callee_is_success.expr(), caller_is_persistent.expr()]); for (field_tag, value) in [ (CallContextFieldTag::CallerId, cb.curr.state.call_id.expr()), @@ -253,16 +213,12 @@ impl ExecutionGadget for CreateGadget { callee_reversion_info.is_persistent(), ), (CallContextFieldTag::TxId, tx_id.expr()), - // ( - // CallContextField::CallerAddress, - // current_call.address.to_word(), - // ), - // (CallContextField::CalleeAddress, new_address.expr()), - // ( - // CallContextField::RwCounterEndOfReversion, - // call.rw_counter_end_of_reversion.to_word(), - // ), - // (CallContextField::IsPersistent, call.is_persistent.to_word()), + (CallContextFieldTag::CallerAddress, caller_address.expr()), + (CallContextFieldTag::CalleeAddress, new_address.expr()), + ( + CallContextFieldTag::RwCounterEndOfReversion, + callee_reversion_info.rw_counter_end_of_reversion(), + ), ] { cb.call_context_lookup(true.expr(), Some(callee_call_id.expr()), field_tag, value); } From 2691f83df1ca5484b420e624d7c3efe00eeddcf8 Mon Sep 17 00:00:00 2001 From: Mason Liang Date: Thu, 8 Dec 2022 15:22:41 -0500 Subject: [PATCH 23/69] wip --- bus-mapping/src/evm/opcodes.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/bus-mapping/src/evm/opcodes.rs b/bus-mapping/src/evm/opcodes.rs index 413e71f5db..566eff7a58 100644 --- a/bus-mapping/src/evm/opcodes.rs +++ b/bus-mapping/src/evm/opcodes.rs @@ -399,7 +399,6 @@ pub fn gen_begin_tx_ops(state: &mut CircuitInputStateRef) -> Result { - // panic!("shouldn't be here!!!!"); state.account_read( &mut exec_step, call.address, @@ -455,9 +454,6 @@ pub fn gen_begin_tx_ops(state: &mut CircuitInputStateRef) -> Result Date: Thu, 8 Dec 2022 15:26:06 -0500 Subject: [PATCH 24/69] fix and fmt --- bus-mapping/src/evm/opcodes/create.rs | 10 +++++---- zkevm-circuits/src/evm_circuit/execution.rs | 1 - .../src/evm_circuit/execution/create.rs | 21 +++++-------------- 3 files changed, 11 insertions(+), 21 deletions(-) diff --git a/bus-mapping/src/evm/opcodes/create.rs b/bus-mapping/src/evm/opcodes/create.rs index f81dba00d2..8ff50822ef 100644 --- a/bus-mapping/src/evm/opcodes/create.rs +++ b/bus-mapping/src/evm/opcodes/create.rs @@ -3,7 +3,6 @@ use crate::evm::Opcode; use crate::operation::{AccountField, AccountOp, CallContextField, TxAccessListAccountOp, RW}; use crate::Error; use eth_types::{evm_types::gas_utils::memory_expansion_gas_cost, GethExecStep, ToWord, Word}; -use keccak256::EMPTY_HASH; #[derive(Debug, Copy, Clone)] pub struct DummyCreate; @@ -94,9 +93,12 @@ impl Opcode for DummyCreate { }, )?; - for (field, value) in [(CallContextField::CalleeAddress, current_call.address)] { - state.call_context_read(&mut exec_step, current_call.call_id, field, value.to_word()); - } + state.call_context_read( + &mut exec_step, + current_call.call_id, + CallContextField::CalleeAddress, + current_call.address.to_word(), + ); // Increase caller's nonce let nonce_prev = state.sdb.get_nonce(&call.caller_address); diff --git a/zkevm-circuits/src/evm_circuit/execution.rs b/zkevm-circuits/src/evm_circuit/execution.rs index 318f32f618..4ccc101aef 100644 --- a/zkevm-circuits/src/evm_circuit/execution.rs +++ b/zkevm-circuits/src/evm_circuit/execution.rs @@ -1019,7 +1019,6 @@ impl ExecutionConfig { ExecutionState::SAR => assign_exec_step!(self.sar_gadget), ExecutionState::EXTCODESIZE => assign_exec_step!(self.extcodesize_gadget), ExecutionState::EXTCODECOPY => assign_exec_step!(self.extcodecopy_gadget), - ExecutionState::CREATE => assign_exec_step!(self.create_gadget), ExecutionState::SELFDESTRUCT => assign_exec_step!(self.selfdestruct_gadget), // end of dummy gadgets ExecutionState::SHA3 => assign_exec_step!(self.sha3_gadget), diff --git a/zkevm-circuits/src/evm_circuit/execution/create.rs b/zkevm-circuits/src/evm_circuit/execution/create.rs index ef93c57011..1a30e98b51 100644 --- a/zkevm-circuits/src/evm_circuit/execution/create.rs +++ b/zkevm-circuits/src/evm_circuit/execution/create.rs @@ -5,19 +5,12 @@ use crate::{ param::{N_BYTES_ACCOUNT_ADDRESS, N_BYTES_GAS, N_BYTES_MEMORY_WORD_SIZE}, step::ExecutionState, util::{ - and, common_gadget::TransferGadget, - constraint_builder::{ - ConstraintBuilder, ReversionInfo, StepStateTransition, - Transition::{Delta, To}, - }, + constraint_builder::{ConstraintBuilder, ReversionInfo}, from_bytes, - math_gadget::{ - BatchedIsZeroGadget, ConstantDivisionGadget, IsEqualGadget, IsZeroGadget, - MinMaxGadget, - }, + math_gadget::ConstantDivisionGadget, memory_gadget::{MemoryAddressGadget, MemoryExpansionGadget}, - select, sum, CachedRegion, Cell, Word, + select, CachedRegion, Cell, Word, }, witness::{Block, Call, ExecStep, Transaction}, }, @@ -25,12 +18,8 @@ use crate::{ util::Expr, }; use bus_mapping::evm::OpcodeId; -use eth_types::{ - evm_types::{GasCost, GAS_STIPEND_CALL_WITH_VALUE}, - Field, ToAddress, ToLittleEndian, ToScalar, U256, -}; +use eth_types::{evm_types::GasCost, Field, ToLittleEndian, ToScalar, U256}; use halo2_proofs::{circuit::Value, plonk::Error}; -use keccak256::EMPTY_HASH_LE; /// Gadget for CREATE and CREATE2 opcodes #[derive(Clone, Debug)] @@ -417,7 +406,7 @@ mod test { Word, }; use itertools::Itertools; - use mock::{eth, TestContext, MOCK_ACCOUNTS}; + use mock::{eth, TestContext}; const CALLEE_ADDRESS: Address = Address::repeat_byte(0xff); const CALLER_ADDRESS: Address = Address::repeat_byte(0x34); From 65d70f6c8a65d9831fe600c3bacf1571c1edb6d9 Mon Sep 17 00:00:00 2001 From: Mason Liang Date: Sat, 10 Dec 2022 01:28:17 -0500 Subject: [PATCH 25/69] wip --- .../circuit_input_builder/input_state_ref.rs | 8 ++-- bus-mapping/src/evm/opcodes/create.rs | 8 ++++ zkevm-circuits/src/evm_circuit/execution.rs | 37 ++++++++------- .../src/evm_circuit/execution/create.rs | 46 ++++++++++--------- .../evm_circuit/execution/return_revert.rs | 4 +- 5 files changed, 59 insertions(+), 44 deletions(-) diff --git a/bus-mapping/src/circuit_input_builder/input_state_ref.rs b/bus-mapping/src/circuit_input_builder/input_state_ref.rs index 0299c813b7..7cd8123100 100644 --- a/bus-mapping/src/circuit_input_builder/input_state_ref.rs +++ b/bus-mapping/src/circuit_input_builder/input_state_ref.rs @@ -162,19 +162,20 @@ impl<'a> CircuitInputStateRef<'a> { /// This method should be used in `Opcode::gen_associated_ops` instead of /// `push_op` when the operation is `RW::WRITE` and it can be reverted (for /// example, a write [`StorageOp`](crate::operation::StorageOp)). - pub fn push_op_reversible( + pub fn push_op_reversible( &mut self, step: &mut ExecStep, rw: RW, op: T, ) -> Result<(), Error> { + dbg!(op.clone()); if matches!(rw, RW::WRITE) { self.apply_op(&op.clone().into_enum()); } let op_ref = self.block.container.insert(Operation::new_reversible( self.block_ctx.rwc.inc_pre(), rw, - op, + op.clone(), )); step.bus_mapping_instance.push(op_ref); @@ -183,6 +184,7 @@ impl<'a> CircuitInputStateRef<'a> { // Add the operation into reversible_ops if this call is not persistent if !self.call()?.is_persistent { + // dbg!(op.clone()); self.tx_ctx .reversion_groups .last_mut() @@ -588,7 +590,7 @@ impl<'a> CircuitInputStateRef<'a> { let caller = self.call()?; let caller_ctx = self.call_ctx()?; - dbg!(caller.address); + // dbg!(caller.address); let (caller_address, address, value) = match kind { CallKind::Call => ( caller.address, diff --git a/bus-mapping/src/evm/opcodes/create.rs b/bus-mapping/src/evm/opcodes/create.rs index 8ff50822ef..62a4171818 100644 --- a/bus-mapping/src/evm/opcodes/create.rs +++ b/bus-mapping/src/evm/opcodes/create.rs @@ -47,6 +47,8 @@ impl Opcode for DummyCreate { state.create_address()? }; + dbg!(call.is_success); + dbg!(call.clone()); state.stack_write( &mut exec_step, geth_step.stack.nth_last_filled(n_pop - 1), @@ -82,6 +84,9 @@ impl Opcode for DummyCreate { } let is_warm = state.sdb.check_account_in_access_list(&address); + dbg!(state.call()?.is_persistent); + dbg!(state.call()?.is_success); + dbg!(state.block_ctx.rwc); state.push_op_reversible( &mut exec_step, RW::WRITE, @@ -92,6 +97,9 @@ impl Opcode for DummyCreate { is_warm_prev: is_warm, }, )?; + dbg!(state.block_ctx.rwc); + // dbg!(state.rw_counter); + // this should not be be reversed?????, but now it's in the wrong call???? state.call_context_read( &mut exec_step, diff --git a/zkevm-circuits/src/evm_circuit/execution.rs b/zkevm-circuits/src/evm_circuit/execution.rs index 4ccc101aef..117de0c094 100644 --- a/zkevm-circuits/src/evm_circuit/execution.rs +++ b/zkevm-circuits/src/evm_circuit/execution.rs @@ -1182,24 +1182,27 @@ impl ExecutionConfig { for (name, value) in assigned_rw_values.iter() { if !rlc_assignments.contains(value) { - log::error!("rw lookup error: name: {}, step: {:?}", *name, step); - } - } - for (idx, assigned_rw_value) in assigned_rw_values.iter().enumerate() { - let rw_idx = step.rw_indices[idx]; - let rw = block.rws[rw_idx]; - let table_assignments = rw.table_assignment_aux(block.randomness); - let rlc = table_assignments.rlc(block.randomness); - if rlc != assigned_rw_value.1 { - log::error!( - "incorrect rw witness. lookup input name: \"{}\"\n{:?}\nrw: {:?}, rw index: {:?}, {}th rw of step {:?}", - assigned_rw_value.0, - assigned_rw_value.1, - rw, - rw_idx, - idx, - step.execution_state); + log::error!("rw lookup error: name: {}", *name); + // log::error!("rw lookup error: name: {}, step: {:?}", *name, + // step); } } + // for (idx, assigned_rw_value) in assigned_rw_values.iter().enumerate() + // { let rw_idx = step.rw_indices[idx]; + // let rw = block.rws[rw_idx]; + // let table_assignments = + // rw.table_assignment_aux(block.randomness); let rlc = + // table_assignments.rlc(block.randomness); if rlc != + // assigned_rw_value.1 { log::error!( + // "incorrect rw witness. lookup input name: + // \"{}\"\n{:?}\nrw: {:?}, rw index: {:?}, {}th rw of step {:?}", + // assigned_rw_value.0, + // assigned_rw_value.1, + // rw, + // rw_idx, + // idx, + // step.execution_state); + // } + // } } } diff --git a/zkevm-circuits/src/evm_circuit/execution/create.rs b/zkevm-circuits/src/evm_circuit/execution/create.rs index 1a30e98b51..f9df10f32f 100644 --- a/zkevm-circuits/src/evm_circuit/execution/create.rs +++ b/zkevm-circuits/src/evm_circuit/execution/create.rs @@ -113,7 +113,8 @@ impl ExecutionGadget for CreateGadget { salt }); let new_address = cb.query_rlc(); - cb.stack_push(new_address.expr()); + let callee_is_success = cb.query_bool(); + cb.stack_push(callee_is_success.expr() * new_address.expr()); let tx_id = cb.call_context(None, CallContextFieldTag::TxId); let mut reversion_info = cb.reversion_info_read(None); @@ -137,9 +138,6 @@ impl ExecutionGadget for CreateGadget { // None, ); - // let caller_address = cb.call_context(None, - // CallContextFieldTag::CalleeAddress); - let mut callee_reversion_info = cb.reversion_info_write(Some(callee_call_id.expr())); cb.account_write( new_address.expr(), @@ -191,9 +189,6 @@ impl ExecutionGadget for CreateGadget { cb.call_context_lookup(true.expr(), None, field_tag, value); } - // TODO: get this from reversion info... - let callee_is_success = cb.query_bool(); - for (field_tag, value) in [ (CallContextFieldTag::CallerId, cb.curr.state.call_id.expr()), (CallContextFieldTag::IsSuccess, callee_is_success.expr()), @@ -263,16 +258,21 @@ impl ExecutionGadget for CreateGadget { Value::known(is_create2.to_scalar().unwrap()), )?; - let [value, initialization_code_start, initialization_code_length, new_address] = - [0, 1, 2, 3 + usize::from(is_create2)] - .map(|i| step.rw_indices[i]) - .map(|idx| block.rws[idx].stack_value()); + let [value, initialization_code_start, initialization_code_length] = [0, 1, 2] + .map(|i| step.rw_indices[i]) + .map(|idx| block.rws[idx].stack_value()); let salt = if is_create2 { block.rws[step.rw_indices[3]].stack_value() } else { U256::zero() }; + let tx_access_rw = block.rws[step.rw_indices[7 + usize::from(is_create2)]]; + dbg!(tx_access_rw.clone()); + + let new_address = tx_access_rw.address().expect("asdfawefasdf"); + dbg!(new_address); + for (word, assignment) in [ // (&self.initialization_code_start, initialization_code_start), // (&self.initialization_code_length, initialization_code_length), @@ -289,15 +289,15 @@ impl ExecutionGadget for CreateGadget { block.randomness, )?; - self.new_address.assign( - region, - offset, - Some(new_address.to_le_bytes()[0..20].try_into().unwrap()), - )?; + let mut bytes = new_address.to_fixed_bytes(); + bytes.reverse(); + + self.new_address.assign(region, offset, Some(bytes))?; self.tx_id .assign(region, offset, Value::known(tx.id.to_scalar().unwrap()))?; + dbg!(call.rw_counter_end_of_reversion, call.is_persistent); self.reversion_info.assign( region, offset, @@ -309,7 +309,7 @@ impl ExecutionGadget for CreateGadget { region, offset, Value::known( - block.rws[step.rw_indices[7 + usize::from(is_create2)]] + tx_access_rw .tx_access_list_value_pair() .1 .to_scalar() @@ -317,7 +317,7 @@ impl ExecutionGadget for CreateGadget { ), )?; - dbg!(call.callee_address); + // dbg!(call.callee_address); self.caller_address.assign( region, offset, @@ -347,7 +347,7 @@ impl ExecutionGadget for CreateGadget { let [callee_rw_counter_end_of_reversion, callee_is_persistent] = [10, 11] .map(|i| block.rws[step.rw_indices[i + usize::from(is_create2)]].call_context_value()); - dbg!(callee_rw_counter_end_of_reversion, callee_is_persistent); + // dbg!(callee_rw_counter_end_of_reversion, callee_is_persistent); self.callee_reversion_info.assign( region, @@ -361,7 +361,7 @@ impl ExecutionGadget for CreateGadget { let [caller_balance_pair, callee_balance_pair] = [13, 14] .map(|i| block.rws[step.rw_indices[i + usize::from(is_create2)]].account_value_pair()); - dbg!(caller_balance_pair, callee_balance_pair, value); + // dbg!(caller_balance_pair, callee_balance_pair, value); self.transfer.assign( region, offset, @@ -383,11 +383,15 @@ impl ExecutionGadget for CreateGadget { (step.gas_left - GasCost::CREATE.as_u64()).into(), )?; + // dbg!(block.rws[step.rw_indices[20 + usize::from(is_create2)]]); + // dbg!(block.rws[step.rw_indices[21 + usize::from(is_create2)]]); + // dbg!(block.rws[step.rw_indices[22 + usize::from(is_create2)]]); + // dbg!(block.rws[step.rw_indices[23 + usize::from(is_create2)]]); self.callee_is_success.assign( region, offset, Value::known( - block.rws[step.rw_indices[20 + usize::from(is_create2)]] + block.rws[step.rw_indices[21 + usize::from(is_create2)]] .call_context_value() .to_scalar() .unwrap(), diff --git a/zkevm-circuits/src/evm_circuit/execution/return_revert.rs b/zkevm-circuits/src/evm_circuit/execution/return_revert.rs index d123c338a1..be4fce0d59 100644 --- a/zkevm-circuits/src/evm_circuit/execution/return_revert.rs +++ b/zkevm-circuits/src/evm_circuit/execution/return_revert.rs @@ -508,9 +508,7 @@ mod test { #[test] fn test_return_nonroot_create() { let test_parameters = [(0, 0), (0, 10), (300, 20), (1000, 0)]; - for ((offset, length), is_return) in - test_parameters.iter().cartesian_product(&[true, false]) - { + for ((offset, length), is_return) in test_parameters.iter().cartesian_product(&[false]) { let initializer = callee_bytecode(*is_return, *offset, *length).code(); let root_code = bytecode! { From e843549784f407307083ca1cb1738e700891f875 Mon Sep 17 00:00:00 2001 From: Mason Liang Date: Mon, 12 Dec 2022 21:22:47 -0500 Subject: [PATCH 26/69] Add memory word size function --- bus-mapping/src/circuit_input_builder/call.rs | 7 +++++++ bus-mapping/src/evm/opcodes/create.rs | 15 ++------------- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/bus-mapping/src/circuit_input_builder/call.rs b/bus-mapping/src/circuit_input_builder/call.rs index b0e3b52773..85620f6320 100644 --- a/bus-mapping/src/circuit_input_builder/call.rs +++ b/bus-mapping/src/circuit_input_builder/call.rs @@ -121,6 +121,13 @@ pub struct CallContext { pub return_data: Vec, } +impl CallContext { + /// Memory size in words, rounded up + pub fn memory_word_size(&self) -> u64 { + u64::try_from(self.memory.len()).expect("failed to convert usize to u64") / 32 + } +} + /// A reversion group is the collection of calls and the operations which are /// [`Operation::reversible`](crate::operation::Operation::reversible) that /// happened in them, that will be reverted at once when the call that initiated diff --git a/bus-mapping/src/evm/opcodes/create.rs b/bus-mapping/src/evm/opcodes/create.rs index 62a4171818..228dbaa7df 100644 --- a/bus-mapping/src/evm/opcodes/create.rs +++ b/bus-mapping/src/evm/opcodes/create.rs @@ -12,20 +12,19 @@ impl Opcode for DummyCreate { state: &mut CircuitInputStateRef, geth_steps: &[GethExecStep], ) -> Result, Error> { - // TODO: replace dummy create here let geth_step = &geth_steps[0]; let offset = geth_step.stack.nth_last(1)?.as_usize(); let length = geth_step.stack.nth_last(2)?.as_usize(); - let curr_memory_word_size = (state.call_ctx()?.memory.len() as u64) / 32; + let curr_memory_word_size = state.call_ctx()?.memory_word_size(); if length != 0 { state .call_ctx_mut()? .memory .extend_at_least(offset + length); } - let next_memory_word_size = (state.call_ctx()?.memory.len() as u64) / 32; + let next_memory_word_size = state.call_ctx()?.memory_word_size(); let mut exec_step = state.new_step(geth_step)?; @@ -46,9 +45,6 @@ impl Opcode for DummyCreate { } else { state.create_address()? }; - - dbg!(call.is_success); - dbg!(call.clone()); state.stack_write( &mut exec_step, geth_step.stack.nth_last_filled(n_pop - 1), @@ -84,9 +80,6 @@ impl Opcode for DummyCreate { } let is_warm = state.sdb.check_account_in_access_list(&address); - dbg!(state.call()?.is_persistent); - dbg!(state.call()?.is_success); - dbg!(state.block_ctx.rwc); state.push_op_reversible( &mut exec_step, RW::WRITE, @@ -97,9 +90,6 @@ impl Opcode for DummyCreate { is_warm_prev: is_warm, }, )?; - dbg!(state.block_ctx.rwc); - // dbg!(state.rw_counter); - // this should not be be reversed?????, but now it's in the wrong call???? state.call_context_read( &mut exec_step, @@ -146,7 +136,6 @@ impl Opcode for DummyCreate { }, )?; - dbg!(call.value); state.transfer( &mut exec_step, call.caller_address, From 42f17108a8c2f975db06db1662df61cd4c202a0b Mon Sep 17 00:00:00 2001 From: Mason Liang Date: Thu, 15 Dec 2022 12:55:17 -0500 Subject: [PATCH 27/69] Add init code copy lookup --- bus-mapping/src/evm/opcodes/create.rs | 61 +++++++++++++++- .../src/evm_circuit/execution/create.rs | 71 ++++++++++++++++--- 2 files changed, 120 insertions(+), 12 deletions(-) diff --git a/bus-mapping/src/evm/opcodes/create.rs b/bus-mapping/src/evm/opcodes/create.rs index 228dbaa7df..ed6b2c9edd 100644 --- a/bus-mapping/src/evm/opcodes/create.rs +++ b/bus-mapping/src/evm/opcodes/create.rs @@ -1,8 +1,15 @@ -use crate::circuit_input_builder::{CircuitInputStateRef, ExecStep}; +use crate::circuit_input_builder::{ + CircuitInputStateRef, CopyDataType, CopyEvent, ExecStep, NumberOrHash, +}; use crate::evm::Opcode; -use crate::operation::{AccountField, AccountOp, CallContextField, TxAccessListAccountOp, RW}; +use crate::operation::{ + AccountField, AccountOp, CallContextField, MemoryOp, TxAccessListAccountOp, RW, +}; use crate::Error; -use eth_types::{evm_types::gas_utils::memory_expansion_gas_cost, GethExecStep, ToWord, Word}; +use eth_types::{ + evm_types::gas_utils::memory_expansion_gas_cost, Bytecode, GethExecStep, ToWord, Word, H256, +}; +use ethers_core::utils::keccak256; #[derive(Debug, Copy, Clone)] pub struct DummyCreate; @@ -55,6 +62,10 @@ impl Opcode for DummyCreate { }, )?; + if length > 0 { + handle_copy(state, &mut exec_step, state.call()?.call_id, offset, length)?; + } + // Quote from [EIP-2929](https://eips.ethereum.org/EIPS/eip-2929) // > When a CREATE or CREATE2 opcode is called, // > immediately (i.e. before checks are done to determine @@ -192,3 +203,47 @@ impl Opcode for DummyCreate { Ok(vec![exec_step]) } } + +fn handle_copy( + state: &mut CircuitInputStateRef, + step: &mut ExecStep, + callee_id: usize, + offset: usize, + length: usize, +) -> Result<(), Error> { + dbg!("asdfasdf"); + dbg!(offset, length, state.call_ctx()?.memory.0.len()); + let initialization_bytes = state.call_ctx()?.memory.0[offset..offset + length].to_vec(); + dbg!("asdfaw3r12341"); + let dst_id = NumberOrHash::Hash(H256(keccak256(&initialization_bytes))); + let bytes: Vec<_> = Bytecode::from(initialization_bytes) + .code + .iter() + .map(|element| (element.value, element.is_code)) + .collect(); + + let rw_counter_start = state.block_ctx.rwc; + for (i, (byte, _)) in bytes.iter().enumerate() { + // this could be a memory read, if this happens before we push the new call? + state.push_op( + step, + RW::READ, + MemoryOp::new(callee_id, (offset + i).into(), *byte), + ); + } + + state.push_copy(CopyEvent { + rw_counter_start, + src_type: CopyDataType::Memory, + src_id: NumberOrHash::Number(callee_id.try_into().unwrap()), + src_addr: offset.try_into().unwrap(), + src_addr_end: (offset + length).try_into().unwrap(), + dst_type: CopyDataType::Bytecode, + dst_id, + dst_addr: 0, + log_id: None, + bytes, + }); + + Ok(()) +} diff --git a/zkevm-circuits/src/evm_circuit/execution/create.rs b/zkevm-circuits/src/evm_circuit/execution/create.rs index f9df10f32f..e4a609e98d 100644 --- a/zkevm-circuits/src/evm_circuit/execution/create.rs +++ b/zkevm-circuits/src/evm_circuit/execution/create.rs @@ -10,16 +10,18 @@ use crate::{ from_bytes, math_gadget::ConstantDivisionGadget, memory_gadget::{MemoryAddressGadget, MemoryExpansionGadget}, - select, CachedRegion, Cell, Word, + not, select, CachedRegion, Cell, Word, }, witness::{Block, Call, ExecStep, Transaction}, }, table::{AccountFieldTag, CallContextFieldTag}, util::Expr, }; -use bus_mapping::evm::OpcodeId; +use bus_mapping::{circuit_input_builder::CopyDataType, evm::OpcodeId}; use eth_types::{evm_types::GasCost, Field, ToLittleEndian, ToScalar, U256}; +use ethers_core::utils::keccak256; use halo2_proofs::{circuit::Value, plonk::Error}; +use keccak256::EMPTY_HASH_LE; /// Gadget for CREATE and CREATE2 opcodes #[derive(Clone, Debug)] @@ -75,6 +77,7 @@ pub(crate) struct CreateGadget { // errors: // is_empty_nonce_and_balance: BatchedIsZeroGadget, // is_empty_code_hash: IsEqualGadget, + code_hash: Cell, } impl ExecutionGadget for CreateGadget { @@ -116,6 +119,32 @@ impl ExecutionGadget for CreateGadget { let callee_is_success = cb.query_bool(); cb.stack_push(callee_is_success.expr() * new_address.expr()); + let code_hash = cb.query_cell(); + cb.condition(initialization_code.has_length(), |cb| { + cb.copy_table_lookup( + cb.curr.state.call_id.expr(), + CopyDataType::Memory.expr(), + code_hash.expr(), + CopyDataType::Bytecode.expr(), + initialization_code.offset(), + initialization_code.address(), + 0.expr(), + initialization_code.length(), + 0.expr(), + initialization_code.length(), + ); + }); + cb.condition(not::expr(initialization_code.has_length()), |cb| { + cb.require_equal( + "", + code_hash.expr(), + Word::random_linear_combine_expr( + (*EMPTY_HASH_LE).map(|b| b.expr()), + cb.power_of_randomness(), + ), + ); + }); + let tx_id = cb.call_context(None, CallContextFieldTag::TxId); let mut reversion_info = cb.reversion_info_read(None); let was_warm = cb.query_bool(); @@ -236,6 +265,7 @@ impl ExecutionGadget for CreateGadget { memory_expansion, gas_left, callee_is_success, + code_hash, } } @@ -267,7 +297,26 @@ impl ExecutionGadget for CreateGadget { U256::zero() }; - let tx_access_rw = block.rws[step.rw_indices[7 + usize::from(is_create2)]]; + let copy_rw_increase = initialization_code_length.as_usize(); + // dopy lookup here advances rw_counter by initialization_code_length; + + let values: Vec<_> = (4 + usize::from(is_create2) + ..4 + usize::from(is_create2) + initialization_code_length.as_usize()) + .map(|i| block.rws[step.rw_indices[i]].memory_value()) + .collect(); + let mut code_hash = keccak256(&values); + code_hash.reverse(); + self.code_hash.assign( + region, + offset, + Value::known(RandomLinearCombination::random_linear_combine( + code_hash, + block.randomness, + )), + )?; + + let tx_access_rw = + block.rws[step.rw_indices[7 + usize::from(is_create2) + copy_rw_increase]]; dbg!(tx_access_rw.clone()); let new_address = tx_access_rw.address().expect("asdfawefasdf"); @@ -328,7 +377,7 @@ impl ExecutionGadget for CreateGadget { region, offset, Value::known( - block.rws[step.rw_indices[9 + usize::from(is_create2)]] + block.rws[step.rw_indices[9 + usize::from(is_create2) + copy_rw_increase]] .account_value_pair() .1 .to_scalar() @@ -344,8 +393,10 @@ impl ExecutionGadget for CreateGadget { // Some(address_bytes) // )?; - let [callee_rw_counter_end_of_reversion, callee_is_persistent] = [10, 11] - .map(|i| block.rws[step.rw_indices[i + usize::from(is_create2)]].call_context_value()); + let [callee_rw_counter_end_of_reversion, callee_is_persistent] = [10, 11].map(|i| { + block.rws[step.rw_indices[i + usize::from(is_create2) + copy_rw_increase]] + .call_context_value() + }); // dbg!(callee_rw_counter_end_of_reversion, callee_is_persistent); @@ -359,8 +410,10 @@ impl ExecutionGadget for CreateGadget { callee_is_persistent.low_u64() != 0, )?; - let [caller_balance_pair, callee_balance_pair] = [13, 14] - .map(|i| block.rws[step.rw_indices[i + usize::from(is_create2)]].account_value_pair()); + let [caller_balance_pair, callee_balance_pair] = [13, 14].map(|i| { + block.rws[step.rw_indices[i + usize::from(is_create2) + copy_rw_increase]] + .account_value_pair() + }); // dbg!(caller_balance_pair, callee_balance_pair, value); self.transfer.assign( region, @@ -391,7 +444,7 @@ impl ExecutionGadget for CreateGadget { region, offset, Value::known( - block.rws[step.rw_indices[21 + usize::from(is_create2)]] + block.rws[step.rw_indices[21 + usize::from(is_create2) + copy_rw_increase]] .call_context_value() .to_scalar() .unwrap(), From ea76327f13ce556ace865dcfe90d1ee4237882e5 Mon Sep 17 00:00:00 2001 From: Mason Liang Date: Thu, 15 Dec 2022 12:57:55 -0500 Subject: [PATCH 28/69] cleanup --- bus-mapping/src/evm/opcodes/create.rs | 3 --- zkevm-circuits/src/evm_circuit/execution.rs | 2 +- .../src/evm_circuit/execution/create.rs | 26 +------------------ 3 files changed, 2 insertions(+), 29 deletions(-) diff --git a/bus-mapping/src/evm/opcodes/create.rs b/bus-mapping/src/evm/opcodes/create.rs index ed6b2c9edd..726dc6ab19 100644 --- a/bus-mapping/src/evm/opcodes/create.rs +++ b/bus-mapping/src/evm/opcodes/create.rs @@ -211,10 +211,7 @@ fn handle_copy( offset: usize, length: usize, ) -> Result<(), Error> { - dbg!("asdfasdf"); - dbg!(offset, length, state.call_ctx()?.memory.0.len()); let initialization_bytes = state.call_ctx()?.memory.0[offset..offset + length].to_vec(); - dbg!("asdfaw3r12341"); let dst_id = NumberOrHash::Hash(H256(keccak256(&initialization_bytes))); let bytes: Vec<_> = Bytecode::from(initialization_bytes) .code diff --git a/zkevm-circuits/src/evm_circuit/execution.rs b/zkevm-circuits/src/evm_circuit/execution.rs index 117de0c094..f79865daba 100644 --- a/zkevm-circuits/src/evm_circuit/execution.rs +++ b/zkevm-circuits/src/evm_circuit/execution.rs @@ -1153,7 +1153,7 @@ impl ExecutionConfig { fn check_rw_lookup( assigned_stored_expressions: &[(String, F)], - step: &ExecStep, + _step: &ExecStep, block: &Block, ) { let mut assigned_rw_values = Vec::new(); diff --git a/zkevm-circuits/src/evm_circuit/execution/create.rs b/zkevm-circuits/src/evm_circuit/execution/create.rs index e4a609e98d..89aa78e03a 100644 --- a/zkevm-circuits/src/evm_circuit/execution/create.rs +++ b/zkevm-circuits/src/evm_circuit/execution/create.rs @@ -317,17 +317,10 @@ impl ExecutionGadget for CreateGadget { let tx_access_rw = block.rws[step.rw_indices[7 + usize::from(is_create2) + copy_rw_increase]]; - dbg!(tx_access_rw.clone()); let new_address = tx_access_rw.address().expect("asdfawefasdf"); - dbg!(new_address); - for (word, assignment) in [ - // (&self.initialization_code_start, initialization_code_start), - // (&self.initialization_code_length, initialization_code_length), - (&self.value, value), - (&self.salt, salt), - ] { + for (word, assignment) in [(&self.value, value), (&self.salt, salt)] { word.assign(region, offset, Some(assignment.to_le_bytes()))?; } let initialization_code_address = self.initialization_code.assign( @@ -346,7 +339,6 @@ impl ExecutionGadget for CreateGadget { self.tx_id .assign(region, offset, Value::known(tx.id.to_scalar().unwrap()))?; - dbg!(call.rw_counter_end_of_reversion, call.is_persistent); self.reversion_info.assign( region, offset, @@ -366,7 +358,6 @@ impl ExecutionGadget for CreateGadget { ), )?; - // dbg!(call.callee_address); self.caller_address.assign( region, offset, @@ -385,21 +376,11 @@ impl ExecutionGadget for CreateGadget { ), )?; - // - // let address_bytes = - // block.rws[step.rw_indices[2]].stack_value().to_le_bytes()[0..20].try_into(). - // unwrap(); self.new_address.assign( - // region, offset, - // Some(address_bytes) - // )?; - let [callee_rw_counter_end_of_reversion, callee_is_persistent] = [10, 11].map(|i| { block.rws[step.rw_indices[i + usize::from(is_create2) + copy_rw_increase]] .call_context_value() }); - // dbg!(callee_rw_counter_end_of_reversion, callee_is_persistent); - self.callee_reversion_info.assign( region, offset, @@ -414,7 +395,6 @@ impl ExecutionGadget for CreateGadget { block.rws[step.rw_indices[i + usize::from(is_create2) + copy_rw_increase]] .account_value_pair() }); - // dbg!(caller_balance_pair, callee_balance_pair, value); self.transfer.assign( region, offset, @@ -436,10 +416,6 @@ impl ExecutionGadget for CreateGadget { (step.gas_left - GasCost::CREATE.as_u64()).into(), )?; - // dbg!(block.rws[step.rw_indices[20 + usize::from(is_create2)]]); - // dbg!(block.rws[step.rw_indices[21 + usize::from(is_create2)]]); - // dbg!(block.rws[step.rw_indices[22 + usize::from(is_create2)]]); - // dbg!(block.rws[step.rw_indices[23 + usize::from(is_create2)]]); self.callee_is_success.assign( region, offset, From c262f5937bd62ab9c9ebb4de5161a9569a1bc361 Mon Sep 17 00:00:00 2001 From: Mason Liang Date: Thu, 15 Dec 2022 15:11:30 -0500 Subject: [PATCH 29/69] wip --- .../src/evm_circuit/execution/create.rs | 83 +++++++++---------- 1 file changed, 40 insertions(+), 43 deletions(-) diff --git a/zkevm-circuits/src/evm_circuit/execution/create.rs b/zkevm-circuits/src/evm_circuit/execution/create.rs index 89aa78e03a..90a08d1e4c 100644 --- a/zkevm-circuits/src/evm_circuit/execution/create.rs +++ b/zkevm-circuits/src/evm_circuit/execution/create.rs @@ -1,4 +1,3 @@ -use crate::evm_circuit::util::RandomLinearCombination; use crate::{ evm_circuit::{ execution::ExecutionGadget, @@ -6,11 +5,14 @@ use crate::{ step::ExecutionState, util::{ common_gadget::TransferGadget, - constraint_builder::{ConstraintBuilder, ReversionInfo}, + constraint_builder::{ + ConstraintBuilder, ReversionInfo, StepStateTransition, + Transition::{Any, Delta, To}, + }, from_bytes, math_gadget::ConstantDivisionGadget, memory_gadget::{MemoryAddressGadget, MemoryExpansionGadget}, - not, select, CachedRegion, Cell, Word, + not, select, CachedRegion, Cell, RandomLinearCombination, Word, }, witness::{Block, Call, ExecStep, Transaction}, }, @@ -29,8 +31,6 @@ pub(crate) struct CreateGadget { opcode: Cell, is_create2: Cell, - // initialization_code_start: Word, - // initialization_code_length: Word, value: Word, salt: Word, new_address: RandomLinearCombination, @@ -44,6 +44,7 @@ pub(crate) struct CreateGadget { nonce: Cell, callee_reversion_info: ReversionInfo, + callee_is_success: Cell, transfer: TransferGadget, @@ -52,31 +53,6 @@ pub(crate) struct CreateGadget { gas_left: ConstantDivisionGadget, - callee_is_success: Cell, - // - // // transfer value to new address - // transfer: TransferGadget, - // callee_reversion_info: ReversionInfo, - // - // // memory - // caller_memory_address: MemoryAddressGadget, - // memory_expansion: MemoryExpansionGadget, - // // new call context - // current_address: Cell, - // depth: Cell, - // gas: Word, - // callee_address: Word, - // value: Word, - // is_success: Cell, - // gas_is_u64: IsZeroGadget, - // - // // gas - // one_64th_gas: ConstantDivisionGadget, - // capped_callee_gas_left: MinMaxGadget, - - // errors: - // is_empty_nonce_and_balance: BatchedIsZeroGadget, - // is_empty_code_hash: IsEqualGadget, code_hash: Cell, } @@ -194,8 +170,9 @@ impl ExecutionGadget for CreateGadget { // (geth_step.gas.0 - geth_step.gas_cost.0 - memory_expansion_gas_cost) / 64; let gas_cost = GasCost::CREATE.expr() + memory_expansion.gas_cost(); - let gas_left = - ConstantDivisionGadget::construct(cb, cb.curr.state.gas_left.expr() - gas_cost, 64); + let gas_remaining = cb.curr.state.gas_left.expr() - gas_cost; + let gas_left = ConstantDivisionGadget::construct(cb, gas_remaining.clone(), 64); + let callee_gas_left = gas_remaining - gas_left.quotient(); for (field_tag, value) in [ ( CallContextFieldTag::ProgramCounter, @@ -236,17 +213,16 @@ impl ExecutionGadget for CreateGadget { cb.call_context_lookup(true.expr(), Some(callee_call_id.expr()), field_tag, value); } - // - // cb.require_step_state_transition(StepStateTransition { - // rw_counter: Delta(cb.rw_counter_offset.clone()), - // call_id: To(callee_call_id.expr()), - // is_root: To(false.expr()), - // is_create: To(true.expr()), - // code_hash: To(initialization_code_hash.expr()), - // gas_left: To(gas.callee_gas_left()), - // reversible_write_counter: To(2.expr()), - // ..StepStateTransition::new_context() - // }); + cb.require_step_state_transition(StepStateTransition { + rw_counter: Delta(cb.rw_counter_offset()), + call_id: To(callee_call_id.expr()), + is_root: To(false.expr()), + is_create: To(true.expr()), + code_hash: To(code_hash.expr()), + gas_left: To(callee_gas_left), + reversible_write_counter: To(3.expr()), + ..StepStateTransition::new_context() + }); Self { opcode, @@ -430,6 +406,27 @@ impl ExecutionGadget for CreateGadget { Ok(()) } } +// +// struct Eip150GasGadget { +// divide_by_64: ConstantDivisionGadget, +// } +// +// impl Eip150GasGadget { +// fn construct() { +// let gas_cost = GasCost::CREATE.expr() + memory_expansion.gas_cost(); +// let gas_left = +// ConstantDivisionGadget::construct(cb, +// cb.curr.state.gas_left.expr() - gas_cost, 64); +// +// } +// +// fn callee_gas_left(&self) -> Expression { +// +// } +// +// fn caller_gas_left(&self) -> Expression { +// +// } #[cfg(test)] mod test { From 8fcd1c047a629e7040e05007bc807e8dfff2a956 Mon Sep 17 00:00:00 2001 From: Mason Liang Date: Fri, 16 Dec 2022 23:19:17 -0500 Subject: [PATCH 30/69] convert to rlcs --- .../src/evm_circuit/execution/create.rs | 51 +++++++++---------- 1 file changed, 25 insertions(+), 26 deletions(-) diff --git a/zkevm-circuits/src/evm_circuit/execution/create.rs b/zkevm-circuits/src/evm_circuit/execution/create.rs index 90a08d1e4c..dfb4f5445c 100644 --- a/zkevm-circuits/src/evm_circuit/execution/create.rs +++ b/zkevm-circuits/src/evm_circuit/execution/create.rs @@ -1,7 +1,7 @@ use crate::{ evm_circuit::{ execution::ExecutionGadget, - param::{N_BYTES_ACCOUNT_ADDRESS, N_BYTES_GAS, N_BYTES_MEMORY_WORD_SIZE}, + param::{N_BYTES_ACCOUNT_ADDRESS, N_BYTES_GAS, N_BYTES_MEMORY_WORD_SIZE, N_BYTES_U64}, step::ExecutionState, util::{ common_gadget::TransferGadget, @@ -40,8 +40,8 @@ pub(crate) struct CreateGadget { reversion_info: ReversionInfo, was_warm: Cell, - caller_address: Cell, - nonce: Cell, + caller_address: RandomLinearCombination, + nonce: RandomLinearCombination, callee_reversion_info: ReversionInfo, callee_is_success: Cell, @@ -132,15 +132,21 @@ impl ExecutionGadget for CreateGadget { Some(&mut reversion_info), ); - let caller_address = cb.call_context(None, CallContextFieldTag::CalleeAddress); - let nonce = cb.query_cell(); + let caller_address = cb.query_rlc(); + cb.call_context_lookup( + 0.expr(), + None, + CallContextFieldTag::CalleeAddress, + from_bytes::expr(&caller_address.cells), + ); + + let nonce = cb.query_rlc(); cb.account_write( caller_address.expr(), AccountFieldTag::Nonce, - nonce.expr() + 1.expr(), - nonce.expr(), + from_bytes::expr(&nonce.cells) + 1.expr(), + from_bytes::expr(&nonce.cells), Some(&mut reversion_info), - // None, ); let mut callee_reversion_info = cb.reversion_info_write(Some(callee_call_id.expr())); @@ -309,7 +315,6 @@ impl ExecutionGadget for CreateGadget { let mut bytes = new_address.to_fixed_bytes(); bytes.reverse(); - self.new_address.assign(region, offset, Some(bytes))?; self.tx_id @@ -334,23 +339,17 @@ impl ExecutionGadget for CreateGadget { ), )?; - self.caller_address.assign( - region, - offset, - Value::known(call.callee_address.to_scalar().unwrap()), - )?; - - self.nonce.assign( - region, - offset, - Value::known( - block.rws[step.rw_indices[9 + usize::from(is_create2) + copy_rw_increase]] - .account_value_pair() - .1 - .to_scalar() - .unwrap(), - ), - )?; + let mut bytes = call.callee_address.to_fixed_bytes(); + bytes.reverse(); + self.caller_address.assign(region, offset, Some(bytes))?; + + let nonce_bytes = block.rws + [step.rw_indices[9 + usize::from(is_create2) + copy_rw_increase]] + .account_value_pair() + .1 + .low_u64() + .to_le_bytes(); + self.nonce.assign(region, offset, Some(nonce_bytes))?; let [callee_rw_counter_end_of_reversion, callee_is_persistent] = [10, 11].map(|i| { block.rws[step.rw_indices[i + usize::from(is_create2) + copy_rw_increase]] From dd190f5dc9eaf9afc671b4cd3b394dc64f84e346 Mon Sep 17 00:00:00 2001 From: Mason Liang Date: Sat, 17 Dec 2022 13:18:08 -0500 Subject: [PATCH 31/69] wip --- zkevm-circuits/src/evm_circuit/execution/create.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/zkevm-circuits/src/evm_circuit/execution/create.rs b/zkevm-circuits/src/evm_circuit/execution/create.rs index dfb4f5445c..2e67dc3b0c 100644 --- a/zkevm-circuits/src/evm_circuit/execution/create.rs +++ b/zkevm-circuits/src/evm_circuit/execution/create.rs @@ -142,7 +142,7 @@ impl ExecutionGadget for CreateGadget { let nonce = cb.query_rlc(); cb.account_write( - caller_address.expr(), + from_bytes::expr(&caller_address.cells), AccountFieldTag::Nonce, from_bytes::expr(&nonce.cells) + 1.expr(), from_bytes::expr(&nonce.cells), @@ -151,7 +151,7 @@ impl ExecutionGadget for CreateGadget { let mut callee_reversion_info = cb.reversion_info_write(Some(callee_call_id.expr())); cb.account_write( - new_address.expr(), + from_bytes::expr(&new_address.cells), AccountFieldTag::Nonce, 1.expr(), 0.expr(), @@ -160,8 +160,8 @@ impl ExecutionGadget for CreateGadget { let transfer = TransferGadget::construct( cb, - caller_address.expr(), - new_address.expr(), + from_bytes::expr(&caller_address.cells), + from_bytes::expr(&new_address.cells), value.clone(), &mut callee_reversion_info, ); @@ -209,8 +209,8 @@ impl ExecutionGadget for CreateGadget { callee_reversion_info.is_persistent(), ), (CallContextFieldTag::TxId, tx_id.expr()), - (CallContextFieldTag::CallerAddress, caller_address.expr()), - (CallContextFieldTag::CalleeAddress, new_address.expr()), + (CallContextFieldTag::CallerAddress, from_bytes::expr(&caller_address.cells),), + (CallContextFieldTag::CalleeAddress, from_bytes::expr(&new_address.cells),), ( CallContextFieldTag::RwCounterEndOfReversion, callee_reversion_info.rw_counter_end_of_reversion(), From 2745b50d056f1154c4df1b0b35062d32958c516d Mon Sep 17 00:00:00 2001 From: Mason Liang Date: Sun, 18 Dec 2022 21:13:00 -0500 Subject: [PATCH 32/69] wip --- .../src/circuit_input_builder/execution.rs | 4 +- bus-mapping/src/evm/opcodes/create.rs | 2 + .../src/evm_circuit/execution/create.rs | 198 ++++++++++++++++-- zkevm-circuits/src/evm_circuit/step.rs | 6 +- zkevm-circuits/src/witness/step.rs | 3 +- 5 files changed, 189 insertions(+), 24 deletions(-) diff --git a/bus-mapping/src/circuit_input_builder/execution.rs b/bus-mapping/src/circuit_input_builder/execution.rs index 875e5b936f..b12ac0f4e2 100644 --- a/bus-mapping/src/circuit_input_builder/execution.rs +++ b/bus-mapping/src/circuit_input_builder/execution.rs @@ -245,14 +245,14 @@ impl CopyEvent { // increase in rw counter from the start of the copy event to step index fn rw_counter_increase(&self, step_index: usize) -> u64 { let source_rw_increase = match self.src_type { - CopyDataType::Bytecode | CopyDataType::TxCalldata => 0, + CopyDataType::Bytecode | CopyDataType::TxCalldata | CopyDataType::RlcAcc => 0, CopyDataType::Memory => std::cmp::min( u64::try_from(step_index + 1).unwrap() / 2, self.src_addr_end .checked_sub(self.src_addr) .unwrap_or_default(), ), - CopyDataType::RlcAcc | CopyDataType::TxLog => unreachable!(), + CopyDataType::TxLog => unreachable!(), }; let destination_rw_increase = match self.dst_type { CopyDataType::RlcAcc | CopyDataType::Bytecode => 0, diff --git a/bus-mapping/src/evm/opcodes/create.rs b/bus-mapping/src/evm/opcodes/create.rs index 726dc6ab19..e073616dcb 100644 --- a/bus-mapping/src/evm/opcodes/create.rs +++ b/bus-mapping/src/evm/opcodes/create.rs @@ -200,6 +200,8 @@ impl Opcode for DummyCreate { state.call_context_write(&mut exec_step, call.call_id, field, value); } + state.block.sha3_inputs.push(vec![0, 0]); + Ok(vec![exec_step]) } } diff --git a/zkevm-circuits/src/evm_circuit/execution/create.rs b/zkevm-circuits/src/evm_circuit/execution/create.rs index 2e67dc3b0c..0b8223498d 100644 --- a/zkevm-circuits/src/evm_circuit/execution/create.rs +++ b/zkevm-circuits/src/evm_circuit/execution/create.rs @@ -12,7 +12,7 @@ use crate::{ from_bytes, math_gadget::ConstantDivisionGadget, memory_gadget::{MemoryAddressGadget, MemoryExpansionGadget}, - not, select, CachedRegion, Cell, RandomLinearCombination, Word, + not, select, CachedRegion, Cell, RandomLinearCombination, Word, rlc, }, witness::{Block, Call, ExecStep, Transaction}, }, @@ -24,6 +24,7 @@ use eth_types::{evm_types::GasCost, Field, ToLittleEndian, ToScalar, U256}; use ethers_core::utils::keccak256; use halo2_proofs::{circuit::Value, plonk::Error}; use keccak256::EMPTY_HASH_LE; +use std::iter::once; /// Gadget for CREATE and CREATE2 opcodes #[derive(Clone, Debug)] @@ -54,6 +55,10 @@ pub(crate) struct CreateGadget { gas_left: ConstantDivisionGadget, code_hash: Cell, + + keccak_input: Cell, + keccak_input_length: Cell, + keccak_output: Word, } impl ExecutionGadget for CreateGadget { @@ -209,8 +214,14 @@ impl ExecutionGadget for CreateGadget { callee_reversion_info.is_persistent(), ), (CallContextFieldTag::TxId, tx_id.expr()), - (CallContextFieldTag::CallerAddress, from_bytes::expr(&caller_address.cells),), - (CallContextFieldTag::CalleeAddress, from_bytes::expr(&new_address.cells),), + ( + CallContextFieldTag::CallerAddress, + from_bytes::expr(&caller_address.cells), + ), + ( + CallContextFieldTag::CalleeAddress, + from_bytes::expr(&new_address.cells), + ), ( CallContextFieldTag::RwCounterEndOfReversion, callee_reversion_info.rw_counter_end_of_reversion(), @@ -225,11 +236,40 @@ impl ExecutionGadget for CreateGadget { is_root: To(false.expr()), is_create: To(true.expr()), code_hash: To(code_hash.expr()), - gas_left: To(callee_gas_left), + // gas_left: To(callee_gas_left), + gas_left: Any, reversible_write_counter: To(3.expr()), ..StepStateTransition::new_context() }); + let keccak_input = cb.query_cell(); + let keccak_input_length = cb.query_cell(); + cb.condition(is_create2.expr(), |cb| { + // TODO: some comments here explaining what's going on.... + let randomness_raised_to_16 = cb.power_of_randomness()[15].clone(); + let randomness_raised_to_32 = randomness_raised_to_16.clone().square(); + let randomness_raised_to_64 = randomness_raised_to_32.clone().square(); + let randomness_raised_to_84 = + randomness_raised_to_64.clone() * cb.power_of_randomness()[19].clone(); + // cb.require_equal( + // "aw3rw3r", + // keccak_input.expr(), + // 0xff.expr() * randomness_raised_to_84 + // + caller_address.expr() * randomness_raised_to_64 + // + salt.expr() * randomness_raised_to_32 + // + code_hash.expr(), + // ); + cb.require_equal("23452345", keccak_input_length.expr(), (1 + 20 + 32 + 32).expr()); + }); + // cb.condition(not::expr(is_create2.expr()), |cb| {()}); + + let keccak_output = cb.query_word(); + // cb.keccak_table_lookup( + // keccak_input.expr(), + // keccak_input_length.expr(), + // keccak_output.expr(), + // ); + Self { opcode, is_create2, @@ -248,6 +288,9 @@ impl ExecutionGadget for CreateGadget { gas_left, callee_is_success, code_hash, + keccak_output, + keccak_input, + keccak_input_length, } } @@ -288,14 +331,9 @@ impl ExecutionGadget for CreateGadget { .collect(); let mut code_hash = keccak256(&values); code_hash.reverse(); - self.code_hash.assign( - region, - offset, - Value::known(RandomLinearCombination::random_linear_combine( - code_hash, - block.randomness, - )), - )?; + let code_hash_rlc = + RandomLinearCombination::random_linear_combine(code_hash.clone(), block.randomness); + self.code_hash.assign(region, offset, Value::known(code_hash_rlc))?; let tx_access_rw = block.rws[step.rw_indices[7 + usize::from(is_create2) + copy_rw_increase]]; @@ -339,9 +377,10 @@ impl ExecutionGadget for CreateGadget { ), )?; - let mut bytes = call.callee_address.to_fixed_bytes(); - bytes.reverse(); - self.caller_address.assign(region, offset, Some(bytes))?; + let mut caller_address_bytes = call.callee_address.to_fixed_bytes(); + caller_address_bytes.reverse(); + self.caller_address + .assign(region, offset, Some(caller_address_bytes.clone()))?; let nonce_bytes = block.rws [step.rw_indices[9 + usize::from(is_create2) + copy_rw_increase]] @@ -402,6 +441,34 @@ impl ExecutionGadget for CreateGadget { ), )?; + if is_create2 { + self.keccak_input.assign( + region, + offset, + Value::known(rlc::value( + once(&0xffu8) + .chain(&caller_address_bytes) + .chain(salt.to_le_bytes().iter()) + .chain(&code_hash), + block.randomness, + )), + )?; + self.keccak_input_length.assign( + region, + offset, + Value::known((1 + 20 + 32 + 32).into()), + )?; + } else { + self.keccak_input.assign(region, offset, Value::known(0.into()))?; + self.keccak_input_length + .assign(region, offset, Value::known(2.into()))?; + } + + let mut keccak_output = keccak256(&[0, 0]); + keccak_output.reverse(); + self.keccak_output + .assign(region, offset, Some(keccak_output))?; + Ok(()) } } @@ -486,11 +553,12 @@ mod test { PUSH1(0) MSTORE + PUSH1(45) // salt PUSH1(initializer.len()) // size PUSH1(32 - initializer.len()) // offset PUSH1(0) // value - CREATE + CREATE2 }; let caller = Account { @@ -577,4 +645,102 @@ mod test { assert_eq!(run_test_circuits(test_context, None), Ok(()),); } + + #[test] + fn create() { + // Test the case where the initialization call is successful, but the CREATE + // call is reverted. + let initializer = callee_bytecode(true, 0, 10).code(); + + let root_code = bytecode! { + PUSH32(Word::from_big_endian(&initializer)) + PUSH1(0) + MSTORE + + PUSH1(initializer.len()) // size + PUSH1(32 - initializer.len()) // offset + PUSH1(0) // value + + CREATE + PUSH1(0) + PUSH1(0) + REVERT + }; + + let caller = Account { + address: CALLER_ADDRESS, + code: root_code.into(), + nonce: Word::one(), + balance: eth(10), + ..Default::default() + }; + + let test_context = TestContext::<2, 1>::new( + None, + |accs| { + accs[0] + .address(address!("0x000000000000000000000000000000000000cafe")) + .balance(eth(10)); + accs[1].account(&caller); + }, + |mut txs, accs| { + txs[0] + .from(accs[0].address) + .to(accs[1].address) + .gas(100000u64.into()); + }, + |block, _| block, + ) + .unwrap(); + + assert_eq!(run_test_circuits(test_context, None), Ok(()),); + } + + #[test] + fn create2() { + // Test the case where the initialization call is successful, but the CREATE + // call is reverted. + let initializer = callee_bytecode(true, 0, 10).code(); + + let root_code = bytecode! { + PUSH32(Word::from_big_endian(&initializer)) + PUSH1(0) + MSTORE + + PUSH1(initializer.len()) // size + PUSH1(32 - initializer.len()) // offset + PUSH1(0) // value + PUSH1(56) // salt + + CREATE2 + }; + + let caller = Account { + address: CALLER_ADDRESS, + code: root_code.into(), + nonce: Word::one(), + balance: eth(10), + ..Default::default() + }; + + let test_context = TestContext::<2, 1>::new( + None, + |accs| { + accs[0] + .address(address!("0x000000000000000000000000000000000000cafe")) + .balance(eth(10)); + accs[1].account(&caller); + }, + |mut txs, accs| { + txs[0] + .from(accs[0].address) + .to(accs[1].address) + .gas(100000u64.into()); + }, + |block, _| block, + ) + .unwrap(); + + assert_eq!(run_test_circuits(test_context, None), Ok(()),); + } } diff --git a/zkevm-circuits/src/evm_circuit/step.rs b/zkevm-circuits/src/evm_circuit/step.rs index 25b86b9793..57d3e97bd3 100644 --- a/zkevm-circuits/src/evm_circuit/step.rs +++ b/zkevm-circuits/src/evm_circuit/step.rs @@ -79,10 +79,9 @@ pub enum ExecutionState { DUP, // DUP1, DUP2, ..., DUP16 SWAP, // SWAP1, SWAP2, ..., SWAP16 LOG, // LOG0, LOG1, ..., LOG4 - CREATE, + CREATE, // CREATE, CREATE2 CALL_OP, // CALL, CALLCODE, DELEGATECALL, STATICCALL RETURN_REVERT, // RETURN, REVERT - CREATE2, SELFDESTRUCT, // Error cases ErrorInvalidOpcode, @@ -301,7 +300,7 @@ impl ExecutionState { OpcodeId::LOG3, OpcodeId::LOG4, ], - Self::CREATE => vec![OpcodeId::CREATE], + Self::CREATE => vec![OpcodeId::CREATE, OpcodeId::CREATE2], Self::CALL_OP => vec![ OpcodeId::CALL, OpcodeId::CALLCODE, @@ -309,7 +308,6 @@ impl ExecutionState { OpcodeId::STATICCALL, ], Self::RETURN_REVERT => vec![OpcodeId::RETURN, OpcodeId::REVERT], - Self::CREATE2 => vec![OpcodeId::CREATE2], Self::SELFDESTRUCT => vec![OpcodeId::SELFDESTRUCT], _ => vec![], } diff --git a/zkevm-circuits/src/witness/step.rs b/zkevm-circuits/src/witness/step.rs index 9d59a9f5ce..ba898a6dd1 100644 --- a/zkevm-circuits/src/witness/step.rs +++ b/zkevm-circuits/src/witness/step.rs @@ -181,13 +181,12 @@ impl From<&circuit_input_builder::ExecStep> for ExecutionState { OpcodeId::RETURN | OpcodeId::REVERT => ExecutionState::RETURN_REVERT, OpcodeId::RETURNDATASIZE => ExecutionState::RETURNDATASIZE, OpcodeId::RETURNDATACOPY => ExecutionState::RETURNDATACOPY, + OpcodeId::CREATE | OpcodeId::CREATE2 => ExecutionState::CREATE, // dummy ops OpcodeId::BALANCE => dummy!(ExecutionState::BALANCE), OpcodeId::SAR => dummy!(ExecutionState::SAR), OpcodeId::EXTCODESIZE => dummy!(ExecutionState::EXTCODESIZE), OpcodeId::EXTCODECOPY => dummy!(ExecutionState::EXTCODECOPY), - OpcodeId::CREATE => dummy!(ExecutionState::CREATE), - OpcodeId::CREATE2 => dummy!(ExecutionState::CREATE2), OpcodeId::SELFDESTRUCT => dummy!(ExecutionState::SELFDESTRUCT), _ => unimplemented!("unimplemented opcode {:?}", op), } From b36697ea9035063170a6c5442e340860bf601b5b Mon Sep 17 00:00:00 2001 From: Mason Liang Date: Mon, 19 Dec 2022 00:16:27 -0500 Subject: [PATCH 33/69] Fix gas cost --- .../src/evm_circuit/execution/create.rs | 120 ++++++++++++++---- zkevm-circuits/src/evm_circuit/step.rs | 14 +- zkevm-circuits/src/witness/step.rs | 3 +- 3 files changed, 99 insertions(+), 38 deletions(-) diff --git a/zkevm-circuits/src/evm_circuit/execution/create.rs b/zkevm-circuits/src/evm_circuit/execution/create.rs index 2e67dc3b0c..789479041f 100644 --- a/zkevm-circuits/src/evm_circuit/execution/create.rs +++ b/zkevm-circuits/src/evm_circuit/execution/create.rs @@ -1,7 +1,10 @@ use crate::{ evm_circuit::{ execution::ExecutionGadget, - param::{N_BYTES_ACCOUNT_ADDRESS, N_BYTES_GAS, N_BYTES_MEMORY_WORD_SIZE, N_BYTES_U64}, + param::{ + N_BYTES_ACCOUNT_ADDRESS, N_BYTES_GAS, N_BYTES_MEMORY_ADDRESS, N_BYTES_MEMORY_WORD_SIZE, + N_BYTES_U64, + }, step::ExecutionState, util::{ common_gadget::TransferGadget, @@ -49,6 +52,7 @@ pub(crate) struct CreateGadget { transfer: TransferGadget, initialization_code: MemoryAddressGadget, + initialization_code_word_size: ConstantDivisionGadget, memory_expansion: MemoryExpansionGadget, gas_left: ConstantDivisionGadget, @@ -83,7 +87,7 @@ impl ExecutionGadget for CreateGadget { cb.stack_pop(value.expr()); let initialization_code = MemoryAddressGadget::construct_2(cb); - cb.stack_pop(initialization_code.offset()); + cb.stack_pop(initialization_code.offset()); // are these rlc or not? cb.stack_pop(initialization_code.length()); let salt = cb.condition(is_create2.expr(), |cb| { @@ -175,7 +179,13 @@ impl ExecutionGadget for CreateGadget { // let caller_gas_left = // (geth_step.gas.0 - geth_step.gas_cost.0 - memory_expansion_gas_cost) / 64; - let gas_cost = GasCost::CREATE.expr() + memory_expansion.gas_cost(); + let initialization_code_word_size = + ConstantDivisionGadget::construct(cb, initialization_code.length() + 31.expr(), 32); + let keccak_gas_cost = GasCost::COPY_SHA3.expr() + * is_create2.expr() + * initialization_code_word_size.quotient(); + + let gas_cost = GasCost::CREATE.expr() + memory_expansion.gas_cost() + keccak_gas_cost; let gas_remaining = cb.curr.state.gas_left.expr() - gas_cost; let gas_left = ConstantDivisionGadget::construct(cb, gas_remaining.clone(), 64); let callee_gas_left = gas_remaining - gas_left.quotient(); @@ -209,8 +219,14 @@ impl ExecutionGadget for CreateGadget { callee_reversion_info.is_persistent(), ), (CallContextFieldTag::TxId, tx_id.expr()), - (CallContextFieldTag::CallerAddress, from_bytes::expr(&caller_address.cells),), - (CallContextFieldTag::CalleeAddress, from_bytes::expr(&new_address.cells),), + ( + CallContextFieldTag::CallerAddress, + from_bytes::expr(&caller_address.cells), + ), + ( + CallContextFieldTag::CalleeAddress, + from_bytes::expr(&new_address.cells), + ), ( CallContextFieldTag::RwCounterEndOfReversion, callee_reversion_info.rw_counter_end_of_reversion(), @@ -248,6 +264,7 @@ impl ExecutionGadget for CreateGadget { gas_left, callee_is_success, code_hash, + initialization_code_word_size, } } @@ -378,17 +395,29 @@ impl ExecutionGadget for CreateGadget { value, )?; - self.memory_expansion.assign( + let (_next_memory_word_size, memory_expansion_gas_cost) = self.memory_expansion.assign( region, offset, step.memory_word_size(), [initialization_code_address], )?; + let (initialization_code_word_size, _remainder) = + self.initialization_code_word_size.assign( + region, + offset, + (31u64 + initialization_code_length.as_u64()).into(), + )?; + self.gas_left.assign( region, offset, - (step.gas_left - GasCost::CREATE.as_u64()).into(), + (step.gas_left + - GasCost::CREATE.as_u64() + - u64::try_from(memory_expansion_gas_cost).unwrap() + - u64::try_from(initialization_code_word_size).unwrap() + * GasCost::COPY_SHA3.as_u64()) + .into(), )?; self.callee_is_success.assign( @@ -405,27 +434,6 @@ impl ExecutionGadget for CreateGadget { Ok(()) } } -// -// struct Eip150GasGadget { -// divide_by_64: ConstantDivisionGadget, -// } -// -// impl Eip150GasGadget { -// fn construct() { -// let gas_cost = GasCost::CREATE.expr() + memory_expansion.gas_cost(); -// let gas_left = -// ConstantDivisionGadget::construct(cb, -// cb.curr.state.gas_left.expr() - gas_cost, 64); -// -// } -// -// fn callee_gas_left(&self) -> Expression { -// -// } -// -// fn caller_gas_left(&self) -> Expression { -// -// } #[cfg(test)] mod test { @@ -528,6 +536,62 @@ mod test { } } + #[test] + fn test_create2() { + let test_parameters = [(0, 0), (0, 10), (300, 20), (1000, 0)]; + for ((offset, length), is_return) in test_parameters.iter().cartesian_product(&[true]) + // FIX MEEEEEE there's an issue when the init call reverts. + { + let initializer = callee_bytecode(*is_return, *offset, *length).code(); + + let root_code = bytecode! { + PUSH32(Word::from_big_endian(&initializer)) + PUSH1(0) + MSTORE + + PUSH1(34) // salt + PUSH1(initializer.len()) // size + PUSH1(32 - initializer.len()) // offset + PUSH1(12) // value + + CREATE2 + }; + + let caller = Account { + address: CALLER_ADDRESS, + code: root_code.into(), + nonce: Word::one(), + balance: eth(10), + ..Default::default() + }; + + let test_context = TestContext::<2, 1>::new( + None, + |accs| { + accs[0] + .address(address!("0x000000000000000000000000000000000000cafe")) + .balance(eth(10)); + accs[1].account(&caller); + }, + |mut txs, accs| { + txs[0] + .from(accs[0].address) + .to(accs[1].address) + .gas(100000u64.into()); + }, + |block, _| block, + ) + .unwrap(); + + assert_eq!( + run_test_circuits(test_context, None), + Ok(()), + "(offset, length, is_return) = {:?}", + (*offset, *length, *is_return), + ); + } + } + #[test] fn mason() { // Test the case where the initialization call is successful, but the CREATE diff --git a/zkevm-circuits/src/evm_circuit/step.rs b/zkevm-circuits/src/evm_circuit/step.rs index 25b86b9793..f2c73c7490 100644 --- a/zkevm-circuits/src/evm_circuit/step.rs +++ b/zkevm-circuits/src/evm_circuit/step.rs @@ -75,14 +75,13 @@ pub enum ExecutionState { MSIZE, GAS, JUMPDEST, - PUSH, // PUSH1, PUSH2, ..., PUSH32 - DUP, // DUP1, DUP2, ..., DUP16 - SWAP, // SWAP1, SWAP2, ..., SWAP16 - LOG, // LOG0, LOG1, ..., LOG4 - CREATE, + PUSH, // PUSH1, PUSH2, ..., PUSH32 + DUP, // DUP1, DUP2, ..., DUP16 + SWAP, // SWAP1, SWAP2, ..., SWAP16 + LOG, // LOG0, LOG1, ..., LOG4 + CREATE, // CREATE, CREATE2 CALL_OP, // CALL, CALLCODE, DELEGATECALL, STATICCALL RETURN_REVERT, // RETURN, REVERT - CREATE2, SELFDESTRUCT, // Error cases ErrorInvalidOpcode, @@ -301,7 +300,7 @@ impl ExecutionState { OpcodeId::LOG3, OpcodeId::LOG4, ], - Self::CREATE => vec![OpcodeId::CREATE], + Self::CREATE => vec![OpcodeId::CREATE, OpcodeId::CREATE2], Self::CALL_OP => vec![ OpcodeId::CALL, OpcodeId::CALLCODE, @@ -309,7 +308,6 @@ impl ExecutionState { OpcodeId::STATICCALL, ], Self::RETURN_REVERT => vec![OpcodeId::RETURN, OpcodeId::REVERT], - Self::CREATE2 => vec![OpcodeId::CREATE2], Self::SELFDESTRUCT => vec![OpcodeId::SELFDESTRUCT], _ => vec![], } diff --git a/zkevm-circuits/src/witness/step.rs b/zkevm-circuits/src/witness/step.rs index 9d59a9f5ce..ba898a6dd1 100644 --- a/zkevm-circuits/src/witness/step.rs +++ b/zkevm-circuits/src/witness/step.rs @@ -181,13 +181,12 @@ impl From<&circuit_input_builder::ExecStep> for ExecutionState { OpcodeId::RETURN | OpcodeId::REVERT => ExecutionState::RETURN_REVERT, OpcodeId::RETURNDATASIZE => ExecutionState::RETURNDATASIZE, OpcodeId::RETURNDATACOPY => ExecutionState::RETURNDATACOPY, + OpcodeId::CREATE | OpcodeId::CREATE2 => ExecutionState::CREATE, // dummy ops OpcodeId::BALANCE => dummy!(ExecutionState::BALANCE), OpcodeId::SAR => dummy!(ExecutionState::SAR), OpcodeId::EXTCODESIZE => dummy!(ExecutionState::EXTCODESIZE), OpcodeId::EXTCODECOPY => dummy!(ExecutionState::EXTCODECOPY), - OpcodeId::CREATE => dummy!(ExecutionState::CREATE), - OpcodeId::CREATE2 => dummy!(ExecutionState::CREATE2), OpcodeId::SELFDESTRUCT => dummy!(ExecutionState::SELFDESTRUCT), _ => unimplemented!("unimplemented opcode {:?}", op), } From e80f90d5ea3a61bafdca2a3f849c2ec1b7755825 Mon Sep 17 00:00:00 2001 From: Mason Liang Date: Mon, 19 Dec 2022 11:21:09 -0500 Subject: [PATCH 34/69] wip --- .../src/evm_circuit/execution/create.rs | 46 +++++++++++-------- 1 file changed, 28 insertions(+), 18 deletions(-) diff --git a/zkevm-circuits/src/evm_circuit/execution/create.rs b/zkevm-circuits/src/evm_circuit/execution/create.rs index 4f3bf456f2..264b365a23 100644 --- a/zkevm-circuits/src/evm_circuit/execution/create.rs +++ b/zkevm-circuits/src/evm_circuit/execution/create.rs @@ -15,7 +15,7 @@ use crate::{ from_bytes, math_gadget::ConstantDivisionGadget, memory_gadget::{MemoryAddressGadget, MemoryExpansionGadget}, - not, select, CachedRegion, Cell, RandomLinearCombination, Word, rlc, + not, rlc, select, CachedRegion, Cell, RandomLinearCombination, Word, }, witness::{Block, Call, ExecStep, Transaction}, }, @@ -23,7 +23,7 @@ use crate::{ util::Expr, }; use bus_mapping::{circuit_input_builder::CopyDataType, evm::OpcodeId}; -use eth_types::{evm_types::GasCost, Field, ToLittleEndian, ToScalar, U256}; +use eth_types::{evm_types::GasCost, Field, ToBigEndian, ToLittleEndian, ToScalar, U256}; use ethers_core::utils::keccak256; use halo2_proofs::{circuit::Value, plonk::Error}; use keccak256::EMPTY_HASH_LE; @@ -256,20 +256,25 @@ impl ExecutionGadget for CreateGadget { let keccak_input_length = cb.query_cell(); cb.condition(is_create2.expr(), |cb| { // TODO: some comments here explaining what's going on.... + // is the power of randomness in reverse order??? that seems impossible let randomness_raised_to_16 = cb.power_of_randomness()[15].clone(); let randomness_raised_to_32 = randomness_raised_to_16.clone().square(); let randomness_raised_to_64 = randomness_raised_to_32.clone().square(); let randomness_raised_to_84 = randomness_raised_to_64.clone() * cb.power_of_randomness()[19].clone(); - // cb.require_equal( - // "aw3rw3r", - // keccak_input.expr(), - // 0xff.expr() * randomness_raised_to_84 - // + caller_address.expr() * randomness_raised_to_64 - // + salt.expr() * randomness_raised_to_32 - // + code_hash.expr(), - // ); - cb.require_equal("23452345", keccak_input_length.expr(), (1 + 20 + 32 + 32).expr()); + cb.require_equal( + "aw3rw3r", + keccak_input.expr(), + 0xff.expr() * randomness_raised_to_84 // + // + caller_address.expr() * randomness_raised_to_64 + // + salt.expr() * randomness_raised_to_32 + // + code_hash.expr(), + ); + cb.require_equal( + "23452345", + keccak_input_length.expr(), + (1 + 20 + 32 + 32).expr(), + ); }); // cb.condition(not::expr(is_create2.expr()), |cb| {()}); @@ -344,7 +349,8 @@ impl ExecutionGadget for CreateGadget { code_hash.reverse(); let code_hash_rlc = RandomLinearCombination::random_linear_combine(code_hash.clone(), block.randomness); - self.code_hash.assign(region, offset, Value::known(code_hash_rlc))?; + self.code_hash + .assign(region, offset, Value::known(code_hash_rlc))?; let tx_access_rw = block.rws[step.rw_indices[7 + usize::from(is_create2) + copy_rw_increase]]; @@ -470,9 +476,13 @@ impl ExecutionGadget for CreateGadget { offset, Value::known(rlc::value( once(&0xffu8) - .chain(&caller_address_bytes) - .chain(salt.to_le_bytes().iter()) - .chain(&code_hash), + .chain(&[0u8; 20]) + .chain(&[0u8; 32]) + .chain(&[0u8; 32]) + .rev(), + // .chain(&caller_address_bytes) + // .chain(salt.to_be_bytes().iter()) + // .chain(&code_hash), block.randomness, )), )?; @@ -482,7 +492,8 @@ impl ExecutionGadget for CreateGadget { Value::known((1 + 20 + 32 + 32).into()), )?; } else { - self.keccak_input.assign(region, offset, Value::known(0.into()))?; + self.keccak_input + .assign(region, offset, Value::known(0.into()))?; self.keccak_input_length .assign(region, offset, Value::known(2.into()))?; } @@ -601,8 +612,7 @@ mod test { #[test] fn test_create2() { let test_parameters = [(0, 0), (0, 10), (300, 20), (1000, 0)]; - for ((offset, length), is_return) in test_parameters.iter().cartesian_product(&[true]) - { + for ((offset, length), is_return) in test_parameters.iter().cartesian_product(&[true]) { let initializer = callee_bytecode(*is_return, *offset, *length).code(); let root_code = bytecode! { From 75b4603bb88002f73d1ef757d6be59e653e6adf8 Mon Sep 17 00:00:00 2001 From: Mason Liang Date: Mon, 19 Dec 2022 11:36:54 -0500 Subject: [PATCH 35/69] wip --- zkevm-circuits/src/evm_circuit/execution/create.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/zkevm-circuits/src/evm_circuit/execution/create.rs b/zkevm-circuits/src/evm_circuit/execution/create.rs index 264b365a23..8bcfec6181 100644 --- a/zkevm-circuits/src/evm_circuit/execution/create.rs +++ b/zkevm-circuits/src/evm_circuit/execution/create.rs @@ -266,8 +266,8 @@ impl ExecutionGadget for CreateGadget { "aw3rw3r", keccak_input.expr(), 0xff.expr() * randomness_raised_to_84 // - // + caller_address.expr() * randomness_raised_to_64 - // + salt.expr() * randomness_raised_to_32 + + caller_address.expr() * randomness_raised_to_64 + + salt.expr() * randomness_raised_to_32 // + code_hash.expr(), ); cb.require_equal( @@ -476,11 +476,11 @@ impl ExecutionGadget for CreateGadget { offset, Value::known(rlc::value( once(&0xffu8) - .chain(&[0u8; 20]) - .chain(&[0u8; 32]) + .chain(&caller_address_bytes) + .chain(salt.to_be_bytes().iter()) .chain(&[0u8; 32]) .rev(), - // .chain(&caller_address_bytes) + // // .chain(salt.to_be_bytes().iter()) // .chain(&code_hash), block.randomness, From f1bcf9394b6bc7dd2fe15743cc785eb36c8ebc0c Mon Sep 17 00:00:00 2001 From: Mason Liang Date: Mon, 19 Dec 2022 13:41:57 -0500 Subject: [PATCH 36/69] fix endianess --- .../src/evm_circuit/execution/create.rs | 27 ++++++++++--------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/zkevm-circuits/src/evm_circuit/execution/create.rs b/zkevm-circuits/src/evm_circuit/execution/create.rs index 8bcfec6181..d3e22ff120 100644 --- a/zkevm-circuits/src/evm_circuit/execution/create.rs +++ b/zkevm-circuits/src/evm_circuit/execution/create.rs @@ -268,7 +268,7 @@ impl ExecutionGadget for CreateGadget { 0xff.expr() * randomness_raised_to_84 // + caller_address.expr() * randomness_raised_to_64 + salt.expr() * randomness_raised_to_32 - // + code_hash.expr(), + + code_hash.expr(), ); cb.require_equal( "23452345", @@ -476,13 +476,11 @@ impl ExecutionGadget for CreateGadget { offset, Value::known(rlc::value( once(&0xffu8) - .chain(&caller_address_bytes) + .chain(&call.callee_address.to_fixed_bytes()) // also don't need to be reversed.... .chain(salt.to_be_bytes().iter()) - .chain(&[0u8; 32]) + .chain(&keccak256(&values)) // don't need to reverse here??? .rev(), - // - // .chain(salt.to_be_bytes().iter()) - // .chain(&code_hash), + block.randomness, )), )?; @@ -514,11 +512,16 @@ mod test { address, bytecode, evm_types::OpcodeId, geth_types::Account, Address, Bytecode, ToWord, Word, }; + use lazy_static::lazy_static; use itertools::Itertools; use mock::{eth, TestContext}; const CALLEE_ADDRESS: Address = Address::repeat_byte(0xff); - const CALLER_ADDRESS: Address = Address::repeat_byte(0x34); + lazy_static! { + static ref CALLER_ADDRESS: Address = + address!("0xaabbccddee000000000000000000000000000000"); + } + fn callee_bytecode(is_return: bool, offset: u64, length: u64) -> Bytecode { let memory_bytes = [0x60; 10]; @@ -575,7 +578,7 @@ mod test { }; let caller = Account { - address: CALLER_ADDRESS, + address: *CALLER_ADDRESS, code: root_code.into(), nonce: Word::one(), balance: eth(10), @@ -629,7 +632,7 @@ mod test { }; let caller = Account { - address: CALLER_ADDRESS, + address: *CALLER_ADDRESS, code: root_code.into(), nonce: Word::one(), balance: eth(10), @@ -685,7 +688,7 @@ mod test { }; let caller = Account { - address: CALLER_ADDRESS, + address: *CALLER_ADDRESS, code: root_code.into(), nonce: Word::one(), balance: eth(10), @@ -735,7 +738,7 @@ mod test { }; let caller = Account { - address: CALLER_ADDRESS, + address: *CALLER_ADDRESS, code: root_code.into(), nonce: Word::one(), balance: eth(10), @@ -783,7 +786,7 @@ mod test { }; let caller = Account { - address: CALLER_ADDRESS, + address: *CALLER_ADDRESS, code: root_code.into(), nonce: Word::one(), balance: eth(10), From 905a2a33c3c13ef30e17cb4ce7ec71faa4d309cf Mon Sep 17 00:00:00 2001 From: Mason Liang Date: Mon, 19 Dec 2022 14:57:59 -0500 Subject: [PATCH 37/69] Add constraint between hash and address --- bus-mapping/src/evm/opcodes/create.rs | 45 +++++++++++++++---- .../src/evm_circuit/execution/create.rs | 39 +++++++++++----- 2 files changed, 64 insertions(+), 20 deletions(-) diff --git a/bus-mapping/src/evm/opcodes/create.rs b/bus-mapping/src/evm/opcodes/create.rs index e073616dcb..62d7604bc1 100644 --- a/bus-mapping/src/evm/opcodes/create.rs +++ b/bus-mapping/src/evm/opcodes/create.rs @@ -7,9 +7,11 @@ use crate::operation::{ }; use crate::Error; use eth_types::{ - evm_types::gas_utils::memory_expansion_gas_cost, Bytecode, GethExecStep, ToWord, Word, H256, + evm_types::gas_utils::memory_expansion_gas_cost, Bytecode, GethExecStep, ToBigEndian, ToWord, + Word, H160, H256, }; -use ethers_core::utils::keccak256; +use ethers_core::utils::{get_create2_address, keccak256}; +use keccak256::EMPTY_HASH_LE; #[derive(Debug, Copy, Clone)] pub struct DummyCreate; @@ -62,8 +64,10 @@ impl Opcode for DummyCreate { }, )?; + let mut initialization_code = vec![]; if length > 0 { - handle_copy(state, &mut exec_step, state.call()?.call_id, offset, length)?; + initialization_code = + handle_copy(state, &mut exec_step, state.call()?.call_id, offset, length)?; } // Quote from [EIP-2929](https://eips.ethereum.org/EIPS/eip-2929) @@ -200,7 +204,32 @@ impl Opcode for DummyCreate { state.call_context_write(&mut exec_step, call.call_id, field, value); } - state.block.sha3_inputs.push(vec![0, 0]); + let keccak_input = if IS_CREATE2 { + let salt = geth_step.stack.nth_last(3)?; + dbg!(salt); + assert_eq!( + address, + get_create2_address( + current_call.address, + salt.to_be_bytes().to_vec(), + initialization_code.clone() + ) + ); + std::iter::once(0xffu8) + .chain(current_call.address.to_fixed_bytes()) // also don't need to be reversed.... + .chain(salt.to_be_bytes()) + .chain(keccak256(&initialization_code)) + .collect::>() + } else { + panic!() + }; + + assert_eq!( + address, + H160(keccak256(&keccak_input)[12..].try_into().unwrap()) + ); + + state.block.sha3_inputs.push(keccak_input); Ok(vec![exec_step]) } @@ -212,10 +241,10 @@ fn handle_copy( callee_id: usize, offset: usize, length: usize, -) -> Result<(), Error> { +) -> Result, Error> { let initialization_bytes = state.call_ctx()?.memory.0[offset..offset + length].to_vec(); - let dst_id = NumberOrHash::Hash(H256(keccak256(&initialization_bytes))); - let bytes: Vec<_> = Bytecode::from(initialization_bytes) + let dst_id = NumberOrHash::Hash(H256(keccak256(&initialization_bytes.clone()))); + let bytes: Vec<_> = Bytecode::from(initialization_bytes.clone()) .code .iter() .map(|element| (element.value, element.is_code)) @@ -244,5 +273,5 @@ fn handle_copy( bytes, }); - Ok(()) + Ok(initialization_bytes) } diff --git a/zkevm-circuits/src/evm_circuit/execution/create.rs b/zkevm-circuits/src/evm_circuit/execution/create.rs index d3e22ff120..f226f3da12 100644 --- a/zkevm-circuits/src/evm_circuit/execution/create.rs +++ b/zkevm-circuits/src/evm_circuit/execution/create.rs @@ -265,7 +265,7 @@ impl ExecutionGadget for CreateGadget { cb.require_equal( "aw3rw3r", keccak_input.expr(), - 0xff.expr() * randomness_raised_to_84 // + 0xff.expr() * randomness_raised_to_84 + caller_address.expr() * randomness_raised_to_64 + salt.expr() * randomness_raised_to_32 + code_hash.expr(), @@ -279,11 +279,23 @@ impl ExecutionGadget for CreateGadget { // cb.condition(not::expr(is_create2.expr()), |cb| {()}); let keccak_output = cb.query_word(); - // cb.keccak_table_lookup( - // keccak_input.expr(), - // keccak_input_length.expr(), - // keccak_output.expr(), - // ); + cb.keccak_table_lookup( + keccak_input.expr(), + keccak_input_length.expr(), + keccak_output.expr(), + ); + + cb.require_equal( + "324124asfr", + new_address.expr(), + rlc::expr( + &keccak_output.cells[..20] + .iter() + .map(Expr::expr) + .collect::>(), + cb.power_of_randomness(), + ), + ); Self { opcode, @@ -480,7 +492,6 @@ impl ExecutionGadget for CreateGadget { .chain(salt.to_be_bytes().iter()) .chain(&keccak256(&values)) // don't need to reverse here??? .rev(), - block.randomness, )), )?; @@ -496,7 +507,13 @@ impl ExecutionGadget for CreateGadget { .assign(region, offset, Value::known(2.into()))?; } - let mut keccak_output = keccak256(&[0, 0]); + let mut keccak_output = keccak256( + &once(0xffu8) + .chain(call.callee_address.to_fixed_bytes()) // also don't need to be reversed.... + .chain(salt.to_be_bytes()) + .chain(keccak256(&values)) + .collect::>(), + ); keccak_output.reverse(); self.keccak_output .assign(region, offset, Some(keccak_output))?; @@ -512,17 +529,15 @@ mod test { address, bytecode, evm_types::OpcodeId, geth_types::Account, Address, Bytecode, ToWord, Word, }; - use lazy_static::lazy_static; use itertools::Itertools; + use lazy_static::lazy_static; use mock::{eth, TestContext}; const CALLEE_ADDRESS: Address = Address::repeat_byte(0xff); lazy_static! { - static ref CALLER_ADDRESS: Address = - address!("0xaabbccddee000000000000000000000000000000"); + static ref CALLER_ADDRESS: Address = address!("0xaabbccddee000000000000000000000000000000"); } - fn callee_bytecode(is_return: bool, offset: u64, length: u64) -> Bytecode { let memory_bytes = [0x60; 10]; let memory_address = 0; From 272d2b3a3209d6ee22a27196afd28b7b52ba90a3 Mon Sep 17 00:00:00 2001 From: Mason Liang Date: Mon, 19 Dec 2022 15:00:14 -0500 Subject: [PATCH 38/69] fix --- bus-mapping/src/evm/opcodes/create.rs | 1 - zkevm-circuits/src/evm_circuit/execution/create.rs | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/bus-mapping/src/evm/opcodes/create.rs b/bus-mapping/src/evm/opcodes/create.rs index 62d7604bc1..3ea0c33e90 100644 --- a/bus-mapping/src/evm/opcodes/create.rs +++ b/bus-mapping/src/evm/opcodes/create.rs @@ -11,7 +11,6 @@ use eth_types::{ Word, H160, H256, }; use ethers_core::utils::{get_create2_address, keccak256}; -use keccak256::EMPTY_HASH_LE; #[derive(Debug, Copy, Clone)] pub struct DummyCreate; diff --git a/zkevm-circuits/src/evm_circuit/execution/create.rs b/zkevm-circuits/src/evm_circuit/execution/create.rs index f226f3da12..120f031aa9 100644 --- a/zkevm-circuits/src/evm_circuit/execution/create.rs +++ b/zkevm-circuits/src/evm_circuit/execution/create.rs @@ -193,7 +193,7 @@ impl ExecutionGadget for CreateGadget { let gas_cost = GasCost::CREATE.expr() + memory_expansion.gas_cost() + keccak_gas_cost; let gas_remaining = cb.curr.state.gas_left.expr() - gas_cost; let gas_left = ConstantDivisionGadget::construct(cb, gas_remaining.clone(), 64); - let callee_gas_left = gas_remaining - gas_left.quotient(); + let _callee_gas_left = gas_remaining - gas_left.quotient(); for (field_tag, value) in [ ( CallContextFieldTag::ProgramCounter, From 2ed8eb79886a5aa5388839e7f3babbbc1c9b97ae Mon Sep 17 00:00:00 2001 From: Mason Liang Date: Thu, 22 Dec 2022 08:12:50 -0500 Subject: [PATCH 39/69] bus_mapping --- bus-mapping/src/evm/opcodes/create.rs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/bus-mapping/src/evm/opcodes/create.rs b/bus-mapping/src/evm/opcodes/create.rs index 3ea0c33e90..fdee424d0b 100644 --- a/bus-mapping/src/evm/opcodes/create.rs +++ b/bus-mapping/src/evm/opcodes/create.rs @@ -10,7 +10,7 @@ use eth_types::{ evm_types::gas_utils::memory_expansion_gas_cost, Bytecode, GethExecStep, ToBigEndian, ToWord, Word, H160, H256, }; -use ethers_core::utils::{get_create2_address, keccak256}; +use ethers_core::utils::{get_create2_address, keccak256, rlp}; #[derive(Debug, Copy, Clone)] pub struct DummyCreate; @@ -113,15 +113,15 @@ impl Opcode for DummyCreate { ); // Increase caller's nonce - let nonce_prev = state.sdb.get_nonce(&call.caller_address); + let caller_nonce = state.sdb.get_nonce(&call.caller_address); state.push_op_reversible( &mut exec_step, RW::WRITE, AccountOp { address: call.caller_address, field: AccountField::Nonce, - value: (nonce_prev + 1).into(), - value_prev: nonce_prev.into(), + value: (caller_nonce + 1).into(), + value_prev: caller_nonce.into(), }, )?; @@ -220,7 +220,11 @@ impl Opcode for DummyCreate { .chain(keccak256(&initialization_code)) .collect::>() } else { - panic!() + let mut stream = rlp::RlpStream::new(); + stream.begin_list(2); + stream.append(¤t_call.address); + stream.append(&Word::from(caller_nonce)); + stream.out().to_vec() }; assert_eq!( From 1989af08c7a7396e3cd1b5b35bb0fa312241a963 Mon Sep 17 00:00:00 2001 From: Mason Liang Date: Thu, 22 Dec 2022 08:32:02 -0500 Subject: [PATCH 40/69] wip --- .../src/evm_circuit/execution/create.rs | 49 +++++++------------ 1 file changed, 19 insertions(+), 30 deletions(-) diff --git a/zkevm-circuits/src/evm_circuit/execution/create.rs b/zkevm-circuits/src/evm_circuit/execution/create.rs index 120f031aa9..1ab2985df4 100644 --- a/zkevm-circuits/src/evm_circuit/execution/create.rs +++ b/zkevm-circuits/src/evm_circuit/execution/create.rs @@ -482,39 +482,28 @@ impl ExecutionGadget for CreateGadget { ), )?; - if is_create2 { - self.keccak_input.assign( - region, - offset, - Value::known(rlc::value( - once(&0xffu8) - .chain(&call.callee_address.to_fixed_bytes()) // also don't need to be reversed.... - .chain(salt.to_be_bytes().iter()) - .chain(&keccak256(&values)) // don't need to reverse here??? - .rev(), - block.randomness, - )), - )?; - self.keccak_input_length.assign( - region, - offset, - Value::known((1 + 20 + 32 + 32).into()), - )?; - } else { - self.keccak_input - .assign(region, offset, Value::known(0.into()))?; - self.keccak_input_length - .assign(region, offset, Value::known(2.into()))?; - } - - let mut keccak_output = keccak256( - &once(0xffu8) - .chain(call.callee_address.to_fixed_bytes()) // also don't need to be reversed.... + let keccak_input: Vec = if is_create2 { + once(0xffu8) + .chain(call.callee_address.to_fixed_bytes()) .chain(salt.to_be_bytes()) .chain(keccak256(&values)) - .collect::>(), - ); + .collect() + } else { + panic!() + }; + let mut keccak_output = keccak256(&keccak_input); keccak_output.reverse(); + + self.keccak_input.assign( + region, + offset, + Value::known(rlc::value(keccak_input.iter().rev(), block.randomness)), + )?; + self.keccak_input_length.assign( + region, + offset, + Value::known(keccak_input.len().to_scalar().unwrap()), + )?; self.keccak_output .assign(region, offset, Some(keccak_output))?; From be585cbc97d27a17dd4fefd92d9ad4361b6c6582 Mon Sep 17 00:00:00 2001 From: Mason Liang Date: Thu, 22 Dec 2022 10:07:45 -0500 Subject: [PATCH 41/69] kecak input for CREATE --- .../src/evm_circuit/execution/create.rs | 71 ++++++++++++++++--- 1 file changed, 63 insertions(+), 8 deletions(-) diff --git a/zkevm-circuits/src/evm_circuit/execution/create.rs b/zkevm-circuits/src/evm_circuit/execution/create.rs index 1ab2985df4..c522cc4c16 100644 --- a/zkevm-circuits/src/evm_circuit/execution/create.rs +++ b/zkevm-circuits/src/evm_circuit/execution/create.rs @@ -24,7 +24,7 @@ use crate::{ }; use bus_mapping::{circuit_input_builder::CopyDataType, evm::OpcodeId}; use eth_types::{evm_types::GasCost, Field, ToBigEndian, ToLittleEndian, ToScalar, U256}; -use ethers_core::utils::keccak256; +use ethers_core::utils::{keccak256, rlp}; use halo2_proofs::{circuit::Value, plonk::Error}; use keccak256::EMPTY_HASH_LE; use std::iter::once; @@ -411,13 +411,13 @@ impl ExecutionGadget for CreateGadget { self.caller_address .assign(region, offset, Some(caller_address_bytes.clone()))?; - let nonce_bytes = block.rws + let caller_nonce = block.rws [step.rw_indices[9 + usize::from(is_create2) + copy_rw_increase]] .account_value_pair() .1 - .low_u64() - .to_le_bytes(); - self.nonce.assign(region, offset, Some(nonce_bytes))?; + .low_u64(); + self.nonce + .assign(region, offset, Some(caller_nonce.to_le_bytes()))?; let [callee_rw_counter_end_of_reversion, callee_is_persistent] = [10, 11].map(|i| { block.rws[step.rw_indices[i + usize::from(is_create2) + copy_rw_increase]] @@ -466,8 +466,12 @@ impl ExecutionGadget for CreateGadget { (step.gas_left - GasCost::CREATE.as_u64() - u64::try_from(memory_expansion_gas_cost).unwrap() - - u64::try_from(initialization_code_word_size).unwrap() - * GasCost::COPY_SHA3.as_u64()) + - if is_create2 { + u64::try_from(initialization_code_word_size).unwrap() + * GasCost::COPY_SHA3.as_u64() + } else { + 0 + }) .into(), )?; @@ -489,7 +493,11 @@ impl ExecutionGadget for CreateGadget { .chain(keccak256(&values)) .collect() } else { - panic!() + let mut stream = rlp::RlpStream::new(); + stream.begin_list(2); + stream.append(&call.callee_address); + stream.append(&U256::from(caller_nonce)); + stream.out().to_vec() }; let mut keccak_output = keccak256(&keccak_input); keccak_output.reverse(); @@ -817,4 +825,51 @@ mod test { assert_eq!(run_test_circuits(test_context, None), Ok(()),); } + + #[test] + fn create2_really_create() { + // Test the case where the initialization call is successful, but the CREATE + // call is reverted. + let initializer = callee_bytecode(true, 0, 10).code(); + + let root_code = bytecode! { + PUSH32(Word::from_big_endian(&initializer)) + PUSH1(0) + MSTORE + + PUSH1(initializer.len()) // size + PUSH1(32 - initializer.len()) // offset + PUSH1(0) // value + + CREATE + }; + + let caller = Account { + address: *CALLER_ADDRESS, + code: root_code.into(), + nonce: Word::one(), + balance: eth(10), + ..Default::default() + }; + + let test_context = TestContext::<2, 1>::new( + None, + |accs| { + accs[0] + .address(address!("0x000000000000000000000000000000000000cafe")) + .balance(eth(10)); + accs[1].account(&caller); + }, + |mut txs, accs| { + txs[0] + .from(accs[0].address) + .to(accs[1].address) + .gas(100000u64.into()); + }, + |block, _| block, + ) + .unwrap(); + + assert_eq!(run_test_circuits(test_context, None), Ok(()),); + } } From 8167354d7183c974229ec994afa99f4deb6654c9 Mon Sep 17 00:00:00 2001 From: Mason Liang Date: Thu, 22 Dec 2022 17:43:58 -0500 Subject: [PATCH 42/69] wip rlpu64 --- .../src/evm_circuit/execution/create.rs | 140 +++++++++++++++++- 1 file changed, 137 insertions(+), 3 deletions(-) diff --git a/zkevm-circuits/src/evm_circuit/execution/create.rs b/zkevm-circuits/src/evm_circuit/execution/create.rs index c522cc4c16..adf789d0d9 100644 --- a/zkevm-circuits/src/evm_circuit/execution/create.rs +++ b/zkevm-circuits/src/evm_circuit/execution/create.rs @@ -13,9 +13,9 @@ use crate::{ Transition::{Any, Delta, To}, }, from_bytes, - math_gadget::ConstantDivisionGadget, + math_gadget::{ConstantDivisionGadget, IsZeroGadget}, memory_gadget::{MemoryAddressGadget, MemoryExpansionGadget}, - not, rlc, select, CachedRegion, Cell, RandomLinearCombination, Word, + not, rlc, select, sum, CachedRegion, Cell, RandomLinearCombination, Word, }, witness::{Block, Call, ExecStep, Transaction}, }, @@ -46,6 +46,10 @@ pub(crate) struct CreateGadget { caller_address: RandomLinearCombination, nonce: RandomLinearCombination, + // TODO: combine these three and above into RlpU64Gadget + // most_significant_nonce_byte: Cell, + // most_significant_nonce_byte_is_zero: IsZeroGadget, + // most_significant_nonce_byte_selectors: [Cell; N_BYTES_U64], callee_reversion_info: ReversionInfo, callee_is_success: Cell, @@ -276,7 +280,25 @@ impl ExecutionGadget for CreateGadget { (1 + 20 + 32 + 32).expr(), ); }); - // cb.condition(not::expr(is_create2.expr()), |cb| {()}); + + // let most_significant_nonce_byte_is_zero = IsZeroGadget::construct(cb); + // let most_significant_nonce_byte_selectors = [(); N_BYTES_U64].map(|()| cb.query_bool()); + // cb.condition(most_significant_nonce_byte_selectors[0].expr(), |cb| { + // cb.require_zero( + // "caller nonce if highest_nonzero_nonce_byte is 0", + // nonce.expr(), + // ); + // cb.require_equal( + // "is zoerasld;fkja;welkfja;sl", + // most_significant_nonce_byte_index.expr(), + // 1.expr(), + // ) + // }); + // let address_rlp_rlc = + // 0x94.expr() * cb.power_of_randomness()[20].clone() + caller_address.expr(); + // + // // cb.condition(not::expr(is_create2.expr()), |cb| { + // // }); let keccak_output = cb.query_word(); cb.keccak_table_lookup( @@ -319,6 +341,8 @@ impl ExecutionGadget for CreateGadget { keccak_input, keccak_input_length, initialization_code_word_size, + // highest_nonzero_nonce_byte_selectors, + // highest_nonzero_nonce_byte_inverse, } } @@ -515,10 +539,120 @@ impl ExecutionGadget for CreateGadget { self.keccak_output .assign(region, offset, Some(keccak_output))?; + // let nonce_le_bytes = caller_nonce.to_le_bytes(); + // let most_significant_nonce_byte_index = + // (u64::from(u64::BITS + 1 - caller_nonce.leading_zeros()) + 7) / 8; + // for i in 0..N_BYTES_U64 { + // self.most_significant_nonce_byte_selectors[i].assign( + // region, + // offset, + // Value::known( + // (u64::try_from(i).unwrap() == most_significant_nonce_byte_index) + // .to_scalar() + // .unwrap(), + // ), + // )?; + // } + Ok(()) } } +struct RlpU64Gadget { + bytes: [Cell; N_BYTES_U64], // make this an RLC + is_most_significant_byte: [Cell; N_BYTES_U64], + most_significant_byte_is_zero: IsZeroGadget, +} + +impl RlpU64Gadget { + fn construct(cb: &mut ConstraintBuilder) -> Self { + let bytes = cb.query_bytes(); + let is_most_significant_byte = [(); N_BYTES_U64].map(|()| cb.query_bool()); + let most_significant_byte = sum::expr( + bytes + .iter() + .zip(&is_most_significant_byte) + .map(|(byte, indicator)| byte.expr() * indicator.expr()), + ); + let most_significant_byte_is_zero = IsZeroGadget::construct(cb, most_significant_byte); + + cb.require_boolean( + "at most one of is_most_significant_byte is one", + sum::expr(&is_most_significant_byte), + ); + + let value = from_bytes::expr(&bytes); + cb.condition(most_significant_byte_is_zero.expr(), |cb| { + cb.require_zero( + "if most_significant_byte_is_zero is 0, value is 0", + value.clone(), + ); + }); + for i in 0..N_BYTES_U64 { + cb.condition(is_most_significant_byte[i].expr(), |cb| { + cb.require_equal( + "most significant byte is non-zero", + most_significant_byte_is_zero.expr(), + 0.expr(), + ); + cb.require_equal( + "higher bytes are 0", + from_bytes::expr(&bytes[..i]), + value.clone(), + ); + }); + } + + Self { + bytes, + is_most_significant_byte, + most_significant_byte_is_zero, + } + } + + fn assign( + &self, + region: &mut CachedRegion<'_, '_, F>, + offset: usize, + value: u64, + ) -> Result<(), Error> { + let bytes = value.to_le_bytes(); + let most_significant_byte_index = bytes + .iter() + .rev() + .position(|byte| *byte != 0) + .map(|i| N_BYTES_U64 - i); + self.most_significant_byte_is_zero.assign( + region, + offset, + most_significant_byte_index + .map(|i| u64::from(bytes[i]).into()) + .unwrap_or(F::zero()), + )?; + for i in 0..N_BYTES_U64 { + self.bytes[i].assign(region, offset, Value::known(u64::from(bytes[i]).into()))?; + self.is_most_significant_byte[i].assign( + region, + offset, + Value::known( + (Some(i) == most_significant_byte_index) + .to_scalar() + .unwrap(), + ), + )?; + } + Ok(()) + } + + // fn value(&self) -> Expression { + // from_bytes::expr(&self.bytes) + // } + // + // fn value_rlc(&self, cb: &ConstraintBuilder) -> Expression { + // rlc::expr(&self.bytes, cb.power_of_randomness()) + // } +} + #[cfg(test)] mod test { use crate::test_util::run_test_circuits; From e3c7ca662daa9affb6b792944ed359281725f387 Mon Sep 17 00:00:00 2001 From: Mason Liang Date: Thu, 22 Dec 2022 18:53:10 -0500 Subject: [PATCH 43/69] wip --- .../src/evm_circuit/execution/create.rs | 49 ++++++++++--------- 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/zkevm-circuits/src/evm_circuit/execution/create.rs b/zkevm-circuits/src/evm_circuit/execution/create.rs index adf789d0d9..70460c90c8 100644 --- a/zkevm-circuits/src/evm_circuit/execution/create.rs +++ b/zkevm-circuits/src/evm_circuit/execution/create.rs @@ -25,7 +25,10 @@ use crate::{ use bus_mapping::{circuit_input_builder::CopyDataType, evm::OpcodeId}; use eth_types::{evm_types::GasCost, Field, ToBigEndian, ToLittleEndian, ToScalar, U256}; use ethers_core::utils::{keccak256, rlp}; -use halo2_proofs::{circuit::Value, plonk::Error}; +use halo2_proofs::{ + circuit::Value, + plonk::{Error, Expression}, +}; use keccak256::EMPTY_HASH_LE; use std::iter::once; @@ -45,11 +48,7 @@ pub(crate) struct CreateGadget { was_warm: Cell, caller_address: RandomLinearCombination, - nonce: RandomLinearCombination, - // TODO: combine these three and above into RlpU64Gadget - // most_significant_nonce_byte: Cell, - // most_significant_nonce_byte_is_zero: IsZeroGadget, - // most_significant_nonce_byte_selectors: [Cell; N_BYTES_U64], + nonce: RlpU64Gadget, callee_reversion_info: ReversionInfo, callee_is_success: Cell, @@ -153,12 +152,12 @@ impl ExecutionGadget for CreateGadget { from_bytes::expr(&caller_address.cells), ); - let nonce = cb.query_rlc(); + let nonce = RlpU64Gadget::construct(cb); cb.account_write( from_bytes::expr(&caller_address.cells), AccountFieldTag::Nonce, - from_bytes::expr(&nonce.cells) + 1.expr(), - from_bytes::expr(&nonce.cells), + nonce.value() + 1.expr(), + nonce.value(), Some(&mut reversion_info), ); @@ -282,7 +281,8 @@ impl ExecutionGadget for CreateGadget { }); // let most_significant_nonce_byte_is_zero = IsZeroGadget::construct(cb); - // let most_significant_nonce_byte_selectors = [(); N_BYTES_U64].map(|()| cb.query_bool()); + // let most_significant_nonce_byte_selectors = [(); N_BYTES_U64].map(|()| + // cb.query_bool()); // cb.condition(most_significant_nonce_byte_selectors[0].expr(), |cb| { // cb.require_zero( // "caller nonce if highest_nonzero_nonce_byte is 0", @@ -295,7 +295,8 @@ impl ExecutionGadget for CreateGadget { // ) // }); // let address_rlp_rlc = - // 0x94.expr() * cb.power_of_randomness()[20].clone() + caller_address.expr(); + // 0x94.expr() * cb.power_of_randomness()[20].clone() + + // caller_address.expr(); // // // cb.condition(not::expr(is_create2.expr()), |cb| { // // }); @@ -440,8 +441,7 @@ impl ExecutionGadget for CreateGadget { .account_value_pair() .1 .low_u64(); - self.nonce - .assign(region, offset, Some(caller_nonce.to_le_bytes()))?; + self.nonce.assign(region, offset, caller_nonce)?; let [callee_rw_counter_end_of_reversion, callee_is_persistent] = [10, 11].map(|i| { block.rws[step.rw_indices[i + usize::from(is_create2) + copy_rw_increase]] @@ -558,8 +558,9 @@ impl ExecutionGadget for CreateGadget { } } +#[derive(Clone, Debug)] struct RlpU64Gadget { - bytes: [Cell; N_BYTES_U64], // make this an RLC + bytes: [Cell; N_BYTES_U64], is_most_significant_byte: [Cell; N_BYTES_U64], most_significant_byte_is_zero: IsZeroGadget, } @@ -584,7 +585,7 @@ impl RlpU64Gadget { let value = from_bytes::expr(&bytes); cb.condition(most_significant_byte_is_zero.expr(), |cb| { cb.require_zero( - "if most_significant_byte_is_zero is 0, value is 0", + "if most significant byte is 0, value is 0", value.clone(), ); }); @@ -597,7 +598,7 @@ impl RlpU64Gadget { ); cb.require_equal( "higher bytes are 0", - from_bytes::expr(&bytes[..i]), + from_bytes::expr(&bytes[..i + 1]), value.clone(), ); }); @@ -616,12 +617,16 @@ impl RlpU64Gadget { offset: usize, value: u64, ) -> Result<(), Error> { + dbg!(value); + let bytes = value.to_le_bytes(); + dbg!(bytes.clone()); let most_significant_byte_index = bytes .iter() .rev() .position(|byte| *byte != 0) - .map(|i| N_BYTES_U64 - i); + .map(|i| N_BYTES_U64 - i - 1); + dbg!(most_significant_byte_index); self.most_significant_byte_is_zero.assign( region, offset, @@ -644,13 +649,9 @@ impl RlpU64Gadget { Ok(()) } - // fn value(&self) -> Expression { - // from_bytes::expr(&self.bytes) - // } - // - // fn value_rlc(&self, cb: &ConstraintBuilder) -> Expression { - // rlc::expr(&self.bytes, cb.power_of_randomness()) - // } + fn value(&self) -> Expression { + from_bytes::expr(&self.bytes) + } } #[cfg(test)] From 1c3b8194477f8c485a22d4fc0df593d3fd8304c4 Mon Sep 17 00:00:00 2001 From: Mason Liang Date: Thu, 22 Dec 2022 19:00:50 -0500 Subject: [PATCH 44/69] use rlc --- .../src/evm_circuit/execution/create.rs | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/zkevm-circuits/src/evm_circuit/execution/create.rs b/zkevm-circuits/src/evm_circuit/execution/create.rs index 70460c90c8..31678cdd0e 100644 --- a/zkevm-circuits/src/evm_circuit/execution/create.rs +++ b/zkevm-circuits/src/evm_circuit/execution/create.rs @@ -560,17 +560,18 @@ impl ExecutionGadget for CreateGadget { #[derive(Clone, Debug)] struct RlpU64Gadget { - bytes: [Cell; N_BYTES_U64], + bytes: RandomLinearCombination, is_most_significant_byte: [Cell; N_BYTES_U64], most_significant_byte_is_zero: IsZeroGadget, } impl RlpU64Gadget { fn construct(cb: &mut ConstraintBuilder) -> Self { - let bytes = cb.query_bytes(); + let bytes = cb.query_rlc(); let is_most_significant_byte = [(); N_BYTES_U64].map(|()| cb.query_bool()); let most_significant_byte = sum::expr( bytes + .cells .iter() .zip(&is_most_significant_byte) .map(|(byte, indicator)| byte.expr() * indicator.expr()), @@ -582,12 +583,9 @@ impl RlpU64Gadget { sum::expr(&is_most_significant_byte), ); - let value = from_bytes::expr(&bytes); + let value = from_bytes::expr(&bytes.cells); cb.condition(most_significant_byte_is_zero.expr(), |cb| { - cb.require_zero( - "if most significant byte is 0, value is 0", - value.clone(), - ); + cb.require_zero("if most significant byte is 0, value is 0", value.clone()); }); for i in 0..N_BYTES_U64 { cb.condition(is_most_significant_byte[i].expr(), |cb| { @@ -598,7 +596,7 @@ impl RlpU64Gadget { ); cb.require_equal( "higher bytes are 0", - from_bytes::expr(&bytes[..i + 1]), + from_bytes::expr(&bytes.cells[..i + 1]), value.clone(), ); }); @@ -634,8 +632,8 @@ impl RlpU64Gadget { .map(|i| u64::from(bytes[i]).into()) .unwrap_or(F::zero()), )?; + self.bytes.assign(region, offset, Some(bytes))?; for i in 0..N_BYTES_U64 { - self.bytes[i].assign(region, offset, Value::known(u64::from(bytes[i]).into()))?; self.is_most_significant_byte[i].assign( region, offset, @@ -650,8 +648,10 @@ impl RlpU64Gadget { } fn value(&self) -> Expression { - from_bytes::expr(&self.bytes) + from_bytes::expr(&self.bytes.cells) } + + // fn rlp_rlc(&self) - } #[cfg(test)] From 5a88e19e221f5523b9cc74838aeca0bd983c2af0 Mon Sep 17 00:00:00 2001 From: Mason Liang Date: Thu, 22 Dec 2022 19:25:51 -0500 Subject: [PATCH 45/69] rlp length --- .../src/evm_circuit/execution/create.rs | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/zkevm-circuits/src/evm_circuit/execution/create.rs b/zkevm-circuits/src/evm_circuit/execution/create.rs index 31678cdd0e..5bf5cd6bf7 100644 --- a/zkevm-circuits/src/evm_circuit/execution/create.rs +++ b/zkevm-circuits/src/evm_circuit/execution/create.rs @@ -298,8 +298,13 @@ impl ExecutionGadget for CreateGadget { // 0x94.expr() * cb.power_of_randomness()[20].clone() + // caller_address.expr(); // - // // cb.condition(not::expr(is_create2.expr()), |cb| { - // // }); + cb.condition(not::expr(is_create2.expr()), |cb| { + cb.require_equal( + "23452345", + keccak_input_length.expr(), + (1 + 20).expr() + nonce.rlp_length(), + ); + }); let keccak_output = cb.query_word(); cb.keccak_table_lookup( @@ -342,8 +347,6 @@ impl ExecutionGadget for CreateGadget { keccak_input, keccak_input_length, initialization_code_word_size, - // highest_nonzero_nonce_byte_selectors, - // highest_nonzero_nonce_byte_inverse, } } @@ -651,7 +654,15 @@ impl RlpU64Gadget { from_bytes::expr(&self.bytes.cells) } - // fn rlp_rlc(&self) - + fn rlp_length(&self) -> Expression { + 1.expr() + + sum::expr( + self.is_most_significant_byte + .iter() + .enumerate() + .map(|(i, indicator)| (1 + i).expr() * indicator.expr()), + ) + } } #[cfg(test)] From b656f6d4eba7b2f66c3bfaabe11ebce06728aef9 Mon Sep 17 00:00:00 2001 From: Mason Liang Date: Fri, 23 Dec 2022 01:42:57 -0500 Subject: [PATCH 46/69] rlp length --- .../src/evm_circuit/execution/create.rs | 128 +++++++++++------- zkevm-circuits/src/evm_circuit/table.rs | 4 + .../evm_circuit/util/constraint_builder.rs | 1 + 3 files changed, 85 insertions(+), 48 deletions(-) diff --git a/zkevm-circuits/src/evm_circuit/execution/create.rs b/zkevm-circuits/src/evm_circuit/execution/create.rs index 5bf5cd6bf7..5b68c8d7d3 100644 --- a/zkevm-circuits/src/evm_circuit/execution/create.rs +++ b/zkevm-circuits/src/evm_circuit/execution/create.rs @@ -274,7 +274,7 @@ impl ExecutionGadget for CreateGadget { + code_hash.expr(), ); cb.require_equal( - "23452345", + "create2 23452345", keccak_input_length.expr(), (1 + 20 + 32 + 32).expr(), ); @@ -300,9 +300,9 @@ impl ExecutionGadget for CreateGadget { // cb.condition(not::expr(is_create2.expr()), |cb| { cb.require_equal( - "23452345", + "create 23452345", keccak_input_length.expr(), - (1 + 20).expr() + nonce.rlp_length(), + (1 + 1 + 20).expr() + nonce.rlp_length(), ); }); @@ -534,6 +534,7 @@ impl ExecutionGadget for CreateGadget { offset, Value::known(rlc::value(keccak_input.iter().rev(), block.randomness)), )?; + dbg!(keccak_input.len()); self.keccak_input_length.assign( region, offset, @@ -566,6 +567,7 @@ struct RlpU64Gadget { bytes: RandomLinearCombination, is_most_significant_byte: [Cell; N_BYTES_U64], most_significant_byte_is_zero: IsZeroGadget, + is_less_than_128: Cell, } impl RlpU64Gadget { @@ -580,6 +582,7 @@ impl RlpU64Gadget { .map(|(byte, indicator)| byte.expr() * indicator.expr()), ); let most_significant_byte_is_zero = IsZeroGadget::construct(cb, most_significant_byte); + let is_less_than_128 = cb.query_bool(); cb.require_boolean( "at most one of is_most_significant_byte is one", @@ -605,10 +608,15 @@ impl RlpU64Gadget { }); } + cb.condition(is_less_than_128.expr(), |cb| { + cb.range_lookup(value, 128); + }); + Self { bytes, is_most_significant_byte, most_significant_byte_is_zero, + is_less_than_128, } } @@ -647,6 +655,11 @@ impl RlpU64Gadget { ), )?; } + self.is_less_than_128.assign( + region, + offset, + Value::known((value < 128).to_scalar().unwrap()), + )?; Ok(()) } @@ -655,13 +668,15 @@ impl RlpU64Gadget { } fn rlp_length(&self) -> Expression { - 1.expr() - + sum::expr( - self.is_most_significant_byte - .iter() - .enumerate() - .map(|(i, indicator)| (1 + i).expr() * indicator.expr()), - ) + self.is_less_than_128.expr() + + not::expr(self.is_less_than_128.expr()) + * (1.expr() + + sum::expr( + self.is_most_significant_byte + .iter() + .enumerate() + .map(|(i, indicator)| (1 + i).expr() * indicator.expr()), + )) } } @@ -672,13 +687,14 @@ mod test { address, bytecode, evm_types::OpcodeId, geth_types::Account, Address, Bytecode, ToWord, Word, }; + use ethers_core::utils::rlp; use itertools::Itertools; use lazy_static::lazy_static; use mock::{eth, TestContext}; const CALLEE_ADDRESS: Address = Address::repeat_byte(0xff); lazy_static! { - static ref CALLER_ADDRESS: Address = address!("0xaabbccddee000000000000000000000000000000"); + static ref CALLER_ADDRESS: Address = address!("0x00bbccddee000000000000000000000000002400"); } fn callee_bytecode(is_return: bool, offset: u64, length: u64) -> Bytecode { @@ -974,48 +990,64 @@ mod test { #[test] fn create2_really_create() { - // Test the case where the initialization call is successful, but the CREATE - // call is reverted. - let initializer = callee_bytecode(true, 0, 10).code(); + for nonce in [0, 1, 127, 128, 255, 256, 0x100] { + let mut stream = rlp::RlpStream::new(); + stream.begin_list(2); + stream.append(&*CALLER_ADDRESS); + stream.append(&Word::from(nonce)); + let x = stream.out().to_vec(); - let root_code = bytecode! { - PUSH32(Word::from_big_endian(&initializer)) - PUSH1(0) - MSTORE + dbg!(nonce, x.len(), x); + } - PUSH1(initializer.len()) // size - PUSH1(32 - initializer.len()) // offset - PUSH1(0) // value + for nonce in [0, 1, 0xff, 0x100] { + dbg!(nonce); + let initializer = callee_bytecode(true, 0, 10).code(); - CREATE - }; + let root_code = bytecode! { + PUSH32(Word::from_big_endian(&initializer)) + PUSH1(0) + MSTORE - let caller = Account { - address: *CALLER_ADDRESS, - code: root_code.into(), - nonce: Word::one(), - balance: eth(10), - ..Default::default() - }; + PUSH1(initializer.len()) // size + PUSH1(32 - initializer.len()) // offset + PUSH1(0) // value - let test_context = TestContext::<2, 1>::new( - None, - |accs| { - accs[0] - .address(address!("0x000000000000000000000000000000000000cafe")) - .balance(eth(10)); - accs[1].account(&caller); - }, - |mut txs, accs| { - txs[0] - .from(accs[0].address) - .to(accs[1].address) - .gas(100000u64.into()); - }, - |block, _| block, - ) - .unwrap(); + CREATE + }; - assert_eq!(run_test_circuits(test_context, None), Ok(()),); + let caller = Account { + address: *CALLER_ADDRESS, + code: root_code.into(), + nonce: nonce.into(), + balance: eth(10), + ..Default::default() + }; + + let test_context = TestContext::<2, 1>::new( + None, + |accs| { + accs[0] + .address(address!("0x000000000000000000000000000000000000cafe")) + .balance(eth(10)); + accs[1].account(&caller); + }, + |mut txs, accs| { + txs[0] + .from(accs[0].address) + .to(accs[1].address) + .gas(100000u64.into()); + }, + |block, _| block, + ) + .unwrap(); + + assert_eq!( + run_test_circuits(test_context, None), + Ok(()), + "nonce = {}", + nonce + ); + } } } diff --git a/zkevm-circuits/src/evm_circuit/table.rs b/zkevm-circuits/src/evm_circuit/table.rs index 222b4dbf40..bc65f97178 100644 --- a/zkevm-circuits/src/evm_circuit/table.rs +++ b/zkevm-circuits/src/evm_circuit/table.rs @@ -15,6 +15,7 @@ pub enum FixedTableTag { Range16, Range32, Range64, + Range128, Range256, Range512, Range1024, @@ -45,6 +46,9 @@ impl FixedTableTag { Self::Range64 => { Box::new((0..64).map(move |value| [tag, F::from(value), F::zero(), F::zero()])) } + Self::Range128 => { + Box::new((0..128).map(move |value| [tag, F::from(value), F::zero(), F::zero()])) + } Self::Range256 => { Box::new((0..256).map(move |value| [tag, F::from(value), F::zero(), F::zero()])) } diff --git a/zkevm-circuits/src/evm_circuit/util/constraint_builder.rs b/zkevm-circuits/src/evm_circuit/util/constraint_builder.rs index c0639f5070..88a876e894 100644 --- a/zkevm-circuits/src/evm_circuit/util/constraint_builder.rs +++ b/zkevm-circuits/src/evm_circuit/util/constraint_builder.rs @@ -525,6 +525,7 @@ impl<'a, F: Field> ConstraintBuilder<'a, F> { 16 => ("Range16", FixedTableTag::Range16), 32 => ("Range32", FixedTableTag::Range32), 64 => ("Range64", FixedTableTag::Range64), + 128 => ("Range64", FixedTableTag::Range128), 256 => ("Range256", FixedTableTag::Range256), 512 => ("Range512", FixedTableTag::Range512), 1024 => ("Range1024", FixedTableTag::Range1024), From 0082bf1ca97b953e0add93784c76bba46766d111 Mon Sep 17 00:00:00 2001 From: Mason Liang Date: Fri, 23 Dec 2022 16:21:26 -0500 Subject: [PATCH 47/69] wip --- .../src/evm_circuit/execution/create.rs | 76 +++++++++++-------- 1 file changed, 46 insertions(+), 30 deletions(-) diff --git a/zkevm-circuits/src/evm_circuit/execution/create.rs b/zkevm-circuits/src/evm_circuit/execution/create.rs index 5b68c8d7d3..7c277ebe4c 100644 --- a/zkevm-circuits/src/evm_circuit/execution/create.rs +++ b/zkevm-circuits/src/evm_circuit/execution/create.rs @@ -266,7 +266,7 @@ impl ExecutionGadget for CreateGadget { let randomness_raised_to_84 = randomness_raised_to_64.clone() * cb.power_of_randomness()[19].clone(); cb.require_equal( - "aw3rw3r", + "for CREATE2, keccak input is 0xff ++ address ++ salt ++ code_hash", keccak_input.expr(), 0xff.expr() * randomness_raised_to_84 + caller_address.expr() * randomness_raised_to_64 @@ -274,33 +274,23 @@ impl ExecutionGadget for CreateGadget { + code_hash.expr(), ); cb.require_equal( - "create2 23452345", + "for CREATE2, keccak input length is 85", keccak_input_length.expr(), (1 + 20 + 32 + 32).expr(), ); }); - // let most_significant_nonce_byte_is_zero = IsZeroGadget::construct(cb); - // let most_significant_nonce_byte_selectors = [(); N_BYTES_U64].map(|()| - // cb.query_bool()); - // cb.condition(most_significant_nonce_byte_selectors[0].expr(), |cb| { - // cb.require_zero( - // "caller nonce if highest_nonzero_nonce_byte is 0", - // nonce.expr(), - // ); - // cb.require_equal( - // "is zoerasld;fkja;welkfja;sl", - // most_significant_nonce_byte_index.expr(), - // 1.expr(), - // ) - // }); - // let address_rlp_rlc = - // 0x94.expr() * cb.power_of_randomness()[20].clone() + - // caller_address.expr(); - // cb.condition(not::expr(is_create2.expr()), |cb| { + // let randomness_raised_to_20 = cb.power_of_randomness()[19].clone(); + // cb.require_equal( + // "for CREATE, keccak input is rlp([address, nonce])", + // keccak_input.expr(), + // (0xc2.expr() * randomness_raised_to_20 + caller_address.expr()) + // * nonce.randomness_raised_to_rlp_length() + // + nonce.rlp_rlc(), + // ); cb.require_equal( - "create 23452345", + "for CREATE, keccak input length is rlp([address, nonce]).len()", keccak_input_length.expr(), (1 + 1 + 20).expr() + nonce.rlp_length(), ); @@ -667,17 +657,43 @@ impl RlpU64Gadget { from_bytes::expr(&self.bytes.cells) } + fn n_bytes_nonce(&self) -> Expression { + sum::expr( + self.is_most_significant_byte + .iter() + .enumerate() + .map(|(i, indicator)| (1 + i).expr() * indicator.expr()), + ) + } + fn rlp_length(&self) -> Expression { - self.is_less_than_128.expr() - + not::expr(self.is_less_than_128.expr()) - * (1.expr() - + sum::expr( - self.is_most_significant_byte - .iter() - .enumerate() - .map(|(i, indicator)| (1 + i).expr() * indicator.expr()), - )) + 1.expr() + not::expr(self.is_less_than_128.expr()) * self.n_bytes_nonce() } + + // fn rlp_rlc(&self) -> Expression { + // select::expr( + // and::expr(&[ + // self.is_less_than_128.expr(), + // not::expr(self.most_significant_byte_is_zero.expr()), + // ]), + // self.value(), + // (0x80.expr() + self.n_bytes_nonce()) * self.randomness_raised_to_rlp_length() + // + self.bytes.expr(), + // ) + // } + + // fn randomness_raised_to_rlp_length(&self, cb: &ConstraintBuilder) -> Expression { + // let powers_of_randomness = cb.power_of_randomness(); + // self.is_less_than_128.expr() + // + not::expr(self.is_less_than_128.expr()) + // * (1.expr() + // + sum::expr( + // self.is_most_significant_byte + // .iter() + // .enumerate() + // .map(|(i, indicator)| (1 + i).expr() * indicator.expr()), + // )) + // } } #[cfg(test)] From cc45cbdb34585c64db016ff1fab95ef7bf3bf105 Mon Sep 17 00:00:00 2001 From: Mason Liang Date: Sat, 24 Dec 2022 23:48:16 -0500 Subject: [PATCH 48/69] wip --- .../src/evm_circuit/execution/create.rs | 98 ++++++++++--------- 1 file changed, 53 insertions(+), 45 deletions(-) diff --git a/zkevm-circuits/src/evm_circuit/execution/create.rs b/zkevm-circuits/src/evm_circuit/execution/create.rs index 7c277ebe4c..8964fd7b49 100644 --- a/zkevm-circuits/src/evm_circuit/execution/create.rs +++ b/zkevm-circuits/src/evm_circuit/execution/create.rs @@ -7,6 +7,7 @@ use crate::{ }, step::ExecutionState, util::{ + and, common_gadget::TransferGadget, constraint_builder::{ ConstraintBuilder, ReversionInfo, StepStateTransition, @@ -281,14 +282,19 @@ impl ExecutionGadget for CreateGadget { }); cb.condition(not::expr(is_create2.expr()), |cb| { - // let randomness_raised_to_20 = cb.power_of_randomness()[19].clone(); - // cb.require_equal( - // "for CREATE, keccak input is rlp([address, nonce])", - // keccak_input.expr(), - // (0xc2.expr() * randomness_raised_to_20 + caller_address.expr()) - // * nonce.randomness_raised_to_rlp_length() - // + nonce.rlp_rlc(), - // ); + let randomness_raised_to_20 = cb.power_of_randomness()[19].clone(); + let randomness_raised_to_21 = cb.power_of_randomness()[20].clone(); + let randomness_raised_to_22 = cb.power_of_randomness()[21].clone(); + let address_rlp_length = 21.expr(); + cb.require_equal( + "for CREATE, keccak input is rlp([address, nonce])", + keccak_input.expr(), + ((0xc0.expr() + address_rlp_length + nonce.rlp_length()) * randomness_raised_to_21 + + 0x94.expr() * randomness_raised_to_20 + + caller_address.expr()) + * nonce.randomness_raised_to_rlp_length(cb) + + nonce.rlp_rlc(cb), + ); cb.require_equal( "for CREATE, keccak input length is rlp([address, nonce]).len()", keccak_input_length.expr(), @@ -519,6 +525,7 @@ impl ExecutionGadget for CreateGadget { let mut keccak_output = keccak256(&keccak_input); keccak_output.reverse(); + dbg!(keccak_input.clone()); self.keccak_input.assign( region, offset, @@ -616,16 +623,16 @@ impl RlpU64Gadget { offset: usize, value: u64, ) -> Result<(), Error> { - dbg!(value); + // dbg!(value); let bytes = value.to_le_bytes(); - dbg!(bytes.clone()); + // dbg!(bytes.clone()); let most_significant_byte_index = bytes .iter() .rev() .position(|byte| *byte != 0) .map(|i| N_BYTES_U64 - i - 1); - dbg!(most_significant_byte_index); + // dbg!(most_significant_byte_index); self.most_significant_byte_is_zero.assign( region, offset, @@ -670,30 +677,31 @@ impl RlpU64Gadget { 1.expr() + not::expr(self.is_less_than_128.expr()) * self.n_bytes_nonce() } - // fn rlp_rlc(&self) -> Expression { - // select::expr( - // and::expr(&[ - // self.is_less_than_128.expr(), - // not::expr(self.most_significant_byte_is_zero.expr()), - // ]), - // self.value(), - // (0x80.expr() + self.n_bytes_nonce()) * self.randomness_raised_to_rlp_length() - // + self.bytes.expr(), - // ) - // } - - // fn randomness_raised_to_rlp_length(&self, cb: &ConstraintBuilder) -> Expression { - // let powers_of_randomness = cb.power_of_randomness(); - // self.is_less_than_128.expr() - // + not::expr(self.is_less_than_128.expr()) - // * (1.expr() - // + sum::expr( - // self.is_most_significant_byte - // .iter() - // .enumerate() - // .map(|(i, indicator)| (1 + i).expr() * indicator.expr()), - // )) - // } + fn rlp_rlc(&self, cb: &ConstraintBuilder) -> Expression { + select::expr( + and::expr(&[ + self.is_less_than_128.expr(), + not::expr(self.most_significant_byte_is_zero.expr()), + ]), + self.value(), + (0x80.expr() + self.n_bytes_nonce()) * self.randomness_raised_to_rlp_length(cb) + + self.bytes.expr(), + ) + } + + fn randomness_raised_to_rlp_length(&self, cb: &ConstraintBuilder) -> Expression { + let powers_of_randomness = cb.power_of_randomness(); + select::expr( + self.is_less_than_128.expr(), + 1.expr(), + sum::expr( + self.is_most_significant_byte + .iter() + .zip(powers_of_randomness) + .map(|(indicator, power)| indicator.expr() * power.clone()), + ), + ) + } } #[cfg(test)] @@ -1006,17 +1014,17 @@ mod test { #[test] fn create2_really_create() { - for nonce in [0, 1, 127, 128, 255, 256, 0x100] { - let mut stream = rlp::RlpStream::new(); - stream.begin_list(2); - stream.append(&*CALLER_ADDRESS); - stream.append(&Word::from(nonce)); - let x = stream.out().to_vec(); - - dbg!(nonce, x.len(), x); - } + // for nonce in [0, 1, 127, 128, 255, 256, 0x100] { + // let mut stream = rlp::RlpStream::new(); + // stream.begin_list(2); + // stream.append(&*CALLER_ADDRESS); + // stream.append(&Word::from(nonce)); + // let x = stream.out().to_vec(); + // + // dbg!(nonce, x.len(), x); + // } - for nonce in [0, 1, 0xff, 0x100] { + for nonce in [1, 0, 1, 0xff, 0x100] { dbg!(nonce); let initializer = callee_bytecode(true, 0, 10).code(); From 0e3418e9e66a33cd2554b041341ddfd830a07291 Mon Sep 17 00:00:00 2001 From: Mason Liang Date: Sun, 25 Dec 2022 00:56:27 -0500 Subject: [PATCH 49/69] wip --- .../src/evm_circuit/execution/create.rs | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/zkevm-circuits/src/evm_circuit/execution/create.rs b/zkevm-circuits/src/evm_circuit/execution/create.rs index 8964fd7b49..e21b0aa765 100644 --- a/zkevm-circuits/src/evm_circuit/execution/create.rs +++ b/zkevm-circuits/src/evm_circuit/execution/create.rs @@ -285,15 +285,18 @@ impl ExecutionGadget for CreateGadget { let randomness_raised_to_20 = cb.power_of_randomness()[19].clone(); let randomness_raised_to_21 = cb.power_of_randomness()[20].clone(); let randomness_raised_to_22 = cb.power_of_randomness()[21].clone(); - let address_rlp_length = 21.expr(); + // let address_rlp_length = 21.expr(); cb.require_equal( "for CREATE, keccak input is rlp([address, nonce])", keccak_input.expr(), - ((0xc0.expr() + address_rlp_length + nonce.rlp_length()) * randomness_raised_to_21 - + 0x94.expr() * randomness_raised_to_20 - + caller_address.expr()) - * nonce.randomness_raised_to_rlp_length(cb) - + nonce.rlp_rlc(cb), + nonce.rlp_rlc(cb) + + 214.expr() * randomness_raised_to_22 + + 148.expr() * randomness_raised_to_21 + // + nonce.randomness_raised_to_rlp_length(cb) + // * ((0xc0.expr() + address_rlp_length + nonce.rlp_length()) + // * randomness_raised_to_21 + // + 0x94.expr() * randomness_raised_to_20 + // + caller_address.expr()), ); cb.require_equal( "for CREATE, keccak input length is rlp([address, nonce]).len()", @@ -718,7 +721,8 @@ mod test { const CALLEE_ADDRESS: Address = Address::repeat_byte(0xff); lazy_static! { - static ref CALLER_ADDRESS: Address = address!("0x00bbccddee000000000000000000000000002400"); + // static ref CALLER_ADDRESS: Address = address!("0x00bbccddee000000000000000000000000002400"); + static ref CALLER_ADDRESS: Address = Address::zero(); } fn callee_bytecode(is_return: bool, offset: u64, length: u64) -> Bytecode { From 0c124e30c9f328a6f707b8c36e6f9793f909c44d Mon Sep 17 00:00:00 2001 From: Mason Liang Date: Sun, 25 Dec 2022 01:49:44 -0500 Subject: [PATCH 50/69] wip --- .../src/evm_circuit/execution/create.rs | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/zkevm-circuits/src/evm_circuit/execution/create.rs b/zkevm-circuits/src/evm_circuit/execution/create.rs index e21b0aa765..ed50e189ee 100644 --- a/zkevm-circuits/src/evm_circuit/execution/create.rs +++ b/zkevm-circuits/src/evm_circuit/execution/create.rs @@ -290,8 +290,8 @@ impl ExecutionGadget for CreateGadget { "for CREATE, keccak input is rlp([address, nonce])", keccak_input.expr(), nonce.rlp_rlc(cb) - + 214.expr() * randomness_raised_to_22 - + 148.expr() * randomness_raised_to_21 + + nonce.randomness_raised_to_rlp_length(cb) * (214.expr() * randomness_raised_to_21 + + 148.expr() * randomness_raised_to_20) // + nonce.randomness_raised_to_rlp_length(cb) // * ((0xc0.expr() + address_rlp_length + nonce.rlp_length()) // * randomness_raised_to_21 @@ -687,7 +687,7 @@ impl RlpU64Gadget { not::expr(self.most_significant_byte_is_zero.expr()), ]), self.value(), - (0x80.expr() + self.n_bytes_nonce()) * self.randomness_raised_to_rlp_length(cb) + (0x80.expr() + self.n_bytes_nonce()) * self.randomness_raised_to_bytes_length(cb) + self.bytes.expr(), ) } @@ -695,7 +695,19 @@ impl RlpU64Gadget { fn randomness_raised_to_rlp_length(&self, cb: &ConstraintBuilder) -> Expression { let powers_of_randomness = cb.power_of_randomness(); select::expr( - self.is_less_than_128.expr(), + and::expr(&[ + self.is_less_than_128.expr(), + not::expr(self.most_significant_byte_is_zero.expr()), + ]), + powers_of_randomness[0].clone(), + powers_of_randomness[0].clone() * self.randomness_raised_to_bytes_length(cb), + ) + } + + fn randomness_raised_to_bytes_length(&self, cb: &ConstraintBuilder) -> Expression { + let powers_of_randomness = cb.power_of_randomness(); + select::expr( + self.most_significant_byte_is_zero.expr(), 1.expr(), sum::expr( self.is_most_significant_byte From 26b1a5313442bb70eda65ce3d1e63c33ee2b34bc Mon Sep 17 00:00:00 2001 From: Mason Liang Date: Sun, 25 Dec 2022 09:33:32 -0500 Subject: [PATCH 51/69] wip --- .../src/evm_circuit/execution/create.rs | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/zkevm-circuits/src/evm_circuit/execution/create.rs b/zkevm-circuits/src/evm_circuit/execution/create.rs index ed50e189ee..fb394acc9f 100644 --- a/zkevm-circuits/src/evm_circuit/execution/create.rs +++ b/zkevm-circuits/src/evm_circuit/execution/create.rs @@ -687,24 +687,22 @@ impl RlpU64Gadget { not::expr(self.most_significant_byte_is_zero.expr()), ]), self.value(), - (0x80.expr() + self.n_bytes_nonce()) * self.randomness_raised_to_bytes_length(cb) + (0x80.expr() + self.n_bytes_nonce()) * self.randomness_raised_n_bytes_nonce(cb) + self.bytes.expr(), ) } fn randomness_raised_to_rlp_length(&self, cb: &ConstraintBuilder) -> Expression { let powers_of_randomness = cb.power_of_randomness(); - select::expr( - and::expr(&[ + powers_of_randomness[0].clone() + * select::expr( self.is_less_than_128.expr(), - not::expr(self.most_significant_byte_is_zero.expr()), - ]), - powers_of_randomness[0].clone(), - powers_of_randomness[0].clone() * self.randomness_raised_to_bytes_length(cb), - ) + 1.expr(), + self.randomness_raised_n_bytes_nonce(cb), + ) } - fn randomness_raised_to_bytes_length(&self, cb: &ConstraintBuilder) -> Expression { + fn randomness_raised_n_bytes_nonce(&self, cb: &ConstraintBuilder) -> Expression { let powers_of_randomness = cb.power_of_randomness(); select::expr( self.most_significant_byte_is_zero.expr(), From ee32bed8205acd2cd940d52bddca1602850b86c3 Mon Sep 17 00:00:00 2001 From: Mason Liang Date: Sun, 25 Dec 2022 11:15:24 -0500 Subject: [PATCH 52/69] wip --- .../src/evm_circuit/execution/create.rs | 27 +++++-------------- 1 file changed, 7 insertions(+), 20 deletions(-) diff --git a/zkevm-circuits/src/evm_circuit/execution/create.rs b/zkevm-circuits/src/evm_circuit/execution/create.rs index fb394acc9f..7858011e37 100644 --- a/zkevm-circuits/src/evm_circuit/execution/create.rs +++ b/zkevm-circuits/src/evm_circuit/execution/create.rs @@ -290,13 +290,11 @@ impl ExecutionGadget for CreateGadget { "for CREATE, keccak input is rlp([address, nonce])", keccak_input.expr(), nonce.rlp_rlc(cb) - + nonce.randomness_raised_to_rlp_length(cb) * (214.expr() * randomness_raised_to_21 - + 148.expr() * randomness_raised_to_20) - // + nonce.randomness_raised_to_rlp_length(cb) - // * ((0xc0.expr() + address_rlp_length + nonce.rlp_length()) - // * randomness_raised_to_21 - // + 0x94.expr() * randomness_raised_to_20 - // + caller_address.expr()), + + nonce.randomness_raised_to_rlp_length(cb) + * (((0xc0.expr() + 21.expr() + nonce.rlp_length()) + * randomness_raised_to_21) + + (0x80 + 20).expr() * randomness_raised_to_20 + + caller_address.expr()), ); cb.require_equal( "for CREATE, keccak input length is rlp([address, nonce]).len()", @@ -731,8 +729,7 @@ mod test { const CALLEE_ADDRESS: Address = Address::repeat_byte(0xff); lazy_static! { - // static ref CALLER_ADDRESS: Address = address!("0x00bbccddee000000000000000000000000002400"); - static ref CALLER_ADDRESS: Address = Address::zero(); + static ref CALLER_ADDRESS: Address = address!("0x00bbccddee000000000000000000000000002400"); } fn callee_bytecode(is_return: bool, offset: u64, length: u64) -> Bytecode { @@ -1028,17 +1025,7 @@ mod test { #[test] fn create2_really_create() { - // for nonce in [0, 1, 127, 128, 255, 256, 0x100] { - // let mut stream = rlp::RlpStream::new(); - // stream.begin_list(2); - // stream.append(&*CALLER_ADDRESS); - // stream.append(&Word::from(nonce)); - // let x = stream.out().to_vec(); - // - // dbg!(nonce, x.len(), x); - // } - - for nonce in [1, 0, 1, 0xff, 0x100] { + for nonce in [1, 0, 1, 0xff, 0x100, 0x1000000] { dbg!(nonce); let initializer = callee_bytecode(true, 0, 10).code(); From cab77db159930af00a780a36c7572a63d8c9e1a3 Mon Sep 17 00:00:00 2001 From: Mason Liang Date: Sun, 25 Dec 2022 14:19:07 -0500 Subject: [PATCH 53/69] Re-add gas constraint --- zkevm-circuits/src/evm_circuit/execution/create.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/zkevm-circuits/src/evm_circuit/execution/create.rs b/zkevm-circuits/src/evm_circuit/execution/create.rs index 7858011e37..20f4fbe210 100644 --- a/zkevm-circuits/src/evm_circuit/execution/create.rs +++ b/zkevm-circuits/src/evm_circuit/execution/create.rs @@ -197,7 +197,7 @@ impl ExecutionGadget for CreateGadget { let gas_cost = GasCost::CREATE.expr() + memory_expansion.gas_cost() + keccak_gas_cost; let gas_remaining = cb.curr.state.gas_left.expr() - gas_cost; let gas_left = ConstantDivisionGadget::construct(cb, gas_remaining.clone(), 64); - let _callee_gas_left = gas_remaining - gas_left.quotient(); + let callee_gas_left = gas_remaining - gas_left.quotient(); for (field_tag, value) in [ ( CallContextFieldTag::ProgramCounter, @@ -250,8 +250,7 @@ impl ExecutionGadget for CreateGadget { is_root: To(false.expr()), is_create: To(true.expr()), code_hash: To(code_hash.expr()), - // gas_left: To(callee_gas_left), - gas_left: Any, + gas_left: To(callee_gas_left), reversible_write_counter: To(3.expr()), ..StepStateTransition::new_context() }); From d6fb607bf4e50bdbaeb178dc5759e915f31a9b4f Mon Sep 17 00:00:00 2001 From: Mason Liang Date: Sun, 25 Dec 2022 17:27:32 -0500 Subject: [PATCH 54/69] undo --- zkevm-circuits/src/evm_circuit/execution/return_revert.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/zkevm-circuits/src/evm_circuit/execution/return_revert.rs b/zkevm-circuits/src/evm_circuit/execution/return_revert.rs index be4fce0d59..d123c338a1 100644 --- a/zkevm-circuits/src/evm_circuit/execution/return_revert.rs +++ b/zkevm-circuits/src/evm_circuit/execution/return_revert.rs @@ -508,7 +508,9 @@ mod test { #[test] fn test_return_nonroot_create() { let test_parameters = [(0, 0), (0, 10), (300, 20), (1000, 0)]; - for ((offset, length), is_return) in test_parameters.iter().cartesian_product(&[false]) { + for ((offset, length), is_return) in + test_parameters.iter().cartesian_product(&[true, false]) + { let initializer = callee_bytecode(*is_return, *offset, *length).code(); let root_code = bytecode! { From a1dd2c43e61560f69f1d23a7cd7838259b7c4ed3 Mon Sep 17 00:00:00 2001 From: Mason Liang Date: Sun, 25 Dec 2022 17:55:04 -0500 Subject: [PATCH 55/69] cleanup --- bus-mapping/src/circuit_input_builder/input_state_ref.rs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/bus-mapping/src/circuit_input_builder/input_state_ref.rs b/bus-mapping/src/circuit_input_builder/input_state_ref.rs index e66a3aba19..2071897846 100644 --- a/bus-mapping/src/circuit_input_builder/input_state_ref.rs +++ b/bus-mapping/src/circuit_input_builder/input_state_ref.rs @@ -162,20 +162,19 @@ impl<'a> CircuitInputStateRef<'a> { /// This method should be used in `Opcode::gen_associated_ops` instead of /// `push_op` when the operation is `RW::WRITE` and it can be reverted (for /// example, a write [`StorageOp`](crate::operation::StorageOp)). - pub fn push_op_reversible( + pub fn push_op_reversible( &mut self, step: &mut ExecStep, rw: RW, op: T, ) -> Result<(), Error> { - dbg!(op.clone()); if matches!(rw, RW::WRITE) { self.apply_op(&op.clone().into_enum()); } let op_ref = self.block.container.insert(Operation::new_reversible( self.block_ctx.rwc.inc_pre(), rw, - op.clone(), + op, )); step.bus_mapping_instance.push(op_ref); @@ -184,7 +183,6 @@ impl<'a> CircuitInputStateRef<'a> { // Add the operation into reversible_ops if this call is not persistent if !self.call()?.is_persistent { - // dbg!(op.clone()); self.tx_ctx .reversion_groups .last_mut() @@ -590,7 +588,6 @@ impl<'a> CircuitInputStateRef<'a> { let caller = self.call()?; let caller_ctx = self.call_ctx()?; - // dbg!(caller.address); let (caller_address, address, value) = match kind { CallKind::Call => ( caller.address, @@ -658,7 +655,7 @@ impl<'a> CircuitInputStateRef<'a> { is_root: false, is_persistent: caller.is_persistent && is_success, is_success, - rw_counter_end_of_reversion: 0, // here???? + rw_counter_end_of_reversion: 0, caller_address, address, code_source, From a99c3d2d86fb6d03de81c1c81630803cde0906a4 Mon Sep 17 00:00:00 2001 From: Mason Liang Date: Sun, 25 Dec 2022 17:56:29 -0500 Subject: [PATCH 56/69] Remove dummy --- bus-mapping/src/evm/opcodes.rs | 12 +++--------- bus-mapping/src/evm/opcodes/create.rs | 4 ++-- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/bus-mapping/src/evm/opcodes.rs b/bus-mapping/src/evm/opcodes.rs index 0e3253d3c1..d4fa009783 100644 --- a/bus-mapping/src/evm/opcodes.rs +++ b/bus-mapping/src/evm/opcodes.rs @@ -70,7 +70,7 @@ use callop::CallOpcode; use callvalue::Callvalue; use codecopy::Codecopy; use codesize::Codesize; -use create::DummyCreate; +use create::Create; use dup::Dup; use error_invalid_jump::ErrorInvalidJump; use error_oog_call::OOGCall; @@ -234,19 +234,13 @@ fn fn_gen_associated_ops(opcode_id: &OpcodeId) -> FnGenAssociatedOps { OpcodeId::LOG4 => Log::gen_associated_ops, OpcodeId::CALL | OpcodeId::CALLCODE => CallOpcode::<7>::gen_associated_ops, OpcodeId::DELEGATECALL | OpcodeId::STATICCALL => CallOpcode::<6>::gen_associated_ops, + OpcodeId::CREATE => Create::::gen_associated_ops, + OpcodeId::CREATE2 => Create::::gen_associated_ops, OpcodeId::RETURN | OpcodeId::REVERT => ReturnRevert::gen_associated_ops, OpcodeId::SELFDESTRUCT => { warn!("Using dummy gen_selfdestruct_ops for opcode SELFDESTRUCT"); DummySelfDestruct::gen_associated_ops } - OpcodeId::CREATE => { - warn!("Using dummy gen_create_ops for opcode {:?}", opcode_id); - DummyCreate::::gen_associated_ops - } - OpcodeId::CREATE2 => { - warn!("Using dummy gen_create_ops for opcode {:?}", opcode_id); - DummyCreate::::gen_associated_ops - } _ => { warn!("Using dummy gen_associated_ops for opcode {:?}", opcode_id); Dummy::gen_associated_ops diff --git a/bus-mapping/src/evm/opcodes/create.rs b/bus-mapping/src/evm/opcodes/create.rs index fdee424d0b..0d1e2f88da 100644 --- a/bus-mapping/src/evm/opcodes/create.rs +++ b/bus-mapping/src/evm/opcodes/create.rs @@ -13,9 +13,9 @@ use eth_types::{ use ethers_core::utils::{get_create2_address, keccak256, rlp}; #[derive(Debug, Copy, Clone)] -pub struct DummyCreate; +pub struct Create; -impl Opcode for DummyCreate { +impl Opcode for Create { fn gen_associated_ops( state: &mut CircuitInputStateRef, geth_steps: &[GethExecStep], From 204f670967b37ff5b083ab61126f4e0be93af600 Mon Sep 17 00:00:00 2001 From: Mason Liang Date: Sun, 25 Dec 2022 17:58:37 -0500 Subject: [PATCH 57/69] cleanup --- bus-mapping/src/evm/opcodes/create.rs | 1 - .../src/evm_circuit/execution/create.rs | 22 ------------------- 2 files changed, 23 deletions(-) diff --git a/bus-mapping/src/evm/opcodes/create.rs b/bus-mapping/src/evm/opcodes/create.rs index 0d1e2f88da..00a4005379 100644 --- a/bus-mapping/src/evm/opcodes/create.rs +++ b/bus-mapping/src/evm/opcodes/create.rs @@ -205,7 +205,6 @@ impl Opcode for Create { let keccak_input = if IS_CREATE2 { let salt = geth_step.stack.nth_last(3)?; - dbg!(salt); assert_eq!( address, get_create2_address( diff --git a/zkevm-circuits/src/evm_circuit/execution/create.rs b/zkevm-circuits/src/evm_circuit/execution/create.rs index 20f4fbe210..ce149ab190 100644 --- a/zkevm-circuits/src/evm_circuit/execution/create.rs +++ b/zkevm-circuits/src/evm_circuit/execution/create.rs @@ -525,13 +525,11 @@ impl ExecutionGadget for CreateGadget { let mut keccak_output = keccak256(&keccak_input); keccak_output.reverse(); - dbg!(keccak_input.clone()); self.keccak_input.assign( region, offset, Value::known(rlc::value(keccak_input.iter().rev(), block.randomness)), )?; - dbg!(keccak_input.len()); self.keccak_input_length.assign( region, offset, @@ -540,21 +538,6 @@ impl ExecutionGadget for CreateGadget { self.keccak_output .assign(region, offset, Some(keccak_output))?; - // let nonce_le_bytes = caller_nonce.to_le_bytes(); - // let most_significant_nonce_byte_index = - // (u64::from(u64::BITS + 1 - caller_nonce.leading_zeros()) + 7) / 8; - // for i in 0..N_BYTES_U64 { - // self.most_significant_nonce_byte_selectors[i].assign( - // region, - // offset, - // Value::known( - // (u64::try_from(i).unwrap() == most_significant_nonce_byte_index) - // .to_scalar() - // .unwrap(), - // ), - // )?; - // } - Ok(()) } } @@ -623,16 +606,12 @@ impl RlpU64Gadget { offset: usize, value: u64, ) -> Result<(), Error> { - // dbg!(value); - let bytes = value.to_le_bytes(); - // dbg!(bytes.clone()); let most_significant_byte_index = bytes .iter() .rev() .position(|byte| *byte != 0) .map(|i| N_BYTES_U64 - i - 1); - // dbg!(most_significant_byte_index); self.most_significant_byte_is_zero.assign( region, offset, @@ -1025,7 +1004,6 @@ mod test { #[test] fn create2_really_create() { for nonce in [1, 0, 1, 0xff, 0x100, 0x1000000] { - dbg!(nonce); let initializer = callee_bytecode(true, 0, 10).code(); let root_code = bytecode! { From 47171640ca50c0cbd80d04c714856bb0f60a826e Mon Sep 17 00:00:00 2001 From: Mason Liang Date: Sun, 25 Dec 2022 18:05:10 -0500 Subject: [PATCH 58/69] cleanup --- .../src/evm_circuit/execution/create.rs | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/zkevm-circuits/src/evm_circuit/execution/create.rs b/zkevm-circuits/src/evm_circuit/execution/create.rs index ce149ab190..4a6769d0e0 100644 --- a/zkevm-circuits/src/evm_circuit/execution/create.rs +++ b/zkevm-circuits/src/evm_circuit/execution/create.rs @@ -11,7 +11,7 @@ use crate::{ common_gadget::TransferGadget, constraint_builder::{ ConstraintBuilder, ReversionInfo, StepStateTransition, - Transition::{Any, Delta, To}, + Transition::{Delta, To}, }, from_bytes, math_gadget::{ConstantDivisionGadget, IsZeroGadget}, @@ -96,7 +96,7 @@ impl ExecutionGadget for CreateGadget { cb.stack_pop(value.expr()); let initialization_code = MemoryAddressGadget::construct_2(cb); - cb.stack_pop(initialization_code.offset()); // are these rlc or not? + cb.stack_pop(initialization_code.offset()); cb.stack_pop(initialization_code.length()); let salt = cb.condition(is_create2.expr(), |cb| { @@ -182,12 +182,6 @@ impl ExecutionGadget for CreateGadget { let memory_expansion = MemoryExpansionGadget::construct(cb, [initialization_code.address()]); - let stack_pointer_delta = 2.expr() + is_create2.expr(); - - // EIP-150: all but one 64th of the caller's gas is sent to the callee. - // let caller_gas_left = - // (geth_step.gas.0 - geth_step.gas_cost.0 - memory_expansion_gas_cost) / 64; - let initialization_code_word_size = ConstantDivisionGadget::construct(cb, initialization_code.length() + 31.expr(), 32); let keccak_gas_cost = GasCost::COPY_SHA3.expr() @@ -205,7 +199,7 @@ impl ExecutionGadget for CreateGadget { ), ( CallContextFieldTag::StackPointer, - cb.curr.state.stack_pointer.expr() + stack_pointer_delta, + cb.curr.state.stack_pointer.expr() + 2.expr() + is_create2.expr(), ), (CallContextFieldTag::GasLeft, gas_left.quotient()), ( @@ -259,7 +253,6 @@ impl ExecutionGadget for CreateGadget { let keccak_input_length = cb.query_cell(); cb.condition(is_create2.expr(), |cb| { // TODO: some comments here explaining what's going on.... - // is the power of randomness in reverse order??? that seems impossible let randomness_raised_to_16 = cb.power_of_randomness()[15].clone(); let randomness_raised_to_32 = randomness_raised_to_16.clone().square(); let randomness_raised_to_64 = randomness_raised_to_32.clone().square(); @@ -283,8 +276,6 @@ impl ExecutionGadget for CreateGadget { cb.condition(not::expr(is_create2.expr()), |cb| { let randomness_raised_to_20 = cb.power_of_randomness()[19].clone(); let randomness_raised_to_21 = cb.power_of_randomness()[20].clone(); - let randomness_raised_to_22 = cb.power_of_randomness()[21].clone(); - // let address_rlp_length = 21.expr(); cb.require_equal( "for CREATE, keccak input is rlp([address, nonce])", keccak_input.expr(), @@ -700,7 +691,7 @@ mod test { address, bytecode, evm_types::OpcodeId, geth_types::Account, Address, Bytecode, ToWord, Word, }; - use ethers_core::utils::rlp; + use itertools::Itertools; use lazy_static::lazy_static; use mock::{eth, TestContext}; From 3518929bfe994bf358bfe57b04cfbdeccf04918d Mon Sep 17 00:00:00 2001 From: Mason Liang Date: Mon, 26 Dec 2022 12:52:15 -0500 Subject: [PATCH 59/69] Remove redundant address cells --- .../src/evm_circuit/execution/create.rs | 55 ++++++------------- 1 file changed, 18 insertions(+), 37 deletions(-) diff --git a/zkevm-circuits/src/evm_circuit/execution/create.rs b/zkevm-circuits/src/evm_circuit/execution/create.rs index 4a6769d0e0..ec46657102 100644 --- a/zkevm-circuits/src/evm_circuit/execution/create.rs +++ b/zkevm-circuits/src/evm_circuit/execution/create.rs @@ -41,9 +41,7 @@ pub(crate) struct CreateGadget { value: Word, salt: Word, - new_address: RandomLinearCombination, - // tx access list for new address tx_id: Cell, reversion_info: ReversionInfo, was_warm: Cell, @@ -104,9 +102,17 @@ impl ExecutionGadget for CreateGadget { cb.stack_pop(salt.expr()); salt }); - let new_address = cb.query_rlc(); + + let keccak_output = cb.query_word(); + let new_address_rlc = rlc::expr( + &keccak_output.cells[..20] + .iter() + .map(Expr::expr) + .collect::>(), + cb.power_of_randomness(), + ); let callee_is_success = cb.query_bool(); - cb.stack_push(callee_is_success.expr() * new_address.expr()); + cb.stack_push(callee_is_success.expr() * new_address_rlc); let code_hash = cb.query_cell(); cb.condition(initialization_code.has_length(), |cb| { @@ -135,11 +141,12 @@ impl ExecutionGadget for CreateGadget { }); let tx_id = cb.call_context(None, CallContextFieldTag::TxId); + let new_address = from_bytes::expr(&keccak_output.cells[..20]); let mut reversion_info = cb.reversion_info_read(None); let was_warm = cb.query_bool(); cb.account_access_list_write( tx_id.expr(), - from_bytes::expr(&new_address.cells), + new_address.clone(), 1.expr(), was_warm.expr(), Some(&mut reversion_info), @@ -164,7 +171,7 @@ impl ExecutionGadget for CreateGadget { let mut callee_reversion_info = cb.reversion_info_write(Some(callee_call_id.expr())); cb.account_write( - from_bytes::expr(&new_address.cells), + new_address.clone(), AccountFieldTag::Nonce, 1.expr(), 0.expr(), @@ -174,7 +181,7 @@ impl ExecutionGadget for CreateGadget { let transfer = TransferGadget::construct( cb, from_bytes::expr(&caller_address.cells), - from_bytes::expr(&new_address.cells), + new_address.clone(), value.clone(), &mut callee_reversion_info, ); @@ -226,10 +233,7 @@ impl ExecutionGadget for CreateGadget { CallContextFieldTag::CallerAddress, from_bytes::expr(&caller_address.cells), ), - ( - CallContextFieldTag::CalleeAddress, - from_bytes::expr(&new_address.cells), - ), + (CallContextFieldTag::CalleeAddress, new_address), ( CallContextFieldTag::RwCounterEndOfReversion, callee_reversion_info.rw_counter_end_of_reversion(), @@ -293,25 +297,12 @@ impl ExecutionGadget for CreateGadget { ); }); - let keccak_output = cb.query_word(); cb.keccak_table_lookup( keccak_input.expr(), keccak_input_length.expr(), keccak_output.expr(), ); - cb.require_equal( - "324124asfr", - new_address.expr(), - rlc::expr( - &keccak_output.cells[..20] - .iter() - .map(Expr::expr) - .collect::>(), - cb.power_of_randomness(), - ), - ); - Self { opcode, is_create2, @@ -320,7 +311,6 @@ impl ExecutionGadget for CreateGadget { was_warm, value, salt, - new_address, caller_address, nonce, callee_reversion_info, @@ -365,9 +355,6 @@ impl ExecutionGadget for CreateGadget { U256::zero() }; - let copy_rw_increase = initialization_code_length.as_usize(); - // dopy lookup here advances rw_counter by initialization_code_length; - let values: Vec<_> = (4 + usize::from(is_create2) ..4 + usize::from(is_create2) + initialization_code_length.as_usize()) .map(|i| block.rws[step.rw_indices[i]].memory_value()) @@ -379,11 +366,6 @@ impl ExecutionGadget for CreateGadget { self.code_hash .assign(region, offset, Value::known(code_hash_rlc))?; - let tx_access_rw = - block.rws[step.rw_indices[7 + usize::from(is_create2) + copy_rw_increase]]; - - let new_address = tx_access_rw.address().expect("asdfawefasdf"); - for (word, assignment) in [(&self.value, value), (&self.salt, salt)] { word.assign(region, offset, Some(assignment.to_le_bytes()))?; } @@ -395,10 +377,6 @@ impl ExecutionGadget for CreateGadget { block.randomness, )?; - let mut bytes = new_address.to_fixed_bytes(); - bytes.reverse(); - self.new_address.assign(region, offset, Some(bytes))?; - self.tx_id .assign(region, offset, Value::known(tx.id.to_scalar().unwrap()))?; @@ -409,6 +387,9 @@ impl ExecutionGadget for CreateGadget { call.is_persistent, )?; + let copy_rw_increase = initialization_code_length.as_usize(); + let tx_access_rw = + block.rws[step.rw_indices[7 + usize::from(is_create2) + copy_rw_increase]]; self.was_warm.assign( region, offset, From 19bb1d8cfe89ca8f2fd1333db585b612d628dd56 Mon Sep 17 00:00:00 2001 From: Mason Liang Date: Thu, 5 Jan 2023 12:38:03 -0500 Subject: [PATCH 60/69] Simplify tests --- .../src/evm_circuit/execution/create.rs | 330 +++--------------- 1 file changed, 40 insertions(+), 290 deletions(-) diff --git a/zkevm-circuits/src/evm_circuit/execution/create.rs b/zkevm-circuits/src/evm_circuit/execution/create.rs index ec46657102..0a8291e469 100644 --- a/zkevm-circuits/src/evm_circuit/execution/create.rs +++ b/zkevm-circuits/src/evm_circuit/execution/create.rs @@ -669,8 +669,7 @@ impl RlpU64Gadget { mod test { use crate::test_util::run_test_circuits; use eth_types::{ - address, bytecode, evm_types::OpcodeId, geth_types::Account, Address, Bytecode, ToWord, - Word, + address, bytecode, evm_types::OpcodeId, geth_types::Account, Address, Bytecode, Word, }; use itertools::Itertools; @@ -682,7 +681,8 @@ mod test { static ref CALLER_ADDRESS: Address = address!("0x00bbccddee000000000000000000000000002400"); } - fn callee_bytecode(is_return: bool, offset: u64, length: u64) -> Bytecode { + // RETURN or REVERT with data of [0x60; 5] + fn initialization_bytecode(is_success: bool) -> Bytecode { let memory_bytes = [0x60; 10]; let memory_address = 0; let memory_value = Word::from_big_endian(&memory_bytes); @@ -690,10 +690,10 @@ mod test { PUSH10(memory_value) PUSH1(memory_address) MSTORE - PUSH2(length) - PUSH2(32u64 - u64::try_from(memory_bytes.len()).unwrap() + offset) + PUSH2(5) + PUSH2(32u64 - u64::try_from(memory_bytes.len()).unwrap()) }; - code.write_op(if is_return { + code.write_op(if is_success { OpcodeId::RETURN } else { OpcodeId::REVERT @@ -701,299 +701,49 @@ mod test { code } - fn caller_bytecode(return_data_offset: u64, return_data_length: u64) -> Bytecode { - bytecode! { - PUSH32(return_data_length) - PUSH32(return_data_offset) - PUSH32(0) // call data length - PUSH32(0) // call data offset - PUSH32(0) // value - PUSH32(CALLEE_ADDRESS.to_word()) - PUSH32(4000) // gas - CALL - STOP + fn creater_bytecode(is_success: bool, is_create2: bool, is_persistent: bool) -> Bytecode { + let initialization_bytes = initialization_bytecode(is_success).code(); + let mut code = bytecode! { + PUSH32(Word::from_big_endian(&initialization_bytes)) + PUSH1(0) + MSTORE + }; + if is_create2 { + code.append(&bytecode! {PUSH1(45)}); // salt; } - } - - #[test] - fn mason2() { - let test_parameters = [(0, 0), (0, 10), (300, 20), (1000, 0)]; - for ((offset, length), is_return) in test_parameters.iter().cartesian_product(&[true]) - // FIX MEEEEEE there's an issue when the init call reverts. - { - let initializer = callee_bytecode(*is_return, *offset, *length).code(); - - let root_code = bytecode! { - PUSH32(Word::from_big_endian(&initializer)) + code.append(&bytecode! { + PUSH1(initialization_bytes.len()) // size + PUSH1(32 - initialization_bytes.len()) // value + PUSH1(10) // value + }); + code.write_op(if is_create2 { + OpcodeId::CREATE2 + } else { + OpcodeId::CREATE + }); + if is_persistent { + code.append(&bytecode! { PUSH1(0) - MSTORE - - PUSH1(45) // salt - PUSH1(initializer.len()) // size - PUSH1(32 - initializer.len()) // offset - PUSH1(0) // value - - CREATE2 - }; - - let caller = Account { - address: *CALLER_ADDRESS, - code: root_code.into(), - nonce: Word::one(), - balance: eth(10), - ..Default::default() - }; - - let test_context = TestContext::<2, 1>::new( - None, - |accs| { - accs[0] - .address(address!("0x000000000000000000000000000000000000cafe")) - .balance(eth(10)); - accs[1].account(&caller); - }, - |mut txs, accs| { - txs[0] - .from(accs[0].address) - .to(accs[1].address) - .gas(100000u64.into()); - }, - |block, _| block, - ) - .unwrap(); - - assert_eq!( - run_test_circuits(test_context, None), - Ok(()), - "(offset, length, is_return) = {:?}", - (*offset, *length, *is_return), - ); - } - } - - #[test] - fn test_create2() { - let test_parameters = [(0, 0), (0, 10), (300, 20), (1000, 0)]; - for ((offset, length), is_return) in test_parameters.iter().cartesian_product(&[true]) { - let initializer = callee_bytecode(*is_return, *offset, *length).code(); - - let root_code = bytecode! { - PUSH32(Word::from_big_endian(&initializer)) PUSH1(0) - MSTORE - - PUSH1(34) // salt - PUSH1(initializer.len()) // size - PUSH1(32 - initializer.len()) // offset - PUSH1(12) // value - - CREATE2 - }; - - let caller = Account { - address: *CALLER_ADDRESS, - code: root_code.into(), - nonce: Word::one(), - balance: eth(10), - ..Default::default() - }; - - let test_context = TestContext::<2, 1>::new( - None, - |accs| { - accs[0] - .address(address!("0x000000000000000000000000000000000000cafe")) - .balance(eth(10)); - accs[1].account(&caller); - }, - |mut txs, accs| { - txs[0] - .from(accs[0].address) - .to(accs[1].address) - .gas(100000u64.into()); - }, - |block, _| block, - ) - .unwrap(); - - assert_eq!( - run_test_circuits(test_context, None), - Ok(()), - "(offset, length, is_return) = {:?}", - (*offset, *length, *is_return), - ); + REVERT + }); } + code } #[test] - fn mason() { - // Test the case where the initialization call is successful, but the CREATE - // call is reverted. - let initializer = callee_bytecode(true, 0, 10).code(); - - let root_code = bytecode! { - PUSH32(Word::from_big_endian(&initializer)) - PUSH1(0) - MSTORE - - PUSH1(initializer.len()) // size - PUSH1(32 - initializer.len()) // offset - PUSH1(0) // value - - CREATE - PUSH1(0) - PUSH1(0) - REVERT - }; - - let caller = Account { - address: *CALLER_ADDRESS, - code: root_code.into(), - nonce: Word::one(), - balance: eth(10), - ..Default::default() - }; - - let test_context = TestContext::<2, 1>::new( - None, - |accs| { - accs[0] - .address(address!("0x000000000000000000000000000000000000cafe")) - .balance(eth(10)); - accs[1].account(&caller); - }, - |mut txs, accs| { - txs[0] - .from(accs[0].address) - .to(accs[1].address) - .gas(100000u64.into()); - }, - |block, _| block, - ) - .unwrap(); - - assert_eq!(run_test_circuits(test_context, None), Ok(()),); - } - - #[test] - fn create() { - // Test the case where the initialization call is successful, but the CREATE - // call is reverted. - let initializer = callee_bytecode(true, 0, 10).code(); - - let root_code = bytecode! { - PUSH32(Word::from_big_endian(&initializer)) - PUSH1(0) - MSTORE - - PUSH1(initializer.len()) // size - PUSH1(32 - initializer.len()) // offset - PUSH1(0) // value - - CREATE - PUSH1(0) - PUSH1(0) - REVERT - }; - - let caller = Account { - address: *CALLER_ADDRESS, - code: root_code.into(), - nonce: Word::one(), - balance: eth(10), - ..Default::default() - }; - - let test_context = TestContext::<2, 1>::new( - None, - |accs| { - accs[0] - .address(address!("0x000000000000000000000000000000000000cafe")) - .balance(eth(10)); - accs[1].account(&caller); - }, - |mut txs, accs| { - txs[0] - .from(accs[0].address) - .to(accs[1].address) - .gas(100000u64.into()); - }, - |block, _| block, - ) - .unwrap(); - - assert_eq!(run_test_circuits(test_context, None), Ok(()),); - } - - #[test] - fn create2() { - // Test the case where the initialization call is successful, but the CREATE - // call is reverted. - let initializer = callee_bytecode(true, 0, 10).code(); - - let root_code = bytecode! { - PUSH32(Word::from_big_endian(&initializer)) - PUSH1(0) - MSTORE - - PUSH1(initializer.len()) // size - PUSH1(32 - initializer.len()) // offset - PUSH1(0) // value - PUSH1(56) // salt - - CREATE2 - }; - - let caller = Account { - address: *CALLER_ADDRESS, - code: root_code.into(), - nonce: Word::one(), - balance: eth(10), - ..Default::default() - }; - - let test_context = TestContext::<2, 1>::new( - None, - |accs| { - accs[0] - .address(address!("0x000000000000000000000000000000000000cafe")) - .balance(eth(10)); - accs[1].account(&caller); - }, - |mut txs, accs| { - txs[0] - .from(accs[0].address) - .to(accs[1].address) - .gas(100000u64.into()); - }, - |block, _| block, - ) - .unwrap(); - - assert_eq!(run_test_circuits(test_context, None), Ok(()),); - } - - #[test] - fn create2_really_create() { - for nonce in [1, 0, 1, 0xff, 0x100, 0x1000000] { - let initializer = callee_bytecode(true, 0, 10).code(); - - let root_code = bytecode! { - PUSH32(Word::from_big_endian(&initializer)) - PUSH1(0) - MSTORE - - PUSH1(initializer.len()) // size - PUSH1(32 - initializer.len()) // offset - PUSH1(0) // value - - CREATE - }; + fn test_create() { + for ((is_success, is_create2), is_persistent) in [true, false] + .iter() + .cartesian_product(&[true, false]) + .cartesian_product(&[true, false]) + { + let root_code = creater_bytecode(*is_success, *is_create2, *is_persistent); let caller = Account { address: *CALLER_ADDRESS, code: root_code.into(), - nonce: nonce.into(), + nonce: Word::one(), balance: eth(10), ..Default::default() }; @@ -1019,8 +769,8 @@ mod test { assert_eq!( run_test_circuits(test_context, None), Ok(()), - "nonce = {}", - nonce + "(is_success, is_create2, is_persistent) = {:?}", + (*is_success, *is_create2, *is_persistent), ); } } From 170ec3b34aae23cf60b719b4e985f5fe4f9ea287 Mon Sep 17 00:00:00 2001 From: Mason Liang Date: Thu, 5 Jan 2023 16:39:28 -0500 Subject: [PATCH 61/69] Add rlp nonce test --- .../src/evm_circuit/execution/create.rs | 62 ++++++++++++------- 1 file changed, 41 insertions(+), 21 deletions(-) diff --git a/zkevm-circuits/src/evm_circuit/execution/create.rs b/zkevm-circuits/src/evm_circuit/execution/create.rs index 0a8291e469..49b1a75a0a 100644 --- a/zkevm-circuits/src/evm_circuit/execution/create.rs +++ b/zkevm-circuits/src/evm_circuit/execution/create.rs @@ -731,6 +731,26 @@ mod test { code } + fn test_context(caller: Account) -> TestContext<2, 1> { + TestContext::new( + None, + |accs| { + accs[0] + .address(address!("0x000000000000000000000000000000000000cafe")) + .balance(eth(10)); + accs[1].account(&caller); + }, + |mut txs, accs| { + txs[0] + .from(accs[0].address) + .to(accs[1].address) + .gas(100000u64.into()); + }, + |block, _| block, + ) + .unwrap() + } + #[test] fn test_create() { for ((is_success, is_create2), is_persistent) in [true, false] @@ -739,7 +759,6 @@ mod test { .cartesian_product(&[true, false]) { let root_code = creater_bytecode(*is_success, *is_create2, *is_persistent); - let caller = Account { address: *CALLER_ADDRESS, code: root_code.into(), @@ -747,31 +766,32 @@ mod test { balance: eth(10), ..Default::default() }; - - let test_context = TestContext::<2, 1>::new( - None, - |accs| { - accs[0] - .address(address!("0x000000000000000000000000000000000000cafe")) - .balance(eth(10)); - accs[1].account(&caller); - }, - |mut txs, accs| { - txs[0] - .from(accs[0].address) - .to(accs[1].address) - .gas(100000u64.into()); - }, - |block, _| block, - ) - .unwrap(); - assert_eq!( - run_test_circuits(test_context, None), + run_test_circuits(test_context(caller), None), Ok(()), "(is_success, is_create2, is_persistent) = {:?}", (*is_success, *is_create2, *is_persistent), ); } } + + #[test] + fn test_create_rlp_nonce() { + for nonce in [0, 1, 255, 256, 0x10000, u64::MAX - 1] { + dbg!(nonce); + let caller = Account { + address: *CALLER_ADDRESS, + code: creater_bytecode(true, false, true).into(), + nonce: nonce.into(), + balance: eth(10), + ..Default::default() + }; + assert_eq!( + run_test_circuits(test_context(caller), None), + Ok(()), + "nonce = {:?}", + nonce, + ); + } + } } From 5a3617443498ab825bf4b9a1b6a2f596754519b1 Mon Sep 17 00:00:00 2001 From: Mason Liang Date: Fri, 6 Jan 2023 15:55:35 -0500 Subject: [PATCH 62/69] Handle case of empty initilization code --- bus-mapping/src/evm/opcodes/create.rs | 4 ++ .../src/evm_circuit/execution/create.rs | 53 +++++++++++++++---- .../src/evm_circuit/util/memory_gadget.rs | 8 +++ 3 files changed, 55 insertions(+), 10 deletions(-) diff --git a/bus-mapping/src/evm/opcodes/create.rs b/bus-mapping/src/evm/opcodes/create.rs index 00a4005379..4517cb1a6c 100644 --- a/bus-mapping/src/evm/opcodes/create.rs +++ b/bus-mapping/src/evm/opcodes/create.rs @@ -233,6 +233,10 @@ impl Opcode for Create { state.block.sha3_inputs.push(keccak_input); + if length == 0 { + state.handle_return(geth_step)?; + } + Ok(vec![exec_step]) } } diff --git a/zkevm-circuits/src/evm_circuit/execution/create.rs b/zkevm-circuits/src/evm_circuit/execution/create.rs index 49b1a75a0a..1211902f1d 100644 --- a/zkevm-circuits/src/evm_circuit/execution/create.rs +++ b/zkevm-circuits/src/evm_circuit/execution/create.rs @@ -94,8 +94,8 @@ impl ExecutionGadget for CreateGadget { cb.stack_pop(value.expr()); let initialization_code = MemoryAddressGadget::construct_2(cb); - cb.stack_pop(initialization_code.offset()); - cb.stack_pop(initialization_code.length()); + cb.stack_pop(initialization_code.offset_rlc()); + cb.stack_pop(initialization_code.length_rlc()); let salt = cb.condition(is_create2.expr(), |cb| { let salt = cb.query_word(); @@ -242,7 +242,7 @@ impl ExecutionGadget for CreateGadget { cb.call_context_lookup(true.expr(), Some(callee_call_id.expr()), field_tag, value); } - cb.require_step_state_transition(StepStateTransition { + cb.condition(initialization_code.has_length(), |cb| cb.require_step_state_transition(StepStateTransition { rw_counter: Delta(cb.rw_counter_offset()), call_id: To(callee_call_id.expr()), is_root: To(false.expr()), @@ -251,7 +251,22 @@ impl ExecutionGadget for CreateGadget { gas_left: To(callee_gas_left), reversible_write_counter: To(3.expr()), ..StepStateTransition::new_context() - }); + })); + + // cb.condition(not::expr(initialization_code.has_length()), |cb| cb.require_step_state_transition(StepStateTransition { + // rw_counter: Delta(cb.rw_counter_offset()), + // program_counter: Delta(1.expr()), + // stack_pointer: Delta(1.expr()), + // gas_left: To(callee_gas_left), + // reversible_write_counter: To(3.expr()), + // ..StepStateTransition::default() + // + // rw_counter: Delta(3.expr()), + // program_counter: Delta(1.expr()), + // stack_pointer: Delta(1.expr()), + // gas_left: Delta(-OpcodeId::MUL.constant_gas_cost().expr()), + // ..Default::default() + // }); let keccak_input = cb.query_cell(); let keccak_input_length = cb.query_cell(); @@ -701,8 +716,12 @@ mod test { code } - fn creater_bytecode(is_success: bool, is_create2: bool, is_persistent: bool) -> Bytecode { - let initialization_bytes = initialization_bytecode(is_success).code(); + fn creater_bytecode( + initialization_bytecode: Bytecode, + is_create2: bool, + is_persistent: bool, + ) -> Bytecode { + let initialization_bytes = initialization_bytecode.code(); let mut code = bytecode! { PUSH32(Word::from_big_endian(&initialization_bytes)) PUSH1(0) @@ -721,7 +740,7 @@ mod test { } else { OpcodeId::CREATE }); - if is_persistent { + if !is_persistent { code.append(&bytecode! { PUSH1(0) PUSH1(0) @@ -758,7 +777,8 @@ mod test { .cartesian_product(&[true, false]) .cartesian_product(&[true, false]) { - let root_code = creater_bytecode(*is_success, *is_create2, *is_persistent); + let initialization_code = initialization_bytecode(*is_success); + let root_code = creater_bytecode(initialization_code, *is_create2, *is_persistent); let caller = Account { address: *CALLER_ADDRESS, code: root_code.into(), @@ -778,10 +798,9 @@ mod test { #[test] fn test_create_rlp_nonce() { for nonce in [0, 1, 255, 256, 0x10000, u64::MAX - 1] { - dbg!(nonce); let caller = Account { address: *CALLER_ADDRESS, - code: creater_bytecode(true, false, true).into(), + code: creater_bytecode(initialization_bytecode(true), false, true).into(), nonce: nonce.into(), balance: eth(10), ..Default::default() @@ -794,4 +813,18 @@ mod test { ); } } + + #[test] + fn test_empty_initialization_code() { + for is_create2 in [true, false] { + let caller = Account { + address: *CALLER_ADDRESS, + code: creater_bytecode(vec![].into(), is_create2, true).into(), + nonce: 10.into(), + balance: eth(10), + ..Default::default() + }; + assert_eq!(run_test_circuits(test_context(caller), None), Ok(())); + } + } } diff --git a/zkevm-circuits/src/evm_circuit/util/memory_gadget.rs b/zkevm-circuits/src/evm_circuit/util/memory_gadget.rs index 1b3642da79..05add3ebf5 100644 --- a/zkevm-circuits/src/evm_circuit/util/memory_gadget.rs +++ b/zkevm-circuits/src/evm_circuit/util/memory_gadget.rs @@ -154,6 +154,14 @@ impl MemoryAddressGadget { self.has_length() * from_bytes::expr(&self.memory_offset_bytes.cells) } + pub(crate) fn offset_rlc(&self) -> Expression { + self.memory_offset.expr() + } + + pub(crate) fn length_rlc(&self) -> Expression { + self.memory_length.expr() + } + pub(crate) fn length(&self) -> Expression { from_bytes::expr(&self.memory_length.cells) } From 9a83513f39c7b06ce78e28eefddb20dcfe8295c2 Mon Sep 17 00:00:00 2001 From: Mason Liang Date: Fri, 6 Jan 2023 16:40:16 -0500 Subject: [PATCH 63/69] Constraint step state transition for empty initilization code --- .../src/evm_circuit/execution/create.rs | 57 ++++++++++--------- 1 file changed, 30 insertions(+), 27 deletions(-) diff --git a/zkevm-circuits/src/evm_circuit/execution/create.rs b/zkevm-circuits/src/evm_circuit/execution/create.rs index 1211902f1d..98b96d9830 100644 --- a/zkevm-circuits/src/evm_circuit/execution/create.rs +++ b/zkevm-circuits/src/evm_circuit/execution/create.rs @@ -196,7 +196,7 @@ impl ExecutionGadget for CreateGadget { * initialization_code_word_size.quotient(); let gas_cost = GasCost::CREATE.expr() + memory_expansion.gas_cost() + keccak_gas_cost; - let gas_remaining = cb.curr.state.gas_left.expr() - gas_cost; + let gas_remaining = cb.curr.state.gas_left.expr() - gas_cost.clone(); let gas_left = ConstantDivisionGadget::construct(cb, gas_remaining.clone(), 64); let callee_gas_left = gas_remaining - gas_left.quotient(); for (field_tag, value) in [ @@ -242,31 +242,29 @@ impl ExecutionGadget for CreateGadget { cb.call_context_lookup(true.expr(), Some(callee_call_id.expr()), field_tag, value); } - cb.condition(initialization_code.has_length(), |cb| cb.require_step_state_transition(StepStateTransition { - rw_counter: Delta(cb.rw_counter_offset()), - call_id: To(callee_call_id.expr()), - is_root: To(false.expr()), - is_create: To(true.expr()), - code_hash: To(code_hash.expr()), - gas_left: To(callee_gas_left), - reversible_write_counter: To(3.expr()), - ..StepStateTransition::new_context() - })); - - // cb.condition(not::expr(initialization_code.has_length()), |cb| cb.require_step_state_transition(StepStateTransition { - // rw_counter: Delta(cb.rw_counter_offset()), - // program_counter: Delta(1.expr()), - // stack_pointer: Delta(1.expr()), - // gas_left: To(callee_gas_left), - // reversible_write_counter: To(3.expr()), - // ..StepStateTransition::default() - // - // rw_counter: Delta(3.expr()), - // program_counter: Delta(1.expr()), - // stack_pointer: Delta(1.expr()), - // gas_left: Delta(-OpcodeId::MUL.constant_gas_cost().expr()), - // ..Default::default() - // }); + cb.condition(initialization_code.has_length(), |cb| { + cb.require_step_state_transition(StepStateTransition { + rw_counter: Delta(cb.rw_counter_offset()), + call_id: To(callee_call_id.expr()), + is_root: To(false.expr()), + is_create: To(true.expr()), + code_hash: To(code_hash.expr()), + gas_left: To(callee_gas_left), + reversible_write_counter: To(3.expr()), + ..StepStateTransition::new_context() + }) + }); + + cb.condition(not::expr(initialization_code.has_length()), |cb| { + cb.require_step_state_transition(StepStateTransition { + rw_counter: Delta(cb.rw_counter_offset()), + program_counter: Delta(1.expr()), + stack_pointer: Delta(2.expr() + is_create2.expr()), + gas_left: Delta(-gas_cost), + reversible_write_counter: Delta(5.expr()), + ..Default::default() + }) + }); let keccak_input = cb.query_cell(); let keccak_input_length = cb.query_cell(); @@ -824,7 +822,12 @@ mod test { balance: eth(10), ..Default::default() }; - assert_eq!(run_test_circuits(test_context(caller), None), Ok(())); + assert_eq!( + run_test_circuits(test_context(caller), None), + Ok(()), + "is_create2 = {:?}", + is_create2 + ); } } } From ee08efbbf35032a882f603c3baffe0da5fb82da1 Mon Sep 17 00:00:00 2001 From: Mason Liang Date: Fri, 6 Jan 2023 16:56:57 -0500 Subject: [PATCH 64/69] Fix clippy --- bus-mapping/src/evm/opcodes/create.rs | 4 ++-- .../src/evm_circuit/execution/create.rs | 16 ++++++++-------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/bus-mapping/src/evm/opcodes/create.rs b/bus-mapping/src/evm/opcodes/create.rs index 4517cb1a6c..376dc8a10c 100644 --- a/bus-mapping/src/evm/opcodes/create.rs +++ b/bus-mapping/src/evm/opcodes/create.rs @@ -249,7 +249,7 @@ fn handle_copy( length: usize, ) -> Result, Error> { let initialization_bytes = state.call_ctx()?.memory.0[offset..offset + length].to_vec(); - let dst_id = NumberOrHash::Hash(H256(keccak256(&initialization_bytes.clone()))); + let dst_id = NumberOrHash::Hash(H256(keccak256(&initialization_bytes))); let bytes: Vec<_> = Bytecode::from(initialization_bytes.clone()) .code .iter() @@ -269,7 +269,7 @@ fn handle_copy( state.push_copy(CopyEvent { rw_counter_start, src_type: CopyDataType::Memory, - src_id: NumberOrHash::Number(callee_id.try_into().unwrap()), + src_id: NumberOrHash::Number(callee_id), src_addr: offset.try_into().unwrap(), src_addr_end: (offset + length).try_into().unwrap(), dst_type: CopyDataType::Bytecode, diff --git a/zkevm-circuits/src/evm_circuit/execution/create.rs b/zkevm-circuits/src/evm_circuit/execution/create.rs index 98b96d9830..0fa41ee4ef 100644 --- a/zkevm-circuits/src/evm_circuit/execution/create.rs +++ b/zkevm-circuits/src/evm_circuit/execution/create.rs @@ -271,7 +271,7 @@ impl ExecutionGadget for CreateGadget { cb.condition(is_create2.expr(), |cb| { // TODO: some comments here explaining what's going on.... let randomness_raised_to_16 = cb.power_of_randomness()[15].clone(); - let randomness_raised_to_32 = randomness_raised_to_16.clone().square(); + let randomness_raised_to_32 = randomness_raised_to_16.square(); let randomness_raised_to_64 = randomness_raised_to_32.clone().square(); let randomness_raised_to_84 = randomness_raised_to_64.clone() * cb.power_of_randomness()[19].clone(); @@ -375,7 +375,7 @@ impl ExecutionGadget for CreateGadget { let mut code_hash = keccak256(&values); code_hash.reverse(); let code_hash_rlc = - RandomLinearCombination::random_linear_combine(code_hash.clone(), block.randomness); + RandomLinearCombination::random_linear_combine(code_hash, block.randomness); self.code_hash .assign(region, offset, Value::known(code_hash_rlc))?; @@ -418,7 +418,7 @@ impl ExecutionGadget for CreateGadget { let mut caller_address_bytes = call.callee_address.to_fixed_bytes(); caller_address_bytes.reverse(); self.caller_address - .assign(region, offset, Some(caller_address_bytes.clone()))?; + .assign(region, offset, Some(caller_address_bytes))?; let caller_nonce = block.rws [step.rw_indices[9 + usize::from(is_create2) + copy_rw_increase]] @@ -473,7 +473,7 @@ impl ExecutionGadget for CreateGadget { offset, (step.gas_left - GasCost::CREATE.as_u64() - - u64::try_from(memory_expansion_gas_cost).unwrap() + - memory_expansion_gas_cost - if is_create2 { u64::try_from(initialization_code_word_size).unwrap() * GasCost::COPY_SHA3.as_u64() @@ -558,8 +558,8 @@ impl RlpU64Gadget { cb.condition(most_significant_byte_is_zero.expr(), |cb| { cb.require_zero("if most significant byte is 0, value is 0", value.clone()); }); - for i in 0..N_BYTES_U64 { - cb.condition(is_most_significant_byte[i].expr(), |cb| { + for (i, is_most_significant) in is_most_significant_byte.iter().enumerate() { + cb.condition(is_most_significant.expr(), |cb| { cb.require_equal( "most significant byte is non-zero", most_significant_byte_is_zero.expr(), @@ -602,7 +602,7 @@ impl RlpU64Gadget { offset, most_significant_byte_index .map(|i| u64::from(bytes[i]).into()) - .unwrap_or(F::zero()), + .unwrap_or_default(), )?; self.bytes.assign(region, offset, Some(bytes))?; for i in 0..N_BYTES_U64 { @@ -813,7 +813,7 @@ mod test { } #[test] - fn test_empty_initialization_code() { + fn test_create_empty_initialization_code() { for is_create2 in [true, false] { let caller = Account { address: *CALLER_ADDRESS, From f15ffa76b230b653ead13bc9761c9411f749be53 Mon Sep 17 00:00:00 2001 From: Mason Liang Date: Fri, 6 Jan 2023 17:03:01 -0500 Subject: [PATCH 65/69] Add 127 and 128 to nonce test cases --- zkevm-circuits/src/evm_circuit/execution/create.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zkevm-circuits/src/evm_circuit/execution/create.rs b/zkevm-circuits/src/evm_circuit/execution/create.rs index 0fa41ee4ef..a94bd330c2 100644 --- a/zkevm-circuits/src/evm_circuit/execution/create.rs +++ b/zkevm-circuits/src/evm_circuit/execution/create.rs @@ -795,7 +795,7 @@ mod test { #[test] fn test_create_rlp_nonce() { - for nonce in [0, 1, 255, 256, 0x10000, u64::MAX - 1] { + for nonce in [0, 1, 127, 128, 255, 256, 0x10000, u64::MAX - 1] { let caller = Account { address: *CALLER_ADDRESS, code: creater_bytecode(initialization_bytecode(true), false, true).into(), From 2aeb3447318ee5abd7701c10d9afd55727b940b1 Mon Sep 17 00:00:00 2001 From: Mason Liang Date: Fri, 6 Jan 2023 17:11:52 -0500 Subject: [PATCH 66/69] Minimize changes to other files --- bus-mapping/src/circuit_input_builder/execution.rs | 4 ++-- zkevm-circuits/src/evm_circuit/execution/callop.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/bus-mapping/src/circuit_input_builder/execution.rs b/bus-mapping/src/circuit_input_builder/execution.rs index b12ac0f4e2..875e5b936f 100644 --- a/bus-mapping/src/circuit_input_builder/execution.rs +++ b/bus-mapping/src/circuit_input_builder/execution.rs @@ -245,14 +245,14 @@ impl CopyEvent { // increase in rw counter from the start of the copy event to step index fn rw_counter_increase(&self, step_index: usize) -> u64 { let source_rw_increase = match self.src_type { - CopyDataType::Bytecode | CopyDataType::TxCalldata | CopyDataType::RlcAcc => 0, + CopyDataType::Bytecode | CopyDataType::TxCalldata => 0, CopyDataType::Memory => std::cmp::min( u64::try_from(step_index + 1).unwrap() / 2, self.src_addr_end .checked_sub(self.src_addr) .unwrap_or_default(), ), - CopyDataType::TxLog => unreachable!(), + CopyDataType::RlcAcc | CopyDataType::TxLog => unreachable!(), }; let destination_rw_increase = match self.dst_type { CopyDataType::RlcAcc | CopyDataType::Bytecode => 0, diff --git a/zkevm-circuits/src/evm_circuit/execution/callop.rs b/zkevm-circuits/src/evm_circuit/execution/callop.rs index 0d185dc514..186d1e23c1 100644 --- a/zkevm-circuits/src/evm_circuit/execution/callop.rs +++ b/zkevm-circuits/src/evm_circuit/execution/callop.rs @@ -140,7 +140,7 @@ impl ExecutionGadget for CallOpGadget { let memory_expansion = MemoryExpansionGadget::construct(cb, [cd_address.address(), rd_address.address()]); - // `code_address` is popped from stack and used to check if it exists in + // `code_address` is poped from stack and used to check if it exists in // access list and get code hash. // For CALLCODE, both caller and callee addresses are // `current_callee_address`. From 049b94e8ecc997ad0b745eb297a45d4cdfb3c866 Mon Sep 17 00:00:00 2001 From: Mason Liang Date: Fri, 6 Jan 2023 17:12:53 -0500 Subject: [PATCH 67/69] Undo state circuit change --- zkevm-circuits/src/state_circuit.rs | 8 -------- 1 file changed, 8 deletions(-) diff --git a/zkevm-circuits/src/state_circuit.rs b/zkevm-circuits/src/state_circuit.rs index 44d5160b5c..f22411bbbe 100644 --- a/zkevm-circuits/src/state_circuit.rs +++ b/zkevm-circuits/src/state_circuit.rs @@ -260,14 +260,6 @@ impl StateCircuitConfig { } state_root }); - } else if !row.is_write() { - assert_eq!( - row.value_assignment(F::one()), - prev_row.value_assignment(F::one()), - "{:?}, {:?}", - row, - prev_row - ); } } From 3373ce9829e990bdb131049f7a707332468182cd Mon Sep 17 00:00:00 2001 From: Mason Liang Date: Mon, 9 Jan 2023 13:30:43 -0500 Subject: [PATCH 68/69] Simplify logic and add comments --- .../circuit_input_builder/input_state_ref.rs | 31 +++++ bus-mapping/src/evm/opcodes/create.rs | 122 ++++++++---------- .../src/evm_circuit/execution/create.rs | 9 +- 3 files changed, 88 insertions(+), 74 deletions(-) diff --git a/bus-mapping/src/circuit_input_builder/input_state_ref.rs b/bus-mapping/src/circuit_input_builder/input_state_ref.rs index 2071897846..7bc837a207 100644 --- a/bus-mapping/src/circuit_input_builder/input_state_ref.rs +++ b/bus-mapping/src/circuit_input_builder/input_state_ref.rs @@ -379,6 +379,25 @@ impl<'a> CircuitInputStateRef<'a> { Ok(()) } + /// Add address to access list for the current transaction. + pub fn tx_access_list_write( + &mut self, + step: &mut ExecStep, + address: Address, + ) -> Result<(), Error> { + let is_warm = self.sdb.check_account_in_access_list(&address); + self.push_op_reversible( + step, + RW::WRITE, + TxAccessListAccountOp { + tx_id: self.tx_ctx.id(), + address, + is_warm: true, + is_warm_prev: is_warm, + }, + ) + } + /// Push a write type [`TxAccessListAccountOp`] into the /// [`OperationContainer`](crate::operation::OperationContainer) with the /// next [`RWCounter`](crate::operation::RWCounter), and then @@ -571,6 +590,18 @@ impl<'a> CircuitInputStateRef<'a> { )) } + pub(crate) fn reversion_info_read(&mut self, step: &mut ExecStep, call: &Call) { + for (field, value) in [ + ( + CallContextField::RwCounterEndOfReversion, + call.rw_counter_end_of_reversion.to_word(), + ), + (CallContextField::IsPersistent, call.is_persistent.to_word()), + ] { + self.call_context_read(step, call.call_id, field, value); + } + } + /// Check if address is a precompiled or not. pub fn is_precompiled(&self, address: &Address) -> bool { address.0[0..19] == [0u8; 19] && (1..=9).contains(&address.0[19]) diff --git a/bus-mapping/src/evm/opcodes/create.rs b/bus-mapping/src/evm/opcodes/create.rs index 376dc8a10c..e6c375d571 100644 --- a/bus-mapping/src/evm/opcodes/create.rs +++ b/bus-mapping/src/evm/opcodes/create.rs @@ -1,11 +1,11 @@ -use crate::circuit_input_builder::{ - CircuitInputStateRef, CopyDataType, CopyEvent, ExecStep, NumberOrHash, +use crate::{ + circuit_input_builder::{ + CircuitInputStateRef, CopyDataType, CopyEvent, ExecStep, NumberOrHash, + }, + evm::Opcode, + operation::{AccountField, AccountOp, CallContextField, MemoryOp, RW}, + Error, }; -use crate::evm::Opcode; -use crate::operation::{ - AccountField, AccountOp, CallContextField, MemoryOp, TxAccessListAccountOp, RW, -}; -use crate::Error; use eth_types::{ evm_types::gas_utils::memory_expansion_gas_cost, Bytecode, GethExecStep, ToBigEndian, ToWord, Word, H160, H256, @@ -36,8 +36,7 @@ impl Opcode for Create { let mut exec_step = state.new_step(geth_step)?; - // TODO: rename this to initialization call? - let call = state.parse_call(geth_step)?; + let callee = state.parse_call(geth_step)?; let n_pop = if IS_CREATE2 { 4 } else { 3 }; for i in 0..n_pop { @@ -56,7 +55,7 @@ impl Opcode for Create { state.stack_write( &mut exec_step, geth_step.stack.nth_last_filled(n_pop - 1), - if call.is_success { + if callee.is_success { address.to_word() } else { Word::zero() @@ -69,81 +68,60 @@ impl Opcode for Create { handle_copy(state, &mut exec_step, state.call()?.call_id, offset, length)?; } - // Quote from [EIP-2929](https://eips.ethereum.org/EIPS/eip-2929) - // > When a CREATE or CREATE2 opcode is called, - // > immediately (i.e. before checks are done to determine - // > whether or not the address is unclaimed) - // > add the address being created to accessed_addresses, - // > but gas costs of CREATE and CREATE2 are unchanged - let tx_id = state.tx_ctx.id(); - let current_call = state.call()?.clone(); + let caller = state.call()?.clone(); - for (field, value) in [ - (CallContextField::TxId, tx_id.to_word()), - ( - CallContextField::RwCounterEndOfReversion, - current_call.rw_counter_end_of_reversion.to_word(), - ), - ( - CallContextField::IsPersistent, - current_call.is_persistent.to_word(), - ), - ] { - state.call_context_read(&mut exec_step, current_call.call_id, field, value); - } - - let is_warm = state.sdb.check_account_in_access_list(&address); - state.push_op_reversible( + state.call_context_read( &mut exec_step, - RW::WRITE, - TxAccessListAccountOp { - tx_id, - address, - is_warm: true, - is_warm_prev: is_warm, - }, - )?; + caller.call_id, + CallContextField::TxId, + tx_id.to_word(), + ); + state.reversion_info_read(&mut exec_step, &caller); + state.tx_access_list_write(&mut exec_step, address)?; state.call_context_read( &mut exec_step, - current_call.call_id, + caller.call_id, CallContextField::CalleeAddress, - current_call.address.to_word(), + caller.address.to_word(), ); // Increase caller's nonce - let caller_nonce = state.sdb.get_nonce(&call.caller_address); + let caller_nonce = state.sdb.get_nonce(&caller.address); state.push_op_reversible( &mut exec_step, RW::WRITE, AccountOp { - address: call.caller_address, + address: caller.address, field: AccountField::Nonce, value: (caller_nonce + 1).into(), value_prev: caller_nonce.into(), }, )?; - state.push_call(call.clone()); - // Increase callee's nonce + // TODO: look into when this can be pushed. Could it be done in parse call? + state.push_call(callee.clone()); + for (field, value) in [ ( CallContextField::RwCounterEndOfReversion, - call.rw_counter_end_of_reversion.to_word(), + callee.rw_counter_end_of_reversion.to_word(), + ), + ( + CallContextField::IsPersistent, + callee.is_persistent.to_word(), ), - (CallContextField::IsPersistent, call.is_persistent.to_word()), ] { - state.call_context_write(&mut exec_step, call.call_id, field, value); + state.call_context_write(&mut exec_step, callee.call_id, field, value); } - let nonce_prev = state.sdb.get_nonce(&call.address); - debug_assert!(nonce_prev == 0); + debug_assert!(state.sdb.get_nonce(&callee.address) == 0); state.push_op_reversible( &mut exec_step, RW::WRITE, AccountOp { - address: call.address, + address: callee.address, field: AccountField::Nonce, value: 1.into(), value_prev: 0.into(), @@ -152,15 +130,16 @@ impl Opcode for Create { state.transfer( &mut exec_step, - call.caller_address, - call.address, - call.value, + callee.caller_address, + callee.address, + callee.value, )?; let memory_expansion_gas_cost = memory_expansion_gas_cost(curr_memory_word_size, next_memory_word_size); - // EIP-150: all but one 64th of the caller's gas is sent to the callee. + // Per EIP-150, all but one 64th of the caller's gas is sent to the + // initialization call. let caller_gas_left = (geth_step.gas.0 - geth_step.gas_cost.0 - memory_expansion_gas_cost) / 64; @@ -177,30 +156,31 @@ impl Opcode for Create { (CallContextField::MemorySize, next_memory_word_size.into()), ( CallContextField::ReversibleWriteCounter, - // +2 is because we do some reversible writes before pushing the call. can be just - // push the call later? (exec_step.reversible_write_counter + 2).into(), ), ] { - state.call_context_write(&mut exec_step, current_call.call_id, field, value); + state.call_context_write(&mut exec_step, caller.call_id, field, value); } for (field, value) in [ - (CallContextField::CallerId, current_call.call_id.into()), - (CallContextField::IsSuccess, call.is_success.to_word()), - (CallContextField::IsPersistent, call.is_persistent.to_word()), + (CallContextField::CallerId, caller.call_id.into()), + (CallContextField::IsSuccess, callee.is_success.to_word()), + ( + CallContextField::IsPersistent, + callee.is_persistent.to_word(), + ), (CallContextField::TxId, state.tx_ctx.id().into()), ( CallContextField::CallerAddress, - current_call.address.to_word(), + callee.caller_address.to_word(), ), - (CallContextField::CalleeAddress, call.address.to_word()), + (CallContextField::CalleeAddress, callee.address.to_word()), ( CallContextField::RwCounterEndOfReversion, - call.rw_counter_end_of_reversion.to_word(), + callee.rw_counter_end_of_reversion.to_word(), ), ] { - state.call_context_write(&mut exec_step, call.call_id, field, value); + state.call_context_write(&mut exec_step, callee.call_id, field, value); } let keccak_input = if IS_CREATE2 { @@ -208,20 +188,20 @@ impl Opcode for Create { assert_eq!( address, get_create2_address( - current_call.address, + caller.address, salt.to_be_bytes().to_vec(), initialization_code.clone() ) ); std::iter::once(0xffu8) - .chain(current_call.address.to_fixed_bytes()) // also don't need to be reversed.... + .chain(caller.address.to_fixed_bytes()) .chain(salt.to_be_bytes()) .chain(keccak256(&initialization_code)) .collect::>() } else { let mut stream = rlp::RlpStream::new(); stream.begin_list(2); - stream.append(¤t_call.address); + stream.append(&caller.address); stream.append(&Word::from(caller_nonce)); stream.out().to_vec() }; diff --git a/zkevm-circuits/src/evm_circuit/execution/create.rs b/zkevm-circuits/src/evm_circuit/execution/create.rs index a94bd330c2..90559bb06a 100644 --- a/zkevm-circuits/src/evm_circuit/execution/create.rs +++ b/zkevm-circuits/src/evm_circuit/execution/create.rs @@ -269,7 +269,10 @@ impl ExecutionGadget for CreateGadget { let keccak_input = cb.query_cell(); let keccak_input_length = cb.query_cell(); cb.condition(is_create2.expr(), |cb| { - // TODO: some comments here explaining what's going on.... + // For CREATE2, the keccak input is the concatenation of 0xff, address, salt, + // and code_hash. Each sequence of bytes occurs in a fixed position, so to + // compute the RLC of the input, we only need to compute some fixed powers of + // the randomness. let randomness_raised_to_16 = cb.power_of_randomness()[15].clone(); let randomness_raised_to_32 = randomness_raised_to_16.square(); let randomness_raised_to_64 = randomness_raised_to_32.clone().square(); @@ -730,8 +733,8 @@ mod test { } code.append(&bytecode! { PUSH1(initialization_bytes.len()) // size - PUSH1(32 - initialization_bytes.len()) // value - PUSH1(10) // value + PUSH1(32 - initialization_bytes.len()) // length + PUSH2(23414) // value }); code.write_op(if is_create2 { OpcodeId::CREATE2 From 53311136bb5099dc8a93680dc9dac7cd2135e131 Mon Sep 17 00:00:00 2001 From: Mason Liang Date: Mon, 9 Jan 2023 16:32:27 -0500 Subject: [PATCH 69/69] Add reversion info constraints and call information lookups --- bus-mapping/src/evm/opcodes/create.rs | 13 ++++++++ .../src/evm_circuit/execution/create.rs | 30 ++++++++++++++++++- 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/bus-mapping/src/evm/opcodes/create.rs b/bus-mapping/src/evm/opcodes/create.rs index e6c375d571..4cee1ef652 100644 --- a/bus-mapping/src/evm/opcodes/create.rs +++ b/bus-mapping/src/evm/opcodes/create.rs @@ -162,6 +162,14 @@ impl Opcode for Create { state.call_context_write(&mut exec_step, caller.call_id, field, value); } + state.call_context_read( + &mut exec_step, + caller.call_id, + CallContextField::Depth, + caller.depth.to_word(), + ); + + let code_hash = keccak256(&initialization_code); for (field, value) in [ (CallContextField::CallerId, caller.call_id.into()), (CallContextField::IsSuccess, callee.is_success.to_word()), @@ -179,6 +187,11 @@ impl Opcode for Create { CallContextField::RwCounterEndOfReversion, callee.rw_counter_end_of_reversion.to_word(), ), + (CallContextField::Depth, callee.depth.to_word()), + (CallContextField::IsRoot, false.to_word()), + (CallContextField::IsStatic, false.to_word()), + (CallContextField::IsCreate, true.to_word()), + (CallContextField::CodeHash, Word::from(code_hash)), ] { state.call_context_write(&mut exec_step, callee.call_id, field, value); } diff --git a/zkevm-circuits/src/evm_circuit/execution/create.rs b/zkevm-circuits/src/evm_circuit/execution/create.rs index 90559bb06a..05d86cf7b3 100644 --- a/zkevm-circuits/src/evm_circuit/execution/create.rs +++ b/zkevm-circuits/src/evm_circuit/execution/create.rs @@ -46,6 +46,7 @@ pub(crate) struct CreateGadget { reversion_info: ReversionInfo, was_warm: Cell, + depth: Cell, caller_address: RandomLinearCombination, nonce: RlpU64Gadget, @@ -169,7 +170,21 @@ impl ExecutionGadget for CreateGadget { Some(&mut reversion_info), ); + // TODO: deduplicate with the code in CallOpGadget let mut callee_reversion_info = cb.reversion_info_write(Some(callee_call_id.expr())); + cb.require_equal( + "callee_is_persistent == is_persistent ⋅ is_success", + callee_reversion_info.is_persistent(), + reversion_info.is_persistent() * callee_is_success.expr(), + ); + cb.condition(callee_is_success.expr() * (1.expr() - reversion_info.is_persistent()), |cb| { + cb.require_equal( + "callee_rw_counter_end_of_reversion == rw_counter_end_of_reversion - (reversible_write_counter + 1)", + callee_reversion_info.rw_counter_end_of_reversion(), + reversion_info.rw_counter_of_reversion(), + ); + }); + cb.account_write( new_address.clone(), AccountFieldTag::Nonce, @@ -221,6 +236,8 @@ impl ExecutionGadget for CreateGadget { cb.call_context_lookup(true.expr(), None, field_tag, value); } + let depth = cb.call_context(None, CallContextFieldTag::Depth); + for (field_tag, value) in [ (CallContextFieldTag::CallerId, cb.curr.state.call_id.expr()), (CallContextFieldTag::IsSuccess, callee_is_success.expr()), @@ -238,6 +255,11 @@ impl ExecutionGadget for CreateGadget { CallContextFieldTag::RwCounterEndOfReversion, callee_reversion_info.rw_counter_end_of_reversion(), ), + (CallContextFieldTag::Depth, depth.expr() + 1.expr()), + (CallContextFieldTag::IsRoot, false.expr()), + (CallContextFieldTag::IsStatic, false.expr()), + (CallContextFieldTag::IsCreate, true.expr()), + (CallContextFieldTag::CodeHash, code_hash.expr()), ] { cb.call_context_lookup(true.expr(), Some(callee_call_id.expr()), field_tag, value); } @@ -329,6 +351,7 @@ impl ExecutionGadget for CreateGadget { salt, caller_address, nonce, + depth, callee_reversion_info, transfer, initialization_code, @@ -395,6 +418,11 @@ impl ExecutionGadget for CreateGadget { self.tx_id .assign(region, offset, Value::known(tx.id.to_scalar().unwrap()))?; + self.depth.assign( + region, + offset, + Value::known(call.depth.to_scalar().unwrap()), + )?; self.reversion_info.assign( region, @@ -490,7 +518,7 @@ impl ExecutionGadget for CreateGadget { region, offset, Value::known( - block.rws[step.rw_indices[21 + usize::from(is_create2) + copy_rw_increase]] + block.rws[step.rw_indices[22 + usize::from(is_create2) + copy_rw_increase]] .call_context_value() .to_scalar() .unwrap(),