mirror of
https://github.com/serai-dex/serai.git
synced 2025-12-13 06:29:25 +00:00
Tidy Borromean, fix bugs in last commit, replace todo! with unreachable!
This commit is contained in:
@@ -1,39 +1,36 @@
|
||||
#![allow(non_snake_case)]
|
||||
|
||||
use std::fmt::Debug;
|
||||
use std::io::{self, Read, Write};
|
||||
use core::fmt::Debug;
|
||||
use std_shims::io::{self, Read, Write};
|
||||
|
||||
use curve25519_dalek::edwards::EdwardsPoint;
|
||||
use curve25519_dalek::scalar::Scalar;
|
||||
use curve25519_dalek::traits::Identity;
|
||||
use curve25519_dalek::{traits::Identity, scalar::Scalar, edwards::EdwardsPoint};
|
||||
|
||||
use monero_generators::H2;
|
||||
use monero_generators::H_pow_2;
|
||||
use crate::{hash_to_scalar, serialize::*};
|
||||
|
||||
use crate::hash_to_scalar;
|
||||
use crate::serialize::*;
|
||||
|
||||
/// A Borromean signature.
|
||||
/// 64 Borromean ring signatures, modified to be aggregated with a shared challenge.
|
||||
///
|
||||
/// Note: This type keeps the data as raw bytes as Monero has
|
||||
/// some transactions with unreduced scalars in this field, we
|
||||
/// could use `from_bytes_mod_order` but then we would not be able
|
||||
/// to encode this back into it's original form.
|
||||
/// This type keeps the data as raw bytes as Monero has some transactions with unreduced scalars in
|
||||
/// this field. While we could use `from_bytes_mod_order`, we'd then not be able to encode this
|
||||
/// back into it's original form.
|
||||
///
|
||||
/// Those scalars also have a custom reduction algorithm...
|
||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||
pub struct BorroSig {
|
||||
pub struct BorromeanSignatures {
|
||||
pub s0: [[u8; 32]; 64],
|
||||
pub s1: [[u8; 32]; 64],
|
||||
pub ee: [u8; 32],
|
||||
}
|
||||
|
||||
impl BorroSig {
|
||||
pub fn read<R: Read>(r: &mut R) -> io::Result<BorroSig> {
|
||||
Ok(BorroSig {
|
||||
impl BorromeanSignatures {
|
||||
pub fn read<R: Read>(r: &mut R) -> io::Result<BorromeanSignatures> {
|
||||
Ok(BorromeanSignatures {
|
||||
s0: read_array(read_bytes, r)?,
|
||||
s1: read_array(read_bytes, r)?,
|
||||
ee: read_bytes(r)?,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn write<W: Write>(&self, w: &mut W) -> io::Result<()> {
|
||||
for s0 in self.s0.iter() {
|
||||
w.write_all(s0)?;
|
||||
@@ -43,66 +40,63 @@ impl BorroSig {
|
||||
}
|
||||
w.write_all(&self.ee)
|
||||
}
|
||||
|
||||
#[cfg(feature = "experimental")]
|
||||
fn verify(&self, keys_a: &[EdwardsPoint], keys_b: &[EdwardsPoint]) -> bool {
|
||||
let mut transcript = [0; 2048];
|
||||
for i in 0 .. 64 {
|
||||
// TODO: These aren't the correct reduction
|
||||
// TODO: Can either of these be tightened?
|
||||
let LL = EdwardsPoint::vartime_double_scalar_mul_basepoint(
|
||||
&Scalar::from_bytes_mod_order(self.ee),
|
||||
&keys_a[i],
|
||||
&Scalar::from_bytes_mod_order(self.s0[i]),
|
||||
);
|
||||
let LV = EdwardsPoint::vartime_double_scalar_mul_basepoint(
|
||||
&hash_to_scalar(LL.compress().as_bytes()),
|
||||
&keys_b[i],
|
||||
&Scalar::from_bytes_mod_order(self.s1[i]),
|
||||
);
|
||||
transcript[i .. ((i + 1) * 32)].copy_from_slice(LV.compress().as_bytes());
|
||||
}
|
||||
|
||||
// TODO: This isn't the correct reduction
|
||||
// TODO: Can this be tightened to from_canonical_bytes?
|
||||
hash_to_scalar(&transcript) == Scalar::from_bytes_mod_order(self.ee)
|
||||
}
|
||||
}
|
||||
|
||||
/// A range proof premised on Borromean ring signatures.
|
||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||
pub struct RangeSig {
|
||||
pub asig: BorroSig,
|
||||
pub Ci: [EdwardsPoint; 64],
|
||||
pub struct BorromeanRange {
|
||||
pub sig: BorromeanSignatures,
|
||||
pub bit_commitments: [EdwardsPoint; 64],
|
||||
}
|
||||
|
||||
impl RangeSig {
|
||||
pub fn read<R: Read>(r: &mut R) -> io::Result<RangeSig> {
|
||||
Ok(RangeSig { asig: BorroSig::read(r)?, Ci: read_array(read_point, r)? })
|
||||
impl BorromeanRange {
|
||||
pub fn read<R: Read>(r: &mut R) -> io::Result<BorromeanRange> {
|
||||
Ok(BorromeanRange {
|
||||
sig: BorromeanSignatures::read(r)?,
|
||||
bit_commitments: read_array(read_point, r)?,
|
||||
})
|
||||
}
|
||||
pub fn write<W: Write>(&self, w: &mut W) -> io::Result<()> {
|
||||
self.asig.write(w)?;
|
||||
write_raw_vec(write_point, &self.Ci, w)
|
||||
self.sig.write(w)?;
|
||||
write_raw_vec(write_point, &self.bit_commitments, w)
|
||||
}
|
||||
|
||||
#[cfg(feature = "experimental")]
|
||||
pub fn verify(&self, commitment: &EdwardsPoint) -> bool {
|
||||
let mut P1 = Vec::with_capacity(64);
|
||||
let mut P2 = Vec::with_capacity(64);
|
||||
let mut bbs0 = Vec::with_capacity(64);
|
||||
let mut bbs1 = Vec::with_capacity(64);
|
||||
|
||||
let bbee = Scalar::from_bytes_mod_order(self.asig.ee);
|
||||
|
||||
let mut C_temp = EdwardsPoint::identity();
|
||||
if &self.bit_commitments.iter().sum::<EdwardsPoint>() != commitment {
|
||||
return false;
|
||||
}
|
||||
|
||||
let H_pow_2 = H_pow_2();
|
||||
let mut commitments_sub_one = [EdwardsPoint::identity(); 64];
|
||||
for i in 0 .. 64 {
|
||||
bbs0.push(Scalar::from_bytes_mod_order(self.asig.s0[i]));
|
||||
bbs1.push(Scalar::from_bytes_mod_order(self.asig.s1[i]));
|
||||
|
||||
P1.push(self.Ci[i]);
|
||||
P2.push(P1[i] - H2[i]);
|
||||
|
||||
C_temp += P1[i];
|
||||
commitments_sub_one[i] = self.bit_commitments[i] - H_pow_2[i];
|
||||
}
|
||||
|
||||
if &C_temp != commitment {
|
||||
false
|
||||
} else {
|
||||
verify_borromean(P1, P2, bbee, bbs0, bbs1)
|
||||
}
|
||||
self.sig.verify(&self.bit_commitments, &commitments_sub_one)
|
||||
}
|
||||
}
|
||||
|
||||
fn verify_borromean(
|
||||
P1: Vec<EdwardsPoint>,
|
||||
P2: Vec<EdwardsPoint>,
|
||||
bbee: Scalar,
|
||||
bbs0: Vec<Scalar>,
|
||||
bbs1: Vec<Scalar>,
|
||||
) -> bool {
|
||||
let mut LV: Vec<u8> = Vec::with_capacity(2048);
|
||||
for i in 0 .. 64 {
|
||||
let LL = EdwardsPoint::vartime_double_scalar_mul_basepoint(&bbee, &P1[i], &bbs0[i]);
|
||||
let chash = hash_to_scalar(LL.compress().as_bytes());
|
||||
let LV_temp = EdwardsPoint::vartime_double_scalar_mul_basepoint(&chash, &P2[i], &bbs1[i]);
|
||||
LV.extend(LV_temp.compress().as_bytes());
|
||||
}
|
||||
let eecomp = hash_to_scalar(&LV);
|
||||
|
||||
eecomp == bbee
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user