Skip to content

Commit 8976839

Browse files
committed
feat: add seal regression testing support
feat: add tests from v16 and v18* *v17 missed result collection for various reasons, but could always be added later if needed
1 parent 266acc3 commit 8976839

12 files changed

+962
-36
lines changed

README.md

+16
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,22 @@ Some results are displayed at the command line, or alternatively written as JSON
186186

187187
Note: On macOS you need `gtime` (`brew install gnu-time`), as the built in `time` command is not enough.
188188

189+
## Regression Testing
190+
191+
Within the `filecoin-proofs` crate there is a regression suite. The idea is to record some generated proofs at various proof release versions, so that future versions/revisions can always ensure that it can properly verify historical proofs as expected.
192+
193+
By default, there is a test that verifies all known regression records that exist within the source tree.
194+
195+
In order to generate a new set of regression records, the feature flag `persist-regression-proofs` must be used.
196+
197+
When the feature is used and all of the `filecoin-proofs` tests are run (including the ignored tests), the following files are written to disk:
198+
199+
```
200+
filecoin-proofs/tests/seal_regression_records.json
201+
```
202+
203+
Once the new files are generated with a given proof version, they should be renamed appropriately and added to the repository and then referenced for verification during routine testing in the `filecoin-proofs/tests/regression.rs` source (see the `const` values at the top and go from there).
204+
189205
## Logging
190206

191207
For better logging with backtraces on errors, developers should use `expects` rather than `expect` on `Result<T, E>` and `Option<T>`.

filecoin-proofs/Cargo.toml

+2
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ serde = { workspace = true, features = ["rc", "derive"] }
3737
serde_json.workspace = true
3838
sha2.workspace = true
3939
typenum.workspace = true
40+
file-lock="2.1.10"
4041

4142
[dev-dependencies]
4243
# Sorted alphabetically
@@ -86,6 +87,7 @@ fixed-rows-to-discard = [
8687
"storage-proofs-post/fixed-rows-to-discard",
8788
"storage-proofs-update/fixed-rows-to-discard",
8889
]
90+
persist-regression-proofs = []
8991

9092
[[bench]]
9193
name = "preprocessing"

filecoin-proofs/src/types/mod.rs

+12
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,18 @@ pub struct SectorUpdateProofInputs {
108108
pub comm_d_new: Commitment,
109109
}
110110

111+
#[derive(Debug, Clone, Serialize, Deserialize)]
112+
pub struct SealRegressionRecord {
113+
pub porep_config: PoRepConfig,
114+
pub comm_r: Commitment,
115+
pub comm_d: Commitment,
116+
pub prover_id: ProverId,
117+
pub sector_id: SectorId,
118+
pub ticket: [u8; 32],
119+
pub seed: [u8; 32],
120+
pub proof: Vec<u8>,
121+
}
122+
111123
// This FallbackPoStSectorProof is used during Fallback PoSt, but
112124
// contains only Vanilla proof information and is not a full Fallback
113125
// PoSt proof.

filecoin-proofs/src/types/porep_config.rs

+3-14
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use std::path::PathBuf;
22

