Skip to content

Commit 6f639d5

Browse files
authored
Merge pull request #444 from filecoin-project/feat/439-generate-post-to-sector-builder
feat/439 - move generate_post to SectorBuilder
2 parents 967f398 + 3dc694c commit 6f639d5

File tree

5 files changed

+126
-72
lines changed

5 files changed

+126
-72
lines changed

filecoin-proofs/examples/ffi/main.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,6 @@ unsafe fn sector_builder_lifecycle() -> Result<(), Box<Error>> {
281281
panic!("{}", c_str_to_rust_str((*resp).error_msg))
282282
}
283283

284-
// copy the bytes from C to Rust
285284
let data_ptr = (*resp).data_ptr as *mut u8;
286285
let data_len = (*resp).data_len;
287286
let mut bytes_out = Vec::with_capacity(data_len);

filecoin-proofs/src/api/internal.rs

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ use storage_proofs::circuit::zigzag::ZigZagCompound;
1717
use storage_proofs::compound_proof::{self, CompoundProof};
1818
use storage_proofs::drgporep::{self, DrgParams};
1919
use storage_proofs::drgraph::{new_seed, DefaultTreeHasher};
20-
use storage_proofs::error::Result;
2120
use storage_proofs::fr32::{bytes_into_fr, fr_into_bytes, Fr32Ary};
2221
use storage_proofs::hasher::Hasher;
2322
use storage_proofs::layered_drgporep;
@@ -30,6 +29,8 @@ use storage_proofs::proof::ProofScheme;
3029
use storage_proofs::zigzag_drgporep::ZigZagDrgPoRep;
3130
use storage_proofs::zigzag_graph::ZigZagBucketGraph;
3231

32+
use crate::error;
33+
3334
type Commitment = [u8; 32];
3435

3536
/// FrSafe is an array of the largest whole number of bytes guaranteed not to overflow the field.
@@ -160,6 +161,34 @@ pub fn get_config(sector_config: &SectorConfig) -> (bool, Option<u32>, usize, us
160161
)
161162
}
162163

