1use std::collections::BTreeMap;
5use std::fs::OpenOptions;
6use std::path::{Path, PathBuf};
7use std::{fmt, io};
8
9use anyhow::{Context, Result};
10use filecoin_proofs::{get_base_tree_leafs, get_base_tree_size, DefaultBinaryTree, DefaultPieceHasher, StoreConfig, BINARY_ARITY};
11use filecoin_proofs_api::post;
12use filecoin_proofs_api::seal;
13use forest_address::Address;
14use memmap::{Mmap, MmapOptions};
15use serde::{Deserialize, Serialize};
16use storage_proofs_core::{
17 cache_key::CacheKey,
18 merkle::{create_base_merkle_tree, BinaryMerkleTree},
19 util::default_rows_to_discard,
20};
21
22pub use filecoin_proofs_api::{
24 seal::{clear_cache, Labels, SealCommitPhase1Output, SealCommitPhase2Output, SealPreCommitPhase1Output, SealPreCommitPhase2Output},
25 update::{
26 empty_sector_update_encode_into, generate_empty_sector_update_proof_with_vanilla, generate_partition_proofs,
27 verify_empty_sector_update_proof, verify_partition_proofs,
28 },
29 ChallengeSeed, Commitment, PaddedBytesAmount, PartitionProofBytes, PieceInfo, PrivateReplicaInfo, ProverId, RegisteredPoStProof,
30 RegisteredSealProof, RegisteredUpdateProof, SectorId, Ticket, UnpaddedBytesAmount,
31};
32
33pub type ActorID = u64;
35
36pub type SnarkProof = crate::b64serde::BytesVec;
37
38#[derive(Debug)]
39pub struct PanicError {
40 pub message: String,
41}
42
43impl std::error::Error for PanicError {}
44
45impl fmt::Display for PanicError {
46 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
47 write!(f, "Panic: {}", self.message)
48 }
49}
50
51macro_rules! safe_call {
52 ($ex:expr) => {
53 match std::panic::catch_unwind(std::panic::AssertUnwindSafe(move || $ex)) {
54 Ok(r) => r,
55 Err(p) => {
56 let error_msg = match p.downcast_ref::<&str>() {
57 Some(message) => message.to_string(),
58 None => p
59 .downcast_ref::<String>()
60 .cloned()
61 .unwrap_or_else(|| format!("non-str unwind err: {:?}", p)),
62 };
63
64 Err(crate::fil_proofs::PanicError { message: error_msg }.into())
65 }
66 }
67 };
68}
69
70pub fn write_and_preprocess<R, W>(
71 registered_proof: RegisteredSealProof,
72 source: R,
73 target: W,
74 piece_size: UnpaddedBytesAmount,
75) -> Result<(PieceInfo, UnpaddedBytesAmount)>
76where
77 R: io::Read,
78 W: io::Read + io::Write + io::Seek,
79{
80 safe_call! {
81 seal::write_and_preprocess(registered_proof, source, target, piece_size)
82 }
83}
84
85pub fn seal_commit_phase1(
86 cache_path: PathBuf,
87 replica_path: PathBuf,
88 prover_id: ProverId,
89 sector_id: SectorId,
90 ticket: Ticket,
91 seed: Ticket,
92 pre_commit: SealPreCommitPhase2Output,
93 piece_infos: &[PieceInfo],
94) -> Result<SealCommitPhase1Output> {
95 safe_call! {
96 seal::seal_commit_phase1(
97 cache_path,
98 replica_path,
99 prover_id,
100 sector_id,
101 ticket,
102 seed,
103 pre_commit,
104 piece_infos,
105 )
106 }
107}
108
109pub fn seal_commit_phase2(
110 phase1_output: SealCommitPhase1Output,
111 prover_id: ProverId,
112 sector_id: SectorId,
113) -> Result<SealCommitPhase2Output> {
114 safe_call! {
115 seal::seal_commit_phase2(phase1_output, prover_id, sector_id)
116 }
117}
118
119pub fn seal_pre_commit_phase1(
120 registered_proof: RegisteredSealProof,
121 cache_path: PathBuf,
122 in_path: PathBuf,
123 out_path: PathBuf,
124 prover_id: ProverId,
125 sector_id: SectorId,
126 ticket: Ticket,
127 piece_infos: &[PieceInfo],
128) -> Result<SealPreCommitPhase1Output> {
129 safe_call! {
130 seal::seal_pre_commit_phase1(
131 registered_proof,
132 cache_path,
133 in_path,
134 out_path,
135 prover_id,
136 sector_id,
137 ticket,
138 piece_infos,
139 )
140 }
141}
142
143pub fn seal_pre_commit_phase2(
144 phase1_output: SealPreCommitPhase1Output,
145 cache_path: PathBuf,
146 out_path: PathBuf,
147) -> Result<SealPreCommitPhase2Output> {
148 safe_call! {
149 seal::seal_pre_commit_phase2(phase1_output, cache_path, out_path)
150 }
151}
152
153#[derive(Clone, Debug, Serialize, Deserialize)]
154pub struct SnapEncodeOutput {
155 pub comm_r_new: Commitment,
156 pub comm_r_last_new: Commitment,
157 pub comm_d_new: Commitment,
158}
159
160pub fn snap_encode_into(
161 registered_proof: RegisteredUpdateProof,
162 new_replica_path: PathBuf,
163 new_cache_path: PathBuf,
164 sector_path: PathBuf,
165 sector_cache_path: PathBuf,
166 staged_data_path: PathBuf,
167 piece_infos: &[PieceInfo],
168) -> Result<SnapEncodeOutput> {
169 safe_call! {
170 empty_sector_update_encode_into(
171 registered_proof,
172 new_replica_path,
173 new_cache_path,
174 sector_path,
175 sector_cache_path,
176 staged_data_path,
177 piece_infos,
178 )
179 .map(|out| SnapEncodeOutput {
180 comm_r_new: out.comm_r_new,
181 comm_r_last_new: out.comm_r_last_new,
182 comm_d_new: out.comm_d_new,
183 })
184 }
185}
186
187pub fn snap_generate_partition_proofs(
188 registered_proof: RegisteredUpdateProof,
189 comm_r_old: Commitment,
190 comm_r_new: Commitment,
191 comm_d_new: Commitment,
192 sector_path: PathBuf,
193 sector_cache_path: PathBuf,
194 replica_path: PathBuf,
195 replica_cache_path: PathBuf,
196) -> Result<Vec<PartitionProofBytes>> {
197 safe_call! {
198 generate_partition_proofs(
199 registered_proof,
200 comm_r_old,
201 comm_r_new,
202 comm_d_new,
203 sector_path,
204 sector_cache_path,
205 replica_path,
206 replica_cache_path,
207 )
208 }
209}
210
211pub type SnapProveOutput = Vec<u8>;
212
213pub fn snap_generate_sector_update_proof(
214 registered_proof: RegisteredUpdateProof,
215 vannilla_proofs: Vec<PartitionProofBytes>,
216 comm_r_old: Commitment,
217 comm_r_new: Commitment,
218 comm_d_new: Commitment,
219) -> Result<SnapProveOutput> {
220 safe_call! {
221 generate_empty_sector_update_proof_with_vanilla(
222 registered_proof,
223 vannilla_proofs,
224 comm_r_old,
225 comm_r_new,
226 comm_d_new,
227 ).map(|out| out.0)
228 }
229}
230
231pub fn snap_verify_sector_update_proof(
232 registered_proof: RegisteredUpdateProof,
233 proof: &[u8],
234 comm_r_old: Commitment,
235 comm_r_new: Commitment,
236 comm_d_new: Commitment,
237) -> Result<bool> {
238 safe_call! {
239 verify_empty_sector_update_proof(
240 registered_proof,
241 proof,
242 comm_r_old,
243 comm_r_new,
244 comm_d_new,
245 )
246 }
247}
248
249pub fn tree_d_path_in_dir(dir: &Path) -> PathBuf {
250 StoreConfig::data_path(dir, &CacheKey::CommDTree.to_string())
251}
252
253enum Bytes {
254 Mmap(Mmap),
255 InMem(Vec<u8>),
256}
257
258impl AsRef<[u8]> for Bytes {
259 #[inline]
260 fn as_ref(&self) -> &[u8] {
261 match self {
262 Bytes::Mmap(m) => &m[..],
263 Bytes::InMem(m) => &m[..],
264 }
265 }
266}
267
268pub fn create_tree_d(registered_proof: RegisteredSealProof, in_path: Option<PathBuf>, cache_path: PathBuf) -> Result<()> {
269 safe_call! {
270 create_tree_d_inner(
271 registered_proof,
272 in_path,
273 cache_path,
274 )
275 }
276}
277
278fn create_tree_d_inner(registered_proof: RegisteredSealProof, in_path: Option<PathBuf>, cache_path: PathBuf) -> Result<()> {
279 let sector_size = registered_proof.sector_size();
280 let tree_size = get_base_tree_size::<DefaultBinaryTree>(sector_size)?;
281 let tree_leafs = get_base_tree_leafs::<DefaultBinaryTree>(tree_size)?;
282
283 let data = match in_path {
284 Some(p) => {
285 let f = OpenOptions::new()
286 .read(true)
287 .open(&p)
288 .with_context(|| format!("open staged file {:?}", p))?;
289
290 let mapped = unsafe { MmapOptions::new().map(&f).with_context(|| format!("mmap staged file: {:?}", p))? };
291
292 Bytes::Mmap(mapped)
293 }
294
295 None => Bytes::InMem(vec![0; sector_size.0 as usize]),
296 };
297
298 let cfg = StoreConfig::new(
299 cache_path,
300 CacheKey::CommDTree.to_string(),
301 default_rows_to_discard(tree_leafs, BINARY_ARITY),
302 );
303
304 create_base_merkle_tree::<BinaryMerkleTree<DefaultPieceHasher>>(Some(cfg), tree_leafs, data.as_ref())?;
305
306 Ok(())
307}
308
309pub fn cached_filenames_for_sector(registered_proof: RegisteredSealProof) -> Vec<PathBuf> {
310 use RegisteredSealProof::*;
311 let mut trees = match registered_proof {
312 StackedDrg2KiBV1 | StackedDrg8MiBV1 | StackedDrg512MiBV1 | StackedDrg2KiBV1_1 | StackedDrg8MiBV1_1 | StackedDrg512MiBV1_1 => {
313 vec!["sc-02-data-tree-r-last.dat".into()]
314 }
315
316 StackedDrg32GiBV1 | StackedDrg32GiBV1_1 => (0..8).map(|idx| format!("sc-02-data-tree-r-last-{}.dat", idx).into()).collect(),
317
318 StackedDrg64GiBV1 | StackedDrg64GiBV1_1 => (0..16).map(|idx| format!("sc-02-data-tree-r-last-{}.dat", idx).into()).collect(),
319 };
320
321 trees.push("p_aux".into());
322 trees.push("t_aux".into());
323
324 trees
325}
326
327pub fn to_prover_id(miner_id: ActorID) -> ProverId {
328 let mut prover_id: ProverId = Default::default();
329 let actor_addr_payload = Address::new_id(miner_id).payload_bytes();
330 prover_id[..actor_addr_payload.len()].copy_from_slice(actor_addr_payload.as_ref());
331 prover_id
332}
333
334pub fn generate_window_post(
335 randomness: &ChallengeSeed,
336 replicas: &BTreeMap<SectorId, PrivateReplicaInfo>,
337 prover_id: ProverId,
338) -> Result<Vec<(RegisteredPoStProof, SnarkProof)>> {
339 safe_call! {
340 post::generate_window_post(
341 randomness,
342 replicas,
343 prover_id,
344 )
345 }
346 .map(|proofs| proofs.into_iter().map(|(r, p)| (r, p.into())).collect())
347}
348
349pub fn generate_winning_post(
350 randomness: &ChallengeSeed,
351 replicas: &BTreeMap<SectorId, PrivateReplicaInfo>,
352 prover_id: ProverId,
353) -> Result<Vec<(RegisteredPoStProof, SnarkProof)>> {
354 safe_call! {
355 post::generate_winning_post(
356 randomness,
357 replicas,
358 prover_id,
359 )
360 }
361 .map(|proofs| proofs.into_iter().map(|(r, p)| (r, p.into())).collect())
362}