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: split up window post API into separate calls #1269

Closed
wants to merge 2 commits into from
Closed
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
201 changes: 195 additions & 6 deletions filecoin-proofs/src/api/post.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::hash::{Hash, Hasher as StdHasher};
use std::marker::PhantomData;
use std::path::{Path, PathBuf};

use anyhow::{ensure, Context, Result};
use anyhow::{anyhow, ensure, Context, Result};
use bincode::deserialize;
use generic_array::typenum::Unsigned;
use log::{info, trace};
Expand All @@ -24,7 +24,8 @@ use crate::caches::{get_post_params, get_post_verifying_key};
use crate::constants::*;
use crate::parameters::{window_post_setup_params, winning_post_setup_params};
use crate::types::{
ChallengeSeed, Commitment, PersistentAux, PoStConfig, ProverId, SectorSize, TemporaryAux,
ChallengeSeed, Commitment, PersistentAux, PoStConfig, ProverId, SectorSize, SnarkProof,
TemporaryAux, WindowPoStChallenges, WindowPoStVanillaProofs,
};
use crate::PoStType;

Expand Down Expand Up @@ -240,8 +241,6 @@ pub fn clear_caches<Tree: MerkleTreeTrait>(
Ok(())
}

pub type SnarkProof = Vec<u8>;

/// Generates a Winning proof-of-spacetime.
pub fn generate_winning_post<Tree: 'static + MerkleTreeTrait>(
post_config: &PoStConfig,
Expand Down Expand Up @@ -327,9 +326,9 @@ pub fn generate_winning_post<Tree: 'static + MerkleTreeTrait>(
Ok(proof)
}

/// Given some randomness and a the length of available sectors, generates the challenged sector.
/// Given some randomness and the length of available sectors, generates the challenged sector.
///
/// The returned values are indicies in the range of `0..sector_set_size`, requiring the caller
/// The returned values are indices in the range of `0..sector_set_size`, requiring the caller
/// to match the index to the correct sector.
pub fn generate_winning_post_sector_challenge<Tree: MerkleTreeTrait>(
post_config: &PoStConfig,
Expand Down Expand Up @@ -440,6 +439,196 @@ pub fn verify_winning_post<Tree: 'static + MerkleTreeTrait>(
Ok(true)
}

/// Generates the challenges per SectorId required for a Window proof-of-spacetime.
pub fn generate_window_post_challenges<Tree: 'static + MerkleTreeTrait>(
post_config: &PoStConfig,
randomness: &ChallengeSeed,
pub_sectors: &[SectorId],
prover_id: ProverId,
) -> Result<WindowPoStChallenges> {
info!("generate_window_post_challenges:start");
ensure!(
post_config.typ == PoStType::Window,
"invalid post config type"
);

let randomness_safe: <Tree::Hasher as Hasher>::Domain =
as_safe_commitment(randomness, "randomness")?;

let public_params = fallback::PublicParams {
sector_size: u64::from(post_config.sector_size),
challenge_count: post_config.challenge_count,
sector_count: post_config.sector_count,
};

let mut sector_challenges: BTreeMap<SectorId, Vec<u64>> = BTreeMap::new();

let num_sectors_per_chunk = post_config.sector_count;
let partitions = match get_partitions_for_window_post(pub_sectors.len(), &post_config) {
Some(x) => x,
None => 1,
};

for partition_index in 0..partitions {
let sectors = pub_sectors
.chunks(num_sectors_per_chunk)
.nth(partition_index)
.ok_or_else(|| anyhow!("invalid number of sectors/partition index"))?;

for (i, sector) in sectors.iter().enumerate() {
let mut challenges = Vec::new();

for n in 0..post_config.challenge_count {
let challenge_index = ((partition_index * post_config.sector_count + i)
* post_config.challenge_count
+ n) as u64;
let challenged_leaf_start = fallback::generate_leaf_challenge(
&public_params,
randomness_safe,
u64::from(*sector),
challenge_index,
)?;
challenges.push(challenged_leaf_start);
}

sector_challenges.insert(*sector, challenges);
}
}

let challenges = WindowPoStChallenges {
post_config: post_config.clone(),
randomness: *randomness,
prover_id,
sector_challenges,
};

info!("generate_window_post_challenges:finish");

Ok(challenges)
}

/// Generates the vanilla proofs required for Window proof-of-spacetime.
pub fn generate_window_post_vanilla_proofs<Tree: 'static + MerkleTreeTrait>(
Copy link
Collaborator

Choose a reason for hiding this comment

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

What we need is a function that generates the vanilla proofs only for a single sector, as described in the issue.

