4 Commits

Author SHA1 Message Date
Luke Parker
3cb7386915 Remove accidentally commited ETH ABI files 2024-07-28 20:42:00 -04:00
Luke Parker
a23e7f6464 Merge branch 'develop' into HEAD 2024-07-28 20:36:51 -04:00
Luke Parker
880565cb81 Rust 1.80
Preserves the fn accessors within the Monero crates so that we can use statics
in some cfgs yet not all (in order to provide support for more low-memory
devices) with the exception of `H` (which truly should be cached).
2024-07-26 19:28:10 -07:00
Luke Parker
6f34c2ff77 Remove unused git allowance for monero-rs 2024-07-19 23:51:05 -04:00
41 changed files with 147 additions and 1770 deletions

View File

@@ -17,7 +17,7 @@ rustdoc-args = ["--cfg", "docsrs"]
workspace = true workspace = true
[dependencies] [dependencies]
spin = { version = "0.9", default-features = false, features = ["use_ticket_mutex", "once"] } spin = { version = "0.9", default-features = false, features = ["use_ticket_mutex", "lazy"] }
hashbrown = { version = "0.14", default-features = false, features = ["ahash", "inline-more"] } hashbrown = { version = "0.14", default-features = false, features = ["ahash", "inline-more"] }
[features] [features]

View File

@@ -26,27 +26,6 @@ mod mutex_shim {
pub use mutex_shim::{ShimMutex as Mutex, MutexGuard}; pub use mutex_shim::{ShimMutex as Mutex, MutexGuard};
#[cfg(feature = "std")] #[cfg(feature = "std")]
pub use std::sync::OnceLock; pub use std::sync::LazyLock;
#[cfg(not(feature = "std"))] #[cfg(not(feature = "std"))]
mod oncelock_shim { pub use spin::Lazy as LazyLock;
use spin::Once;
pub struct OnceLock<T>(Once<T>);
impl<T> OnceLock<T> {
pub const fn new() -> OnceLock<T> {
OnceLock(Once::new())
}
pub fn get(&self) -> Option<&T> {
self.0.poll()
}
pub fn get_mut(&mut self) -> Option<&mut T> {
self.0.get_mut()
}
pub fn get_or_init<F: FnOnce() -> T>(&self, f: F) -> &T {
self.0.call_once(f)
}
}
}
#[cfg(not(feature = "std"))]
pub use oncelock_shim::*;

View File

@@ -101,6 +101,5 @@ allow-git = [
"https://github.com/rust-lang-nursery/lazy-static.rs", "https://github.com/rust-lang-nursery/lazy-static.rs",
"https://github.com/serai-dex/substrate-bip39", "https://github.com/serai-dex/substrate-bip39",
"https://github.com/serai-dex/substrate", "https://github.com/serai-dex/substrate",
"https://github.com/monero-rs/base58-monero",
"https://github.com/orcalabs/dockertest-rs", "https://github.com/orcalabs/dockertest-rs",
] ]

View File

@@ -6,7 +6,7 @@ license = "MIT"
repository = "https://github.com/serai-dex/serai/tree/develop/networks/bitcoin" repository = "https://github.com/serai-dex/serai/tree/develop/networks/bitcoin"
authors = ["Luke Parker <lukeparker5132@gmail.com>", "Vrx <vrx00@proton.me>"] authors = ["Luke Parker <lukeparker5132@gmail.com>", "Vrx <vrx00@proton.me>"]
edition = "2021" edition = "2021"
rust-version = "1.79" rust-version = "1.80"
[package.metadata.docs.rs] [package.metadata.docs.rs]
all-features = true all-features = true

View File

