1use crate::{
10 advz::{
11 polynomial_eval, AdvzInternal, Common, HasherDigest, KzgCommit, KzgEvalsMerkleTree,
12 MaybeGPU, Pairing, PolynomialMultiplier, UnivariateKzgPCS,
13 },
14 precomputable::Precomputable,
15 vid, VidDisperse, VidResult,
16};
17use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
18use ark_std::{end_timer, start_timer, vec::Vec};
19use jf_merkle_tree::{MerkleCommitment, MerkleTreeScheme};
20use jf_pcs::{prelude::Commitment, PolynomialCommitmentScheme, UnivariatePCS};
21
22use jf_utils::canonical;
23use serde::{Deserialize, Serialize};
24
25impl<E, H, T> Precomputable for AdvzInternal<E, H, T>
26where
27 E: Pairing,
28 H: HasherDigest,
29 T: Sync,
30 AdvzInternal<E, H, T>: MaybeGPU<E>,
31{
32 type PrecomputeData = PrecomputeData<E>;
33
34 fn commit_only_precompute<B>(
35 &self,
36 payload: B,
37 ) -> VidResult<(Self::Commit, Self::PrecomputeData)>
38 where
39 B: AsRef<[u8]>,
40 {
41 let payload = payload.as_ref();
42 let multiplicity = self.min_multiplicity(payload.len());
43 let polys = self.bytes_to_polys(payload)?;
44 let poly_commits: Vec<Commitment<E>> =
45 UnivariateKzgPCS::batch_commit(&self.ck, &polys).map_err(vid)?;
46 Ok((
47 Self::derive_commit(&poly_commits, payload.len(), self.num_storage_nodes)?,
48 PrecomputeData { poly_commits },
49 ))
50 }
51
52 fn disperse_precompute<B>(
53 &self,
54 payload: B,
55 data: &Self::PrecomputeData,
56 ) -> VidResult<VidDisperse<Self>>
57 where
58 B: AsRef<[u8]>,
59 {
60 let payload = payload.as_ref();
61 let polys = self.bytes_to_polys(payload)?;
62 let poly_commits = data.poly_commits.clone();
63
64 self.disperse_with_polys_and_commits(payload, polys, poly_commits)
65 }
66}
67
68#[derive(
69 Debug,
70 Clone,
71 CanonicalSerialize,
72 CanonicalDeserialize,
73 Derivative,
74 Deserialize,
75 Serialize,
76 PartialEq,
77 Eq,
78)]
79#[derivative(Hash(bound = ""))]
80pub struct PrecomputeData<E>
82where
83 E: Pairing,
84{
85 #[serde(with = "canonical")]
86 poly_commits: Vec<KzgCommit<E>>,
87}
88
89#[cfg(test)]
90mod tests {
91 use crate::{
92 advz::{
93 test::{advz_init, init_random_payload, init_srs},
94 Advz,
95 },
96 precomputable::Precomputable,
97 VidScheme,
98 };
99 use ark_bls12_381::Bls12_381;
100 use sha2::Sha256;
101
102 #[ignore]
103 #[test]
104 fn commit_only_with_data_timer() {
105 let (recovery_threshold, num_storage_nodes) = (256, 512);
107 let mut rng = jf_utils::test_rng();
108 let multiplicity = 1;
109 let srs = init_srs((recovery_threshold * multiplicity) as usize, &mut rng);
110 let advz = Advz::<Bls12_381, Sha256>::with_multiplicity(
111 num_storage_nodes,
112 recovery_threshold,
113 multiplicity,
114 srs,
115 )
116 .unwrap();
117 let payload_random = init_random_payload(1 << 20, &mut rng);
118
119 let (_commit, _data) = advz.commit_only_precompute(payload_random).unwrap();
120 }
121
122 #[ignore]
123 #[test]
124 fn disperse_with_data_timer() {
125 let (recovery_threshold, num_storage_nodes) = (64, 128);
127 let multiplicity = 4;
128 let mut rng = jf_utils::test_rng();
129 let srs = init_srs((recovery_threshold * multiplicity) as usize, &mut rng);
130 let advz = Advz::<Bls12_381, Sha256>::with_multiplicity(
131 num_storage_nodes,
132 recovery_threshold,
133 multiplicity,
134 srs,
135 )
136 .unwrap();
137 let payload_random = init_random_payload(1 << 20, &mut rng);
138 let (_commit, data) = advz.commit_only_precompute(&payload_random).unwrap();
139 let _ = advz.disperse_precompute(payload_random, &data);
140 }
141
142 #[test]
143 fn commit_disperse_recover_with_precomputed_data() {
144 let (advz, bytes_random) = advz_init();
145 let (commit, data) = advz.commit_only_precompute(&bytes_random).unwrap();
146 let disperse = advz.disperse_precompute(&bytes_random, &data).unwrap();
147 let (shares, common) = (disperse.shares, disperse.common);
148 for share in &shares {
149 let v = advz.verify_share(share, &common, &commit);
150 assert!(v.is_ok(), "share verification should succeed");
151 }
152
153 let bytes_recovered = advz
154 .recover_payload(&shares, &common)
155 .expect("recover_payload should succeed");
156 assert_eq!(bytes_recovered, bytes_random);
157 }
158}