fix errors related to sterilization of addresses between rpc and cashier

This commit is contained in:
ghassmo
2021-09-10 19:01:46 +03:00
parent fecbb7894b
commit 44a2d95370
5 changed files with 133 additions and 73 deletions

View File

@@ -2,6 +2,7 @@ use std::path::PathBuf;
use serde_json::json;
use drk::serial::serialize;
use drk::cli::{Config, DrkCli, DrkConfig};
use drk::rpc::jsonrpc;
use drk::rpc::jsonrpc::JsonResult;
@@ -86,11 +87,13 @@ impl Drk {
}
pub async fn transfer(&self, address: String, amount: f64) -> Result<()> {
let address = serialize(&address);
let r = jsonrpc::request(json!("transfer"), json!([address, amount]));
Ok(self.request("transfer", r).await?)
}
pub async fn withdraw(&self, address: String, amount: f64) -> Result<()> {
let address = serialize(&address);
let r = jsonrpc::request(json!("withdraw"), json!([address, amount]));
Ok(self.request("withdraw", r).await?)
}

View File

@@ -10,7 +10,7 @@ use crate::crypto::{
use crate::rpc::adapters::{RpcClient, RpcClientAdapter};
use crate::rpc::jsonserver;
use crate::serial::Encodable;
use crate::serial::{deserialize, Decodable};
use crate::serial::Decodable;
use crate::service::{CashierClient, GatewayClient, GatewaySlabsSubscriber};
use crate::state::{state_transition, ProgramState, StateUpdate};
use crate::wallet::{CashierDbPtr, WalletPtr};
@@ -124,19 +124,17 @@ impl Client {
Ok(())
}
pub async fn transfer(self: &mut Self, pub_key: String, amount: f64) -> Result<()> {
let address = bs58::decode(pub_key.clone())
.into_vec()
.map_err(|_| ClientFailed::UnvalidAddress(pub_key.clone()))?;
let address: jubjub::SubgroupPoint =
deserialize(&address).map_err(|_| ClientFailed::UnvalidAddress(pub_key))?;
pub async fn transfer(
self: &mut Self,
pub_key: jubjub::SubgroupPoint,
amount: f64,
) -> Result<()> {
if amount <= 0.0 {
return Err(ClientFailed::UnvalidAmount(amount as u64).into());
}
self.send(address.clone(), amount.clone() as u64, 1, false)
self.send(pub_key.clone(), amount.clone() as u64, 1, false)
.await?;
Ok(())

View File

@@ -1,5 +1,5 @@
use crate::client::{Client, ClientFailed};
use crate::serial::{deserialize, serialize};
use crate::serial::{deserialize, serialize, Decodable};
use crate::service::CashierClient;
use crate::{Error, Result};
@@ -31,11 +31,11 @@ pub trait RpcClient {
/// transfer
#[rpc(name = "transfer")]
fn transfer(&self, pub_key: String, amount: f64) -> BoxFuture<Result<String>>;
fn transfer(&self, pub_key: Vec<u8>, amount: f64) -> BoxFuture<Result<String>>;
/// withdraw
#[rpc(name = "withdraw")]
fn withdraw(&self, pub_key: String, amount: f64) -> BoxFuture<Result<String>>;
fn withdraw(&self, pub_key: Vec<u8>, amount: f64) -> BoxFuture<Result<String>>;
/// deposit
#[rpc(name = "deposit")]
@@ -75,9 +75,17 @@ impl RpcClientAdapter {
async fn transfer_process(
client: Arc<Mutex<Client>>,
address: String,
address: Vec<u8>,
amount: f64,
) -> Result<String> {
let pub_key: String = deserialize(&address)?;
let address = bs58::decode(pub_key.clone())
.into_vec()
.map_err(|_| ClientFailed::UnvalidAddress(pub_key.clone()))?;
let address: jubjub::SubgroupPoint =
deserialize(&address).map_err(|_| ClientFailed::UnvalidAddress(pub_key))?;
client
.lock()
.await
@@ -90,7 +98,7 @@ impl RpcClientAdapter {
async fn withdraw_process(
client: Arc<Mutex<Client>>,
cashier_client: Arc<Mutex<CashierClient>>,
address: String,
address: Vec<u8>,
amount: f64,
) -> Result<String> {
let drk_public = cashier_client
@@ -101,8 +109,6 @@ impl RpcClientAdapter {
.map_err(|err| ClientFailed::from(err))?;
if let Some(drk_addr) = drk_public {
let drk_addr = bs58::encode(serialize(&drk_addr)).into_string();
client
.lock()
.await
@@ -118,10 +124,13 @@ impl RpcClientAdapter {
}
}
async fn deposit_process(
async fn deposit_process<T>(
client: Arc<Mutex<Client>>,
cashier_client: Arc<Mutex<CashierClient>>,
) -> Result<String> {
) -> Result<String>
where
T: Decodable + ToString,
{
let deposit_addr = client.lock().await.state.wallet.get_public_keys()?[0];
let coin_public = cashier_client
.lock()
@@ -131,7 +140,8 @@ impl RpcClientAdapter {
.map_err(|err| ClientFailed::from(err))?;
if let Some(coin_addr) = coin_public {
return Ok(deserialize(&coin_addr)?);
let pub_k: T = deserialize(&coin_addr)?;
return Ok(pub_k.to_string());
} else {
return Err(Error::from(ClientFailed::UnableToGetDepositAddress));
}
@@ -159,12 +169,12 @@ impl RpcClient for RpcClientAdapter {
Self::key_gen_process(self.client.clone()).boxed()
}
fn transfer(&self, pub_key: String, amount: f64) -> BoxFuture<Result<String>> {
fn transfer(&self, pub_key: Vec<u8>, amount: f64) -> BoxFuture<Result<String>> {
debug!(target: "RPC USER ADAPTER", "transfer() [START]");
Self::transfer_process(self.client.clone(), pub_key, amount).boxed()
}
fn withdraw(&self, pub_key: String, amount: f64) -> BoxFuture<Result<String>> {
fn withdraw(&self, pub_key: Vec<u8>, amount: f64) -> BoxFuture<Result<String>> {
debug!(target: "RPC USER ADAPTER", "withdraw() [START]");
Self::withdraw_process(
self.client.clone(),
@@ -177,6 +187,11 @@ impl RpcClient for RpcClientAdapter {
fn deposit(&self) -> BoxFuture<Result<String>> {
debug!(target: "RPC USER ADAPTER", "deposit() [START]");
Self::deposit_process(self.client.clone(), self.cashier_client.clone()).boxed()
#[cfg(feature = "default")]
Self::deposit_process::<bitcoin::PublicKey>(
self.client.clone(),
self.cashier_client.clone(),
)
.boxed()
}
}

View File

@@ -1,7 +1,8 @@
use crate::serial::{Decodable, Encodable};
use crate::Result;
use super::bridge::CoinClient;
use crate::serial::{Decodable, Encodable, serialize};
use crate::Result;
use async_trait::async_trait;
use bitcoin::blockdata::script::Script;
use bitcoin::network::constants::Network;
use bitcoin::util::address::Address;
@@ -11,7 +12,6 @@ use log::*;
use rand::distributions::Alphanumeric;
use rand::{thread_rng, Rng};
use secp256k1::key::SecretKey;
use async_trait::async_trait;
use async_std::sync::Arc;
use std::str::FromStr;
@@ -132,50 +132,6 @@ impl BitcoinKeys {
}
}
impl Encodable for bitcoin::Address {
fn encode<S: std::io::Write>(&self, s: S) -> Result<usize> {
let addr = self.to_string();
let len = addr.encode(s)?;
Ok(len)
}
}
impl Decodable for bitcoin::Address {
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| crate::Error::from(BtcFailed::from(err)))?;
Ok(addr)
}
}
#[derive(Debug)]
pub enum BtcFailed {
NotEnoughValue(u64),
BadBTCAddress(String),
ElectrumError(String),
BtcError(String),
}
impl std::error::Error for BtcFailed {}
impl std::fmt::Display for BtcFailed {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
BtcFailed::NotEnoughValue(i) => {
write!(f, "There is no enough value {}", i)
}
BtcFailed::BadBTCAddress(ref err) => {
write!(f, "Unable to create Electrum Client: {}", err)
}
BtcFailed::ElectrumError(ref err) => write!(f, "could not parse BTC address: {}", err),
BtcFailed::BtcError(i) => {
write!(f, "BtcFailed: {}", i)
}
}
}
}
pub struct BtcClient {
client: Arc<ElectrumClient>,
@@ -209,14 +165,97 @@ impl CoinClient for BtcClient {
//let _script = btc_keys.get_script();
//
Ok((btc_priv.to_bytes(), btc_pub.to_bytes()))
Ok((serialize(&btc_priv.to_bytes()), serialize(&btc_pub.to_bytes())))
}
async fn send(&self, _address: Vec<u8>, _amount: u64) -> Result<()> {
// TODO
Ok(())
}
}
impl Encodable for bitcoin::Address {
fn encode<S: std::io::Write>(&self, s: S) -> Result<usize> {
let addr = self.to_string();
let len = addr.encode(s)?;
Ok(len)
}
}
impl Decodable for bitcoin::Address {
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| crate::Error::from(BtcFailed::from(err)))?;
Ok(addr)
}
}
impl Encodable for bitcoin::PublicKey {
fn encode<S: std::io::Write>(&self, s: S) -> Result<usize> {
let key = self.to_bytes();
let len = key.encode(s)?;
Ok(len)
}
}
impl Decodable for bitcoin::PublicKey {
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| crate::Error::from(BtcFailed::from(err)))?;
Ok(key)
}
}
impl Encodable for bitcoin::PrivateKey {
fn encode<S: std::io::Write>(&self, s: S) -> Result<usize> {
let key = self.to_bytes();
let len = key.encode(s)?;
Ok(len)
}
}
impl Decodable for bitcoin::PrivateKey {
fn decode<D: std::io::Read>(mut d: D) -> Result<Self> {
let key: Vec<u8> = Decodable::decode(&mut d)?;
let key = bitcoin::PrivateKey::from_slice(&key, Network::Testnet)
.map_err(|err| crate::Error::from(BtcFailed::from(err)))?;
Ok(key)
}
}
#[derive(Debug)]
pub enum BtcFailed {
NotEnoughValue(u64),
BadBTCAddress(String),
ElectrumError(String),
BtcError(String),
DecodeAndEncodeError(String),
}
impl std::error::Error for BtcFailed {}
impl std::fmt::Display for BtcFailed {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
BtcFailed::NotEnoughValue(i) => {
write!(f, "There is no enough value {}", i)
}
BtcFailed::BadBTCAddress(ref err) => {
write!(f, "Unable to create Electrum Client: {}", err)
}
BtcFailed::ElectrumError(ref err) => write!(f, "could not parse BTC address: {}", err),
BtcFailed::DecodeAndEncodeError(ref err) => write!(f, "Decode and decode keys error: {}", err),
BtcFailed::BtcError(i) => {
write!(f, "BtcFailed: {}", i)
}
}
}
}
impl From<crate::error::Error> for BtcFailed {
fn from(err: crate::error::Error) -> BtcFailed {
BtcFailed::BtcError(err.to_string())
@@ -234,6 +273,12 @@ impl From<electrum_client::Error> for BtcFailed {
}
}
impl From<bitcoin::util::key::Error> for BtcFailed {
fn from(err: bitcoin::util::key::Error) -> BtcFailed {
BtcFailed::DecodeAndEncodeError(err.to_string())
}
}
pub type BtcResult<T> = std::result::Result<T, BtcFailed>;
#[cfg(test)]

View File

@@ -238,14 +238,13 @@ impl CashierService {
}
1 => {
debug!(target: "CASHIER DAEMON", "Received withdraw request");
let (asset_id, coin_address): (u64, String) = deserialize(&request.get_payload())?;
let (asset_id, coin_address): (u64, Vec<u8>) = deserialize(&request.get_payload())?;
//let btc_address: String = deserialize(&btc_address)?;
//let btc_address = bitcoin::util::address::Address::from_str(&btc_address)
// .map_err(|err| crate::Error::from(super::BtcFailed::from(err)))?;
//
let asset_id = serialize(&asset_id);
let coin_address = serialize(&coin_address);
let cashier_public: jubjub::SubgroupPoint;
@@ -301,7 +300,7 @@ impl CashierClient {
pub async fn withdraw(
&mut self,
asset_id: u64,
coin_address: String,
coin_address: Vec<u8>,
) -> Result<Option<jubjub::SubgroupPoint>> {
let handle_error = Arc::new(handle_error);
let rep = self