@@ -1,14 +1,11 @@
use std::sync::OnceLock; use std::sync::LazyLock;
use bitcoin_serai::rpc::Rpc; use bitcoin_serai::rpc::Rpc;
use tokio::sync::Mutex; use tokio::sync::Mutex;
static SEQUENTIAL_CELL: OnceLock<Mutex<()>> = OnceLock::new(); #[allow(dead_code)]
#[allow(non_snake_case)] pub(crate) static SEQUENTIAL: LazyLock<Mutex<()>> = LazyLock::new(|| Mutex::new(()));
pub fn SEQUENTIAL() -> &'static Mutex<()> {
SEQUENTIAL_CELL.get_or_init(|| Mutex::new(()))
}
#[allow(dead_code)] #[allow(dead_code)]
pub(crate) async fn rpc() -> Rpc { pub(crate) async fn rpc() -> Rpc {
@@ -34,7 +31,7 @@ macro_rules! async_sequential {
$( $(
#[tokio::test] #[tokio::test]
async fn $name() { async fn $name() {
let guard = runner::SEQUENTIAL().lock().await; let guard = runner::SEQUENTIAL.lock().await;
let local = tokio::task::LocalSet::new(); let local = tokio::task::LocalSet::new();
local.run_until(async move { local.run_until(async move {
if let Err(err) = tokio::task::spawn_local(async move { $body }).await { if let Err(err) = tokio::task::spawn_local(async move { $body }).await {

File diff suppressed because it is too large Load Diff

View File

@@ -1,410 +0,0 @@
pub use schnorr::*;
/// This module was auto-generated with ethers-rs Abigen.
/// More information at: <https://github.com/gakonst/ethers-rs>
#[allow(
clippy::enum_variant_names,
clippy::too_many_arguments,
clippy::upper_case_acronyms,
clippy::type_complexity,
dead_code,
non_camel_case_types,
)]
pub mod schnorr {
#[allow(deprecated)]
fn __abi() -> ::ethers_core::abi::Abi {
::ethers_core::abi::ethabi::Contract {
constructor: ::core::option::Option::None,
functions: ::core::convert::From::from([
(
::std::borrow::ToOwned::to_owned("Q"),
::std::vec![
::ethers_core::abi::ethabi::Function {
name: ::std::borrow::ToOwned::to_owned("Q"),
inputs: ::std::vec![],
outputs: ::std::vec![
::ethers_core::abi::ethabi::Param {
name: ::std::string::String::new(),
kind: ::ethers_core::abi::ethabi::ParamType::Uint(256usize),
internal_type: ::core::option::Option::Some(
::std::borrow::ToOwned::to_owned("uint256"),
),
},
],
constant: ::core::option::Option::None,
state_mutability: ::ethers_core::abi::ethabi::StateMutability::View,
},
],
),
(
::std::borrow::ToOwned::to_owned("verify"),
::std::vec![
::ethers_core::abi::ethabi::Function {
name: ::std::borrow::ToOwned::to_owned("verify"),
inputs: ::std::vec![
::ethers_core::abi::ethabi::Param {
name: ::std::borrow::ToOwned::to_owned("parity"),
kind: ::ethers_core::abi::ethabi::ParamType::Uint(8usize),
internal_type: ::core::option::Option::Some(
::std::borrow::ToOwned::to_owned("uint8"),
),
},
::ethers_core::abi::ethabi::Param {
name: ::std::borrow::ToOwned::to_owned("px"),
kind: ::ethers_core::abi::ethabi::ParamType::FixedBytes(
32usize,
),
internal_type: ::core::option::Option::Some(
::std::borrow::ToOwned::to_owned("bytes32"),
),
},
::ethers_core::abi::ethabi::Param {
name: ::std::borrow::ToOwned::to_owned("message"),
kind: ::ethers_core::abi::ethabi::ParamType::FixedBytes(
32usize,
),
internal_type: ::core::option::Option::Some(
::std::borrow::ToOwned::to_owned("bytes32"),
),
},
::ethers_core::abi::ethabi::Param {
name: ::std::borrow::ToOwned::to_owned("c"),
kind: ::ethers_core::abi::ethabi::ParamType::FixedBytes(
32usize,
),
internal_type: ::core::option::Option::Some(
::std::borrow::ToOwned::to_owned("bytes32"),
),
},
::ethers_core::abi::ethabi::Param {
name: ::std::borrow::ToOwned::to_owned("s"),
kind: ::ethers_core::abi::ethabi::ParamType::FixedBytes(
32usize,
),
internal_type: ::core::option::Option::Some(
::std::borrow::ToOwned::to_owned("bytes32"),
),
},
],
outputs: ::std::vec![
::ethers_core::abi::ethabi::Param {
name: ::std::string::String::new(),
kind: ::ethers_core::abi::ethabi::ParamType::Bool,
internal_type: ::core::option::Option::Some(
::std::borrow::ToOwned::to_owned("bool"),
),
},
],
constant: ::core::option::Option::None,
state_mutability: ::ethers_core::abi::ethabi::StateMutability::View,
},
],
),
]),
events: ::std::collections::BTreeMap::new(),
errors: ::core::convert::From::from([
(
::std::borrow::ToOwned::to_owned("InvalidSOrA"),
::std::vec![
::ethers_core::abi::ethabi::AbiError {
name: ::std::borrow::ToOwned::to_owned("InvalidSOrA"),
inputs: ::std::vec![],
},
],
),
(
::std::borrow::ToOwned::to_owned("InvalidSignature"),
::std::vec![
::ethers_core::abi::ethabi::AbiError {
name: ::std::borrow::ToOwned::to_owned("InvalidSignature"),
inputs: ::std::vec![],
},
],
),
]),
receive: false,
fallback: false,
}
}
///The parsed JSON ABI of the contract.
pub static SCHNORR_ABI: ::ethers_contract::Lazy<::ethers_core::abi::Abi> = ::ethers_contract::Lazy::new(
__abi,
);
pub struct Schnorr<M>(::ethers_contract::Contract<M>);
impl<M> ::core::clone::Clone for Schnorr<M> {
fn clone(&self) -> Self {
Self(::core::clone::Clone::clone(&self.0))
}
}
impl<M> ::core::ops::Deref for Schnorr<M> {
type Target = ::ethers_contract::Contract<M>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<M> ::core::ops::DerefMut for Schnorr<M> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl<M> ::core::fmt::Debug for Schnorr<M> {
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
f.debug_tuple(::core::stringify!(Schnorr)).field(&self.address()).finish()
}
}
impl<M: ::ethers_providers::Middleware> Schnorr<M> {
/// Creates a new contract instance with the specified `ethers` client at
/// `address`. The contract derefs to a `ethers::Contract` object.
pub fn new<T: Into<::ethers_core::types::Address>>(
address: T,
client: ::std::sync::Arc<M>,
) -> Self {
Self(
::ethers_contract::Contract::new(
address.into(),
SCHNORR_ABI.clone(),
client,
),
)
}
///Calls the contract's `Q` (0xe493ef8c) function
pub fn q(
&self,
) -> ::ethers_contract::builders::ContractCall<M, ::ethers_core::types::U256> {
self.0
.method_hash([228, 147, 239, 140], ())
.expect("method not found (this should never happen)")
}
///Calls the contract's `verify` (0x9186da4c) function
pub fn verify(
&self,
parity: u8,
px: [u8; 32],
message: [u8; 32],
c: [u8; 32],
s: [u8; 32],
) -> ::ethers_contract::builders::ContractCall<M, bool> {
self.0
.method_hash([145, 134, 218, 76], (parity, px, message, c, s))
.expect("method not found (this should never happen)")
}
}
impl<M: ::ethers_providers::Middleware> From<::ethers_contract::Contract<M>>
for Schnorr<M> {
fn from(contract: ::ethers_contract::Contract<M>) -> Self {
Self::new(contract.address(), contract.client())
}
}
///Custom Error type `InvalidSOrA` with signature `InvalidSOrA()` and selector `0x4e99a12e`
#[derive(
Clone,
::ethers_contract::EthError,
::ethers_contract::EthDisplay,
Default,
Debug,
PartialEq,
Eq,
Hash
)]
#[etherror(name = "InvalidSOrA", abi = "InvalidSOrA()")]
pub struct InvalidSOrA;
///Custom Error type `InvalidSignature` with signature `InvalidSignature()` and selector `0x8baa579f`
#[derive(
Clone,
::ethers_contract::EthError,
::ethers_contract::EthDisplay,
Default,
Debug,
PartialEq,
Eq,
Hash
)]
#[etherror(name = "InvalidSignature", abi = "InvalidSignature()")]
pub struct InvalidSignature;
///Container type for all of the contract's custom errors
#[derive(Clone, ::ethers_contract::EthAbiType, Debug, PartialEq, Eq, Hash)]
pub enum SchnorrErrors {
InvalidSOrA(InvalidSOrA),
InvalidSignature(InvalidSignature),
/// The standard solidity revert string, with selector
/// Error(string) -- 0x08c379a0
RevertString(::std::string::String),
}
impl ::ethers_core::abi::AbiDecode for SchnorrErrors {
fn decode(
data: impl AsRef<[u8]>,
) -> ::core::result::Result<Self, ::ethers_core::abi::AbiError> {
let data = data.as_ref();
if let Ok(decoded) = <::std::string::String as ::ethers_core::abi::AbiDecode>::decode(
data,
) {
return Ok(Self::RevertString(decoded));
}
if let Ok(decoded) = <InvalidSOrA as ::ethers_core::abi::AbiDecode>::decode(
data,
) {
return Ok(Self::InvalidSOrA(decoded));
}
if let Ok(decoded) = <InvalidSignature as ::ethers_core::abi::AbiDecode>::decode(
data,
) {
return Ok(Self::InvalidSignature(decoded));
}
Err(::ethers_core::abi::Error::InvalidData.into())
}
}
impl ::ethers_core::abi::AbiEncode for SchnorrErrors {
fn encode(self) -> ::std::vec::Vec<u8> {
match self {
Self::InvalidSOrA(element) => {
::ethers_core::abi::AbiEncode::encode(element)
}
Self::InvalidSignature(element) => {
::ethers_core::abi::AbiEncode::encode(element)
}
Self::RevertString(s) => ::ethers_core::abi::AbiEncode::encode(s),
}
}
}
impl ::ethers_contract::ContractRevert for SchnorrErrors {
fn valid_selector(selector: [u8; 4]) -> bool {
match selector {
[0x08, 0xc3, 0x79, 0xa0] => true,
_ if selector
== <InvalidSOrA as ::ethers_contract::EthError>::selector() => true,
_ if selector
== <InvalidSignature as ::ethers_contract::EthError>::selector() => {
true
}
_ => false,
}
}
}
impl ::core::fmt::Display for SchnorrErrors {
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
match self {
Self::InvalidSOrA(element) => ::core::fmt::Display::fmt(element, f),
Self::InvalidSignature(element) => ::core::fmt::Display::fmt(element, f),
Self::RevertString(s) => ::core::fmt::Display::fmt(s, f),
}
}
}
impl ::core::convert::From<::std::string::String> for SchnorrErrors {
fn from(value: String) -> Self {
Self::RevertString(value)
}
}
impl ::core::convert::From<InvalidSOrA> for SchnorrErrors {
fn from(value: InvalidSOrA) -> Self {
Self::InvalidSOrA(value)
}
}
impl ::core::convert::From<InvalidSignature> for SchnorrErrors {
fn from(value: InvalidSignature) -> Self {
Self::InvalidSignature(value)
}
}
///Container type for all input parameters for the `Q` function with signature `Q()` and selector `0xe493ef8c`
#[derive(
Clone,
::ethers_contract::EthCall,
::ethers_contract::EthDisplay,
Default,
Debug,
PartialEq,
Eq,
Hash
)]
#[ethcall(name = "Q", abi = "Q()")]
pub struct QCall;
///Container type for all input parameters for the `verify` function with signature `verify(uint8,bytes32,bytes32,bytes32,bytes32)` and selector `0x9186da4c`
#[derive(
Clone,
::ethers_contract::EthCall,
::ethers_contract::EthDisplay,
Default,
Debug,
PartialEq,
Eq,
Hash
)]
#[ethcall(name = "verify", abi = "verify(uint8,bytes32,bytes32,bytes32,bytes32)")]
pub struct VerifyCall {
pub parity: u8,
pub px: [u8; 32],
pub message: [u8; 32],
pub c: [u8; 32],
pub s: [u8; 32],
}
///Container type for all of the contract's call
#[derive(Clone, ::ethers_contract::EthAbiType, Debug, PartialEq, Eq, Hash)]
pub enum SchnorrCalls {
Q(QCall),
Verify(VerifyCall),
}
impl ::ethers_core::abi::AbiDecode for SchnorrCalls {
fn decode(
data: impl AsRef<[u8]>,
) -> ::core::result::Result<Self, ::ethers_core::abi::AbiError> {
let data = data.as_ref();
if let Ok(decoded) = <QCall as ::ethers_core::abi::AbiDecode>::decode(data) {
return Ok(Self::Q(decoded));
}
if let Ok(decoded) = <VerifyCall as ::ethers_core::abi::AbiDecode>::decode(
data,
) {
return Ok(Self::Verify(decoded));
}
Err(::ethers_core::abi::Error::InvalidData.into())
}
}
impl ::ethers_core::abi::AbiEncode for SchnorrCalls {
fn encode(self) -> Vec<u8> {
match self {
Self::Q(element) => ::ethers_core::abi::AbiEncode::encode(element),
Self::Verify(element) => ::ethers_core::abi::AbiEncode::encode(element),
}
}
}
impl ::core::fmt::Display for SchnorrCalls {
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
match self {
Self::Q(element) => ::core::fmt::Display::fmt(element, f),
Self::Verify(element) => ::core::fmt::Display::fmt(element, f),
}
}
}
impl ::core::convert::From<QCall> for SchnorrCalls {
fn from(value: QCall) -> Self {
Self::Q(value)
}
}
impl ::core::convert::From<VerifyCall> for SchnorrCalls {
fn from(value: VerifyCall) -> Self {
Self::Verify(value)
}
}
///Container type for all return fields from the `Q` function with signature `Q()` and selector `0xe493ef8c`
#[derive(
Clone,
::ethers_contract::EthAbiType,
::ethers_contract::EthAbiCodec,
Default,
Debug,
PartialEq,
Eq,
Hash
)]
pub struct QReturn(pub ::ethers_core::types::U256);
///Container type for all return fields from the `verify` function with signature `verify(uint8,bytes32,bytes32,bytes32,bytes32)` and selector `0x9186da4c`
#[derive(
Clone,
::ethers_contract::EthAbiType,
::ethers_contract::EthAbiCodec,
Default,
Debug,
PartialEq,
Eq,
Hash
)]
pub struct VerifyReturn(pub bool);
}

