Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(prover): Update witness generator to zkevm_test_harness 0.150.6 #3029

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
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
6 changes: 3 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -217,15 +217,15 @@ circuit_sequencer_api_1_3_3 = { package = "circuit_sequencer_api", version = "0.
circuit_sequencer_api_1_4_0 = { package = "circuit_sequencer_api", version = "0.140" }
circuit_sequencer_api_1_4_1 = { package = "circuit_sequencer_api", version = "0.141" }
circuit_sequencer_api_1_4_2 = { package = "circuit_sequencer_api", version = "0.142" }
circuit_sequencer_api_1_5_0 = { package = "circuit_sequencer_api", version = "=0.150.5" }
circuit_sequencer_api_1_5_0 = { git = "https://github.com/matter-labs/zksync-protocol.git", package = "circuit_sequencer_api" }
crypto_codegen = { package = "zksync_solidity_vk_codegen", version = "=0.30.1" }
kzg = { package = "zksync_kzg", version = "=0.150.5" }
kzg = { git = "https://github.com/matter-labs/zksync-protocol.git", package = "zksync_kzg" }
zk_evm = { version = "=0.133.0" }
zk_evm_1_3_1 = { package = "zk_evm", version = "0.131.0-rc.2" }
zk_evm_1_3_3 = { package = "zk_evm", version = "0.133" }
zk_evm_1_4_0 = { package = "zk_evm", version = "0.140" }
zk_evm_1_4_1 = { package = "zk_evm", version = "0.141" }
zk_evm_1_5_0 = { package = "zk_evm", version = "=0.150.5" }
zk_evm_1_5_0 = { git = "https://github.com/matter-labs/zksync-protocol.git", package = "zk_evm" }

# New VM; pinned to a specific commit because of instability
zksync_vm2 = { git = "https://github.com/matter-labs/vm2.git", rev = "74577d9be13b1bff9d1a712389731f669b179e47" }
Expand Down
6 changes: 3 additions & 3 deletions prover/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,9 @@ tracing-subscriber = "0.3"
vise = "0.2.0"

# Proving dependencies
circuit_definitions = "=0.150.5"
circuit_sequencer_api = "=0.150.5"
zkevm_test_harness = "=0.150.5"
circuit_definitions = { git = "https://github.com/matter-labs/zksync-protocol.git", package = "circuit_definitions" }
circuit_sequencer_api = { git = "https://github.com/matter-labs/zksync-protocol.git", package = "circuit_sequencer_api" }
zkevm_test_harness = { git = "https://github.com/matter-labs/zksync-protocol.git", package = "zkevm_test_harness" }

# GPU proving dependencies
wrapper_prover = { package = "zksync-wrapper-prover", version = "=0.150.9" }
Expand Down
150 changes: 36 additions & 114 deletions prover/crates/bin/witness_generator/src/rounds/basic_circuits/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::{
};

use circuit_definitions::{
circuit_definitions::base_layer::{ZkSyncBaseLayerCircuit, ZkSyncBaseLayerStorage},
circuit_definitions::base_layer::ZkSyncBaseLayerStorage,
encodings::recursion_request::RecursionQueueSimulator,
zkevm_circuits::fsm_input_output::ClosedFormInputCompactFormWitness,
};
Expand All @@ -21,7 +21,7 @@ use zksync_multivm::{
zk_evm_latest::ethereum_types::Address,
};
use zksync_object_store::ObjectStore;
use zksync_prover_fri_types::{keys::ClosedFormInputKey, CircuitAuxData};
use zksync_prover_fri_types::keys::ClosedFormInputKey;
use zksync_prover_interface::inputs::WitnessInputData;
use zksync_system_constants::BOOTLOADER_ADDRESS;
use zksync_types::L1BatchNumber;
Expand All @@ -31,8 +31,7 @@ use crate::{
rounds::basic_circuits::Witness,
storage_oracle::StorageOracle,
utils::{
expand_bootloader_contents, save_circuit, save_ram_premutation_queue_witness,
ClosedFormInputWrapper, KZG_TRUSTED_SETUP_FILE,
expand_bootloader_contents, save_circuit, ClosedFormInputWrapper, KZG_TRUSTED_SETUP_FILE,
},
witness::WitnessStorage,
};
Expand Down Expand Up @@ -64,17 +63,38 @@ pub(super) async fn generate_witness(

let (circuit_sender, mut circuit_receiver) = tokio::sync::mpsc::channel(1);
let (queue_sender, mut queue_receiver) = tokio::sync::mpsc::channel(1);
let (ram_permutation_queue_sender, mut ram_permutation_queue_receiver) =
tokio::sync::mpsc::channel(1);

let make_circuits_span = tracing::info_span!("make_circuits");
let make_circuits_span_copy = make_circuits_span.clone();

use std::{sync::mpsc::sync_channel, thread};
let (artifacts_sender, artifacts_receiver) = sync_channel(1);

let artifacts_receiver_handle = thread::spawn(move || {
let span = tracing::info_span!(parent: make_circuits_span_copy, "make_circuits_blocking");

while let Ok(artifact) = artifacts_receiver.recv() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks fine, but shouldn't we do something if we can't receive? Maybe log the error?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like we can have only RecvError, which occurs if the sender is disconnected. This is the expected state after test_harness has finished its work, I don't think we want to log this.

match artifact {
WitnessGenerationArtifact::BaseLayerCircuit(circuit) => {
let parent_span = span.clone();
tracing::info_span!(parent: parent_span, "send_circuit").in_scope(|| {
circuit_sender
.blocking_send(circuit)
.expect("failed to send circuit from harness");
});
}
WitnessGenerationArtifact::RecursionQueue((a, b, c)) => queue_sender
.blocking_send((a as u8, b, c))
.expect("failed to send recursion queue from harness"),
_ => {}
}
}
});

// Blocking call from harness that does the CPU heavy lifting.
// Provides circuits and recursion queue via callback functions and returns scheduler witnesses.
// Circuits are "streamed" one by one as they're being generated.
let make_circuits_handle = tokio::task::spawn_blocking(move || {
let span = tracing::info_span!(parent: make_circuits_span_copy, "make_circuits_blocking");

let witness_storage = WitnessStorage::new(input.vm_run_data.witness_block_state);
let storage_view = StorageView::new(witness_storage).to_rc_ptr();

Expand All @@ -91,29 +111,6 @@ pub(super) async fn generate_witness(
.to_str()
.expect("Path to KZG trusted setup is not a UTF-8 string");

let artifacts_callback = |artifact: WitnessGenerationArtifact| match artifact {
WitnessGenerationArtifact::BaseLayerCircuit(circuit) => {
let parent_span = span.clone();
tracing::info_span!(parent: parent_span, "send_circuit").in_scope(|| {
circuit_sender
.blocking_send(circuit)
.expect("failed to send circuit from harness");
});
}
WitnessGenerationArtifact::RecursionQueue((a, b, c)) => queue_sender
.blocking_send((a as u8, b, c))
.expect("failed to send recursion queue from harness"),
a @ WitnessGenerationArtifact::MemoryQueueWitness(_) => {
let parent_span = span.clone();
tracing::info_span!(parent: parent_span, "send_ram_permutation_queue_witness")
.in_scope(|| {
ram_permutation_queue_sender
.blocking_send(a)
.expect("failed to send ram permutation queue sitness from harness");
});
}
};

let (scheduler_witness, block_witness) = zkevm_test_harness::external_calls::run(
Address::zero(),
BOOTLOADER_ADDRESS,
Expand All @@ -129,9 +126,9 @@ pub(super) async fn generate_witness(
geometry_config,
storage_oracle,
tree,
path,
path.to_owned(),
input.eip_4844_blobs.blobs(),
artifacts_callback,
artifacts_sender,
);
(scheduler_witness, block_witness)
})
Expand All @@ -150,8 +147,6 @@ pub(super) async fn generate_witness(
// If the order is tampered with, proving will fail (as the proof would be computed for a different sequence of instruction).
let mut circuit_sequence = 0;

let mut ram_circuit_sequence = 0;

while let Some(circuit) = circuit_receiver
.recv()
.instrument(tracing::info_span!("wait_for_circuit"))
Expand All @@ -166,84 +161,16 @@ pub(super) async fn generate_witness(
.await
.expect("failed to get permit for running save circuit task");

let partial_circuit_aux_data = match &circuit {
ZkSyncBaseLayerCircuit::RAMPermutation(_) => {
let circuit_subsequence_number = ram_circuit_sequence;
ram_circuit_sequence += 1;
Some(CircuitAuxData {
circuit_subsequence_number,
})
}
_ => None,
};

save_circuit_handles.push(tokio::task::spawn(async move {
let (circuit_id, circuit_url) = save_circuit(
block_number,
circuit,
sequence,
partial_circuit_aux_data,
object_store,
)
.await;
let (circuit_id, circuit_url) =
save_circuit(block_number, circuit, sequence, object_store).await;
drop(permit);
(circuit_id, circuit_url)
}));
}
}
.instrument(save_circuits_span);

let mut save_ram_queue_witness_handles = vec![];

let save_ram_queue_witness_span = tracing::info_span!("save_circuits");

// Future which receives part of RAM permutation circuits witnesses and saves them async.
// Uses semaphore because these artifacts are of significant size
let ram_queue_witness_receiver_handle = async {
let mut sorted_sequence = 0;
let mut unsorted_sequence = 0;

while let Some(witness_artifact) = ram_permutation_queue_receiver
.recv()
.instrument(tracing::info_span!("wait_for_ram_witness"))
.await
{
let object_store = object_store.clone();
let semaphore = semaphore.clone();
let permit = semaphore
.acquire_owned()
.await
.expect("failed to get permit for running save ram permutation queue witness task");
let (is_sorted, witness, sequence) = match witness_artifact {
WitnessGenerationArtifact::MemoryQueueWitness((witness, sorted)) => {
let sequence = if sorted {
let sequence = sorted_sequence;
sorted_sequence += 1;
sequence
} else {
let sequence = unsorted_sequence;
unsorted_sequence += 1;
sequence
};
(sorted, witness, sequence)
}
_ => panic!("Invalid artifact received"),
};
save_ram_queue_witness_handles.push(tokio::task::spawn(async move {
let _ = save_ram_premutation_queue_witness(
block_number,
sequence,
is_sorted,
witness,
object_store,
)
.await;
drop(permit);
}));
}
}
.instrument(save_ram_queue_witness_span);

let mut save_queue_handles = vec![];

let save_queues_span = tracing::info_span!("save_queues");
Expand All @@ -260,7 +187,7 @@ pub(super) async fn generate_witness(
let object_store = object_store.clone();
save_queue_handles.push(tokio::task::spawn(save_recursion_queue(
block_number,
circuit_id,
circuit_id.try_into().unwrap(),
queue,
inputs,
object_store,
Expand All @@ -269,11 +196,10 @@ pub(super) async fn generate_witness(
}
.instrument(save_queues_span);

let (witnesses, _, _, _) = tokio::join!(
let (witnesses, _, _) = tokio::join!(
make_circuits_handle,
circuit_receiver_handle,
queue_receiver_handle,
ram_queue_witness_receiver_handle
queue_receiver_handle
);
let (mut scheduler_witness, block_aux_witness) = witnesses.unwrap();

Expand All @@ -298,11 +224,7 @@ pub(super) async fn generate_witness(
.filter(|(circuit_id, _, _)| circuits_present.contains(circuit_id))
.collect();

let _: Vec<_> = futures::future::join_all(save_ram_queue_witness_handles)
.await
.into_iter()
.map(|result| result.expect("failed to save ram permutation queue witness"))
.collect();
artifacts_receiver_handle.join().unwrap();

scheduler_witness.previous_block_meta_hash = input.previous_batch_metadata.meta_hash.0;
scheduler_witness.previous_block_aux_hash = input.previous_batch_metadata.aux_hash.0;
Expand Down
51 changes: 8 additions & 43 deletions prover/crates/bin/witness_generator/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,7 @@ use std::{
sync::Arc,
};

use circuit_definitions::{
circuit_definitions::base_layer::ZkSyncBaseLayerCircuit,
encodings::memory_query::MemoryQueueStateWitnesses,
};
use circuit_definitions::circuit_definitions::base_layer::ZkSyncBaseLayerCircuit;
use once_cell::sync::Lazy;
use zkevm_test_harness::boojum::field::goldilocks::GoldilocksField;
use zksync_multivm::utils::get_used_bootloader_memory_bytes;
Expand All @@ -24,8 +21,8 @@ use zksync_prover_fri_types::{
encodings::recursion_request::RecursionQueueSimulator,
zkevm_circuits::scheduler::input::SchedulerCircuitInstanceWitness,
},
keys::{AggregationsKey, ClosedFormInputKey, FriCircuitKey, RamPermutationQueueWitnessKey},
CircuitAuxData, CircuitWrapper, FriProofWrapper, RamPermutationQueueWitness,
keys::{AggregationsKey, ClosedFormInputKey, FriCircuitKey},
CircuitWrapper, FriProofWrapper,
};
use zksync_types::{basic_fri_types::AggregationRound, L1BatchNumber, ProtocolVersionId, U256};

Expand Down Expand Up @@ -121,7 +118,6 @@ pub async fn save_circuit(
block_number: L1BatchNumber,
circuit: ZkSyncBaseLayerCircuit,
sequence_number: usize,
aux_data_for_partial_circuit: Option<CircuitAuxData>,
object_store: Arc<dyn ObjectStore>,
) -> (u8, String) {
let circuit_id = circuit.numeric_circuit_type();
Expand All @@ -133,43 +129,12 @@ pub async fn save_circuit(
depth: 0,
};

let blob_url = if let Some(aux_data_for_partial_circuit) = aux_data_for_partial_circuit {
object_store
.put(
circuit_key,
&CircuitWrapper::BasePartial((circuit, aux_data_for_partial_circuit)),
)
.await
.unwrap()
} else {
object_store
.put(circuit_key, &CircuitWrapper::Base(circuit))
.await
.unwrap()
};
(circuit_id, blob_url)
}

#[tracing::instrument(
skip_all,
fields(l1_batch = %block_number)
)]
pub async fn save_ram_premutation_queue_witness(
block_number: L1BatchNumber,
circuit_subsequence_number: usize,
is_sorted: bool,
witness: MemoryQueueStateWitnesses<GoldilocksField>,
object_store: Arc<dyn ObjectStore>,
) -> String {
let witness_key = RamPermutationQueueWitnessKey {
block_number,
circuit_subsequence_number,
is_sorted,
};
object_store
.put(witness_key, &RamPermutationQueueWitness { witness })
let blob_url = object_store
.put(circuit_key, &CircuitWrapper::Base(circuit))
.await
.unwrap()
.unwrap();

(circuit_id, blob_url)
}

#[tracing::instrument(
Expand Down
2 changes: 1 addition & 1 deletion prover/crates/lib/keystore/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ zksync_basic_types.workspace = true
zksync_utils.workspace = true
zksync_prover_fri_types.workspace = true
zkevm_test_harness.workspace = true
circuit_definitions = { workspace = true, features = ["log_tracing"] }
circuit_definitions = { git = "https://github.com/matter-labs/zksync-protocol.git", package = "circuit_definitions", features = [ "log_tracing" ] }
shivini = { workspace = true, optional = true }

anyhow.workspace = true
Expand Down
1 change: 1 addition & 0 deletions prover/crates/lib/keystore/src/keystore.rs
Original file line number Diff line number Diff line change
Expand Up @@ -470,6 +470,7 @@ impl Keystore {
}

/// Async loads mapping of all circuits to setup key, if successful
#[cfg(feature = "gpu")]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Huh, was this a miss on my end?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep

pub async fn load_all_setup_key_mapping(
&self,
) -> anyhow::Result<HashMap<ProverServiceDataKey, Arc<GoldilocksGpuProverSetupData>>> {
Expand Down
2 changes: 1 addition & 1 deletion prover/crates/lib/prover_fri_types/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,5 @@ categories.workspace = true
[dependencies]
zksync_object_store.workspace = true
zksync_types.workspace = true
circuit_definitions = { workspace = true, features = [ "log_tracing" ] }
circuit_definitions = { git = "https://github.com/matter-labs/zksync-protocol.git", package = "circuit_definitions", features = [ "log_tracing" ] }
serde = { workspace = true, features = ["derive"] }
Loading