depolymerization

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

commit 7f443715468c292d84c4a0c54942aab550120cfb
parent c0109078a74e73ae2015bfd13580392d3c843eac
Author: Antoine A <>
Date:   Tue,  4 Jan 2022 14:57:41 +0100

Improve configurations

Diffstat:
Mbtc-wire/src/config.rs | 13+++++++++++--
Mbtc-wire/src/main.rs | 12+++++++-----
Ascript/conf/bitcoin.conf | 8++++++++
Ascript/conf/bitcoin2.conf | 8++++++++
Ascript/conf/taler_test.conf | 11+++++++++++
Ascript/conf/taler_unix.conf | 12++++++++++++
Mscript/setup.sh | 29+++++++++++++----------------
Mtaler-config/src/lib.rs | 80+++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------
Dtest.conf | 13-------------
Mwire-gateway/src/main.rs | 2+-
10 files changed, 125 insertions(+), 63 deletions(-)

diff --git a/btc-wire/src/config.rs b/btc-wire/src/config.rs @@ -26,6 +26,7 @@ fn rpc_port(network: Network) -> u16 { } } +/// Bitcoin config relevant for btc-wire #[derive(Clone)] pub struct BitcoinConfig { pub network: Network, @@ -34,6 +35,7 @@ pub struct BitcoinConfig { } impl BitcoinConfig { + /// Load from bitcoin data_dir pub fn load(data_dir: impl AsRef<Path>) -> Result<Self, ini::Error> { let conf = ini::Ini::load_from_file(data_dir.as_ref().join("bitcoin.conf"))?; @@ -54,14 +56,21 @@ impl BitcoinConfig { Network::Bitcoin }; - let port = if let Some(addr) = section.get("rpcport") { + let section = match network { + Network::Bitcoin => Some(section), + Network::Testnet => conf.section(Some("test")), + Network::Signet => conf.section(Some("signet")), + Network::Regtest => conf.section(Some("regtest")), + }; + + let port = if let Some(addr) = section.and_then(|s| s.get("rpcport")) { addr.parse() .expect("bitcoin config value 'rpcport' is not a valid port number") } else { rpc_port(network) }; - let addr = if let Some(addr) = section.get("rpcbind") { + let addr = if let Some(addr) = section.and_then(|s| s.get("rpcbind")) { SocketAddr::from_str(addr) .expect("bitcoin config value 'rpcbind' is not a valid socket address") } else { diff --git a/btc-wire/src/main.rs b/btc-wire/src/main.rs @@ -449,12 +449,14 @@ fn main() { #[cfg(feature = "fail")] taler_log::log::warn!("Running with random failures is unsuitable for production"); - // Guess network by trying to connect to a JSON RPC server - let data_dir = std::env::args() - .nth(1) - .map(|str| PathBuf::from_str(&str).unwrap()) + let config = taler_config::Config::load_from_file( + std::env::args_os().nth(1).expect("Missing conf path arg"), + ); + let data_dir = config + .btc_data_dir + .as_ref() + .map(|p| p.clone()) .unwrap_or_else(default_data_dir); - let config = taler_config::Config::from_path("test.conf"); let config: &'static Config = Box::leak(Box::new(config)); let btc_config = BitcoinConfig::load(&data_dir).unwrap(); let mut rpc = BtcRpc::common(&btc_config).unwrap(); diff --git a/script/conf/bitcoin.conf b/script/conf/bitcoin.conf @@ -0,0 +1,7 @@ +regtest=1 +txindex=1 +fallbackfee=0.00000001 + +[regtest] +port=8345 +rpcport=18345 +\ No newline at end of file diff --git a/script/conf/bitcoin2.conf b/script/conf/bitcoin2.conf @@ -0,0 +1,7 @@ +regtest=1 +txindex=1 +fallbackfee=0.00000001 + +[regtest] +port=8346 +rpcport=18346 +\ No newline at end of file diff --git a/script/conf/taler_test.conf b/script/conf/taler_test.conf @@ -0,0 +1,10 @@ +[exchange] +BASE_URL = http://test.com + +[depolymerizer-bitcoin] +DB_URL = postgres://localhost:5454/postgres?user=postgres&password=password +PORT = 8060 +PAYTO = payto://bitcoin/bcrt1qgkgxkjj27g3f7s87mcvjjsghay7gh34cx39prj +CONFIRMATION = 3 +BTC_WALLET = wire +BOUNCE_FEE = 1000 +\ No newline at end of file diff --git a/script/conf/taler_unix.conf b/script/conf/taler_unix.conf @@ -0,0 +1,11 @@ +[exchange] +BASE_URL = http://test.com + +[depolymerizer-bitcoin] +DB_URL = postgres://localhost:5454/postgres?user=postgres&password=password +UNIXPATH = /tmp/wire.sock +PAYTO = payto://bitcoin/bcrt1qgkgxkjj27g3f7s87mcvjjsghay7gh34cx39prj +CONFIRMATION = 3 +BTC_WALLET = wire +BTC_DATA_DIR = ~/.bitcoin +BOUNCE_FEE = 1000 +\ No newline at end of file diff --git a/script/setup.sh b/script/setup.sh @@ -21,13 +21,16 @@ DIR=$(mktemp -d) BTC_DIR=$DIR/bitcoin BTC_DIR2=$DIR/bitcoin2 DB_DIR=$DIR/db +CONF=$DIR/taler.conf for dir in $BTC_DIR $BTC_DIR2 $DB_DIR; do mkdir -p $dir done # Load test.conf as bash variables function load_config() { - source <(grep = test.conf | sed 's/ *= */=/' | sed 's/=\(.*\)/="\1"/g1') + cp ${BASH_SOURCE%/*}/conf/${CONFIG:-taler_test.conf} $CONF + echo -e "\nBTC_DATA_DIR = ${BTC_DIR}" >> $CONF + source <(grep = $CONF | sed 's/ *= */=/' | sed 's/=\(.*\)/="\1"/g1') BANK_ENDPOINT=http://127.0.0.1:$PORT/ } @@ -51,24 +54,18 @@ function reset_db() { # Start a bitcoind regtest node function init_btc() { - echo "regtest=1" > $BTC_DIR/bitcoin.conf - echo "txindex=1" >> $BTC_DIR/bitcoin.conf - echo "fallbackfee=0.00000001" >> $BTC_DIR/bitcoin.conf + cp ${BASH_SOURCE%/*}/conf/bitcoin.conf $BTC_DIR/bitcoin.conf BTC_CLI="bitcoin-cli -datadir=$BTC_DIR" - bitcoind -datadir=$BTC_DIR -port=8345 &> btc.log & + bitcoind -datadir=$BTC_DIR &> btc.log & BTC_PID="$!" $BTC_CLI -rpcwait getnetworkinfo > /dev/null } # Start a second bitcoind regtest node connected to the first one function init_btc2() { - echo "regtest=1" > $BTC_DIR2/bitcoin.conf - echo "txindex=1" >> $BTC_DIR2/bitcoin.conf - echo "fallbackfee=0.00000001" >> $BTC_DIR2/bitcoin.conf - echo "[regtest]" >> $BTC_DIR2/bitcoin.conf - echo "rpcport=18345" >> $BTC_DIR2/bitcoin.conf + cp ${BASH_SOURCE%/*}/conf/bitcoin2.conf $BTC_DIR2/bitcoin.conf BTC_CLI2="bitcoin-cli -datadir=$BTC_DIR2" - bitcoind -datadir=$BTC_DIR2 -port=8346 &> btc2.log & + bitcoind -datadir=$BTC_DIR2 &> btc2.log & $BTC_CLI2 -rpcwait getnetworkinfo > /dev/null $BTC_CLI addnode 127.0.0.1:8346 onetry } @@ -146,22 +143,22 @@ function check_balance() { # Start btc_wire function btc_wire() { cargo build --bin btc-wire --release &> /dev/null - target/release/btc-wire $BTC_DIR &> btc_wire.log & + target/release/btc-wire $CONF &> btc_wire.log & WIRE_PID="$!" } # Start btc_wire with random failures function fail_btc_wire() { cargo build --bin btc-wire --release --features fail &> /dev/null - target/release/btc-wire $BTC_DIR &> btc_wire.log & + target/release/btc-wire $CONF &> btc_wire.log & WIRE_PID="$!" } # Start multiple btc_wire in parallel function stressed_btc_wire() { cargo build --bin btc-wire --release &> /dev/null - target/release/btc-wire $BTC_DIR &> btc_wire.log & - target/release/btc-wire $BTC_DIR &> btc_wire1.log & + target/release/btc-wire $CONF &> btc_wire.log & + target/release/btc-wire $CONF &> btc_wire1.log & } # ----- Gateway ------ # @@ -169,7 +166,7 @@ function stressed_btc_wire() { # Start wire_gateway in test mode function gateway() { cargo build --bin wire-gateway --release --features test &> /dev/null - target/release/wire-gateway &> gateway.log & + target/release/wire-gateway $CONF &> gateway.log & for n in `seq 1 50`; do echo -n "." sleep 0.2 diff --git a/taler-config/src/lib.rs b/taler-config/src/lib.rs @@ -1,11 +1,18 @@ -use std::path::Path; +use ini::Properties; +use std::{ + path::{Path, PathBuf}, + str::FromStr, +}; use url::Url; +/// Taler config with depolymerizer config #[derive(Debug, Clone, PartialEq, Eq)] pub struct Config { pub base_url: Url, pub db_url: String, pub port: u16, + pub unix_path: Option<PathBuf>, + pub btc_data_dir: Option<PathBuf>, pub payto: Url, pub confirmation: u8, pub btc_wallet: String, @@ -13,34 +20,55 @@ pub struct Config { } impl Config { - pub fn from_path(path: impl AsRef<Path>) -> Self { - let conf = ini::Ini::load_from_file(path).unwrap(); + /// Load from a file + pub fn load_from_file(config_file: impl AsRef<Path>) -> Self { + let conf = ini::Ini::load_from_file(config_file).unwrap(); let ex_conf = conf.section(Some("exchange")).unwrap(); let self_conf = conf.section(Some("depolymerizer-bitcoin")).unwrap(); Self { - base_url: Url::parse(ex_conf.get("BASE_URL").expect("Missing config BASE_URL")) - .expect("BASE_URL is not a valid url"), - db_url: self_conf - .get("DB_URL") - .expect("Missing config DB_URL") - .to_string(), - port: self_conf - .get("PORT") - .unwrap_or("8080") - .parse() - .expect("Config PORT is not a number"), - payto: Url::parse(self_conf.get("PAYTO").unwrap()).unwrap(), - confirmation: self_conf - .get("CONFIRMATION") - .unwrap_or("1") - .parse() - .expect("Config CONFIRMATION is not a number"), - btc_wallet: self_conf.get("BTC_WALLET").unwrap_or("wire").to_string(), - bounce_fee: self_conf - .get("BOUNCE_FEE") - .unwrap_or("0") - .parse() - .expect("Config BOUNCE_FEE is not a number"), + base_url: require(ex_conf, "BASE_URL", url), + db_url: require(self_conf, "DB_URL", string), + port: nb(self_conf, "PORT").unwrap_or(8080), + unix_path: path(self_conf, "UNIXPATH"), + btc_data_dir: path(self_conf, "BTC_DATA_DIR"), + payto: require(self_conf, "PAYTO", url), + confirmation: nb(self_conf, "CONFIRMATION").unwrap_or(6), + btc_wallet: string(self_conf, "BTC_WALLET").unwrap_or_else(|| "wire".to_string()), + bounce_fee: nb(self_conf, "BOUNCE_FEE").unwrap_or(1000), } } } + +/* ----- Helper functions ----- */ + +fn require<T>( + properties: &Properties, + name: &str, + lambda: fn(properties: &Properties, name: &str) -> Option<T>, +) -> T { + let result = lambda(properties, name); + result.unwrap_or_else(|| panic!("missing config {}", name)) +} + +fn string(properties: &Properties, name: &str) -> Option<String> { + properties.get(name).map(|s| s.to_string()) +} + +fn path(properties: &Properties, name: &str) -> Option<PathBuf> { + properties.get(name).map(|s| { + PathBuf::from_str(s).unwrap_or_else(|_| panic!("config value {} is not a valid path", name)) + }) +} + +fn nb<T: FromStr>(properties: &Properties, name: &str) -> Option<T> { + properties.get(name).map(|s| { + s.parse() + .unwrap_or_else(|_| panic!("config value {} is not a number", name)) + }) +} + +fn url(properties: &Properties, name: &str) -> Option<Url> { + properties.get(name).map(|s| { + Url::parse(&s).unwrap_or_else(|_| panic!("config value {} is not a valid url", name)) + }) +} diff --git a/test.conf b/test.conf @@ -1,12 +0,0 @@ -[exchange] -BASE_URL = http://test.com - -[depolymerizer-bitcoin] -DB_URL = postgres://localhost:5454/postgres?user=postgres&password=password -PORT = 8060 -UNIXPATH = TODO -PAYTO = payto://bitcoin/bcrt1qgkgxkjj27g3f7s87mcvjjsghay7gh34cx39prj -CONFIRMATION = 3 -BTC_WALLET = wire -BTC_DATA_DIR = ~/.bitcoin -BOUNCE_FEE = 1000 -\ No newline at end of file diff --git a/wire-gateway/src/main.rs b/wire-gateway/src/main.rs @@ -32,7 +32,7 @@ struct ServerState { async fn main() { taler_log::init(); - let conf = taler_config::Config::from_path("test.conf"); + let conf = taler_config::Config::load_from_file(std::env::args_os().nth(1).expect("Missing conf path arg")); #[cfg(feature = "test")] taler_log::log::warn!("Running with test admin endpoint unsuitable for production");