View File

@@ -6,7 +6,7 @@ license = "MIT"
repository = "https://github.com/serai-dex/serai/tree/develop/networks/monero" repository = "https://github.com/serai-dex/serai/tree/develop/networks/monero"
authors = ["Luke Parker <lukeparker5132@gmail.com>"] authors = ["Luke Parker <lukeparker5132@gmail.com>"]
edition = "2021" edition = "2021"
rust-version = "1.79" rust-version = "1.80"
[package.metadata.docs.rs] [package.metadata.docs.rs]
all-features = true all-features = true

View File

@@ -3,7 +3,7 @@
#![deny(missing_docs)] #![deny(missing_docs)]
#![cfg_attr(not(feature = "std"), no_std)] #![cfg_attr(not(feature = "std"), no_std)]
use std_shims::{sync::OnceLock, vec::Vec}; use std_shims::{sync::LazyLock, vec::Vec};
use sha3::{Digest, Keccak256}; use sha3::{Digest, Keccak256};
@@ -21,33 +21,30 @@ fn keccak256(data: &[u8]) -> [u8; 32] {
Keccak256::digest(data).into() Keccak256::digest(data).into()
} }
static H_CELL: OnceLock<EdwardsPoint> = OnceLock::new();
/// Monero's `H` generator. /// Monero's `H` generator.
/// ///
/// Contrary to convention (`G` for values, `H` for randomness), `H` is used by Monero for amounts /// Contrary to convention (`G` for values, `H` for randomness), `H` is used by Monero for amounts
/// within Pedersen commitments. /// within Pedersen commitments.
#[allow(non_snake_case)] #[allow(non_snake_case)]
pub fn H() -> EdwardsPoint { pub static H: LazyLock<EdwardsPoint> = LazyLock::new(|| {
*H_CELL.get_or_init(|| {
decompress_point(keccak256(&ED25519_BASEPOINT_POINT.compress().to_bytes())) decompress_point(keccak256(&ED25519_BASEPOINT_POINT.compress().to_bytes()))
.unwrap() .unwrap()
.mul_by_cofactor() .mul_by_cofactor()
}) });
}
static H_POW_2_CELL: OnceLock<[EdwardsPoint; 64]> = OnceLock::new(); static H_POW_2_CELL: LazyLock<[EdwardsPoint; 64]> = LazyLock::new(|| {
let mut res = [*H; 64];
for i in 1 .. 64 {
res[i] = res[i - 1] + res[i - 1];
}
res
});
/// Monero's `H` generator, multiplied by 2**i for i in 1 ..= 64. /// Monero's `H` generator, multiplied by 2**i for i in 1 ..= 64.
/// ///
/// This table is useful when working with amounts, which are u64s. /// This table is useful when working with amounts, which are u64s.
#[allow(non_snake_case)] #[allow(non_snake_case)]
pub fn H_pow_2() -> &'static [EdwardsPoint; 64] { pub fn H_pow_2() -> &'static [EdwardsPoint; 64] {
H_POW_2_CELL.get_or_init(|| { &H_POW_2_CELL
let mut res = [H(); 64];
for i in 1 .. 64 {
res[i] = res[i - 1] + res[i - 1];
}
res
})
} }
/// The maximum amount of commitments provable for within a single range proof. /// The maximum amount of commitments provable for within a single range proof.
@@ -74,7 +71,7 @@ pub fn bulletproofs_generators(dst: &'static [u8]) -> Generators {
// The maximum amount of bits used within a single range proof. // The maximum amount of bits used within a single range proof.
const MAX_MN: usize = MAX_COMMITMENTS * COMMITMENT_BITS; const MAX_MN: usize = MAX_COMMITMENTS * COMMITMENT_BITS;
let mut preimage = H().compress().to_bytes().to_vec(); let mut preimage = H.compress().to_bytes().to_vec();
preimage.extend(dst); preimage.extend(dst);
let mut res = Generators { G: Vec::with_capacity(MAX_MN), H: Vec::with_capacity(MAX_MN) }; let mut res = Generators { G: Vec::with_capacity(MAX_MN), H: Vec::with_capacity(MAX_MN) };

View File

@@ -6,6 +6,7 @@ license = "MIT"
repository = "https://github.com/serai-dex/serai/tree/develop/networks/monero/io" repository = "https://github.com/serai-dex/serai/tree/develop/networks/monero/io"
authors = ["Luke Parker <lukeparker5132@gmail.com>"] authors = ["Luke Parker <lukeparker5132@gmail.com>"]
edition = "2021" edition = "2021"
rust-version = "1.80"
[package.metadata.docs.rs] [package.metadata.docs.rs]
all-features = true all-features = true

View File

@@ -6,7 +6,7 @@ license = "MIT"
repository = "https://github.com/serai-dex/serai/tree/develop/networks/monero/primitives" repository = "https://github.com/serai-dex/serai/tree/develop/networks/monero/primitives"
authors = ["Luke Parker <lukeparker5132@gmail.com>"] authors = ["Luke Parker <lukeparker5132@gmail.com>"]
edition = "2021" edition = "2021"
rust-version = "1.79" rust-version = "1.80"
[package.metadata.docs.rs] [package.metadata.docs.rs]
all-features = true all-features = true

View File

@@ -5,7 +5,7 @@
use std_shims::{io, vec::Vec}; use std_shims::{io, vec::Vec};
#[cfg(feature = "std")] #[cfg(feature = "std")]
use std_shims::sync::OnceLock; use std_shims::sync::LazyLock;
use zeroize::{Zeroize, ZeroizeOnDrop}; use zeroize::{Zeroize, ZeroizeOnDrop};
@@ -28,15 +28,15 @@ mod tests;
// On std, we cache some variables in statics. // On std, we cache some variables in statics.
#[cfg(feature = "std")] #[cfg(feature = "std")]
static INV_EIGHT_CELL: OnceLock<Scalar> = OnceLock::new(); static INV_EIGHT_CELL: LazyLock<Scalar> = LazyLock::new(|| Scalar::from(8u8).invert());
/// The inverse of 8 over l. /// The inverse of 8 over l, the prime factor of the order of Ed25519.
#[cfg(feature = "std")] #[cfg(feature = "std")]
#[allow(non_snake_case)] #[allow(non_snake_case)]
pub fn INV_EIGHT() -> Scalar { pub fn INV_EIGHT() -> Scalar {
*INV_EIGHT_CELL.get_or_init(|| Scalar::from(8u8).invert()) *INV_EIGHT_CELL
} }
// In no-std environments, we prefer the reduced memory use and calculate it ad-hoc. // In no-std environments, we prefer the reduced memory use and calculate it ad-hoc.
/// The inverse of 8 over l. /// The inverse of 8 over l, the prime factor of the order of Ed25519.
#[cfg(not(feature = "std"))] #[cfg(not(feature = "std"))]
#[allow(non_snake_case)] #[allow(non_snake_case)]
pub fn INV_EIGHT() -> Scalar { pub fn INV_EIGHT() -> Scalar {
@@ -44,12 +44,13 @@ pub fn INV_EIGHT() -> Scalar {
} }
#[cfg(feature = "std")] #[cfg(feature = "std")]
static G_PRECOMP_CELL: OnceLock<VartimeEdwardsPrecomputation> = OnceLock::new(); static G_PRECOMP_CELL: LazyLock<VartimeEdwardsPrecomputation> =
LazyLock::new(|| VartimeEdwardsPrecomputation::new([ED25519_BASEPOINT_POINT]));
/// A cached (if std) pre-computation of the Ed25519 generator, G. /// A cached (if std) pre-computation of the Ed25519 generator, G.
#[cfg(feature = "std")] #[cfg(feature = "std")]
#[allow(non_snake_case)] #[allow(non_snake_case)]
pub fn G_PRECOMP() -> &'static VartimeEdwardsPrecomputation { pub fn G_PRECOMP() -> &'static VartimeEdwardsPrecomputation {
G_PRECOMP_CELL.get_or_init(|| VartimeEdwardsPrecomputation::new([ED25519_BASEPOINT_POINT])) &G_PRECOMP_CELL
} }
/// A cached (if std) pre-computation of the Ed25519 generator, G. /// A cached (if std) pre-computation of the Ed25519 generator, G.
#[cfg(not(feature = "std"))] #[cfg(not(feature = "std"))]
@@ -105,7 +106,7 @@ impl Commitment {
/// Calculate the Pedersen commitment, as a point, from this transparent structure. /// Calculate the Pedersen commitment, as a point, from this transparent structure.
pub fn calculate(&self) -> EdwardsPoint { pub fn calculate(&self) -> EdwardsPoint {
EdwardsPoint::vartime_double_scalar_mul_basepoint(&Scalar::from(self.amount), &H(), &self.mask) EdwardsPoint::vartime_double_scalar_mul_basepoint(&Scalar::from(self.amount), &H, &self.mask)
} }
/// Write the Commitment. /// Write the Commitment.

View File

@@ -1,6 +1,6 @@
use core::cmp::Ordering; use core::cmp::Ordering;
use std_shims::{ use std_shims::{
sync::OnceLock, sync::LazyLock,
io::{self, *}, io::{self, *},
}; };
@@ -10,18 +10,14 @@ use curve25519_dalek::scalar::Scalar;
use monero_io::*; use monero_io::*;
static PRECOMPUTED_SCALARS_CELL: OnceLock<[Scalar; 8]> = OnceLock::new();
// Precomputed scalars used to recover an incorrectly reduced scalar. // Precomputed scalars used to recover an incorrectly reduced scalar.
#[allow(non_snake_case)] static PRECOMPUTED_SCALARS: LazyLock<[Scalar; 8]> = LazyLock::new(|| {
fn PRECOMPUTED_SCALARS() -> [Scalar; 8] {
*PRECOMPUTED_SCALARS_CELL.get_or_init(|| {
let mut precomputed_scalars = [Scalar::ONE; 8]; let mut precomputed_scalars = [Scalar::ONE; 8];
for (i, scalar) in precomputed_scalars.iter_mut().enumerate().skip(1) { for (i, scalar) in precomputed_scalars.iter_mut().enumerate().skip(1) {
*scalar = Scalar::from(u8::try_from((i * 2) + 1).unwrap()); *scalar = Scalar::from(u8::try_from((i * 2) + 1).unwrap());
} }
precomputed_scalars precomputed_scalars
}) });
}
/// An unreduced scalar. /// An unreduced scalar.
/// ///
@@ -127,14 +123,12 @@ impl UnreducedScalar {
return Scalar::from_bytes_mod_order(self.0); return Scalar::from_bytes_mod_order(self.0);
} }
let precomputed_scalars = PRECOMPUTED_SCALARS();
let mut recovered = Scalar::ZERO; let mut recovered = Scalar::ZERO;
for &numb in self.non_adjacent_form().iter().rev() { for &numb in self.non_adjacent_form().iter().rev() {
recovered += recovered; recovered += recovered;
match numb.cmp(&0) { match numb.cmp(&0) {
Ordering::Greater => recovered += precomputed_scalars[usize::try_from(numb).unwrap() / 2], Ordering::Greater => recovered += PRECOMPUTED_SCALARS[usize::try_from(numb).unwrap() / 2],
Ordering::Less => recovered -= precomputed_scalars[usize::try_from(-numb).unwrap() / 2], Ordering::Less => recovered -= PRECOMPUTED_SCALARS[usize::try_from(-numb).unwrap() / 2],
Ordering::Equal => (), Ordering::Equal => (),
} }
} }

