Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Resolve merge conflict for zkevm-circuits/src/evm_circuit/witness.rs #2

Open
wants to merge 43 commits into
base: opcodes/returndatacopy
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
219b303
Add circuit for RETURNDATASIZE opcode
xiaodino Aug 22, 2022
dce1366
Update tests
xiaodino Aug 25, 2022
3a1d151
update last call info in return (#2)
smtmfft Aug 27, 2022
d162713
Update tests
xiaodino Aug 27, 2022
f3d78c4
Merge branch 'xiaodino/returndatasize' of github.com:xiaodino/zkevm-c…
xiaodino Aug 27, 2022
d8891b7
Update tests
xiaodino Aug 27, 2022
69080e1
Update format in zkevm-circuits/src/evm_circuit/execution.rs
xiaodino Aug 27, 2022
fde42c3
Change unwrap to expect in returndatasize.rs
xiaodino Aug 27, 2022
aed1d7d
Add circuit for RETURNDATASIZE opcode
xiaodino Aug 22, 2022
012cea4
Update tests
xiaodino Aug 25, 2022
136fad9
update last call info in return (#2)
smtmfft Aug 27, 2022
c0b8872
Update tests
xiaodino Aug 27, 2022
2955c3d
Update tests
xiaodino Aug 27, 2022
7a03cb4
Update format in zkevm-circuits/src/evm_circuit/execution.rs
xiaodino Aug 27, 2022
fbdaa0e
Change unwrap to expect in returndatasize.rs
xiaodino Aug 27, 2022
c4f4237
according to RETURN spec, callee info update happens only in case C, …
smtmfft Aug 29, 2022
3dda80d
Merge branch 'xiaodino/returndatasize' of github.com:xiaodino/zkevm-c…
xiaodino Aug 29, 2022
6f7766c
Fix the issues with rustfmt
xiaodino Aug 29, 2022
0ee04d2
Fix merge conflicts
xiaodino Aug 29, 2022
eb35689
Merge branch 'main' into xiaodino/returndatasize
xiaodino Aug 29, 2022
fddfaa7
Update
xiaodino Aug 30, 2022
25371f6
Merge branch 'xiaodino/returndatasize' of github.com:xiaodino/zkevm-c…
xiaodino Aug 30, 2022
0dc902b
Add tests
xiaodino Aug 30, 2022
bfccd63
Merge branch 'main' into xiaodino/returndatasize
roynalnaruto Aug 31, 2022
2591c14
Merge branch 'main' into xiaodino/returndatasize
roynalnaruto Aug 31, 2022
dfdf1a7
Merge branch 'main' into xiaodino/returndatasize
CPerezz Sep 2, 2022
2267a2b
Merge branch 'main' into xiaodino/returndatasize
roynalnaruto Sep 2, 2022
45869a6
Merge branch 'main' into xiaodino/returndatasize
roynalnaruto Sep 3, 2022
72094ed
Merge branch 'main' into xiaodino/returndatasize
CPerezz Sep 6, 2022
f6e55be
Resolve conflicts
xiaodino Sep 8, 2022
34711d2
Merge branch 'xiaodino/returndatasize' of github.com:xiaodino/zkevm-c…
xiaodino Sep 8, 2022
56cff65
Resolve merge conflicts
xiaodino Sep 8, 2022
d6db32e
Merge pull request #5 from xiaodino/xiaodino/returndatasize
xiaodino Sep 11, 2022
1a09d03
add return data copy execution
Sep 5, 2022
cccadc0
fix returndatacopy op code bus mapping and simple test case
Sep 6, 2022
4cf811c
fix RETURNDATACOPY tracer test
Sep 7, 2022
63dced2
generate copy step & init copy table in returndatacopy bus mapping
Sep 7, 2022
650a4c3
update last callee info correctly
Sep 8, 2022
4a66505
copy return data from current call_ctx's return[] buf
Sep 8, 2022
9c15715
add return data memory write op into return opcode's bus mapping logic
Sep 9, 2022
4fe4216
add copy out of bound check
Sep 9, 2022
f02626d
fix rebase
Sep 11, 2022
adf28b5
Resolve merge conflict for zkevm-circuits/src/evm_circuit/witness.rs
xiaodino Sep 11, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions bus-mapping/src/circuit_input_builder/call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ pub struct Call {
pub call_id: usize,
/// Caller's id.
pub caller_id: usize,
/// Last Callee's id.
pub last_callee_id: usize,
/// Type of call
pub kind: CallKind,
/// This call is being executed without write access (STATIC)
Expand Down Expand Up @@ -87,6 +89,10 @@ pub struct Call {
pub return_data_offset: u64,
/// Return data length
pub return_data_length: u64,
/// last callee's return data offset
pub last_callee_return_data_offset: u64,
/// last callee's return data length
pub last_callee_return_data_length: u64,
}

impl Call {
Expand Down
26 changes: 23 additions & 3 deletions bus-mapping/src/circuit_input_builder/input_state_ref.rs
Original file line number Diff line number Diff line change
Expand Up @@ -476,6 +476,13 @@ impl<'a> CircuitInputStateRef<'a> {
.map(|caller_idx| &self.tx.calls()[caller_idx])
}

/// Mutable reference to the current call's caller Call
pub fn caller_mut(&mut self) -> Result<&mut Call, Error> {
self.tx_ctx
.caller_index()
.map(|caller_idx| &mut self.tx.calls_mut()[caller_idx])
}

/// Reference to the current Call
pub fn call(&self) -> Result<&Call, Error> {
self.tx_ctx
Expand Down Expand Up @@ -641,6 +648,7 @@ impl<'a> CircuitInputStateRef<'a> {
let call = Call {
call_id: self.block_ctx.rwc.0,
caller_id: caller.call_id,
last_callee_id: 0,
kind,
is_static: kind == CallKind::StaticCall || caller.is_static,
is_root: false,
Expand All @@ -657,6 +665,8 @@ impl<'a> CircuitInputStateRef<'a> {
call_data_length,
return_data_offset,
return_data_length,
last_callee_return_data_offset: 0,
last_callee_return_data_length: 0,
};

Ok(call)
Expand Down Expand Up @@ -797,11 +807,11 @@ impl<'a> CircuitInputStateRef<'a> {
pub fn handle_return(&mut self, step: &GethExecStep) -> Result<(), Error> {
let call = self.call()?.clone();
let call_ctx = self.call_ctx()?;
let offset = step.stack.nth_last(0)?;
let length = step.stack.nth_last(1)?;

// Store deployed code if it's a successful create
if call.is_create() && call.is_success && step.op == OpcodeId::RETURN {
let offset = step.stack.nth_last(0)?;
let length = step.stack.nth_last(1)?;
let code = call_ctx
.memory
.read_chunk(offset.low_u64().into(), length.low_u64().into());
Expand All @@ -818,8 +828,18 @@ impl<'a> CircuitInputStateRef<'a> {
self.handle_reversion();
}

self.tx_ctx.pop_call_ctx();
// If current call has caller.
// TODO: use is_root??
match self.caller_mut() {
Ok(caller) => {
caller.last_callee_id = call.call_id;
caller.last_callee_return_data_length = call.return_data_length;
caller.last_callee_return_data_offset = call.return_data_offset;
}
Err(_) => {}
}

self.tx_ctx.pop_call_ctx();
Ok(())
}

Expand Down
7 changes: 4 additions & 3 deletions bus-mapping/src/circuit_input_builder/tracer_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1193,9 +1193,7 @@ fn tracer_err_return_data_out_of_bounds() {
accs[0]
.address(address!("0x0000000000000000000000000000000000000000"))
.code(code_a);
accs[1]
.address(address!("0x000000000000000000000000000000000cafe001"))
.code(code_b);
accs[1].address(*ADDR_B).code(code_b);
accs[2]
.address(address!("0x000000000000000000000000000000000cafe002"))
.balance(Word::from(1u64 << 30));
Expand Down Expand Up @@ -1372,6 +1370,7 @@ fn tracer_err_write_protection() {
builder.state_ref().push_call(Call {
call_id: 0,
caller_id: 0,
last_callee_id: 0,
kind: CallKind::StaticCall,
is_static: true,
is_root: false,
Expand All @@ -1388,6 +1387,8 @@ fn tracer_err_write_protection() {
call_data_length: 0,
return_data_offset: 0,
return_data_length: 0,
last_callee_return_data_offset: 0,
last_callee_return_data_length: 0,
});

assert_eq!(
Expand Down
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
33 changes: 32 additions & 1 deletion bus-mapping/src/evm/opcodes/return.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::circuit_input_builder::{CircuitInputStateRef, ExecStep};
use crate::evm::Opcode;
use crate::operation::CallContextField;
use crate::Error;
use eth_types::GethExecStep;

Expand All @@ -12,7 +13,7 @@ impl Opcode for Return {
geth_steps: &[GethExecStep],
) -> Result<Vec<ExecStep>, Error> {
let geth_step = &geth_steps[0];
let exec_step = state.new_step(geth_step)?;
let mut exec_step = state.new_step(geth_step)?;

let current_call = state.call()?.clone();
let offset = geth_step.stack.nth_last(0)?.as_usize();
Expand All @@ -36,12 +37,42 @@ impl Opcode for Return {
caller_ctx.return_data.resize(length as usize, 0);
caller_ctx.return_data[0..copy_len]
.copy_from_slice(&memory.0[offset..offset + copy_len]);
(0..copy_len)
.map(|idx| {
state.memory_write(
&mut exec_step,
(return_offset + idx).into(),
memory.0[offset as usize + idx],
)
})
.collect::<Result<Vec<_>, _>>()?;
} else {
// dealing with contract creation
assert!(offset + length <= memory.0.len());
let code = memory.0[offset..offset + length].to_vec();
state.code_db.insert(code);
}

state.call_context_write(
&mut exec_step,
state.call()?.call_id,
CallContextField::LastCalleeId,
state.call()?.call_id.into(),
);

state.call_context_write(
&mut exec_step,
state.caller()?.call_id,
CallContextField::LastCalleeReturnDataOffset,
offset.into(),
);

state.call_context_write(
&mut exec_step,
state.caller()?.call_id,
CallContextField::LastCalleeReturnDataLength,
length.into(),
);
}

state.handle_return(&geth_steps[0])?;
Expand Down
146 changes: 142 additions & 4 deletions bus-mapping/src/evm/opcodes/returndatacopy.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
use crate::circuit_input_builder::{CircuitInputStateRef, ExecStep};
use crate::circuit_input_builder::{
CircuitInputStateRef, CopyDataType, CopyEvent, CopyStep, ExecStep, NumberOrHash,
};
use crate::evm::Opcode;
use crate::operation::{CallContextField, MemoryOp, RW};
use crate::Error;
use eth_types::GethExecStep;

Expand All @@ -12,16 +15,46 @@ impl Opcode for Returndatacopy {
geth_steps: &[GethExecStep],
) -> Result<Vec<ExecStep>, Error> {
// TODO: complete `ExecStep` and circuit implementation
let exec_step = state.new_step(&geth_steps[0])?;
let mut exec_step = state.new_step(&geth_steps[0])?;

// reconstruction
let geth_step = &geth_steps[0];
let dest_offset = geth_step.stack.nth_last(0)?;
let offset = geth_step.stack.nth_last(1)?;
let size = geth_step.stack.nth_last(2)?;

// can we reduce this clone?
let return_data = state.call_ctx()?.return_data.clone();
state.stack_read(
&mut exec_step,
geth_step.stack.nth_last_filled(0),
dest_offset,
)?;
state.stack_read(&mut exec_step, geth_step.stack.nth_last_filled(1), offset)?;
state.stack_read(&mut exec_step, geth_step.stack.nth_last_filled(2), size)?;

let call_id = state.call()?.call_id;
let call_ctx = state.call_ctx()?;
let return_data = call_ctx.return_data.clone();
let last_callee_return_data_offset = state.call()?.last_callee_return_data_offset;
let last_callee_return_data_length = state.call()?.last_callee_return_data_length;
assert_eq!(
last_callee_return_data_length as usize,
return_data.len(),
"callee return data size should be correct"
);

// read last callee info
for (field, value) in [
(
CallContextField::LastCalleeReturnDataOffset,
last_callee_return_data_offset.into(),
),
(
CallContextField::LastCalleeReturnDataLength,
return_data.len().into(),
),
] {
state.call_context_read(&mut exec_step, call_id, field, value);
}

let call_ctx = state.call_ctx_mut()?;
let memory = &mut call_ctx.memory;
Expand All @@ -41,10 +74,115 @@ impl Opcode for Returndatacopy {
// there is no more steps.
}
}

let copy_event = gen_copy_event(state, geth_step)?;
state.push_copy(copy_event);
Ok(vec![exec_step])
}
}

fn gen_copy_steps(
state: &mut CircuitInputStateRef,
exec_step: &mut ExecStep,
src_addr: u64,
dst_addr: u64,
src_addr_end: u64,
bytes_left: u64,
_is_root: bool,
) -> Result<Vec<CopyStep>, Error> {
let mut copy_steps = Vec::with_capacity(2 * bytes_left as usize);
for idx in 0..bytes_left {
let addr = src_addr + idx;
let rwc = state.block_ctx.rwc;
let (value, is_pad) = if addr < src_addr_end {
let byte = state.call_ctx()?.return_data
[(addr - state.call()?.last_callee_return_data_offset) as usize];
state.push_op(
exec_step,
RW::READ,
MemoryOp::new(state.call()?.last_callee_id, addr.into(), byte),
);
(byte, false)
} else {
//TODO: return out of bound
assert!(addr < src_addr_end, "return data copy out of bound");
(1, false)
};
let tag = CopyDataType::Memory;
// Read
copy_steps.push(CopyStep {
addr,
tag,
rw: RW::READ,
value,
is_code: None,
is_pad,
rwc,
rwc_inc_left: 0,
});
// Write
copy_steps.push(CopyStep {
addr: dst_addr + idx,
tag: CopyDataType::Memory,
rw: RW::WRITE,
value,
is_code: None,
is_pad: false,
rwc: state.block_ctx.rwc,
rwc_inc_left: 0,
});
state.memory_write(exec_step, (dst_addr + idx).into(), value)?;
}

for cs in copy_steps.iter_mut() {
cs.rwc_inc_left = state.block_ctx.rwc.0 as u64 - cs.rwc.0 as u64;
}

Ok(copy_steps)
}

fn gen_copy_event(
state: &mut CircuitInputStateRef,
geth_step: &GethExecStep,
) -> Result<CopyEvent, Error> {
let dst_memory_offset = geth_step.stack.nth_last(0)?.as_u64();
let data_offset = geth_step.stack.nth_last(1)?.as_u64();
let length = geth_step.stack.nth_last(2)?.as_u64();

let last_callee_return_data_offset = state.call()?.last_callee_return_data_offset;
let last_callee_return_data_length = state.call()?.last_callee_return_data_length;
let (src_addr, src_addr_end) = (
last_callee_return_data_offset + data_offset,
last_callee_return_data_offset + last_callee_return_data_length,
);

let mut exec_step = state.new_step(geth_step)?;
let copy_steps = gen_copy_steps(
state,
&mut exec_step,
src_addr,
dst_memory_offset,
src_addr_end,
length,
state.call()?.is_root,
)?;

let (src_type, src_id) = (CopyDataType::Memory, state.call()?.call_id);

Ok(CopyEvent {
src_type,
src_id: NumberOrHash::Number(src_id),
src_addr,
src_addr_end,
dst_type: CopyDataType::Memory,
dst_id: NumberOrHash::Number(src_id),
dst_addr: dst_memory_offset,
log_id: None,
length,
steps: copy_steps,
})
}

#[cfg(test)]
mod return_tests {
use crate::mock::BlockData;
Expand Down
Loading