replicas: &BTreeMap<SectorId, PrivateReplicaInfo<Tree>>,
challenges: &WindowPoStChallenges,
) -> Result<WindowPoStVanillaProofs<Tree>> {
info!("generate_window_post_vanilla_proofs:start");
ensure!(
challenges.post_config.typ == PoStType::Window,
"invalid post config type"
);

let randomness_safe = as_safe_commitment(&challenges.randomness, "randomness")?;
let prover_id_safe = as_safe_commitment(&challenges.prover_id, "prover_id")?;

let vanilla_params = window_post_setup_params(&challenges.post_config);
let partitions = get_partitions_for_window_post(replicas.len(), &challenges.post_config);

let sector_count = vanilla_params.sector_count;
let setup_params = compound_proof::SetupParams {
vanilla_params: vanilla_params.clone(),
partitions,
priority: challenges.post_config.priority,
};

let pub_params: compound_proof::PublicParams<fallback::FallbackPoSt<Tree>> =
fallback::FallbackPoStCompound::setup(&setup_params)?;

let trees: Vec<_> = replicas
.iter()
.map(|(_id, replica)| replica.merkle_tree(challenges.post_config.sector_size))
.collect::<Result<_>>()?;

let mut pub_sectors = Vec::with_capacity(sector_count);
let mut priv_sectors = Vec::with_capacity(sector_count);

for ((sector_id, replica), tree) in replicas.iter().zip(trees.iter()) {
let comm_r = replica.safe_comm_r()?;
let comm_c = replica.safe_comm_c()?;
let comm_r_last = replica.safe_comm_r_last()?;

pub_sectors.push(fallback::PublicSector {
id: *sector_id,
comm_r,
});
priv_sectors.push(fallback::PrivateSector {
tree,
comm_c,
comm_r_last,
});
}

let pub_inputs = fallback::PublicInputs {
randomness: randomness_safe,
prover_id: prover_id_safe,
sectors: &pub_sectors,
k: None,
};

let priv_inputs = fallback::PrivateInputs::<Tree> {
sectors: &priv_sectors,
};

let vanilla_proofs = fallback::FallbackPoStCompound::prove_vanilla_with_challenges(
&pub_params,
&pub_inputs,
&priv_inputs,
&challenges.sector_challenges,
)?;

info!("generate_window_post_vanilla_proofs:finish");

Ok(WindowPoStVanillaProofs {
partitions,
vanilla_params,
pub_sectors,
vanilla_proofs,
})
}

/// Generates a Window proof-of-spacetime.
pub fn generate_window_post_circuit_proof<Tree: 'static + MerkleTreeTrait>(
challenges: &WindowPoStChallenges,
Copy link
Collaborator

Choose a reason for hiding this comment

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

We don't need the challenges here — just the vanilla proofs. WindosPostChallenges is being used as a vehicle to carry arguments (randomness, prover_id), which should just be passed independently.

vanilla_proofs: &WindowPoStVanillaProofs<Tree>,
) -> Result<SnarkProof> {
info!("generate_window_post_circuit_proof:finish");
ensure!(
challenges.post_config.typ == PoStType::Window,
"invalid post config type"
);

let randomness_safe = as_safe_commitment(&challenges.randomness, "randomness")?;
let prover_id_safe = as_safe_commitment(&challenges.prover_id, "prover_id")?;

let setup_params = compound_proof::SetupParams {
vanilla_params: vanilla_proofs.vanilla_params.clone(),
partitions: vanilla_proofs.partitions,
priority: challenges.post_config.priority,
};

let pub_params: compound_proof::PublicParams<fallback::FallbackPoSt<Tree>> =
fallback::FallbackPoStCompound::setup(&setup_params)?;
let groth_params = get_post_params::<Tree>(&challenges.post_config)?;

let pub_inputs = fallback::PublicInputs {
randomness: randomness_safe,
prover_id: prover_id_safe,
sectors: &vanilla_proofs.pub_sectors,
k: None,
};

let proof = fallback::FallbackPoStCompound::prove_circuit(
&pub_params,
&pub_inputs,
vanilla_proofs.vanilla_proofs.clone(),
&groth_params,
)?;

info!("generate_window_post_circuit_proof:finish");

Ok(proof.to_vec()?)
}

/// Generates a Window proof-of-spacetime.
pub fn generate_window_post<Tree: 'static + MerkleTreeTrait>(
post_config: &PoStConfig,
Expand Down
4 changes: 2 additions & 2 deletions filecoin-proofs/src/parameters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ use storage_proofs::proof::ProofScheme;
use crate::constants::*;
use crate::types::{MerkleTreeTrait, PaddedBytesAmount, PoStConfig};

type WinningPostSetupParams = fallback::SetupParams;
pub type WinningPostSetupParams = fallback::SetupParams;
pub type WinningPostPublicParams = fallback::PublicParams;

type WindowPostSetupParams = fallback::SetupParams;
pub type WindowPostSetupParams = fallback::SetupParams;
pub type WindowPostPublicParams = fallback::PublicParams;

pub fn public_params<Tree: 'static + MerkleTreeTrait>(
Expand Down
32 changes: 32 additions & 0 deletions filecoin-proofs/src/types/mod.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
use std::collections::BTreeMap;

