diff --git a/bin/cashier/src/error.rs b/bin/cashier/src/error.rs new file mode 100644 index 000000000..e8411a155 --- /dev/null +++ b/bin/cashier/src/error.rs @@ -0,0 +1,45 @@ +pub type Result = std::result::Result; + +#[derive(Debug, Clone, thiserror::Error)] +pub enum Error { + /// Service + #[error("Services Error: `{0}`")] + ServicesError(&'static str), + #[error("Client failed: `{0}`")] + ClientFailed(String), + #[cfg(feature = "btc")] + #[error(transparent)] + BtcFailed(#[from] crate::service::BtcFailed), + #[cfg(feature = "sol")] + #[error("Sol client failed: `{0}`")] + SolFailed(String), + #[cfg(feature = "eth")] + #[error(transparent)] + EthFailed(#[from] crate::service::EthFailed), + #[error("BridgeError Error: `{0}`")] + BridgeError(String), + + #[error("Async_channel sender error")] + AsyncChannelSenderError, + #[error(transparent)] + AsyncChannelReceiverError(#[from] async_channel::RecvError), +} + +#[cfg(feature = "sol")] +impl From for Error { + fn from(err: crate::service::SolFailed) -> Error { + Error::SolFailed(err.to_string()) + } +} + +impl From for Error { + fn from(err: darkfi::Error) -> Error { + Error::ClientFailed(err.to_string()) + } +} + +impl From> for Error { + fn from(_err: async_channel::SendError) -> Error { + Error::AsyncChannelSenderError + } +} diff --git a/bin/cashier/src/lib.rs b/bin/cashier/src/lib.rs index 1f278a4d5..03141d739 100644 --- a/bin/cashier/src/lib.rs +++ b/bin/cashier/src/lib.rs @@ -1 +1,2 @@ +pub mod error; pub mod service; diff --git a/bin/cashier/src/main.rs b/bin/cashier/src/main.rs index 1fd0cd517..b6acc17f9 100644 --- a/bin/cashier/src/main.rs +++ b/bin/cashier/src/main.rs @@ -43,10 +43,10 @@ use cashier::service::{bridge, bridge::Bridge}; fn handle_bridge_error(error_code: u32) -> Result<()> { match error_code { - 1 => Err(Error::BridgeError("Not Supported Client".into())), - 2 => Err(Error::BridgeError("Unable to watch the deposit address".into())), - 3 => Err(Error::BridgeError("Unable to send the token".into())), - _ => Err(Error::BridgeError("Unknown error_code".into())), + 1 => Err(Error::CashierError("Not Supported Client".into())), + 2 => Err(Error::CashierError("Unable to watch the deposit address".into())), + 3 => Err(Error::CashierError("Unable to send the token".into())), + _ => Err(Error::CashierError("Unknown error_code".into())), } } @@ -123,7 +123,7 @@ impl Cashierd { #[cfg(feature = "sol")] NetworkName::Solana => { debug!(target: "CASHIER DAEMON", "Adding solana network"); - use drk::service::SolClient; + use cashier::service::SolClient; let _bridge = self.bridge.clone(); @@ -141,7 +141,7 @@ impl Cashierd { NetworkName::Ethereum => { debug!(target: "CASHIER DAEMON", "Adding ethereum network"); - use drk::service::EthClient; + use cashier::service::EthClient; let _bridge = self.bridge.clone(); @@ -161,7 +161,7 @@ impl Cashierd { #[cfg(feature = "btc")] NetworkName::Bitcoin => { debug!(target: "CASHIER DAEMON", "Adding bitcoin network"); - use drk::service::btc::BtcClient; + use cashier::service::btc::BtcClient; let _bridge = self.bridge.clone(); @@ -292,7 +292,9 @@ impl Cashierd { .await?; } _ => { - return Err(Error::BridgeError("Receive unknown value from Subscription".into())) + return Err(Error::CashierError( + "Receive unknown value from Subscription".into(), + )) } } } @@ -304,7 +306,7 @@ impl Cashierd { match network { #[cfg(feature = "sol")] NetworkName::Solana => { - use drk::service::sol::SOL_NATIVE_TOKEN_ID; + use cashier::service::sol::SOL_NATIVE_TOKEN_ID; if _token_id != SOL_NATIVE_TOKEN_ID { return Ok(Some(_token_id.to_string())) } @@ -312,7 +314,7 @@ impl Cashierd { } #[cfg(feature = "eth")] NetworkName::Ethereum => { - use drk::service::eth::ETH_NATIVE_TOKEN_ID; + use cashier::service::eth::ETH_NATIVE_TOKEN_ID; if _token_id != ETH_NATIVE_TOKEN_ID { return Ok(Some(_token_id.to_string())) } @@ -438,7 +440,7 @@ impl Cashierd { Ok(token_key.public_key) } bridge::BridgeResponsePayload::Address(token_pub) => Ok(token_pub), - _ => Err(Error::BridgeError("Receive unknown value from Subscription".into())), + _ => Err(Error::CashierError("Receive unknown value from Subscription".into())), } } .await; diff --git a/bin/cashier/src/service/btc.rs b/bin/cashier/src/service/btc.rs index 0463c9901..5fb3f7796 100644 --- a/bin/cashier/src/service/btc.rs +++ b/bin/cashier/src/service/btc.rs @@ -339,7 +339,7 @@ impl BtcClient { .put_main_keys( &TokenKey { secret_key: serialize(&main_keypair), - public_key: serialize(&main_keypair.pubkey()), + public_key: serialize(&SecPublicKey(main_keypair.pubkey())), }, &NetworkName::Bitcoin, ) @@ -518,12 +518,13 @@ impl BtcClient { )?; let _txid = signed_tx.txid(); + let signed_tx = BtcTransaction(signed_tx); let _serialized_tx = serialize(&signed_tx); info!(target: "BTC BRIDGE", "Signed tx: {:?}", - serialize_hex(&signed_tx)); + serialize_hex(&signed_tx.0)); - let txid = electrum.transaction_broadcast_raw(&signed_tx.serialize().to_vec())?; + let txid = electrum.transaction_broadcast_raw(&signed_tx.0.serialize().to_vec())?; info!(target: "BTC BRIDGE", "Sent {} satoshi to main wallet, txid: {}", amount, txid); Ok(()) @@ -595,7 +596,7 @@ impl NetworkClient for BtcClient { ) -> Result<()> { // address is not a btc address, so derive the btc address let electrum = &self.client.lock().await.electrum; - let public_key = deserialize(&address)?; + let public_key = deserialize::(&address)?.0; let script_pubkey = Account::derive_btc_script_pubkey(public_key, self.network); let main_script_pubkey = &self.main_account.script_pubkey; @@ -751,76 +752,84 @@ impl fmt::Display for ScriptStatus { } } } -impl Encodable for bitcoin::Transaction { + +// Aliases +pub struct BtcTransaction(bitcoin::Transaction); +pub struct BtcAddress(bitcoin::Address); +pub struct BtcPublicKey(bitcoin::PublicKey); +pub struct BtcPrivateKey(bitcoin::PrivateKey); +pub struct SecPublicKey(secp256k1::key::PublicKey); + +impl Encodable for BtcTransaction { fn encode(&self, s: S) -> Result { - let tx = self.serialize(); + let tx = self.0.serialize(); let len = tx.encode(s)?; Ok(len) } } -impl Encodable for bitcoin::Address { +impl Encodable for BtcAddress { fn encode(&self, s: S) -> Result { - let addr = self.to_string(); + let addr = self.0.to_string(); let len = addr.encode(s)?; Ok(len) } } -impl Decodable for bitcoin::Address { +impl Decodable for BtcAddress { fn decode(mut d: D) -> Result { let addr: String = Decodable::decode(&mut d)?; let addr = bitcoin::Address::from_str(&addr) .map_err(|err| darkfi::Error::from(BtcFailed::from(err)))?; - Ok(addr) + Ok(BtcAddress(addr)) } } -impl Encodable for bitcoin::PublicKey { +impl Encodable for BtcPublicKey { fn encode(&self, s: S) -> Result { - let key = self.to_bytes(); + let key = self.0.to_bytes(); let len = key.encode(s)?; Ok(len) } } -impl Decodable for bitcoin::PublicKey { +impl Decodable for BtcPublicKey { fn decode(mut d: D) -> Result { let key: Vec = Decodable::decode(&mut d)?; let key = bitcoin::PublicKey::from_slice(&key) .map_err(|err| darkfi::Error::from(BtcFailed::from(err)))?; - Ok(key) + Ok(BtcPublicKey(key)) } } -impl Encodable for bitcoin::PrivateKey { +impl Encodable for BtcPrivateKey { fn encode(&self, s: S) -> Result { - let key: String = self.to_string(); + let key: String = self.0.to_string(); let len = key.encode(s)?; Ok(len) } } -impl Decodable for bitcoin::PrivateKey { +impl Decodable for BtcPrivateKey { fn decode(mut d: D) -> Result { let key: String = Decodable::decode(&mut d)?; let key = bitcoin::PrivateKey::from_str(&key) .map_err(|err| darkfi::Error::from(BtcFailed::from(err)))?; - Ok(key) + Ok(BtcPrivateKey(key)) } } -impl Encodable for secp256k1::key::PublicKey { +impl Encodable for SecPublicKey { fn encode(&self, s: S) -> Result { - let key: Vec = self.serialize().to_vec(); + let key: Vec = self.0.serialize().to_vec(); let len = key.encode(s)?; Ok(len) } } -impl Decodable for secp256k1::key::PublicKey { +impl Decodable for SecPublicKey { fn decode(mut d: D) -> Result { let key: Vec = Decodable::decode(&mut d)?; let key = secp256k1::key::PublicKey::from_slice(&key) .map_err(|err| darkfi::Error::from(BtcFailed::from(err)))?; - Ok(key) + Ok(SecPublicKey(key)) } } // TODO: add secret + public keys together for Encodable @@ -892,6 +901,12 @@ impl From for BtcFailed { } } +impl From for Error { + fn from(error: BtcFailed) -> Self { + Error::CashierError(error.to_string()) + } +} + pub type BtcResult = std::result::Result; #[cfg(test)] @@ -903,7 +918,7 @@ mod tests { use darkfi::serial::{deserialize, serialize}; - use super::Keypair; + use super::*; const KEYPAIR_LENGTH: usize = SECRET_KEY_SIZE + PUBLIC_KEY_SIZE; @@ -912,10 +927,12 @@ mod tests { let btc_addr = bitcoin::Address::from_str(&String::from("mxVFsFW5N4mu1HPkxPttorvocvzeZ7KZyk"))?; - let btc_ser = serialize(&btc_addr); - let btc_dser = deserialize(&btc_ser)?; + let btc_addr = BtcAddress(btc_addr); - assert_eq!(btc_addr, btc_dser); + let btc_ser = serialize(&btc_addr); + let btc_dser = deserialize::(&btc_ser)?.0; + + assert_eq!(btc_addr.0, btc_dser); Ok(()) } diff --git a/bin/cashier/src/service/eth.rs b/bin/cashier/src/service/eth.rs index 6ec2a96e0..e4e944c3c 100644 --- a/bin/cashier/src/service/eth.rs +++ b/bin/cashier/src/service/eth.rs @@ -546,6 +546,12 @@ impl From for EthFailed { } } +impl From for Error { + fn from(error: EthFailed) -> Self { + Error::CashierError(error.to_string()) + } +} + pub type EthResult = std::result::Result; #[allow(unused_imports)] diff --git a/bin/cashier/src/service/sol.rs b/bin/cashier/src/service/sol.rs index 7595036b7..43104301d 100644 --- a/bin/cashier/src/service/sol.rs +++ b/bin/cashier/src/service/sol.rs @@ -12,9 +12,9 @@ use solana_client::{blockhash_query::BlockhashQuery, rpc_client::RpcClient}; use solana_sdk::{ native_token::{lamports_to_sol, sol_to_lamports}, program_pack::Pack, - pubkey::Pubkey as SolPubkey, + pubkey::Pubkey, signature::{Signature, Signer}, - signer::keypair::Keypair as SolKeypair, + signer::keypair::Keypair, system_instruction, transaction::Transaction, }; @@ -31,15 +31,14 @@ use darkfi::{ expand_path, generate_id2, load_keypair_to_str, parse::truncate, rpc::{jsonrpc, jsonrpc::JsonResult, websockets, websockets::WsStream}, - sleep, NetworkName, + sleep, Error, NetworkName, Result, }, - Error, Result, }; pub const SOL_NATIVE_TOKEN_ID: &str = "So11111111111111111111111111111111111111112"; -struct Keypair(SolKeypair); -struct Pubkey(SolPubkey); +struct SolKeypair(Keypair); +struct SolPubkey(Pubkey); #[derive(Serialize)] struct SubscribeParams { @@ -65,34 +64,37 @@ impl SolClient { ) -> Result> { let notify_channel = async_channel::unbounded(); - let main_keypair: Keypair; + let main_keypair: SolKeypair; let main_keypairs = cashier_wallet.get_main_keys(&NetworkName::Solana).await?; if keypair_path.is_empty() { if main_keypairs.is_empty() { - main_keypair = Keypair::new(); + main_keypair = SolKeypair(Keypair::new()); cashier_wallet .put_main_keys( &TokenKey { secret_key: serialize(&main_keypair), - public_key: serialize(&main_keypair.pubkey()), + public_key: serialize(&SolPubkey(main_keypair.0.pubkey())), }, &NetworkName::Solana, ) .await?; } else { - main_keypair = deserialize(&main_keypairs[main_keypairs.len() - 1].secret_key)?; + main_keypair = + deserialize::(&main_keypairs[main_keypairs.len() - 1].secret_key)?; } } else { let keypair_str = load_keypair_to_str(expand_path(keypair_path)?)?; let keypair_bytes: Vec = serde_json::from_str(&keypair_str)?; - main_keypair = Keypair::from_bytes(&keypair_bytes) - .map_err(|e| SolFailed::Signature(e.to_string()))?; + main_keypair = SolKeypair( + Keypair::from_bytes(&keypair_bytes) + .map_err(|e| SolFailed::Signature(e.to_string()))?, + ); } - info!(target: "SOL BRIDGE", "Main SOL wallet pubkey: {:?}", &main_keypair.pubkey()); + info!(target: "SOL BRIDGE", "Main SOL wallet pubkey: {:?}", &main_keypair.0.pubkey()); let (rpc_server, wss_server) = match network { "mainnet" => ("https://api.mainnet-beta.solana.com", "wss://api.devnet.solana.com"), @@ -103,7 +105,7 @@ impl SolClient { }; Ok(Arc::new(Self { - main_keypair, + main_keypair: main_keypair.0, subscriptions: Arc::new(Mutex::new(Vec::new())), notify_channel, rpc_server, @@ -439,9 +441,9 @@ impl NetworkClient for SolClient { mint_address: Option, executor: Arc>, ) -> Result { - let keypair = Keypair::new(); + let keypair = SolKeypair(Keypair::new()); - let public_key = keypair.pubkey().to_string(); + let public_key = keypair.0.pubkey().to_string(); let private_key = serialize(&keypair); let mint = self.check_mint_address(mint_address)?; @@ -455,7 +457,7 @@ impl NetworkClient for SolClient { executor .spawn(async move { - let result = self.handle_subscribe_request(keypair, drk_pub_key, mint).await; + let result = self.handle_subscribe_request(keypair.0, drk_pub_key, mint).await; if let Err(e) = result { error!(target: "SOL BRIDGE SUBSCRIPTION","{}", e.to_string()); } @@ -474,7 +476,7 @@ impl NetworkClient for SolClient { mint_address: Option, executor: Arc>, ) -> Result { - let keypair: Keypair = deserialize(&private_key)?; + let keypair: Keypair = deserialize::(&private_key)?.0; let public_key = keypair.pubkey().to_string(); @@ -511,7 +513,7 @@ impl NetworkClient for SolClient { debug!(target: "SOL BRIDGE", "start sending {} sol", lamports_to_sol(amount) ); let rpc = RpcClient::new(self.rpc_server.to_string()); - let address: Pubkey = deserialize(&address)?; + let address: Pubkey = deserialize::(&address)?.0; let mut decimals = 9; @@ -582,41 +584,38 @@ pub fn sign_and_send_transaction( } } -impl Encodable for Keypair { - fn encode(&self, s: S) -> Result { - let key: Vec = self.to_bytes().to_vec(); +impl Encodable for SolKeypair { + fn encode(&self, s: S) -> darkfi::Result { + let key: Vec = self.0.to_bytes().to_vec(); let len = key.encode(s)?; Ok(len) } } -impl Decodable for Keypair { - fn decode(mut d: D) -> Result { +impl Decodable for SolKeypair { + fn decode(mut d: D) -> darkfi::Result { let key: Vec = Decodable::decode(&mut d)?; - let key = Keypair::from_bytes(key.as_slice()).map_err(|_| { - darkfi::Error::from(SolFailed::DecodeAndEncodeError("load keypair from slice".into())) - })?; - Ok(key) + let key = Keypair::from_bytes(key.as_slice()) + .map_err(|_| darkfi::Error::DecodeError("SOL BRIDGE: load keypair from slice"))?; + Ok(SolKeypair(key)) } } -impl Encodable for Pubkey { - fn encode(&self, s: S) -> Result { - let key = self.to_string(); +impl Encodable for SolPubkey { + fn encode(&self, s: S) -> darkfi::Result { + let key = self.0.to_string(); let len = key.encode(s)?; Ok(len) } } -impl Decodable for Pubkey { - fn decode(mut d: D) -> Result { +impl Decodable for SolPubkey { + fn decode(mut d: D) -> darkfi::Result { let key: String = Decodable::decode(&mut d)?; let key = Pubkey::try_from(key.as_str()).map_err(|_| { - darkfi::Error::from(SolFailed::DecodeAndEncodeError( - "load public key from slice".into(), - )) + darkfi::Error::DecodeError("SOL BRIDGE: load public key from slice".into()) })?; - Ok(key) + Ok(SolPubkey(key)) } } @@ -652,4 +651,10 @@ pub enum SolFailed { Darkfi(#[from] darkfi::error::Error), } +impl From for Error { + fn from(error: SolFailed) -> Self { + Error::CashierError(error.to_string()) + } +} + pub type SolResult = std::result::Result; diff --git a/src/util/error.rs b/src/util/error.rs index bb140291b..2a74aad1a 100644 --- a/src/util/error.rs +++ b/src/util/error.rs @@ -17,6 +17,10 @@ pub enum Error { /// Parsing And Encode/Decode errors #[error("parse failed: `{0}`")] ParseFailed(&'static str), + #[error("decode failed: `{0}`")] + DecodeError(&'static str), + #[error("encode failed: `{0}`")] + EncodeError(&'static str), #[error(transparent)] ParseIntError(#[from] std::num::ParseIntError), #[error(transparent)] @@ -89,17 +93,8 @@ pub enum Error { ServicesError(&'static str), #[error("Client failed: `{0}`")] ClientFailed(String), - #[cfg(feature = "btc")] - #[error(transparent)] - BtcFailed(#[from] crate::service::BtcFailed), - #[cfg(feature = "sol")] - #[error("Sol client failed: `{0}`")] - SolFailed(String), - #[cfg(feature = "eth")] - #[error(transparent)] - EthFailed(#[from] crate::service::EthFailed), - #[error("BridgeError Error: `{0}`")] - BridgeError(String), + #[error("Cashier failed: `{0}`")] + CashierError(String), #[error("ZmqError: `{0}`")] ZmqError(String), @@ -144,8 +139,6 @@ pub enum Error { ConfigNotFound, #[error("No keypair file detected.")] KeypairPathNotFound, - #[error("No cashier public keys detected.")] - CashierKeysNotFound, #[error("SetLoggerError")] SetLoggerError, #[error("Async_channel sender error")] @@ -234,13 +227,6 @@ impl From for Error { } } -#[cfg(feature = "sol")] -impl From for Error { - fn from(err: crate::service::SolFailed) -> Error { - Error::SolFailed(err.to_string()) - } -} - impl From for Error { fn from(err: halo2::plonk::Error) -> Error { Error::PlonkError(format!("{:?}", err))