mirror of
https://github.com/serai-dex/serai.git
synced 2025-12-12 14:09:25 +00:00
add mlsag
This commit is contained in:
35
coins/monero/src/ringct/mlsag/mod.rs
Normal file
35
coins/monero/src/ringct/mlsag/mod.rs
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
use std::io;
|
||||||
|
use std::io::{Read, Write};
|
||||||
|
|
||||||
|
use curve25519_dalek::edwards::EdwardsPoint;
|
||||||
|
use curve25519_dalek::scalar::Scalar;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
Commitment, random_scalar, hash_to_scalar, wallet::decoys::Decoys, ringct::hash_to_point,
|
||||||
|
serialize::*,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// MLSAG signature, as used in Monero.
|
||||||
|
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||||
|
pub struct Mlsag {
|
||||||
|
pub ss: Vec<Vec<Scalar>>,
|
||||||
|
pub cc: EdwardsPoint,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Mlsag {
|
||||||
|
pub fn write<W: Write>(&self, w: &mut W) -> io::Result<()> {
|
||||||
|
for ss in self.ss.iter() {
|
||||||
|
write_raw_vec(write_scalar, ss, w)?;
|
||||||
|
}
|
||||||
|
write_point(&self.cc, w)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read<R: Read>(decoys: usize, elements: usize, r: &mut R) -> io::Result<Mlsag> {
|
||||||
|
Ok(Mlsag {
|
||||||
|
ss: (0 .. decoys)
|
||||||
|
.map(|_| read_raw_vec(read_scalar, elements, r))
|
||||||
|
.collect::<Result<_, _>>()?,
|
||||||
|
cc: read_point(r)?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,13 +10,15 @@ pub use hash_to_point::{raw_hash_to_point, hash_to_point};
|
|||||||
|
|
||||||
/// CLSAG struct, along with signing and verifying functionality.
|
/// CLSAG struct, along with signing and verifying functionality.
|
||||||
pub mod clsag;
|
pub mod clsag;
|
||||||
|
/// MLSAG struct, along with verifying functionality.
|
||||||
|
pub mod mlsag;
|
||||||
/// Bulletproofs(+) structs, along with proving and verifying functionality.
|
/// Bulletproofs(+) structs, along with proving and verifying functionality.
|
||||||
pub mod bulletproofs;
|
pub mod bulletproofs;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
Protocol,
|
Protocol,
|
||||||
serialize::*,
|
serialize::*,
|
||||||
ringct::{clsag::Clsag, bulletproofs::Bulletproofs},
|
ringct::{clsag::Clsag, mlsag::Mlsag, bulletproofs::Bulletproofs},
|
||||||
};
|
};
|
||||||
|
|
||||||
/// 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)`.
|
||||||
@@ -71,7 +73,17 @@ impl RctBase {
|
|||||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||||
pub enum RctPrunable {
|
pub enum RctPrunable {
|
||||||
Null,
|
Null,
|
||||||
Clsag { bulletproofs: Vec<Bulletproofs>, clsags: Vec<Clsag>, pseudo_outs: Vec<EdwardsPoint> },
|
BulletProof {
|
||||||
|
bulletproofs: Vec<Bulletproofs>,
|
||||||
|
mlsags: Vec<Mlsag>,
|
||||||
|
pseudo_outs: Vec<EdwardsPoint>,
|
||||||
|
v2: bool,
|
||||||
|
},
|
||||||
|
Clsag {
|
||||||
|
bulletproofs: Vec<Bulletproofs>,
|
||||||
|
clsags: Vec<Clsag>,
|
||||||
|
pseudo_outs: Vec<EdwardsPoint>,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RctPrunable {
|
impl RctPrunable {
|
||||||
@@ -79,6 +91,13 @@ impl RctPrunable {
|
|||||||
pub fn rct_type(&self) -> u8 {
|
pub fn rct_type(&self) -> u8 {
|
||||||
match self {
|
match self {
|
||||||
RctPrunable::Null => 0,
|
RctPrunable::Null => 0,
|
||||||
|
RctPrunable::BulletProof { v2, .. } => {
|
||||||
|
if !v2 {
|
||||||
|
3
|
||||||
|
} else {
|
||||||
|
4
|
||||||
|
}
|
||||||
|
}
|
||||||
RctPrunable::Clsag { bulletproofs, .. } => {
|
RctPrunable::Clsag { bulletproofs, .. } => {
|
||||||
if matches!(bulletproofs[0], Bulletproofs::Original { .. }) {
|
if matches!(bulletproofs[0], Bulletproofs::Original { .. }) {
|
||||||
5
|
5
|
||||||
@@ -97,7 +116,17 @@ impl RctPrunable {
|
|||||||
pub fn write<W: Write>(&self, w: &mut W) -> io::Result<()> {
|
pub fn write<W: Write>(&self, w: &mut W) -> io::Result<()> {
|
||||||
match self {
|
match self {
|
||||||
RctPrunable::Null => Ok(()),
|
RctPrunable::Null => Ok(()),
|
||||||
RctPrunable::Clsag { bulletproofs, clsags, pseudo_outs, .. } => {
|
RctPrunable::BulletProof { bulletproofs, mlsags, pseudo_outs, v2 } => {
|
||||||
|
if !v2 {
|
||||||
|
w.write_all(&u32::try_from(bulletproofs.len()).unwrap().to_le_bytes())?;
|
||||||
|
} else {
|
||||||
|
write_varint(&bulletproofs.len().try_into().unwrap(), w)?;
|
||||||
|
}
|
||||||
|
write_raw_vec(Bulletproofs::write, bulletproofs, w)?;
|
||||||
|
write_raw_vec(Mlsag::write, mlsags, w)?;
|
||||||
|
write_raw_vec(write_point, pseudo_outs, w)
|
||||||
|
}
|
||||||
|
RctPrunable::Clsag { bulletproofs, clsags, pseudo_outs } => {
|
||||||
write_vec(Bulletproofs::write, bulletproofs, w)?;
|
write_vec(Bulletproofs::write, bulletproofs, w)?;
|
||||||
write_raw_vec(Clsag::write, clsags, w)?;
|
write_raw_vec(Clsag::write, clsags, w)?;
|
||||||
write_raw_vec(write_point, pseudo_outs, w)
|
write_raw_vec(write_point, pseudo_outs, w)
|
||||||
@@ -114,6 +143,20 @@ impl RctPrunable {
|
|||||||
pub fn read<R: Read>(rct_type: u8, decoys: &[usize], r: &mut R) -> io::Result<RctPrunable> {
|
pub fn read<R: Read>(rct_type: u8, decoys: &[usize], r: &mut R) -> io::Result<RctPrunable> {
|
||||||
Ok(match rct_type {
|
Ok(match rct_type {
|
||||||
0 => RctPrunable::Null,
|
0 => RctPrunable::Null,
|
||||||
|
3 | 4 => RctPrunable::BulletProof {
|
||||||
|
bulletproofs: read_raw_vec(
|
||||||
|
Bulletproofs::read,
|
||||||
|
if rct_type == 3 {
|
||||||
|
read_u32(r)?.try_into().unwrap()
|
||||||
|
} else {
|
||||||
|
read_varint(r)?.try_into().unwrap()
|
||||||
|
},
|
||||||
|
r,
|
||||||
|
)?,
|
||||||
|
mlsags: decoys.iter().map(|d| Mlsag::read(*d, 2, r)).collect::<Result<_, _>>()?,
|
||||||
|
pseudo_outs: read_raw_vec(read_point, decoys.len(), r)?,
|
||||||
|
v2: rct_type == 4,
|
||||||
|
},
|
||||||
5 | 6 => RctPrunable::Clsag {
|
5 | 6 => RctPrunable::Clsag {
|
||||||
bulletproofs: read_vec(
|
bulletproofs: read_vec(
|
||||||
if rct_type == 5 { Bulletproofs::read } else { Bulletproofs::read_plus },
|
if rct_type == 5 { Bulletproofs::read } else { Bulletproofs::read_plus },
|
||||||
@@ -129,6 +172,7 @@ impl RctPrunable {
|
|||||||
pub(crate) fn signature_write<W: Write>(&self, w: &mut W) -> io::Result<()> {
|
pub(crate) fn signature_write<W: Write>(&self, w: &mut W) -> io::Result<()> {
|
||||||
match self {
|
match self {
|
||||||
RctPrunable::Null => panic!("Serializing RctPrunable::Null for a signature"),
|
RctPrunable::Null => panic!("Serializing RctPrunable::Null for a signature"),
|
||||||
|
RctPrunable::BulletProof {..} => todo!(),
|
||||||
RctPrunable::Clsag { bulletproofs, .. } => {
|
RctPrunable::Clsag { bulletproofs, .. } => {
|
||||||
bulletproofs.iter().try_for_each(|bp| bp.signature_write(w))
|
bulletproofs.iter().try_for_each(|bp| bp.signature_write(w))
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user