depolymerization

wire gateway for Bitcoin/Ethereum
Log | Files | Refs | Submodules | README | LICENSE

commit 5362e27f9b98beaae7e517639db1f848bee86e6d
parent 03d679a05cf5c057df1d86acc628e71304672c37
Author: Antoine A <>
Date:   Tue, 22 Feb 2022 17:24:23 +0100

instrumentation: new instrumentation test

Diffstat:
M.gitignore | 6++++--
MCargo.lock | 145++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
MCargo.toml | 1+
Mbtc-wire/src/bin/btc-wire-utils.rs | 2+-
Mbtc-wire/src/lib.rs | 15+++++++++++++++
Mbtc-wire/src/loops/worker.rs | 4++--
Mbtc-wire/src/main.rs | 17++---------------
Mbtc-wire/src/sql.rs | 2+-
Rbtc-wire/src/taler_util.rs -> btc-wire/src/taler_utils.rs | 0
Mcommon/src/config.rs | 2+-
Meth-wire/Cargo.toml | 2+-
Ainstrumentation/Cargo.toml | 21+++++++++++++++++++++
Ainstrumentation/src/main.rs | 284+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mmakefile | 1+
Mwire-gateway/Cargo.toml | 3++-
Mwire-gateway/src/main.rs | 18+++++++++++-------
16 files changed, 491 insertions(+), 32 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -4,4 +4,6 @@ log /docs/* !/docs/*.docx !/docs/*.tex -!/docs/media -\ No newline at end of file +!/docs/media +/tmp +taler.conf +\ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock @@ -188,6 +188,12 @@ dependencies = [ ] [[package]] +name = "chunked_transfer" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fff857943da45f546682664a79488be82e69e43c1a7a2307679ab9afb3a66d2e" + +[[package]] name = "clap" version = "2.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -257,6 +263,15 @@ dependencies = [ ] [[package]] +name = "crc32fast" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +dependencies = [ + "cfg-if", +] + +[[package]] name = "criterion" version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -545,6 +560,18 @@ dependencies = [ ] [[package]] +name = "flate2" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e6988e897c1c9c485f43b47a529cef42fde0547f9d8d41a7062518f1d8fc53f" +dependencies = [ + "cfg-if", + "crc32fast", + "libc", + "miniz_oxide 0.4.4", +] + +[[package]] name = "flexi_logger" version = "0.22.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -858,6 +885,18 @@ dependencies = [ ] [[package]] +name = "instrumentation" +version = "0.1.0" +dependencies = [ + "bitcoin", + "btc-wire", + "clap 3.1.1", + "common", + "eth-wire", + "ureq", +] + +[[package]] name = "itertools" version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -960,6 +999,16 @@ dependencies = [ [[package]] name = "miniz_oxide" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" +dependencies = [ + "adler", + "autocfg", +] + +[[package]] +name = "miniz_oxide" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2b29bd4bc3f33391105ebee3589c19197c4271e3e5a9ec9bfe8127eeff8f082" @@ -1037,6 +1086,12 @@ dependencies = [ ] [[package]] +name = "once_cell" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5" + +[[package]] name = "oorandom" version = "11.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1382,6 +1437,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" [[package]] +name = "ring" +version = "0.16.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" +dependencies = [ + "cc", + "libc", + "once_cell", + "spin", + "untrusted", + "web-sys", + "winapi", +] + +[[package]] name = "rust-ini" version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1407,6 +1477,18 @@ dependencies = [ ] [[package]] +name = "rustls" +version = "0.20.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fbfeb8d0ddb84706bc597a5574ab8912817c52a397f819e5b614e2265206921" +dependencies = [ + "log", + "ring", + "sct", + "webpki", +] + +[[package]] name = "rustversion" version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1434,6 +1516,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] +name = "sct" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] name = "secp256k1" version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1585,6 +1677,12 @@ dependencies = [ ] [[package]] +name = "spin" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" + +[[package]] name = "static_assertions" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1862,6 +1960,31 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" [[package]] +name = "untrusted" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" + +[[package]] +name = "ureq" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9399fa2f927a3d327187cbd201480cee55bee6ac5d3c77dd27f0c6814cff16d5" +dependencies = [ + "base64", + "chunked_transfer", + "flate2", + "log", + "once_cell", + "rustls", + "serde", + "serde_json", + "url", + "webpki", + "webpki-roots", +] + +[[package]] name = "uri-pack" version = "0.1.0" dependencies = [ @@ -1992,6 +2115,25 @@ dependencies = [ ] [[package]] +name = "webpki" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "webpki-roots" +version = "0.22.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "552ceb903e957524388c4d3475725ff2c8b7960922063af6ce53c9a43da07449" +dependencies = [ + "webpki", +] + +[[package]] name = "winapi" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2027,13 +2169,14 @@ name = "wire-gateway" version = "0.1.0" dependencies = [ "bitcoin", + "clap 3.1.1", "common", "deadpool-postgres", "ethereum-types", "hyper", "hyperlocal", "listenfd", - "miniz_oxide", + "miniz_oxide 0.5.1", "serde", "serde_json", "serde_urlencoded", diff --git a/Cargo.toml b/Cargo.toml @@ -5,4 +5,5 @@ members = [ "eth-wire", "uri-pack", "common", + "instrumentation" ] diff --git a/btc-wire/src/bin/btc-wire-utils.rs b/btc-wire/src/bin/btc-wire-utils.rs @@ -44,7 +44,7 @@ struct Args { #[derive(clap::Subcommand, Debug)] enum Cmd { - /// Wait or mine the next block + /// Send taler deposit transactions Transfer { #[clap(short, long, default_value_t = String::from("client"))] /// sender wallet diff --git a/btc-wire/src/lib.rs b/btc-wire/src/lib.rs @@ -16,14 +16,19 @@ use std::str::FromStr; use bitcoin::{hashes::hex::FromHex, Address, Amount, Network, Txid}; +use common::config::BtcConfig; use rpc::{Category, Rpc, Transaction}; use rpc_utils::{segwit_min_amount, sender_address}; use segwit::{decode_segwit_msg, encode_segwit_key}; +use taler_utils::taler_to_btc; +use common::api_common::Amount as TalerAmount; pub mod config; +pub mod metadata; pub mod rpc; pub mod rpc_utils; pub mod segwit; +pub mod taler_utils; #[derive(Debug, thiserror::Error)] pub enum GetSegwitErr { @@ -133,3 +138,13 @@ impl Rpc { self.send(&sender, &bounce_amount, metadata, true) } } + +const DEFAULT_BOUNCE_FEE: &'static str = "BTC:0.00001"; + +pub fn config_bounce_fee(config: &BtcConfig) -> Amount { + let config = config.bounce_fee.as_deref().unwrap_or(DEFAULT_BOUNCE_FEE); + TalerAmount::from_str(&config) + .ok() + .and_then(|a| taler_to_btc(&a).ok()) + .expect("config value BOUNCE_FEE is no a valid bitcoin amount") +} diff --git a/btc-wire/src/loops/worker.rs b/btc-wire/src/loops/worker.rs @@ -22,8 +22,10 @@ use std::{ use bitcoin::{hashes::Hash, Amount as BtcAmount, BlockHash, Txid}; use btc_wire::{ + metadata::OutMetadata, rpc::{self, AutoRpcWallet, Category, ErrorCode, Rpc, Transaction}, rpc_utils::sender_address, + taler_utils::{btc_payto_url, btc_to_taler}, GetOpReturnErr, GetSegwitErr, }; use common::{ @@ -38,9 +40,7 @@ use postgres::{fallible_iterator::FallibleIterator, Client}; use crate::{ fail_point::fail_point, - metadata::OutMetadata, sql::{sql_addr, sql_btc_amount, sql_txid}, - taler_util::{btc_payto_url, btc_to_taler}, WireState, }; diff --git a/btc-wire/src/main.rs b/btc-wire/src/main.rs @@ -16,32 +16,27 @@ use bitcoin::{Amount as BtcAmount, Network}; use btc_wire::{ config::{BitcoinConfig, WIRE_WALLET_NAME}, + config_bounce_fee, rpc::{self, auto_rpc_common, auto_rpc_wallet, ErrorCode, Rpc}, rpc_utils::default_data_dir, }; use clap::StructOpt; use common::{ - api_common::Amount, config::{load_btc_config, BtcConfig, Config, CoreConfig}, log::log::info, named_spawn, password, postgres::{Client, NoTls}, reconnect::auto_reconnect_db, }; -use std::{path::PathBuf, str::FromStr, sync::atomic::AtomicU16}; -use taler_util::taler_to_btc; +use std::{path::PathBuf, sync::atomic::AtomicU16}; use crate::loops::{analysis::analysis, watcher::watcher, worker::worker}; mod fail_point; mod loops; -mod metadata; mod sql; -mod taler_util; const DEFAULT_CONFIRMATION: u16 = 6; -const DEFAULT_BOUNCE_FEE: &'static str = "BTC:0.00001"; - pub struct WireState { confirmation: AtomicU16, max_confirmation: u16, @@ -49,14 +44,6 @@ pub struct WireState { bounce_fee: BtcAmount, } -fn config_bounce_fee(config: &BtcConfig) -> BtcAmount { - let config = config.bounce_fee.as_deref().unwrap_or(DEFAULT_BOUNCE_FEE); - Amount::from_str(&config) - .ok() - .and_then(|a| taler_to_btc(&a).ok()) - .expect("config value BOUNCE_FEE is no a valid bitcoin amount") -} - /// Taler wire for bitcoincore #[derive(clap::Parser, Debug)] struct Args { diff --git a/btc-wire/src/sql.rs b/btc-wire/src/sql.rs @@ -18,7 +18,7 @@ use bitcoin::{hashes::Hash, Address, Amount as BtcAmount, Txid}; use common::postgres::Row; use common::sql::{sql_amount, sql_url}; -use crate::taler_util::{btc_payto_addr, taler_to_btc}; +use btc_wire::taler_utils::{btc_payto_addr, taler_to_btc}; pub fn sql_btc_amount(row: &Row, idx: usize) -> BtcAmount { let amount = sql_amount(row, idx); diff --git a/btc-wire/src/taler_util.rs b/btc-wire/src/taler_utils.rs diff --git a/common/src/config.rs b/common/src/config.rs @@ -47,7 +47,7 @@ pub trait Config: Sized { if currency != curr { fail(format_args!( "expected config CURRENCY = {} got {}", - curr, currency + currency, curr )) } } diff --git a/eth-wire/Cargo.toml b/eth-wire/Cargo.toml @@ -11,7 +11,7 @@ fail = [] [dependencies] # Cli args -clap = { version = "3.1.0", features = ["derive"] } +clap = { version = "3.1.1", features = ["derive"] } # Serialization library serde = { version = "1.0.136", features = ["derive"] } serde_json = "1.0.78" diff --git a/instrumentation/Cargo.toml b/instrumentation/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "instrumentation" +version = "0.1.0" +edition = "2021" +license = "AGPL-3.0-or-later" +rust-version = "1.56.1" + +[dependencies] +# Cli args parser +clap = { version = "3.1.1", features = ["derive"] } +common = { path = "../common" } +# Bitcoin +btc-wire = { path = "../btc-wire" } +bitcoin = { version = "0.27.1", features = [ + "std", + "use-serde", +], default-features = false } +# Ethereum +eth-wire = { path = "../eth-wire" } +# Wire Gateway +ureq = { version = "2.4.0", features = ["json"] } diff --git a/instrumentation/src/main.rs b/instrumentation/src/main.rs @@ -0,0 +1,284 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU Affero General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License along with + TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> +*/ + +use std::{fmt::Display, io::Write, path::PathBuf}; + +use bitcoin::{Amount, BlockHash, Network, SignedAmount}; +use btc_wire::{ + config::BitcoinConfig, + config_bounce_fee, + metadata::OutMetadata, + rpc::{self, Category, ErrorCode, Rpc}, + rpc_utils::{self, default_data_dir}, + taler_utils::{btc_payto_url, btc_to_taler}, +}; +use clap::StructOpt; +use common::{ + api_common::Base32, + api_wire::{IncomingBankTransaction, IncomingHistory, OutgoingHistory, TransferRequest}, + config::{load_btc_config, Config, GatewayConfig}, + rand_slice, + url::Url, +}; + +pub const CLIENT: &str = "client"; +pub const WIRE: &str = "wire"; + +fn unsigned(amount: SignedAmount) -> Amount { + amount.abs().to_unsigned().unwrap() +} + +fn print_now(disp: impl Display) { + print!("{}", disp); + std::io::stdout().flush().unwrap(); +} + +fn wait_while_pending(rpc: &mut Rpc, wallet: &str, since: &mut BlockHash) { + print_now(format_args!("Skip pending {}:", wallet)); + let mut pending = true; + while pending { + pending = false; + rpc.wait_for_new_block(0).unwrap(); + print_now("."); + let sync = rpc.list_since_block(Some(&since), 1).unwrap(); + for tx in sync.transactions { + if tx.confirmations == 0 { + pending = true; + } + } + *since = sync.lastblock; + } + println!(""); +} + +/// Depolymerizer instrumentation test +#[derive(clap::Parser, Debug)] +struct Args { + /// Override default configuration file path + #[clap(global = true, short, long)] + config: Option<PathBuf>, +} + +pub fn main() { + common::log::init(); + let args = Args::parse(); + let gateway_conf = GatewayConfig::load_taler_config(args.config.as_deref(), None); + let base_url = format!("http://localhost:{}", gateway_conf.port); + + match gateway_conf.core.currency.as_str() { + "BTC" => { + let config = load_btc_config(args.config.as_deref()); + let data_dir = config + .core + .data_dir + .as_ref() + .cloned() + .unwrap_or_else(default_data_dir); + let btc_config = BitcoinConfig::load(&data_dir).unwrap(); + + if btc_config.network == Network::Bitcoin { + panic!("You should never run this test on a real bitcoin network"); + } + + let bounce_fee = config_bounce_fee(&config); + let min_fund = Amount::from_sat(10_000); + + let mut rpc = Rpc::common(&btc_config).unwrap(); + // Load client + match rpc.load_wallet(CLIENT) { + Ok(_) => {} + Err(rpc::Error::RPC { + code: ErrorCode::RpcWalletNotFound, + .. + }) => { + rpc.create_wallet(CLIENT, "").unwrap(); + } + Err(rpc::Error::RPC { + code: ErrorCode::RpcWalletError, + .. + }) => {} + Err(e) => panic!("{}", e), + }; + let mut client_rpc = Rpc::wallet(&btc_config, CLIENT).unwrap(); + let client_addr = client_rpc.gen_addr().unwrap(); + if client_rpc.get_balance().unwrap() < min_fund { + println!("Client need a minimum of {} BTC to run this test, send coins to this address: {}", min_fund.as_btc(), client_addr); + print_now("Waiting for fund:"); + while client_rpc.get_balance().unwrap() < min_fund { + client_rpc.wait_for_new_block(0).unwrap(); + print_now("."); + } + } + let mut since = client_rpc.list_since_block(None, 1).unwrap().lastblock; + // Load wire + match rpc.load_wallet(WIRE) { + Ok(_) => {} + Err(rpc::Error::RPC { + code: ErrorCode::RpcWalletError, + .. + }) => {} + Err(rpc::Error::RPC { + code: ErrorCode::RpcWalletNotFound, + .. + }) => panic!("Wire wallet is not initialized"), + Err(e) => panic!("{}", e), + }; + let mut wire_rpc = Rpc::wallet(&btc_config, WIRE).unwrap(); + let wire_addr = wire_rpc.gen_addr().unwrap(); + // Skip pending + wait_while_pending(&mut client_rpc, CLIENT, &mut since); + wait_while_pending(&mut wire_rpc, WIRE, &mut since); + // Load balances + let client_balance = client_rpc.get_balance().unwrap(); + let wire_balance = wire_rpc.get_balance().unwrap(); + // Test amount + let test_amount = Amount::from_sat(2000); + let min_send_amount = rpc_utils::segwit_min_amount(); // To small to send back + let min_bounce_amount = rpc_utils::segwit_min_amount() + Amount::from_sat(999); // To small after bounce fee + let taler_test_amount = btc_to_taler(&test_amount.to_signed().unwrap()); + // Send transaction + let reserve_pub_key = rand_slice(); + let deposit_id = client_rpc + .send_segwit_key(&wire_addr, &test_amount, &reserve_pub_key) + .unwrap(); + let bounce_min_id = client_rpc + .send(&wire_addr, &min_bounce_amount, None, false) + .unwrap(); + let send_min_id = client_rpc + .send(&wire_addr, &min_send_amount, None, false) + .unwrap(); + let bounce_id = client_rpc + .send(&wire_addr, &test_amount, None, false) + .unwrap(); + let client_sent_amount_cost = test_amount + + min_send_amount * 2 + + min_bounce_amount + + min_send_amount + + test_amount; + let client_sent_fees_cost: Amount = [deposit_id, bounce_min_id, send_min_id, bounce_id] + .into_iter() + .map(|id| unsigned(client_rpc.get_tx(&id).unwrap().fee.unwrap())) + .reduce(|acc, i| acc + i) + .unwrap(); + let new_balance = client_rpc.get_balance().unwrap(); + assert_eq!( + client_balance - client_sent_amount_cost - client_sent_fees_cost, + new_balance + ); + + // Wait for mining and bounce + print_now("Wait for mining and bounce:"); + let mut pending = true; + let mut bounced_id = None; + while pending || bounced_id.is_none() { + pending = false; + rpc.wait_for_new_block(0).unwrap(); + print_now("."); + let sync = client_rpc.list_since_block(Some(&since), 1).unwrap(); + for tx in sync.transactions { + if tx.confirmations == 0 { + pending = true; + } else if tx.category == Category::Receive { + let (_, metadata) = client_rpc.get_tx_op_return(&tx.txid).unwrap(); + let metadata = OutMetadata::decode(&metadata).unwrap(); + match metadata { + OutMetadata::Withdraw { .. } => {} + OutMetadata::Bounce { bounced } => { + if bounced == bounce_id { + bounced_id.replace(tx.txid); + } else if bounced == send_min_id { + panic!("Bounced send min"); + } else if bounced == bounce_min_id { + panic!("Bounced bounce min"); + } + } + } + } + } + since = sync.lastblock; + } + println!(""); + // Check balances change + let new_client_balance = client_rpc.get_balance().unwrap(); + let new_wire_balance = wire_rpc.get_balance().unwrap(); + let bounced = client_rpc.get_tx(&bounced_id.unwrap()).unwrap(); + assert_eq!( + client_balance - client_sent_amount_cost - client_sent_fees_cost + + unsigned(bounced.amount), + new_client_balance + ); + assert_eq!( + wire_balance + test_amount + min_bounce_amount + min_send_amount + bounce_fee, + new_wire_balance + ); + // Check history + let history: IncomingHistory = ureq::get(&format!("{}/history/incoming", base_url)) + .query("delta", "-5") + .call() + .unwrap() + .into_json() + .unwrap(); + assert!(history + .incoming_transactions + .iter() + .find(|h| { + matches!( + h, + IncomingBankTransaction::IncomingReserveTransaction { + reserve_pub, + amount, + .. + } if reserve_pub == &Base32::from(reserve_pub_key) && amount == &taler_test_amount + ) + }) + .is_some()); + // Get back some money + let url = Url::parse("ftp://example.com").unwrap(); + let wtid = rand_slice(); + ureq::post(&format!("{}/transfer", base_url)) + .send_json(TransferRequest { + request_uid: Base32::from(rand_slice()), + amount: taler_test_amount.clone(), + exchange_base_url: url.clone(), + wtid: Base32::from(wtid), + credit_account: btc_payto_url(&client_addr), + }) + .unwrap(); + wait_while_pending(&mut wire_rpc, WIRE, &mut since); + + // Check balances change + let last_client_balance = client_rpc.get_balance().unwrap(); + assert_eq!(new_client_balance + test_amount, last_client_balance); + // Check history + let history: OutgoingHistory = ureq::get(&format!("{}/history/outgoing", base_url)) + .query("delta", "-5") + .call() + .unwrap() + .into_json() + .unwrap(); + assert!(history + .outgoing_transactions + .iter() + .find(|h| { + h.wtid == Base32::from(wtid) + && h.exchange_base_url == url + && h.amount == taler_test_amount + }) + .is_some()); + } + _ => unimplemented!(), + } +} diff --git a/makefile b/makefile @@ -6,6 +6,7 @@ install: install_test: install cargo install --path btc-wire --bin btc-wire-utils cargo install --path eth-wire --bin eth-wire-utils + cargo install --path instrumentation test_gateway: install_test test/gateway/api.sh diff --git a/wire-gateway/Cargo.toml b/wire-gateway/Cargo.toml @@ -35,7 +35,8 @@ common = { path = "../common" } bitcoin = { version = "0.27.1", optional = true } # Euthereum types ethereum-types = { version = "0.13.0", default-features = false, optional = true } - +# Cli args parser +clap = { version = "3.1.1", features = ["derive"] } [features] default = ["btc", "eth"] diff --git a/wire-gateway/src/main.rs b/wire-gateway/src/main.rs @@ -1,3 +1,4 @@ +use clap::StructOpt; /* This file is part of TALER Copyright (C) 2022 Taler Systems SA @@ -85,16 +86,19 @@ impl ServerState { } } +/// Taler wire gateway server for depolymerizer +#[derive(clap::Parser, Debug)] +struct Args { + /// Override default configuration file path + #[clap(global = true, short, long)] + config: Option<PathBuf>, +} + #[tokio::main] async fn main() { common::log::init(); - - let conf = GatewayConfig::load_taler_config( - Some(&PathBuf::from( - std::env::args_os().nth(1).expect("Missing conf path arg"), - )), - None, - ); + let args = Args::parse(); + let conf = GatewayConfig::load_taler_config(args.config.as_deref(),None); #[cfg(feature = "test")] common::log::log::warn!("Running with test admin endpoint unsuitable for production");