use serde::{Deserialize, Serialize};
use storage_proofs::hasher::Hasher;
use storage_proofs::porep::stacked;
use storage_proofs::post::fallback::*;
use storage_proofs::sector::*;

use crate::constants::*;
use crate::parameters::*;

mod bytes_amount;
mod piece_info;
Expand Down Expand Up @@ -83,3 +88,30 @@ pub struct SealPreCommitPhase1Output<Tree: MerkleTreeTrait> {
pub config: StoreConfig,
pub comm_d: Commitment,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct WindowPoStChallenges {
pub post_config: PoStConfig,
pub randomness: ChallengeSeed,
pub prover_id: ProverId,
pub sector_challenges: BTreeMap<SectorId, Vec<u64>>,
}

pub type SnarkProof = Vec<u8>;
pub type VanillaProof<Tree> = Proof<<Tree as MerkleTreeTrait>::Proof>;

#[derive(Debug, Serialize, Deserialize)]
pub struct WindowPoStVanillaProofs<Tree: MerkleTreeTrait> {
pub vanilla_params: WindowPostSetupParams,
pub partitions: Option<usize>,
#[serde(bound(
serialize = "Vec<PublicSector<<Tree::Hasher as Hasher>::Domain>>: Serialize",
deserialize = "Vec<PublicSector<<Tree::Hasher as Hasher>::Domain>>: Deserialize<'de>"
))]
pub pub_sectors: Vec<PublicSector<<Tree::Hasher as Hasher>::Domain>>,
#[serde(bound(
serialize = "Vec<VanillaProof<Tree>>: Serialize",
deserialize = "Vec<VanillaProof<Tree>>: Deserialize<'de>"
))]
pub vanilla_proofs: Vec<VanillaProof<Tree>>,
}
Copy link
Collaborator

@porcuquine porcuquine Sep 8, 2020

Choose a reason for hiding this comment

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

This struct should just contain the vanilla proofs for a single sector and nothing else. As above, I don't think you need to differentiate between Window and Winning PoSt. Something like:

pub struct FallbackPoStVanillaProofs<Tree: MerkleTreeTrait> {
    pub sector_id: SectorId,
    pub replica_info: PublicReplicaInfo,
    pub vanilla_proofs: Vec<VanillaProof<Tree>>
}

I include SectorId and replica_info because these are sector-specific. What's not needed is general proof configuration parameters.

Copy link
Collaborator

Choose a reason for hiding this comment

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

What I think may be missing are the sector-specific private inputs: comm_c and comm_r_last. We could technically get the latter from the inclusion proofs, but the former is needed in order to prove the relationship between comm_r_last and comm_r.

Note that PublicReplicaInfo above is effectively just comm_r. We could either include PersistentAux here, create a new structure just for all the needed commitments, or just individually include comm_c, comm_r_last, and comm_r.

4 changes: 2 additions & 2 deletions filecoin-proofs/src/types/post_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use storage_proofs::post::fallback;

use crate::types::*;

#[derive(Clone, Debug)]
#[derive(Clone, Serialize, Deserialize, Debug)]
pub struct PoStConfig {
pub sector_size: SectorSize,
pub challenge_count: usize,
Expand All @@ -16,7 +16,7 @@ pub struct PoStConfig {
pub priority: bool,
}

#[derive(Debug, Clone, PartialEq, Eq)]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum PoStType {
Winning,
Window,
Expand Down
2 changes: 1 addition & 1 deletion filecoin-proofs/src/types/sector_size.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::fr32::to_unpadded_bytes;
use crate::types::*;

#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct SectorSize(pub u64);

impl From<u64> for SectorSize {
Expand Down
17 changes: 16 additions & 1 deletion filecoin-proofs/tests/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,22 @@ fn window_post<Tree: 'static + MerkleTreeTrait>(
priority: false,
};

let proof = generate_window_post::<Tree>(&config, &randomness, &priv_replicas, prover_id)?;
/////////////////////////////////////////////
// The following methods of proof generation are functionally equivalent:
// 1)
//let proof = generate_window_post::<Tree>(&config, &randomness, &priv_replicas, prover_id)?;
//
// 2)
let replica_sectors = priv_replicas
.iter()
.map(|(sector, _replica)| *sector)
.collect::<Vec<SectorId>>();

let challenges =
generate_window_post_challenges::<Tree>(&config, &randomness, &replica_sectors, prover_id)?;
let vanilla_proofs = generate_window_post_vanilla_proofs::<Tree>(&priv_replicas, &challenges)?;
let proof = generate_window_post_circuit_proof::<Tree>(&challenges, &vanilla_proofs)?;
/////////////////////////////////////////////

let valid = verify_window_post::<Tree>(&config, &randomness, &pub_replicas, prover_id, &proof)?;
assert!(valid, "proof did not verify");
Expand Down
Loading