View File

@@ -6,7 +6,7 @@ license = "MIT"
repository = "https://github.com/serai-dex/serai/tree/develop/networks/monero/ringct/borromean" repository = "https://github.com/serai-dex/serai/tree/develop/networks/monero/ringct/borromean"
authors = ["Luke Parker <lukeparker5132@gmail.com>"] authors = ["Luke Parker <lukeparker5132@gmail.com>"]
edition = "2021" edition = "2021"
rust-version = "1.79" rust-version = "1.80"
[package.metadata.docs.rs] [package.metadata.docs.rs]
all-features = true all-features = true

View File

@@ -6,7 +6,7 @@ license = "MIT"
repository = "https://github.com/serai-dex/serai/tree/develop/networks/monero/ringct/bulletproofs" repository = "https://github.com/serai-dex/serai/tree/develop/networks/monero/ringct/bulletproofs"
authors = ["Luke Parker <lukeparker5132@gmail.com>"] authors = ["Luke Parker <lukeparker5132@gmail.com>"]
edition = "2021" edition = "2021"
rust-version = "1.79" rust-version = "1.80"
[package.metadata.docs.rs] [package.metadata.docs.rs]
all-features = true all-features = true

View File

@@ -40,17 +40,14 @@ fn generators(prefix: &'static str, path: &str) {
.write_all( .write_all(
format!( format!(
" "
static GENERATORS_CELL: OnceLock<Generators> = OnceLock::new(); pub(crate) static GENERATORS: LazyLock<Generators> = LazyLock::new(|| Generators {{
pub(crate) fn GENERATORS() -> &'static Generators {{
GENERATORS_CELL.get_or_init(|| Generators {{
G: std_shims::vec![ G: std_shims::vec![
{G_str} {G_str}
], ],
H: std_shims::vec![ H: std_shims::vec![
{H_str} {H_str}
], ],
}}) }});
}}
", ",
) )
.as_bytes(), .as_bytes(),
@@ -67,12 +64,9 @@ fn generators(prefix: &'static str, path: &str) {
.write_all( .write_all(
format!( format!(
r#" r#"
static GENERATORS_CELL: OnceLock<Generators> = OnceLock::new(); pub(crate) static GENERATORS: LazyLock<Generators> = LazyLock::new(|| {{
pub(crate) fn GENERATORS() -> &'static Generators {{
GENERATORS_CELL.get_or_init(|| {{
monero_generators::bulletproofs_generators(b"{prefix}") monero_generators::bulletproofs_generators(b"{prefix}")
}}) }});
}}
"#, "#,
) )
.as_bytes(), .as_bytes(),

View File

@@ -7,7 +7,7 @@ use curve25519_dalek::{
edwards::EdwardsPoint, edwards::EdwardsPoint,
}; };
use monero_generators::{H, Generators}; use monero_generators::{H as MONERO_H, Generators};
use crate::{original, plus}; use crate::{original, plus};
@@ -57,7 +57,7 @@ pub(crate) struct BulletproofsBatchVerifier(pub(crate) InternalBatchVerifier);
impl BulletproofsBatchVerifier { impl BulletproofsBatchVerifier {
#[must_use] #[must_use]
pub(crate) fn verify(self) -> bool { pub(crate) fn verify(self) -> bool {
self.0.verify(ED25519_BASEPOINT_POINT, H(), original::GENERATORS()) self.0.verify(ED25519_BASEPOINT_POINT, *MONERO_H, &original::GENERATORS)
} }
} }
@@ -68,7 +68,7 @@ impl BulletproofsPlusBatchVerifier {
pub(crate) fn verify(self) -> bool { pub(crate) fn verify(self) -> bool {
// Bulletproofs+ is written as per the paper, with G for the value and H for the mask // Bulletproofs+ is written as per the paper, with G for the value and H for the mask
// Monero uses H for the value and G for the mask // Monero uses H for the value and G for the mask
self.0.verify(H(), ED25519_BASEPOINT_POINT, plus::GENERATORS()) self.0.verify(*MONERO_H, ED25519_BASEPOINT_POINT, &plus::GENERATORS)
} }
} }

