commit 7f443715468c292d84c4a0c54942aab550120cfb
parent c0109078a74e73ae2015bfd13580392d3c843eac
Author: Antoine A <>
Date: Tue, 4 Jan 2022 14:57:41 +0100
Improve configurations
Diffstat:
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");