Skip to content
This repository was archived by the owner on Apr 18, 2025. It is now read-only.
Merged
18 changes: 16 additions & 2 deletions bus-mapping/src/circuit_input_builder/execution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use crate::{
use eth_types::{
evm_types::{memory::MemoryWordRange, Gas, GasCost, MemoryAddress, OpcodeId, ProgramCounter},
sign_types::SignData,
Field, GethExecStep, ToLittleEndian, Word, H256, U256,
Address, Field, GethExecStep, ToLittleEndian, Word, H256, U256,
};
use ethers_core::k256::elliptic_curve::subtle::CtOption;
use gadgets::impl_expr;
Expand Down Expand Up @@ -228,6 +228,7 @@ pub enum CopyDataType {
/// tx-table and destination is rw-table.
AccessListStorageKeys,
}

impl CopyDataType {
/// How many bits are necessary to represent a copy data type.
pub const N_BITS: usize = 3usize;
Expand All @@ -247,6 +248,8 @@ impl CopyDataTypeIter {
3usize => Some(CopyDataType::TxCalldata),
4usize => Some(CopyDataType::TxLog),
5usize => Some(CopyDataType::RlcAcc),
6usize => Some(CopyDataType::AccessListAddresses),
7usize => Some(CopyDataType::AccessListStorageKeys),
_ => None,
}
}
Expand Down Expand Up @@ -363,6 +366,12 @@ pub enum NumberOrHash {
Hash(H256),
}

impl Default for NumberOrHash {
fn default() -> Self {
Self::Number(0)
}
}

/// Represents all bytes related in one copy event.
///
/// - When the source is memory, `bytes` is the memory content, including masked areas. The
Expand Down Expand Up @@ -404,7 +413,7 @@ impl CopyBytes {
/// Defines a copy event associated with EVM opcodes such as CALLDATACOPY,
/// CODECOPY, CREATE, etc. More information:
/// <https://github.com/privacy-scaling-explorations/zkevm-specs/blob/master/specs/copy-proof.md>.
#[derive(Clone, Debug)]
#[derive(Clone, Debug, Default)]
pub struct CopyEvent {
/// Represents the start address at the source of the copy event.
pub src_addr: u64,
Expand All @@ -428,6 +437,11 @@ pub struct CopyEvent {
pub rw_counter_start: RWCounter,
/// Represents the list of bytes related during this copy event
pub copy_bytes: CopyBytes,
/// Represents transaction access list (EIP-2930), if copy data type is
/// address, the first item is access list address and second is zero, if
/// copy data type is storage key, the first item is access list address and
/// second is access list storage key.
pub access_list: Vec<(Address, Word)>,
Comment thread
roynalnaruto marked this conversation as resolved.
}

pub type CopyEventSteps = Vec<(u8, bool, bool)>;
Expand Down
29 changes: 26 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 @@ -16,8 +16,8 @@ use crate::{
exec_trace::OperationRef,
operation::{
AccountField, AccountOp, CallContextField, CallContextOp, MemoryOp, Op, OpEnum, Operation,
StackOp, Target, TxAccessListAccountOp, TxLogField, TxLogOp, TxReceiptField, TxReceiptOp,
RW,
StackOp, Target, TxAccessListAccountOp, TxAccessListAccountStorageOp, TxLogField, TxLogOp,
TxReceiptField, TxReceiptOp, RW,
},
precompile::{is_precompiled, PrecompileCalls},
state_db::{CodeDB, StateDB},
Expand Down Expand Up @@ -591,7 +591,7 @@ impl<'a> CircuitInputStateRef<'a> {
/// adds a reference to the stored operation ([`OperationRef`]) inside
/// the bus-mapping instance of the current [`ExecStep`]. Then increase
/// the `block_ctx` [`RWCounter`](crate::operation::RWCounter) by one.
pub fn tx_accesslist_account_write(
pub fn tx_access_list_account_write(
&mut self,
step: &mut ExecStep,
tx_id: usize,
Expand All @@ -611,6 +611,29 @@ impl<'a> CircuitInputStateRef<'a> {
)
}

/// Add address storage key to access list for the current transaction.
pub fn tx_access_list_storage_key_write(
&mut self,
step: &mut ExecStep,
tx_id: usize,
address: Address,
key: Word,
is_warm: bool,
is_warm_prev: bool,
) -> Result<(), Error> {
self.push_op(
step,
RW::WRITE,
TxAccessListAccountStorageOp {
tx_id,
address,
key,
is_warm,
is_warm_prev,
},
)
}

/// Push 2 reversible [`AccountOp`] to update `sender` and `receiver`'s
/// balance by `value`. If `fee` is existing (not None), also need to push 1
/// non-reversible [`AccountOp`] to update `sender` balance by `fee`.
Expand Down
142 changes: 101 additions & 41 deletions bus-mapping/src/evm/opcodes/begin_end_tx.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use super::TxExecSteps;
use crate::{
circuit_input_builder::{
CircuitInputStateRef, CopyBytes, CopyDataType, CopyEvent, ExecState, ExecStep, NumberOrHash,
Expand All @@ -16,13 +17,10 @@ use eth_types::{
gas_utils::{tx_access_list_gas_cost, tx_data_gas_cost},
GasCost, MAX_REFUND_QUOTIENT_OF_GAS_USED,
},
geth_types::access_list_size,
Bytecode, ToWord, Word,
};
use ethers_core::utils::get_contract_address;

use super::TxExecSteps;

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

Expand Down Expand Up @@ -146,7 +144,7 @@ pub fn gen_begin_tx_steps(state: &mut CircuitInputStateRef) -> Result<ExecStep,
for address in 1..=9 {
let address = eth_types::Address::from_low_u64_be(address);
let is_warm_prev = !state.sdb.add_account_to_access_list(address);
state.tx_accesslist_account_write(
state.tx_access_list_account_write(
&mut exec_step,
state.tx_ctx.id(),
address,
Expand All @@ -171,7 +169,7 @@ pub fn gen_begin_tx_steps(state: &mut CircuitInputStateRef) -> Result<ExecStep,
let accessed_addresses = [call.caller_address, call.address];
for address in accessed_addresses {
let is_warm_prev = !state.sdb.add_account_to_access_list(address);
state.tx_accesslist_account_write(
state.tx_access_list_account_write(
&mut exec_step,
state.tx_ctx.id(),
address,
Expand Down Expand Up @@ -316,6 +314,7 @@ pub fn gen_begin_tx_steps(state: &mut CircuitInputStateRef) -> Result<ExecStep,
log_id: None,
rw_counter_start,
copy_bytes: CopyBytes::new(bytes, None, None),
..Default::default()
},
);
}
Expand Down Expand Up @@ -628,46 +627,107 @@ fn gen_tx_eip2930_ops(
return Ok(());
}

let tx_id = NumberOrHash::Number(state.tx_ctx.id());
let (address_size, storage_key_size) = access_list_size(&state.tx.access_list);
add_access_list_address_copy_event(state, exec_step)?;
add_access_list_storage_key_copy_event(state, exec_step)?;

Ok(())
}

fn add_access_list_address_copy_event(
state: &mut CircuitInputStateRef,
exec_step: &mut ExecStep,
) -> Result<(), Error> {
let tx_id = state.tx_ctx.id();

// Add copy event for access-list addresses.
// Build copy access list including addresses.
let access_list = if let Some(access_list) = state.tx.access_list.clone() {
let mut addresses = Vec::with_capacity(access_list.0.len());

for item in access_list.0.iter() {
// Add RW write operations for access list addresses
// (will lookup in copy circuit).
state.tx_access_list_account_write(exec_step, tx_id, item.address, true, false)?;

addresses.push((item.address, 0.into()));
}

addresses
} else {
vec![]
};
Comment thread
lispc marked this conversation as resolved.
Outdated

let tx_id = NumberOrHash::Number(tx_id);
let rw_counter_start = state.block_ctx.rwc;
state.push_copy(
exec_step,
CopyEvent {
src_addr: 0,
src_addr_end: address_size,
src_type: CopyDataType::AccessListAddresses,
src_id: tx_id.clone(),
dst_addr: 0,
dst_type: CopyDataType::AccessListAddresses,
dst_id: tx_id.clone(),
log_id: None,
rw_counter_start,
// TODO
copy_bytes: CopyBytes::new(vec![], None, None),
},
);
let copy_bytes = CopyBytes::new(vec![(0, false, false); access_list.len()], None, None);

// Add copy event to copy table.
let copy_event = CopyEvent {
src_type: CopyDataType::AccessListAddresses,
src_id: tx_id,
src_addr: 1, // index starts from 1.
src_addr_end: access_list.len() as u64 + 1,
rw_counter_start,
copy_bytes,
access_list,
..Default::default()
};

state.push_copy(exec_step, copy_event);

Ok(())
}

fn add_access_list_storage_key_copy_event(
state: &mut CircuitInputStateRef,
exec_step: &mut ExecStep,
) -> Result<(), Error> {
let tx_id = state.tx_ctx.id();

// Build copy access list including addresses and storage keys.
let access_list = if let Some(access_list) = state.tx.access_list.clone() {
let mut address_storage_keys = vec![];

for item in access_list.0.iter() {
for storage_key in item.storage_keys.iter() {
let storage_key = storage_key.to_word();

// Add RW write operations for access list address storage keys
// (will lookup in copy circuit).
state.tx_access_list_storage_key_write(
exec_step,
tx_id,
item.address,
storage_key,
true,
false,
)?;

address_storage_keys.push((item.address, storage_key));
}
}

address_storage_keys
} else {
vec![]
};
Comment thread
silathdiir marked this conversation as resolved.
Outdated

// Add copy event for access-list storage keys.
let rw_counter_start = state.block_ctx.rwc;
state.push_copy(
exec_step,
CopyEvent {
src_addr: 0,
src_addr_end: storage_key_size,
src_type: CopyDataType::AccessListStorageKeys,
src_id: tx_id.clone(),
dst_addr: 0,
dst_type: CopyDataType::AccessListStorageKeys,
dst_id: tx_id,
log_id: None,
rw_counter_start,
// TODO
copy_bytes: CopyBytes::new(vec![], None, None),
},
);
let tx_id = NumberOrHash::Number(state.tx_ctx.id());
let copy_bytes = CopyBytes::new(vec![(0, false, false); access_list.len()], None, None);

// Add copy event to copy table.
let copy_event = CopyEvent {
src_type: CopyDataType::AccessListStorageKeys,
src_id: tx_id,
src_addr: 1, // index starts from 1 in tx-table.
src_addr_end: access_list.len() as u64 + 1,
rw_counter_start,
copy_bytes,
access_list,
..Default::default()
};

state.push_copy(exec_step, copy_event);

Ok(())
}
2 changes: 2 additions & 0 deletions bus-mapping/src/evm/opcodes/calldatacopy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ fn gen_copy_event(
log_id: None,
rw_counter_start,
copy_bytes,
..Default::default()
})
} else {
let (read_steps, write_steps, prev_bytes) =
Expand All @@ -137,6 +138,7 @@ fn gen_copy_event(
rw_counter_start,
//fetch pre read and write bytes of CopyBytes
copy_bytes: CopyBytes::new(read_steps, Some(write_steps), Some(prev_bytes)),
..Default::default()
})
}
}
Expand Down
3 changes: 3 additions & 0 deletions bus-mapping/src/evm/opcodes/callop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,7 @@ impl<const N_ARGS: usize> Opcode for CallOpcode<N_ARGS> {
log_id: None,
rw_counter_start,
copy_bytes: CopyBytes::new(copy_steps, None, None),
..Default::default()
Comment thread
roynalnaruto marked this conversation as resolved.
Outdated
},
);
Some(input_bytes)
Expand Down Expand Up @@ -412,6 +413,7 @@ impl<const N_ARGS: usize> Opcode for CallOpcode<N_ARGS> {
log_id: None,
rw_counter_start,
copy_bytes: CopyBytes::new(copy_steps, None, Some(prev_bytes)),
..Default::default()
},
);
Some(output_bytes)
Expand Down Expand Up @@ -451,6 +453,7 @@ impl<const N_ARGS: usize> Opcode for CallOpcode<N_ARGS> {
Some(write_steps),
Some(prev_bytes),
),
..Default::default()
},
);
Some(returned_bytes)
Expand Down
1 change: 1 addition & 0 deletions bus-mapping/src/evm/opcodes/codecopy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ fn gen_copy_event(
rw_counter_start,
//fetch pre write bytes of CopyBytes
copy_bytes: CopyBytes::new(copy_steps, None, Some(prev_bytes)),
..Default::default()
})
}

