mirror of
https://github.com/serai-dex/serai.git
synced 2025-12-11 13:39:25 +00:00
Tidy Mlsag
This commit is contained in:
@@ -1,5 +1,3 @@
|
|||||||
#![allow(non_snake_case)]
|
|
||||||
|
|
||||||
use core::fmt::Debug;
|
use core::fmt::Debug;
|
||||||
use std_shims::io::{self, Read, Write};
|
use std_shims::io::{self, Read, Write};
|
||||||
|
|
||||||
@@ -52,11 +50,13 @@ impl BorromeanSignatures {
|
|||||||
for i in 0 .. 64 {
|
for i in 0 .. 64 {
|
||||||
// TODO: These aren't the correct reduction
|
// TODO: These aren't the correct reduction
|
||||||
// TODO: Can either of these be tightened?
|
// TODO: Can either of these be tightened?
|
||||||
|
#[allow(non_snake_case)]
|
||||||
let LL = EdwardsPoint::vartime_double_scalar_mul_basepoint(
|
let LL = EdwardsPoint::vartime_double_scalar_mul_basepoint(
|
||||||
&Scalar::from_bytes_mod_order(self.ee),
|
&Scalar::from_bytes_mod_order(self.ee),
|
||||||
&keys_a[i],
|
&keys_a[i],
|
||||||
&Scalar::from_bytes_mod_order(self.s0[i]),
|
&Scalar::from_bytes_mod_order(self.s0[i]),
|
||||||
);
|
);
|
||||||
|
#[allow(non_snake_case)]
|
||||||
let LV = EdwardsPoint::vartime_double_scalar_mul_basepoint(
|
let LV = EdwardsPoint::vartime_double_scalar_mul_basepoint(
|
||||||
&hash_to_scalar(LL.compress().as_bytes()),
|
&hash_to_scalar(LL.compress().as_bytes()),
|
||||||
&keys_b[i],
|
&keys_b[i],
|
||||||
@@ -74,19 +74,19 @@ impl BorromeanSignatures {
|
|||||||
/// A range proof premised on Borromean ring signatures.
|
/// A range proof premised on Borromean ring signatures.
|
||||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||||
pub struct BorromeanRange {
|
pub struct BorromeanRange {
|
||||||
pub sig: BorromeanSignatures,
|
pub sigs: BorromeanSignatures,
|
||||||
pub bit_commitments: [EdwardsPoint; 64],
|
pub bit_commitments: [EdwardsPoint; 64],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BorromeanRange {
|
impl BorromeanRange {
|
||||||
pub fn read<R: Read>(r: &mut R) -> io::Result<BorromeanRange> {
|
pub fn read<R: Read>(r: &mut R) -> io::Result<BorromeanRange> {
|
||||||
Ok(BorromeanRange {
|
Ok(BorromeanRange {
|
||||||
sig: BorromeanSignatures::read(r)?,
|
sigs: BorromeanSignatures::read(r)?,
|
||||||
bit_commitments: read_array(read_point, r)?,
|
bit_commitments: read_array(read_point, r)?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
pub fn write<W: Write>(&self, w: &mut W) -> io::Result<()> {
|
pub fn write<W: Write>(&self, w: &mut W) -> io::Result<()> {
|
||||||
self.sig.write(w)?;
|
self.sigs.write(w)?;
|
||||||
write_raw_vec(write_point, &self.bit_commitments, w)
|
write_raw_vec(write_point, &self.bit_commitments, w)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,12 +96,13 @@ impl BorromeanRange {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(non_snake_case)]
|
||||||
let H_pow_2 = H_pow_2();
|
let H_pow_2 = H_pow_2();
|
||||||
let mut commitments_sub_one = [EdwardsPoint::identity(); 64];
|
let mut commitments_sub_one = [EdwardsPoint::identity(); 64];
|
||||||
for i in 0 .. 64 {
|
for i in 0 .. 64 {
|
||||||
commitments_sub_one[i] = self.bit_commitments[i] - H_pow_2[i];
|
commitments_sub_one[i] = self.bit_commitments[i] - H_pow_2[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
self.sig.verify(&self.bit_commitments, &commitments_sub_one)
|
self.sigs.verify(&self.bit_commitments, &commitments_sub_one)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,23 +1,23 @@
|
|||||||
#![allow(non_snake_case)]
|
use std_shims::{
|
||||||
|
vec::Vec,
|
||||||
use std::io;
|
io::{self, Read, Write},
|
||||||
use std::io::{Read, Write};
|
};
|
||||||
|
|
||||||
use curve25519_dalek::scalar::Scalar;
|
use curve25519_dalek::scalar::Scalar;
|
||||||
|
#[cfg(feature = "experimental")]
|
||||||
use curve25519_dalek::edwards::EdwardsPoint;
|
use curve25519_dalek::edwards::EdwardsPoint;
|
||||||
use curve25519_dalek::traits::Identity;
|
|
||||||
|
|
||||||
use crate::{hash_to_scalar, serialize::*};
|
use crate::serialize::*;
|
||||||
use crate::ringct::hash_to_point;
|
#[cfg(feature = "experimental")]
|
||||||
|
use crate::{hash_to_scalar, ringct::hash_to_point};
|
||||||
|
|
||||||
/// MgSig part of MLSAG, as used in Monero.
|
|
||||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||||
pub struct MgSig {
|
pub struct Mlsag {
|
||||||
pub ss: Vec<[Scalar; 2]>,
|
pub ss: Vec<[Scalar; 2]>,
|
||||||
pub cc: Scalar,
|
pub cc: Scalar,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MgSig {
|
impl Mlsag {
|
||||||
pub fn write<W: Write>(&self, w: &mut W) -> io::Result<()> {
|
pub fn write<W: Write>(&self, w: &mut W) -> io::Result<()> {
|
||||||
for ss in self.ss.iter() {
|
for ss in self.ss.iter() {
|
||||||
write_raw_vec(write_scalar, ss, w)?;
|
write_raw_vec(write_scalar, ss, w)?;
|
||||||
@@ -25,8 +25,8 @@ impl MgSig {
|
|||||||
write_scalar(&self.cc, w)
|
write_scalar(&self.cc, w)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read<R: Read>(mixins: usize, r: &mut R) -> io::Result<MgSig> {
|
pub fn read<R: Read>(mixins: usize, r: &mut R) -> io::Result<Mlsag> {
|
||||||
Ok(MgSig {
|
Ok(Mlsag {
|
||||||
ss: (0 .. mixins).map(|_| read_array(read_scalar, r)).collect::<Result<_, _>>()?,
|
ss: (0 .. mixins).map(|_| read_array(read_scalar, r)).collect::<Result<_, _>>()?,
|
||||||
cc: read_scalar(r)?,
|
cc: read_scalar(r)?,
|
||||||
})
|
})
|
||||||
@@ -38,27 +38,16 @@ impl MgSig {
|
|||||||
pubs: &[[EdwardsPoint; 2]],
|
pubs: &[[EdwardsPoint; 2]],
|
||||||
out_pks: &[EdwardsPoint],
|
out_pks: &[EdwardsPoint],
|
||||||
fee: &EdwardsPoint,
|
fee: &EdwardsPoint,
|
||||||
I: &EdwardsPoint,
|
key_image: &EdwardsPoint,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
if pubs.is_empty() {
|
let sum_out_pk = out_pks.iter().sum::<EdwardsPoint>();
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
let sum_out_pk = {
|
|
||||||
let mut sum = EdwardsPoint::identity();
|
|
||||||
for out_pk in out_pks {
|
|
||||||
sum += out_pk;
|
|
||||||
}
|
|
||||||
sum
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut ring_matrix = Vec::with_capacity(pubs.len());
|
let mut ring_matrix = Vec::with_capacity(pubs.len());
|
||||||
|
|
||||||
for member in pubs.iter() {
|
for member in pubs.iter() {
|
||||||
ring_matrix.push([member[0], member[1] - sum_out_pk - fee])
|
ring_matrix.push([member[0], member[1] - sum_out_pk - fee])
|
||||||
}
|
}
|
||||||
|
|
||||||
self.verify_mlsag(msg, &ring_matrix, I)
|
self.verify(msg, &ring_matrix, key_image)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn verify_rct_simple(
|
pub fn verify_rct_simple(
|
||||||
@@ -66,44 +55,45 @@ impl MgSig {
|
|||||||
msg: &[u8; 32],
|
msg: &[u8; 32],
|
||||||
pubs: &[[EdwardsPoint; 2]],
|
pubs: &[[EdwardsPoint; 2]],
|
||||||
pseudo_out: &EdwardsPoint,
|
pseudo_out: &EdwardsPoint,
|
||||||
I: &EdwardsPoint,
|
key_image: &EdwardsPoint,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
if pubs.is_empty() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut ring_matrix = Vec::with_capacity(pubs.len());
|
let mut ring_matrix = Vec::with_capacity(pubs.len());
|
||||||
|
|
||||||
for member in pubs.iter() {
|
for member in pubs.iter() {
|
||||||
ring_matrix.push([member[0], member[1] - pseudo_out])
|
ring_matrix.push([member[0], member[1] - pseudo_out])
|
||||||
}
|
}
|
||||||
|
|
||||||
self.verify_mlsag(msg, &ring_matrix, I)
|
self.verify(msg, &ring_matrix, key_image)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn verify_mlsag(&self, msg: &[u8; 32], ring: &[[EdwardsPoint; 2]], I: &EdwardsPoint) -> bool {
|
#[cfg(feature = "experimental")]
|
||||||
let mut buf = Vec::with_capacity(32 * 6);
|
pub fn verify(
|
||||||
|
&self,
|
||||||
|
msg: &[u8; 32],
|
||||||
|
ring: &[[EdwardsPoint; 2]],
|
||||||
|
key_image: &EdwardsPoint,
|
||||||
|
) -> bool {
|
||||||
|
if ring.is_empty() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut buf = Vec::with_capacity(6 * 32);
|
||||||
let mut ci = self.cc;
|
let mut ci = self.cc;
|
||||||
|
|
||||||
for (i, ring_member) in ring.iter().enumerate() {
|
for (i, ring_member) in ring.iter().enumerate() {
|
||||||
buf.extend_from_slice(msg);
|
buf.extend_from_slice(msg);
|
||||||
|
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
let L =
|
||||||
|
|r| EdwardsPoint::vartime_double_scalar_mul_basepoint(&ci, &ring_member[r], &self.ss[i][r]);
|
||||||
|
|
||||||
buf.extend_from_slice(ring_member[0].compress().as_bytes());
|
buf.extend_from_slice(ring_member[0].compress().as_bytes());
|
||||||
|
buf.extend_from_slice(L(0).compress().as_bytes());
|
||||||
|
|
||||||
let L1 =
|
#[allow(non_snake_case)]
|
||||||
EdwardsPoint::vartime_double_scalar_mul_basepoint(&ci, &ring_member[0], &self.ss[i][0]);
|
let R = (self.ss[i][0] * hash_to_point(ring_member[0])) + (ci * key_image);
|
||||||
buf.extend_from_slice(L1.compress().as_bytes());
|
|
||||||
|
|
||||||
let temp = hash_to_point(ring_member[0]);
|
|
||||||
|
|
||||||
let R = self.ss[i][0] * temp + ci * I;
|
|
||||||
buf.extend_from_slice(R.compress().as_bytes());
|
buf.extend_from_slice(R.compress().as_bytes());
|
||||||
|
|
||||||
buf.extend_from_slice(ring_member[1].compress().as_bytes());
|
buf.extend_from_slice(ring_member[1].compress().as_bytes());
|
||||||
|
buf.extend_from_slice(L(1).compress().as_bytes());
|
||||||
let L2 =
|
|
||||||
EdwardsPoint::vartime_double_scalar_mul_basepoint(&ci, &ring_member[1], &self.ss[i][1]);
|
|
||||||
buf.extend_from_slice(L2.compress().as_bytes());
|
|
||||||
|
|
||||||
ci = hash_to_scalar(&buf);
|
ci = hash_to_scalar(&buf);
|
||||||
buf.clear();
|
buf.clear();
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ pub mod bulletproofs;
|
|||||||
use crate::{
|
use crate::{
|
||||||
Protocol,
|
Protocol,
|
||||||
serialize::*,
|
serialize::*,
|
||||||
ringct::{clsag::Clsag, mlsag::MgSig, bulletproofs::Bulletproofs, borromean::BorromeanRange},
|
ringct::{clsag::Clsag, mlsag::Mlsag, bulletproofs::Bulletproofs, borromean::BorromeanRange},
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Generate a key image for a given key. Defined as `x * hash_to_point(xG)`.
|
/// Generate a key image for a given key. Defined as `x * hash_to_point(xG)`.
|
||||||
@@ -111,12 +111,12 @@ pub enum RctPrunable {
|
|||||||
Null,
|
Null,
|
||||||
Borromean {
|
Borromean {
|
||||||
range_sigs: Vec<BorromeanRange>,
|
range_sigs: Vec<BorromeanRange>,
|
||||||
mlsags: Vec<MgSig>,
|
mlsags: Vec<Mlsag>,
|
||||||
simple: bool,
|
simple: bool,
|
||||||
},
|
},
|
||||||
BulletProof {
|
BulletProof {
|
||||||
bulletproofs: Vec<Bulletproofs>,
|
bulletproofs: Vec<Bulletproofs>,
|
||||||
mlsags: Vec<MgSig>,
|
mlsags: Vec<Mlsag>,
|
||||||
pseudo_outs: Vec<EdwardsPoint>,
|
pseudo_outs: Vec<EdwardsPoint>,
|
||||||
v2: bool,
|
v2: bool,
|
||||||
},
|
},
|
||||||
@@ -166,7 +166,7 @@ impl RctPrunable {
|
|||||||
RctPrunable::Null => Ok(()),
|
RctPrunable::Null => Ok(()),
|
||||||
RctPrunable::Borromean { range_sigs, mlsags, simple: _ } => {
|
RctPrunable::Borromean { range_sigs, mlsags, simple: _ } => {
|
||||||
write_raw_vec(BorromeanRange::write, range_sigs, w)?;
|
write_raw_vec(BorromeanRange::write, range_sigs, w)?;
|
||||||
write_raw_vec(MgSig::write, mlsags, w)
|
write_raw_vec(Mlsag::write, mlsags, w)
|
||||||
}
|
}
|
||||||
RctPrunable::BulletProof { bulletproofs, mlsags, pseudo_outs, v2 } => {
|
RctPrunable::BulletProof { bulletproofs, mlsags, pseudo_outs, v2 } => {
|
||||||
if !v2 {
|
if !v2 {
|
||||||
@@ -175,7 +175,7 @@ impl RctPrunable {
|
|||||||
write_varint(&bulletproofs.len().try_into().unwrap(), w)?;
|
write_varint(&bulletproofs.len().try_into().unwrap(), w)?;
|
||||||
}
|
}
|
||||||
write_raw_vec(Bulletproofs::write, bulletproofs, w)?;
|
write_raw_vec(Bulletproofs::write, bulletproofs, w)?;
|
||||||
write_raw_vec(MgSig::write, mlsags, w)?;
|
write_raw_vec(Mlsag::write, mlsags, w)?;
|
||||||
write_raw_vec(write_point, pseudo_outs, w)
|
write_raw_vec(write_point, pseudo_outs, w)
|
||||||
}
|
}
|
||||||
RctPrunable::Clsag { bulletproofs, clsags, pseudo_outs } => {
|
RctPrunable::Clsag { bulletproofs, clsags, pseudo_outs } => {
|
||||||
@@ -202,7 +202,7 @@ impl RctPrunable {
|
|||||||
0 => RctPrunable::Null,
|
0 => RctPrunable::Null,
|
||||||
1 | 2 => RctPrunable::Borromean {
|
1 | 2 => RctPrunable::Borromean {
|
||||||
range_sigs: read_raw_vec(BorromeanRange::read, outputs, r)?,
|
range_sigs: read_raw_vec(BorromeanRange::read, outputs, r)?,
|
||||||
mlsags: decoys.iter().map(|d| MgSig::read(*d, r)).collect::<Result<_, _>>()?,
|
mlsags: decoys.iter().map(|d| Mlsag::read(*d, r)).collect::<Result<_, _>>()?,
|
||||||
simple: rct_type == 2,
|
simple: rct_type == 2,
|
||||||
},
|
},
|
||||||
3 | 4 => RctPrunable::BulletProof {
|
3 | 4 => RctPrunable::BulletProof {
|
||||||
@@ -215,7 +215,7 @@ impl RctPrunable {
|
|||||||
},
|
},
|
||||||
r,
|
r,
|
||||||
)?,
|
)?,
|
||||||
mlsags: decoys.iter().map(|d| MgSig::read(*d, r)).collect::<Result<_, _>>()?,
|
mlsags: decoys.iter().map(|d| Mlsag::read(*d, r)).collect::<Result<_, _>>()?,
|
||||||
pseudo_outs: read_raw_vec(read_point, decoys.len(), r)?,
|
pseudo_outs: read_raw_vec(read_point, decoys.len(), r)?,
|
||||||
v2: rct_type == 4,
|
v2: rct_type == 4,
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user