From 65664dafa4b430c6ecc6f2cc6725e75798771637 Mon Sep 17 00:00:00 2001 From: Luke Parker Date: Sat, 15 Oct 2022 23:21:43 -0400 Subject: [PATCH] Make coin a dedicated library Closes https://github.com/serai-dex/serai/issues/128. --- Cargo.lock | 28 ++++++++----- coin/Cargo.toml | 41 ++++++++++++++++++++ coin/LICENSE | 21 ++++++++++ processor/src/coin/mod.rs => coin/src/lib.rs | 9 ++++- {processor/src/coin => coin/src}/monero.rs | 20 +++++----- coin/src/utils.rs | 11 ++++++ processor/Cargo.toml | 19 +++------ processor/src/lib.rs | 10 +---- processor/src/tests/mod.rs | 2 +- 9 files changed, 119 insertions(+), 42 deletions(-) create mode 100644 coin/Cargo.toml create mode 100644 coin/LICENSE rename processor/src/coin/mod.rs => coin/src/lib.rs (92%) rename {processor/src/coin => coin/src}/monero.rs (94%) create mode 100644 coin/src/utils.rs diff --git a/Cargo.lock b/Cargo.lock index 0b562451..030b4d15 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4564,7 +4564,7 @@ dependencies = [ [[package]] name = "modular-frost" -version = "0.2.3" +version = "0.2.4" dependencies = [ "dalek-ff-group", "dleq", @@ -7497,6 +7497,23 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" 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]] name = "serai-consensus" version = "0.1.0" @@ -7587,20 +7604,13 @@ name = "serai-processor" version = "0.1.0" dependencies = [ "async-trait", - "blake2", - "curve25519-dalek 3.2.0", - "dalek-ff-group", "flexible-transcript", "futures", "group", "hex", - "k256", "modular-frost", - "monero-serai", "rand_core 0.6.4", - "serde", - "serde_json", - "sha3 0.10.5", + "serai-coin", "thiserror", "tokio", ] diff --git a/coin/Cargo.toml b/coin/Cargo.toml new file mode 100644 index 00000000..a8ef301e --- /dev/null +++ b/coin/Cargo.toml @@ -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 "] +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"] diff --git a/coin/LICENSE b/coin/LICENSE new file mode 100644 index 00000000..f05b748b --- /dev/null +++ b/coin/LICENSE @@ -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. diff --git a/processor/src/coin/mod.rs b/coin/src/lib.rs similarity index 92% rename from processor/src/coin/mod.rs rename to coin/src/lib.rs index d018a7b7..bf19e388 100644 --- a/processor/src/coin/mod.rs +++ b/coin/src/lib.rs @@ -6,6 +6,8 @@ use thiserror::Error; use transcript::RecommendedTranscript; use frost::{curve::Curve, FrostKeys, sign::PreprocessMachine}; +pub(crate) mod utils; + pub mod monero; pub use self::monero::Monero; @@ -79,9 +81,12 @@ pub trait Coin { tx: &Self::Transaction, ) -> Result<(Vec, Vec<::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); - #[cfg(test)] + #[cfg(any(test, feature = "test"))] async fn test_send(&self, key: Self::Address); } diff --git a/processor/src/coin/monero.rs b/coin/src/monero.rs similarity index 94% rename from processor/src/coin/monero.rs rename to coin/src/monero.rs index d859a6c2..fde20cb6 100644 --- a/processor/src/coin/monero.rs +++ b/coin/src/monero.rs @@ -17,10 +17,7 @@ use monero_serai::{ }, }; -use crate::{ - coin::{CoinError, Output as OutputTrait, Coin}, - view_key, -}; +use crate::{CoinError, Output as OutputTrait, Coin, utils::additional_key}; #[derive(Clone, Debug)] pub struct Output(SpendableOutput); @@ -70,14 +67,14 @@ pub struct Monero { impl Monero { pub async fn new(url: String) -> Monero { - Monero { rpc: Rpc::new(url), view: view_key::(0).0 } + Monero { rpc: Rpc::new(url), view: additional_key::(0).0 } } fn scanner(&self, spend: dfg::EdwardsPoint) -> Scanner { Scanner::from_view(ViewPair::new(spend.0, self.view), Network::Mainnet, None) } - #[cfg(test)] + #[cfg(any(test, feature = "test"))] fn empty_scanner() -> Scanner { use group::Group; Scanner::from_view( @@ -87,7 +84,7 @@ impl Monero { ) } - #[cfg(test)] + #[cfg(any(test, feature = "test"))] fn empty_address() -> 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())) } - #[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) { #[derive(serde::Deserialize, Debug)] struct EmptyResponse {} @@ -229,7 +231,7 @@ impl Coin for Monero { .unwrap(); } - #[cfg(test)] + #[cfg(any(test, feature = "test"))] async fn test_send(&self, address: Self::Address) { use rand_core::OsRng; diff --git a/coin/src/utils.rs b/coin/src/utils.rs new file mode 100644 index 00000000..3370f59c --- /dev/null +++ b/coin/src/utils.rs @@ -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(k: u64) -> ::F { + C::Curve::hash_to_F(b"Serai DEX Additional Key", &[C::ID, &k.to_le_bytes()].concat()) +} diff --git a/processor/Cargo.toml b/processor/Cargo.toml index 18942d4b..f11e39a6 100644 --- a/processor/Cargo.toml +++ b/processor/Cargo.toml @@ -3,7 +3,7 @@ name = "serai-processor" version = "0.1.0" description = "Multichain processor premised on canonicity to reach distributed consensus automatically" license = "AGPL-3.0-only" -repository = "https://github.com/serai-dex/processor" +repository = "https://github.com/serai-dex/serai" authors = ["Luke Parker "] keywords = [] edition = "2021" @@ -14,24 +14,17 @@ async-trait = "0.1" rand_core = "0.6" thiserror = "1" -hex = "0.4" -serde = { version = "1.0", features = ["derive"] } -serde_json = "1.0" - -sha3 = "0.10" -blake2 = "0.10" - 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"] } -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"] } +serai-coin = { path = "../coin" } [dev-dependencies] -group = "0.12" +hex = "0.4" + futures = "0.3" tokio = { version = "1", features = ["full"] } + +serai-coin = { path = "../coin", features = ["test"] } diff --git a/processor/src/lib.rs b/processor/src/lib.rs index 58346e0e..77b22dcd 100644 --- a/processor/src/lib.rs +++ b/processor/src/lib.rs @@ -5,8 +5,9 @@ use thiserror::Error; use frost::{curve::Curve, FrostError}; -mod coin; +pub use serai_coin as coin; use coin::{CoinError, Coin}; + mod wallet; #[cfg(test)] @@ -29,10 +30,3 @@ pub enum SignError { #[error("network had an error {0}")] 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(k: u64) -> ::F { - C::Curve::hash_to_F(b"Serai DEX View Key", &[C::ID, &k.to_le_bytes()].concat()) -} diff --git a/processor/src/tests/mod.rs b/processor/src/tests/mod.rs index c365acf8..27cd8f31 100644 --- a/processor/src/tests/mod.rs +++ b/processor/src/tests/mod.rs @@ -112,6 +112,6 @@ async fn test_send(coin: C, fee: C::Fee) { #[tokio::test] async fn monero() { 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; }