mirror of
https://github.com/serai-dex/serai.git
synced 2024-11-17 01:17:36 +00:00
Make coin a dedicated library
Closes https://github.com/serai-dex/serai/issues/128.
This commit is contained in:
parent
f50148d17a
commit
65664dafa4
9 changed files with 119 additions and 42 deletions
28
Cargo.lock
generated
28
Cargo.lock
generated
|
@ -4564,7 +4564,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "modular-frost"
|
name = "modular-frost"
|
||||||
version = "0.2.3"
|
version = "0.2.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"dalek-ff-group",
|
"dalek-ff-group",
|
||||||
"dleq",
|
"dleq",
|
||||||
|
@ -7497,6 +7497,23 @@ version = "0.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "930c0acf610d3fdb5e2ab6213019aaa04e227ebe9547b0649ba599b16d788bd7"
|
checksum = "930c0acf610d3fdb5e2ab6213019aaa04e227ebe9547b0649ba599b16d788bd7"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serai-coin"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"async-trait",
|
||||||
|
"curve25519-dalek 3.2.0",
|
||||||
|
"dalek-ff-group",
|
||||||
|
"flexible-transcript",
|
||||||
|
"group",
|
||||||
|
"modular-frost",
|
||||||
|
"monero-serai",
|
||||||
|
"rand_core 0.6.4",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"thiserror",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serai-consensus"
|
name = "serai-consensus"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
@ -7587,20 +7604,13 @@ name = "serai-processor"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"blake2",
|
|
||||||
"curve25519-dalek 3.2.0",
|
|
||||||
"dalek-ff-group",
|
|
||||||
"flexible-transcript",
|
"flexible-transcript",
|
||||||
"futures",
|
"futures",
|
||||||
"group",
|
"group",
|
||||||
"hex",
|
"hex",
|
||||||
"k256",
|
|
||||||
"modular-frost",
|
"modular-frost",
|
||||||
"monero-serai",
|
|
||||||
"rand_core 0.6.4",
|
"rand_core 0.6.4",
|
||||||
"serde",
|
"serai-coin",
|
||||||
"serde_json",
|
|
||||||
"sha3 0.10.5",
|
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"tokio",
|
"tokio",
|
||||||
]
|
]
|
||||||
|
|
41
coin/Cargo.toml
Normal file
41
coin/Cargo.toml
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
[package]
|
||||||
|
name = "serai-coin"
|
||||||
|
version = "0.1.0"
|
||||||
|
description = "Abstract interface to represent a coin"
|
||||||
|
license = "MIT"
|
||||||
|
repository = "https://github.com/serai-dex/serai"
|
||||||
|
authors = ["Luke Parker <lukeparker5132@gmail.com>"]
|
||||||
|
keywords = []
|
||||||
|
edition = "2021"
|
||||||
|
publish = false
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
async-trait = "0.1"
|
||||||
|
thiserror = "1"
|
||||||
|
|
||||||
|
curve25519-dalek = { version = "3", features = ["std"] }
|
||||||
|
|
||||||
|
transcript = { package = "flexible-transcript", path = "../crypto/transcript", features = ["recommended"] }
|
||||||
|
dalek-ff-group = { path = "../crypto/dalek-ff-group" }
|
||||||
|
frost = { package = "modular-frost", path = "../crypto/frost", features = ["secp256k1", "ed25519"] }
|
||||||
|
|
||||||
|
monero-serai = { path = "../coins/monero", features = ["multisig"] }
|
||||||
|
|
||||||
|
# Test Dependencies
|
||||||
|
rand_core = { version = "0.6", optional = true }
|
||||||
|
|
||||||
|
group = { version = "0.12", optional = true }
|
||||||
|
|
||||||
|
serde = { version = "1.0", features = ["derive"], optional = true }
|
||||||
|
serde_json = { version = "1.0", optional = true }
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
rand_core = "0.6"
|
||||||
|
|
||||||
|
group = "0.12"
|
||||||
|
|
||||||
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
|
serde_json = "1.0"
|
||||||
|
|
||||||
|
[features]
|
||||||
|
test = ["rand_core", "group", "serde", "serde_json"]
|
21
coin/LICENSE
Normal file
21
coin/LICENSE
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2022 Luke Parker
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
|
@ -6,6 +6,8 @@ use thiserror::Error;
|
||||||
use transcript::RecommendedTranscript;
|
use transcript::RecommendedTranscript;
|
||||||
use frost::{curve::Curve, FrostKeys, sign::PreprocessMachine};
|
use frost::{curve::Curve, FrostKeys, sign::PreprocessMachine};
|
||||||
|
|
||||||
|
pub(crate) mod utils;
|
||||||
|
|
||||||
pub mod monero;
|
pub mod monero;
|
||||||
pub use self::monero::Monero;
|
pub use self::monero::Monero;
|
||||||
|
|
||||||
|
@ -79,9 +81,12 @@ pub trait Coin {
|
||||||
tx: &Self::Transaction,
|
tx: &Self::Transaction,
|
||||||
) -> Result<(Vec<u8>, Vec<<Self::Output as Output>::Id>), CoinError>;
|
) -> Result<(Vec<u8>, Vec<<Self::Output as Output>::Id>), CoinError>;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(any(test, feature = "test"))]
|
||||||
|
async fn get_fee(&self) -> Self::Fee;
|
||||||
|
|
||||||
|
#[cfg(any(test, feature = "test"))]
|
||||||
async fn mine_block(&self);
|
async fn mine_block(&self);
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(any(test, feature = "test"))]
|
||||||
async fn test_send(&self, key: Self::Address);
|
async fn test_send(&self, key: Self::Address);
|
||||||
}
|
}
|
|
@ -17,10 +17,7 @@ use monero_serai::{
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{CoinError, Output as OutputTrait, Coin, utils::additional_key};
|
||||||
coin::{CoinError, Output as OutputTrait, Coin},
|
|
||||||
view_key,
|
|
||||||
};
|
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Output(SpendableOutput);
|
pub struct Output(SpendableOutput);
|
||||||
|
@ -70,14 +67,14 @@ pub struct Monero {
|
||||||
|
|
||||||
impl Monero {
|
impl Monero {
|
||||||
pub async fn new(url: String) -> Monero {
|
pub async fn new(url: String) -> Monero {
|
||||||
Monero { rpc: Rpc::new(url), view: view_key::<Monero>(0).0 }
|
Monero { rpc: Rpc::new(url), view: additional_key::<Monero>(0).0 }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn scanner(&self, spend: dfg::EdwardsPoint) -> Scanner {
|
fn scanner(&self, spend: dfg::EdwardsPoint) -> Scanner {
|
||||||
Scanner::from_view(ViewPair::new(spend.0, self.view), Network::Mainnet, None)
|
Scanner::from_view(ViewPair::new(spend.0, self.view), Network::Mainnet, None)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(any(test, feature = "test"))]
|
||||||
fn empty_scanner() -> Scanner {
|
fn empty_scanner() -> Scanner {
|
||||||
use group::Group;
|
use group::Group;
|
||||||
Scanner::from_view(
|
Scanner::from_view(
|
||||||
|
@ -87,7 +84,7 @@ impl Monero {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(any(test, feature = "test"))]
|
||||||
fn empty_address() -> Address {
|
fn empty_address() -> Address {
|
||||||
Self::empty_scanner().address()
|
Self::empty_scanner().address()
|
||||||
}
|
}
|
||||||
|
@ -209,7 +206,12 @@ impl Coin for Monero {
|
||||||
Ok((tx.hash().to_vec(), tx.prefix.outputs.iter().map(|output| output.key.to_bytes()).collect()))
|
Ok((tx.hash().to_vec(), tx.prefix.outputs.iter().map(|output| output.key.to_bytes()).collect()))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(any(test, feature = "test"))]
|
||||||
|
async fn get_fee(&self) -> Self::Fee {
|
||||||
|
self.rpc.get_fee().await.unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(any(test, feature = "test"))]
|
||||||
async fn mine_block(&self) {
|
async fn mine_block(&self) {
|
||||||
#[derive(serde::Deserialize, Debug)]
|
#[derive(serde::Deserialize, Debug)]
|
||||||
struct EmptyResponse {}
|
struct EmptyResponse {}
|
||||||
|
@ -229,7 +231,7 @@ impl Coin for Monero {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(any(test, feature = "test"))]
|
||||||
async fn test_send(&self, address: Self::Address) {
|
async fn test_send(&self, address: Self::Address) {
|
||||||
use rand_core::OsRng;
|
use rand_core::OsRng;
|
||||||
|
|
11
coin/src/utils.rs
Normal file
11
coin/src/utils.rs
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
use frost::curve::Curve;
|
||||||
|
|
||||||
|
use crate::Coin;
|
||||||
|
|
||||||
|
// Generate a static additional key for a given chain in a globally consistent manner
|
||||||
|
// Doesn't consider the current group key to increase the simplicity of verifying Serai's status
|
||||||
|
// Takes an index, k, to support protocols which use multiple secondary keys
|
||||||
|
// Presumably a view key
|
||||||
|
pub(crate) fn additional_key<C: Coin>(k: u64) -> <C::Curve as Curve>::F {
|
||||||
|
C::Curve::hash_to_F(b"Serai DEX Additional Key", &[C::ID, &k.to_le_bytes()].concat())
|
||||||
|
}
|
|
@ -3,7 +3,7 @@ name = "serai-processor"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
description = "Multichain processor premised on canonicity to reach distributed consensus automatically"
|
description = "Multichain processor premised on canonicity to reach distributed consensus automatically"
|
||||||
license = "AGPL-3.0-only"
|
license = "AGPL-3.0-only"
|
||||||
repository = "https://github.com/serai-dex/processor"
|
repository = "https://github.com/serai-dex/serai"
|
||||||
authors = ["Luke Parker <lukeparker5132@gmail.com>"]
|
authors = ["Luke Parker <lukeparker5132@gmail.com>"]
|
||||||
keywords = []
|
keywords = []
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
@ -14,24 +14,17 @@ async-trait = "0.1"
|
||||||
rand_core = "0.6"
|
rand_core = "0.6"
|
||||||
thiserror = "1"
|
thiserror = "1"
|
||||||
|
|
||||||
hex = "0.4"
|
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
|
||||||
serde_json = "1.0"
|
|
||||||
|
|
||||||
sha3 = "0.10"
|
|
||||||
blake2 = "0.10"
|
|
||||||
|
|
||||||
group = "0.12"
|
group = "0.12"
|
||||||
k256 = { version = "0.11", features = ["arithmetic", "keccak256", "ecdsa"] }
|
|
||||||
curve25519-dalek = { version = "3", features = ["std"] }
|
|
||||||
|
|
||||||
transcript = { package = "flexible-transcript", path = "../crypto/transcript", features = ["recommended"] }
|
transcript = { package = "flexible-transcript", path = "../crypto/transcript", features = ["recommended"] }
|
||||||
dalek-ff-group = { path = "../crypto/dalek-ff-group" }
|
|
||||||
frost = { package = "modular-frost", path = "../crypto/frost", features = ["secp256k1", "ed25519"] }
|
frost = { package = "modular-frost", path = "../crypto/frost", features = ["secp256k1", "ed25519"] }
|
||||||
|
|
||||||
monero-serai = { path = "../coins/monero", features = ["multisig"] }
|
serai-coin = { path = "../coin" }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
group = "0.12"
|
hex = "0.4"
|
||||||
|
|
||||||
futures = "0.3"
|
futures = "0.3"
|
||||||
tokio = { version = "1", features = ["full"] }
|
tokio = { version = "1", features = ["full"] }
|
||||||
|
|
||||||
|
serai-coin = { path = "../coin", features = ["test"] }
|
||||||
|
|
|
@ -5,8 +5,9 @@ use thiserror::Error;
|
||||||
|
|
||||||
use frost::{curve::Curve, FrostError};
|
use frost::{curve::Curve, FrostError};
|
||||||
|
|
||||||
mod coin;
|
pub use serai_coin as coin;
|
||||||
use coin::{CoinError, Coin};
|
use coin::{CoinError, Coin};
|
||||||
|
|
||||||
mod wallet;
|
mod wallet;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -29,10 +30,3 @@ pub enum SignError {
|
||||||
#[error("network had an error {0}")]
|
#[error("network had an error {0}")]
|
||||||
NetworkError(NetworkError),
|
NetworkError(NetworkError),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate a static view key for a given chain in a globally consistent manner
|
|
||||||
// Doesn't consider the current group key to increase the simplicity of verifying Serai's status
|
|
||||||
// Takes an index, k, for more modern privacy protocols which use multiple view keys
|
|
||||||
pub fn view_key<C: Coin>(k: u64) -> <C::Curve as Curve>::F {
|
|
||||||
C::Curve::hash_to_F(b"Serai DEX View Key", &[C::ID, &k.to_le_bytes()].concat())
|
|
||||||
}
|
|
||||||
|
|
|
@ -112,6 +112,6 @@ async fn test_send<C: Coin + Clone>(coin: C, fee: C::Fee) {
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn monero() {
|
async fn monero() {
|
||||||
let monero = Monero::new("http://127.0.0.1:18081".to_string()).await;
|
let monero = Monero::new("http://127.0.0.1:18081".to_string()).await;
|
||||||
let fee = monero.rpc.get_fee().await.unwrap();
|
let fee = monero.get_fee().await;
|
||||||
test_send(monero, fee).await;
|
test_send(monero, fee).await;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue