mirror of
https://github.com/serai-dex/serai.git
synced 2025-12-12 14:09:25 +00:00
add borromean + fix mlsag
This commit is contained in:
54
coins/monero/src/ringct/borromean.rs
Normal file
54
coins/monero/src/ringct/borromean.rs
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
#![allow(non_snake_case)]
|
||||||
|
|
||||||
|
use std::fmt::Debug;
|
||||||
|
use std::io::{self, Read, Write};
|
||||||
|
|
||||||
|
use curve25519_dalek::edwards::EdwardsPoint;
|
||||||
|
use curve25519_dalek::scalar::Scalar;
|
||||||
|
|
||||||
|
use crate::serialize::*;
|
||||||
|
|
||||||
|
fn read_64_array<R: Read, T: Debug, F: Fn(&mut R) -> io::Result<T>>(
|
||||||
|
f: F,
|
||||||
|
r: &mut R,
|
||||||
|
) -> io::Result<[T; 64]> {
|
||||||
|
(0 .. 64).map(|_| f(r)).collect::<io::Result<Vec<T>>>().map(|vec| vec.try_into().unwrap())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||||
|
pub struct BorroSig {
|
||||||
|
pub s0: [Scalar; 64],
|
||||||
|
pub s1: [Scalar; 64],
|
||||||
|
pub ee: Scalar,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BorroSig {
|
||||||
|
pub fn read<R: Read>(r: &mut R) -> io::Result<BorroSig> {
|
||||||
|
Ok(BorroSig {
|
||||||
|
s0: read_64_array(read_scalar, r)?,
|
||||||
|
s1: read_64_array(read_scalar, r)?,
|
||||||
|
ee: read_scalar(r)?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
pub fn write<W: Write>(&self, w: &mut W) -> io::Result<()> {
|
||||||
|
write_raw_vec(write_scalar, &self.s0, w)?;
|
||||||
|
write_raw_vec(write_scalar, &self.s1, w)?;
|
||||||
|
write_scalar(&self.ee, w)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||||
|
pub struct RangeSig {
|
||||||
|
pub asig: BorroSig,
|
||||||
|
pub Ci: [EdwardsPoint; 64],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RangeSig {
|
||||||
|
pub fn read<R: Read>(r: &mut R) -> io::Result<RangeSig> {
|
||||||
|
Ok(RangeSig { asig: BorroSig::read(r)?, Ci: read_64_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)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -13,7 +13,7 @@ use crate::{
|
|||||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||||
pub struct Mlsag {
|
pub struct Mlsag {
|
||||||
pub ss: Vec<Vec<Scalar>>,
|
pub ss: Vec<Vec<Scalar>>,
|
||||||
pub cc: EdwardsPoint,
|
pub cc: Scalar,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Mlsag {
|
impl Mlsag {
|
||||||
@@ -21,15 +21,15 @@ impl Mlsag {
|
|||||||
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)?;
|
||||||
}
|
}
|
||||||
write_point(&self.cc, w)
|
write_scalar(&self.cc, w)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read<R: Read>(decoys: usize, elements: usize, r: &mut R) -> io::Result<Mlsag> {
|
pub fn read<R: Read>(mixins: usize, ss2_elements: usize, r: &mut R) -> io::Result<Mlsag> {
|
||||||
Ok(Mlsag {
|
Ok(Mlsag {
|
||||||
ss: (0 .. decoys)
|
ss: (0 .. mixins)
|
||||||
.map(|_| read_raw_vec(read_scalar, elements, r))
|
.map(|_| read_raw_vec(read_scalar, ss2_elements, r))
|
||||||
.collect::<Result<_, _>>()?,
|
.collect::<Result<_, _>>()?,
|
||||||
cc: read_point(r)?,
|
cc: read_scalar(r)?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,15 +10,17 @@ 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.
|
/// MLSAG struct.
|
||||||
pub mod mlsag;
|
pub mod mlsag;
|
||||||
|
/// RangeSig struct.
|
||||||
|
pub mod borromean;
|
||||||
/// 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, mlsag::Mlsag, bulletproofs::Bulletproofs},
|
ringct::{clsag::Clsag, mlsag::Mlsag, bulletproofs::Bulletproofs, borromean::RangeSig},
|
||||||
};
|
};
|
||||||
|
|
||||||
/// 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)`.
|
||||||
@@ -26,10 +28,36 @@ pub fn generate_key_image(secret: &Zeroizing<Scalar>) -> EdwardsPoint {
|
|||||||
hash_to_point(&ED25519_BASEPOINT_TABLE * secret.deref()) * secret.deref()
|
hash_to_point(&ED25519_BASEPOINT_TABLE * secret.deref()) * secret.deref()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||||
|
pub enum EcdhInfo {
|
||||||
|
Standard { mask: Scalar, amount: Scalar },
|
||||||
|
Bulletproof { amount: [u8; 8] },
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EcdhInfo {
|
||||||
|
pub fn read<R: Read>(rct_type: u8, r: &mut R) -> io::Result<(EcdhInfo)> {
|
||||||
|
Ok(match rct_type {
|
||||||
|
0 ..= 3 => EcdhInfo::Standard { mask: read_scalar(r)?, amount: read_scalar(r)? },
|
||||||
|
_ => EcdhInfo::Bulletproof { amount: read_bytes(r)? },
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write<W: Write>(&self, w: &mut W) -> io::Result<()> {
|
||||||
|
match self {
|
||||||
|
EcdhInfo::Standard { mask, amount } => {
|
||||||
|
write_scalar(mask, w)?;
|
||||||
|
write_scalar(amount, w)
|
||||||
|
}
|
||||||
|
EcdhInfo::Bulletproof { amount } => w.write_all(amount),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||||
pub struct RctBase {
|
pub struct RctBase {
|
||||||
pub fee: u64,
|
pub fee: u64,
|
||||||
pub ecdh_info: Vec<[u8; 8]>,
|
pub ecdh_info: Vec<EcdhInfo>,
|
||||||
|
pub pseudo_outs: Vec<EdwardsPoint>,
|
||||||
pub commitments: Vec<EdwardsPoint>,
|
pub commitments: Vec<EdwardsPoint>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -42,10 +70,13 @@ impl RctBase {
|
|||||||
w.write_all(&[rct_type])?;
|
w.write_all(&[rct_type])?;
|
||||||
match rct_type {
|
match rct_type {
|
||||||
0 => Ok(()),
|
0 => Ok(()),
|
||||||
5 | 6 => {
|
_ => {
|
||||||
write_varint(&self.fee, w)?;
|
write_varint(&self.fee, w)?;
|
||||||
|
if rct_type == 2 {
|
||||||
|
write_raw_vec(write_point, &self.pseudo_outs, w)?;
|
||||||
|
}
|
||||||
for ecdh in &self.ecdh_info {
|
for ecdh in &self.ecdh_info {
|
||||||
w.write_all(ecdh)?;
|
ecdh.write(w)?;
|
||||||
}
|
}
|
||||||
write_raw_vec(write_point, &self.commitments, w)
|
write_raw_vec(write_point, &self.commitments, w)
|
||||||
}
|
}
|
||||||
@@ -53,15 +84,18 @@ impl RctBase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read<R: Read>(outputs: usize, r: &mut R) -> io::Result<(RctBase, u8)> {
|
pub fn read<R: Read>(inputs: usize, outputs: usize, r: &mut R) -> io::Result<(RctBase, u8)> {
|
||||||
let rct_type = read_byte(r)?;
|
let rct_type = read_byte(r)?;
|
||||||
Ok((
|
Ok((
|
||||||
if rct_type == 0 {
|
if rct_type == 0 {
|
||||||
RctBase { fee: 0, ecdh_info: vec![], commitments: vec![] }
|
RctBase { fee: 0, ecdh_info: vec![], pseudo_outs: vec![], commitments: vec![] }
|
||||||
} else {
|
} else {
|
||||||
RctBase {
|
RctBase {
|
||||||
fee: read_varint(r)?,
|
fee: read_varint(r)?,
|
||||||
ecdh_info: (0 .. outputs).map(|_| read_bytes(r)).collect::<Result<_, _>>()?,
|
pseudo_outs: if rct_type == 2 { read_raw_vec(read_point, inputs, r)? } else { vec![] },
|
||||||
|
ecdh_info: (0 .. outputs)
|
||||||
|
.map(|_| EcdhInfo::read(rct_type, r))
|
||||||
|
.collect::<Result<_, _>>()?,
|
||||||
commitments: read_raw_vec(read_point, outputs, r)?,
|
commitments: read_raw_vec(read_point, outputs, r)?,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -73,6 +107,11 @@ impl RctBase {
|
|||||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||||
pub enum RctPrunable {
|
pub enum RctPrunable {
|
||||||
Null,
|
Null,
|
||||||
|
Borromean {
|
||||||
|
range_sigs: Vec<RangeSig>,
|
||||||
|
mlsags: Vec<Mlsag>,
|
||||||
|
simple: bool,
|
||||||
|
},
|
||||||
BulletProof {
|
BulletProof {
|
||||||
bulletproofs: Vec<Bulletproofs>,
|
bulletproofs: Vec<Bulletproofs>,
|
||||||
mlsags: Vec<Mlsag>,
|
mlsags: Vec<Mlsag>,
|
||||||
@@ -91,6 +130,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::Borromean { simple, .. } => {
|
||||||
|
if !simple {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
2
|
||||||
|
}
|
||||||
|
}
|
||||||
RctPrunable::BulletProof { v2, .. } => {
|
RctPrunable::BulletProof { v2, .. } => {
|
||||||
if !v2 {
|
if !v2 {
|
||||||
3
|
3
|
||||||
@@ -116,6 +162,10 @@ 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::Borromean { range_sigs, mlsags, simple: _ } => {
|
||||||
|
write_raw_vec(RangeSig::write, range_sigs, 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 {
|
||||||
w.write_all(&u32::try_from(bulletproofs.len()).unwrap().to_le_bytes())?;
|
w.write_all(&u32::try_from(bulletproofs.len()).unwrap().to_le_bytes())?;
|
||||||
@@ -140,9 +190,26 @@ impl RctPrunable {
|
|||||||
serialized
|
serialized
|
||||||
}
|
}
|
||||||
|
|
||||||
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],
|
||||||
|
outputs: usize,
|
||||||
|
r: &mut R,
|
||||||
|
) -> io::Result<RctPrunable> {
|
||||||
Ok(match rct_type {
|
Ok(match rct_type {
|
||||||
0 => RctPrunable::Null,
|
0 => RctPrunable::Null,
|
||||||
|
1 => RctPrunable::Borromean {
|
||||||
|
range_sigs: read_raw_vec(RangeSig::read, outputs, r)?,
|
||||||
|
mlsags: vec![Mlsag::read(decoys[0], 1 + decoys.len(), r)?],
|
||||||
|
simple: false,
|
||||||
|
},
|
||||||
|
2 => RctPrunable::Borromean {
|
||||||
|
range_sigs: read_raw_vec(RangeSig::read, outputs, r)?,
|
||||||
|
mlsags: (0 .. decoys.len())
|
||||||
|
.map(|o| Mlsag::read(decoys[o], 2, r))
|
||||||
|
.collect::<Result<_, _>>()?,
|
||||||
|
simple: true,
|
||||||
|
},
|
||||||
3 | 4 => RctPrunable::BulletProof {
|
3 | 4 => RctPrunable::BulletProof {
|
||||||
bulletproofs: read_raw_vec(
|
bulletproofs: read_raw_vec(
|
||||||
Bulletproofs::read,
|
Bulletproofs::read,
|
||||||
@@ -172,10 +239,10 @@ 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))
|
||||||
}
|
}
|
||||||
|
_ => todo!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -203,7 +270,7 @@ impl RctSignatures {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn read<R: Read>(decoys: Vec<usize>, outputs: usize, r: &mut R) -> io::Result<RctSignatures> {
|
pub fn read<R: Read>(decoys: Vec<usize>, outputs: usize, r: &mut R) -> io::Result<RctSignatures> {
|
||||||
let base = RctBase::read(outputs, r)?;
|
let base = RctBase::read(decoys.len(), outputs, r)?;
|
||||||
Ok(RctSignatures { base: base.0, prunable: RctPrunable::read(base.1, &decoys, r)? })
|
Ok(RctSignatures { base: base.0, prunable: RctPrunable::read(base.1, &decoys, outputs, r)? })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -249,7 +249,7 @@ impl Transaction {
|
|||||||
let prefix = TransactionPrefix::read(r)?;
|
let prefix = TransactionPrefix::read(r)?;
|
||||||
let mut signatures = vec![];
|
let mut signatures = vec![];
|
||||||
let mut rct_signatures = RctSignatures {
|
let mut rct_signatures = RctSignatures {
|
||||||
base: RctBase { fee: 0, ecdh_info: vec![], commitments: vec![] },
|
base: RctBase { fee: 0, ecdh_info: vec![], pseudo_outs: vec![], commitments: vec![] },
|
||||||
prunable: RctPrunable::Null,
|
prunable: RctPrunable::Null,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ pub use send::{
|
|||||||
pub(crate) use send::InternalPayment;
|
pub(crate) use send::InternalPayment;
|
||||||
#[cfg(feature = "multisig")]
|
#[cfg(feature = "multisig")]
|
||||||
pub use send::TransactionMachine;
|
pub use send::TransactionMachine;
|
||||||
|
use crate::ringct::EcdhInfo;
|
||||||
|
|
||||||
fn key_image_sort(x: &EdwardsPoint, y: &EdwardsPoint) -> std::cmp::Ordering {
|
fn key_image_sort(x: &EdwardsPoint, y: &EdwardsPoint) -> std::cmp::Ordering {
|
||||||
x.compress().to_bytes().cmp(&y.compress().to_bytes()).reverse()
|
x.compress().to_bytes().cmp(&y.compress().to_bytes()).reverse()
|
||||||
@@ -92,8 +93,24 @@ pub(crate) fn amount_encryption(amount: u64, key: Scalar) -> [u8; 8] {
|
|||||||
(amount ^ u64::from_le_bytes(hash(&amount_mask)[.. 8].try_into().unwrap())).to_le_bytes()
|
(amount ^ u64::from_le_bytes(hash(&amount_mask)[.. 8].try_into().unwrap())).to_le_bytes()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn amount_decryption(amount: [u8; 8], key: Scalar) -> u64 {
|
fn amount_decryption(amount: &EcdhInfo, key: Scalar) -> u64 {
|
||||||
u64::from_le_bytes(amount_encryption(u64::from_le_bytes(amount), key))
|
match amount {
|
||||||
|
EcdhInfo::Standard { mask, amount } => {
|
||||||
|
let shared_sec1 = hash(key.as_bytes());
|
||||||
|
let shared_sec2 = hash(&shared_sec1);
|
||||||
|
let mask_scalar = mask - Scalar::from_bytes_mod_order(shared_sec1);
|
||||||
|
|
||||||
|
let amount_scalar = amount - Scalar::from_bytes_mod_order(shared_sec2);
|
||||||
|
// get first 64 bits (d2b in rctTypes.cpp)
|
||||||
|
let amount_significant_bytes =
|
||||||
|
amount_scalar.to_bytes()[0 .. 8].try_into().expect("Can't fail");
|
||||||
|
let amount = u64::from_le_bytes(amount_significant_bytes);
|
||||||
|
amount
|
||||||
|
}
|
||||||
|
EcdhInfo::Bulletproof { amount } => {
|
||||||
|
u64::from_le_bytes(amount_encryption(u64::from_le_bytes(*amount), key))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn commitment_mask(shared_key: Scalar) -> Scalar {
|
pub(crate) fn commitment_mask(shared_key: Scalar) -> Scalar {
|
||||||
|
|||||||
@@ -372,7 +372,7 @@ impl Scanner {
|
|||||||
// Regular transaction
|
// Regular transaction
|
||||||
} else {
|
} else {
|
||||||
let amount = match tx.rct_signatures.base.ecdh_info.get(o) {
|
let amount = match tx.rct_signatures.base.ecdh_info.get(o) {
|
||||||
Some(amount) => amount_decryption(*amount, shared_key),
|
Some(amount) => amount_decryption(amount, shared_key),
|
||||||
// This should never happen, yet it may be possible with miner transactions?
|
// This should never happen, yet it may be possible with miner transactions?
|
||||||
// Using get just decreases the possibility of a panic and lets us move on in that case
|
// Using get just decreases the possibility of a panic and lets us move on in that case
|
||||||
None => break,
|
None => break,
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ pub use builder::SignableTransactionBuilder;
|
|||||||
mod multisig;
|
mod multisig;
|
||||||
#[cfg(feature = "multisig")]
|
#[cfg(feature = "multisig")]
|
||||||
pub use multisig::TransactionMachine;
|
pub use multisig::TransactionMachine;
|
||||||
|
use crate::ringct::EcdhInfo;
|
||||||
|
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
#[derive(Clone, PartialEq, Eq, Debug, Zeroize, ZeroizeOnDrop)]
|
#[derive(Clone, PartialEq, Eq, Debug, Zeroize, ZeroizeOnDrop)]
|
||||||
@@ -632,7 +633,7 @@ impl SignableTransaction {
|
|||||||
key: output.dest.compress(),
|
key: output.dest.compress(),
|
||||||
view_tag: Some(output.view_tag).filter(|_| matches!(self.protocol, Protocol::v16)),
|
view_tag: Some(output.view_tag).filter(|_| matches!(self.protocol, Protocol::v16)),
|
||||||
});
|
});
|
||||||
ecdh_info.push(output.amount);
|
ecdh_info.push(EcdhInfo::Bulletproof { amount: output.amount });
|
||||||
}
|
}
|
||||||
|
|
||||||
(
|
(
|
||||||
@@ -649,6 +650,7 @@ impl SignableTransaction {
|
|||||||
base: RctBase {
|
base: RctBase {
|
||||||
fee,
|
fee,
|
||||||
ecdh_info,
|
ecdh_info,
|
||||||
|
pseudo_outs: vec![],
|
||||||
commitments: commitments.iter().map(|commitment| commitment.calculate()).collect(),
|
commitments: commitments.iter().map(|commitment| commitment.calculate()).collect(),
|
||||||
},
|
},
|
||||||
prunable: RctPrunable::Clsag {
|
prunable: RctPrunable::Clsag {
|
||||||
@@ -701,7 +703,7 @@ impl SignableTransaction {
|
|||||||
clsags.append(&mut clsag_pairs.iter().map(|clsag| clsag.0.clone()).collect::<Vec<_>>());
|
clsags.append(&mut clsag_pairs.iter().map(|clsag| clsag.0.clone()).collect::<Vec<_>>());
|
||||||
pseudo_outs.append(&mut clsag_pairs.iter().map(|clsag| clsag.1).collect::<Vec<_>>());
|
pseudo_outs.append(&mut clsag_pairs.iter().map(|clsag| clsag.1).collect::<Vec<_>>());
|
||||||
}
|
}
|
||||||
RctPrunable::BulletProof { .. } => {
|
_ => {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -753,7 +755,8 @@ impl Eventuality {
|
|||||||
view_tag: Some(expected.view_tag).filter(|_| matches!(self.protocol, Protocol::v16)),
|
view_tag: Some(expected.view_tag).filter(|_| matches!(self.protocol, Protocol::v16)),
|
||||||
} != actual) ||
|
} != actual) ||
|
||||||
(Some(&expected.commitment.calculate()) != tx.rct_signatures.base.commitments.get(o)) ||
|
(Some(&expected.commitment.calculate()) != tx.rct_signatures.base.commitments.get(o)) ||
|
||||||
(Some(&expected.amount) != tx.rct_signatures.base.ecdh_info.get(o))
|
(Some(&EcdhInfo::Bulletproof { amount: expected.amount }) !=
|
||||||
|
tx.rct_signatures.base.ecdh_info.get(o))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -429,7 +429,7 @@ impl SignatureMachine<Transaction> for TransactionSignatureMachine {
|
|||||||
pseudo_outs.push(pseudo_out);
|
pseudo_outs.push(pseudo_out);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RctPrunable::BulletProof { .. } => todo!(""),
|
_ => todo!(""),
|
||||||
}
|
}
|
||||||
Ok(tx)
|
Ok(tx)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user