monero_bulletproofs/
core.rs1use std_shims::{vec, vec::Vec};
2
3use curve25519_dalek::{
4 traits::{MultiscalarMul as _, VartimeMultiscalarMul as _},
5 scalar::Scalar,
6 edwards::EdwardsPoint,
7};
8
9pub(crate) use monero_bulletproofs_generators::{
10 MAX_BULLETPROOF_COMMITMENTS as MAX_COMMITMENTS, COMMITMENT_BITS,
11};
12
13pub(crate) fn multiexp(pairs: &[(Scalar, EdwardsPoint)]) -> EdwardsPoint {
14 let mut buf_scalars = Vec::with_capacity(pairs.len());
15 let mut buf_points = Vec::with_capacity(pairs.len());
16 for (scalar, point) in pairs {
17 buf_scalars.push(scalar);
18 buf_points.push(point);
19 }
20 EdwardsPoint::multiscalar_mul(buf_scalars, buf_points)
21}
22
23pub(crate) fn multiexp_vartime(pairs: &[(Scalar, EdwardsPoint)]) -> EdwardsPoint {
24 let mut buf_scalars = Vec::with_capacity(pairs.len());
25 let mut buf_points = Vec::with_capacity(pairs.len());
26 for (scalar, point) in pairs {
27 buf_scalars.push(scalar);
28 buf_points.push(point);
29 }
30 EdwardsPoint::vartime_multiscalar_mul(buf_scalars, buf_points)
31}
32
33pub(crate) fn challenge_products(challenges: &[(Scalar, Scalar)]) -> Vec<Scalar> {
53 let mut products = vec![Scalar::ONE; 1 << challenges.len()];
54
55 if !challenges.is_empty() {
56 products[0] = challenges[0].1;
57 products[1] = challenges[0].0;
58
59 for (j, challenge) in challenges.iter().enumerate().skip(1) {
60 let mut slots = (1 << (j + 1)) - 1;
61 while slots > 0 {
62 products[slots] = products[slots / 2] * challenge.0;
63 products[slots - 1] = products[slots / 2] * challenge.1;
64
65 slots = slots.saturating_sub(2);
66 }
67 }
68
69 for product in &products {
71 debug_assert!(*product != Scalar::ZERO);
72 }
73 }
74
75 products
76}