commit 5362e27f9b98beaae7e517639db1f848bee86e6d
parent 03d679a05cf5c057df1d86acc628e71304672c37
Author: Antoine A <>
Date: Tue, 22 Feb 2022 17:24:23 +0100
instrumentation: new instrumentation test
Diffstat:
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");