diff --git a/Cargo.lock b/Cargo.lock index f35ee46129..95208fcb96 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -85,9 +85,9 @@ checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" [[package]] name = "async-trait" -version = "0.1.52" +version = "0.1.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "061a7acccaa286c011ddc30970520b98fa40e00c9d644633fb26b5fc63a265e3" +checksum = "ed6aa3524a2dfcf9fe180c51eae2b58738348d819517ceadf95789c51fff7600" dependencies = [ "proc-macro2", "quote", @@ -170,9 +170,9 @@ checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" [[package]] name = "base64ct" -version = "1.4.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71acf5509fc522cce1b100ac0121c635129bfd4d91cdf036bcc9b9935f97ccf5" +checksum = "dea908e7347a8c64e378c17e30ef880ad73e3b4498346b055c2c00ea342f3179" [[package]] name = "bech32" @@ -371,9 +371,9 @@ checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" [[package]] name = "bytemuck" -version = "1.8.0" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e851ca7c24871e7336801608a4797d7376545b6928a10d32d75685687141ead" +checksum = "cdead85bdec19c194affaeeb670c0e41fe23de31459efd1c174d049269cf02cc" [[package]] name = "byteorder" @@ -416,7 +416,7 @@ checksum = "4acbb09d9ee8e23699b9634375c72795d095bf268439da88562cf9b501f181fa" dependencies = [ "camino", "cargo-platform", - "semver 1.0.6", + "semver 1.0.7", "serde", "serde_json", ] @@ -1319,7 +1319,7 @@ dependencies = [ "thiserror", "tokio", "tokio-tungstenite", - "tokio-util", + "tokio-util 0.6.9", "tracing", "tracing-futures", "url", @@ -1346,7 +1346,7 @@ dependencies = [ "futures-util", "hex", "rand", - "semver 1.0.6", + "semver 1.0.7", "sha2 0.9.9", "thiserror", ] @@ -1366,7 +1366,7 @@ dependencies = [ "md-5", "once_cell", "regex", - "semver 1.0.6", + "semver 1.0.7", "serde", "serde_json", "sha2 0.9.9", @@ -1664,9 +1664,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d39cd93900197114fa1fcb7ae84ca742095eed9442088988ae74fa744e930e77" +checksum = "9be70c98951c83b8d2f8f60d7065fa6d5146873094452a1008da8c2f1e4205ad" dependencies = [ "cfg-if 1.0.0", "js-sys", @@ -1725,9 +1725,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.12" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62eeb471aa3e3c9197aa4bfeabfe02982f6dc96f750486c0bb0009ac58b26d2b" +checksum = "37a82c6d637fc9515a4694bbf1cb2457b79d81ce52b3108bdeea58b07dd34a57" dependencies = [ "bytes", "fnv", @@ -1738,7 +1738,7 @@ dependencies = [ "indexmap", "slab", "tokio", - "tokio-util", + "tokio-util 0.7.1", "tracing", ] @@ -1849,9 +1849,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.14.17" +version = "0.14.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "043f0e083e9901b6cc658a77d1eb86f4fc650bbb977a4337dd63192826aa85dd" +checksum = "b26ae0a80afebe130861d90abf98e3814a4f28a4c6ffeb5ab8ebb2be311e0ef2" dependencies = [ "bytes", "futures-channel", @@ -1970,9 +1970,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "1.8.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282a6247722caba404c065016bbfa522806e51714c34f5dfc3e4a3a46fcb4223" +checksum = "0f647032dfaa1f8b6dc29bd3edb7bbef4861b8b8007ebb118d6db284fd59f6ee" dependencies = [ "autocfg", "hashbrown", @@ -2101,18 +2101,19 @@ checksum = "efaa7b300f3b5fe8eb6bf21ce3895e1751d9665086af2d64b42f19701015ff4f" [[package]] name = "lock_api" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88943dd7ef4a2e5a4bfa2753aaab3013e34ce2533d1996fb18ef591e315e2b3b" +checksum = "327fa5b6a6940e4699ec49a9beae1ea4845c6bab9314e4f84ac68742139d8c53" dependencies = [ + "autocfg", "scopeguard", ] [[package]] name = "log" -version = "0.4.15" +version = "0.4.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c4dcd960cc540667f619483fc99102f88d6118b87730e24e8fbe8054b7445e4" +checksum = "6389c490849ff5bc16be905ae24bc913a9c8892e19b2341dbc175e14c341c2b8" dependencies = [ "cfg-if 1.0.0", ] @@ -2200,9 +2201,9 @@ dependencies = [ [[package]] name = "native-tls" -version = "0.2.8" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48ba9f7719b5a0f42f338907614285fb5fd70e53858141f69898a1fb7203b24d" +checksum = "fd7e2f3618557f980e0b17e8856252eee3c97fa12c54dff0ca290fb6266ca4a9" dependencies = [ "lazy_static", "libc", @@ -2391,7 +2392,7 @@ dependencies = [ [[package]] name = "pairing_bn256" version = "0.1.0" -source = "git+https://github.com/appliedzkp/pairing#530f4c0022ed0fa430500e837ac7772e84bb4c2c" +source = "git+https://github.com/appliedzkp/pairing#58986019b8bc7ad9c81c861c6acd8940b5eb1f66" dependencies = [ "ff 0.11.0", "group 0.11.0", @@ -2465,9 +2466,9 @@ dependencies = [ [[package]] name = "paste" -version = "1.0.6" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0744126afe1a6dd7f394cb50a716dbe086cb06e255e53d8d0185d82828358fb5" +checksum = "0c520e05135d6e763148b6426a837e239041653ba7becd2e538c076c738025fc" [[package]] name = "pathfinder_geometry" @@ -2570,9 +2571,9 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.24" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58893f751c9b0412871a09abd62ecd2a00298c6c83befa223ef98c52aef40cbe" +checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae" [[package]] name = "plotters" @@ -2640,9 +2641,9 @@ checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" [[package]] name = "pretty_assertions" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57c038cb5319b9c704bf9c227c261d275bfec0ad438118a2787ce47944fb228b" +checksum = "c89f989ac94207d048d92db058e4f6ec7342b0971fc58d1271ca148b799b3563" dependencies = [ "ansi_term", "ctor", @@ -2727,9 +2728,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.16" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4af2ec4714533fcdf07e886f17025ace8b997b9ce51204ee69b6da831c3da57" +checksum = "632d02bff7f874a36f33ea8bb416cd484b90cc66c1194b1a1110d067a7013f58" dependencies = [ "proc-macro2", ] @@ -2812,18 +2813,18 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.2.11" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8380fe0152551244f0747b1bf41737e0f8a74f97a14ccefd1148187271634f3c" +checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42" dependencies = [ "bitflags", ] [[package]] name = "redox_users" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7776223e2696f1aa4c6b0170e83212f47296a00424305117d013dfe86fb0fe55" +checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" dependencies = [ "getrandom", "redox_syscall", @@ -2971,7 +2972,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" dependencies = [ - "semver 1.0.6", + "semver 1.0.7", ] [[package]] @@ -3128,9 +3129,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.6" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a3381e03edd24287172047536f20cabde766e2cd3e65e6b00fb3af51c4f38d" +checksum = "d65bd28f48be7196d222d95b9243287f48d27aca604e08497513019ff0502cc4" dependencies = [ "serde", ] @@ -3318,9 +3319,9 @@ dependencies = [ [[package]] name = "slab" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5" +checksum = "eb703cfe953bccee95685111adeedb76fabe4e97549a58d16f03ea7b9367bb32" [[package]] name = "smallvec" @@ -3373,9 +3374,9 @@ checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" [[package]] name = "syn" -version = "1.0.89" +version = "1.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea297be220d52398dcc07ce15a209fce436d361735ac1db700cab3b6cdfb9f54" +checksum = "704df27628939572cd88d33f171cd6f896f4eaca85252c6e0a72d8d8287ee86f" dependencies = [ "proc-macro2", "quote", @@ -3587,6 +3588,20 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-util" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0edfdeb067411dba2044da6d1cb2df793dd35add7888d73c16e3381ded401764" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", + "tracing", +] + [[package]] name = "toml" version = "0.5.8" @@ -3627,9 +3642,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa31669fa42c09c34d94d8165dd2012e8ff3c66aca50f3bb226b68f216f2706c" +checksum = "90442985ee2f57c9e1b548ee72ae842f4a9a20e3f417cc38dbc5dc684d9bb4ee" dependencies = [ "lazy_static", ] diff --git a/bus-mapping/src/evm/opcodes.rs b/bus-mapping/src/evm/opcodes.rs index 4d1585a889..5687a54203 100644 --- a/bus-mapping/src/evm/opcodes.rs +++ b/bus-mapping/src/evm/opcodes.rs @@ -27,6 +27,7 @@ mod gasprice; mod mload; mod mstore; mod number; +mod origin; mod selfbalance; mod sload; mod stackonlyop; @@ -43,6 +44,7 @@ use extcodehash::Extcodehash; use gasprice::GasPrice; use mload::Mload; use mstore::Mstore; +use origin::Origin; use selfbalance::Selfbalance; use sload::Sload; use stackonlyop::StackOnlyOpcode; @@ -107,7 +109,7 @@ fn fn_gen_associated_ops(opcode_id: &OpcodeId) -> FnGenAssociatedOps { // OpcodeId::SHA3 => {}, // OpcodeId::ADDRESS => {}, // OpcodeId::BALANCE => {}, - // OpcodeId::ORIGIN => {}, + OpcodeId::ORIGIN => Origin::gen_associated_ops, OpcodeId::CALLER => Caller::gen_associated_ops, OpcodeId::CALLVALUE => Callvalue::gen_associated_ops, OpcodeId::CALLDATASIZE => Calldatasize::gen_associated_ops, diff --git a/bus-mapping/src/evm/opcodes/origin.rs b/bus-mapping/src/evm/opcodes/origin.rs new file mode 100644 index 0000000000..f98c089126 --- /dev/null +++ b/bus-mapping/src/evm/opcodes/origin.rs @@ -0,0 +1,118 @@ +use super::Opcode; +use crate::circuit_input_builder::{CircuitInputStateRef, ExecStep}; +use crate::operation::{CallContextField, CallContextOp, RW}; +use crate::Error; +use eth_types::GethExecStep; + +#[derive(Debug, Copy, Clone)] +pub(crate) struct Origin; + +impl Opcode for Origin { + fn gen_associated_ops( + state: &mut CircuitInputStateRef, + geth_steps: &[GethExecStep], + ) -> Result, Error> { + let geth_step = &geth_steps[0]; + let mut exec_step = state.new_step(geth_step)?; + // Get origin result from next step + let value = geth_steps[1].stack.last()?; + let tx_id = state.tx_ctx.id(); + + // CallContext read of the TxId + state.push_op( + &mut exec_step, + RW::READ, + CallContextOp { + call_id: state.call()?.call_id, + field: CallContextField::TxId, + value: tx_id.into(), + }, + ); + + // Stack write of the origin address value + state.push_stack_op( + &mut exec_step, + RW::WRITE, + geth_step.stack.last_filled().map(|a| a - 1), + value, + )?; + + Ok(vec![exec_step]) + } +} + +#[cfg(test)] +mod origin_tests { + use crate::{ + circuit_input_builder::ExecState, + evm::OpcodeId, + mock::BlockData, + operation::{CallContextField, CallContextOp, StackOp, RW}, + Error, + }; + use eth_types::{bytecode, evm_types::StackAddress, geth_types::GethData, ToWord, Word}; + use mock::{ + test_ctx::{helpers::*, TestContext}, + MOCK_ACCOUNTS, + }; + use pretty_assertions::assert_eq; + + #[test] + fn origin_opcode_impl() -> Result<(), Error> { + let code = bytecode! { + #[start] + ORIGIN + STOP + }; + + // Get the execution steps from the external tracer + let block: GethData = TestContext::<2, 1>::new( + None, + account_0_code_account_1_no_code(code), + tx_from_1_to_0, + |block, _tx| block.number(0xcafeu64), + ) + .unwrap() + .into(); + + let mut builder = BlockData::new_from_geth_data(block.clone()).new_circuit_input_builder(); + builder + .handle_block(&block.eth_block, &block.geth_traces) + .unwrap(); + + let step = builder.block.txs()[0] + .steps() + .iter() + .find(|step| step.exec_state == ExecState::Op(OpcodeId::ORIGIN)) + .unwrap(); + + let op_origin = &builder.block.container.stack[step.bus_mapping_instance[1].as_usize()]; + assert_eq!( + (op_origin.rw(), op_origin.op()), + ( + RW::WRITE, + &StackOp::new(1, StackAddress(1023usize), MOCK_ACCOUNTS[1].to_word()) + ) + ); + + let call_id = builder.block.txs()[0].calls()[0].call_id; + + assert_eq!( + { + let operation = + &builder.block.container.call_context[step.bus_mapping_instance[0].as_usize()]; + (operation.rw(), operation.op()) + }, + ( + RW::READ, + &CallContextOp { + call_id, + field: CallContextField::TxId, + value: Word::one(), + } + ) + ); + + Ok(()) + } +} diff --git a/zkevm-circuits/src/evm_circuit/execution.rs b/zkevm-circuits/src/evm_circuit/execution.rs index 5fe0bfe46c..4bbf02b1c2 100644 --- a/zkevm-circuits/src/evm_circuit/execution.rs +++ b/zkevm-circuits/src/evm_circuit/execution.rs @@ -45,6 +45,7 @@ mod memory_copy; mod msize; mod mul; mod number; +mod origin; mod pc; mod pop; mod push; @@ -85,6 +86,7 @@ use memory_copy::CopyToMemoryGadget; use msize::MsizeGadget; use mul::MulGadget; use number::NumberGadget; +use origin::OriginGadget; use pc::PcGadget; use pop::PopGadget; use push::PushGadget; @@ -130,6 +132,7 @@ pub(crate) struct ExecutionConfig { calldatacopy_gadget: CallDataCopyGadget, calldataload_gadget: CallDataLoadGadget, calldatasize_gadget: CallDataSizeGadget, + origin_gadget: OriginGadget, caller_gadget: CallerGadget, call_value_gadget: CallValueGadget, call_gadget: CallGadget, @@ -349,6 +352,7 @@ impl ExecutionConfig { calldatacopy_gadget: configure_gadget!(), calldataload_gadget: configure_gadget!(), calldatasize_gadget: configure_gadget!(), + origin_gadget: configure_gadget!(), caller_gadget: configure_gadget!(), call_value_gadget: configure_gadget!(), call_gadget: configure_gadget!(), @@ -638,6 +642,7 @@ impl ExecutionConfig { ExecutionState::PUSH => assign_exec_step!(self.push_gadget), ExecutionState::DUP => assign_exec_step!(self.dup_gadget), ExecutionState::SWAP => assign_exec_step!(self.swap_gadget), + ExecutionState::ORIGIN => assign_exec_step!(self.origin_gadget), ExecutionState::CALLER => assign_exec_step!(self.caller_gadget), ExecutionState::CALLVALUE => { assign_exec_step!(self.call_value_gadget) diff --git a/zkevm-circuits/src/evm_circuit/execution/origin.rs b/zkevm-circuits/src/evm_circuit/execution/origin.rs new file mode 100644 index 0000000000..9ae1431485 --- /dev/null +++ b/zkevm-circuits/src/evm_circuit/execution/origin.rs @@ -0,0 +1,120 @@ +use crate::{ + evm_circuit::{ + execution::ExecutionGadget, + param::N_BYTES_ACCOUNT_ADDRESS, + step::ExecutionState, + table::{CallContextFieldTag, TxContextFieldTag}, + util::{ + common_gadget::SameContextGadget, + constraint_builder::{ConstraintBuilder, StepStateTransition, Transition::Delta}, + from_bytes, Cell, RandomLinearCombination, + }, + witness::{Block, Call, ExecStep, Transaction}, + }, + util::Expr, +}; +use bus_mapping::evm::OpcodeId; +use eth_types::{Field, ToLittleEndian}; +use halo2_proofs::{circuit::Region, plonk::Error}; +use std::convert::TryInto; + +#[derive(Clone, Debug)] +pub(crate) struct OriginGadget { + tx_id: Cell, + origin: RandomLinearCombination, + same_context: SameContextGadget, +} + +impl ExecutionGadget for OriginGadget { + const NAME: &'static str = "ORIGIN"; + + const EXECUTION_STATE: ExecutionState = ExecutionState::ORIGIN; + + fn configure(cb: &mut ConstraintBuilder) -> Self { + let origin = cb.query_rlc::(); + + // Lookup in call_ctx the TxId + let tx_id = cb.call_context(None, CallContextFieldTag::TxId); + // Lookup rw_table -> call_context with tx origin address + cb.tx_context_lookup( + tx_id.expr(), + TxContextFieldTag::CallerAddress, + None, // None because unrelated to calldata + from_bytes::expr(&origin.cells), + ); + + // Push the value to the stack + cb.stack_push(origin.expr()); + + // State transition + let opcode = cb.query_cell(); + let step_state_transition = StepStateTransition { + rw_counter: Delta(2u64.expr()), + program_counter: Delta(1u64.expr()), + stack_pointer: Delta((-1i32).expr()), + gas_left: Delta(-OpcodeId::ORIGIN.constant_gas_cost().expr()), + ..Default::default() + }; + let same_context = SameContextGadget::construct(cb, opcode, step_state_transition); + + Self { + tx_id, + origin, + same_context, + } + } + + fn assign_exec_step( + &self, + region: &mut Region<'_, F>, + offset: usize, + block: &Block, + tx: &Transaction, + _: &Call, + step: &ExecStep, + ) -> Result<(), Error> { + let origin = block.rws.sorted_stack_rw()[0].stack_value(); + + // Assing TxId. + self.tx_id + .assign(region, offset, Some(F::from(tx.id as u64)))?; + + // Assign Origin addr RLC. + self.origin.assign( + region, + offset, + Some( + origin.to_le_bytes()[..N_BYTES_ACCOUNT_ADDRESS] + .try_into() + .unwrap(), + ), + )?; + + // Assign SameContextGadget witnesses. + self.same_context.assign_exec_step(region, offset, step)?; + Ok(()) + } +} + +#[cfg(test)] +mod test { + use crate::test_util::run_test_circuits; + use eth_types::bytecode; + use mock::TestContext; + + #[test] + fn origin_gadget_test() { + let bytecode = bytecode! { + ORIGIN + STOP + }; + + assert_eq!( + run_test_circuits( + TestContext::<2, 1>::simple_ctx_with_bytecode(bytecode).unwrap(), + None + ), + Ok(()) + ); + } +} diff --git a/zkevm-circuits/src/evm_circuit/witness.rs b/zkevm-circuits/src/evm_circuit/witness.rs index d032af8d5f..0047923781 100644 --- a/zkevm-circuits/src/evm_circuit/witness.rs +++ b/zkevm-circuits/src/evm_circuit/witness.rs @@ -1109,6 +1109,7 @@ impl From<&circuit_input_builder::ExecStep> for ExecutionState { OpcodeId::CALLDATACOPY => ExecutionState::CALLDATACOPY, OpcodeId::ISZERO => ExecutionState::ISZERO, OpcodeId::CALL => ExecutionState::CALL, + OpcodeId::ORIGIN => ExecutionState::ORIGIN, _ => unimplemented!("unimplemented opcode {:?}", op), } }