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: expose an API suitable for NI-PoRep proof aggregation #1757

Merged
merged 2 commits into from
May 17, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
61 changes: 52 additions & 9 deletions filecoin-proofs/src/api/seal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -492,22 +492,30 @@ pub fn seal_commit_phase1_inner<T: AsRef<Path>, Tree: 'static + MerkleTreeTrait>
Ok(out)
}

/// This new API is added and made public specifically for generating
/// NonInteractive PoRep proofs that will later be aggregated using
/// the existing `aggregate_seal_commit_proofs` method. It is also
/// used internally outside of the NonInteractivePoRep use-case to
/// avoid code duplication.
///
/// Note that if `seal_commit_phase2` is used for NonInteractivePoRep
/// and it's later decided that multiple NI-PoRep proofs should be
/// aggregated, it will fail.
#[allow(clippy::too_many_arguments)]
pub fn seal_commit_phase2<Tree: 'static + MerkleTreeTrait>(
pub fn seal_commit_phase2_circuit_proofs<Tree: 'static + MerkleTreeTrait>(
porep_config: &PoRepConfig,
phase1_output: SealCommitPhase1Output<Tree>,
prover_id: ProverId,
sector_id: SectorId,
) -> Result<SealCommitOutput> {
info!("seal_commit_phase2:start: {:?}", sector_id);
info!("seal_commit_phase2_circuit_proofs:start: {:?}", sector_id);

let SealCommitPhase1Output {
vanilla_proofs,
comm_d,
comm_r,
replica_id,
seed,
ticket,
ticket: _,
} = phase1_output;

ensure!(comm_d != [0; 32], "Invalid all zero commitment (comm_d)");
Expand Down Expand Up @@ -562,23 +570,58 @@ pub fn seal_commit_phase2<Tree: 'static + MerkleTreeTrait>(
)?;
trace!("snark_proof:finish");

// By returning the groth proofs wrapped in the SealCommitOutput
// type as normal, we minimize exported types across the API and
// allow re-use of existing aggregation/verification APIs
let verifying_key = get_stacked_verifying_key::<Tree>(porep_config)?;
let proof = MultiProof::new(groth_proofs, &verifying_key);
let mut buf =
Vec::with_capacity(SINGLE_PARTITION_PROOF_LEN * usize::from(porep_config.partitions));

proof.write(&mut buf)?;

info!("seal_commit_phase2_circuit_proofs:finish: {:?}", sector_id);
Ok(SealCommitOutput { proof: buf })
}

#[allow(clippy::too_many_arguments)]
pub fn seal_commit_phase2<Tree: 'static + MerkleTreeTrait>(
porep_config: &PoRepConfig,
phase1_output: SealCommitPhase1Output<Tree>,
prover_id: ProverId,
sector_id: SectorId,
) -> Result<SealCommitOutput> {
info!("seal_commit_phase2:start: {:?}", sector_id);

let SealCommitPhase1Output {
vanilla_proofs: _,
comm_d,
comm_r,
replica_id: _,
seed,
ticket,
} = phase1_output;

let seal_commit_output =
seal_commit_phase2_circuit_proofs::<Tree>(porep_config, phase1_output, sector_id)?;

// Non-interactive PoRep is an aggregated proof, hence we use that as the returned buffer.
if porep_config.feature_enabled(ApiFeature::NonInteractivePoRep) {
buf = aggregate_seal_commit_proofs::<Tree>(
let buf = if porep_config.feature_enabled(ApiFeature::NonInteractivePoRep) {
ensure!(
porep_config.api_version >= ApiFeature::NonInteractivePoRep.first_supported_version(),
"API version does not support NonInteractivePoRep"
);

aggregate_seal_commit_proofs::<Tree>(
porep_config,
&[comm_r],
&[seed],
&[SealCommitOutput { proof: buf }],
&[seal_commit_output],
groth16::aggregate::AggregateVersion::V2,
)?;
}
)?
} else {
seal_commit_output.proof
};

// Verification is cheap when parameters are cached,
// and it is never correct to return a proof which does not verify.
Expand Down
Loading