Skip to content

Commit be65d20

Browse files
authored
Add seal regression testing support (#1765)
* 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 * fix: skip regression tests on macos (parameters missing)
1 parent 266acc3 commit be65d20

10 files changed

+939
-36
lines changed

README.md

Lines changed: 16 additions & 0 deletions
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

Lines changed: 2 additions & 0 deletions
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 = { version = "2.1.10", optional = true }
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 = ["dep:file-lock"]
8991

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

filecoin-proofs/src/types/porep_config.rs

Lines changed: 3 additions & 14 deletions
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

Lines changed: 3 additions & 1 deletion
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 {

filecoin-proofs/src/types/sector_size.rs

Lines changed: 2 additions & 1 deletion
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

Lines changed: 83 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,15 @@ 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+
mod regression;
69+
#[cfg(feature = "persist-regression-proofs")]
70+
use regression::persist_generated_proof_for_regression_testing;
71+
6672
// Use a fixed PoRep ID, so that the parents cache can be re-used between some tests.
6773
// Note however, that parents caches cannot be shared when testing the differences
6874
// between API v1 and v2 behaviour (since the parent caches will be different for the
@@ -403,30 +409,68 @@ fn test_seal_lifecycle_32kib_base_8() -> Result<()> {
403409

404410
#[cfg(feature = "big-tests")]
405411
#[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
412+
fn test_seal_lifecycle_8mib_base_8() -> Result<()> {
413+
let test_inputs = vec![
414+
(ARBITRARY_POREP_ID_V1_0_0, ApiVersion::V1_0_0, Vec::new()),
415+
(ARBITRARY_POREP_ID_V1_1_0, ApiVersion::V1_1_0, Vec::new()),
416+
(ARBITRARY_POREP_ID_V1_2_0, ApiVersion::V1_2_0, Vec::new()),
417+
(
418+
ARBITRARY_POREP_ID_V1_2_0,
419+
ApiVersion::V1_2_0,
420+
vec![ApiFeature::SyntheticPoRep],
421+
),
422+
(
423+
ARBITRARY_POREP_ID_V1_2_0,
424+
ApiVersion::V1_2_0,
425+
vec![ApiFeature::NonInteractivePoRep],
426+
),
427+
];
409428

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));
429+
for (porep_id, api_version, features) in test_inputs {
430+
let porep_config = PoRepConfig::new_groth16_with_features(
431+
SECTOR_SIZE_8_MIB,
432+
porep_id,
433+
api_version,
434+
features,
435+
)?;
413436

414-
let porep_config = PoRepConfig::new_groth16(SECTOR_SIZE_512_MIB, porep_id, ApiVersion::V1_0_0);
415-
seal_lifecycle::<SectorShape512MiB>(&porep_config)
437+
seal_lifecycle::<SectorShape8MiB>(&porep_config)?;
438+
}
439+
440+
Ok(())
416441
}
417442

418443
#[cfg(feature = "big-tests")]
419444
#[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
445+
fn test_seal_lifecycle_512mib_base_8() -> Result<()> {
446+
let test_inputs = vec![
447+
(ARBITRARY_POREP_ID_V1_0_0, ApiVersion::V1_0_0, Vec::new()),
448+
(ARBITRARY_POREP_ID_V1_1_0, ApiVersion::V1_1_0, Vec::new()),
449+
(ARBITRARY_POREP_ID_V1_2_0, ApiVersion::V1_2_0, Vec::new()),
450+
(
451+
ARBITRARY_POREP_ID_V1_2_0,
452+
ApiVersion::V1_2_0,
453+
vec![ApiFeature::SyntheticPoRep],
454+
),
455+
(
456+
ARBITRARY_POREP_ID_V1_2_0,
457+
ApiVersion::V1_2_0,
458+
vec![ApiFeature::NonInteractivePoRep],
459+
),
460+
];
423461

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));
462+
for (porep_id, api_version, features) in test_inputs {
463+
let porep_config = PoRepConfig::new_groth16_with_features(
464+
SECTOR_SIZE_512_MIB,
465+
porep_id,
466+
api_version,
467+
features,
468+
)?;
469+
470+
seal_lifecycle::<SectorShape512MiB>(&porep_config)?;
471+
}
427472

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

432476
#[cfg(feature = "big-tests")]
@@ -962,6 +1006,15 @@ fn aggregate_seal_proofs<Tree: 'static + MerkleTreeTrait>(
9621006
);
9631007

9641008
for aggregate_version in aggregate_versions {
1009+
info!(
1010+
"Aggregating {} seal proofs with ApiVersion {}, Snarkpack{}, Features {:?}, and PoRep ID {:?}",
1011+
num_proofs_to_aggregate,
1012+
porep_config.api_version,
1013+
aggregate_version,
1014+
porep_config.api_features,
1015+
porep_config.porep_id
1016+
);
1017+
9651018
let mut commit_outputs = Vec::with_capacity(num_proofs_to_aggregate);
9661019
let mut commit_inputs = Vec::with_capacity(num_proofs_to_aggregate);
9671020
let mut seeds = Vec::with_capacity(num_proofs_to_aggregate);
@@ -2224,6 +2277,18 @@ fn proof_and_unseal<Tree: 'static + MerkleTreeTrait>(
22242277
aggregation_enabled,
22252278
)?;
22262279

2280+
// For regression suite only -- persist seal proof and everything required for the verify here
2281+
#[cfg(feature = "persist-regression-proofs")]
2282+
persist_generated_proof_for_regression_testing::<Tree>(
2283+
config,
2284+
prover_id,
2285+
sector_id,
2286+
ticket,
2287+
seed,
2288+
&pre_commit_output,
2289+
&commit_output,
2290+
)?;
2291+
22272292
unseal::<Tree>(
22282293
config,
22292294
cache_dir_path,
@@ -2283,7 +2348,7 @@ fn create_seal<R: Rng, Tree: 'static + MerkleTreeTrait>(
22832348
)?;
22842349
compare_trees::<Tree>(&tree_r_last_dir, &cache_dir, CacheKey::CommRLastTree)?;
22852350

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

0 commit comments

Comments
 (0)