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

Simulate memory queues in parallel for BWG #166

Merged
merged 35 commits into from
Aug 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
ee09313
Init parallelization
0xVolosnikov Jul 22, 2024
dd5d583
Run sorted queue simulation and callstack simulation in separate threads
0xVolosnikov Jul 22, 2024
35a4827
Remove unused implicit memory queries amount calculation
0xVolosnikov Jul 22, 2024
6f4b1dc
Cargo fmt
0xVolosnikov Jul 22, 2024
bec123d
Simplify memory queue states accumulation
0xVolosnikov Jul 22, 2024
d9ec995
Cargo fmt
0xVolosnikov Jul 23, 2024
6105dd6
Fix memory-related circuits
0xVolosnikov Jul 23, 2024
a1f0072
Cleanup in simulate_implicit_memory_queues
0xVolosnikov Jul 23, 2024
bf879fe
Cargo fmt
0xVolosnikov Jul 23, 2024
a6353b4
Unpack structures for memory-related circuits
0xVolosnikov Jul 23, 2024
a5b2605
Cargo fmt
0xVolosnikov Jul 23, 2024
c692816
Cleanup
0xVolosnikov Jul 23, 2024
5c7a988
Merge remote-tracking branch 'origin/v1.5.0' into vv-oracle-paralleli…
0xVolosnikov Aug 8, 2024
389812e
Unify callbacks
0xVolosnikov Aug 8, 2024
2dc6e67
Simulate queues in parts
0xVolosnikov Aug 8, 2024
4bb9690
cleanup
0xVolosnikov Aug 9, 2024
f18e144
Remove excessive cloning
0xVolosnikov Aug 9, 2024
c63514d
Move MemoryArtifacts out of simulate_memory_queue
0xVolosnikov Aug 9, 2024
1861080
fix tests
0xVolosnikov Aug 9, 2024
7ccde37
Do not store unneeded encodings in stack simulator
0xVolosnikov Aug 9, 2024
0bdab6e
Add more profiling
0xVolosnikov Aug 9, 2024
bdacaa5
Fix encodings test
0xVolosnikov Aug 12, 2024
6f6c629
Cargo fmt
0xVolosnikov Aug 12, 2024
fda6a4d
Merge branch 'v1.5.0' into vv-oracle-parallelization2
0xVolosnikov Aug 12, 2024
8bda472
Add comments; Cleanup
0xVolosnikov Aug 13, 2024
d78428f
Remove unused code
0xVolosnikov Aug 13, 2024
8ee8349
Cleanup in RAM permutation circuit
0xVolosnikov Aug 13, 2024
7ed6111
Update comments in ram_permutation
0xVolosnikov Aug 13, 2024
07b81bd
Update WitnessGenerationArtifact definition
0xVolosnikov Aug 13, 2024
d7fd754
Move MemoryQueueStateWitnesses definition to circuit_encodings
0xVolosnikov Aug 13, 2024
de4b511
Simplify WitnessGenerationArtifact enum
0xVolosnikov Aug 14, 2024
9d5e200
Remove RAM profiling
0xVolosnikov Aug 14, 2024
ee759eb
Cargo fmt
0xVolosnikov Aug 14, 2024
ba9ce62
Remove unnecessary structs from ram permutation processing
0xVolosnikov Aug 14, 2024
c714745
Add comment in ram_permutation
0xVolosnikov Aug 15, 2024
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
27 changes: 14 additions & 13 deletions circuit_encodings/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -316,8 +316,6 @@ impl<
pub struct FullWidthQueueIntermediateStates<F: SmallField, const SW: usize, const ROUNDS: usize> {
pub head: [F; SW],
pub tail: [F; SW],
pub old_head: [F; SW],
pub old_tail: [F; SW],
pub num_items: u32,
pub round_function_execution_pairs: [([F; SW], [F; SW]); ROUNDS],
}
Expand Down Expand Up @@ -433,8 +431,6 @@ impl<
let intermediate_info = FullWidthQueueIntermediateStates {
head: self.head,
tail: new_tail,
old_head: self.head,
old_tail,
num_items: self.num_items,
round_function_execution_pairs: states,
};
Expand Down Expand Up @@ -473,8 +469,6 @@ impl<
let intermediate_info = FullWidthQueueIntermediateStates {
head: self.head,
tail: self.tail,
old_head,
old_tail: self.tail,
num_items: self.num_items,
round_function_execution_pairs: states,
};
Expand Down Expand Up @@ -562,6 +556,12 @@ impl<
}
}

