mirror of
https://github.com/serai-dex/serai.git
synced 2025-12-11 13:39:25 +00:00
doc ringct/mod.rs
This commit is contained in:
@@ -15,8 +15,8 @@ const CORRECT_BLOCK_HASH_202612: [u8; 32] =
|
|||||||
const EXISTING_BLOCK_HASH_202612: [u8; 32] =
|
const EXISTING_BLOCK_HASH_202612: [u8; 32] =
|
||||||
hex_literal::hex!("bbd604d2ba11ba27935e006ed39c9bfdd99b76bf4a50654bc1e1e61217962698");
|
hex_literal::hex!("bbd604d2ba11ba27935e006ed39c9bfdd99b76bf4a50654bc1e1e61217962698");
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
|
||||||
/// The header of a [`Block`].
|
/// The header of a [`Block`].
|
||||||
|
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||||
pub struct BlockHeader {
|
pub struct BlockHeader {
|
||||||
/// This represents the hardfork number of the block.
|
/// This represents the hardfork number of the block.
|
||||||
pub major_version: u8,
|
pub major_version: u8,
|
||||||
@@ -60,9 +60,7 @@ impl BlockHeader {
|
|||||||
w.write_all(&self.nonce.to_le_bytes())
|
w.write_all(&self.nonce.to_le_bytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Serialize [`Self`].
|
/// Serialize [`Self`] into a new byte buffer.
|
||||||
///
|
|
||||||
/// This allocates and returns a new buffer containing the serialized bytes.
|
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
/// ```rust
|
/// ```rust
|
||||||
@@ -125,8 +123,8 @@ impl BlockHeader {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
|
||||||
/// Block on the Monero blockchain.
|
/// Block on the Monero blockchain.
|
||||||
|
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||||
pub struct Block {
|
pub struct Block {
|
||||||
/// The header of this block.
|
/// The header of this block.
|
||||||
pub header: BlockHeader,
|
pub header: BlockHeader,
|
||||||
@@ -197,9 +195,7 @@ impl Block {
|
|||||||
hash
|
hash
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Serialize [`Self`].
|
/// Serialize [`Self`] into a new byte buffer.
|
||||||
///
|
|
||||||
/// This allocates and returns a new buffer containing the serialized bytes.
|
|
||||||
pub fn serialize(&self) -> Vec<u8> {
|
pub fn serialize(&self) -> Vec<u8> {
|
||||||
let mut serialized = vec![];
|
let mut serialized = vec![];
|
||||||
self.write(&mut serialized).unwrap();
|
self.write(&mut serialized).unwrap();
|
||||||
|
|||||||
@@ -93,19 +93,34 @@ pub(crate) fn BASEPOINT_PRECOMP() -> &'static VartimeEdwardsPrecomputation {
|
|||||||
#[derive(Clone, Copy, PartialEq, Eq, Debug, Zeroize)]
|
#[derive(Clone, Copy, PartialEq, Eq, Debug, Zeroize)]
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
pub enum Protocol {
|
pub enum Protocol {
|
||||||
|
/// Version 14.
|
||||||
v14,
|
v14,
|
||||||
|
/// Version 16.
|
||||||
v16,
|
v16,
|
||||||
|
/// A custom version with customized properties.
|
||||||
Custom {
|
Custom {
|
||||||
|
/// See [`Self::ring_len`].
|
||||||
ring_len: usize,
|
ring_len: usize,
|
||||||
|
/// See [`Self::bp_plus`].
|
||||||
bp_plus: bool,
|
bp_plus: bool,
|
||||||
|
/// See [`Self::optimal_rct_type`].
|
||||||
optimal_rct_type: RctType,
|
optimal_rct_type: RctType,
|
||||||
|
/// See [`Self::view_tags`].
|
||||||
view_tags: bool,
|
view_tags: bool,
|
||||||
|
/// See [`Self::v16_fee`].
|
||||||
v16_fee: bool,
|
v16_fee: bool,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Protocol {
|
impl Protocol {
|
||||||
/// Amount of ring members under this protocol version.
|
/// Amount of ring members under this protocol version.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
/// ```rust
|
||||||
|
/// # use monero_serai::*;
|
||||||
|
/// assert_eq!(Protocol::v14.ring_len(), 11);
|
||||||
|
/// assert_eq!(Protocol::v16.ring_len(), 16);
|
||||||
|
/// ```
|
||||||
pub fn ring_len(&self) -> usize {
|
pub fn ring_len(&self) -> usize {
|
||||||
match self {
|
match self {
|
||||||
Protocol::v14 => 11,
|
Protocol::v14 => 11,
|
||||||
@@ -117,6 +132,13 @@ impl Protocol {
|
|||||||
/// Whether or not the specified version uses Bulletproofs or Bulletproofs+.
|
/// Whether or not the specified version uses Bulletproofs or Bulletproofs+.
|
||||||
///
|
///
|
||||||
/// This method will likely be reworked when versions not using Bulletproofs at all are added.
|
/// This method will likely be reworked when versions not using Bulletproofs at all are added.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
/// ```rust
|
||||||
|
/// # use monero_serai::*;
|
||||||
|
/// assert_eq!(Protocol::v14.bp_plus(), false);
|
||||||
|
/// assert_eq!(Protocol::v16.bp_plus(), true);
|
||||||
|
/// ```
|
||||||
pub fn bp_plus(&self) -> bool {
|
pub fn bp_plus(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Protocol::v14 => false,
|
Protocol::v14 => false,
|
||||||
@@ -125,6 +147,14 @@ impl Protocol {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The optimal RingCT type for this version.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
/// ```rust
|
||||||
|
/// # use monero_serai::{*, ringct::*};
|
||||||
|
/// assert_eq!(Protocol::v14.optimal_rct_type(), RctType::Clsag);
|
||||||
|
/// assert_eq!(Protocol::v16.optimal_rct_type(), RctType::BulletproofsPlus);
|
||||||
|
/// ```
|
||||||
// TODO: Make this an Option when we support pre-RCT protocols
|
// TODO: Make this an Option when we support pre-RCT protocols
|
||||||
pub fn optimal_rct_type(&self) -> RctType {
|
pub fn optimal_rct_type(&self) -> RctType {
|
||||||
match self {
|
match self {
|
||||||
@@ -135,6 +165,13 @@ impl Protocol {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Whether or not the specified version uses view tags.
|
/// Whether or not the specified version uses view tags.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
/// ```rust
|
||||||
|
/// # use monero_serai::{*, ringct::*};
|
||||||
|
/// assert_eq!(Protocol::v14.view_tags(), false);
|
||||||
|
/// assert_eq!(Protocol::v16.view_tags(), true);
|
||||||
|
/// ```
|
||||||
pub fn view_tags(&self) -> bool {
|
pub fn view_tags(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Protocol::v14 => false,
|
Protocol::v14 => false,
|
||||||
@@ -145,6 +182,13 @@ impl Protocol {
|
|||||||
|
|
||||||
/// Whether or not the specified version uses the fee algorithm from Monero
|
/// Whether or not the specified version uses the fee algorithm from Monero
|
||||||
/// hard fork version 16 (released in v18 binaries).
|
/// hard fork version 16 (released in v18 binaries).
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
/// ```rust
|
||||||
|
/// # use monero_serai::{*, ringct::*};
|
||||||
|
/// assert_eq!(Protocol::v14.v16_fee(), false);
|
||||||
|
/// assert_eq!(Protocol::v16.v16_fee(), true);
|
||||||
|
/// ```
|
||||||
pub fn v16_fee(&self) -> bool {
|
pub fn v16_fee(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Protocol::v14 => false,
|
Protocol::v14 => false,
|
||||||
@@ -206,11 +250,15 @@ impl Protocol {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Transparent structure representing a Pedersen commitment's contents.
|
/// Transparent structure representing a [https://web.getmonero.org/resources/moneropedia/pedersen-commitment.html]()'s contents.
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
#[derive(Clone, PartialEq, Eq, Zeroize, ZeroizeOnDrop)]
|
#[derive(Clone, PartialEq, Eq, Zeroize, ZeroizeOnDrop)]
|
||||||
pub struct Commitment {
|
pub struct Commitment {
|
||||||
|
/// The value used to mask the `amount`.
|
||||||
pub mask: Scalar,
|
pub mask: Scalar,
|
||||||
|
/// The value being masked.
|
||||||
|
///
|
||||||
|
/// In Monero's case, this is the amount of XMR in atomic units.
|
||||||
pub amount: u64,
|
pub amount: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -226,6 +274,7 @@ impl Commitment {
|
|||||||
Commitment { mask: Scalar::ONE, amount: 0 }
|
Commitment { mask: Scalar::ONE, amount: 0 }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Create a new [`Self`].
|
||||||
pub fn new(mask: Scalar, amount: u64) -> Commitment {
|
pub fn new(mask: Scalar, amount: u64) -> Commitment {
|
||||||
Commitment { mask, amount }
|
Commitment { mask, amount }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ use monero_generators::hash_to_point;
|
|||||||
|
|
||||||
use crate::{serialize::*, hash_to_scalar};
|
use crate::{serialize::*, hash_to_scalar};
|
||||||
|
|
||||||
|
/// A signature within a [`RingSignature`].
|
||||||
#[derive(Clone, PartialEq, Eq, Debug, Zeroize)]
|
#[derive(Clone, PartialEq, Eq, Debug, Zeroize)]
|
||||||
pub struct Signature {
|
pub struct Signature {
|
||||||
c: Scalar,
|
c: Scalar,
|
||||||
@@ -18,23 +19,37 @@ pub struct Signature {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Signature {
|
impl Signature {
|
||||||
|
/// Serialize [`Self`] into the writer `w`.
|
||||||
|
///
|
||||||
|
/// # Errors
|
||||||
|
/// This function returns any errors from the writer itself.
|
||||||
pub fn write<W: Write>(&self, w: &mut W) -> io::Result<()> {
|
pub fn write<W: Write>(&self, w: &mut W) -> io::Result<()> {
|
||||||
write_scalar(&self.c, w)?;
|
write_scalar(&self.c, w)?;
|
||||||
write_scalar(&self.r, w)?;
|
write_scalar(&self.r, w)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Create [`Self`] from the reader `r`.
|
||||||
|
///
|
||||||
|
/// # Errors
|
||||||
|
/// This function returns an error if either the reader failed,
|
||||||
|
/// or if the data could not be deserialized into a [`Self`].
|
||||||
pub fn read<R: Read>(r: &mut R) -> io::Result<Signature> {
|
pub fn read<R: Read>(r: &mut R) -> io::Result<Signature> {
|
||||||
Ok(Signature { c: read_scalar(r)?, r: read_scalar(r)? })
|
Ok(Signature { c: read_scalar(r)?, r: read_scalar(r)? })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A [ring signature](https://en.wikipedia.org/wiki/Ring_signature).
|
||||||
#[derive(Clone, PartialEq, Eq, Debug, Zeroize)]
|
#[derive(Clone, PartialEq, Eq, Debug, Zeroize)]
|
||||||
pub struct RingSignature {
|
pub struct RingSignature {
|
||||||
sigs: Vec<Signature>,
|
sigs: Vec<Signature>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RingSignature {
|
impl RingSignature {
|
||||||
|
/// Serialize [`Self`] into the writer `w`.
|
||||||
|
///
|
||||||
|
/// # Errors
|
||||||
|
/// This function returns any errors from the writer itself.
|
||||||
pub fn write<W: Write>(&self, w: &mut W) -> io::Result<()> {
|
pub fn write<W: Write>(&self, w: &mut W) -> io::Result<()> {
|
||||||
for sig in &self.sigs {
|
for sig in &self.sigs {
|
||||||
sig.write(w)?;
|
sig.write(w)?;
|
||||||
@@ -42,6 +57,11 @@ impl RingSignature {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Create [`Self`] from the reader `r`.
|
||||||
|
///
|
||||||
|
/// # Errors
|
||||||
|
/// This function returns an error if either the reader failed,
|
||||||
|
/// or if the data could not be deserialized into a [`Self`].
|
||||||
pub fn read<R: Read>(members: usize, r: &mut R) -> io::Result<RingSignature> {
|
pub fn read<R: Read>(members: usize, r: &mut R) -> io::Result<RingSignature> {
|
||||||
Ok(RingSignature { sigs: read_raw_vec(Signature::read, members, r)? })
|
Ok(RingSignature { sigs: read_raw_vec(Signature::read, members, r)? })
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -81,7 +81,18 @@ pub enum RctType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl RctType {
|
impl RctType {
|
||||||
/// Convert the RctType to its byte representation.
|
/// Convert [`self`] to its byte representation.
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # use monero_serai::ringct::*;
|
||||||
|
/// assert_eq!(RctType::Null.to_bytes(), 0);
|
||||||
|
/// assert_eq!(RctType::MlsagAggregate.to_bytes(), 1);
|
||||||
|
/// assert_eq!(RctType::MlsagIndividual.to_bytes(), 2);
|
||||||
|
/// assert_eq!(RctType::Bulletproofs.to_bytes(), 3);
|
||||||
|
/// assert_eq!(RctType::BulletproofsCompactAmount.to_bytes(), 4);
|
||||||
|
/// assert_eq!(RctType::Clsag.to_bytes(), 5);
|
||||||
|
/// assert_eq!(RctType::BulletproofsPlus.to_bytes(), 6);
|
||||||
|
/// ```
|
||||||
pub fn to_byte(self) -> u8 {
|
pub fn to_byte(self) -> u8 {
|
||||||
match self {
|
match self {
|
||||||
RctType::Null => 0,
|
RctType::Null => 0,
|
||||||
@@ -94,7 +105,25 @@ impl RctType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert the RctType from its byte representation.
|
/// Create [`Self`] from a byte representation.
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # use monero_serai::ringct::*;
|
||||||
|
/// assert_eq!(RctType::from_bytes(0).unwrap(), RctType::Null);
|
||||||
|
/// assert_eq!(RctType::from_bytes(1).unwrap(), RctType::MlsagAggregate);
|
||||||
|
/// assert_eq!(RctType::from_bytes(2).unwrap(), RctType::MlsagIndividual);
|
||||||
|
/// assert_eq!(RctType::from_bytes(3).unwrap(), RctType::Bulletproofs);
|
||||||
|
/// assert_eq!(RctType::from_bytes(4).unwrap(), RctType::BulletproofsCompactAmount);
|
||||||
|
/// assert_eq!(RctType::from_bytes(5).unwrap(), RctType::Clsag);
|
||||||
|
/// assert_eq!(RctType::from_bytes(6).unwrap(), RctType::BulletproofsPlus);
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// # Errors
|
||||||
|
/// This function returns [`None`] if the byte representation is invalid.
|
||||||
|
/// ```rust
|
||||||
|
/// # use monero_serai::ringct::*;
|
||||||
|
/// assert_eq!(RctType::from_bytes(7), None);
|
||||||
|
/// ```
|
||||||
pub fn from_byte(byte: u8) -> Option<Self> {
|
pub fn from_byte(byte: u8) -> Option<Self> {
|
||||||
Some(match byte {
|
Some(match byte {
|
||||||
0 => RctType::Null,
|
0 => RctType::Null,
|
||||||
@@ -109,12 +138,23 @@ impl RctType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if this RctType uses compact encrypted amounts, false otherwise.
|
/// Returns true if this RctType uses compact encrypted amounts, false otherwise.
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # use monero_serai::ringct::*;
|
||||||
|
/// assert_eq!(RctType::Null.compact_encrypted_amounts(), false);
|
||||||
|
/// assert_eq!(RctType::MlsagAggregate.compact_encrypted_amounts(), false);
|
||||||
|
/// assert_eq!(RctType::MlsagIndividual.compact_encrypted_amounts(), false);
|
||||||
|
/// assert_eq!(RctType::Bulletproofs.compact_encrypted_amounts(), false);
|
||||||
|
/// assert_eq!(RctType::BulletproofsCompactAmount.compact_encrypted_amounts(), true);
|
||||||
|
/// assert_eq!(RctType::Clsag.compact_encrypted_amounts(), true);
|
||||||
|
/// assert_eq!(RctType::BulletproofsPlus.compact_encrypted_amounts(), true);
|
||||||
|
/// ```
|
||||||
pub fn compact_encrypted_amounts(&self) -> bool {
|
pub fn compact_encrypted_amounts(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
RctType::Null |
|
RctType::Null
|
||||||
RctType::MlsagAggregate |
|
| RctType::MlsagAggregate
|
||||||
RctType::MlsagIndividual |
|
| RctType::MlsagIndividual
|
||||||
RctType::Bulletproofs => false,
|
| RctType::Bulletproofs => false,
|
||||||
RctType::BulletproofsCompactAmount | RctType::Clsag | RctType::BulletproofsPlus => true,
|
RctType::BulletproofsCompactAmount | RctType::Clsag | RctType::BulletproofsPlus => true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -170,10 +210,10 @@ impl RctBase {
|
|||||||
|
|
||||||
match rct_type {
|
match rct_type {
|
||||||
RctType::Null | RctType::MlsagAggregate | RctType::MlsagIndividual => {}
|
RctType::Null | RctType::MlsagAggregate | RctType::MlsagIndividual => {}
|
||||||
RctType::Bulletproofs |
|
RctType::Bulletproofs
|
||||||
RctType::BulletproofsCompactAmount |
|
| RctType::BulletproofsCompactAmount
|
||||||
RctType::Clsag |
|
| RctType::Clsag
|
||||||
RctType::BulletproofsPlus => {
|
| RctType::BulletproofsPlus => {
|
||||||
if outputs == 0 {
|
if outputs == 0 {
|
||||||
// Because the Bulletproofs(+) layout must be canonical, there must be 1 Bulletproof if
|
// Because the Bulletproofs(+) layout must be canonical, there must be 1 Bulletproof if
|
||||||
// Bulletproofs are in use
|
// Bulletproofs are in use
|
||||||
@@ -198,7 +238,7 @@ impl RctBase {
|
|||||||
} else {
|
} else {
|
||||||
vec![]
|
vec![]
|
||||||
},
|
},
|
||||||
encrypted_amounts: (0 .. outputs)
|
encrypted_amounts: (0..outputs)
|
||||||
.map(|_| EncryptedAmount::read(rct_type.compact_encrypted_amounts(), r))
|
.map(|_| EncryptedAmount::read(rct_type.compact_encrypted_amounts(), r))
|
||||||
.collect::<Result<_, _>>()?,
|
.collect::<Result<_, _>>()?,
|
||||||
commitments: read_raw_vec(read_point, outputs, r)?,
|
commitments: read_raw_vec(read_point, outputs, r)?,
|
||||||
@@ -209,6 +249,7 @@ impl RctBase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The prunable portion of the RingCT data.
|
||||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||||
pub enum RctPrunable {
|
pub enum RctPrunable {
|
||||||
Null,
|
Null,
|
||||||
@@ -235,10 +276,14 @@ pub enum RctPrunable {
|
|||||||
impl RctPrunable {
|
impl RctPrunable {
|
||||||
pub(crate) fn fee_weight(protocol: Protocol, inputs: usize, outputs: usize) -> usize {
|
pub(crate) fn fee_weight(protocol: Protocol, inputs: usize, outputs: usize) -> usize {
|
||||||
// 1 byte for number of BPs (technically a VarInt, yet there's always just zero or one)
|
// 1 byte for number of BPs (technically a VarInt, yet there's always just zero or one)
|
||||||
1 + Bulletproof::fee_weight(protocol.bp_plus(), outputs) +
|
1 + Bulletproof::fee_weight(protocol.bp_plus(), outputs)
|
||||||
(inputs * (Clsag::fee_weight(protocol.ring_len()) + 32))
|
+ (inputs * (Clsag::fee_weight(protocol.ring_len()) + 32))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Serialize [`Self`] into the writer `w`.
|
||||||
|
///
|
||||||
|
/// # Errors
|
||||||
|
/// This function returns any errors from the writer itself.
|
||||||
pub fn write<W: Write>(&self, w: &mut W, rct_type: RctType) -> io::Result<()> {
|
pub fn write<W: Write>(&self, w: &mut W, rct_type: RctType) -> io::Result<()> {
|
||||||
match self {
|
match self {
|
||||||
RctPrunable::Null => Ok(()),
|
RctPrunable::Null => Ok(()),
|
||||||
@@ -271,12 +316,18 @@ impl RctPrunable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Serialize [`Self`] into a new byte buffer.
|
||||||
pub fn serialize(&self, rct_type: RctType) -> Vec<u8> {
|
pub fn serialize(&self, rct_type: RctType) -> Vec<u8> {
|
||||||
let mut serialized = vec![];
|
let mut serialized = vec![];
|
||||||
self.write(&mut serialized, rct_type).unwrap();
|
self.write(&mut serialized, rct_type).unwrap();
|
||||||
serialized
|
serialized
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Create [`Self`] from the reader `r`.
|
||||||
|
///
|
||||||
|
/// # Errors
|
||||||
|
/// This function returns an error if either the reader failed,
|
||||||
|
/// or if the data could not be deserialized into a [`Self`].
|
||||||
pub fn read<R: Read>(
|
pub fn read<R: Read>(
|
||||||
rct_type: RctType,
|
rct_type: RctType,
|
||||||
ring_length: usize,
|
ring_length: usize,
|
||||||
@@ -303,7 +354,7 @@ impl RctPrunable {
|
|||||||
},
|
},
|
||||||
RctType::MlsagIndividual => RctPrunable::MlsagBorromean {
|
RctType::MlsagIndividual => RctPrunable::MlsagBorromean {
|
||||||
borromean: read_raw_vec(BorromeanRange::read, outputs, r)?,
|
borromean: read_raw_vec(BorromeanRange::read, outputs, r)?,
|
||||||
mlsags: (0 .. inputs).map(|_| Mlsag::read(ring_length, 2, r)).collect::<Result<_, _>>()?,
|
mlsags: (0..inputs).map(|_| Mlsag::read(ring_length, 2, r)).collect::<Result<_, _>>()?,
|
||||||
},
|
},
|
||||||
RctType::Bulletproofs | RctType::BulletproofsCompactAmount => {
|
RctType::Bulletproofs | RctType::BulletproofsCompactAmount => {
|
||||||
RctPrunable::MlsagBulletproofs {
|
RctPrunable::MlsagBulletproofs {
|
||||||
@@ -318,9 +369,7 @@ impl RctPrunable {
|
|||||||
}
|
}
|
||||||
Bulletproof::read(r)?
|
Bulletproof::read(r)?
|
||||||
},
|
},
|
||||||
mlsags: (0 .. inputs)
|
mlsags: (0..inputs).map(|_| Mlsag::read(ring_length, 2, r)).collect::<Result<_, _>>()?,
|
||||||
.map(|_| Mlsag::read(ring_length, 2, r))
|
|
||||||
.collect::<Result<_, _>>()?,
|
|
||||||
pseudo_outs: read_raw_vec(read_point, inputs, r)?,
|
pseudo_outs: read_raw_vec(read_point, inputs, r)?,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -331,7 +380,7 @@ impl RctPrunable {
|
|||||||
}
|
}
|
||||||
(if rct_type == RctType::Clsag { Bulletproof::read } else { Bulletproof::read_plus })(r)?
|
(if rct_type == RctType::Clsag { Bulletproof::read } else { Bulletproof::read_plus })(r)?
|
||||||
},
|
},
|
||||||
clsags: (0 .. inputs).map(|_| Clsag::read(ring_length, r)).collect::<Result<_, _>>()?,
|
clsags: (0..inputs).map(|_| Clsag::read(ring_length, r)).collect::<Result<_, _>>()?,
|
||||||
pseudo_outs: read_raw_vec(read_point, inputs, r)?,
|
pseudo_outs: read_raw_vec(read_point, inputs, r)?,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@@ -340,19 +389,22 @@ 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::AggregateMlsagBorromean { borromean, .. } |
|
RctPrunable::AggregateMlsagBorromean { borromean, .. }
|
||||||
RctPrunable::MlsagBorromean { borromean, .. } => {
|
| RctPrunable::MlsagBorromean { borromean, .. } => {
|
||||||
borromean.iter().try_for_each(|rs| rs.write(w))
|
borromean.iter().try_for_each(|rs| rs.write(w))
|
||||||
}
|
}
|
||||||
RctPrunable::MlsagBulletproofs { bulletproofs, .. } |
|
RctPrunable::MlsagBulletproofs { bulletproofs, .. }
|
||||||
RctPrunable::Clsag { bulletproofs, .. } => bulletproofs.signature_write(w),
|
| RctPrunable::Clsag { bulletproofs, .. } => bulletproofs.signature_write(w),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// RingCT signature data.
|
||||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||||
pub struct RctSignatures {
|
pub struct RctSignatures {
|
||||||
|
/// The base of the RingCT data.
|
||||||
pub base: RctBase,
|
pub base: RctBase,
|
||||||
|
/// The prunable portion of the RingCT data.
|
||||||
pub prunable: RctPrunable,
|
pub prunable: RctPrunable,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -393,18 +445,28 @@ impl RctSignatures {
|
|||||||
RctBase::fee_weight(outputs, fee) + RctPrunable::fee_weight(protocol, inputs, outputs)
|
RctBase::fee_weight(outputs, fee) + RctPrunable::fee_weight(protocol, inputs, outputs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Serialize [`Self`] into the writer `w`.
|
||||||
|
///
|
||||||
|
/// # Errors
|
||||||
|
/// This function returns any errors from the writer itself.
|
||||||
pub fn write<W: Write>(&self, w: &mut W) -> io::Result<()> {
|
pub fn write<W: Write>(&self, w: &mut W) -> io::Result<()> {
|
||||||
let rct_type = self.rct_type();
|
let rct_type = self.rct_type();
|
||||||
self.base.write(w, rct_type)?;
|
self.base.write(w, rct_type)?;
|
||||||
self.prunable.write(w, rct_type)
|
self.prunable.write(w, rct_type)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Serialize [`Self`] into a new byte buffer.
|
||||||
pub fn serialize(&self) -> Vec<u8> {
|
pub fn serialize(&self) -> Vec<u8> {
|
||||||
let mut serialized = vec![];
|
let mut serialized = vec![];
|
||||||
self.write(&mut serialized).unwrap();
|
self.write(&mut serialized).unwrap();
|
||||||
serialized
|
serialized
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Create [`Self`] from the reader `r` and other data.
|
||||||
|
///
|
||||||
|
/// # Errors
|
||||||
|
/// This function returns an error if either the reader failed,
|
||||||
|
/// or if the data could not be deserialized into a [`Self`].
|
||||||
pub fn read<R: Read>(
|
pub fn read<R: Read>(
|
||||||
ring_length: usize,
|
ring_length: usize,
|
||||||
inputs: usize,
|
inputs: usize,
|
||||||
|
|||||||
Reference in New Issue
Block a user