Expand Down
1 change: 1 addition & 0 deletions bus-mapping/src/evm/opcodes/create.rs
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,7 @@ fn handle_copy(
dst_addr: 0,
log_id: None,
copy_bytes: CopyBytes::new(copy_steps, None, None),
..Default::default()
},
);

Expand Down
1 change: 1 addition & 0 deletions bus-mapping/src/evm/opcodes/extcodecopy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ fn gen_copy_event(
log_id: None,
rw_counter_start,
copy_bytes: CopyBytes::new(copy_steps, None, Some(prev_bytes)),
..Default::default()
})
}

Expand Down
1 change: 1 addition & 0 deletions bus-mapping/src/evm/opcodes/logs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ fn gen_copy_event(
log_id: Some(state.tx_ctx.log_id as u64 + 1),
rw_counter_start,
copy_bytes: CopyBytes::new(read_steps, Some(write_steps), None),
..Default::default()
})
}

Expand Down
2 changes: 2 additions & 0 deletions bus-mapping/src/evm/opcodes/return_revert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,7 @@ fn handle_copy(
dst_addr: destination.offset.try_into().unwrap(),
log_id: None,
copy_bytes: CopyBytes::new(read_steps, Some(write_steps), Some(dst_data_prev)),
..Default::default()
},
);

Expand Down Expand Up @@ -348,6 +349,7 @@ fn handle_create(
dst_addr: 0,
log_id: None,
copy_bytes: CopyBytes::new(copy_steps, None, None),
..Default::default()
},
);

Expand Down
1 change: 1 addition & 0 deletions bus-mapping/src/evm/opcodes/returndatacopy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ fn gen_copy_event(
log_id: None,
rw_counter_start,
copy_bytes: CopyBytes::new(read_steps, Some(write_steps), Some(prev_bytes)),
..Default::default()
})
}

Expand Down
Loading