Skip to content
This repository was archived by the owner on Jul 5, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
8 changes: 6 additions & 2 deletions bus-mapping/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,25 @@ license = "MIT OR Apache-2.0"
eth-types = { path = "../eth-types" }
gadgets = { path = "../gadgets" }
keccak256 = { path = "../keccak256" }
mock = { path = "../mock", optional = true }

ethers-core = "0.6"
ethers-providers = "0.6"
halo2_proofs = { version = "0.1.0-beta.1" }
itertools = "0.10"
lazy_static = "1.4"
log = "0.4.14"
rand = { version = "0.8", optional = true }
serde = {version = "1.0.130", features = ["derive"] }
serde_json = "1.0.66"
strum = "0.24"
strum_macros = "0.24"

[dev-dependencies]
hex = "0.4.3"
mock = { path = "../mock" }
pretty_assertions = "1.0.0"
rand = "0.8"
tokio = { version = "1.13", features = ["macros"] }
url = "2.2.2"

[features]
test = ["mock", "rand"]
3 changes: 3 additions & 0 deletions bus-mapping/src/evm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,6 @@ pub(crate) mod opcodes;

pub use eth_types::evm_types::opcode_ids::OpcodeId;
pub use opcodes::Opcode;

#[cfg(any(feature = "test", test))]
pub use opcodes::{gen_sha3_code, MemoryKind};
3 changes: 3 additions & 0 deletions bus-mapping/src/evm/opcodes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ use eth_types::{
use keccak256::EMPTY_HASH;
use log::warn;

#[cfg(any(feature = "test", test))]
pub use sha3::sha3_tests::{gen_sha3_code, MemoryKind};

mod call;
mod calldatacopy;
mod calldataload;
Expand Down
43 changes: 27 additions & 16 deletions bus-mapping/src/evm/opcodes/sha3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,8 @@ impl Opcode for Sha3 {
}
}

