Files
serai/coins/monero/generators/src/lib.rs

81 lines
2.4 KiB
Rust
Raw Normal View History

2022-09-29 05:25:29 -04:00
//! Generators used by Monero in both its Pedersen commitments and Bulletproofs(+).
//! An implementation of Monero's `ge_fromfe_frombytes_vartime`, simply called
//! `hash_to_point` here, is included, as needed to generate generators.
#![cfg_attr(not(feature = "std"), no_std)]
use lazy_static::lazy_static;
2022-09-29 08:08:49 -04:00
use sha3::{Digest, Keccak256};
use curve25519_dalek::edwards::{EdwardsPoint as DalekPoint, CompressedEdwardsY};
use curve25519_dalek::scalar::Scalar;
use std_shims::vec::Vec;
use group::{Group, GroupEncoding};
use dalek_ff_group::EdwardsPoint;
mod varint;
use varint::write_varint;
mod hash_to_point;
pub use hash_to_point::hash_to_point;
fn hash(data: &[u8]) -> [u8; 32] {
2022-09-29 08:08:49 -04:00
Keccak256::digest(data).into()
}
lazy_static! {
/// Monero alternate generator `H`, used for amounts in Pedersen commitments.
pub static ref H: DalekPoint =
CompressedEdwardsY(hash(&EdwardsPoint::generator().to_bytes()))
.decompress()
.unwrap()
.mul_by_cofactor();
/// Monero's `H` generator multiplied 2^i for each index, i.e. H, 2H, 4H, 8H, ...
/// used in old range proofs.
2023-06-23 17:58:33 +01:00
/// https://github.com/monero-project/monero/blob/94e67bf96bbc010241f29ada6abc89f49a81759c/src/
/// ringct/rctTypes.h#L628
pub static ref H2: [DalekPoint; 64] = generate_H2();
}
#[allow(non_snake_case)]
fn generate_H2() -> [DalekPoint; 64] {
let mut temp = Vec::with_capacity(64);
2023-06-23 17:58:33 +01:00
for i in 0 .. 64 {
temp.push(Scalar::from(2_u128.pow(i)) * *H)
}
temp.try_into().unwrap()
}
const MAX_M: usize = 16;
const N: usize = 64;
const MAX_MN: usize = MAX_M * N;
/// Container struct for Bulletproofs(+) generators.
#[allow(non_snake_case)]
pub struct Generators {
pub G: [EdwardsPoint; MAX_MN],
pub H: [EdwardsPoint; MAX_MN],
}
/// Generate generators as needed for Bulletproofs(+), as Monero does.
pub fn bulletproofs_generators(dst: &'static [u8]) -> Generators {
let mut res =
Generators { G: [EdwardsPoint::identity(); MAX_MN], H: [EdwardsPoint::identity(); MAX_MN] };
for i in 0 .. MAX_MN {
let i = 2 * i;
let mut even = H.compress().to_bytes().to_vec();
even.extend(dst);
let mut odd = even.clone();
write_varint(&i.try_into().unwrap(), &mut even).unwrap();
write_varint(&(i + 1).try_into().unwrap(), &mut odd).unwrap();
res.H[i / 2] = EdwardsPoint(hash_to_point(hash(&even)));
res.G[i / 2] = EdwardsPoint(hash_to_point(hash(&odd)));
}
res
}