mirror of
https://github.com/serai-dex/serai.git
synced 2025-12-12 05:59:23 +00:00
Further documentation, start shoring up API boundaries of existing crates
This commit is contained in:
@@ -18,7 +18,6 @@ workspace = true
|
||||
[dependencies]
|
||||
std-shims = { path = "../../../common/std-shims", version = "^0.1.1", default-features = false }
|
||||
|
||||
rand_core = { version = "0.6", default-features = false }
|
||||
zeroize = { version = "^1.5", default-features = false, features = ["zeroize_derive"] }
|
||||
|
||||
# Cryptographic dependencies
|
||||
@@ -33,7 +32,6 @@ monero-generators = { path = "../generators", version = "0.4", default-features
|
||||
std = [
|
||||
"std-shims/std",
|
||||
|
||||
"rand_core/std",
|
||||
"zeroize/std",
|
||||
|
||||
"sha3/std",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#![doc = include_str!("../README.md")]
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
use std_shims::{vec, vec::Vec};
|
||||
use std_shims::vec::Vec;
|
||||
#[cfg(feature = "std")]
|
||||
use std_shims::sync::OnceLock;
|
||||
|
||||
@@ -16,25 +16,25 @@ use curve25519_dalek::{
|
||||
edwards::{EdwardsPoint, VartimeEdwardsPrecomputation},
|
||||
};
|
||||
|
||||
use monero_io::varint_len;
|
||||
use monero_generators::H;
|
||||
|
||||
// TODO: Replace this with a const
|
||||
// On std, we cache some variables in statics.
|
||||
#[cfg(feature = "std")]
|
||||
static INV_EIGHT_CELL: OnceLock<Scalar> = OnceLock::new();
|
||||
#[cfg(feature = "std")]
|
||||
#[allow(non_snake_case)]
|
||||
/// The inverse of 8 over l.
|
||||
pub fn INV_EIGHT() -> Scalar {
|
||||
*INV_EIGHT_CELL.get_or_init(|| Scalar::from(8u8).invert())
|
||||
}
|
||||
// In no-std environments, we prefer the reduced memory use and calculate it ad-hoc.
|
||||
#[cfg(not(feature = "std"))]
|
||||
#[allow(non_snake_case)]
|
||||
/// The inverse of 8 over l.
|
||||
pub fn INV_EIGHT() -> Scalar {
|
||||
Scalar::from(8u8).invert()
|
||||
}
|
||||
|
||||
// On std, we cache this in a static
|
||||
// In no-std environments, we prefer the reduced memory use and calculate it ad-hoc
|
||||
#[cfg(feature = "std")]
|
||||
static BASEPOINT_PRECOMP_CELL: OnceLock<VartimeEdwardsPrecomputation> = OnceLock::new();
|
||||
#[cfg(feature = "std")]
|
||||
@@ -49,11 +49,14 @@ pub fn BASEPOINT_PRECOMP() -> VartimeEdwardsPrecomputation {
|
||||
VartimeEdwardsPrecomputation::new([ED25519_BASEPOINT_POINT])
|
||||
}
|
||||
|
||||
/// The Keccak-256 hash function.
|
||||
pub fn keccak256(data: impl AsRef<[u8]>) -> [u8; 32] {
|
||||
Keccak256::digest(data.as_ref()).into()
|
||||
}
|
||||
|
||||
/// Hash the provided data to a scalar via keccak256(data) % l.
|
||||
///
|
||||
/// This function panics if it finds the Keccak-256 preimage for [0; 32].
|
||||
pub fn keccak256_to_scalar(data: impl AsRef<[u8]>) -> Scalar {
|
||||
let scalar = Scalar::from_bytes_mod_order(keccak256(data.as_ref()));
|
||||
// Monero will explicitly error in this case
|
||||
@@ -84,39 +87,68 @@ impl Commitment {
|
||||
Commitment { mask: Scalar::ONE, amount: 0 }
|
||||
}
|
||||
|
||||
/// Create a new Commitment.
|
||||
pub fn new(mask: Scalar, amount: u64) -> Commitment {
|
||||
Commitment { mask, amount }
|
||||
}
|
||||
|
||||
/// Calculate a Pedersen commitment, as a point, from the transparent structure.
|
||||
/// Calculate the Pedersen commitment, as a point, from this transparent structure.
|
||||
pub fn calculate(&self) -> EdwardsPoint {
|
||||
EdwardsPoint::vartime_double_scalar_mul_basepoint(&Scalar::from(self.amount), &H(), &self.mask)
|
||||
}
|
||||
}
|
||||
|
||||
/// Decoy data, containing the actual member as well (at index `i`).
|
||||
/// Decoy data, as used for producing Monero's ring signatures.
|
||||
#[derive(Clone, PartialEq, Eq, Debug, Zeroize, ZeroizeOnDrop)]
|
||||
pub struct Decoys {
|
||||
pub i: u8,
|
||||
pub offsets: Vec<u64>,
|
||||
pub ring: Vec<[EdwardsPoint; 2]>,
|
||||
offsets: Vec<u64>,
|
||||
signer_index: u8,
|
||||
ring: Vec<[EdwardsPoint; 2]>,
|
||||
}
|
||||
|
||||
#[allow(clippy::len_without_is_empty)]
|
||||
impl Decoys {
|
||||
pub fn fee_weight(offsets: &[u64]) -> usize {
|
||||
varint_len(offsets.len()) + offsets.iter().map(|offset| varint_len(*offset)).sum::<usize>()
|
||||
/// Create a new instance of decoy data.
|
||||
///
|
||||
/// `offsets` are the positions of each ring member within the Monero blockchain, offset from the
|
||||
/// prior member's position (with the initial ring member offset from 0).
|
||||
pub fn new(offsets: Vec<u64>, signer_index: u8, ring: Vec<[EdwardsPoint; 2]>) -> Option<Self> {
|
||||
if (offsets.len() != ring.len()) || (usize::from(signer_index) >= ring.len()) {
|
||||
None?;
|
||||
}
|
||||
Some(Decoys { offsets, signer_index, ring })
|
||||
}
|
||||
|
||||
/// The length of the ring.
|
||||
pub fn len(&self) -> usize {
|
||||
self.offsets.len()
|
||||
}
|
||||
|
||||
pub fn indexes(&self) -> Vec<u64> {
|
||||
let mut res = vec![self.offsets[0]; self.len()];
|
||||
/// The positions of the ring members within the Monero blockchain, as their offsets.
|
||||
///
|
||||
/// The list is formatted as the position of the first ring member, then the offset from each
|
||||
/// ring member to its prior.
|
||||
pub fn offsets(&self) -> &[u64] {
|
||||
&self.offsets
|
||||
}
|
||||
|
||||
/// The positions of the ring members within the Monero blockchain.
|
||||
pub fn positions(&self) -> Vec<u64> {
|
||||
let mut res = Vec::with_capacity(self.len());
|
||||
res.push(self.offsets[0]);
|
||||
for m in 1 .. res.len() {
|
||||
res[m] = res[m - 1] + self.offsets[m];
|
||||
res.push(res[m - 1] + self.offsets[m]);
|
||||
}
|
||||
res
|
||||
}
|
||||
|
||||
/// The index of the signer within the ring.
|
||||
pub fn signer_index(&self) -> u8 {
|
||||
self.signer_index
|
||||
}
|
||||
|
||||
// The ring.
|
||||
pub fn ring(&self) -> &[[EdwardsPoint; 2]] {
|
||||
&self.ring
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user