diff options
author | Antoine A <> | 2022-01-03 02:14:52 +0100 |
---|---|---|
committer | Antoine A <> | 2022-01-03 02:14:52 +0100 |
commit | cf984689d19c3a2f532ee0005dbcce19c87e59f3 (patch) | |
tree | 52da2da7e2727d9265f1902cab40cf0eefdba583 | |
parent | fe30526e0158774da8dbc52242a4e769746259d5 (diff) | |
download | depolymerization-cf984689d19c3a2f532ee0005dbcce19c87e59f3.tar.gz depolymerization-cf984689d19c3a2f532ee0005dbcce19c87e59f3.tar.bz2 depolymerization-cf984689d19c3a2f532ee0005dbcce19c87e59f3.zip |
Handle blockchain reorganisation
-rw-r--r-- | Cargo.lock | 14 | ||||
-rw-r--r-- | btc-wire/src/main.rs | 88 | ||||
-rw-r--r-- | makefile | 1 | ||||
-rw-r--r-- | script/setup.sh | 56 | ||||
-rw-r--r-- | script/test_btc_fail.sh | 3 | ||||
-rw-r--r-- | script/test_btc_fork.sh | 147 | ||||
-rw-r--r-- | script/test_btc_reconnect.sh | 6 | ||||
-rw-r--r-- | script/test_btc_stress.sh | 7 | ||||
-rw-r--r-- | script/test_btc_wire.sh | 59 | ||||
-rw-r--r-- | taler-api/src/api_common.rs | 4 | ||||
-rw-r--r-- | test.conf | 2 |
11 files changed, 316 insertions, 71 deletions
@@ -651,13 +651,13 @@ dependencies = [ [[package]] name = "http" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1323096b05d41827dadeaee54c9981958c0f94e670bc94ed80037d1a7b8b186b" +checksum = "31f4c6746584866f0feabcc69893c5b51beef3831656a968ed7ae254cdc4fd03" dependencies = [ "bytes", "fnv", - "itoa 0.4.8", + "itoa 1.0.1", ] [[package]] @@ -1048,9 +1048,9 @@ dependencies = [ [[package]] name = "ppv-lite86" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed0cfbc8191465bed66e1718596ee0b0b35d5ee1f41c5df2189d0fe8bde535ba" +checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" [[package]] name = "proc-macro2" @@ -1689,9 +1689,9 @@ checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" [[package]] name = "version_check" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "walkdir" diff --git a/btc-wire/src/main.rs b/btc-wire/src/main.rs index b078231..83c65fb 100644 --- a/btc-wire/src/main.rs +++ b/btc-wire/src/main.rs @@ -11,12 +11,13 @@ use postgres::{fallible_iterator::FallibleIterator, Client}; use rand::{rngs::OsRng, RngCore};
use reconnect::{AutoReconnectRPC, AutoReconnectSql};
use std::{
- collections::HashMap,
+ collections::{HashMap, HashSet},
path::PathBuf,
+ process::exit,
str::FromStr,
time::{Duration, SystemTime},
};
-use taler_api::api_common::{crockford_base32_encode, Amount};
+use taler_api::api_common::{base32, Amount};
use taler_config::Config;
use taler_log::log::{error, info, warn};
use url::Url;
@@ -83,11 +84,11 @@ fn worker(mut rpc: AutoReconnectRPC, mut db: AutoReconnectSql, config: &Config) if let Some(row) = &row {
let id: i32 = row.get(0);
let amount = taler_amount_to_btc_amount(&Amount::from_str(row.get(1))?)?;
- let reserve_pub: &[u8] = row.get(2);
+ let wtid: &[u8] = row.get(2);
let addr: Address = btc_payto_addr(&Url::parse(row.get(3))?)?;
let exchange_base_url: Url = Url::parse(row.get(4))?;
let info = Info::Transaction {
- wtid: reserve_pub.try_into()?,
+ wtid: wtid.try_into()?,
url: exchange_base_url,
};
let metadata = encode_info(&info);
@@ -101,7 +102,7 @@ fn worker(mut rpc: AutoReconnectRPC, mut db: AutoReconnectSql, config: &Config) &[&(TxStatus::Sent as i16), &tx_id.as_ref(), &id],
)?;
let amount = btc_amount_to_taler_amount(&amount.to_signed().unwrap());
- info!("send {} {} in {}", addr, amount, tx_id);
+ info!(">> {} {} in {} to {}", amount, base32(&wtid), tx_id, addr);
}
Err(e) => {
info!("sender: RPC - {}", e);
@@ -139,7 +140,7 @@ fn worker(mut rpc: AutoReconnectRPC, mut db: AutoReconnectSql, config: &Config) fail_point("Skip send_op_return", 0.2)?;
match rpc.bounce(&bounced, &fee, &metadata) {
Ok(it) => {
- info!("bounce {} in {}", &bounced, &it);
+ info!("|| {} in {}", &bounced, &it);
tx.execute(
"UPDATE bounce SET txid = $1, status = $2 WHERE id = $3",
&[&it.as_ref(), &(BounceStatus::Sent as i16), &id],
@@ -150,7 +151,7 @@ fn worker(mut rpc: AutoReconnectRPC, mut db: AutoReconnectSql, config: &Config) code: ErrorCode::RpcWalletInsufficientFunds | ErrorCode::RpcWalletError,
msg,
} => {
- info!("ignore bounce {} because {}", &bounced, msg);
+ info!("|| (ignore) {} because {}", &bounced, msg);
tx.execute(
"UPDATE bounce SET status = $1 WHERE id = $2",
&[&(BounceStatus::Ignored as i16), &id],
@@ -166,7 +167,8 @@ fn worker(mut rpc: AutoReconnectRPC, mut db: AutoReconnectSql, config: &Config) // TODO check if transactions are abandoned
- let mut failed = false;
+ // Alway start with a sync work
+ let mut skip_notification = true;
loop {
let rpc = rpc.client();
let db = db.client();
@@ -176,8 +178,7 @@ fn worker(mut rpc: AutoReconnectRPC, mut db: AutoReconnectSql, config: &Config) // Wait for the next notification
{
let mut ntf = db.notifications();
- // On failure retry without waiting for notifications
- if !failed && ntf.is_empty() {
+ if !skip_notification && ntf.is_empty() {
// Block until next notification
ntf.blocking_iter().next()?;
}
@@ -205,9 +206,10 @@ fn worker(mut rpc: AutoReconnectRPC, mut db: AutoReconnectSql, config: &Config) })();
if let Err(e) = result {
error!("worker: DB - {}", e);
- failed = true;
+ // On failure retry without waiting for notifications
+ skip_notification = true;
} else {
- failed = false;
+ skip_notification = false;
}
}
}
@@ -223,7 +225,7 @@ fn sync_chain( let min_confirmations = config.confirmation;
// Get a set of transactions ids to parse
- let (txs, lastblock): (HashMap<Txid, (Category, i32)>, BlockHash) = {
+ let (txs, removed, lastblock): (HashMap<Txid, (Category, i32)>, HashSet<Txid>, BlockHash) = {
// Get all transactions made since this block
let list = rpc.list_since_block(last_hash.as_ref(), min_confirmations, true)?;
// Only keep ids and category
@@ -232,9 +234,35 @@ fn sync_chain( .into_iter()
.map(|tx| (tx.txid, (tx.category, tx.confirmations)))
.collect();
- (txs, list.lastblock)
+ let removed = list
+ .removed
+ .into_iter()
+ .filter_map(|tx| (tx.category == Category::Receive).then(|| tx.txid))
+ .collect();
+ (txs, removed, list.lastblock)
};
+ // Check if a confirmed incoming transaction have been removed by a blockchain reorganisation
+ if !removed.is_empty() {
+ for id in removed {
+ if let Ok((full, key)) = rpc.get_tx_segwit_key(&id) {
+ // If the removed tx is not in confirmed the txs list and the tx is stored in the database hard error
+ if txs
+ .get(&id)
+ .map(|(_, confirmations)| *confirmations < min_confirmations as i32)
+ .unwrap_or(true)
+ && db
+ .query_opt("SELECT 1 FROM tx_in WHERE reserve_pub=$1", &[&key.as_ref()])?
+ .is_some()
+ {
+ let credit_addr = full.details[0].address.as_ref().unwrap();
+ error!("Received transaction {} in {} from {} have been removed from the blockchain, bitcoin backing is compromised until the transaction reappear", base32(&key), id, credit_addr);
+ exit(1);
+ }
+ }
+ }
+ }
+
for (id, (category, confirmations)) in txs {
match category {
Category::Send => {
@@ -244,7 +272,7 @@ fn sync_chain( match decode_info(&bytes) {
Ok(info) => {
match info {
- Info::Transaction { wtid, url } => {
+ Info::Transaction { wtid, .. } => {
let addr = full.details[0].address.as_ref().unwrap();
let amount = btc_amount_to_taler_amount(&full.amount);
@@ -262,8 +290,11 @@ fn sync_chain( &[&(TxStatus::Sent as i16), &_id],
)?;
warn!(
- "send (recoverd) {} {} in {}",
- addr, amount, &id
+ ">> (recovered) {} {} in {} to {}",
+ amount,
+ base32(&wtid),
+ id,
+ addr
);
}
TxStatus::Sent => {}
@@ -281,10 +312,11 @@ fn sync_chain( )?;
if nb > 0 {
warn!(
- "onchain {} {} in tx {}",
- crockford_base32_encode(&wtid),
- &url,
- id
+ ">> (onchain) {} {} in {} to {}",
+ amount,
+ base32(&wtid),
+ id,
+ addr
);
}
}
@@ -303,7 +335,7 @@ fn sync_chain( "UPDATE bounce SET status=$1 where id=$2",
&[&(BounceStatus::Sent as i16), &_id],
)?;
- warn!("recovered bounce {} in {}", &bounced, &id);
+ warn!("|| (recovered) {} in {}", &bounced, &id);
}
BounceStatus::Ignored => error!("watcher: ignored bounce {} found in chain at {}", bounced, id),
BounceStatus::Sent => {}
@@ -314,7 +346,7 @@ fn sync_chain( &[&bounced.as_ref(), &id.as_ref(), &(BounceStatus::Sent as i16)],
)?;
if nb > 0 {
- warn!("onchain bounce {} in {}", &bounced, &id);
+ warn!("|| (onchain) {} in {}", &bounced, &id);
}
}
}
@@ -342,8 +374,11 @@ fn sync_chain( ])?;
if nb > 0 {
info!(
- "receive {} << {} {} in {}",
- &debit_addr, &credit_addr, &amount, &id
+ "<< {} {} in {} from {}",
+ amount,
+ base32(&reserve_pub),
+ id,
+ debit_addr
);
}
}
@@ -433,7 +468,6 @@ fn main() { let db_listener = AutoReconnectSql::new(&config.db_url, Duration::from_secs(5));
let db_worker = AutoReconnectSql::new(&config.db_url, Duration::from_secs(5));
- let join = std::thread::spawn(move || block_listener(rpc_listener, db_listener));
+ std::thread::spawn(move || block_listener(rpc_listener, db_listener));
worker(rpc_worker, db_worker, config);
- join.join().unwrap();
}
@@ -7,4 +7,5 @@ test: script/test_btc_wire.sh
script/test_btc_reconnect.sh
script/test_btc_fail.sh
+ script/test_btc_fork.sh
script/test_btc_stress.sh
\ No newline at end of file diff --git a/script/setup.sh b/script/setup.sh index ef3896a..080ed75 100644 --- a/script/setup.sh +++ b/script/setup.sh @@ -19,9 +19,11 @@ trap cleanup EXIT DIR=$(mktemp -d) BTC_DIR=$DIR/bitcoin +BTC_DIR2=$DIR/bitcoin2 DB_DIR=$DIR/db -mkdir -p $BTC_DIR -mkdir -p $DB_DIR +for dir in $BTC_DIR $BTC_DIR2 $DB_DIR; do + mkdir -p $dir +done # Load test.conf as bash variables function load_config() { @@ -29,6 +31,8 @@ function load_config() { BANK_ENDPOINT=http://127.0.0.1:$PORT/ } +# ----- Database ----- # + # Create new postgresql cluster and init database schema function setup_db() { pg_ctl init -D $DB_DIR &> /dev/null @@ -43,20 +47,47 @@ function reset_db() { psql $DB_URL < wire-gateway/db/schema.sql > /dev/null } -# Start a bitcoind regtest server in a temporary directory +# ----- Bitcoin node ----- # + +# 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 - BTC_CLI="bitcoin-cli -regtest -datadir=$BTC_DIR" - bitcoind -datadir=$BTC_DIR &> btc.log & + BTC_CLI="bitcoin-cli -datadir=$BTC_DIR" + bitcoind -datadir=$BTC_DIR -port=8345 &> 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 + BTC_CLI2="bitcoin-cli -datadir=$BTC_DIR2" + bitcoind -datadir=$BTC_DIR2 -port=8346 &> btc2.log & + $BTC_CLI2 -rpcwait getnetworkinfo > /dev/null + $BTC_CLI addnode 127.0.0.1:8346 onetry +} + +# Disconnect the two nodes +function btc2_deco() { + $BTC_CLI disconnectnode 127.0.0.1:8346 +} + +# Create a fork on the second node and reconnect the two node +function btc2_fork() { + $BTC_CLI2 generatetoaddress ${1:-50} $RESERVE > /dev/null + $BTC_CLI addnode 127.0.0.1:8346 onetry + sleep 1 +} + # Start a bitcoind regest server in a previously created temporary directory and load wallets function restart_btc() { - BTC_CLI="bitcoin-cli -regtest -datadir=$BTC_DIR" - bitcoind -datadir=$BTC_DIR -fallbackfee=0.00000001 &>> btc.log & + bitcoind -datadir=$BTC_DIR &>> btc.log & $BTC_CLI -rpcwait getnetworkinfo > /dev/null for wallet in wire client reserve; do $BTC_CLI loadwallet $wallet > /dev/null @@ -76,6 +107,11 @@ function setup_btc() { mine_btc } +function stop_btc() { + kill $BTC_PID + wait $BTC_PID +} + # Mine blocks function mine_btc() { $BTC_CLI generatetoaddress "${1:-1}" $RESERVE > /dev/null @@ -105,16 +141,20 @@ function check_balance() { fi } +# ----- btc-wire ----- # + # Start btc_wire function btc_wire() { cargo build --bin btc-wire --release &> /dev/null target/release/btc-wire $BTC_DIR &> 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 & + WIRE_PID="$!" } # Start multiple btc_wire in parallel @@ -124,6 +164,8 @@ function stressed_btc_wire() { target/release/btc-wire $BTC_DIR &> btc_wire1.log & } +# ----- Gateway ------ # + # Start wire_gateway in test mode function gateway() { cargo build --bin wire-gateway --release --features test &> /dev/null diff --git a/script/test_btc_fail.sh b/script/test_btc_fail.sh index 849a525..ee7e23b 100644 --- a/script/test_btc_fail.sh +++ b/script/test_btc_fail.sh @@ -13,7 +13,7 @@ echo "Start database" setup_db echo "Start bitcoin node" init_btc -echo "Start bitcoin regtest" +echo "Setup bitcoin" setup_btc echo "Start failing btc-wire" fail_btc_wire @@ -73,6 +73,7 @@ for n in `$SEQ`; do $BTC_CLI -rpcwallet=client sendtoaddress $WIRE 0.000$n > /dev/null mine_btc done +next_btc sleep 20 echo " OK" diff --git a/script/test_btc_fork.sh b/script/test_btc_fork.sh new file mode 100644 index 0000000..1bfc8e8 --- /dev/null +++ b/script/test_btc_fork.sh @@ -0,0 +1,147 @@ +#!/bin/bash + +## Test btc_wire correctness when a blockchain reorganisation occurs + +set -eu + +source "${BASH_SOURCE%/*}/setup.sh" + +echo "----- Setup -----" +echo "Load config file" +load_config +echo "Start database" +setup_db +echo "Start bitcoin node" +init_btc +echo "Setup bitcoin" +setup_btc +echo "Start second bitcoin node" +init_btc2 +echo "Start btc-wire" +btc_wire +echo "Start gateway" +gateway +echo "" + +# Check btc-wire is running +function check_up() { + if [ `ps -p $WIRE_PID | grep -c $WIRE_PID` == 0 ]; then + echo "btc_wire with pid $WIRE_PID should be up" + ps -p $WIRE_PID + exit 1 + fi +} + +# Check btc-wire is not running +function check_down() { + if [ `ps -p $WIRE_PID | grep -c $WIRE_PID` != 0 ]; then + echo "btc_wire with pid $WIRE_PID should be down" + ps -p $WIRE_PID + exit 1 + fi +} + +SEQ="seq 10 20" + +echo "----- Handle reorg incoming transactions -----" + +echo "Loose second bitcoin node" +btc2_deco + +echo -n "Gen incoming transactions:" +for n in `$SEQ`; do + btc-wire-cli -d $BTC_DIR transfer 0.000$n + mine_btc # Mine transactions +done +next_btc # Trigger btc_wire +check_delta "incoming?delta=-100" "$SEQ" "0.000" +check_balance 9.99826299 0.00165000 +echo " OK" + +echo -n "Perform fork and check btc-wire hard error:" +check_up +btc2_fork +check_balance 9.99826299 0.00000000 +check_down +echo " OK" + +echo -n "Check btc-wire hard error on restart:" +btc_wire +sleep 1 +check_down +echo " OK" + +echo -n "Recover orphaned transactions:" +next_btc +check_balance 9.99826299 0.00165000 +echo " OK" + +echo -n "Check btc-wire heal on restart:" +btc_wire +sleep 1 +check_up +echo " OK" + +echo "----- Handle reorg outgoing transactions -----" + +echo "Loose second bitcoin node" +btc2_deco + +echo -n "Gen outgoing transactions:" +for n in `$SEQ`; do + taler-exchange-wire-gateway-client \ + -b $BANK_ENDPOINT \ + -C payto://bitcoin/$CLIENT \ + -a BTC:0.0000$n > /dev/null +done +sleep 1 +mine_btc # Mine transactions +check_delta "outgoing?delta=-100" "$SEQ" +check_balance 9.99842799 0.00146311 +echo " OK" + +echo -n "Perform fork and check btc-wire still up:" +check_up +btc2_fork +check_balance 9.99826299 0.00146311 +check_up +echo " OK" + +echo -n "Recover orphaned transactions:" +next_btc +check_balance 9.99842799 0.00146311 +echo " OK" + +echo "----- Handle reorg bounce -----" + +echo -n "Clear wire wallet:" +$BTC_CLI -rpcwallet=wire sendtoaddress $CLIENT `$BTC_CLI -rpcwallet=wire getbalance` "" "" true > /dev/null +mine_btc +echo " OK" + +echo "Loose second bitcoin node" +btc2_deco + +echo -n "Generate bounce:" +for n in `$SEQ`; do + $BTC_CLI -rpcwallet=client sendtoaddress $WIRE 0.000$n > /dev/null + mine_btc +done +next_btc +sleep 1 +check_balance "*" 0.00011000 +echo " OK" + +echo -n "Perform fork and check btc-wire still up:" +check_up +btc2_fork +check_balance "*" 0.00000000 +check_up +echo " OK" + +echo -n "Recover orphaned transactions:" +next_btc +check_balance "*" 0.00011000 +echo " OK" + +echo "All tests passed"
\ No newline at end of file diff --git a/script/test_btc_reconnect.sh b/script/test_btc_reconnect.sh index 3ab9292..32088b8 100644 --- a/script/test_btc_reconnect.sh +++ b/script/test_btc_reconnect.sh @@ -13,7 +13,7 @@ echo "Start database" setup_db echo "Start bitcoin node" init_btc -echo "Start bitcoin regtest" +echo "Setup bitcoin" setup_btc echo "Start btc-wire" btc_wire @@ -40,9 +40,7 @@ btc-wire-cli -d $BTC_DIR transfer 0.00004 next_btc check_balance 9.99948077 0.00050200 echo "Stop bitcoin node" -PID=`jobs -p bitcoind` -kill $PID -wait $PID +stop_btc echo -n "Requesting exchange incoming transaction list:" taler-exchange-wire-gateway-client -b $BANK_ENDPOINT -i 2>&1 | grep -q "504" && echo " OK" || echo " Failed" diff --git a/script/test_btc_stress.sh b/script/test_btc_stress.sh index 91f8f8b..10c7021 100644 --- a/script/test_btc_stress.sh +++ b/script/test_btc_stress.sh @@ -13,7 +13,7 @@ echo "Start database" setup_db echo "Start bitcoin node" init_btc -echo "Start bitcoin regtest" +echo "Setup bitcoin" setup_btc echo "Start btc-wire stressed" stressed_btc_wire @@ -97,7 +97,10 @@ for n in `$SEQ`; do $BTC_CLI -rpcwallet=client sendtoaddress $WIRE 0.000$n > /dev/null mine_btc done -sleep 20 +next_btc +sleep 10 +mine_btc +sleep 10 echo " OK" echo -n "Check balance:" diff --git a/script/test_btc_wire.sh b/script/test_btc_wire.sh index 3b48bae..6559bac 100644 --- a/script/test_btc_wire.sh +++ b/script/test_btc_wire.sh @@ -13,7 +13,7 @@ echo "Start database" setup_db echo "Start bitcoin node" init_btc -echo "Start bitcoin regtest" +echo "Setup bitcoin" setup_btc echo "Start btc-wire" btc_wire @@ -21,37 +21,56 @@ echo "Start gateway" gateway echo "" -echo "---- Receive -----" +SEQ="seq 10 20" + +echo "----- Receive -----" echo -n "Making wire transfer to exchange:" -btc-wire-cli -d $BTC_DIR transfer 0.00004 -next_btc -check_balance 9.99995209 0.00004000 +for n in `$SEQ`; do + btc-wire-cli -d $BTC_DIR transfer 0.000$n + mine_btc # Mine transactions +done +next_btc # Trigger btc_wire +check_balance 9.99826299 0.00165000 echo " OK" echo -n "Requesting exchange incoming transaction list:" -taler-exchange-wire-gateway-client -b $BANK_ENDPOINT -i | grep BTC:0.00004 > /dev/null +check_delta "incoming?delta=-100" "$SEQ" "0.000" echo " OK" -echo "---- Bounce-----" -$BTC_CLI -rpcwallet=client sendtoaddress $WIRE 0.00042 -next_btc -check_balance 9.99993883 0.00005000 - -echo "---- Send -----" +echo "----- Send -----" echo -n "Making wire transfer from exchange:" -taler-exchange-wire-gateway-client \ - -b $BANK_ENDPOINT \ - -C payto://bitcoin/$CLIENT \ - -a BTC:0.00002 > /dev/null -sleep 0.3 -mine_btc -check_balance 9.99995883 0.00002801 +for n in `$SEQ`; do + taler-exchange-wire-gateway-client \ + -b $BANK_ENDPOINT \ + -C payto://bitcoin/$CLIENT \ + -a BTC:0.0000$n > /dev/null +done +sleep 1 +mine_btc # Mine transactions +check_balance 9.99842799 0.00146311 echo " OK" echo -n "Requesting exchange's outgoing transaction list:" -taler-exchange-wire-gateway-client -b $BANK_ENDPOINT -o | grep BTC:0.00002 > /dev/null +check_delta "outgoing?delta=-100" "$SEQ" +echo " OK" + +echo "----- Bounce -----" + +echo -n "Clear wire wallet:" +$BTC_CLI -rpcwallet=wire sendtoaddress $CLIENT `$BTC_CLI -rpcwallet=wire getbalance` "" "" true > /dev/null +mine_btc +echo " OK" + +echo -n "Bounce:" +for n in `$SEQ`; do + $BTC_CLI -rpcwallet=client sendtoaddress $WIRE 0.000$n > /dev/null + mine_btc +done +next_btc +sleep 1 +check_balance "*" 0.00011000 echo " OK" echo "All tests passed"
\ No newline at end of file diff --git a/taler-api/src/api_common.rs b/taler-api/src/api_common.rs index 778e884..ab635ec 100644 --- a/taler-api/src/api_common.rs +++ b/taler-api/src/api_common.rs @@ -296,13 +296,13 @@ impl<const L: usize> FromStr for Base32<L> { }
}
-pub fn crockford_base32_encode(bytes: &[u8]) -> String {
+pub fn base32(bytes: &[u8]) -> String {
base32::encode(base32::Alphabet::Crockford, bytes)
}
impl<const L: usize> Display for Base32<L> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- f.write_str(&crockford_base32_encode(&self.0))
+ f.write_str(&base32(&self.0))
}
}
@@ -6,7 +6,7 @@ DB_URL = postgres://localhost:5454/postgres?user=postgres&password=passwor PORT = 8060 UNIXPATH = TODO PAYTO = payto://bitcoin/bcrt1qgkgxkjj27g3f7s87mcvjjsghay7gh34cx39prj -CONFIRMATION = 1 +CONFIRMATION = 3 BTC_WALLET = wire BTC_DATA_DIR = ~/.bitcoin BOUNCE_FEE = 1000
\ No newline at end of file |