monero_bulletproofs_generators/
lib.rs

1#![cfg_attr(docsrs, feature(doc_cfg))]
2#![doc = include_str!("../README.md")]
3#![cfg_attr(not(feature = "std"), no_std)]
4
5use std_shims::prelude::*;
6
7use curve25519_dalek::EdwardsPoint;
8
9use monero_io::VarInt;
10use monero_ed25519::Point;
11use monero_primitives::keccak256;
12
13/// The maximum amount of commitments provable for within a single Bulletproof(+).
14#[doc(hidden)]
15pub const MAX_BULLETPROOF_COMMITMENTS: usize = 16;
16/// The amount of bits a value within a commitment may use.
17#[doc(hidden)]
18pub const COMMITMENT_BITS: usize = 64;
19
20/// Container struct for Bulletproofs(+) generators.
21#[allow(non_snake_case)]
22#[doc(hidden)]
23pub struct Generators {
24  /// The G (bold) vector of generators.
25  #[doc(hidden)]
26  pub G: Vec<EdwardsPoint>,
27  /// The H (bold) vector of generators.
28  #[doc(hidden)]
29  pub H: Vec<EdwardsPoint>,
30}
31
32/// Generate generators as needed for Bulletproofs(+), as Monero does.
33///
34/// Consumers should not call this function ad-hoc, yet call it within a build script or use a
35/// once-initialized static.
36#[doc(hidden)]
37pub fn bulletproofs_generators(dst: &'static [u8]) -> Generators {
38  // The maximum amount of bits used within a single range proof.
39  const MAX_MN: usize = MAX_BULLETPROOF_COMMITMENTS * COMMITMENT_BITS;
40
41  let mut preimage = monero_ed25519::CompressedPoint::H.to_bytes().to_vec();
42  preimage.extend(dst);
43
44  let mut res = Generators { G: Vec::with_capacity(MAX_MN), H: Vec::with_capacity(MAX_MN) };
45  for i in 0 .. MAX_MN {
46    // We generate a pair of generators per iteration
47    let i = 2 * i;
48
49    let mut even = preimage.clone();
50    VarInt::write(&i, &mut even).expect("write failed but <Vec as io::Write> doesn't fail");
51    res.H.push(Point::biased_hash(keccak256(&even)).into());
52
53    let mut odd = preimage.clone();
54    VarInt::write(&(i + 1), &mut odd).expect("write failed but <Vec as io::Write> doesn't fail");
55    res.G.push(Point::biased_hash(keccak256(&odd)).into());
56  }
57  res
58}