View File

@@ -96,13 +96,13 @@ impl IpStatement {
mut transcript: Scalar, mut transcript: Scalar,
witness: IpWitness, witness: IpWitness,
) -> Result<IpProof, IpError> { ) -> Result<IpProof, IpError> {
let generators = crate::original::GENERATORS(); let generators = &crate::original::GENERATORS;
let g_bold_slice = &generators.G[.. witness.a.len()]; let g_bold_slice = &generators.G[.. witness.a.len()];
let h_bold_slice = &generators.H[.. witness.a.len()]; let h_bold_slice = &generators.H[.. witness.a.len()];
let (mut g_bold, mut h_bold, u, mut a, mut b) = { let (mut g_bold, mut h_bold, u, mut a, mut b) = {
let IpStatement { h_bold_weights, u } = self; let IpStatement { h_bold_weights, u } = self;
let u = H() * u; let u = *H * u;
// Ensure we have the exact amount of weights // Ensure we have the exact amount of weights
if h_bold_weights.len() != g_bold_slice.len() { if h_bold_weights.len() != g_bold_slice.len() {
@@ -218,7 +218,7 @@ impl IpStatement {
verifier_weight: Scalar, verifier_weight: Scalar,
proof: IpProof, proof: IpProof,
) -> Result<(), IpError> { ) -> Result<(), IpError> {
let generators = crate::original::GENERATORS(); let generators = &crate::original::GENERATORS;
let g_bold_slice = &generators.G[.. ip_rows]; let g_bold_slice = &generators.G[.. ip_rows];
let h_bold_slice = &generators.H[.. ip_rows]; let h_bold_slice = &generators.H[.. ip_rows];

View File

@@ -1,4 +1,4 @@
use std_shims::{sync::OnceLock, vec::Vec}; use std_shims::{sync::LazyLock, vec::Vec};
use rand_core::{RngCore, CryptoRng}; use rand_core::{RngCore, CryptoRng};
@@ -6,7 +6,7 @@ use zeroize::Zeroize;
use curve25519_dalek::{constants::ED25519_BASEPOINT_POINT, Scalar, EdwardsPoint}; use curve25519_dalek::{constants::ED25519_BASEPOINT_POINT, Scalar, EdwardsPoint};
use monero_generators::{H, Generators, MAX_COMMITMENTS, COMMITMENT_BITS}; use monero_generators::{H as MONERO_H, Generators, MAX_COMMITMENTS, COMMITMENT_BITS};
use monero_primitives::{Commitment, INV_EIGHT, keccak256_to_scalar}; use monero_primitives::{Commitment, INV_EIGHT, keccak256_to_scalar};
use crate::{core::multiexp, scalar_vector::ScalarVector, BulletproofsBatchVerifier}; use crate::{core::multiexp, scalar_vector::ScalarVector, BulletproofsBatchVerifier};
@@ -107,7 +107,7 @@ impl<'a> AggregateRangeStatement<'a> {
None? None?
}; };
let generators = GENERATORS(); let generators = &GENERATORS;
let (mut transcript, _) = self.initial_transcript(); let (mut transcript, _) = self.initial_transcript();
@@ -186,7 +186,7 @@ impl<'a> AggregateRangeStatement<'a> {
let tau_1 = Scalar::random(&mut *rng); let tau_1 = Scalar::random(&mut *rng);
let T1 = { let T1 = {
let mut T1_terms = [(t1, H()), (tau_1, ED25519_BASEPOINT_POINT)]; let mut T1_terms = [(t1, *MONERO_H), (tau_1, ED25519_BASEPOINT_POINT)];
for term in &mut T1_terms { for term in &mut T1_terms {
term.0 *= INV_EIGHT(); term.0 *= INV_EIGHT();
} }
@@ -196,7 +196,7 @@ impl<'a> AggregateRangeStatement<'a> {
}; };
let tau_2 = Scalar::random(&mut *rng); let tau_2 = Scalar::random(&mut *rng);
let T2 = { let T2 = {
let mut T2_terms = [(t2, H()), (tau_2, ED25519_BASEPOINT_POINT)]; let mut T2_terms = [(t2, *MONERO_H), (tau_2, ED25519_BASEPOINT_POINT)];
for term in &mut T2_terms { for term in &mut T2_terms {
term.0 *= INV_EIGHT(); term.0 *= INV_EIGHT();
} }

View File

@@ -1,6 +1,6 @@
#![allow(non_snake_case)] #![allow(non_snake_case)]
use std_shims::sync::OnceLock; use std_shims::sync::LazyLock;
use curve25519_dalek::{constants::ED25519_BASEPOINT_POINT, scalar::Scalar, edwards::EdwardsPoint}; use curve25519_dalek::{constants::ED25519_BASEPOINT_POINT, scalar::Scalar, edwards::EdwardsPoint};
@@ -39,7 +39,7 @@ include!(concat!(env!("OUT_DIR"), "/generators_plus.rs"));
impl BpPlusGenerators { impl BpPlusGenerators {
#[allow(clippy::new_without_default)] #[allow(clippy::new_without_default)]
pub(crate) fn new() -> Self { pub(crate) fn new() -> Self {
let gens = GENERATORS(); let gens = &GENERATORS;
BpPlusGenerators { g_bold: &gens.G, h_bold: &gens.H } BpPlusGenerators { g_bold: &gens.G, h_bold: &gens.H }
} }
@@ -48,7 +48,7 @@ impl BpPlusGenerators {
} }
pub(crate) fn g() -> EdwardsPoint { pub(crate) fn g() -> EdwardsPoint {
H() *H
} }
pub(crate) fn h() -> EdwardsPoint { pub(crate) fn h() -> EdwardsPoint {

View File

@@ -1,4 +1,4 @@
use std_shims::{sync::OnceLock, vec::Vec}; use std_shims::{sync::LazyLock, vec::Vec};
use curve25519_dalek::{scalar::Scalar, edwards::EdwardsPoint}; use curve25519_dalek::{scalar::Scalar, edwards::EdwardsPoint};
@@ -6,15 +6,12 @@ use monero_generators::hash_to_point;
use monero_primitives::{keccak256, keccak256_to_scalar}; use monero_primitives::{keccak256, keccak256_to_scalar};
// Monero starts BP+ transcripts with the following constant. // Monero starts BP+ transcripts with the following constant.
static TRANSCRIPT_CELL: OnceLock<[u8; 32]> = OnceLock::new(); // Why this uses a hash_to_point is completely unknown.
pub(crate) fn TRANSCRIPT() -> [u8; 32] { pub(crate) static TRANSCRIPT: LazyLock<[u8; 32]> =
// Why this uses a hash_to_point is completely unknown. LazyLock::new(|| hash_to_point(keccak256(b"bulletproof_plus_transcript")).compress().to_bytes());
*TRANSCRIPT_CELL
.get_or_init(|| hash_to_point(keccak256(b"bulletproof_plus_transcript")).compress().to_bytes())
}
pub(crate) fn initial_transcript(commitments: core::slice::Iter<'_, EdwardsPoint>) -> Scalar { pub(crate) fn initial_transcript(commitments: core::slice::Iter<'_, EdwardsPoint>) -> Scalar {
let commitments_hash = let commitments_hash =
keccak256_to_scalar(commitments.flat_map(|V| V.compress().to_bytes()).collect::<Vec<_>>()); keccak256_to_scalar(commitments.flat_map(|V| V.compress().to_bytes()).collect::<Vec<_>>());
keccak256_to_scalar([TRANSCRIPT().as_ref(), &commitments_hash.to_bytes()].concat()) keccak256_to_scalar([TRANSCRIPT.as_ref(), &commitments_hash.to_bytes()].concat())
} }

View File

@@ -35,12 +35,12 @@ fn test_zero_inner_product() {
#[test] #[test]
fn test_inner_product() { fn test_inner_product() {
// P = sum(g_bold * a, h_bold * b, g * u * <a, b>) // P = sum(g_bold * a, h_bold * b, g * u * <a, b>)
let generators = GENERATORS(); let generators = &GENERATORS;
let mut verifier = BulletproofsBatchVerifier::default(); let mut verifier = BulletproofsBatchVerifier::default();
verifier.0.g_bold = vec![Scalar::ZERO; 32]; verifier.0.g_bold = vec![Scalar::ZERO; 32];
verifier.0.h_bold = vec![Scalar::ZERO; 32]; verifier.0.h_bold = vec![Scalar::ZERO; 32];
for i in [1, 2, 4, 8, 16, 32] { for i in [1, 2, 4, 8, 16, 32] {
let g = H(); let g = *H;
let mut g_bold = vec![]; let mut g_bold = vec![];
let mut h_bold = vec![]; let mut h_bold = vec![];
for i in 0 .. i { for i in 0 .. i {

View File

@@ -6,7 +6,7 @@ license = "MIT"
repository = "https://github.com/serai-dex/serai/tree/develop/networks/monero/ringct/clsag" repository = "https://github.com/serai-dex/serai/tree/develop/networks/monero/ringct/clsag"
authors = ["Luke Parker <lukeparker5132@gmail.com>"] authors = ["Luke Parker <lukeparker5132@gmail.com>"]
edition = "2021" edition = "2021"
rust-version = "1.79" rust-version = "1.80"
[package.metadata.docs.rs] [package.metadata.docs.rs]
all-features = true all-features = true

View File

@@ -6,7 +6,7 @@ license = "MIT"
repository = "https://github.com/serai-dex/serai/tree/develop/networks/monero/ringct/mlsag" repository = "https://github.com/serai-dex/serai/tree/develop/networks/monero/ringct/mlsag"
authors = ["Luke Parker <lukeparker5132@gmail.com>"] authors = ["Luke Parker <lukeparker5132@gmail.com>"]
edition = "2021" edition = "2021"
rust-version = "1.79" rust-version = "1.80"
[package.metadata.docs.rs] [package.metadata.docs.rs]
all-features = true all-features = true

View File

@@ -203,7 +203,7 @@ impl AggregateRingMatrixBuilder {
AggregateRingMatrixBuilder { AggregateRingMatrixBuilder {
key_ring: vec![], key_ring: vec![],
amounts_ring: vec![], amounts_ring: vec![],
sum_out: commitments.iter().sum::<EdwardsPoint>() + (H() * Scalar::from(fee)), sum_out: commitments.iter().sum::<EdwardsPoint>() + (*H * Scalar::from(fee)),
} }
} }

View File

@@ -6,7 +6,7 @@ license = "MIT"
repository = "https://github.com/serai-dex/serai/tree/develop/networks/monero/rpc" repository = "https://github.com/serai-dex/serai/tree/develop/networks/monero/rpc"
authors = ["Luke Parker <lukeparker5132@gmail.com>"] authors = ["Luke Parker <lukeparker5132@gmail.com>"]
edition = "2021" edition = "2021"
rust-version = "1.79" rust-version = "1.80"
[package.metadata.docs.rs] [package.metadata.docs.rs]
all-features = true all-features = true

View File

@@ -6,7 +6,7 @@ license = "MIT"
repository = "https://github.com/serai-dex/serai/tree/develop/networks/monero/rpc/simple-request" repository = "https://github.com/serai-dex/serai/tree/develop/networks/monero/rpc/simple-request"
authors = ["Luke Parker <lukeparker5132@gmail.com>"] authors = ["Luke Parker <lukeparker5132@gmail.com>"]
edition = "2021" edition = "2021"
rust-version = "1.79" rust-version = "1.80"
[package.metadata.docs.rs] [package.metadata.docs.rs]
all-features = true all-features = true

View File

@@ -1,4 +1,4 @@
use std::sync::OnceLock; use std::sync::LazyLock;
use tokio::sync::Mutex; use tokio::sync::Mutex;
use monero_address::{Network, MoneroAddress}; use monero_address::{Network, MoneroAddress};
@@ -8,7 +8,7 @@ use monero_address::{Network, MoneroAddress};
// Accordingly, we test monero-rpc here (implicitly testing the simple-request transport) // Accordingly, we test monero-rpc here (implicitly testing the simple-request transport)
use monero_simple_request_rpc::*; use monero_simple_request_rpc::*;
static SEQUENTIAL: OnceLock<Mutex<()>> = OnceLock::new(); static SEQUENTIAL: LazyLock<Mutex<()>> = LazyLock::new(|| Mutex::new(()));
const ADDRESS: &str = const ADDRESS: &str =
"4B33mFPMq6mKi7Eiyd5XuyKRVMGVZz1Rqb9ZTyGApXW5d1aT7UBDZ89ewmnWFkzJ5wPd2SFbn313vCT8a4E2Qf4KQH4pNey"; "4B33mFPMq6mKi7Eiyd5XuyKRVMGVZz1Rqb9ZTyGApXW5d1aT7UBDZ89ewmnWFkzJ5wPd2SFbn313vCT8a4E2Qf4KQH4pNey";
@@ -17,7 +17,7 @@ const ADDRESS: &str =
async fn test_rpc() { async fn test_rpc() {
use monero_rpc::Rpc; use monero_rpc::Rpc;
let guard = SEQUENTIAL.get_or_init(|| Mutex::new(())).lock().await; let guard = SEQUENTIAL.lock().await;
let rpc = let rpc =
SimpleRequestRpc::new("http://serai:seraidex@127.0.0.1:18081".to_string()).await.unwrap(); SimpleRequestRpc::new("http://serai:seraidex@127.0.0.1:18081".to_string()).await.unwrap();
@@ -68,7 +68,7 @@ async fn test_rpc() {
async fn test_decoy_rpc() { async fn test_decoy_rpc() {
use monero_rpc::{Rpc, DecoyRpc}; use monero_rpc::{Rpc, DecoyRpc};
let guard = SEQUENTIAL.get_or_init(|| Mutex::new(())).lock().await; let guard = SEQUENTIAL.lock().await;
let rpc = let rpc =
SimpleRequestRpc::new("http://serai:seraidex@127.0.0.1:18081".to_string()).await.unwrap(); SimpleRequestRpc::new("http://serai:seraidex@127.0.0.1:18081".to_string()).await.unwrap();
@@ -122,7 +122,7 @@ async fn test_decoy_rpc() {
async fn test_zero_out_tx_o_indexes() { async fn test_zero_out_tx_o_indexes() {
use monero_rpc::Rpc; use monero_rpc::Rpc;
let guard = SEQUENTIAL.get_or_init(|| Mutex::new(())).lock().await; let guard = SEQUENTIAL.lock().await;
let rpc = SimpleRequestRpc::new("https://node.sethforprivacy.com".to_string()).await.unwrap(); let rpc = SimpleRequestRpc::new("https://node.sethforprivacy.com".to_string()).await.unwrap();

View File

@@ -6,7 +6,7 @@ license = "MIT"
repository = "https://github.com/serai-dex/serai/tree/develop/networks/monero/verify-chain" repository = "https://github.com/serai-dex/serai/tree/develop/networks/monero/verify-chain"
authors = ["Luke Parker <lukeparker5132@gmail.com>"] authors = ["Luke Parker <lukeparker5132@gmail.com>"]
edition = "2021" edition = "2021"
rust-version = "1.79" rust-version = "1.80"
publish = false publish = false
[package.metadata.docs.rs] [package.metadata.docs.rs]

View File

@@ -6,7 +6,7 @@ license = "MIT"
repository = "https://github.com/serai-dex/serai/tree/develop/networks/monero/wallet" repository = "https://github.com/serai-dex/serai/tree/develop/networks/monero/wallet"
authors = ["Luke Parker <lukeparker5132@gmail.com>"] authors = ["Luke Parker <lukeparker5132@gmail.com>"]
edition = "2021" edition = "2021"
rust-version = "1.79" rust-version = "1.80"
[package.metadata.docs.rs] [package.metadata.docs.rs]
all-features = true all-features = true

View File

@@ -6,7 +6,7 @@ license = "MIT"
repository = "https://github.com/serai-dex/serai/tree/develop/networks/monero/wallet/address" repository = "https://github.com/serai-dex/serai/tree/develop/networks/monero/wallet/address"
authors = ["Luke Parker <lukeparker5132@gmail.com>"] authors = ["Luke Parker <lukeparker5132@gmail.com>"]
edition = "2021" edition = "2021"
rust-version = "1.79" rust-version = "1.80"
[package.metadata.docs.rs] [package.metadata.docs.rs]
all-features = true all-features = true

View File

@@ -6,7 +6,7 @@ license = "MIT"
repository = "https://github.com/serai-dex/serai/tree/develop/networks/monero/wallet/polyseed" repository = "https://github.com/serai-dex/serai/tree/develop/networks/monero/wallet/polyseed"
authors = ["Luke Parker <lukeparker5132@gmail.com>"] authors = ["Luke Parker <lukeparker5132@gmail.com>"]
edition = "2021" edition = "2021"
rust-version = "1.79" rust-version = "1.80"
[package.metadata.docs.rs] [package.metadata.docs.rs]
all-features = true all-features = true

View File

@@ -4,7 +4,7 @@
#![cfg_attr(not(feature = "std"), no_std)] #![cfg_attr(not(feature = "std"), no_std)]
use core::fmt; use core::fmt;
use std_shims::{sync::OnceLock, string::String, collections::HashMap}; use std_shims::{sync::LazyLock, string::String, collections::HashMap};
#[cfg(feature = "std")] #[cfg(feature = "std")]
use std::time::{SystemTime, UNIX_EPOCH}; use std::time::{SystemTime, UNIX_EPOCH};
@@ -163,10 +163,7 @@ impl WordList {
} }
} }
static LANGUAGES_CELL: OnceLock<HashMap<Language, WordList>> = OnceLock::new(); static LANGUAGES: LazyLock<HashMap<Language, WordList>> = LazyLock::new(|| {
#[allow(non_snake_case)]
fn LANGUAGES() -> &'static HashMap<Language, WordList> {
LANGUAGES_CELL.get_or_init(|| {
HashMap::from([ HashMap::from([
(Language::Czech, WordList::new(include!("./words/cs.rs"), true, false)), (Language::Czech, WordList::new(include!("./words/cs.rs"), true, false)),
(Language::French, WordList::new(include!("./words/fr.rs"), true, true)), (Language::French, WordList::new(include!("./words/fr.rs"), true, true)),
@@ -185,8 +182,7 @@ fn LANGUAGES() -> &'static HashMap<Language, WordList> {
WordList::new(include!("./words/zh_traditional.rs"), false, false), WordList::new(include!("./words/zh_traditional.rs"), false, false),
), ),
]) ])
}) });
}
/// A Polyseed. /// A Polyseed.
#[derive(Clone, PartialEq, Eq, Zeroize, ZeroizeOnDrop)] #[derive(Clone, PartialEq, Eq, Zeroize, ZeroizeOnDrop)]
@@ -317,7 +313,7 @@ impl Polyseed {
let mut poly = [0; POLYSEED_LENGTH]; let mut poly = [0; POLYSEED_LENGTH];
// Validate words are in the lang word list // Validate words are in the lang word list
let lang_word_list: &WordList = &LANGUAGES()[&lang]; let lang_word_list: &WordList = &LANGUAGES[&lang];
for (i, word) in seed.split_whitespace().enumerate() { for (i, word) in seed.split_whitespace().enumerate() {
// Find the word's index // Find the word's index
fn check_if_matches<S: AsRef<str>, I: Iterator<Item = S>>( fn check_if_matches<S: AsRef<str>, I: Iterator<Item = S>>(
@@ -464,7 +460,7 @@ impl Polyseed {
// Output words // Output words
let mut seed = Zeroizing::new(String::new()); let mut seed = Zeroizing::new(String::new());
let words = &LANGUAGES()[&self.language].words; let words = &LANGUAGES[&self.language].words;
for i in 0 .. poly.len() { for i in 0 .. poly.len() {
seed.push_str(words[usize::from(poly[i])]); seed.push_str(words[usize::from(poly[i])]);
if i < poly.len() - 1 { if i < poly.len() - 1 {

View File

@@ -6,7 +6,7 @@ license = "MIT"
repository = "https://github.com/serai-dex/serai/tree/develop/networks/monero/wallet/seed" repository = "https://github.com/serai-dex/serai/tree/develop/networks/monero/wallet/seed"
authors = ["Luke Parker <lukeparker5132@gmail.com>"] authors = ["Luke Parker <lukeparker5132@gmail.com>"]
edition = "2021" edition = "2021"
rust-version = "1.79" rust-version = "1.80"
[package.metadata.docs.rs] [package.metadata.docs.rs]
all-features = true all-features = true

View File

@@ -5,7 +5,7 @@
use core::{ops::Deref, fmt}; use core::{ops::Deref, fmt};
use std_shims::{ use std_shims::{
sync::OnceLock, sync::LazyLock,
vec, vec,
vec::Vec, vec::Vec,
string::{String, ToString}, string::{String, ToString},
@@ -102,10 +102,7 @@ impl WordList {
} }
} }
static LANGUAGES_CELL: OnceLock<HashMap<Language, WordList>> = OnceLock::new(); static LANGUAGES: LazyLock<HashMap<Language, WordList>> = LazyLock::new(|| {
#[allow(non_snake_case)]
fn LANGUAGES() -> &'static HashMap<Language, WordList> {
LANGUAGES_CELL.get_or_init(|| {
HashMap::from([ HashMap::from([
(Language::Chinese, WordList::new(include!("./words/zh.rs"), 1)), (Language::Chinese, WordList::new(include!("./words/zh.rs"), 1)),
(Language::English, WordList::new(include!("./words/en.rs"), 3)), (Language::English, WordList::new(include!("./words/en.rs"), 3)),
@@ -121,8 +118,7 @@ fn LANGUAGES() -> &'static HashMap<Language, WordList> {
(Language::Lojban, WordList::new(include!("./words/jbo.rs"), 4)), (Language::Lojban, WordList::new(include!("./words/jbo.rs"), 4)),
(Language::DeprecatedEnglish, WordList::new(include!("./words/ang.rs"), 4)), (Language::DeprecatedEnglish, WordList::new(include!("./words/ang.rs"), 4)),
]) ])
}) });
}
fn checksum_index(words: &[Zeroizing<String>], lang: &WordList) -> usize { fn checksum_index(words: &[Zeroizing<String>], lang: &WordList) -> usize {
let mut trimmed_words = Zeroizing::new(String::new()); let mut trimmed_words = Zeroizing::new(String::new());
@@ -170,7 +166,7 @@ fn key_to_seed(lang: Language, key: Zeroizing<Scalar>) -> Seed {
let bytes = Zeroizing::new(key.to_bytes()); let bytes = Zeroizing::new(key.to_bytes());
// get the language words // get the language words
let words = &LANGUAGES()[&lang].word_list; let words = &LANGUAGES[&lang].word_list;
let list_len = u64::try_from(words.len()).unwrap(); let list_len = u64::try_from(words.len()).unwrap();
// To store the found words & add the checksum word later. // To store the found words & add the checksum word later.
@@ -204,7 +200,7 @@ fn key_to_seed(lang: Language, key: Zeroizing<Scalar>) -> Seed {
// create a checksum word for all languages except old english // create a checksum word for all languages except old english
if lang != Language::DeprecatedEnglish { if lang != Language::DeprecatedEnglish {
let checksum = seed[checksum_index(&seed, &LANGUAGES()[&lang])].clone(); let checksum = seed[checksum_index(&seed, &LANGUAGES[&lang])].clone();
seed.push(checksum); seed.push(checksum);
} }
@@ -232,7 +228,7 @@ fn seed_to_bytes(lang: Language, words: &str) -> Result<Zeroizing<[u8; 32]>, See
} }
// Validate words are in the language word list // Validate words are in the language word list
let lang_word_list: &WordList = &LANGUAGES()[&lang]; let lang_word_list: &WordList = &LANGUAGES[&lang];
let matched_indices = (|| { let matched_indices = (|| {
let has_checksum = words.len() == SEED_LENGTH_WITH_CHECKSUM; let has_checksum = words.len() == SEED_LENGTH_WITH_CHECKSUM;
let mut matched_indices = Zeroizing::new(vec![]); let mut matched_indices = Zeroizing::new(vec![]);

View File

@@ -183,7 +183,7 @@ fn test_original_seed() {
for vector in vectors { for vector in vectors {
fn trim_by_lang(word: &str, lang: Language) -> String { fn trim_by_lang(word: &str, lang: Language) -> String {
if lang != Language::DeprecatedEnglish { if lang != Language::DeprecatedEnglish {
word.chars().take(LANGUAGES()[&lang].unique_prefix_length).collect() word.chars().take(LANGUAGES[&lang].unique_prefix_length).collect()
} else { } else {
word.to_string() word.to_string()
} }

View File

@@ -1,5 +1,5 @@
use core::ops::Deref; use core::ops::Deref;
use std_shims::sync::OnceLock; use std_shims::sync::LazyLock;
use zeroize::Zeroizing; use zeroize::Zeroizing;
use rand_core::OsRng; use rand_core::OsRng;
@@ -145,7 +145,7 @@ pub async fn rpc() -> SimpleRequestRpc {
rpc rpc
} }
pub static SEQUENTIAL: OnceLock<Mutex<()>> = OnceLock::new(); pub(crate) static SEQUENTIAL: LazyLock<Mutex<()>> = LazyLock::new(|| Mutex::new(()));
#[macro_export] #[macro_export]
macro_rules! async_sequential { macro_rules! async_sequential {
@@ -153,7 +153,7 @@ macro_rules! async_sequential {
$( $(
#[tokio::test] #[tokio::test]
async fn $name() { async fn $name() {
let guard = runner::SEQUENTIAL.get_or_init(|| tokio::sync::Mutex::new(())).lock().await; let guard = runner::SEQUENTIAL.lock().await;
let local = tokio::task::LocalSet::new(); let local = tokio::task::LocalSet::new();
local.run_until(async move { local.run_until(async move {
if let Err(err) = tokio::task::spawn_local(async move { $body }).await { if let Err(err) = tokio::task::spawn_local(async move { $body }).await {

View File

@@ -6,7 +6,7 @@ license = "MIT"
repository = "https://github.com/serai-dex/serai/tree/develop/networks/monero/wallet/util" repository = "https://github.com/serai-dex/serai/tree/develop/networks/monero/wallet/util"
authors = ["Luke Parker <lukeparker5132@gmail.com>"] authors = ["Luke Parker <lukeparker5132@gmail.com>"]
edition = "2021" edition = "2021"
rust-version = "1.79" rust-version = "1.80"
[package.metadata.docs.rs] [package.metadata.docs.rs]
all-features = true all-features = true

View File

@@ -1,5 +1,5 @@
# rust:1.79.0-slim-bookworm as of June 14th, 2024 (GMT) # rust:1.80.0-slim-bookworm as of July 27th, 2024 (GMT)
FROM --platform=linux/amd64 rust@sha256:fa189cd885739dd17fc6bb4e132687fce43f2bf42983c0ac39b60e4943201e9c as deterministic FROM --platform=linux/amd64 rust@sha256:37e6f90f98b3afd15c2526d7abb257a1f4cb7d49808fe3729d9d62020b07b544 as deterministic
# Move to a Debian package snapshot # Move to a Debian package snapshot
RUN rm -rf /etc/apt/sources.list.d/debian.sources && \ RUN rm -rf /etc/apt/sources.list.d/debian.sources && \

View File

@@ -146,7 +146,7 @@ fn build_serai_service(prelude: &str, release: bool, features: &str, package: &s
format!( format!(
r#" r#"
FROM rust:1.79-slim-bookworm as builder FROM rust:1.80-slim-bookworm as builder
COPY --from=mimalloc-debian libmimalloc.so /usr/lib COPY --from=mimalloc-debian libmimalloc.so /usr/lib
RUN echo "/usr/lib/libmimalloc.so" >> /etc/ld.so.preload RUN echo "/usr/lib/libmimalloc.so" >> /etc/ld.so.preload

View File

@@ -1,5 +1,5 @@
[toolchain] [toolchain]
channel = "1.79" channel = "1.80"
targets = ["wasm32-unknown-unknown"] targets = ["wasm32-unknown-unknown"]
profile = "minimal" profile = "minimal"
components = ["rust-src", "rustfmt", "clippy"] components = ["rust-src", "rustfmt", "clippy"]