mirror of
https://github.com/serai-dex/serai.git
synced 2025-12-12 14:09:25 +00:00
Compare commits
4 Commits
8eb7e66a23
...
3cb7386915
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3cb7386915 | ||
|
|
a23e7f6464 | ||
|
|
880565cb81 | ||
|
|
6f34c2ff77 |
@@ -17,7 +17,7 @@ rustdoc-args = ["--cfg", "docsrs"]
|
||||
workspace = true
|
||||
|
||||
[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"] }
|
||||
|
||||
[features]
|
||||
|
||||
@@ -26,27 +26,6 @@ mod mutex_shim {
|
||||
pub use mutex_shim::{ShimMutex as Mutex, MutexGuard};
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
pub use std::sync::OnceLock;
|
||||
pub use std::sync::LazyLock;
|
||||
#[cfg(not(feature = "std"))]
|
||||
mod oncelock_shim {
|
||||
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::*;
|
||||
pub use spin::Lazy as LazyLock;
|
||||
|
||||
@@ -101,6 +101,5 @@ allow-git = [
|
||||
"https://github.com/rust-lang-nursery/lazy-static.rs",
|
||||
"https://github.com/serai-dex/substrate-bip39",
|
||||
"https://github.com/serai-dex/substrate",
|
||||
"https://github.com/monero-rs/base58-monero",
|
||||
"https://github.com/orcalabs/dockertest-rs",
|
||||
]
|
||||
|
||||
@@ -6,7 +6,7 @@ license = "MIT"
|
||||
repository = "https://github.com/serai-dex/serai/tree/develop/networks/bitcoin"
|
||||
authors = ["Luke Parker <lukeparker5132@gmail.com>", "Vrx <vrx00@proton.me>"]
|
||||
edition = "2021"
|
||||
rust-version = "1.79"
|
||||
rust-version = "1.80"
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
all-features = true
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
use std::sync::OnceLock;
|
||||
use std::sync::LazyLock;
|
||||
|
||||
use bitcoin_serai::rpc::Rpc;
|
||||
|
||||
use tokio::sync::Mutex;
|
||||
|
||||
static SEQUENTIAL_CELL: OnceLock<Mutex<()>> = OnceLock::new();
|
||||
#[allow(non_snake_case)]
|
||||
pub fn SEQUENTIAL() -> &'static Mutex<()> {
|
||||
SEQUENTIAL_CELL.get_or_init(|| Mutex::new(()))
|
||||
}
|
||||
#[allow(dead_code)]
|
||||
pub(crate) static SEQUENTIAL: LazyLock<Mutex<()>> = LazyLock::new(|| Mutex::new(()));
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub(crate) async fn rpc() -> Rpc {
|
||||
@@ -34,7 +31,7 @@ macro_rules! async_sequential {
|
||||
$(
|
||||
#[tokio::test]
|
||||
async fn $name() {
|
||||
let guard = runner::SEQUENTIAL().lock().await;
|
||||
let guard = runner::SEQUENTIAL.lock().await;
|
||||
let local = tokio::task::LocalSet::new();
|
||||
local.run_until(async move {
|
||||
if let Err(err) = tokio::task::spawn_local(async move { $body }).await {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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);
|
||||
}
|
||||
@@ -6,7 +6,7 @@ license = "MIT"
|
||||
repository = "https://github.com/serai-dex/serai/tree/develop/networks/monero"
|
||||
authors = ["Luke Parker <lukeparker5132@gmail.com>"]
|
||||
edition = "2021"
|
||||
rust-version = "1.79"
|
||||
rust-version = "1.80"
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
all-features = true
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#![deny(missing_docs)]
|
||||
#![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};
|
||||
|
||||
@@ -21,33 +21,30 @@ fn keccak256(data: &[u8]) -> [u8; 32] {
|
||||
Keccak256::digest(data).into()
|
||||
}
|
||||
|
||||
static H_CELL: OnceLock<EdwardsPoint> = OnceLock::new();
|
||||
/// Monero's `H` generator.
|
||||
///
|
||||
/// Contrary to convention (`G` for values, `H` for randomness), `H` is used by Monero for amounts
|
||||
/// within Pedersen commitments.
|
||||
#[allow(non_snake_case)]
|
||||
pub fn H() -> EdwardsPoint {
|
||||
*H_CELL.get_or_init(|| {
|
||||
decompress_point(keccak256(&ED25519_BASEPOINT_POINT.compress().to_bytes()))
|
||||
.unwrap()
|
||||
.mul_by_cofactor()
|
||||
})
|
||||
}
|
||||
pub static H: LazyLock<EdwardsPoint> = LazyLock::new(|| {
|
||||
decompress_point(keccak256(&ED25519_BASEPOINT_POINT.compress().to_bytes()))
|
||||
.unwrap()
|
||||
.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.
|
||||
///
|
||||
/// This table is useful when working with amounts, which are u64s.
|
||||
#[allow(non_snake_case)]
|
||||
pub fn H_pow_2() -> &'static [EdwardsPoint; 64] {
|
||||
H_POW_2_CELL.get_or_init(|| {
|
||||
let mut res = [H(); 64];
|
||||
for i in 1 .. 64 {
|
||||
res[i] = res[i - 1] + res[i - 1];
|
||||
}
|
||||
res
|
||||
})
|
||||
&H_POW_2_CELL
|
||||
}
|
||||
|
||||
/// 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.
|
||||
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);
|
||||
|
||||
let mut res = Generators { G: Vec::with_capacity(MAX_MN), H: Vec::with_capacity(MAX_MN) };
|
||||
|
||||
@@ -6,6 +6,7 @@ license = "MIT"
|
||||
repository = "https://github.com/serai-dex/serai/tree/develop/networks/monero/io"
|
||||
authors = ["Luke Parker <lukeparker5132@gmail.com>"]
|
||||
edition = "2021"
|
||||
rust-version = "1.80"
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
all-features = true
|
||||
|
||||
@@ -6,7 +6,7 @@ license = "MIT"
|
||||
repository = "https://github.com/serai-dex/serai/tree/develop/networks/monero/primitives"
|
||||
authors = ["Luke Parker <lukeparker5132@gmail.com>"]
|
||||
edition = "2021"
|
||||
rust-version = "1.79"
|
||||
rust-version = "1.80"
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
all-features = true
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
use std_shims::{io, vec::Vec};
|
||||
#[cfg(feature = "std")]
|
||||
use std_shims::sync::OnceLock;
|
||||
use std_shims::sync::LazyLock;
|
||||
|
||||
use zeroize::{Zeroize, ZeroizeOnDrop};
|
||||
|
||||
@@ -28,15 +28,15 @@ mod tests;
|
||||
|
||||
// On std, we cache some variables in statics.
|
||||
#[cfg(feature = "std")]
|
||||
static INV_EIGHT_CELL: OnceLock<Scalar> = OnceLock::new();
|
||||
/// The inverse of 8 over l.
|
||||
static INV_EIGHT_CELL: LazyLock<Scalar> = LazyLock::new(|| Scalar::from(8u8).invert());
|
||||
/// The inverse of 8 over l, the prime factor of the order of Ed25519.
|
||||
#[cfg(feature = "std")]
|
||||
#[allow(non_snake_case)]
|
||||
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.
|
||||
/// The inverse of 8 over l.
|
||||
/// The inverse of 8 over l, the prime factor of the order of Ed25519.
|
||||
#[cfg(not(feature = "std"))]
|
||||
#[allow(non_snake_case)]
|
||||
pub fn INV_EIGHT() -> Scalar {
|
||||
@@ -44,12 +44,13 @@ pub fn INV_EIGHT() -> Scalar {
|
||||
}
|
||||
|
||||
#[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.
|
||||
#[cfg(feature = "std")]
|
||||
#[allow(non_snake_case)]
|
||||
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.
|
||||
#[cfg(not(feature = "std"))]
|
||||
@@ -105,7 +106,7 @@ impl Commitment {
|
||||
|
||||
/// 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)
|
||||
EdwardsPoint::vartime_double_scalar_mul_basepoint(&Scalar::from(self.amount), &H, &self.mask)
|
||||
}
|
||||
|
||||
/// Write the Commitment.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use core::cmp::Ordering;
|
||||
use std_shims::{
|
||||
sync::OnceLock,
|
||||
sync::LazyLock,
|
||||
io::{self, *},
|
||||
};
|
||||
|
||||
@@ -10,18 +10,14 @@ use curve25519_dalek::scalar::Scalar;
|
||||
|
||||
use monero_io::*;
|
||||
|
||||
static PRECOMPUTED_SCALARS_CELL: OnceLock<[Scalar; 8]> = OnceLock::new();
|
||||
// Precomputed scalars used to recover an incorrectly reduced scalar.
|
||||
#[allow(non_snake_case)]
|
||||
fn PRECOMPUTED_SCALARS() -> [Scalar; 8] {
|
||||
*PRECOMPUTED_SCALARS_CELL.get_or_init(|| {
|
||||
let mut precomputed_scalars = [Scalar::ONE; 8];
|
||||
for (i, scalar) in precomputed_scalars.iter_mut().enumerate().skip(1) {
|
||||
*scalar = Scalar::from(u8::try_from((i * 2) + 1).unwrap());
|
||||
}
|
||||
precomputed_scalars
|
||||
})
|
||||
}
|
||||
static PRECOMPUTED_SCALARS: LazyLock<[Scalar; 8]> = LazyLock::new(|| {
|
||||
let mut precomputed_scalars = [Scalar::ONE; 8];
|
||||
for (i, scalar) in precomputed_scalars.iter_mut().enumerate().skip(1) {
|
||||
*scalar = Scalar::from(u8::try_from((i * 2) + 1).unwrap());
|
||||
}
|
||||
precomputed_scalars
|
||||
});
|
||||
|
||||
/// An unreduced scalar.
|
||||
///
|
||||
@@ -127,14 +123,12 @@ impl UnreducedScalar {
|
||||
return Scalar::from_bytes_mod_order(self.0);
|
||||
}
|
||||
|
||||
let precomputed_scalars = PRECOMPUTED_SCALARS();
|
||||
|
||||
let mut recovered = Scalar::ZERO;
|
||||
for &numb in self.non_adjacent_form().iter().rev() {
|
||||
recovered += recovered;
|
||||
match numb.cmp(&0) {
|
||||
Ordering::Greater => recovered += precomputed_scalars[usize::try_from(numb).unwrap() / 2],
|
||||
Ordering::Less => 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::Equal => (),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ license = "MIT"
|
||||
repository = "https://github.com/serai-dex/serai/tree/develop/networks/monero/ringct/borromean"
|
||||
authors = ["Luke Parker <lukeparker5132@gmail.com>"]
|
||||
edition = "2021"
|
||||
rust-version = "1.79"
|
||||
rust-version = "1.80"
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
all-features = true
|
||||
|
||||
@@ -6,7 +6,7 @@ license = "MIT"
|
||||
repository = "https://github.com/serai-dex/serai/tree/develop/networks/monero/ringct/bulletproofs"
|
||||
authors = ["Luke Parker <lukeparker5132@gmail.com>"]
|
||||
edition = "2021"
|
||||
rust-version = "1.79"
|
||||
rust-version = "1.80"
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
all-features = true
|
||||
|
||||
@@ -40,17 +40,14 @@ fn generators(prefix: &'static str, path: &str) {
|
||||
.write_all(
|
||||
format!(
|
||||
"
|
||||
static GENERATORS_CELL: OnceLock<Generators> = OnceLock::new();
|
||||
pub(crate) fn GENERATORS() -> &'static Generators {{
|
||||
GENERATORS_CELL.get_or_init(|| Generators {{
|
||||
G: std_shims::vec![
|
||||
{G_str}
|
||||
],
|
||||
H: std_shims::vec![
|
||||
{H_str}
|
||||
],
|
||||
}})
|
||||
}}
|
||||
pub(crate) static GENERATORS: LazyLock<Generators> = LazyLock::new(|| Generators {{
|
||||
G: std_shims::vec![
|
||||
{G_str}
|
||||
],
|
||||
H: std_shims::vec![
|
||||
{H_str}
|
||||
],
|
||||
}});
|
||||
",
|
||||
)
|
||||
.as_bytes(),
|
||||
@@ -67,12 +64,9 @@ fn generators(prefix: &'static str, path: &str) {
|
||||
.write_all(
|
||||
format!(
|
||||
r#"
|
||||
static GENERATORS_CELL: OnceLock<Generators> = OnceLock::new();
|
||||
pub(crate) fn GENERATORS() -> &'static Generators {{
|
||||
GENERATORS_CELL.get_or_init(|| {{
|
||||
monero_generators::bulletproofs_generators(b"{prefix}")
|
||||
}})
|
||||
}}
|
||||
pub(crate) static GENERATORS: LazyLock<Generators> = LazyLock::new(|| {{
|
||||
monero_generators::bulletproofs_generators(b"{prefix}")
|
||||
}});
|
||||
"#,
|
||||
)
|
||||
.as_bytes(),
|
||||
|
||||
@@ -7,7 +7,7 @@ use curve25519_dalek::{
|
||||
edwards::EdwardsPoint,
|
||||
};
|
||||
|
||||
use monero_generators::{H, Generators};
|
||||
use monero_generators::{H as MONERO_H, Generators};
|
||||
|
||||
use crate::{original, plus};
|
||||
|
||||
@@ -57,7 +57,7 @@ pub(crate) struct BulletproofsBatchVerifier(pub(crate) InternalBatchVerifier);
|
||||
impl BulletproofsBatchVerifier {
|
||||
#[must_use]
|
||||
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 {
|
||||
// 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
|
||||
self.0.verify(H(), ED25519_BASEPOINT_POINT, plus::GENERATORS())
|
||||
self.0.verify(*MONERO_H, ED25519_BASEPOINT_POINT, &plus::GENERATORS)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -96,13 +96,13 @@ impl IpStatement {
|
||||
mut transcript: Scalar,
|
||||
witness: IpWitness,
|
||||
) -> Result<IpProof, IpError> {
|
||||
let generators = crate::original::GENERATORS();
|
||||
let generators = &crate::original::GENERATORS;
|
||||
let g_bold_slice = &generators.G[.. 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 IpStatement { h_bold_weights, u } = self;
|
||||
let u = H() * u;
|
||||
let u = *H * u;
|
||||
|
||||
// Ensure we have the exact amount of weights
|
||||
if h_bold_weights.len() != g_bold_slice.len() {
|
||||
@@ -218,7 +218,7 @@ impl IpStatement {
|
||||
verifier_weight: Scalar,
|
||||
proof: IpProof,
|
||||
) -> Result<(), IpError> {
|
||||
let generators = crate::original::GENERATORS();
|
||||
let generators = &crate::original::GENERATORS;
|
||||
let g_bold_slice = &generators.G[.. ip_rows];
|
||||
let h_bold_slice = &generators.H[.. ip_rows];
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use std_shims::{sync::OnceLock, vec::Vec};
|
||||
use std_shims::{sync::LazyLock, vec::Vec};
|
||||
|
||||
use rand_core::{RngCore, CryptoRng};
|
||||
|
||||
@@ -6,7 +6,7 @@ use zeroize::Zeroize;
|
||||
|
||||
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 crate::{core::multiexp, scalar_vector::ScalarVector, BulletproofsBatchVerifier};
|
||||
|
||||
@@ -107,7 +107,7 @@ impl<'a> AggregateRangeStatement<'a> {
|
||||
None?
|
||||
};
|
||||
|
||||
let generators = GENERATORS();
|
||||
let generators = &GENERATORS;
|
||||
|
||||
let (mut transcript, _) = self.initial_transcript();
|
||||
|
||||
@@ -186,7 +186,7 @@ impl<'a> AggregateRangeStatement<'a> {
|
||||
|
||||
let tau_1 = Scalar::random(&mut *rng);
|
||||
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 {
|
||||
term.0 *= INV_EIGHT();
|
||||
}
|
||||
@@ -196,7 +196,7 @@ impl<'a> AggregateRangeStatement<'a> {
|
||||
};
|
||||
let tau_2 = Scalar::random(&mut *rng);
|
||||
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 {
|
||||
term.0 *= INV_EIGHT();
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#![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};
|
||||
|
||||
@@ -39,7 +39,7 @@ include!(concat!(env!("OUT_DIR"), "/generators_plus.rs"));
|
||||
impl BpPlusGenerators {
|
||||
#[allow(clippy::new_without_default)]
|
||||
pub(crate) fn new() -> Self {
|
||||
let gens = GENERATORS();
|
||||
let gens = &GENERATORS;
|
||||
BpPlusGenerators { g_bold: &gens.G, h_bold: &gens.H }
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ impl BpPlusGenerators {
|
||||
}
|
||||
|
||||
pub(crate) fn g() -> EdwardsPoint {
|
||||
H()
|
||||
*H
|
||||
}
|
||||
|
||||
pub(crate) fn h() -> EdwardsPoint {
|
||||
|
||||
@@ -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};
|
||||
|
||||
@@ -6,15 +6,12 @@ use monero_generators::hash_to_point;
|
||||
use monero_primitives::{keccak256, keccak256_to_scalar};
|
||||
|
||||
// Monero starts BP+ transcripts with the following constant.
|
||||
static TRANSCRIPT_CELL: OnceLock<[u8; 32]> = OnceLock::new();
|
||||
pub(crate) fn TRANSCRIPT() -> [u8; 32] {
|
||||
// Why this uses a hash_to_point is completely unknown.
|
||||
*TRANSCRIPT_CELL
|
||||
.get_or_init(|| hash_to_point(keccak256(b"bulletproof_plus_transcript")).compress().to_bytes())
|
||||
}
|
||||
// Why this uses a hash_to_point is completely unknown.
|
||||
pub(crate) static TRANSCRIPT: LazyLock<[u8; 32]> =
|
||||
LazyLock::new(|| hash_to_point(keccak256(b"bulletproof_plus_transcript")).compress().to_bytes());
|
||||
|
||||
pub(crate) fn initial_transcript(commitments: core::slice::Iter<'_, EdwardsPoint>) -> Scalar {
|
||||
let commitments_hash =
|
||||
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())
|
||||
}
|
||||
|
||||
@@ -35,12 +35,12 @@ fn test_zero_inner_product() {
|
||||
#[test]
|
||||
fn test_inner_product() {
|
||||
// P = sum(g_bold * a, h_bold * b, g * u * <a, b>)
|
||||
let generators = GENERATORS();
|
||||
let generators = &GENERATORS;
|
||||
let mut verifier = BulletproofsBatchVerifier::default();
|
||||
verifier.0.g_bold = vec![Scalar::ZERO; 32];
|
||||
verifier.0.h_bold = vec![Scalar::ZERO; 32];
|
||||
for i in [1, 2, 4, 8, 16, 32] {
|
||||
let g = H();
|
||||
let g = *H;
|
||||
let mut g_bold = vec![];
|
||||
let mut h_bold = vec![];
|
||||
for i in 0 .. i {
|
||||
|
||||
@@ -6,7 +6,7 @@ license = "MIT"
|
||||
repository = "https://github.com/serai-dex/serai/tree/develop/networks/monero/ringct/clsag"
|
||||
authors = ["Luke Parker <lukeparker5132@gmail.com>"]
|
||||
edition = "2021"
|
||||
rust-version = "1.79"
|
||||
rust-version = "1.80"
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
all-features = true
|
||||
|
||||
@@ -6,7 +6,7 @@ license = "MIT"
|
||||
repository = "https://github.com/serai-dex/serai/tree/develop/networks/monero/ringct/mlsag"
|
||||
authors = ["Luke Parker <lukeparker5132@gmail.com>"]
|
||||
edition = "2021"
|
||||
rust-version = "1.79"
|
||||
rust-version = "1.80"
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
all-features = true
|
||||
|
||||
@@ -203,7 +203,7 @@ impl AggregateRingMatrixBuilder {
|
||||
AggregateRingMatrixBuilder {
|
||||
key_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)),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ license = "MIT"
|
||||
repository = "https://github.com/serai-dex/serai/tree/develop/networks/monero/rpc"
|
||||
authors = ["Luke Parker <lukeparker5132@gmail.com>"]
|
||||
edition = "2021"
|
||||
rust-version = "1.79"
|
||||
rust-version = "1.80"
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
all-features = true
|
||||
|
||||
@@ -6,7 +6,7 @@ license = "MIT"
|
||||
repository = "https://github.com/serai-dex/serai/tree/develop/networks/monero/rpc/simple-request"
|
||||
authors = ["Luke Parker <lukeparker5132@gmail.com>"]
|
||||
edition = "2021"
|
||||
rust-version = "1.79"
|
||||
rust-version = "1.80"
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
all-features = true
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use std::sync::OnceLock;
|
||||
use std::sync::LazyLock;
|
||||
use tokio::sync::Mutex;
|
||||
|
||||
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)
|
||||
use monero_simple_request_rpc::*;
|
||||
|
||||
static SEQUENTIAL: OnceLock<Mutex<()>> = OnceLock::new();
|
||||
static SEQUENTIAL: LazyLock<Mutex<()>> = LazyLock::new(|| Mutex::new(()));
|
||||
|
||||
const ADDRESS: &str =
|
||||
"4B33mFPMq6mKi7Eiyd5XuyKRVMGVZz1Rqb9ZTyGApXW5d1aT7UBDZ89ewmnWFkzJ5wPd2SFbn313vCT8a4E2Qf4KQH4pNey";
|
||||
@@ -17,7 +17,7 @@ const ADDRESS: &str =
|
||||
async fn test_rpc() {
|
||||
use monero_rpc::Rpc;
|
||||
|
||||
let guard = SEQUENTIAL.get_or_init(|| Mutex::new(())).lock().await;
|
||||
let guard = SEQUENTIAL.lock().await;
|
||||
|
||||
let rpc =
|
||||
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() {
|
||||
use monero_rpc::{Rpc, DecoyRpc};
|
||||
|
||||
let guard = SEQUENTIAL.get_or_init(|| Mutex::new(())).lock().await;
|
||||
let guard = SEQUENTIAL.lock().await;
|
||||
|
||||
let rpc =
|
||||
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() {
|
||||
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();
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ license = "MIT"
|
||||
repository = "https://github.com/serai-dex/serai/tree/develop/networks/monero/verify-chain"
|
||||
authors = ["Luke Parker <lukeparker5132@gmail.com>"]
|
||||
edition = "2021"
|
||||
rust-version = "1.79"
|
||||
rust-version = "1.80"
|
||||
publish = false
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
|
||||
@@ -6,7 +6,7 @@ license = "MIT"
|
||||
repository = "https://github.com/serai-dex/serai/tree/develop/networks/monero/wallet"
|
||||
authors = ["Luke Parker <lukeparker5132@gmail.com>"]
|
||||
edition = "2021"
|
||||
rust-version = "1.79"
|
||||
rust-version = "1.80"
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
all-features = true
|
||||
|
||||
@@ -6,7 +6,7 @@ license = "MIT"
|
||||
repository = "https://github.com/serai-dex/serai/tree/develop/networks/monero/wallet/address"
|
||||
authors = ["Luke Parker <lukeparker5132@gmail.com>"]
|
||||
edition = "2021"
|
||||
rust-version = "1.79"
|
||||
rust-version = "1.80"
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
all-features = true
|
||||
|
||||
@@ -6,7 +6,7 @@ license = "MIT"
|
||||
repository = "https://github.com/serai-dex/serai/tree/develop/networks/monero/wallet/polyseed"
|
||||
authors = ["Luke Parker <lukeparker5132@gmail.com>"]
|
||||
edition = "2021"
|
||||
rust-version = "1.79"
|
||||
rust-version = "1.80"
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
all-features = true
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
use core::fmt;
|
||||
use std_shims::{sync::OnceLock, string::String, collections::HashMap};
|
||||
use std_shims::{sync::LazyLock, string::String, collections::HashMap};
|
||||
#[cfg(feature = "std")]
|
||||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
|
||||
@@ -163,30 +163,26 @@ impl WordList {
|
||||
}
|
||||
}
|
||||
|
||||
static LANGUAGES_CELL: OnceLock<HashMap<Language, WordList>> = OnceLock::new();
|
||||
#[allow(non_snake_case)]
|
||||
fn LANGUAGES() -> &'static HashMap<Language, WordList> {
|
||||
LANGUAGES_CELL.get_or_init(|| {
|
||||
HashMap::from([
|
||||
(Language::Czech, WordList::new(include!("./words/cs.rs"), true, false)),
|
||||
(Language::French, WordList::new(include!("./words/fr.rs"), true, true)),
|
||||
(Language::Korean, WordList::new(include!("./words/ko.rs"), false, false)),
|
||||
(Language::English, WordList::new(include!("./words/en.rs"), true, false)),
|
||||
(Language::Italian, WordList::new(include!("./words/it.rs"), true, false)),
|
||||
(Language::Spanish, WordList::new(include!("./words/es.rs"), true, true)),
|
||||
(Language::Japanese, WordList::new(include!("./words/ja.rs"), false, false)),
|
||||
(Language::Portuguese, WordList::new(include!("./words/pt.rs"), true, false)),
|
||||
(
|
||||
Language::ChineseSimplified,
|
||||
WordList::new(include!("./words/zh_simplified.rs"), false, false),
|
||||
),
|
||||
(
|
||||
Language::ChineseTraditional,
|
||||
WordList::new(include!("./words/zh_traditional.rs"), false, false),
|
||||
),
|
||||
])
|
||||
})
|
||||
}
|
||||
static LANGUAGES: LazyLock<HashMap<Language, WordList>> = LazyLock::new(|| {
|
||||
HashMap::from([
|
||||
(Language::Czech, WordList::new(include!("./words/cs.rs"), true, false)),
|
||||
(Language::French, WordList::new(include!("./words/fr.rs"), true, true)),
|
||||
(Language::Korean, WordList::new(include!("./words/ko.rs"), false, false)),
|
||||
(Language::English, WordList::new(include!("./words/en.rs"), true, false)),
|
||||
(Language::Italian, WordList::new(include!("./words/it.rs"), true, false)),
|
||||
(Language::Spanish, WordList::new(include!("./words/es.rs"), true, true)),
|
||||
(Language::Japanese, WordList::new(include!("./words/ja.rs"), false, false)),
|
||||
(Language::Portuguese, WordList::new(include!("./words/pt.rs"), true, false)),
|
||||
(
|
||||
Language::ChineseSimplified,
|
||||
WordList::new(include!("./words/zh_simplified.rs"), false, false),
|
||||
),
|
||||
(
|
||||
Language::ChineseTraditional,
|
||||
WordList::new(include!("./words/zh_traditional.rs"), false, false),
|
||||
),
|
||||
])
|
||||
});
|
||||
|
||||
/// A Polyseed.
|
||||
#[derive(Clone, PartialEq, Eq, Zeroize, ZeroizeOnDrop)]
|
||||
@@ -317,7 +313,7 @@ impl Polyseed {
|
||||
let mut poly = [0; POLYSEED_LENGTH];
|
||||
|
||||
// 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() {
|
||||
// Find the word's index
|
||||
fn check_if_matches<S: AsRef<str>, I: Iterator<Item = S>>(
|
||||
@@ -464,7 +460,7 @@ impl Polyseed {
|
||||
|
||||
// Output words
|
||||
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() {
|
||||
seed.push_str(words[usize::from(poly[i])]);
|
||||
if i < poly.len() - 1 {
|
||||
|
||||
@@ -6,7 +6,7 @@ license = "MIT"
|
||||
repository = "https://github.com/serai-dex/serai/tree/develop/networks/monero/wallet/seed"
|
||||
authors = ["Luke Parker <lukeparker5132@gmail.com>"]
|
||||
edition = "2021"
|
||||
rust-version = "1.79"
|
||||
rust-version = "1.80"
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
all-features = true
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
use core::{ops::Deref, fmt};
|
||||
use std_shims::{
|
||||
sync::OnceLock,
|
||||
sync::LazyLock,
|
||||
vec,
|
||||
vec::Vec,
|
||||
string::{String, ToString},
|
||||
@@ -102,27 +102,23 @@ impl WordList {
|
||||
}
|
||||
}
|
||||
|
||||
static LANGUAGES_CELL: OnceLock<HashMap<Language, WordList>> = OnceLock::new();
|
||||
#[allow(non_snake_case)]
|
||||
fn LANGUAGES() -> &'static HashMap<Language, WordList> {
|
||||
LANGUAGES_CELL.get_or_init(|| {
|
||||
HashMap::from([
|
||||
(Language::Chinese, WordList::new(include!("./words/zh.rs"), 1)),
|
||||
(Language::English, WordList::new(include!("./words/en.rs"), 3)),
|
||||
(Language::Dutch, WordList::new(include!("./words/nl.rs"), 4)),
|
||||
(Language::French, WordList::new(include!("./words/fr.rs"), 4)),
|
||||
(Language::Spanish, WordList::new(include!("./words/es.rs"), 4)),
|
||||
(Language::German, WordList::new(include!("./words/de.rs"), 4)),
|
||||
(Language::Italian, WordList::new(include!("./words/it.rs"), 4)),
|
||||
(Language::Portuguese, WordList::new(include!("./words/pt.rs"), 4)),
|
||||
(Language::Japanese, WordList::new(include!("./words/ja.rs"), 3)),
|
||||
(Language::Russian, WordList::new(include!("./words/ru.rs"), 4)),
|
||||
(Language::Esperanto, WordList::new(include!("./words/eo.rs"), 4)),
|
||||
(Language::Lojban, WordList::new(include!("./words/jbo.rs"), 4)),
|
||||
(Language::DeprecatedEnglish, WordList::new(include!("./words/ang.rs"), 4)),
|
||||
])
|
||||
})
|
||||
}
|
||||
static LANGUAGES: LazyLock<HashMap<Language, WordList>> = LazyLock::new(|| {
|
||||
HashMap::from([
|
||||
(Language::Chinese, WordList::new(include!("./words/zh.rs"), 1)),
|
||||
(Language::English, WordList::new(include!("./words/en.rs"), 3)),
|
||||
(Language::Dutch, WordList::new(include!("./words/nl.rs"), 4)),
|
||||
(Language::French, WordList::new(include!("./words/fr.rs"), 4)),
|
||||
(Language::Spanish, WordList::new(include!("./words/es.rs"), 4)),
|
||||
(Language::German, WordList::new(include!("./words/de.rs"), 4)),
|
||||
(Language::Italian, WordList::new(include!("./words/it.rs"), 4)),
|
||||
(Language::Portuguese, WordList::new(include!("./words/pt.rs"), 4)),
|
||||
(Language::Japanese, WordList::new(include!("./words/ja.rs"), 3)),
|
||||
(Language::Russian, WordList::new(include!("./words/ru.rs"), 4)),
|
||||
(Language::Esperanto, WordList::new(include!("./words/eo.rs"), 4)),
|
||||
(Language::Lojban, WordList::new(include!("./words/jbo.rs"), 4)),
|
||||
(Language::DeprecatedEnglish, WordList::new(include!("./words/ang.rs"), 4)),
|
||||
])
|
||||
});
|
||||
|
||||
fn checksum_index(words: &[Zeroizing<String>], lang: &WordList) -> usize {
|
||||
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());
|
||||
|
||||
// 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();
|
||||
|
||||
// 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
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
let lang_word_list: &WordList = &LANGUAGES()[&lang];
|
||||
let lang_word_list: &WordList = &LANGUAGES[&lang];
|
||||
let matched_indices = (|| {
|
||||
let has_checksum = words.len() == SEED_LENGTH_WITH_CHECKSUM;
|
||||
let mut matched_indices = Zeroizing::new(vec![]);
|
||||
|
||||
@@ -183,7 +183,7 @@ fn test_original_seed() {
|
||||
for vector in vectors {
|
||||
fn trim_by_lang(word: &str, lang: Language) -> String {
|
||||
if lang != Language::DeprecatedEnglish {
|
||||
word.chars().take(LANGUAGES()[&lang].unique_prefix_length).collect()
|
||||
word.chars().take(LANGUAGES[&lang].unique_prefix_length).collect()
|
||||
} else {
|
||||
word.to_string()
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use core::ops::Deref;
|
||||
use std_shims::sync::OnceLock;
|
||||
use std_shims::sync::LazyLock;
|
||||
|
||||
use zeroize::Zeroizing;
|
||||
use rand_core::OsRng;
|
||||
@@ -145,7 +145,7 @@ pub async fn rpc() -> SimpleRequestRpc {
|
||||
rpc
|
||||
}
|
||||
|
||||
pub static SEQUENTIAL: OnceLock<Mutex<()>> = OnceLock::new();
|
||||
pub(crate) static SEQUENTIAL: LazyLock<Mutex<()>> = LazyLock::new(|| Mutex::new(()));
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! async_sequential {
|
||||
@@ -153,7 +153,7 @@ macro_rules! async_sequential {
|
||||
$(
|
||||
#[tokio::test]
|
||||
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();
|
||||
local.run_until(async move {
|
||||
if let Err(err) = tokio::task::spawn_local(async move { $body }).await {
|
||||
|
||||
@@ -6,7 +6,7 @@ license = "MIT"
|
||||
repository = "https://github.com/serai-dex/serai/tree/develop/networks/monero/wallet/util"
|
||||
authors = ["Luke Parker <lukeparker5132@gmail.com>"]
|
||||
edition = "2021"
|
||||
rust-version = "1.79"
|
||||
rust-version = "1.80"
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
all-features = true
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# rust:1.79.0-slim-bookworm as of June 14th, 2024 (GMT)
|
||||
FROM --platform=linux/amd64 rust@sha256:fa189cd885739dd17fc6bb4e132687fce43f2bf42983c0ac39b60e4943201e9c as deterministic
|
||||
# rust:1.80.0-slim-bookworm as of July 27th, 2024 (GMT)
|
||||
FROM --platform=linux/amd64 rust@sha256:37e6f90f98b3afd15c2526d7abb257a1f4cb7d49808fe3729d9d62020b07b544 as deterministic
|
||||
|
||||
# Move to a Debian package snapshot
|
||||
RUN rm -rf /etc/apt/sources.list.d/debian.sources && \
|
||||
|
||||
@@ -146,7 +146,7 @@ fn build_serai_service(prelude: &str, release: bool, features: &str, package: &s
|
||||
|
||||
format!(
|
||||
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
|
||||
RUN echo "/usr/lib/libmimalloc.so" >> /etc/ld.so.preload
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
[toolchain]
|
||||
channel = "1.79"
|
||||
channel = "1.80"
|
||||
targets = ["wasm32-unknown-unknown"]
|
||||
profile = "minimal"
|
||||
components = ["rust-src", "rustfmt", "clippy"]
|
||||
|
||||
Reference in New Issue
Block a user