Skip to content

Commit

Permalink
Add circuit for RETURNDATASIZE opcode (privacy-scaling-explorations#703)
Browse files Browse the repository at this point in the history
* Add circuit for RETURNDATASIZE opcode

* Update tests

* update last call info in return (#2)

Signed-off-by: smtmfft <[email protected]>

Signed-off-by: smtmfft <[email protected]>

* Update tests

* Update tests

* Update format in zkevm-circuits/src/evm_circuit/execution.rs

* Change unwrap to expect in returndatasize.rs

* Add circuit for RETURNDATASIZE opcode

* Update tests

* update last call info in return (#2)

Signed-off-by: smtmfft <[email protected]>

Signed-off-by: smtmfft <[email protected]>

* Update tests

* Update tests

* Update format in zkevm-circuits/src/evm_circuit/execution.rs

* Change unwrap to expect in returndatasize.rs

* according to RETURN spec, callee info update happens only in case C, (#3)

i.e., only if it is not root call.

RETURN spec:

The `RETURN` opcode terminates the call successfully with return data for the
caller.

It behaves differently in different scenarios:

- `is_create` and `is_root`
    - A. Returns the specified memory chunk as deployment code.
    - B. End the execution
- `is_create` and `not is_root`
    - A. Returns the specified memory chunk as deployment code.
    - C. Restores caller's context and switch to it.
- `not is_create` and `is_root`
    - B. End the execution
- `not is_create` and `not is_root`
    - D. Returns the specified memory chunk to the caller.
    - C. Restores caller's context and switch to it.

Signed-off-by: smtmfft <[email protected]>

Signed-off-by: smtmfft <[email protected]>
Co-authored-by: smtmfft <[email protected]>

* Fix the issues with rustfmt

* Fix merge conflicts

* Update

* Add tests

* Resolve merge conflicts

* Update bus-mapping return.rs, use N_BYTES_U64 for return_data_size and update tests

* Revert change in bus-mapping return

* Update bus-mapping returndatasize_tests

Signed-off-by: smtmfft <[email protected]>
Signed-off-by: smtmfft <[email protected]>
Co-authored-by: smtmfft <[email protected]>
Co-authored-by: smtmfft <[email protected]>
Co-authored-by: Rohit Narurkar <[email protected]>
Co-authored-by: Carlos Pérez <[email protected]>
Co-authored-by: z2trillion <[email protected]>
Co-authored-by: adria0.eth <[email protected]>
  • Loading branch information
7 people authored Oct 29, 2022
1 parent 044d995 commit 103ddd7
Show file tree
Hide file tree
Showing 5 changed files with 343 additions and 4 deletions.
4 changes: 3 additions & 1 deletion bus-mapping/src/evm/opcodes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ mod number;
mod origin;
mod r#return;
mod returndatacopy;
mod returndatasize;
mod selfbalance;
mod sha3;
mod sload;
Expand Down Expand Up @@ -76,6 +77,7 @@ use mstore::Mstore;
use origin::Origin;
use r#return::Return;
use returndatacopy::Returndatacopy;
use returndatasize::Returndatasize;
use selfbalance::Selfbalance;
use sload::Sload;
use sstore::Sstore;
Expand Down Expand Up @@ -161,7 +163,7 @@ fn fn_gen_associated_ops(opcode_id: &OpcodeId) -> FnGenAssociatedOps {
OpcodeId::CODESIZE => Codesize::gen_associated_ops,
OpcodeId::EXTCODESIZE => Extcodesize::gen_associated_ops,
OpcodeId::EXTCODECOPY => Extcodecopy::gen_associated_ops,
OpcodeId::RETURNDATASIZE => StackOnlyOpcode::<0, 1>::gen_associated_ops,
OpcodeId::RETURNDATASIZE => Returndatasize::gen_associated_ops,
OpcodeId::RETURNDATACOPY => Returndatacopy::gen_associated_ops,
OpcodeId::EXTCODEHASH => Extcodehash::gen_associated_ops,
OpcodeId::BLOCKHASH => StackOnlyOpcode::<1, 1>::gen_associated_ops,
Expand Down
163 changes: 163 additions & 0 deletions bus-mapping/src/evm/opcodes/returndatasize.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
use crate::{
circuit_input_builder::{CircuitInputStateRef, ExecStep},
operation::CallContextField,
Error,
};

use eth_types::GethExecStep;

use super::Opcode;

#[derive(Clone, Copy, Debug)]
pub(crate) struct Returndatasize;

impl Opcode for Returndatasize {
fn gen_associated_ops(
state: &mut CircuitInputStateRef,
geth_steps: &[GethExecStep],
) -> Result<Vec<ExecStep>, Error> {
let geth_step = &geth_steps[0];
let mut exec_step = state.new_step(geth_step)?;
let value = geth_steps[1].stack.last()?;
state.call_context_read(
&mut exec_step,
state.call()?.call_id,
CallContextField::LastCalleeReturnDataLength,
value,
);

state.stack_write(
&mut exec_step,
geth_step.stack.last_filled().map(|a| a - 1),
value,
)?;

Ok(vec![exec_step])
}
}

#[cfg(test)]
mod returndatasize_tests {
use crate::circuit_input_builder::CircuitsParams;
use crate::{
circuit_input_builder::ExecState,
mock::BlockData,
operation::{CallContextField, CallContextOp, StackOp, RW},
};
use eth_types::{
bytecode,
evm_types::{OpcodeId, StackAddress},
geth_types::GethData,
word, Word,
};
use mock::test_ctx::{helpers::*, TestContext};
use pretty_assertions::assert_eq;

#[test]
fn test_ok() {
let return_data_size = 0x20;

// // deployed contract
// PUSH1 0x20
// PUSH1 0
// PUSH1 0
// CALLDATACOPY
// PUSH1 0x20
// PUSH1 0
// RETURN
//
// bytecode: 0x6020600060003760206000F3
//
// // constructor
// PUSH12 0x6020600060003760206000F3
// PUSH1 0
// MSTORE
// PUSH1 0xC
// PUSH1 0x14
// RETURN
//
// bytecode: 0x6B6020600060003760206000F3600052600C6014F3
let code = bytecode! {
PUSH21(word!("6B6020600060003760206000F3600052600C6014F3"))
PUSH1(0)
MSTORE

PUSH1 (0x15)
PUSH1 (0xB)
PUSH1 (0)
CREATE

PUSH1 (0x20)
PUSH1 (0x20)
PUSH1 (0x20)
PUSH1 (0)
PUSH1 (0)
DUP6
PUSH2 (0xFFFF)
CALL

RETURNDATASIZE

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_with_params(
block.clone(),
CircuitsParams {
max_rws: 512,
..Default::default()
},
)
.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::RETURNDATASIZE))
.unwrap();

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::LastCalleeReturnDataLength,
value: Word::from(return_data_size),
}
)
);
assert_eq!(
{
let operation =
&builder.block.container.stack[step.bus_mapping_instance[1].as_usize()];
(operation.rw(), operation.op())
},
(
RW::WRITE,
&StackOp::new(
call_id,
StackAddress::from(1021),
Word::from(return_data_size)
)
)
);
}
}
6 changes: 4 additions & 2 deletions zkevm-circuits/src/evm_circuit/execution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ mod pc;
mod pop;
mod push;
mod r#return;
mod returndatasize;
mod sdiv_smod;
mod selfbalance;
mod sha3;
Expand Down Expand Up @@ -123,6 +124,7 @@ use pc::PcGadget;
use pop::PopGadget;
use push::PushGadget;
use r#return::ReturnGadget;
use returndatasize::ReturnDataSizeGadget;
use sdiv_smod::SignedDivModGadget;
use selfbalance::SelfbalanceGadget;
use shl_shr::ShlShrGadget;
Expand Down Expand Up @@ -220,7 +222,7 @@ pub(crate) struct ExecutionConfig<F> {
sar_gadget: DummyGadget<F, 2, 1, { ExecutionState::SAR }>,
extcodesize_gadget: DummyGadget<F, 1, 1, { ExecutionState::EXTCODESIZE }>,
extcodecopy_gadget: DummyGadget<F, 4, 0, { ExecutionState::EXTCODECOPY }>,
returndatasize_gadget: DummyGadget<F, 0, 1, { ExecutionState::RETURNDATASIZE }>,
returndatasize_gadget: ReturnDataSizeGadget<F>,
returndatacopy_gadget: DummyGadget<F, 3, 0, { ExecutionState::RETURNDATACOPY }>,
create_gadget: DummyGadget<F, 3, 1, { ExecutionState::CREATE }>,
callcode_gadget: DummyGadget<F, 7, 1, { ExecutionState::CALLCODE }>,
Expand Down Expand Up @@ -980,6 +982,7 @@ impl<F: Field> ExecutionConfig<F> {
ExecutionState::POP => assign_exec_step!(self.pop_gadget),
ExecutionState::PUSH => assign_exec_step!(self.push_gadget),
ExecutionState::RETURN => assign_exec_step!(self.return_gadget),
ExecutionState::RETURNDATASIZE => assign_exec_step!(self.returndatasize_gadget),
ExecutionState::SCMP => assign_exec_step!(self.signed_comparator_gadget),
ExecutionState::SDIV_SMOD => assign_exec_step!(self.sdiv_smod_gadget),
ExecutionState::BLOCKCTXU64 => assign_exec_step!(self.block_ctx_u64_gadget),
Expand All @@ -993,7 +996,6 @@ impl<F: Field> ExecutionConfig<F> {
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::RETURNDATASIZE => assign_exec_step!(self.returndatasize_gadget),
ExecutionState::RETURNDATACOPY => assign_exec_step!(self.returndatacopy_gadget),
ExecutionState::CREATE => assign_exec_step!(self.create_gadget),
ExecutionState::CALLCODE => assign_exec_step!(self.callcode_gadget),
Expand Down
Loading

0 comments on commit 103ddd7

Please sign in to comment.