Tidy Mlsag

This commit is contained in:
Luke Parker
2023-07-03 18:36:26 -04:00
parent 23b19fcd91
commit 56ee1eaf9c
3 changed files with 51 additions and 60 deletions

View File

@@ -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)
} }
} }

View File

@@ -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();

View File

@@ -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,
}, },