From 020d246b8f7e7052a0f58c21b8256a21351dfc2a Mon Sep 17 00:00:00 2001 From: Luke Parker Date: Fri, 24 Jun 2022 19:53:41 -0400 Subject: [PATCH] Reorganize processor's handling of coins --- processor/src/coin/mod.rs | 84 +++++++++++++++++++++ processor/src/{coins => coin}/monero.rs | 2 +- processor/src/coins/mod.rs | 1 - processor/src/lib.rs | 98 +++---------------------- processor/src/tests/mod.rs | 6 +- processor/src/wallet.rs | 2 +- 6 files changed, 99 insertions(+), 94 deletions(-) create mode 100644 processor/src/coin/mod.rs rename processor/src/{coins => coin}/monero.rs (98%) delete mode 100644 processor/src/coins/mod.rs diff --git a/processor/src/coin/mod.rs b/processor/src/coin/mod.rs new file mode 100644 index 00000000..fed65c26 --- /dev/null +++ b/processor/src/coin/mod.rs @@ -0,0 +1,84 @@ +use std::{marker::Send, sync::Arc}; + +use async_trait::async_trait; +use thiserror::Error; + +use transcript::RecommendedTranscript; +use frost::{curve::Curve, MultisigKeys, sign::PreprocessMachine}; + +pub mod monero; +pub use self::monero::Monero; + +#[derive(Clone, Error, Debug)] +pub enum CoinError { + #[error("failed to connect to coin daemon")] + ConnectionError +} + +pub trait Output: Sized + Clone { + type Id: AsRef<[u8]>; + + fn id(&self) -> Self::Id; + fn amount(&self) -> u64; + + fn serialize(&self) -> Vec; + fn deserialize(reader: &mut R) -> std::io::Result; +} + +#[async_trait] +pub trait Coin { + type Curve: Curve; + + type Fee: Copy; + type Transaction; + type Block; + + type Output: Output; + type SignableTransaction; + type TransactionMachine: PreprocessMachine; + + type Address: Send; + + const ID: &'static [u8]; + const CONFIRMATIONS: usize; + const MAX_INPUTS: usize; + const MAX_OUTPUTS: usize; // TODO: Decide if this includes change or not + + // Doesn't have to take self, enables some level of caching which is pleasant + fn address(&self, key: ::G) -> Self::Address; + + async fn get_height(&self) -> Result; + async fn get_block(&self, height: usize) -> Result; + async fn get_outputs( + &self, + block: &Self::Block, + key: ::G + ) -> Vec; + + async fn prepare_send( + &self, + keys: Arc>, + transcript: RecommendedTranscript, + height: usize, + inputs: Vec, + payments: &[(Self::Address, u64)], + fee: Self::Fee + ) -> Result; + + async fn attempt_send( + &self, + transaction: Self::SignableTransaction, + included: &[u16] + ) -> Result; + + async fn publish_transaction( + &self, + tx: &Self::Transaction + ) -> Result<(Vec, Vec<::Id>), CoinError>; + + #[cfg(test)] + async fn mine_block(&self, address: Self::Address); + + #[cfg(test)] + async fn test_send(&self, key: Self::Address); +} diff --git a/processor/src/coins/monero.rs b/processor/src/coin/monero.rs similarity index 98% rename from processor/src/coins/monero.rs rename to processor/src/coin/monero.rs index 06dc2f75..80d19a89 100644 --- a/processor/src/coins/monero.rs +++ b/processor/src/coin/monero.rs @@ -15,7 +15,7 @@ use monero_serai::{ wallet::{Fee, SpendableOutput, SignableTransaction as MSignableTransaction, TransactionMachine} }; -use crate::{CoinError, Output as OutputTrait, Coin, view_key}; +use crate::{coin::{CoinError, Output as OutputTrait, Coin}, view_key}; #[derive(Clone, Debug)] pub struct Output(SpendableOutput); diff --git a/processor/src/coins/mod.rs b/processor/src/coins/mod.rs deleted file mode 100644 index 3c43a86a..00000000 --- a/processor/src/coins/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod monero; diff --git a/processor/src/lib.rs b/processor/src/lib.rs index caf92d2f..fe427dfe 100644 --- a/processor/src/lib.rs +++ b/processor/src/lib.rs @@ -1,107 +1,33 @@ -use std::{marker::Send, sync::Arc, collections::HashMap}; +use std::{marker::Send, collections::HashMap}; use async_trait::async_trait; use thiserror::Error; -use transcript::RecommendedTranscript; -use frost::{curve::Curve, FrostError, MultisigKeys, sign::PreprocessMachine}; +use frost::{curve::Curve, FrostError}; -mod coins; +mod coin; +use coin::{CoinError, Coin}; mod wallet; #[cfg(test)] mod tests; -#[derive(Clone, Error, Debug)] -pub enum CoinError { - #[error("failed to connect to coin daemon")] - ConnectionError -} - #[derive(Clone, Error, Debug)] pub enum NetworkError {} -#[derive(Clone, Error, Debug)] -pub enum SignError { - #[error("coin had an error {0}")] - CoinError(CoinError), - #[error("network had an error {0}")] - NetworkError(NetworkError), - #[error("FROST had an error {0}")] - FrostError(FrostError) -} - #[async_trait] pub trait Network: Send { async fn round(&mut self, data: Vec) -> Result>, NetworkError>; } -pub trait Output: Sized + Clone { - type Id: AsRef<[u8]>; - - fn id(&self) -> Self::Id; - fn amount(&self) -> u64; - - fn serialize(&self) -> Vec; - fn deserialize(reader: &mut R) -> std::io::Result; -} - -#[async_trait] -pub trait Coin { - type Curve: Curve; - - type Fee: Copy; - type Transaction; - type Block; - - type Output: Output; - type SignableTransaction; - type TransactionMachine: PreprocessMachine; - - type Address: Send; - - const ID: &'static [u8]; - const CONFIRMATIONS: usize; - const MAX_INPUTS: usize; - const MAX_OUTPUTS: usize; // TODO: Decide if this includes change or not - - // Doesn't have to take self, enables some level of caching which is pleasant - fn address(&self, key: ::G) -> Self::Address; - - async fn get_height(&self) -> Result; - async fn get_block(&self, height: usize) -> Result; - async fn get_outputs( - &self, - block: &Self::Block, - key: ::G - ) -> Vec; - - async fn prepare_send( - &self, - keys: Arc>, - transcript: RecommendedTranscript, - height: usize, - inputs: Vec, - payments: &[(Self::Address, u64)], - fee: Self::Fee - ) -> Result; - - async fn attempt_send( - &self, - transaction: Self::SignableTransaction, - included: &[u16] - ) -> Result; - - async fn publish_transaction( - &self, - tx: &Self::Transaction - ) -> Result<(Vec, Vec<::Id>), CoinError>; - - #[cfg(test)] - async fn mine_block(&self, address: Self::Address); - - #[cfg(test)] - async fn test_send(&self, key: Self::Address); +#[derive(Clone, Error, Debug)] +pub enum SignError { + #[error("FROST had an error {0}")] + FrostError(FrostError), + #[error("coin had an error {0}")] + CoinError(CoinError), + #[error("network had an error {0}")] + NetworkError(NetworkError) } // Generate a static view key for a given chain in a globally consistent manner diff --git a/processor/src/tests/mod.rs b/processor/src/tests/mod.rs index eacb8223..728b0668 100644 --- a/processor/src/tests/mod.rs +++ b/processor/src/tests/mod.rs @@ -8,11 +8,7 @@ use group::Group; use frost::curve::Curve; -use crate::{ - NetworkError, Network, - Coin, coins::monero::Monero, - wallet::{WalletKeys, MemCoinDb, Wallet} -}; +use crate::{NetworkError, Network, coin::{Coin, Monero}, wallet::{WalletKeys, MemCoinDb, Wallet}}; #[derive(Clone)] struct LocalNetwork { diff --git a/processor/src/wallet.rs b/processor/src/wallet.rs index 0680ea53..6789cb8f 100644 --- a/processor/src/wallet.rs +++ b/processor/src/wallet.rs @@ -6,7 +6,7 @@ use transcript::{Transcript, RecommendedTranscript}; use frost::{curve::Curve, MultisigKeys, sign::{PreprocessMachine, SignMachine, SignatureMachine}}; -use crate::{CoinError, SignError, Output, Coin, Network}; +use crate::{coin::{CoinError, Output, Coin}, SignError, Network}; pub struct WalletKeys { keys: MultisigKeys,