Skip to content

Commit 65a56c2

Browse files
committed
make sure Verification type is not dropped w/o verification
1 parent 18a5a22 commit 65a56c2

File tree

2 files changed

+37
-19
lines changed

2 files changed

+37
-19
lines changed

src/range_proof/mod.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ impl RangeProof {
135135
n: usize,
136136
) -> Result<(), &'static str> {
137137
RangeProof::verify_batch(
138-
&[self.prepare_verification(value_commitments, transcript, rng, n)],
138+
[self.prepare_verification(value_commitments, transcript, rng, n)],
139139
gens,
140140
rng
141141
)
@@ -206,8 +206,6 @@ mod tests {
206206
let mut rng = OsRng::new().unwrap();
207207
let transcript = ProofTranscript::new(b"AggregatedRangeProofTest");
208208

209-
let max_n = nm.iter().map(|(n,_)| *n).max().unwrap_or(0);
210-
let max_m = nm.iter().map(|(_,m)| *m).max().unwrap_or(0);
211209
let verifications = nm.iter().map(|(n,m)| {
212210
let (p, vc) = singleparty_create_helper(*n,*m);
213211
bincode::deserialize::<RangeProof>(&p)
@@ -220,11 +218,14 @@ mod tests {
220218
)
221219
}).collect::<Vec<_>>();
222220

221+
let max_n = verifications.iter().map(|v| v.n).max().unwrap_or(0);
222+
let max_m = verifications.iter().map(|v| v.m).max().unwrap_or(0);
223+
223224
let generators = Generators::new(PedersenGenerators::default(), max_n, max_m);
224225

225226
assert!(
226227
RangeProof::verify_batch(
227-
verifications.as_slice(),
228+
verifications,
228229
generators.all(),
229230
&mut rng
230231
).is_ok()

src/range_proof/verification.rs

Lines changed: 32 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,10 @@ use util;
2020
/// `RangeProof::verify_batch` function.
2121
pub struct Verification {
2222
/// Number of commitments in the aggregated proof
23-
m: usize,
23+
pub m: usize,
2424

2525
/// Size of the range in bits
26-
n: usize,
26+
pub n: usize,
2727

2828
/// Pair of scalars multiplying pedersen bases `B`, `B_blinding`.
2929
pedersen_base_scalars: (Scalar, Scalar),
@@ -41,6 +41,19 @@ pub struct Verification {
4141

4242
/// List of dynamic bases for the corresponding scalars.
4343
dynamic_bases: Vec<RistrettoPoint>,
44+
45+
/// Internal flag that prevents accidentally dropping
46+
/// this struct without properly verifying it first.
47+
verified: bool,
48+
}
49+
50+
impl Drop for Verification {
51+
fn drop(&mut self) {
52+
if !self.verified {
53+
panic!("Deferred range proof Verification was not explicitly \
54+
verified using `RangeProof::verify_batch`!");
55+
}
56+
}
4457
}
4558

4659
impl RangeProof {
@@ -133,7 +146,8 @@ impl RangeProof {
133146
.chain(self.ipp_proof.L_vec.iter())
134147
.chain(self.ipp_proof.R_vec.iter())
135148
.cloned()
136-
.collect()
149+
.collect(),
150+
verified: false
137151
}
138152
}
139153

@@ -142,39 +156,42 @@ impl RangeProof {
142156
/// Proofs may use different ranges (`n`) or different number of aggregated commitments (`m`).
143157
/// You must provide big enough view into generators (`gens`) that covers
144158
/// the biggest proof
145-
pub fn verify_batch<R: Rng, V: Borrow<Verification>>(
146-
batch: &[V],
147-
gens: GeneratorsView,
159+
pub fn verify_batch<R: Rng, B: AsMut<[Verification]>>(
160+
mut batch: B,
161+
gens: GeneratorsView,
148162
rng: &mut R
149163
) -> Result<(), &'static str> {
164+
let batch = batch.as_mut();
165+
150166
// we will special-case the first item to avoid unnecessary multiplication,
151167
// so lets check that we have at least one item.
152168
if batch.len() == 0 {
153169
return Ok(())
154170
}
155171

156172
// Make sure we have enough static generators
157-
let n = batch.iter().map(|v| v.borrow().n).max().unwrap_or(0);
158-
let m = batch.iter().map(|v| v.borrow().m).max().unwrap_or(0);
173+
let n = batch.iter().map(|v| v.n).max().unwrap_or(0);
174+
let m = batch.iter().map(|v| v.m).max().unwrap_or(0);
159175
if gens.G.len() < (n * m) {
160176
return Err("The generators view does not have enough generators for the largest proof")
161177
}
162178

163179
// First statement is used without a random factor
164-
let mut pedersen_base_scalars: (Scalar, Scalar) = batch[0].borrow().pedersen_base_scalars;
165-
let mut g_scalars: Vec<Scalar> = batch[0].borrow().g_scalars.clone();
166-
let mut h_scalars: Vec<Scalar> = batch[0].borrow().h_scalars.clone();
180+
batch[0].verified = true;
181+
let mut pedersen_base_scalars: (Scalar, Scalar) = batch[0].pedersen_base_scalars;
182+
let mut g_scalars: Vec<Scalar> = batch[0].g_scalars.clone();
183+
let mut h_scalars: Vec<Scalar> = batch[0].h_scalars.clone();
167184

168185
// pad static scalars to the largest proof
169186
g_scalars.resize(n*m, Scalar::zero());
170187
h_scalars.resize(n*m, Scalar::zero());
171188

172-
let mut dynamic_base_scalars: Vec<Scalar> = batch[0].borrow().dynamic_base_scalars.clone();
173-
let mut dynamic_bases: Vec<RistrettoPoint> = batch[0].borrow().dynamic_bases.clone();
189+
let mut dynamic_base_scalars: Vec<Scalar> = batch[0].dynamic_base_scalars.clone();
190+
let mut dynamic_bases: Vec<RistrettoPoint> = batch[0].dynamic_bases.clone();
174191

175192
// Other statements are added with a random factor per statement
176-
for borrowable_verification in &batch[1..] {
177-
let verification = borrowable_verification.borrow();
193+
for verification in &mut batch[1..] {
194+
verification.verified = true;
178195
let batch_challenge = Scalar::random(rng);
179196

180197
pedersen_base_scalars.0 += batch_challenge*verification.pedersen_base_scalars.0;

0 commit comments

Comments
 (0)