//! Pedersen Commitments = v*G + b*H
//!
//! Tim Ruffing:
//! Switch commitment is (v*G + b*H), where b = b' + hash(v*G + b'*H,
//! b'*J). (So this "tweaks" the commitment, in a pay-to-contract / taproot
//! style).
// After the switch, users can reveal (v*G + b'*H, b'*J), and verifiers
// check if it's computed correctly and use as if it were the ElGamal
// commitment (v*G + b*H, b*J).
#![allow(non_snake_case)]
use mohan::{
hash::{
blake256,
hash_to_ristretto
},
dalek::{
constants::{
RISTRETTO_BASEPOINT_COMPRESSED,
RISTRETTO_BASEPOINT_POINT
},
ristretto::RistrettoPoint,
scalar::Scalar,
traits::MultiscalarMul,
}
};
use bacteria::Transcript;
/// Represents a pair of base points for Pedersen commitments.
///
/// The Bulletproofs implementation and API is designed to support
/// pluggable bases for Pedersen commitments, so that the choice of
/// bases is not hard-coded.
///
/// The default generators are:
///
/// * `B`: the `ristretto255` basepoint;
/// * `B_blinding`: the result of `ristretto255` SHA3-512
/// hash-to-group on input `B_bytes`.
#[derive(Copy, Clone)]
pub struct PedersenGens
{
/// Base for the committed value
pub B: RistrettoPoint,
/// Base for the blinding factor
pub B_blinding: RistrettoPoint,
/// Elgmal extension base
pub J_blinding: RistrettoPoint
}
impl PedersenGens {
/// Creates a Pedersen commitment using the value scalar and a blinding factor.
pub fn commit(&self, value: &Scalar, blinding: &Scalar) -> RistrettoPoint {
RistrettoPoint::multiscalar_mul(vec![value, blinding].into_iter(), &[self.B, self.B_blinding])
}
/// Creats a Switch Commitment Blind
pub fn blind_switch(&self, value: &Scalar, blinding: &Scalar) -> Scalar {
//r = r' + hash( v*H + r'*G , r'*J )
let rj = blinding * self.J_blinding;
//xG + vH
let sub_commit = self.commit(value, blinding);
let mut transcript = Transcript::new(b"blind_switch");
let c = {
transcript.commit_point(b"left", &sub_commit.compress());
transcript.commit_point(b"right", &rj.compress());
transcript.challenge_scalar(b"c")
};
blinding + c
}
/// Create a Switch Commitment
pub fn switch_commit(&self, value: &Scalar, blinding: &Scalar) -> RistrettoPoint {
self. commit(&value, &self.blind_switch(&value, &blinding))
}
}
impl Default for PedersenGens {
fn default() -> Self {
PedersenGens {
B: RISTRETTO_BASEPOINT_POINT,
B_blinding: hash_to_ristretto(RISTRETTO_BASEPOINT_COMPRESSED.as_bytes()),
J_blinding: hash_to_ristretto(
hash_to_ristretto(
RISTRETTO_BASEPOINT_COMPRESSED.as_bytes()
).compress().as_bytes()
)
}
}
}