monero_ed25519/
commitment.rs1use std_shims::{sync::LazyLock, io};
2
3use subtle::{Choice, ConstantTimeEq};
4use zeroize::{Zeroize, ZeroizeOnDrop};
5
6use monero_io::read_u64;
7
8use crate::{CompressedPoint, Point, Scalar};
9
10static H: LazyLock<curve25519_dalek::EdwardsPoint> = LazyLock::new(|| {
12 curve25519_dalek::edwards::CompressedEdwardsY(CompressedPoint::H.to_bytes())
13 .decompress()
14 .expect("couldn't decompress `CompressedPoint::H`")
15});
16
17#[derive(Clone, Zeroize, ZeroizeOnDrop)]
19pub struct Commitment {
20 pub mask: Scalar,
22 pub amount: u64,
24}
25
26impl ConstantTimeEq for Commitment {
27 fn ct_eq(&self, other: &Self) -> Choice {
28 self.mask.ct_eq(&other.mask) & self.amount.ct_eq(&other.amount)
29 }
30}
31
32impl core::fmt::Debug for Commitment {
33 fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
35 fmt.debug_struct("Commitment").field("amount", &self.amount).finish_non_exhaustive()
36 }
37}
38
39impl Commitment {
40 #[doc(hidden)] pub fn zero() -> Commitment {
47 Commitment { mask: Scalar::from(curve25519_dalek::Scalar::ONE), amount: 0 }
48 }
49
50 pub fn new(mask: Scalar, amount: u64) -> Commitment {
52 Commitment { mask, amount }
53 }
54
55 pub fn commit(&self) -> Point {
58 Point::from(
59 <curve25519_dalek::EdwardsPoint as curve25519_dalek::traits::MultiscalarMul>::multiscalar_mul(
60 [self.mask.into(), self.amount.into()],
61 [curve25519_dalek::constants::ED25519_BASEPOINT_POINT, *H],
62 ),
63 )
64 }
65
66 pub fn write<W: io::Write>(&self, w: &mut W) -> io::Result<()> {
71 self.mask.write(w)?;
72 w.write_all(&self.amount.to_le_bytes())
73 }
74
75 pub fn read<R: io::Read>(r: &mut R) -> io::Result<Commitment> {
80 Ok(Commitment::new(Scalar::read(r)?, read_u64(r)?))
81 }
82}