pub fn replace_container(mut self, container: C) -> (Self, C) {
let prev_container = self.witness;
self.witness = container;
(self, prev_container)
}

pub fn take_sponge_like_queue_state(&self) -> QueueStateWitness<F, SW> {
let result = QueueStateWitness {
head: self.head,
Expand Down Expand Up @@ -605,8 +605,6 @@ impl<
let intermediate_info = FullWidthQueueIntermediateStates {
head: self.head,
tail: new_tail,
old_head: self.head,
old_tail,
num_items: self.num_items,
round_function_execution_pairs: states,
};
Expand Down Expand Up @@ -644,7 +642,7 @@ pub struct FullWidthStackSimulator<
> {
pub state: [F; SW],
pub num_items: u32,
pub witness: Vec<([F; N], [F; SW], I)>,
pub witness: Vec<([F; SW], I)>,
}

impl<
Expand Down Expand Up @@ -697,7 +695,7 @@ impl<

let states = make_round_function_pairs(old_state, states);

self.witness.push((encoding, self.state, element));
self.witness.push((self.state, element));
self.num_items += 1;
self.state = new_state;

Expand Down Expand Up @@ -727,7 +725,7 @@ impl<
let popped = self.witness.pop().unwrap();
self.num_items -= 1;

let (_element_encoding, previous_state, element) = popped;
let (previous_state, element) = popped;
let encoding = element.encoding_witness();

let mut state = previous_state;
Expand Down Expand Up @@ -867,6 +865,9 @@ mod tests {
}
assert_eq!(queue.num_items, 10);

let old_head = queue.head;
let old_tail = queue.tail;

// pop one element
let (element, data) = queue.pop_and_output_intermediate_data(&round_function);
// it should return the first one that we entered (with circuit 0).
Expand All @@ -876,8 +877,8 @@ mod tests {
assert_eq!(data.num_items, 9);

assert_eq!(data.head, tail_after_first);
assert_eq!(data.old_head, empty_head);
assert_eq!(data.old_tail, data.tail);
assert_eq!(old_head, empty_head);
assert_eq!(data.tail, old_tail);

let mut parts = queue.split_by(3, &round_function);

Expand Down
4 changes: 4 additions & 0 deletions circuit_encodings/src/memory_query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,3 +157,7 @@ impl<F: SmallField> CircuitEquivalentReflection<F> for MemoryQuery {
}
}
}

use zkevm_circuits::base_structures::memory_query::MemoryQueryWitness;
pub type MemoryQueueStateWitnesses<F> =
Vec<(MemoryQueryWitness<F>, [F; FULL_SPONGE_QUEUE_STATE_WIDTH])>;
17 changes: 4 additions & 13 deletions src/external_calls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ pub use crate::run_vms::SCHEDULER_TIMESTAMP;
use crate::snark_wrapper::boojum::field::goldilocks::GoldilocksExt2;
use crate::snark_wrapper::boojum::gadgets::recursion::recursive_tree_hasher::CircuitGoldilocksPoseidon2Sponge;
use crate::toolset::GeometryConfig;
use crate::witness::oracle::WitnessGenerationArtifact;
use crate::witness::tree::BinarySparseStorageTree;
use crate::witness::tree::ZkSyncStorageLeaf;
use crate::zk_evm::abstractions::Storage;
Expand All @@ -28,15 +29,7 @@ use circuit_definitions::Field as MainField;
///
/// This function will setup the environment and will run out-of-circuit and then in-circuit.
/// GenericNoopTracer will be used as out-of-circuit tracer
pub fn run<
S: Storage,
CB: FnMut(ZkSyncBaseLayerCircuit),
QSCB: FnMut(
u64,
RecursionQueueSimulator<MainField>,
Vec<ClosedFormInputCompactFormWitness<MainField>>,
),
>(
pub fn run<S: Storage, CB: FnMut(WitnessGenerationArtifact)>(
caller: Address, // for real block must be zero
entry_point_address: Address, // for real block must be the bootloader
entry_point_code: Vec<[u8; 32]>, // for read block must be a bootloader code
Expand All @@ -52,8 +45,7 @@ pub fn run<
tree: impl BinarySparseStorageTree<256, 32, 32, 8, 32, Blake2s256, ZkSyncStorageLeaf>,
trusted_setup_path: &str,
eip_4844_repack_inputs: [Option<Vec<u8>>; MAX_4844_BLOBS_PER_BLOCK],
circuit_callback: CB,
queue_simulator_callback: QSCB,
artifacts_callback: CB,
) -> (
SchedulerCircuitInstanceWitness<MainField, CircuitGoldilocksPoseidon2Sponge, GoldilocksExt2>,
BlockAuxilaryOutputWitness<MainField>,
Expand All @@ -75,8 +67,7 @@ pub fn run<
tree,
trusted_setup_path,
eip_4844_repack_inputs,
circuit_callback,
queue_simulator_callback,
artifacts_callback,
&mut out_of_circuit_tracer,
) {
Ok((scheduler_circuit_witness, aux_data)) => (scheduler_circuit_witness, aux_data),
Expand Down
17 changes: 4 additions & 13 deletions src/run_vms.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use crate::snark_wrapper::boojum::gadgets::recursion::recursive_tree_hasher::Cir
use crate::toolset::create_tools;
use crate::toolset::GeometryConfig;
use crate::witness::oracle::create_artifacts_from_tracer;
use crate::witness::oracle::WitnessGenerationArtifact;
use crate::witness::tracer::tracer::WitnessTracer;
use crate::witness::tree::BinarySparseStorageTree;
use crate::witness::tree::ZkSyncStorageLeaf;
Expand Down Expand Up @@ -61,15 +62,7 @@ pub type RunVMsResult = (
/// - witness with AUX data (with information that might be useful during verification to generate the public input)
///
/// This function will setup the environment and will run out-of-circuit and then in-circuit
pub fn run_vms<
S: Storage,
CB: FnMut(ZkSyncBaseLayerCircuit),
QSCB: FnMut(
u64,
RecursionQueueSimulator<MainField>,
Vec<ClosedFormInputCompactFormWitness<MainField>>,
),
>(
pub fn run_vms<S: Storage, CB: FnMut(WitnessGenerationArtifact)>(
caller: Address, // for real block must be zero
entry_point_address: Address, // for real block must be the bootloader
entry_point_code: Vec<[u8; 32]>, // for read block must be a bootloader code
Expand All @@ -85,8 +78,7 @@ pub fn run_vms<
tree: impl BinarySparseStorageTree<256, 32, 32, 8, 32, Blake2s256, ZkSyncStorageLeaf>,
trusted_setup_path: &str,
eip_4844_repack_inputs: [Option<Vec<u8>>; MAX_4844_BLOBS_PER_BLOCK],
circuit_callback: CB,
queue_simulator_callback: QSCB,
artifacts_callback: CB,
out_of_circuit_tracer: &mut impl Tracer<SupportedMemory = SimpleMemory>,
) -> Result<RunVMsResult, RunVmError> {
let round_function = ZkSyncDefaultRoundFunction::default();
Expand Down Expand Up @@ -254,8 +246,7 @@ pub fn run_vms<
evm_simulator_code_hash,
eip_4844_repack_inputs.clone(),
trusted_setup_path,
circuit_callback,
queue_simulator_callback,
artifacts_callback,
);

let (scheduler_circuit_witness, aux_data) = {
Expand Down
53 changes: 43 additions & 10 deletions src/tests/complex_tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ use crate::zk_evm::GenericNoopTracer;
use crate::zkevm_circuits::eip_4844::input::*;
use crate::zkevm_circuits::scheduler::block_header::MAX_4844_BLOBS_PER_BLOCK;
use crate::zkevm_circuits::scheduler::input::SchedulerCircuitInstanceWitness;
use boojum::gadgets::queue::full_state_queue::FullStateCircuitQueueRawWitness;
use circuit_definitions::aux_definitions::witness_oracle::VmWitnessOracle;
use circuit_definitions::circuit_definitions::aux_layer::compression::{
self, CompressionMode1Circuit,
Expand All @@ -58,6 +59,7 @@ use circuit_definitions::{
use circuit_definitions::{Field, RoundFunction};
use utils::read_basic_test_artifact;

use witness::oracle::WitnessGenerationArtifact;
use zkevm_assembly::Assembly;

#[ignore = "Too slow"]
Expand Down Expand Up @@ -255,6 +257,27 @@ pub(crate) fn generate_base_layer(

let mut basic_block_circuits = vec![];
let mut recursion_queues = vec![];
let mut unsorted_memory_queue_witnesses = vec![];
let mut sorted_memory_queue_witnesses = vec![];

let artifacts_callback = |artifact: WitnessGenerationArtifact| match artifact {
WitnessGenerationArtifact::BaseLayerCircuit(circuit) => basic_block_circuits.push(circuit),
WitnessGenerationArtifact::RecursionQueue((a, b, c)) => recursion_queues.push((
a,
b,
c.into_iter()
.map(|x| ZkSyncBaseLayerStorage::from_inner(a as u8, x))
.collect(),
)),
WitnessGenerationArtifact::MemoryQueueWitness((witnesses, sorted)) => {
if sorted {
sorted_memory_queue_witnesses.push(witnesses);
} else {
unsorted_memory_queue_witnesses.push(witnesses);
}
}
};

let (scheduler_partial_input, _aux_data) = run(
Address::zero(),
test_artifact.entry_point_address,
Expand All @@ -271,18 +294,28 @@ pub(crate) fn generate_base_layer(
tree,
"kzg/src/trusted_setup.json",
blobs,
|circuit| basic_block_circuits.push(circuit),
|a, b, c| {
recursion_queues.push((
a,
b,
c.into_iter()
.map(|x| ZkSyncBaseLayerStorage::from_inner(a as u8, x))
.collect(),
))
},
artifacts_callback,
);

let mut unsorted_memory_queue_witnesses_it = unsorted_memory_queue_witnesses.into_iter();
let mut sorted_memory_queue_witnesses = sorted_memory_queue_witnesses.into_iter();
for el in basic_block_circuits.iter_mut() {
match &el {
ZkSyncBaseLayerCircuit::RAMPermutation(inner) => {
let mut witness = inner.witness.take().unwrap();
witness.sorted_queue_witness = FullStateCircuitQueueRawWitness {
elements: sorted_memory_queue_witnesses.next().unwrap().into(),
};
witness.unsorted_queue_witness = FullStateCircuitQueueRawWitness {
elements: unsorted_memory_queue_witnesses_it.next().unwrap().into(),
};

inner.witness.store(Some(witness));
}
_ => {}
}
}

(
basic_block_circuits,
recursion_queues,
Expand Down
35 changes: 33 additions & 2 deletions src/tests/run_manually.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,11 @@ use crate::zk_evm::witness_trace::VmWitnessTracer;
use crate::zk_evm::GenericNoopTracer;
use crate::zkevm_circuits::base_structures::vm_state::GlobalContextWitness;
use crate::zkevm_circuits::main_vm::main_vm_entry_point;
use boojum::gadgets::queue::full_state_queue::FullStateCircuitQueueRawWitness;
use circuit_definitions::aux_definitions::witness_oracle::VmWitnessOracle;
use circuit_definitions::zk_evm::vm_state::cycle;
use storage::{InMemoryCustomRefundStorage, StorageRefund};
use witness::oracle::WitnessGenerationArtifact;
use zkevm_assembly::Assembly;

#[test]
Expand Down Expand Up @@ -260,11 +262,25 @@ pub(crate) fn run_with_options(entry_point_bytecode: Vec<[u8; 32]>, options: Opt
save_predeployed_contracts(&mut storage_impl.storage, &mut tree, &known_contracts);

let mut basic_block_circuits = vec![];
let mut unsorted_memory_queue_witnesses = vec![];
let mut sorted_memory_queue_witnesses = vec![];

// we are using TestingTracer to track prints and exceptions inside out_of_circuit_vm cycles
let mut out_of_circuit_tracer =
TestingTracer::new(Some(storage_impl.create_refund_controller()));

let artifacts_callback = |artifact: WitnessGenerationArtifact| match artifact {
WitnessGenerationArtifact::BaseLayerCircuit(circuit) => basic_block_circuits.push(circuit),
WitnessGenerationArtifact::MemoryQueueWitness((witnesses, sorted)) => {
if sorted {
sorted_memory_queue_witnesses.push(witnesses)
} else {
unsorted_memory_queue_witnesses.push(witnesses)
}
}
_ => {}
};

if let Err(err) = run_vms(
Address::zero(),
*BOOTLOADER_FORMAL_ADDRESS,
Expand All @@ -281,8 +297,7 @@ pub(crate) fn run_with_options(entry_point_bytecode: Vec<[u8; 32]>, options: Opt
tree,
"kzg/src/trusted_setup.json",
std::array::from_fn(|_| None),
|circuit| basic_block_circuits.push(circuit),
|_, _, _| {},
artifacts_callback,
&mut out_of_circuit_tracer,
) {
let error_text = match err {
Expand All @@ -303,8 +318,24 @@ pub(crate) fn run_with_options(entry_point_bytecode: Vec<[u8; 32]>, options: Opt

println!("Simulation and witness creation are completed");

let mut unsorted_memory_queue_witnesses_it = unsorted_memory_queue_witnesses.into_iter();
let mut sorted_memory_queue_witnesses = sorted_memory_queue_witnesses.into_iter();
for el in basic_block_circuits {
println!("Doing {} circuit", el.short_description());
match &el {
ZkSyncBaseLayerCircuit::RAMPermutation(inner) => {
let mut witness = inner.witness.take().unwrap();
witness.sorted_queue_witness = FullStateCircuitQueueRawWitness {
elements: sorted_memory_queue_witnesses.next().unwrap().into(),
};
witness.unsorted_queue_witness = FullStateCircuitQueueRawWitness {
elements: unsorted_memory_queue_witnesses_it.next().unwrap().into(),
};

inner.witness.store(Some(witness));
}
_ => {}
}
base_test_circuit(el);
}

Expand Down
7 changes: 0 additions & 7 deletions src/witness/artifacts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,13 +121,6 @@ pub struct MemoryArtifacts<F: SmallField> {
CircuitsEntryAccumulatorSparse<(u32, QueueStateWitness<F, FULL_SPONGE_QUEUE_STATE_WIDTH>)>,
}

#[derive(Derivative)]
#[derivative(Default)]
pub struct ImplicitMemoryArtifacts<F: SmallField> {
pub memory_queries: Vec<MemoryQuery>,
pub memory_queue_states: Vec<MemoryQueueState<F>>,
}

#[derive(Derivative)]
#[derivative(Default)]
pub struct LogCircuitsArtifacts<F: SmallField> {
Expand Down
8 changes: 8 additions & 0 deletions src/witness/aux_data_structs/per_circuit_accumulator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ impl<T> PerCircuitAccumulatorContainer<T> {
self.accumulated
}

pub fn amount_of_circuits_accumulated(&self) -> usize {
self.circuits_data.len()
}

pub fn last(&self) -> Option<&T> {
let last_batch = self.circuits_data.last();
last_batch?;
Expand Down Expand Up @@ -181,6 +185,10 @@ impl<T> PerCircuitAccumulator<T> {
self.container.len()
}

pub fn amount_of_circuits_accumulated(&self) -> usize {
self.container.amount_of_circuits_accumulated()
}

pub fn push(&mut self, val: T) {
assert!(self.container.cycles_per_circuit != 0);
let idx = self.container.len();
Expand Down
Loading
Loading