$$
\def\line#1{{{\small \rm \rlap{#1.}\hphantom{10.}} \ \ }}
\def\SECTORSIZE{\textsf{SECTOR_SIZE}}
\def\ReplicaID{\text{ReplicaID}}
\def\NIPARTS{\textsf{NI_POREP_PARTITIONS}}
\def\NICHALLENGES{\textsf{NI_POREP_CHALLENGES}}
\def\PARTCHALLENGES{\textsf{POREP_PARTITION_CHALLENGES}}
\def\thin{\thinspace}
\def\const{\textbf{const }}
\def\type{\textbf{type }}
\def\bullet{\ {\small \text{• }}}
$$
# NI-PoRep Audit Spec
## Constants & Types
$\bullet \const \SECTORSIZE \in \{2 \text{ KiB}, 4 \text{ KiB}, 16 \text{ KiB}, 32 \text{ KiB}, 8 \text{ MiB}, 16 \text{ MiB}, 512 \text{ MiB}, 1 \text{ GiB}, 32 \text{ GiB}, 64 \text{ GiB}\}$
$\bullet \const \textsf{SECTOR_NODES} = {\SECTORSIZE \over 32 \text{ bytes per node}}$
$\bullet \type \ReplicaID \equiv [\texttt{u8;} \thin 32]$
$\bullet \type \text{CommR} \equiv [\texttt{u8;} \thin 32]$
${\small \text{• }} \type \text{Challenge} \equiv \mathbb{N} \in [1, \textsf{SECTOR_NODES})$
### PoRep [Interactive]:
$\bullet \const \PARTCHALLENGES = \begin{cases}18 & \text{if } \SECTORSIZE \geq 32 \text{ GiB} \\ 2 & \text{otherwise}\end{cases}$
$\bullet \const \textsf{POREP_MIN_CHALLENGES} = \begin{cases} 176 & \text{if } \SECTORSIZE \geq 32\ \text{GiB} \\ 2 &\text{otherwise}\end{cases}$
### NI-PoRep:
$\bullet \const \textsf{NI_POREP_MIN_CHALLENGES} = \left\lceil 12.8 * \textsf{POREP_MIN_CHALLENGES} \right\rceil = \begin{cases}2253 & \text{if } \SECTORSIZE \geq 32 \text{ GiB} \\ 26 & \text{otherwise}\end{cases}$
$\bullet \const \NIPARTS = \left\lceil {\textsf{NI_POREP_MIN_CHALLENGES} \over \PARTCHALLENGES} \right\rceil = \begin{cases}126 & \text{if } \SECTORSIZE \geq 32 \text{ GiB} \\ 13 & \text{otherwise}\end{cases}$
$\bullet \const \NICHALLENGES = \NIPARTS * \PARTCHALLENGES = \begin{cases} 2268 & \text{if } \SECTORSIZE \geq 32\ \text{GiB} \\ 2 &\text{otherwise}\end{cases}$
## Challenge Generation
[Link to challenge generation code in `rust-fil-proofs`](https://github.com/filecoin-project/rust-fil-proofs/blob/23c09732dd56c384078b76c3ba36be69f5118e07/storage-proofs-porep/src/stacked/vanilla/challenges.rs#L127-L157)
$\bullet \const \textsf{NI_POREP_CHALLENGE_GEN_TAG}: [\texttt{u8;}\thin 36] = \texttt{utf8_bytes}(\text{“filecoin.io|PoRep|1|NonInteractive|1"})$
$\overline{\underline{\text{Function:}\ \texttt{gen_niporep_challenges}(\text{ReplicaID}, \text{CommR}) \rightarrow \left[\text{Challenge} \texttt{;}\thin \NICHALLENGES\right]}}$
$\line{1} \text{challenges}: [\text{Challenge} \texttt{;}\thin \NICHALLENGES] = [\thinspace]$
$\line{2} \text{preimg_prefix}: [\texttt{u8}; 100] = \textsf{NI_POREP_CHALLENGE_GEN_TAG} \mathbin\Vert \text{ReplicaID} \mathbin\Vert \text{CommR}$
$\line{3} \texttt{for } \text{challenge_index} \in [0, \textsf{NI_POREP_CHALLENGES})\thinspace \textbf{:}$
$\line{4} \quad \text{preimg}: [\texttt{u8}; 104] = \text{preimg_prefix} \mathbin\Vert \texttt{le_bytes}(\text{challenge_index}, 4)$
$\line{5} \quad \text{digest_words}: [\texttt{u32}; 8] = \texttt{sha256}(\text{preimg})$
$\line{6} \quad \text{digest_int}: \texttt{u256} = \texttt{u256::from_le_u32s}(\text{digest_words})$
$\line{7} \quad \text{challenge}: \text{Challenge} = (\text{digest_int} \mathbin\% (\text{SECTOR_NODES} - 1)) + 1$
$\line{8} \quad \text{challenges}\textbf{.}\texttt{push}(\text{challenge})$
$\line{9} \texttt{return } \text{challenges}$
## Groth16 Proving
$\bullet \textbf{const } \textsf{POREP_MAX_GROTH16_BATCH_SIZE} = 10$
$\overline{\underline{\text{Function:}\ \texttt{ni_porep_groth16_batch_prove}(\text{circuits}: [\text{PoRepCircuit}\texttt{;}\thin \NIPARTS]) \rightarrow [\text{Groth16Proof}\texttt{;}\thin \NIPARTS]}}$
$\line{1} \text{groth16_proofs}: [\text{Groth16Proof}; \NIPARTS] = [\thin]$
$\line{2} \textbf{for } \text{circuit_batch} \in \text{circuits}\texttt{.chunks}(\textsf{POREP_MAX_GROTH16_BATCH_SIZE}) \thin\textbf{:}$
$\line{3} \quad \text{groth16_proofs} = \text{groth16_proofs} \mathbin{\Vert} \texttt{groth16_batch_prove}(\text{circuit_batch})$
$\line{4} \texttt{return } \text{groth16_proofs}$
## Groth16 Aggregation
[Link to NI-PoRep SnarkPack proving in `rust-fil-proofs`](https://github.com/filecoin-project/rust-fil-proofs/blob/23c09732dd56c384078b76c3ba36be69f5118e07/filecoin-proofs/src/api/seal.rs#L570-L579)
[Link to NI-PoRep SnarkPack verification in `rust-fil-proofs`](https://github.com/filecoin-project/rust-fil-proofs/blob/23c09732dd56c384078b76c3ba36be69f5118e07/filecoin-proofs/src/api/seal.rs#L906-L924)
$\overline{\text{Function:}\ \texttt{ni_porep_snarkpack_aggregate}( \quad\quad\quad\quad\quad\quad\quad\quad}$
$\quad \textsf{groth16_proofs}: [\text{Groth16Proof}\texttt{;}\thin \NIPARTS],$
$\quad \textsf{comm_r}: \text{CommR},$
$\quad \textsf{challenge_seed}: [\texttt{u8;} \thin 32],$
$\underline{) \rightarrow \text{SnarkPackProof}\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\ \ }$
$\line{1} \textsf{proofs_len} = \NIPARTS$
$\line{2} \textsf{agg_proofs_len} = 2^{\lceil \log_2(\textsf{proofs_len}) \rceil}$
$\line{3} \textsf{agg_pad_len} = \textsf{agg_proofs_len} - \textsf{proofs_len}$
$\line{4} \textsf{proofs_padded}: [\text{Groth16Proof} \texttt{;}\thin \textsf{agg_proofs_len}] = \textsf{groth16_proofs} \mathbin\Vert [\textsf{groth16_proofs}\texttt{.last}() \texttt{;}\thin \textsf{agg_pad_len}]$
$\line{5} \textsf{transcript}: [\texttt{u8;} 32] = \texttt{sha256}(\textsf{challenge_seed} \mathbin\Vert \textsf{comm_r})$
$\line{6} \texttt{return snarkpack_prove}(\textsf{proofs_padded}, \textsf{transcript})$