164+
pub struct PoStOutput {
165+
pub snark_proof: [u8; 192],
166+
pub faults: Vec<u64>,
167+
}
168+
169+
pub struct PoStInputPart {
170+
pub sealed_sector_access: Option<String>,
171+
pub comm_r: [u8; 32],
172+
}
173+
174+
pub struct PoStInput {
175+
pub challenge_seed: [u8; 32],
176+
pub input_parts: Vec<PoStInputPart>,
177+
}
178+
179+
pub fn generate_post(input: PoStInput) -> error::Result<PoStOutput> {
180+
let faults: Vec<u64> = if !input.input_parts.is_empty() {
181+
vec![0]
182+
} else {
183+
Default::default()
184+
};
185+
186+
Ok(PoStOutput {
187+
snark_proof: [42; 192],
188+
faults,
189+
})
190+
}
191+
163192
pub struct SealOutput {
164193
pub comm_r: Commitment,
165194
pub comm_r_star: Commitment,
@@ -173,7 +202,7 @@ pub fn seal<T: Into<PathBuf> + AsRef<Path>>(
173202
out_path: T,
174203
prover_id_in: &FrSafe,
175204
sector_id_in: &FrSafe,
176-
) -> Result<SealOutput> {
205+
) -> error::Result<SealOutput> {
177206
let (fake, delay_seconds, sector_bytes, proof_sector_bytes, uses_official_circuit) =
178207
get_config(sector_config);
179208

@@ -313,7 +342,7 @@ fn perform_replication<T: AsRef<Path>>(
313342
data: &mut [u8],
314343
fake: bool,
315344
proof_sector_bytes: usize,
316-
) -> Result<(
345+
) -> error::Result<(
317346
layered_drgporep::Tau<<DefaultTreeHasher as Hasher>::Domain>,
318347
Vec<MerkleTree<<DefaultTreeHasher as Hasher>::Domain, <DefaultTreeHasher as Hasher>::Function>>,
319348
)> {
@@ -343,7 +372,7 @@ fn perform_replication<T: AsRef<Path>>(
343372
}
344373
}
345374

346-
fn write_data<T: AsRef<Path>>(out_path: T, data: &[u8]) -> Result<()> {
375+
fn write_data<T: AsRef<Path>>(out_path: T, data: &[u8]) -> error::Result<()> {
347376
// Write replicated data to out_path.
348377
let f_out = File::create(out_path)?;
349378
let mut buf_writer = BufWriter::new(f_out);
@@ -359,7 +388,7 @@ pub fn get_unsealed_range<T: Into<PathBuf> + AsRef<Path>>(
359388
sector_id_in: &FrSafe,
360389
offset: u64,
361390
num_bytes: u64,
362-
) -> Result<(u64)> {
391+
) -> error::Result<(u64)> {
363392
let (fake, delay_seconds, sector_bytes, proof_sector_bytes, _uses_official_circuit) =
364393
get_config(sector_config);
365394
if let Some(delay) = delay_seconds {
@@ -401,7 +430,7 @@ pub fn verify_seal(
401430
prover_id_in: &FrSafe,
402431
sector_id_in: &FrSafe,
403432
proof_vec: &[u8],
404-
) -> Result<bool> {
433+
) -> error::Result<bool> {
405434
let (_fake, _delay_seconds, _sector_bytes, proof_sector_bytes, uses_official_circuit) =
406435
get_config(sector_config);
407436

@@ -455,7 +484,7 @@ pub fn verify_seal(
455484

456485
let proof = MultiProof::new_from_reader(Some(POREP_PARTITIONS), proof_vec, groth_params)?;
457486

458-
ZigZagCompound::verify(&compound_public_params, &public_inputs, &proof)
487+
ZigZagCompound::verify(&compound_public_params, &public_inputs, &proof).map_err(|e| e.into())
459488
}
460489

461490
#[cfg(test)]

filecoin-proofs/src/api/mod.rs

Lines changed: 24 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::api::internal::PoStOutput;
12
use crate::api::responses::err_code_and_msg;
23
use crate::api::responses::FCPResponseStatus;
34
use crate::api::responses::FFIPieceMetadata;
@@ -69,7 +70,7 @@ pub unsafe extern "C" fn verify_seal(
6970
response.is_valid = false;
7071
}
7172
Err(err) => {
72-
let (code, ptr) = err_code_and_msg(&err.into());
73+
let (code, ptr) = err_code_and_msg(&err);
7374
response.status_code = code;
7475
response.error_msg = ptr;
7576
}
@@ -87,18 +88,12 @@ pub unsafe extern "C" fn verify_seal(
8788

8889
/// Generates a proof-of-spacetime for the given replica commitments.
8990
///
90-
/// # Arguments
91-
///
92-
/// * `flattened_comm_rs_ptr` - pointer to the first cell in an array containing replica commitment
93-
/// bytes
94-
/// * `flattened_comm_rs_len` - number of bytes in the flattened_comm_rs_ptr array (must be a
95-
/// multiple of 32)
96-
/// * `_challenge_seed` - currently unused
9791
#[no_mangle]
9892
pub unsafe extern "C" fn generate_post(
93+
ptr: *mut SectorBuilder,
9994
flattened_comm_rs_ptr: *const u8,
10095
flattened_comm_rs_len: libc::size_t,
101-
_challenge_seed: &[u8; 32],
96+
challenge_seed: &[u8; 32],
10297
) -> *mut responses::GeneratePoSTResponse {
10398
let comm_rs = from_raw_parts(flattened_comm_rs_ptr, flattened_comm_rs_len)
10499
.iter()
@@ -111,24 +106,30 @@ pub unsafe extern "C" fn generate_post(
111106
acc
112107
});
113108

114-
// if more than one comm_r was provided, pretend like the first was faulty
115-
let fault_idxs: Vec<u64> = vec![0]
116-
.into_iter()
117-
.take(if comm_rs.len() > 1 { 1 } else { 0 })
118-
.collect();
109+
let mut response: responses::GeneratePoSTResponse = Default::default();
119110

120-
let mut result: responses::GeneratePoSTResponse = Default::default();
121-
122-
result.faults_len = fault_idxs.len();
123-
result.faults_ptr = fault_idxs.as_ptr();
111+
match (*ptr).generate_post(&comm_rs, challenge_seed) {
112+
Ok(PoStOutput {
113+
snark_proof,
114+
faults,
115+
}) => {
116+
response.status_code = FCPResponseStatus::FCPNoError;
117+
response.proof = snark_proof;
124118

125-
// tell Rust to forget about the Vec; we'll free it when we free the GeneratePoSTResult
126-
mem::forget(fault_idxs);
119+
response.faults_len = faults.len();
120+
response.faults_ptr = faults.as_ptr();
127121

128-
// write some fake proof
129-
result.proof = [42; API_POST_PROOF_BYTES];
122+
// we'll free this stuff when we free the GeneratePoSTResponse
123+
mem::forget(faults);
124+
}
125+
Err(err) => {
126+
let (code, ptr) = err_code_and_msg(&err);
127+
response.status_code = code;
128+
response.error_msg = ptr;
129+
}
130+
}
130131

131-
Box::into_raw(Box::new(result))
132+
raw_ptr(response)
132133
}
133134

134135
/// Verifies that a proof-of-spacetime is valid.
@@ -482,43 +483,3 @@ pub unsafe extern "C" fn get_staged_sectors(
482483

483484
raw_ptr(response)
484485
}
485-
486-
#[cfg(test)]
487-
mod tests {
488-
use super::*;
489-
use rand::{thread_rng, Rng};
490-
491-
#[test]
492-
fn generate_verify_post_roundtrip_test() {
493-
unsafe {
494-
let comm_rs: [u8; 32] = thread_rng().gen();
495-
let challenge_seed: [u8; 32] = thread_rng().gen();
496-
let generate_post_res = generate_post(&comm_rs[0], 32, &challenge_seed);
497-
498-
assert_eq!(
499-
FCPResponseStatus::FCPNoError,
500-
(*generate_post_res).status_code,
501-
"generate_post failed"
502-
);
503-
504-
let verify_post_res = verify_post(
505-
&comm_rs[0],
506-
32,
507-
&challenge_seed,
508-
&(*generate_post_res).proof,
509-
(*generate_post_res).faults_ptr,
510-
(*generate_post_res).faults_len,
511-
);
512-
513-
assert_eq!(
514-
FCPResponseStatus::FCPNoError,
515-
(*verify_post_res).status_code,
516-
"error verifying PoSt"
517-
);
518-
assert_eq!(true, (*verify_post_res).is_valid, "invalid PoSt");
519-
520-
responses::destroy_generate_post_response(generate_post_res);
521-
responses::destroy_verify_post_response(verify_post_res);
522-
}
523-
}
524-
}

filecoin-proofs/src/api/sector_builder/mod.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::api::internal::PoStOutput;
12
use crate::api::sector_builder::errors::SectorBuilderErr;
23
use crate::api::sector_builder::kv_store::fs::FileSystemKvs;
34
use crate::api::sector_builder::kv_store::KeyValueStore;
@@ -143,7 +144,18 @@ impl SectorBuilder {
143144

144145
// Returns all staged sector metadata.
145146
pub fn get_staged_sectors(&self) -> Result<Vec<StagedSectorMetadata>> {
146-
self.run_blocking(Request::GetStagedSectors)
147+
log_unrecov(self.run_blocking(Request::GetStagedSectors))
148+
}
149+
150+
// Generates a proof-of-spacetime. Blocks the calling thread.
151+
pub fn generate_post(
152+
&self,
153+
comm_rs: &[[u8; 32]],
154+
challenge_seed: &[u8; 32],
155+
) -> Result<PoStOutput> {
156+
log_unrecov(
157+
self.run_blocking(|tx| Request::GeneratePoSt(Vec::from(comm_rs), *challenge_seed, tx)),
158+
)
147159
}
148160

149161
// Run a task, blocking on the return channel.

filecoin-proofs/src/api/sector_builder/scheduler.rs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
use crate::api::internal;
2+
use crate::api::internal::PoStInput;
3+
use crate::api::internal::PoStInputPart;
4+
use crate::api::internal::PoStOutput;
15
use crate::api::sector_builder::errors::err_piecenotfound;
26
use crate::api::sector_builder::errors::err_unrecov;
37
use crate::api::sector_builder::helpers::add_piece::add_piece;
@@ -17,6 +21,7 @@ use crate::api::sector_builder::WrappedKeyValueStore;
1721
use crate::api::sector_builder::WrappedSectorStore;
1822
use crate::error::ExpectWithBacktrace;
1923
use crate::error::Result;
24+
use std::collections::HashMap;
2025
use std::sync::mpsc;
2126
use std::sync::Arc;
2227
use std::thread;
@@ -40,6 +45,11 @@ pub enum Request {
4045
GetSealedSectors(mpsc::SyncSender<Result<Vec<SealedSectorMetadata>>>),
4146
GetStagedSectors(mpsc::SyncSender<Result<Vec<StagedSectorMetadata>>>),
4247
GetSealStatus(SectorId, mpsc::SyncSender<Result<SealStatus>>),
48+
GeneratePoSt(
49+
Vec<[u8; 32]>,
50+
[u8; 32],
51+
mpsc::SyncSender<Result<PoStOutput>>,
52+
),
4353
RetrievePiece(String, mpsc::SyncSender<Result<Vec<u8>>>),
4454
SealAllStagedSectors(mpsc::SyncSender<Result<()>>),
4555
GetMaxUserBytesPerStagedSector(mpsc::SyncSender<u64>),
@@ -117,6 +127,9 @@ impl Scheduler {
117127
Request::HandleSealResult(sector_id, result) => {
118128
m.handle_seal_result(sector_id, *result);
119129
}
130+
Request::GeneratePoSt(comm_rs, chg_seed, tx) => {
131+
m.generate_post(&comm_rs, &chg_seed, tx)
132+
}
120133
Request::Shutdown => break,
121134
}
122135
}
@@ -143,6 +156,46 @@ pub struct SectorMetadataManager {
143156
}
144157

145158
impl SectorMetadataManager {
159+
pub fn generate_post(
160+
&self,
161+
comm_rs: &[[u8; 32]],
162+
challenge_seed: &[u8; 32],
163+
return_channel: mpsc::SyncSender<Result<PoStOutput>>,
164+
) {
165+
// reduce our sealed sector state-map to a mapping of comm_r to sealed
166+
// sector access (AKA path to sealed sector file)
167+
let comm_r_to_sector_access: HashMap<[u8; 32], String> = self
168+
.state
169+
.sealed
170+
.sectors
171+
.values()
172+
.fold(HashMap::new(), |mut acc, item| {
173+
let v = item.sector_access.clone();
174+
let k = item.comm_r;
175+
acc.entry(k).or_insert(v);
176+
acc
177+
});
178+
179+
let mut input_parts: Vec<PoStInputPart> = Default::default();
180+
181+
// eject from this loop with an error if we've been provided a comm_r
182+
// which does not correspond to any sealed sector metadata
183+
for comm_r in comm_rs {
184+
input_parts.push(PoStInputPart {
185+
sealed_sector_access: comm_r_to_sector_access.get(comm_r).cloned(),
186+
comm_r: *comm_r,
187+
});
188+
}
189+
190+
let output = internal::generate_post(PoStInput {
191+
challenge_seed: *challenge_seed,
192+
input_parts,
193+
});
194+
195+
// TODO: Where should this work be scheduled? New worker type?
196+
return_channel.send(output).expects(FATAL_HUNGUP);
197+
}
198+
146199
// Unseals the sector containing the referenced piece and returns its
147200
// bytes. Produces an error if this sector builder does not have a sealed
148201
// sector containing the referenced piece.

0 commit comments

Comments
 (0)