Skip to content
This repository has been archived by the owner on Aug 16, 2024. It is now read-only.

Fix witness generation logic, update circuits with missing gates #33

Merged
merged 5 commits into from
Oct 20, 2023
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
1 change: 1 addition & 0 deletions circuit_definitions/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ zk_evm = {git = "https://github.com/matter-labs/era-zk_evm.git", branch = "v1.4.
derivative = "*"
serde = {version = "1", features = ["derive"]}
crossbeam = "0.8"
seq-macro = "0.3.5"

[features]
default = []
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,11 @@ pub struct ECRecoverFunctionInstanceSynthesisFunction<
_marker: std::marker::PhantomData<(F, R)>,
}

use zkevm_circuits::ecrecover::ecrecover_function_entry_point;
use zkevm_circuits::ecrecover::input::*;
use zkevm_circuits::ecrecover::{
decomp_table::*, ecrecover_function_entry_point, naf_abs_div2_table::*,
secp256k1::fixed_base_mul_table::*,
};

impl<
F: SmallField,
Expand Down Expand Up @@ -69,7 +72,10 @@ where
share_constants: false,
},
);

let builder = U8x4FMAGate::configure_builder(
builder,
GatePlacementStrategy::UseGeneralPurposeColumns,
);
let builder = ZeroCheckGate::configure_builder(
builder,
GatePlacementStrategy::UseGeneralPurposeColumns,
Expand All @@ -87,6 +93,10 @@ where
builder,
GatePlacementStrategy::UseGeneralPurposeColumns,
);
let builder = UIntXAddGate::<8>::configure_builder(
builder,
GatePlacementStrategy::UseGeneralPurposeColumns,
);
let builder = DotProductGate::<4>::configure_builder(
builder,
GatePlacementStrategy::UseGeneralPurposeColumns,
Expand Down Expand Up @@ -147,6 +157,31 @@ where
let table = create_and8_table();
cs.add_lookup_table::<And8Table, 3>(table);

let table = create_naf_abs_div2_table();
cs.add_lookup_table::<NafAbsDiv2Table, 3>(table);

let table = create_wnaf_decomp_table();
cs.add_lookup_table::<WnafDecompTable, 3>(table);

seq_macro::seq!(C in 0..32 {
let table = create_fixed_base_mul_table::<F, 0, C>();
cs.add_lookup_table::<FixedBaseMulTable<0, C>, 3>(table);
let table = create_fixed_base_mul_table::<F, 1, C>();
cs.add_lookup_table::<FixedBaseMulTable<1, C>, 3>(table);
let table = create_fixed_base_mul_table::<F, 2, C>();
cs.add_lookup_table::<FixedBaseMulTable<2, C>, 3>(table);
let table = create_fixed_base_mul_table::<F, 3, C>();
cs.add_lookup_table::<FixedBaseMulTable<3, C>, 3>(table);
let table = create_fixed_base_mul_table::<F, 4, C>();
cs.add_lookup_table::<FixedBaseMulTable<4, C>, 3>(table);
let table = create_fixed_base_mul_table::<F, 5, C>();
cs.add_lookup_table::<FixedBaseMulTable<5, C>, 3>(table);
let table = create_fixed_base_mul_table::<F, 6, C>();
cs.add_lookup_table::<FixedBaseMulTable<6, C>, 3>(table);
let table = create_fixed_base_mul_table::<F, 7, C>();
cs.add_lookup_table::<FixedBaseMulTable<7, C>, 3>(table);
});

let table = create_byte_split_table::<F, 1>();
cs.add_lookup_table::<ByteSplitTable<1>, 3>(table);
let table = create_byte_split_table::<F, 2>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,10 @@ where
builder,
GatePlacementStrategy::UseGeneralPurposeColumns,
);
let builder = UIntXAddGate::<8>::configure_builder(
builder,
GatePlacementStrategy::UseGeneralPurposeColumns,
);
let builder = SelectionGate::configure_builder(
builder,
GatePlacementStrategy::UseGeneralPurposeColumns,
Expand Down
2 changes: 1 addition & 1 deletion src/external_calls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ round_function: R, // used for all queues implementation
// dbg!(tools.witness_tracer.vm_snapshots.len());

let (instance_oracles, artifacts) = create_artifacts_from_tracer(
out_of_circuit_vm.witness_tracer,
&mut out_of_circuit_vm.witness_tracer,
&round_function,
&geometry,
(
Expand Down
10 changes: 8 additions & 2 deletions src/witness/individual_circuits/events_sort_dedup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ pub fn compute_events_dedup_and_sort<
// return singe dummy witness
use crate::boojum::gadgets::queue::QueueState;

let initial_fsm_state = EventsDeduplicatorFSMInputOutput::<F>::placeholder_witness();
let mut initial_fsm_state = EventsDeduplicatorFSMInputOutput::<F>::placeholder_witness();

assert_eq!(
take_queue_state_from_simulator(&unsorted_simulator),
Expand All @@ -44,7 +44,13 @@ pub fn compute_events_dedup_and_sort<
take_queue_state_from_simulator(&unsorted_simulator);
passthrough_input.intermediate_sorted_queue_state = QueueState::placeholder_witness();

let final_fsm_state = EventsDeduplicatorFSMInputOutput::<F>::placeholder_witness();
let mut final_fsm_state = EventsDeduplicatorFSMInputOutput::<F>::placeholder_witness();
// NOTE: little hack to make the trivial case work. we should really however remove the
// requirement to have trivial events sorter circuits in the scheduler.
initial_fsm_state.lhs_accumulator = [F::ONE; 2];
initial_fsm_state.rhs_accumulator = [F::ONE; 2];
final_fsm_state.lhs_accumulator = [F::ONE; 2];
final_fsm_state.rhs_accumulator = [F::ONE; 2];

let mut passthrough_output = EventsDeduplicatorOutputData::placeholder_witness();
passthrough_output.final_queue_state = QueueState::placeholder_witness();
Expand Down
85 changes: 44 additions & 41 deletions src/witness/individual_circuits/keccak256_round_function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,11 @@ pub fn keccak256_decompose_into_per_circuit_witness<
} = el;

// we read, then write
if let Some(reads) = reads.as_ref() {
artifacts.keccak_256_memory_queries.extend_from_slice(reads);
}
reads.iter().for_each(|read| {
if let Some(read) = read {
artifacts.keccak_256_memory_queries.push(*read);
}
});

if let Some(writes) = writes.as_ref() {
artifacts
Expand Down Expand Up @@ -204,9 +206,14 @@ pub fn keccak256_decompose_into_per_circuit_witness<
assert_eq!(request, _req);

// those are refreshed every cycle
let mut input_buffer = zk_evm::zk_evm_abstractions::precompiles::keccak256::Buffer::new();
use crate::zk_evm::zk_evm_abstractions::precompiles::keccak256::NEW_WORDS_PER_CYCLE;
let mut words_buffer = [0u64; NEW_WORDS_PER_CYCLE];
use crate::zk_evm::zk_evm_abstractions::precompiles::keccak256::KECCAK_PRECOMPILE_BUFFER_SIZE;
let mut input_buffer = zk_evm::zk_evm_abstractions::precompiles::keccak256::ByteBuffer {
bytes: [0u8; KECCAK_PRECOMPILE_BUFFER_SIZE],
filled: 0,
};
use crate::zk_evm::zk_evm_abstractions::precompiles::keccak256::MEMORY_READS_PER_CYCLE;
use crate::zk_evm::zk_evm_abstractions::precompiles::keccak256::NUM_WORDS_PER_QUERY;
let mut words_buffer = [0u8; NUM_WORDS_PER_QUERY * MEMORY_READS_PER_CYCLE * 8];

use crate::zk_evm::zk_evm_abstractions::precompiles::precompile_abi_in_log;
let mut precompile_request = precompile_abi_in_log(request);
Expand All @@ -219,25 +226,25 @@ pub fn keccak256_decompose_into_per_circuit_witness<

precompile_state = Keccak256PrecompileState::RunRoundFunction;

let needs_full_padding_round =
precompile_request.input_memory_length as usize % KECCAK_PRECOMPILE_BUFFER_SIZE == 0;

for (round_idx, round) in round_witness.into_iter().enumerate() {
// we proceed the request as long as we can
if round_idx == 0 {
assert!(round.new_request.is_some());
}

// simulate absorb
if input_buffer.can_read_into() {
if input_buffer.can_fill_bytes(NUM_WORDS_PER_QUERY * MEMORY_READS_PER_CYCLE * 8) {
use crate::zk_evm::zk_evm_abstractions::precompiles::keccak256::NUM_WORDS_PER_QUERY;
assert!(round.reads.is_some());
let reads = round.reads.unwrap();
for (query_index, read) in reads.into_iter().enumerate() {
let data = read.value;
let mut bytes32_buffer = [0u8; 32];
data.to_big_endian(&mut bytes32_buffer[..]);
for (i, chunk) in bytes32_buffer.chunks(8).enumerate() {
let as_u64 = u64::from_le_bytes(chunk.try_into().unwrap());
words_buffer[query_index * NUM_WORDS_PER_QUERY + i] = as_u64;
for (query_index, read) in round.reads.into_iter().enumerate() {
if read.is_none() {
continue;
}
let read = read.unwrap();
let data = read.value;
data.to_big_endian(&mut words_buffer[..]);

let read_query = memory_queries_it.next().unwrap();
assert_eq!(read, read_query);
Expand All @@ -255,10 +262,14 @@ pub fn keccak256_decompose_into_per_circuit_witness<
precompile_request.input_memory_offset += 1;
}

input_buffer.append(&words_buffer);
input_buffer.fill_with_bytes(&words_buffer, 0, 32);
}

let words = input_buffer.consume_rate();
let words: Vec<u64> = input_buffer
.consume::<KECCAK_PRECOMPILE_BUFFER_SIZE>()
.chunks(8)
.map(|chunk| u64::from_le_bytes(chunk.try_into().unwrap()))
.collect();
use crate::zk_evm::zk_evm_abstractions::precompiles::keccak256::KECCAK_RATE_IN_U64_WORDS;
let mut block = [0u8; KECCAK_RATE_IN_U64_WORDS * 8];

Expand Down Expand Up @@ -327,8 +338,8 @@ pub fn keccak256_decompose_into_per_circuit_witness<
for el in u64_words_buffer_markers.iter_mut() {
*el = false;
}
for el in input_buffer.words.iter_mut() {
*el = 0u64;
for el in input_buffer.bytes.iter_mut() {
*el = 0u8;
}
// internal state is a bit more tricky, it'll be a round over empty input
let mut internal_state_over_empty_buffer = Keccak256::default();
Expand All @@ -354,21 +365,29 @@ pub fn keccak256_decompose_into_per_circuit_witness<
let read_precompile_call =
precompile_state == Keccak256PrecompileState::GetRequestFromQueue;

let padding_round = read_unaligned_words_for_round
&& precompile_request.input_memory_length == 0
&& needs_full_padding_round;

let hidden_fsm_output_state = Keccak256RoundFunctionFSMWitness::<F> {
completed,
read_unaligned_words_for_round,
padding_round,
keccak_internal_state,
read_precompile_call,
timestamp_to_use_for_read: request.timestamp.0,
timestamp_to_use_for_write: request.timestamp.0 + 1,
u8_words_buffer: buffer_to_bytes(&input_buffer),
u64_words_buffer_markers,
precompile_call_params: Keccak256PrecompileCallParamsWitness::<F> {
input_page: precompile_request.memory_page_to_read,
input_offset: precompile_request.input_memory_offset,
input_memory_byte_offset: precompile_request.input_memory_offset,
input_memory_byte_length: precompile_request.input_memory_length,
output_page: precompile_request.memory_page_to_write,
output_offset: precompile_request.output_memory_offset,
num_rounds: num_rounds_left as u32,
output_word_offset: precompile_request.output_memory_offset,
needs_full_padding_round,
},
buffer: zkevm_circuits::keccak256_round_function::buffer::ByteBufferWitness {
bytes: input_buffer.bytes,
filled: input_buffer.filled as u8,
},
};

Expand Down Expand Up @@ -474,22 +493,6 @@ pub(crate) fn encode_kecca256_inner_state(state: [u64; 25]) -> [[[u8; 8]; 5]; 5]
result
}

fn buffer_to_bytes(
buffer: &zk_evm::zk_evm_abstractions::precompiles::keccak256::Buffer,
) -> [u8; zkevm_circuits::keccak256_round_function::BYTES_BUFFER_SIZE] {
assert_eq!(
zkevm_circuits::keccak256_round_function::BUFFER_SIZE_IN_U64_WORDS,
buffer.words.len()
);

let mut result = [0u8; zkevm_circuits::keccak256_round_function::BYTES_BUFFER_SIZE];
for (dst, src) in result.array_chunks_mut::<8>().zip(buffer.words.iter()) {
*dst = src.to_le_bytes();
}

result
}

// #[cfg(test)]
// mod test {
// use super::*;
Expand Down
4 changes: 3 additions & 1 deletion src/witness/individual_circuits/storage_application.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ use crate::boojum::sha3::digest::{FixedOutput, Update};
use crate::boojum::sha3::Keccak256;
use crate::witness::individual_circuits::keccak256_round_function::encode_kecca256_inner_state;
use crate::witness::tree::*;
use crate::zk_evm::zk_evm_abstractions::precompiles::keccak256::{transmute_state, BUFFER_SIZE};
use crate::zk_evm::zk_evm_abstractions::precompiles::keccak256::{
transmute_state, KECCAK_PRECOMPILE_BUFFER_SIZE,
};
use crate::zkevm_circuits::base_structures::state_diff_record::NUM_KECCAK256_ROUNDS_PER_RECORD_ACCUMULATION;
use crate::zkevm_circuits::storage_application::input::*;
use blake2::Blake2s256;
Expand Down
12 changes: 6 additions & 6 deletions src/witness/oracle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ pub fn create_artifacts_from_tracer<
F: SmallField,
R: BuildableCircuitRoundFunction<F, 8, 12, 4> + AlgebraicRoundFunction<F, 8, 12, 4>,
>(
tracer: WitnessTracer,
tracer: &mut WitnessTracer,
round_function: &R,
geometry: &GeometryConfig,
entry_point_decommittment_query: (DecommittmentQuery, Vec<U256>),
Expand Down Expand Up @@ -933,11 +933,11 @@ pub fn create_artifacts_from_tracer<
// when it potentially came into and out of scope

let mut artifacts = FullBlockArtifacts::<F>::default();
artifacts.vm_memory_queries_accumulated = vm_memory_queries_accumulated;
artifacts.all_decommittment_queries = decommittment_queries;
artifacts.keccak_round_function_witnesses = keccak_round_function_witnesses;
artifacts.sha256_round_function_witnesses = sha256_round_function_witnesses;
artifacts.ecrecover_witnesses = ecrecover_witnesses;
artifacts.vm_memory_queries_accumulated = vm_memory_queries_accumulated.to_vec();
artifacts.all_decommittment_queries = decommittment_queries.to_vec();
artifacts.keccak_round_function_witnesses = keccak_round_function_witnesses.to_vec();
artifacts.sha256_round_function_witnesses = sha256_round_function_witnesses.to_vec();
artifacts.ecrecover_witnesses = ecrecover_witnesses.to_vec();
artifacts.original_log_queue = original_log_queue;
artifacts.original_log_queue_simulator =
original_log_queue_simulator.unwrap_or(LogQueueSimulator::empty());
Expand Down