commit 3e080b281767c1d9623cf97091d2e4e1c01b450c
parent da0d6bcab7fb18212298a55a104333fb3e101a76
Author: Antoine A <>
Date: Mon, 14 Feb 2022 19:40:44 +0100
Use taler amount format for bounce fee in config
Diffstat:
13 files changed, 99 insertions(+), 55 deletions(-)
diff --git a/README.md b/README.md
@@ -15,14 +15,14 @@ The configuration is based on [taler.conf](https://docs.taler.net/manpages/taler
``` ini
# taler.conf - common config
[taler]
-CURRENCY = ___
+CURRENCY = ___
[exchange]
-BASE_URL = https://___
+BASE_URL = https://___
[depolymerizer-___]
-DB_URL = postgres://___
-PAYTO = payto://___
+DB_URL = postgres://___
+PAYTO = payto://___
```
### Process lifetime
@@ -35,9 +35,9 @@ done.
``` ini
[depolymerizer-___]
# Number of requests to serve before gateway shutdown (0 mean never)
-HTTP_LIFETIME = 0
+HTTP_LIFETIME = 0
# Number of worker's loops before wire implementation shutdown (0 mean never)
-WIRE_LIFETIME = 0
+WIRE_LIFETIME = 0
```
### Stuck transaction
diff --git a/btc-wire/src/loops/analysis.rs b/btc-wire/src/loops/analysis.rs
@@ -53,11 +53,11 @@ pub fn analysis(mut rpc: AutoReconnectRPC, mut db: AutoReconnectDb, state: &Wire
// If new fork is bigger than the current confirmation
if fork > current_conf {
// Max two time the configuration
- let new_conf = fork.min(state.config.confirmation * 2);
+ let new_conf = fork.min(state.max_confirmation);
state.confirmation.store(new_conf, Ordering::SeqCst);
warn!(
"analysis: found dangerous fork of {} blocks, adapt confirmation to {} blocks capped at {}, you should update taler.conf",
- fork, new_conf, state.config.confirmation * 2
+ fork, new_conf, state.max_confirmation
);
}
}
diff --git a/btc-wire/src/loops/worker.rs b/btc-wire/src/loops/worker.rs
@@ -119,9 +119,8 @@ pub fn worker(mut rpc: AutoReconnectRPC, mut db: AutoReconnectDb, state: &WireSt
);
}
- let bounce_fee = BtcAmount::from_sat(state.config.bounce_fee);
// Send requested bounce
- while bounce(db, rpc, &bounce_fee)? {}
+ while bounce(db, rpc, &state.bounce_fee)? {}
}
Ok(())
diff --git a/btc-wire/src/main.rs b/btc-wire/src/main.rs
@@ -13,18 +13,21 @@
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 bitcoin::Network;
+use bitcoin::{Amount as BtcAmount, Network};
use btc_wire::{
config::{BitcoinConfig, WIRE_WALLET_NAME},
rpc::{auto_reconnect_rpc, Rpc},
rpc_utils::default_data_dir,
};
use common::{
+ api_common::Amount,
config::{load_btc_config, BtcConfig},
log::log::info,
- reconnect::auto_reconnect_db, named_spawn,
+ named_spawn,
+ reconnect::auto_reconnect_db,
};
-use std::{sync::atomic::AtomicU16, thread::JoinHandle};
+use std::{str::FromStr, sync::atomic::AtomicU16};
+use taler_util::taler_to_btc;
use crate::loops::{analysis::analysis, watcher::watcher, worker::worker};
@@ -34,9 +37,22 @@ 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,
config: BtcConfig,
+ 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")
}
fn main() {
@@ -68,8 +84,11 @@ fn main() {
};
info!("Running on {} chain", chain_name);
+ let init_confirmation = config.confirmation.unwrap_or(DEFAULT_CONFIRMATION);
let state: &'static WireState = Box::leak(Box::new(WireState {
- confirmation: AtomicU16::new(config.confirmation),
+ confirmation: AtomicU16::new(init_confirmation),
+ max_confirmation: init_confirmation * 2,
+ bounce_fee: config_bounce_fee(&config),
config,
}));
diff --git a/common/src/config.rs b/common/src/config.rs
@@ -92,26 +92,24 @@ impl Config for GatewayConfig {
// TODO currency name as const generic
#[derive(Debug, Clone, PartialEq, Eq)]
-pub struct WireConfig<const DEFAULT_FEE: u64, const DEFAULT_CONFIRMATION: u16> {
+pub struct WireConfig {
pub base_url: Url,
- pub confirmation: u16,
- pub bounce_fee: u64,
+ pub confirmation: Option<u16>,
+ pub bounce_fee: Option<String>,
pub wire_lifetime: Option<u32>,
pub bump_delay: Option<u32>,
pub payto: Url,
pub core: CoreConfig,
}
-impl<const DEFAULT_FEE: u64, const DEFAULT_CONFIRMATION: u16> Config
- for WireConfig<DEFAULT_FEE, DEFAULT_CONFIRMATION>
-{
+impl Config for WireConfig {
fn load_from_ini(ini: &Ini, currency: &str, dep: &Properties) -> Self {
let ex = section(ini, "exchange");
- Self {
+ let config = Self {
base_url: require(ex, "BASE_URL", url),
payto: require(dep, "PAYTO", url),
- confirmation: nb(dep, "CONFIRMATION").unwrap_or(DEFAULT_CONFIRMATION),
- bounce_fee: nb(dep, "BOUNCE_FEE").unwrap_or(DEFAULT_FEE),
+ confirmation: nb(dep, "CONFIRMATION"),
+ bounce_fee: string(dep, "BOUNCE_FEE"),
wire_lifetime: nb(dep, "WIRE_LIFETIME")
.and_then(|nb| (nb != 0).then(|| Some(nb)))
.unwrap_or(None),
@@ -119,11 +117,13 @@ impl<const DEFAULT_FEE: u64, const DEFAULT_CONFIRMATION: u16> Config
.and_then(|nb| (nb != 0).then(|| Some(nb)))
.unwrap_or(None),
core: CoreConfig::load_from_ini(ini, currency, dep),
- }
+ };
+ assert_eq!(config.core.currency, currency);
+ return config;
}
}
-pub type BtcConfig = WireConfig<1000, 6>;
+pub type BtcConfig = WireConfig;
pub fn load_btc_config(path: Option<&str>) -> BtcConfig {
let config = WireConfig::load_taler_config(path);
@@ -131,7 +131,7 @@ pub fn load_btc_config(path: Option<&str>) -> BtcConfig {
return config;
}
-pub type EthConfig = WireConfig<10_000_000_000_000, 24>;
+pub type EthConfig = WireConfig;
pub fn load_eth_config(path: Option<&str>) -> EthConfig {
let config = WireConfig::load_taler_config(path);
diff --git a/eth-wire/src/loops.rs b/eth-wire/src/loops.rs
@@ -14,6 +14,25 @@
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
+use common::postgres;
+use eth_wire::rpc;
+
+use crate::fail_point::Injected;
+
+pub mod analysis;
pub mod watcher;
pub mod worker;
-pub mod analysis;
+
+#[derive(Debug, thiserror::Error)]
+pub enum LoopError {
+ #[error(transparent)]
+ RPC(#[from] rpc::Error),
+ #[error(transparent)]
+ DB(#[from] postgres::Error),
+ #[error("Another eth-wire process is running concurrently")]
+ Concurrency,
+ #[error(transparent)]
+ Injected(#[from] Injected),
+}
+
+pub type LoopResult<T> = Result<T, LoopError>;
diff --git a/eth-wire/src/loops/analysis.rs b/eth-wire/src/loops/analysis.rs
@@ -24,7 +24,9 @@ use common::{
use eth_wire::rpc::{AutoReconnectRPC, Rpc};
use ethereum_types::{H256, U64};
-use crate::{LoopResult, WireState};
+use crate::WireState;
+
+use super::LoopResult;
/// Analyse blockchain behavior and adapt confirmations in real time
pub fn analysis(mut rpc: AutoReconnectRPC, mut db: AutoReconnectDb, state: &WireState) {
@@ -48,11 +50,11 @@ pub fn analysis(mut rpc: AutoReconnectRPC, mut db: AutoReconnectDb, state: &Wire
// If new fork is bigger than the current confirmation
if fork > current_conf {
// Max two time the configuration
- let new_conf = fork.min(state.config.confirmation * 2);
+ let new_conf = fork.min(state.max_confirmations);
state.confirmation.store(new_conf, Ordering::SeqCst);
warn!(
"analysis: found dangerous fork of {} blocks, adapt confirmation to {} blocks capped at {}, you should update taler.conf",
- fork, new_conf, state.config.confirmation * 2
+ fork, new_conf, state.max_confirmations
);
}
}
diff --git a/eth-wire/src/loops/watcher.rs b/eth-wire/src/loops/watcher.rs
@@ -16,7 +16,7 @@
use common::{log::log::error, reconnect::AutoReconnectDb};
use eth_wire::rpc::AutoReconnectRPC;
-use crate::LoopResult;
+use super::LoopResult;
/// Wait for new block and notify arrival with postgreSQL notifications
pub fn watcher(mut rpc: AutoReconnectRPC, mut db: AutoReconnectDb) {
diff --git a/eth-wire/src/loops/worker.rs b/eth-wire/src/loops/worker.rs
@@ -33,10 +33,13 @@ use ethereum_types::{Address, H256, U256, U64};
use crate::{
fail_point::fail_point,
+ loops::LoopError,
sql::{sql_addr, sql_eth_amount, sql_hash},
- LoopError, LoopResult, WireState,
+ WireState,
};
+use super::LoopResult;
+
pub fn worker(mut rpc: AutoReconnectRPC, mut db: AutoReconnectDb, state: &WireState) {
let mut lifetime = state.config.wire_lifetime;
let mut status = true;
@@ -95,7 +98,7 @@ pub fn worker(mut rpc: AutoReconnectRPC, mut db: AutoReconnectDb, state: &WireSt
while withdraw(db, rpc, state)? {}
// Send requested bounce
- while bounce(db, rpc, U256::from(state.config.bounce_fee))? {}
+ while bounce(db, rpc, state.bounce_fee)? {}
}
Ok(())
})();
diff --git a/eth-wire/src/main.rs b/eth-wire/src/main.rs
@@ -14,54 +14,56 @@
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
-use std::sync::atomic::AtomicU16;
+use std::{str::FromStr, sync::atomic::AtomicU16};
use common::{
+ api_common::Amount,
config::{load_eth_config, EthConfig},
- named_spawn, postgres,
+ named_spawn,
reconnect::auto_reconnect_db,
};
use eth_wire::{
- rpc::{self, auto_reconnect_rpc},
- taler_util::eth_payto_addr,
+ rpc::auto_reconnect_rpc,
+ taler_util::{eth_payto_addr, taler_to_eth},
};
-use ethereum_types::H160;
-use fail_point::Injected;
+use ethereum_types::{H160, U256};
use loops::{analysis::analysis, watcher::watcher, worker::worker};
mod fail_point;
mod loops;
mod sql;
+const DEFAULT_CONFIRMATION: u16 = 24;
+const DEFAULT_BOUNCE_FEE: &'static str = "ETH:0.00001";
+
pub struct WireState {
confirmation: AtomicU16,
+ max_confirmations: u16,
address: H160,
config: EthConfig,
+ bounce_fee: U256,
}
-#[derive(Debug, thiserror::Error)]
-pub enum LoopError {
- #[error(transparent)]
- RPC(#[from] rpc::Error),
- #[error(transparent)]
- DB(#[from] postgres::Error),
- #[error("Another eth-wire process is running concurrently")]
- Concurrency,
- #[error(transparent)]
- Injected(#[from] Injected),
+fn config_bounce_fee(config: &EthConfig) -> U256 {
+ let config = config.bounce_fee.as_deref().unwrap_or(DEFAULT_BOUNCE_FEE);
+ Amount::from_str(&config)
+ .ok()
+ .and_then(|a| taler_to_eth(&a).ok())
+ .expect("config value BOUNCE_FEE is no a valid ethereum amount")
}
-pub type LoopResult<T> = Result<T, LoopError>;
-
fn main() {
common::log::init();
let path = std::env::args().nth(1).unwrap();
let config = load_eth_config(Some(&path));
+ let init_confirmation = config.confirmation.unwrap_or(DEFAULT_CONFIRMATION);
let state: &'static WireState = Box::leak(Box::new(WireState {
- confirmation: AtomicU16::new(config.confirmation),
+ confirmation: AtomicU16::new(init_confirmation),
+ max_confirmations: init_confirmation * 2,
address: eth_payto_addr(&config.payto).unwrap(),
+ bounce_fee: config_bounce_fee(&config),
config,
}));
diff --git a/eth-wire/src/rpc.rs b/eth-wire/src/rpc.rs
@@ -22,7 +22,7 @@
use common::{log::log::error, reconnect::AutoReconnect, url::Url};
use ethereum_types::{Address, H256, U256, U64};
use serde::de::DeserializeOwned;
-use serde_json::{error::Category, Value};
+use serde_json::error::Category;
use std::{
fmt::Debug,
io::{self, BufWriter, ErrorKind, Read, Write},
diff --git a/test/conf/taler_btc_bump.conf b/test/conf/taler_btc_bump.conf
@@ -1,5 +1,5 @@
[taler]
-CURRENCY = BTC
+CURRENCY = BTC
[exchange]
BASE_URL = http://test.com
diff --git a/test/conf/taler_btc_lifetime.conf b/test/conf/taler_btc_lifetime.conf
@@ -1,5 +1,5 @@
[taler]
-CURRENCY = BTC
+CURRENCY = BTC
[exchange]
BASE_URL = http://test.com