Skip to content

Commit

Permalink
feat: minimal changes to fix the open 'grindability issue'
Browse files Browse the repository at this point in the history
Some more details here:
#1270
  • Loading branch information
cryptonemo committed Mar 1, 2023
1 parent 1680ad0 commit 845d2e1
Show file tree
Hide file tree
Showing 9 changed files with 118 additions and 34 deletions.
25 changes: 21 additions & 4 deletions filecoin-proofs/src/api/post_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ use log::{debug, info};
use storage_proofs_core::{
cache_key::CacheKey, merkle::MerkleTreeTrait, proof::ProofScheme, sector::SectorId,
};
use storage_proofs_post::fallback::{self, generate_leaf_challenge, FallbackPoSt, SectorProof};
use storage_proofs_post::fallback::{
self, generate_leaf_challenge, get_challenge_index, FallbackPoSt, SectorProof,
};

use crate::{
api::as_safe_commitment,
Expand Down Expand Up @@ -100,9 +102,24 @@ pub fn generate_fallback_sector_challenges<Tree: 'static + MerkleTreeTrait>(
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 challenge_index = match post_config.typ {
PoStType::Window => get_challenge_index(
post_config.api_version,
partition_index,
i,
num_sectors_per_chunk,
post_config.challenge_count,
n,
),
PoStType::Winning => get_challenge_index(
post_config.api_version,
partition_index,
i,
post_config.sector_count,
post_config.challenge_count,
n,
),
};
let challenged_leaf = generate_leaf_challenge(
&public_params,
randomness_safe,
Expand Down
25 changes: 17 additions & 8 deletions filecoin-proofs/tests/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ use filecoin_proofs::{
// same porep_ids).
const ARBITRARY_POREP_ID_V1_0_0: [u8; 32] = [127; 32];
const ARBITRARY_POREP_ID_V1_1_0: [u8; 32] = [128; 32];
const ARBITRARY_POREP_ID_V1_2_0: [u8; 32] = [129; 32];

const TEST_SEED: [u8; 16] = [
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, 0xe5,
Expand All @@ -76,6 +77,7 @@ fn test_seal_lifecycle_2kib_porep_id_v1_1_base_8() -> Result<()> {
let mut porep_id = [0u8; 32];
porep_id[..8].copy_from_slice(&porep_id_v1_1.to_le_bytes());
assert!(!is_legacy_porep_id(porep_id));

seal_lifecycle::<SectorShape2KiB>(SECTOR_SIZE_2_KIB, &porep_id, ApiVersion::V1_1_0)
}

Expand Down Expand Up @@ -290,6 +292,10 @@ fn seal_lifecycle<Tree: 'static + MerkleTreeTrait>(
let mut prover_id = [0u8; 32];
prover_id.copy_from_slice(AsRef::<[u8]>::as_ref(&prover_fr));

info!(
"Creating seal proof with ApiVersion {} and PoRep ID {:?}",
api_version, porep_id
);
let (_, replica, _, _) = create_seal::<_, Tree>(
&mut rng,
sector_size,
Expand Down Expand Up @@ -806,6 +812,7 @@ fn winning_post<Tree: 'static + MerkleTreeTrait>(
let porep_id = match api_version {
ApiVersion::V1_0_0 => ARBITRARY_POREP_ID_V1_0_0,
ApiVersion::V1_1_0 => ARBITRARY_POREP_ID_V1_1_0,
ApiVersion::V1_2_0 => ARBITRARY_POREP_ID_V1_2_0,
};

let (sector_id, replica, comm_r, cache_dir) = if fake {
Expand Down Expand Up @@ -909,7 +916,7 @@ fn test_window_post_single_partition_smaller_2kib_base_8() -> Result<()> {
.get(&sector_size)
.expect("unknown sector size");

let versions = vec![ApiVersion::V1_0_0, ApiVersion::V1_1_0];
let versions = vec![ApiVersion::V1_0_0, ApiVersion::V1_1_0, ApiVersion::V1_2_0];
for version in versions {
window_post::<SectorShape2KiB>(
sector_size,
Expand All @@ -934,7 +941,7 @@ fn test_window_post_two_partitions_matching_2kib_base_8() -> Result<()> {
.get(&sector_size)
.expect("unknown sector size");

let versions = vec![ApiVersion::V1_0_0, ApiVersion::V1_1_0];
let versions = vec![ApiVersion::V1_0_0, ApiVersion::V1_1_0, ApiVersion::V1_2_0];
for version in versions {
window_post::<SectorShape2KiB>(
sector_size,
Expand All @@ -959,7 +966,7 @@ fn test_window_post_two_partitions_matching_4kib_sub_8_2() -> Result<()> {
.get(&sector_size)
.expect("unknown sector size");

let versions = vec![ApiVersion::V1_0_0, ApiVersion::V1_1_0];
let versions = vec![ApiVersion::V1_0_0, ApiVersion::V1_1_0, ApiVersion::V1_2_0];
for version in versions {
window_post::<SectorShape4KiB>(
sector_size,
Expand All @@ -984,7 +991,7 @@ fn test_window_post_two_partitions_matching_16kib_sub_8_8() -> Result<()> {
.get(&sector_size)
.expect("unknown sector size");

let versions = vec![ApiVersion::V1_0_0, ApiVersion::V1_1_0];
let versions = vec![ApiVersion::V1_0_0, ApiVersion::V1_1_0, ApiVersion::V1_2_0];
for version in versions {
window_post::<SectorShape16KiB>(
sector_size,
Expand Down Expand Up @@ -1015,7 +1022,7 @@ fn test_window_post_two_partitions_matching_32kib_top_8_8_2() -> Result<()> {
.get(&sector_size)
.expect("unknown sector size");

let versions = vec![ApiVersion::V1_0_0, ApiVersion::V1_1_0];
let versions = vec![ApiVersion::V1_0_0, ApiVersion::V1_1_0, ApiVersion::V1_2_0];
for version in versions {
window_post::<SectorShape32KiB>(
sector_size,
Expand Down Expand Up @@ -1046,7 +1053,7 @@ fn test_window_post_two_partitions_smaller_2kib_base_8() -> Result<()> {
.get(&sector_size)
.expect("unknown sector size");

let versions = vec![ApiVersion::V1_0_0, ApiVersion::V1_1_0];
let versions = vec![ApiVersion::V1_0_0, ApiVersion::V1_1_0, ApiVersion::V1_2_0];
for version in versions {
window_post::<SectorShape2KiB>(
sector_size,
Expand Down Expand Up @@ -1077,7 +1084,7 @@ fn test_window_post_single_partition_matching_2kib_base_8() -> Result<()> {
.get(&sector_size)
.expect("unknown sector size");

let versions = vec![ApiVersion::V1_0_0, ApiVersion::V1_1_0];
let versions = vec![ApiVersion::V1_0_0, ApiVersion::V1_1_0, ApiVersion::V1_2_0];
for version in versions {
window_post::<SectorShape2KiB>(sector_size, sector_count, sector_count, false, version)?;
window_post::<SectorShape2KiB>(sector_size, sector_count, sector_count, true, version)?;
Expand All @@ -1095,7 +1102,7 @@ fn test_window_post_partition_matching_2kib_base_8() -> Result<()> {
.get(&sector_size)
.expect("unknown sector size");

let versions = vec![ApiVersion::V1_0_0, ApiVersion::V1_1_0];
let versions = vec![ApiVersion::V1_0_0, ApiVersion::V1_1_0, ApiVersion::V1_2_0];
for version in versions {
partition_window_post::<SectorShape2KiB>(
sector_size,
Expand Down Expand Up @@ -1133,6 +1140,7 @@ fn partition_window_post<Tree: 'static + MerkleTreeTrait>(
let porep_id = match api_version {
ApiVersion::V1_0_0 => ARBITRARY_POREP_ID_V1_0_0,
ApiVersion::V1_1_0 => ARBITRARY_POREP_ID_V1_1_0,
ApiVersion::V1_2_0 => ARBITRARY_POREP_ID_V1_2_0,
};

for _ in 0..total_sector_count {
Expand Down Expand Up @@ -1271,6 +1279,7 @@ fn window_post<Tree: 'static + MerkleTreeTrait>(
let porep_id = match api_version {
ApiVersion::V1_0_0 => ARBITRARY_POREP_ID_V1_0_0,
ApiVersion::V1_1_0 => ARBITRARY_POREP_ID_V1_1_0,
ApiVersion::V1_2_0 => ARBITRARY_POREP_ID_V1_2_0,
};

for _ in 0..total_sector_count {
Expand Down
7 changes: 7 additions & 0 deletions storage-proofs-core/src/api_version.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,15 @@ use semver::Version;
pub enum ApiVersion {
V1_0_0,
V1_1_0,
V1_2_0,
}

impl ApiVersion {
pub fn as_semver(&self) -> Version {
match self {
ApiVersion::V1_0_0 => Version::new(1, 0, 0),
ApiVersion::V1_1_0 => Version::new(1, 1, 0),
ApiVersion::V1_2_0 => Version::new(1, 2, 0),
}
}
}
Expand All @@ -40,6 +42,7 @@ impl FromStr for ApiVersion {
match (api_version.major, api_version.minor, api_version.patch) {
(1, 0, 0) => Ok(ApiVersion::V1_0_0),
(1, 1, 0) => Ok(ApiVersion::V1_1_0),
(1, 2, 0) => Ok(ApiVersion::V1_2_0),
(1, 1, _) | (1, 0, _) => Err(format_err!(
"Could not parse API Version from string (patch)"
)),
Expand All @@ -57,14 +60,18 @@ impl FromStr for ApiVersion {
fn test_fmt() {
assert_eq!(format!("{}", ApiVersion::V1_0_0), "1.0.0");
assert_eq!(format!("{}", ApiVersion::V1_1_0), "1.1.0");
assert_eq!(format!("{}", ApiVersion::V1_2_0), "1.2.0");
}

#[test]
fn test_as_semver() {
assert_eq!(ApiVersion::V1_0_0.as_semver().major, 1);
assert_eq!(ApiVersion::V1_1_0.as_semver().major, 1);
assert_eq!(ApiVersion::V1_2_0.as_semver().major, 1);
assert_eq!(ApiVersion::V1_0_0.as_semver().minor, 0);
assert_eq!(ApiVersion::V1_1_0.as_semver().minor, 1);
assert_eq!(ApiVersion::V1_2_0.as_semver().minor, 2);
assert_eq!(ApiVersion::V1_0_0.as_semver().patch, 0);
assert_eq!(ApiVersion::V1_1_0.as_semver().patch, 0);
assert_eq!(ApiVersion::V1_2_0.as_semver().patch, 0);
}
8 changes: 4 additions & 4 deletions storage-proofs-core/src/drgraph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ impl<H: Hasher> Graph<H> for BucketGraph<H> {

let (predecessor_index, other_drg_parents) = match self.api_version {
ApiVersion::V1_0_0 => (m_prime, &mut parents[..]),
ApiVersion::V1_1_0 => (0, &mut parents[1..]),
ApiVersion::V1_1_0 | ApiVersion::V1_2_0 => (0, &mut parents[1..]),
};

for parent in other_drg_parents.iter_mut().take(m_prime) {
Expand Down Expand Up @@ -291,7 +291,7 @@ mod tests {
let new_porep_id = porep_id(5);

graph_bucket_aux::<H>(legacy_porep_id, ApiVersion::V1_0_0);
graph_bucket_aux::<H>(new_porep_id, ApiVersion::V1_1_0);
graph_bucket_aux::<H>(new_porep_id, ApiVersion::V1_2_0);
}

fn graph_bucket_aux<H: Hasher>(porep_id: PoRepID, api_version: ApiVersion) {
Expand Down Expand Up @@ -337,7 +337,7 @@ mod tests {
"immediate predecessor was not last DRG parent"
);
}
ApiVersion::V1_1_0 => {
ApiVersion::V1_1_0 | ApiVersion::V1_2_0 => {
assert_eq!(
i - 1,
pa1[0] as usize,
Expand All @@ -362,7 +362,7 @@ mod tests {
fn gen_proof<H: 'static + Hasher, U: 'static + PoseidonArity>(config: Option<StoreConfig>) {
let leafs = 64;
let porep_id = [1; 32];
let g = BucketGraph::<H>::new(leafs, BASE_DEGREE, 0, porep_id, ApiVersion::V1_1_0)
let g = BucketGraph::<H>::new(leafs, BASE_DEGREE, 0, porep_id, ApiVersion::V1_2_0)
.expect("bucket graph new failed");
let data = vec![2u8; NODE_SIZE * leafs];

Expand Down
28 changes: 19 additions & 9 deletions storage-proofs-porep/src/stacked/vanilla/graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -374,8 +374,10 @@ where

match self.api_version {
ApiVersion::V1_0_0 => transformed as u32 / self.expansion_degree as u32,
ApiVersion::V1_1_0 => u32::try_from(transformed / self.expansion_degree as u64)
.expect("invalid transformation"),
ApiVersion::V1_1_0 | ApiVersion::V1_2_0 => {
u32::try_from(transformed / self.expansion_degree as u64)
.expect("invalid transformation")
}
}

// Collapse the output in the matrix search space to the row of the corresponding
Expand Down Expand Up @@ -511,11 +513,19 @@ mod tests {
porep_id
};

test_pathology_aux(porep_id(3), sector32_nodes, ApiVersion::V1_0_0);
test_pathology_aux(porep_id(4), sector64_nodes, ApiVersion::V1_0_0);
let test_inputs = vec![
(porep_id(3), sector32_nodes, ApiVersion::V1_0_0),
(porep_id(4), sector64_nodes, ApiVersion::V1_0_0),
(porep_id(8), sector32_nodes, ApiVersion::V1_1_0),
(porep_id(9), sector64_nodes, ApiVersion::V1_1_0),
// Confirms that V1_1_0 and V1_2_0 are compatible
(porep_id(8), sector32_nodes, ApiVersion::V1_2_0),
(porep_id(9), sector64_nodes, ApiVersion::V1_2_0),
];

test_pathology_aux(porep_id(8), sector32_nodes, ApiVersion::V1_1_0);
test_pathology_aux(porep_id(9), sector64_nodes, ApiVersion::V1_1_0);
for inputs in test_inputs {
test_pathology_aux(inputs.0, inputs.1, inputs.2);
}
}

fn test_pathology_aux(porep_id: PoRepID, nodes: u32, api_version: ApiVersion) {
Expand All @@ -531,7 +541,7 @@ mod tests {

let expect_pathological = match api_version {
ApiVersion::V1_0_0 => true,
ApiVersion::V1_1_0 => false,
ApiVersion::V1_1_0 | ApiVersion::V1_2_0 => false,
};

let graph = StackedBucketGraph::<PoseidonHasher>::new_stacked(
Expand Down Expand Up @@ -606,7 +616,7 @@ mod tests {
BASE_DEGREE,
EXP_DEGREE,
porep_id,
ApiVersion::V1_1_0,
ApiVersion::V1_2_0,
)
.expect("stacked bucket graph new_stacked");

Expand Down Expand Up @@ -656,7 +666,7 @@ mod tests {
BASE_DEGREE,
EXP_DEGREE,
porep_id,
ApiVersion::V1_1_0,
ApiVersion::V1_2_0,
)
.expect("stacked bucket graph new_stacked failed");

Expand Down
15 changes: 11 additions & 4 deletions storage-proofs-post/src/fallback/compound.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ use storage_proofs_core::{
util::NODE_SIZE,
};

use crate::fallback::{generate_leaf_challenge_inner, FallbackPoSt, FallbackPoStCircuit, Sector};
use crate::fallback::{
generate_leaf_challenge_inner, get_challenge_index, FallbackPoSt, FallbackPoStCircuit, Sector,
};

pub struct FallbackPoStCompound<Tree>
where
Expand Down Expand Up @@ -70,9 +72,14 @@ impl<'a, Tree: 'static + MerkleTreeTrait>

// 2. Inputs for verifying inclusion paths
for n in 0..pub_params.challenge_count {
let challenge_index = ((partition_index * pub_params.sector_count + i)
* pub_params.challenge_count
+ n) as u64;
let challenge_index = get_challenge_index(
pub_params.api_version,
partition_index,
i,
pub_params.sector_count,
pub_params.challenge_count,
n,
);
let challenged_leaf = generate_leaf_challenge_inner::<
<Tree::Hasher as Hasher>::Domain,
>(
Expand Down
2 changes: 2 additions & 0 deletions storage-proofs-post/src/fallback/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
mod circuit;
mod compound;
mod utils;
mod vanilla;

pub use circuit::*;
pub use compound::*;
pub use utils::*;
pub use vanilla::*;
19 changes: 19 additions & 0 deletions storage-proofs-post/src/fallback/utils.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
use storage_proofs_core::api_version::ApiVersion;

/// Selects the challenge index used to determine the leaf challenge for PoSt
pub fn get_challenge_index(
api_version: ApiVersion,
sector: usize,
sector_chunk_index: usize,
num_sectors_per_chunk: usize,
challenge_count: usize,
challenge_index: usize,
) -> u64 {
(match api_version {
ApiVersion::V1_2_0 => challenge_index,
_ => {
(sector * num_sectors_per_chunk + sector_chunk_index) * challenge_count
+ challenge_index
}
} as u64)
}
Loading

0 comments on commit 845d2e1

Please sign in to comment.