33
use anyhow::{anyhow, Result};
4+
use serde::{Deserialize, Serialize};
45
use storage_proofs_core::{
56
api_version::{ApiFeature, ApiVersion},
67
merkle::MerkleTreeTrait,
@@ -18,7 +19,7 @@ use crate::{
1819
POREP_PARTITIONS,
1920
};
2021

21-
#[derive(Clone, Debug)]
22+
#[derive(Clone, Debug, Serialize, Deserialize)]
2223
pub struct PoRepConfig {
2324
pub sector_size: SectorSize,
2425
pub partitions: PoRepProofPartitions,
@@ -79,19 +80,7 @@ impl PoRepConfig {
7980
api_version: ApiVersion,
8081
api_features: Vec<ApiFeature>,
8182
) -> Result<Self> {
82-
let mut config = Self {
83-
sector_size: SectorSize(sector_size),
84-
partitions: PoRepProofPartitions(
85-
*POREP_PARTITIONS
86-
.read()
87-
.expect("POREP_PARTITIONS poisoned")
88-
.get(&sector_size)
89-
.expect("unknown sector size"),
90-
),
91-
porep_id,
92-
api_version,
93-
api_features: vec![],
94-
};
83+
let mut config = PoRepConfig::new_groth16(sector_size, porep_id, api_version);
9584
for feature in api_features {
9685
config.enable_feature(feature)?;
9786
}

filecoin-proofs/src/types/porep_proof_partitions.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
#[derive(Clone, Copy, Debug)]
1+
use serde::{Deserialize, Serialize};
2+
3+
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
24
pub struct PoRepProofPartitions(pub u8);
35

46
impl From<PoRepProofPartitions> for usize {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
use storage_proofs_core::api_version::ApiVersion;
2+
3+
use crate::types::{PoRepConfig, PoRepProofPartitions, SectorSize};
4+
5+
#[derive(Clone, Copy, Debug)]
6+
pub struct SectorClass {
7+
pub sector_size: SectorSize,
8+
pub partitions: PoRepProofPartitions,
9+
pub porep_id: [u8; 32],
10+
pub api_version: ApiVersion,
11+
}
12+
13+
impl From<SectorClass> for PoRepConfig {
14+
fn from(x: SectorClass) -> Self {
15+
let SectorClass {
16+
sector_size,
17+
partitions,
18+
porep_id,
19+
api_version,
20+
} = x;
21+
PoRepConfig {
22+
sector_size,
23+
partitions,
24+
porep_id,
25+
api_version,
26+
api_features: vec![],
27+
}
28+
}
29+
}

filecoin-proofs/src/types/sector_size.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
use fr32::to_unpadded_bytes;
2+
use serde::{Deserialize, Serialize};
23

34
use crate::types::{PaddedBytesAmount, UnpaddedBytesAmount};
45

5-
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
6+
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
67
pub struct SectorSize(pub u64);
78

89
impl From<u64> for SectorSize {

filecoin-proofs/tests/api.rs

+81-18
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,13 @@ use filecoin_proofs::constants::{
6060

6161
#[cfg(feature = "big-tests")]
6262
use filecoin_proofs::{
63-
SectorShape512MiB, SectorShape64GiB, SECTOR_SIZE_512_MIB, SECTOR_SIZE_64_GIB,
63+
SectorShape512MiB, SectorShape64GiB, SectorShape8MiB, SECTOR_SIZE_512_MIB, SECTOR_SIZE_64_GIB,
64+
SECTOR_SIZE_8_MIB,
6465
};
6566

67+
#[cfg(feature = "persist-regression-proofs")]
68+
use regression::persist_generated_proof_for_regression_testing;
69+
6670
// Use a fixed PoRep ID, so that the parents cache can be re-used between some tests.
6771
// Note however, that parents caches cannot be shared when testing the differences
6872
// between API v1 and v2 behaviour (since the parent caches will be different for the
@@ -403,30 +407,68 @@ fn test_seal_lifecycle_32kib_base_8() -> Result<()> {
403407

404408
#[cfg(feature = "big-tests")]
405409
#[test]
406-
fn test_seal_lifecycle_512mib_porep_id_v1_top_8_0_0_api_v1() -> Result<()> {
407-
use filecoin_proofs::{SectorShape512MiB, SECTOR_SIZE_512_MIB};
408-
let porep_id_v1: u64 = 2; // This is a RegisteredSealProof value
410+
fn test_seal_lifecycle_8mib_base_8() -> Result<()> {
411+
let test_inputs = vec![
412+
(ARBITRARY_POREP_ID_V1_0_0, ApiVersion::V1_0_0, Vec::new()),
413+
(ARBITRARY_POREP_ID_V1_1_0, ApiVersion::V1_1_0, Vec::new()),
414+
(ARBITRARY_POREP_ID_V1_2_0, ApiVersion::V1_2_0, Vec::new()),
415+
(
416+
ARBITRARY_POREP_ID_V1_2_0,
417+
ApiVersion::V1_2_0,
418+
vec![ApiFeature::SyntheticPoRep],
419+
),
420+
(
421+
ARBITRARY_POREP_ID_V1_2_0,
422+
ApiVersion::V1_2_0,
423+
vec![ApiFeature::NonInteractivePoRep],
424+
),
425+
];
409426

410-
let mut porep_id = [0u8; 32];
411-
porep_id[..8].copy_from_slice(&porep_id_v1.to_le_bytes());
412-
assert!(is_legacy_porep_id(porep_id));
427+
for (porep_id, api_version, features) in test_inputs {
428+
let porep_config = PoRepConfig::new_groth16_with_features(
429+
SECTOR_SIZE_8_MIB,
430+
porep_id,
431+
api_version,
432+
features,
433+
)?;
413434

414-
let porep_config = PoRepConfig::new_groth16(SECTOR_SIZE_512_MIB, porep_id, ApiVersion::V1_0_0);
415-
seal_lifecycle::<SectorShape512MiB>(&porep_config)
435+
seal_lifecycle::<SectorShape8MiB>(&porep_config)?;
436+
}
437+
438+
Ok(())
416439
}
417440

418441
#[cfg(feature = "big-tests")]
419442
#[test]
420-
fn test_seal_lifecycle_512mib_porep_id_v1_top_8_0_0_api_v1_1() -> Result<()> {
421-
use filecoin_proofs::{SectorShape512MiB, SECTOR_SIZE_512_MIB};
422-
let porep_id_v1_1: u64 = 7; // This is a RegisteredSealProof value
443+
fn test_seal_lifecycle_512mib_base_8() -> Result<()> {
444+
let test_inputs = vec![
445+
(ARBITRARY_POREP_ID_V1_0_0, ApiVersion::V1_0_0, Vec::new()),
446+
(ARBITRARY_POREP_ID_V1_1_0, ApiVersion::V1_1_0, Vec::new()),
447+
(ARBITRARY_POREP_ID_V1_2_0, ApiVersion::V1_2_0, Vec::new()),
448+
(
449+
ARBITRARY_POREP_ID_V1_2_0,
450+
ApiVersion::V1_2_0,
451+
vec![ApiFeature::SyntheticPoRep],
452+
),
453+
(
454+
ARBITRARY_POREP_ID_V1_2_0,
455+
ApiVersion::V1_2_0,
456+
vec![ApiFeature::NonInteractivePoRep],
457+
),
458+
];
423459

424-
let mut porep_id = [0u8; 32];
425-
porep_id[..8].copy_from_slice(&porep_id_v1_1.to_le_bytes());
426-
assert!(!is_legacy_porep_id(porep_id));
460+
for (porep_id, api_version, features) in test_inputs {
461+
let porep_config = PoRepConfig::new_groth16_with_features(
462+
SECTOR_SIZE_512_MIB,
463+
porep_id,
464+
api_version,
465+
features,
466+
)?;
467+
468+
seal_lifecycle::<SectorShape512MiB>(&porep_config)?;
469+
}
427470

428-
let porep_config = PoRepConfig::new_groth16(SECTOR_SIZE_512_MIB, porep_id, ApiVersion::V1_1_0);
429-
seal_lifecycle::<SectorShape512MiB>(&porep_config)
471+
Ok(())
430472
}
431473

432474
#[cfg(feature = "big-tests")]
@@ -962,6 +1004,15 @@ fn aggregate_seal_proofs<Tree: 'static + MerkleTreeTrait>(
9621004
);
9631005

9641006
for aggregate_version in aggregate_versions {
1007+
info!(
1008+
"Aggregating {} seal proofs with ApiVersion {}, Snarkpack{}, Features {:?}, and PoRep ID {:?}",
1009+
num_proofs_to_aggregate,
1010+
porep_config.api_version,
1011+
aggregate_version,
1012+
porep_config.api_features,
1013+
porep_config.porep_id
1014+
);
1015+
9651016
let mut commit_outputs = Vec::with_capacity(num_proofs_to_aggregate);
9661017
let mut commit_inputs = Vec::with_capacity(num_proofs_to_aggregate);
9671018
let mut seeds = Vec::with_capacity(num_proofs_to_aggregate);
@@ -2224,6 +2275,18 @@ fn proof_and_unseal<Tree: 'static + MerkleTreeTrait>(
22242275
aggregation_enabled,
22252276
)?;
22262277

2278+
// For regression suite only -- persist seal proof and everything required for the verify here
2279+
#[cfg(feature = "persist-regression-proofs")]
2280+
persist_generated_proof_for_regression_testing::<Tree>(
2281+
config,
2282+
prover_id,
2283+
sector_id,
2284+
ticket,
2285+
seed,
2286+
&pre_commit_output,
2287+
&commit_output,
2288+
)?;
2289+
22272290
unseal::<Tree>(
22282291
config,
22292292
cache_dir_path,
@@ -2283,7 +2346,7 @@ fn create_seal<R: Rng, Tree: 'static + MerkleTreeTrait>(
22832346
)?;
22842347
compare_trees::<Tree>(&tree_r_last_dir, &cache_dir, CacheKey::CommRLastTree)?;
22852348

2286-
// Check if creating only the tree_r generates the same output as the full pre commit phase 2
2349+
// Check if creating only the tree_c generates the same output as the full pre commit phase 2
22872350
// process.
22882351
let tree_c_dir = tempdir().expect("failed to create temp dir");
22892352
generate_tree_c::<_, _, Tree>(

0 commit comments

Comments
 (0)