#[cfg(test)]
mod sha3_tests {
#[cfg(any(feature = "test", test))]
pub mod sha3_tests {
use eth_types::{bytecode, evm_types::OpcodeId, geth_types::GethData, Bytecode, Word};
use ethers_core::utils::keccak256;
use mock::{
Expand All @@ -120,18 +120,9 @@ mod sha3_tests {
operation::{MemoryOp, RWCounter, StackOp, RW},
};

enum MemoryKind {
Empty,
LessThanSize,
EqualToSize,
MoreThanSize,
}

fn rand_bytes(size: usize) -> Vec<u8> {
(0..size).map(|_| random()).collect::<Vec<u8>>()
}

fn test_ok(offset: usize, size: usize, mem_kind: MemoryKind) {
/// Generate bytecode for SHA3 opcode after having populated sufficient
/// memory given the offset and size arguments for SHA3.
pub fn gen_sha3_code(offset: usize, size: usize, mem_kind: MemoryKind) -> (Bytecode, Vec<u8>) {
let mut rng = rand::thread_rng();
let data_len = match mem_kind {
MemoryKind::LessThanSize => offset + rng.gen_range(0..size),
Expand All @@ -158,8 +149,6 @@ mod sha3_tests {
code.push(32, (32 * i).into());
code.write_op(OpcodeId::MSTORE);
}
let memory_len = memory.len();

// append SHA3 related opcodes at the tail end.
let code_tail = bytecode! {
PUSH32(size)
Expand All @@ -168,6 +157,28 @@ mod sha3_tests {
STOP
};
code.append(&code_tail);
(code, memory)
}

/// Memory of a context with respect to the input size to SHA3.
pub enum MemoryKind {
/// Variant defining empty memory.
Empty,
/// Variant defining memory length being less than size.
LessThanSize,
/// Variant defining memory length being equal to size.
EqualToSize,
/// Variant defining memory length being more than size.
MoreThanSize,
}

fn rand_bytes(size: usize) -> Vec<u8> {
(0..size).map(|_| random()).collect::<Vec<u8>>()
}

fn test_ok(offset: usize, size: usize, mem_kind: MemoryKind) {
let (code, memory) = gen_sha3_code(offset, size, mem_kind);
let memory_len = memory.len();

// The memory that is hashed.
let mut memory_view = memory
Expand Down
1 change: 1 addition & 0 deletions zkevm-circuits/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ num-bigint = { version = "0.4" }
subtle = "2.4"

[dev-dependencies]
bus-mapping = { path = "../bus-mapping", features = ["test"] }
criterion = "0.3"
ctor = "0.1.22"
env_logger = "0.9.0"
Expand Down
21 changes: 20 additions & 1 deletion zkevm-circuits/src/copy_circuit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,7 @@ impl<F: Field> CopyCircuit<F> {
.filter(|s| s.rw.is_write())
.map(|s| s.value)
.collect::<Vec<u8>>();
rlc::value(&values, block.randomness)
rlc::value(values.iter().rev(), block.randomness)
} else {
F::zero()
};
Expand Down Expand Up @@ -670,6 +670,7 @@ mod tests {
use super::*;
use bus_mapping::{
circuit_input_builder::{CircuitInputBuilder, CopyDataType},
evm::{gen_sha3_code, MemoryKind},
mock::BlockData,
operation::RWCounter,
};
Expand Down Expand Up @@ -802,6 +803,17 @@ mod tests {
builder
}

fn gen_sha3_data() -> CircuitInputBuilder {
let (code, _) = gen_sha3_code(0x20, 0x200, MemoryKind::EqualToSize);
let test_ctx = TestContext::<2, 1>::simple_ctx_with_bytecode(code).unwrap();
let block: GethData = test_ctx.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();
builder
}

#[test]
fn copy_circuit_valid_calldatacopy() {
let builder = gen_calldatacopy_data();
Expand All @@ -816,6 +828,13 @@ mod tests {
assert!(run_circuit(10, block).is_ok());
}

#[test]
fn copy_circuit_valid_sha3() {
let builder = gen_codecopy_data();
let block = block_convert(&builder.block, &builder.code_db);
assert!(run_circuit(20, block).is_ok());
}

fn perturb_tag(block: &mut bus_mapping::circuit_input_builder::Block, tag: CopyDataType) {
debug_assert!(!block.copy_events.is_empty());
debug_assert!(!block.copy_events[0].steps.is_empty());
Expand Down
39 changes: 16 additions & 23 deletions zkevm-circuits/src/evm_circuit/execution/sha3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ impl<F: Field> ExecutionGadget<F> for Sha3Gadget<F> {
let values: Vec<u8> = (3..3 + (size.low_u64() as usize))
.map(|i| block.rws[step.rw_indices[i]].memory_value())
.collect();
let rlc_acc = rlc::value(&values, block.randomness);
let rlc_acc = rlc::value(values.iter().rev(), block.randomness);
self.rlc_acc.assign(region, offset, Some(rlc_acc))?;

// Memory expansion and dynamic gas cost for reading it.
Expand All @@ -145,19 +145,13 @@ impl<F: Field> ExecutionGadget<F> for Sha3Gadget<F> {

#[cfg(test)]
mod tests {
use eth_types::bytecode;
use bus_mapping::evm::{gen_sha3_code, MemoryKind};
use mock::TestContext;

use crate::test_util::run_test_circuits;

#[test]
fn sha3_gadget_simple() {
let code = bytecode! {
PUSH32(0x08) // size
PUSH32(0x00) // offset
SHA3
STOP
};
fn test_ok(offset: usize, size: usize, mem_kind: MemoryKind) {
let (code, _) = gen_sha3_code(offset, size, mem_kind);
assert_eq!(
run_test_circuits(
TestContext::<2, 1>::simple_ctx_with_bytecode(code).unwrap(),
Expand All @@ -167,20 +161,19 @@ mod tests {
);
}

#[test]
fn sha3_gadget_simple() {
test_ok(0x00, 0x08, MemoryKind::Empty);
test_ok(0x10, 0x10, MemoryKind::LessThanSize);
test_ok(0x24, 0x16, MemoryKind::EqualToSize);
test_ok(0x32, 0x78, MemoryKind::MoreThanSize);
}

#[test]
fn sha3_gadget_large() {
let code = bytecode! {
PUSH32(0x101)
PUSH32(0x202)
SHA3
STOP
};
assert_eq!(
run_test_circuits(
TestContext::<2, 1>::simple_ctx_with_bytecode(code).unwrap(),
None
),
Ok(())
);
test_ok(0x101, 0x202, MemoryKind::Empty);
test_ok(0x202, 0x303, MemoryKind::LessThanSize);
test_ok(0x303, 0x404, MemoryKind::EqualToSize);
test_ok(0x404, 0x505, MemoryKind::MoreThanSize);
}
}
2 changes: 1 addition & 1 deletion zkevm-circuits/src/evm_circuit/witness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1207,6 +1207,7 @@ impl From<&circuit_input_builder::ExecStep> for ExecutionState {
OpcodeId::DIFFICULTY | OpcodeId::BASEFEE => ExecutionState::BLOCKCTXU256,
OpcodeId::GAS => ExecutionState::GAS,
OpcodeId::SELFBALANCE => ExecutionState::SELFBALANCE,
OpcodeId::SHA3 => ExecutionState::SHA3,
OpcodeId::SHR => ExecutionState::SHR,
OpcodeId::SLOAD => ExecutionState::SLOAD,
OpcodeId::SSTORE => ExecutionState::SSTORE,
Expand All @@ -1221,7 +1222,6 @@ impl From<&circuit_input_builder::ExecStep> for ExecutionState {
OpcodeId::CODESIZE => ExecutionState::CODESIZE,
OpcodeId::RETURN | OpcodeId::REVERT => ExecutionState::RETURN,
// dummy ops
OpcodeId::SHA3 => dummy!(ExecutionState::SHA3),
OpcodeId::ADDRESS => dummy!(ExecutionState::ADDRESS),
OpcodeId::BALANCE => dummy!(ExecutionState::BALANCE),
OpcodeId::BLOCKHASH => dummy!(ExecutionState::BLOCKHASH),
Expand Down
2 changes: 1 addition & 1 deletion zkevm-circuits/src/table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -771,7 +771,7 @@ impl CopyTable {
.filter(|s| s.rw.is_write())
.map(|s| s.value)
.collect::<Vec<u8>>();
rlc::value(&values, randomness)
rlc::value(values.iter().rev(), randomness)
} else {
F::zero()
};
Expand Down