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

Commit

Permalink
Fix witness generation logic, update circuits with missing gates (#33)
Browse files Browse the repository at this point in the history
  • Loading branch information
jules authored Oct 20, 2023
1 parent f89c09d commit f776180
Show file tree
Hide file tree
Showing 8 changed files with 104 additions and 53 deletions.
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

0 comments on commit f776180

Please sign in to comment.