continue works on issue #35

This commit is contained in:
ghassmo
2022-01-11 17:26:17 +04:00
parent a3fe19f0d1
commit b0fc31ead2
7 changed files with 156 additions and 94 deletions

45
bin/cashier/src/error.rs Normal file
View File

@@ -0,0 +1,45 @@
pub type Result<T> = std::result::Result<T, Error>;
#[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<crate::service::SolFailed> for Error {
fn from(err: crate::service::SolFailed) -> Error {
Error::SolFailed(err.to_string())
}
}
impl From<darkfi::Error> for Error {
fn from(err: darkfi::Error) -> Error {
Error::ClientFailed(err.to_string())
}
}
impl<T> From<async_channel::SendError<T>> for Error {
fn from(_err: async_channel::SendError<T>) -> Error {
Error::AsyncChannelSenderError
}
}

View File

@@ -1 +1,2 @@
pub mod error;
pub mod service;

View File

@@ -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;

View File

@@ -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::<SecPublicKey>(&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<S: std::io::Write>(&self, s: S) -> Result<usize> {
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<S: std::io::Write>(&self, s: S) -> Result<usize> {
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<D: std::io::Read>(mut d: D) -> Result<Self> {
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<S: std::io::Write>(&self, s: S) -> Result<usize> {
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<D: std::io::Read>(mut d: D) -> Result<Self> {
let key: Vec<u8> = 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<S: std::io::Write>(&self, s: S) -> Result<usize> {
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<D: std::io::Read>(mut d: D) -> Result<Self> {
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<S: std::io::Write>(&self, s: S) -> Result<usize> {
let key: Vec<u8> = self.serialize().to_vec();
let key: Vec<u8> = self.0.serialize().to_vec();
let len = key.encode(s)?;
Ok(len)
}
}
impl Decodable for secp256k1::key::PublicKey {
impl Decodable for SecPublicKey {
fn decode<D: std::io::Read>(mut d: D) -> Result<Self> {
let key: Vec<u8> = 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<anyhow::Error> for BtcFailed {
}
}
impl From<BtcFailed> for Error {
fn from(error: BtcFailed) -> Self {
Error::CashierError(error.to_string())
}
}
pub type BtcResult<T> = std::result::Result<T, BtcFailed>;
#[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::<BtcAddress>(&btc_ser)?.0;
assert_eq!(btc_addr.0, btc_dser);
Ok(())
}

View File

@@ -546,6 +546,12 @@ impl From<serde_json::Error> for EthFailed {
}
}
impl From<EthFailed> for Error {
fn from(error: EthFailed) -> Self {
Error::CashierError(error.to_string())
}
}
pub type EthResult<T> = std::result::Result<T, EthFailed>;
#[allow(unused_imports)]

View File

@@ -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<Arc<Self>> {
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::<SolKeypair>(&main_keypairs[main_keypairs.len() - 1].secret_key)?;
}
} else {
let keypair_str = load_keypair_to_str(expand_path(keypair_path)?)?;
let keypair_bytes: Vec<u8> = 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<String>,
executor: Arc<Executor<'_>>,
) -> Result<TokenSubscribtion> {
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<String>,
executor: Arc<Executor<'_>>,
) -> Result<String> {
let keypair: Keypair = deserialize(&private_key)?;
let keypair: Keypair = deserialize::<SolKeypair>(&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::<SolPubkey>(&address)?.0;
let mut decimals = 9;
@@ -582,41 +584,38 @@ pub fn sign_and_send_transaction(
}
}
impl Encodable for Keypair {
fn encode<S: std::io::Write>(&self, s: S) -> Result<usize> {
let key: Vec<u8> = self.to_bytes().to_vec();
impl Encodable for SolKeypair {
fn encode<S: std::io::Write>(&self, s: S) -> darkfi::Result<usize> {
let key: Vec<u8> = self.0.to_bytes().to_vec();
let len = key.encode(s)?;
Ok(len)
}
}
impl Decodable for Keypair {
fn decode<D: std::io::Read>(mut d: D) -> Result<Self> {
impl Decodable for SolKeypair {
fn decode<D: std::io::Read>(mut d: D) -> darkfi::Result<Self> {
let key: Vec<u8> = 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<S: std::io::Write>(&self, s: S) -> Result<usize> {
let key = self.to_string();
impl Encodable for SolPubkey {
fn encode<S: std::io::Write>(&self, s: S) -> darkfi::Result<usize> {
let key = self.0.to_string();
let len = key.encode(s)?;
Ok(len)
}
}
impl Decodable for Pubkey {
fn decode<D: std::io::Read>(mut d: D) -> Result<Self> {
impl Decodable for SolPubkey {
fn decode<D: std::io::Read>(mut d: D) -> darkfi::Result<Self> {
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<SolFailed> for Error {
fn from(error: SolFailed) -> Self {
Error::CashierError(error.to_string())
}
}
pub type SolResult<T> = std::result::Result<T, SolFailed>;

View File

@@ -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<tungstenite::Error> for Error {
}
}
#[cfg(feature = "sol")]
impl From<crate::service::SolFailed> for Error {
fn from(err: crate::service::SolFailed) -> Error {
Error::SolFailed(err.to_string())
}
}
impl From<halo2::plonk::Error> for Error {
fn from(err: halo2::plonk::Error) -> Error {
Error::PlonkError(format!("{:?}", err))