gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[taler-depolymerization] branch master updated (0412d20 -> 4a83288)


From: gnunet
Subject: [taler-depolymerization] branch master updated (0412d20 -> 4a83288)
Date: Thu, 27 Jan 2022 17:55:44 +0100

This is an automated email from the git hooks/post-receive script.

antoine pushed a change to branch master
in repository depolymerization.

    from 0412d20  Update dependencies
     new 32fc54e  Break long function in two and other improvements
     new 906264d  Remove fastrand when rand is used and improve taler_common
     new 4a83288  Presentation draft 2

The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .gitignore                                     |   6 +-
 Cargo.lock                                     |  11 +-
 README.md                                      |   4 +-
 btc-wire/Cargo.toml                            |   9 -
 btc-wire/benches/metadata.rs                   |  10 +-
 btc-wire/src/bin/btc-wire-cli.rs               |   2 +-
 btc-wire/src/bin/btc-wire-utils.rs             |  12 +-
 btc-wire/src/bin/test.rs                       |   4 +-
 btc-wire/src/fail_point.rs                     |   2 +-
 btc-wire/src/info.rs                           |   9 +-
 btc-wire/src/lib.rs                            |   1 -
 btc-wire/src/loops.rs                          |   3 +-
 btc-wire/src/loops/analysis.rs                 |   2 +-
 btc-wire/src/loops/{listener.rs => watcher.rs} |   4 +-
 btc-wire/src/loops/worker.rs                   | 326 +++++++++++++------------
 btc-wire/src/main.rs                           |  16 +-
 btc-wire/src/reconnect.rs                      |   2 +-
 btc-wire/src/rpc.rs                            |   2 +-
 btc-wire/src/segwit.rs                         |  25 +-
 btc-wire/src/sql.rs                            |   2 +-
 btc-wire/src/taler_util.rs                     |   2 +-
 btc-wire/src/test.rs                           |  26 --
 docs/fee.png                                   | Bin 0 -> 25200 bytes
 docs/presentation.tex                          | 221 +++++++++++++++++
 docs/taler.png                                 | Bin 0 -> 24424 bytes
 taler-common/Cargo.toml                        |   2 +
 taler-common/src/lib.rs                        |  12 +-
 wire-gateway/Cargo.toml                        |   3 -
 wire-gateway/src/main.rs                       |   5 +-
 29 files changed, 470 insertions(+), 253 deletions(-)
 rename btc-wire/src/loops/{listener.rs => watcher.rs} (91%)
 delete mode 100644 btc-wire/src/test.rs
 create mode 100644 docs/fee.png
 create mode 100644 docs/presentation.tex
 create mode 100644 docs/taler.png

diff --git a/.gitignore b/.gitignore
index d1791f9..1d69ca7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,7 @@
 /target
 log
-/.vscode
\ No newline at end of file
+/.vscode
+/docs/*
+!/docs/*.docx
+!/docs/*.tex
+!/docs/*.png
\ No newline at end of file
diff --git a/Cargo.lock b/Cargo.lock
index 964143b..4d27de6 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -155,9 +155,6 @@ dependencies = [
  "bech32",
  "bitcoin",
  "criterion",
- "fastrand",
- "postgres",
- "rand",
  "rust-ini",
  "serde",
  "serde_json",
@@ -165,7 +162,6 @@ dependencies = [
  "taler-common",
  "thiserror",
  "uri-pack",
- "url",
 ]
 
 [[package]]
@@ -799,9 +795,9 @@ checksum = 
"e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
 
 [[package]]
 name = "libc"
-version = "0.2.113"
+version = "0.2.114"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "eef78b64d87775463c549fbd80e19249ef436ea3bf1de2a1eb7e717ec7fab1e9"
+checksum = "b0005d08a8f7b65fb8073cb697aa0b12b631ed251ce73d862ce50eeb52ce3b50"
 
 [[package]]
 name = "listenfd"
@@ -1489,6 +1485,7 @@ dependencies = [
  "flexi_logger",
  "log",
  "postgres",
+ "rand",
  "rust-ini",
  "serde",
  "serde_json",
@@ -1876,8 +1873,6 @@ dependencies = [
  "hyperlocal",
  "listenfd",
  "miniz_oxide",
- "postgres",
- "rand",
  "serde",
  "serde_json",
  "serde_urlencoded",
diff --git a/README.md b/README.md
index 53b2009..48ab3da 100644
--- a/README.md
+++ b/README.md
@@ -51,7 +51,7 @@ Modules have specific configuration:
 
 ```
  ┌─────┐   ┌────────────────┐   ┌──────────┐
- │Taler├───┤Depolymerization├───┤Blockchain│
+ │Taler│◄─►│Depolymerization│◄─►│Blockchain│
  └─────┘   └────────────────┘   └──────────┘
 ```
 
@@ -59,6 +59,6 @@ Modules have specific configuration:
 
 ```
  ┌────────────┐   ┌──────────┐   ┌────────┐
- │wire_gateway├───┤PostgreSQL├───┤###_wire│
+ │wire_gateway│◄─►│PostgreSQL│◄─►│###_wire│
  └────────────┘   └──────────┘   └────────┘
 ```
\ No newline at end of file
diff --git a/btc-wire/Cargo.toml b/btc-wire/Cargo.toml
index 019eb09..8a5abcb 100644
--- a/btc-wire/Cargo.toml
+++ b/btc-wire/Cargo.toml
@@ -18,23 +18,14 @@ bitcoin = { version = "0.27.1", features = [
 argh = "0.1.7"
 # Bech32 encoding and decoding
 bech32 = "0.8.1"
-# Secure random
-rand = { version = "0.8.4", features = ["getrandom"] }
-# Fast insecure random
-fastrand = "1.7.0"
 # Serialization library
 serde = { version = "1.0.133", features = ["derive"] }
 serde_json = "1.0.75"
 serde_repr = "0.1.7"
 # Error macros
 thiserror = "1.0.30"
-# Postgres client
-postgres = "0.19.2"
 # Optimized uri binary format
 uri-pack = { path = "../uri-pack" }
-# Url format
-url = { version = "2.2.2", features = ["serde"] }
-# Ansi color
 base64 = "0.13.0"
 # Taler libs
 taler-common = {path = "../taler-common"}
diff --git a/btc-wire/benches/metadata.rs b/btc-wire/benches/metadata.rs
index 5418e0f..da6f557 100644
--- a/btc-wire/benches/metadata.rs
+++ b/btc-wire/benches/metadata.rs
@@ -13,24 +13,22 @@
   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 btc_wire::{
-    segwit::{decode_segwit_msg, encode_segwit_key, rand_addresses},
-    test::rand_key,
-};
+use btc_wire::segwit::{decode_segwit_msg, encode_segwit_key, rand_addresses};
 use criterion::{criterion_group, criterion_main, Criterion};
+use taler_common::rand_slice;
 
 fn criterion_benchmark(c: &mut Criterion) {
     let mut group = c.benchmark_group("SegWit addresses");
     group.bench_function("encode", |b| {
         b.iter_batched(
-            rand_key,
+            || rand_slice(),
             |key| encode_segwit_key("bench", &key),
             criterion::BatchSize::SmallInput,
         );
     });
     group.bench_function("decode", |b| {
         b.iter_batched(
-            || rand_addresses("bench", &rand_key()),
+            || rand_addresses("bench", &rand_slice()),
             |addrs| decode_segwit_msg(&addrs),
             criterion::BatchSize::SmallInput,
         );
diff --git a/btc-wire/src/bin/btc-wire-cli.rs b/btc-wire/src/bin/btc-wire-cli.rs
index 46bd424..992e18c 100644
--- a/btc-wire/src/bin/btc-wire-cli.rs
+++ b/btc-wire/src/bin/btc-wire-cli.rs
@@ -18,7 +18,7 @@ use btc_wire::{
     rpc::{BtcRpc, Error, ErrorCode},
     rpc_utils::default_data_dir,
 };
-use postgres::{Client, NoTls};
+use taler_common::postgres::{NoTls, Client};
 
 fn main() {
     let args: Vec<_> = std::env::args().collect();
diff --git a/btc-wire/src/bin/btc-wire-utils.rs 
b/btc-wire/src/bin/btc-wire-utils.rs
index 7f38033..c65d462 100644
--- a/btc-wire/src/bin/btc-wire-utils.rs
+++ b/btc-wire/src/bin/btc-wire-utils.rs
@@ -20,10 +20,8 @@ use btc_wire::{
     config::BitcoinConfig,
     rpc::{BtcRpc, Category, Error, ErrorCode},
     rpc_utils::default_data_dir,
-    test::rand_key,
 };
-use postgres::{Client, NoTls};
-use taler_common::config::Config;
+use taler_common::{config::Config, rand_slice, postgres::{NoTls, Client}};
 
 #[derive(argh::FromArgs)]
 /// Bitcoin wire test client
@@ -115,9 +113,9 @@ impl App {
             }
         }
         let mut wallet = BtcRpc::wallet(&self.config, name).unwrap();
-        let addr = wallet.get_new_address().unwrap_or_else(|_| {
-            panic!("Failed to get wallet address {}", name)
-        });
+        let addr = wallet
+            .get_new_address()
+            .unwrap_or_else(|_| panic!("Failed to get wallet address {}", 
name));
         (wallet, addr)
     }
 
@@ -149,7 +147,7 @@ fn main() {
             let (mut client, _) = app.auto_wallet(&from);
             let (_, to) = app.auto_wallet(&to);
             let tx = client
-                .send_segwit_key(&to, &Amount::from_btc(amount).unwrap(), 
&rand_key())
+                .send_segwit_key(&to, &Amount::from_btc(amount).unwrap(), 
&rand_slice())
                 .unwrap();
             println!("{}", tx);
         }
diff --git a/btc-wire/src/bin/test.rs b/btc-wire/src/bin/test.rs
index e1d5085..eb150e5 100644
--- a/btc-wire/src/bin/test.rs
+++ b/btc-wire/src/bin/test.rs
@@ -21,8 +21,8 @@ use btc_wire::{
     config::BitcoinConfig,
     rpc::{self, BtcRpc, Category},
     rpc_utils::{default_data_dir, CLIENT, WIRE},
-    test::rand_key,
 };
+use taler_common::rand_slice;
 
 const RESERVE: &str = "reserve";
 
@@ -188,7 +188,7 @@ pub fn main() {
     });
     runner.test("SegWit metadata", || {
         // Send metadata
-        let key = rand_key();
+        let key = rand_slice();
         let id = client_rpc
             .send_segwit_key(&wire_addr, &test_amount, &key)
             .unwrap();
diff --git a/btc-wire/src/fail_point.rs b/btc-wire/src/fail_point.rs
index 58d894f..ad88b3a 100644
--- a/btc-wire/src/fail_point.rs
+++ b/btc-wire/src/fail_point.rs
@@ -21,7 +21,7 @@ pub struct Injected(&'static str);
 #[allow(unused_variables)]
 pub fn fail_point(msg: &'static str, prob: f32) -> Result<(), Injected> {
     #[cfg(feature = "fail")]
-    return if fastrand::f32() < prob {
+    return if taler_common::rand::random::<f32>() < prob {
         Err(Injected(msg))
     } else {
         Ok(())
diff --git a/btc-wire/src/info.rs b/btc-wire/src/info.rs
index fd4ff08..23467ea 100644
--- a/btc-wire/src/info.rs
+++ b/btc-wire/src/info.rs
@@ -14,7 +14,7 @@
   TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
 */
 use bitcoin::{hashes::Hash, Txid};
-use url::Url;
+use taler_common::url::Url;
 
 #[derive(Debug, Clone, Copy, thiserror::Error)]
 pub enum DecodeErr {
@@ -87,8 +87,7 @@ pub fn decode_info(bytes: &[u8]) -> Result<Info, DecodeErr> {
 #[cfg(test)]
 mod test {
     use bitcoin::{hashes::Hash, Txid};
-    use btc_wire::test::rand_key;
-    use url::Url;
+    use taler_common::{rand_slice, url::Url};
 
     use crate::info::{decode_info, encode_info, Info};
 
@@ -101,7 +100,7 @@ mod test {
             "http://git.taler.net/depolymerization.git/";,
         ];
         for url in urls {
-            let wtid = rand_key();
+            let wtid = rand_slice();
             let url = Url::parse(url).unwrap();
             let info = Info::Transaction { wtid, url };
             let encode = encode_info(&info);
@@ -113,7 +112,7 @@ mod test {
     #[test]
     fn decode_encode_bounce() {
         for _ in 0..4 {
-            let id = rand_key();
+            let id: [u8; 32] = rand_slice();
             let info = Info::Bounce {
                 bounced: Txid::from_slice(&id).unwrap(),
             };
diff --git a/btc-wire/src/lib.rs b/btc-wire/src/lib.rs
index 9b865bf..4f824c9 100644
--- a/btc-wire/src/lib.rs
+++ b/btc-wire/src/lib.rs
@@ -24,7 +24,6 @@ pub mod config;
 pub mod rpc;
 pub mod rpc_utils;
 pub mod segwit;
-pub mod test;
 
 #[derive(Debug, thiserror::Error)]
 pub enum GetSegwitErr {
diff --git a/btc-wire/src/loops.rs b/btc-wire/src/loops.rs
index 6009c59..999a671 100644
--- a/btc-wire/src/loops.rs
+++ b/btc-wire/src/loops.rs
@@ -15,11 +15,12 @@
 */
 
 use btc_wire::rpc;
+use taler_common::postgres;
 
 use crate::fail_point::Injected;
 
 pub mod analysis;
-pub mod listener;
+pub mod watcher;
 pub mod worker;
 
 #[derive(Debug, thiserror::Error)]
diff --git a/btc-wire/src/loops/analysis.rs b/btc-wire/src/loops/analysis.rs
index 2981b50..07d5f1c 100644
--- a/btc-wire/src/loops/analysis.rs
+++ b/btc-wire/src/loops/analysis.rs
@@ -16,10 +16,10 @@
 use std::sync::atomic::Ordering;
 
 use btc_wire::rpc::ChainTipsStatus;
-use postgres::fallible_iterator::FallibleIterator;
 use taler_common::{
     config::Config,
     log::log::{error, warn},
+    postgres::fallible_iterator::FallibleIterator,
 };
 
 use crate::{
diff --git a/btc-wire/src/loops/listener.rs b/btc-wire/src/loops/watcher.rs
similarity index 91%
rename from btc-wire/src/loops/listener.rs
rename to btc-wire/src/loops/watcher.rs
index 66defc7..f7f5543 100644
--- a/btc-wire/src/loops/listener.rs
+++ b/btc-wire/src/loops/watcher.rs
@@ -20,7 +20,7 @@ use crate::reconnect::{AutoReconnectRPC, AutoReconnectSql};
 use super::LoopResult;
 
 /// Wait for new block and notify arrival with postgreSQL notifications
-pub fn block_listener(mut rpc: AutoReconnectRPC, mut db: AutoReconnectSql) {
+pub fn watcher(mut rpc: AutoReconnectRPC, mut db: AutoReconnectSql) {
     loop {
         let rpc = rpc.client();
         let db = db.client();
@@ -29,7 +29,7 @@ pub fn block_listener(mut rpc: AutoReconnectRPC, mut db: 
AutoReconnectSql) {
             db.execute("NOTIFY new_block", &[])?;
         })();
         if let Err(e) = result {
-            error!("listener: {}", e);
+            error!("watcher: {}", e);
         }
     }
 }
diff --git a/btc-wire/src/loops/worker.rs b/btc-wire/src/loops/worker.rs
index d30faa5..aa45664 100644
--- a/btc-wire/src/loops/worker.rs
+++ b/btc-wire/src/loops/worker.rs
@@ -22,7 +22,7 @@ use std::{
 
 use bitcoin::{hashes::Hash, Amount as BtcAmount, BlockHash, Txid};
 use btc_wire::{
-    rpc::{self, BtcRpc, Category, ErrorCode},
+    rpc::{self, BtcRpc, Category, ErrorCode, TransactionFull},
     rpc_utils::sender_address,
     GetOpReturnErr, GetSegwitErr,
 };
@@ -31,6 +31,7 @@ use taler_common::{
     api_common::base32,
     config::Config,
     log::log::{error, info, warn},
+    postgres,
     sql::{sql_array, sql_url},
 };
 
@@ -142,7 +143,7 @@ fn send(db: &mut Client, rpc: &mut BtcRpc, status: 
TxStatus) -> LoopResult<bool>
     assert!(status == TxStatus::Delayed || status == TxStatus::Requested);
     // We rely on the advisory lock to ensure we are the only one sending 
transactions
     let row = db.query_opt(
-        "SELECT id, amount, wtid, credit_acc, exchange_url FROM tx_out WHERE 
status=$1 LIMIT 1",
+        "SELECT id, amount, wtid, credit_acc, exchange_url FROM tx_out WHERE 
status=$1 ORDER BY _date LIMIT 1",
         &[&(status as i16)],
     )?;
     if let Some(row) = &row {
@@ -186,7 +187,7 @@ fn bounce(
     assert!(status == BounceStatus::Delayed || status == 
BounceStatus::Requested);
     // We rely on the advisory lock to ensure we are the only one sending 
transactions
     let row = db.query_opt(
-        "SELECT id, bounced FROM bounce WHERE status=$1 LIMIT 1",
+        "SELECT id, bounced FROM bounce WHERE status=$1 ORDER BY _date LIMIT 
1",
         &[&(status as i16)],
     )?;
     if let Some(row) = &row {
@@ -405,168 +406,193 @@ fn sync_chain_outgoing(
     {
         Ok((full, Ok(info))) => match info {
             Info::Transaction { wtid, .. } => {
-                let credit_addr = full.details[0].address.as_ref().unwrap();
-                let amount = btc_to_taler(&full.amount);
-
-                if confirmations < 0 {
-                    if full.replaced_by_txid.is_none() {
-                        // Handle conflicting tx
-                        let nb_row = db.execute(
-                            "UPDATE tx_out SET status=$1, txid=NULL where 
txid=$2",
-                            &[&(TxStatus::Delayed as i16), &id.as_ref()],
-                        )?;
-                        if nb_row > 0 {
-                            warn!(
-                                ">> (conflict) {} in {} to {}",
-                                base32(&wtid),
-                                id,
-                                credit_addr
-                            );
-                        }
-                    }
-                } else {
-                    // Get previous out tx
-                    let row = db.query_opt(
-                        "SELECT id, status, txid FROM tx_out WHERE wtid=$1 FOR 
UPDATE",
-                        &[&wtid.as_ref()],
+                sync_chain_outgoing_send(id, &full, &wtid, rpc, db, 
confirmations, config)?
+            }
+            Info::Bounce { bounced } => {
+                sync_chain_outgoing_bounce(id, &bounced, db, confirmations)?
+            }
+        },
+        Ok((_, Err(e))) => warn!("send: decode-info {} - {}", id, e),
+        Err(e) => match e {
+            GetOpReturnErr::MissingOpReturn => { /* Ignore */ }
+            GetOpReturnErr::RPC(e) => return Err(e)?,
+        },
+    }
+    Ok(())
+}
+
+/// Sync database with an outgoing send transaction
+fn sync_chain_outgoing_send(
+    id: &Txid,
+    full: &TransactionFull,
+    wtid: &[u8; 32],
+    rpc: &mut BtcRpc,
+    db: &mut Client,
+    confirmations: i32,
+    config: &Config,
+) -> LoopResult<()> {
+    let credit_addr = full.details[0].address.as_ref().unwrap();
+    let amount = btc_to_taler(&full.amount);
+
+    if confirmations < 0 {
+        if full.replaced_by_txid.is_none() {
+            // Handle conflicting tx
+            let nb_row = db.execute(
+                "UPDATE tx_out SET status=$1, txid=NULL where txid=$2",
+                &[&(TxStatus::Delayed as i16), &id.as_ref()],
+            )?;
+            if nb_row > 0 {
+                warn!(
+                    ">> (conflict) {} in {} to {}",
+                    base32(wtid),
+                    id,
+                    credit_addr
+                );
+            }
+        }
+    } else {
+        // Get previous out tx
+        let row = db.query_opt(
+            "SELECT id, status, txid FROM tx_out WHERE wtid=$1 FOR UPDATE",
+            &[&wtid.as_ref()],
+        )?;
+        if let Some(row) = row {
+            // If already in database, sync status
+            let row_id: i32 = row.get(0);
+            let status: i16 = row.get(1);
+            match TxStatus::try_from(status as u8).unwrap() {
+                TxStatus::Requested | TxStatus::Delayed => {
+                    let nb_row = db.execute(
+                        "UPDATE tx_out SET status=$1, txid=$2 WHERE id=$3 AND 
status=$4",
+                        &[&(TxStatus::Sent as i16), &id.as_ref(), &row_id, 
&status],
                     )?;
-                    if let Some(row) = row {
-                        // If already in database sync status
-                        let row_id: i32 = row.get(0);
-                        let status: i16 = row.get(1);
-                        match TxStatus::try_from(status as u8).unwrap() {
-                            TxStatus::Requested | TxStatus::Delayed => {
-                                let nb_row = db.execute(
-                                    "UPDATE tx_out SET status=$1, txid=$2 
WHERE id=$3 AND status=$4",
-                                    &[&(TxStatus::Sent as i16), &id.as_ref(), 
&row_id, &status],
-                                )?;
-                                if nb_row > 0 {
-                                    warn!(
-                                        ">> (recovered) {} {} in {} to {}",
-                                        amount,
-                                        base32(&wtid),
-                                        id,
-                                        credit_addr
-                                    );
-                                }
-                            }
-                            TxStatus::Sent => {
-                                if let Some(txid) = full.replaces_txid {
-                                    let stored_id = sql_txid(&row, 2);
-                                    if txid == stored_id {
-                                        let nb_row = db.execute(
-                                            "UPDATE tx_out SET txid=$1 WHERE 
txid=$2",
-                                            &[&id.as_ref(), &txid.as_ref()],
-                                        )?;
-                                        if nb_row > 0 {
-                                            info!(
-                                                ">> (recovered) {} replace {} 
with {}",
-                                                base32(&wtid),
-                                                txid,
-                                                id
-                                            );
-                                        }
-                                    }
-                                }
-                            }
-                        }
-                    } else {
-                        // Else add to database
-                        let debit_addr = sender_address(rpc, &full)?;
-                        let date = SystemTime::UNIX_EPOCH + 
Duration::from_secs(full.time);
-                        let nb = db.execute(
-                    "INSERT INTO tx_out (_date, amount, wtid, debit_acc, 
credit_acc, exchange_url, status, txid, request_uid) VALUES ($1, $2, $3, $4, 
$5, $6, $7, $8, $9) ON CONFLICT (wtid) DO NOTHING",
-                    &[&date, &amount.to_string(), &wtid.as_ref(), 
&btc_payto_url(&debit_addr).as_ref(), &btc_payto_url(credit_addr).as_ref(), 
&config.base_url.as_ref(), &(TxStatus::Sent as i16), &id.as_ref(), 
&None::<&[u8]>],
-                        )?;
-                        if nb > 0 {
-                            warn!(
-                                ">> (onchain) {} {} in {} to {}",
-                                amount,
-                                base32(&wtid),
-                                id,
-                                credit_addr
-                            );
-                        }
+                    if nb_row > 0 {
+                        warn!(
+                            ">> (recovered) {} {} in {} to {}",
+                            amount,
+                            base32(wtid),
+                            id,
+                            credit_addr
+                        );
                     }
-
-                    if let Some(delay) = config.bump_delay {
-                        if confirmations == 0 && 
full.replaced_by_txid.is_none() {
-                            let now = SystemTime::now()
-                                .duration_since(SystemTime::UNIX_EPOCH)
-                                .unwrap()
-                                .as_secs();
-                            if now - full.time > delay as u64 {
-                                let bump = rpc.bump_fee(id)?;
-                                fail_point("(injected) fail bump", 0.3)?;
-                                db.execute(
-                                    "UPDATE tx_out SET txid=$1 WHERE txid=$2",
-                                    &[&bump.txid.as_ref(), &id.as_ref()],
-                                )?;
+                }
+                TxStatus::Sent => {
+                    if let Some(txid) = full.replaces_txid {
+                        let stored_id = sql_txid(&row, 2);
+                        if txid == stored_id {
+                            let nb_row = db.execute(
+                                "UPDATE tx_out SET txid=$1 WHERE txid=$2",
+                                &[&id.as_ref(), &txid.as_ref()],
+                            )?;
+                            if nb_row > 0 {
                                 info!(
-                                    ">> (bump) {} replace {} with {}",
-                                    base32(&wtid),
-                                    id,
-                                    bump.txid
+                                    ">> (recovered) {} replace {} with {}",
+                                    base32(wtid),
+                                    txid,
+                                    id
                                 );
                             }
                         }
                     }
                 }
             }
-            Info::Bounce { bounced } => {
-                if confirmations < 0 {
-                    // Handle conflicting tx
+        } else {
+            // Else add to database
+            let debit_addr = sender_address(rpc, full)?;
+            let date = SystemTime::UNIX_EPOCH + Duration::from_secs(full.time);
+            let nb = db.execute(
+                    "INSERT INTO tx_out (_date, amount, wtid, debit_acc, 
credit_acc, exchange_url, status, txid, request_uid) VALUES ($1, $2, $3, $4, 
$5, $6, $7, $8, $9) ON CONFLICT (wtid) DO NOTHING",
+                    &[&date, &amount.to_string(), &wtid.as_ref(), 
&btc_payto_url(&debit_addr).as_ref(), &btc_payto_url(credit_addr).as_ref(), 
&config.base_url.as_ref(), &(TxStatus::Sent as i16), &id.as_ref(), 
&None::<&[u8]>],
+                        )?;
+            if nb > 0 {
+                warn!(
+                    ">> (onchain) {} {} in {} to {}",
+                    amount,
+                    base32(wtid),
+                    id,
+                    credit_addr
+                );
+            }
+        }
+
+        if let Some(delay) = config.bump_delay {
+            if confirmations == 0 && full.replaced_by_txid.is_none() {
+                let now = SystemTime::now()
+                    .duration_since(SystemTime::UNIX_EPOCH)
+                    .unwrap()
+                    .as_secs();
+                if now - full.time > delay as u64 {
+                    let bump = rpc.bump_fee(id)?;
+                    fail_point("(injected) fail bump", 0.3)?;
+                    db.execute(
+                        "UPDATE tx_out SET txid=$1 WHERE txid=$2",
+                        &[&bump.txid.as_ref(), &id.as_ref()],
+                    )?;
+                    info!(
+                        ">> (bump) {} replace {} with {}",
+                        base32(wtid),
+                        id,
+                        bump.txid
+                    );
+                }
+            }
+        }
+    }
+    Ok(())
+}
+
+/// Sync database with an outgoing bounce transaction
+fn sync_chain_outgoing_bounce(
+    id: &Txid,
+    bounced: &Txid,
+    db: &mut Client,
+    confirmations: i32,
+) -> LoopResult<()> {
+    if confirmations < 0 {
+        // Handle conflicting tx
+        let nb_row = db.execute(
+            "UPDATE bounce SET status=$1, txid=NULL where txid=$2",
+            &[&(BounceStatus::Delayed as i16), &id.as_ref()],
+        )?;
+        if nb_row > 0 {
+            warn!("|| (conflict) {} in {}", &bounced, &id);
+        }
+    } else {
+        // Get previous bounce
+        let row = db.query_opt(
+            "SELECT id, status FROM bounce WHERE bounced=$1",
+            &[&bounced.as_ref()],
+        )?;
+        if let Some(row) = row {
+            // If already in database, sync status
+            let row_id: i32 = row.get(0);
+            let status: i16 = row.get(1);
+            match BounceStatus::try_from(status as u8).unwrap() {
+                BounceStatus::Requested | BounceStatus::Delayed => {
                     let nb_row = db.execute(
-                        "UPDATE bounce SET status=$1, txid=NULL where txid=$2",
-                        &[&(BounceStatus::Delayed as i16), &id.as_ref()],
+                        "UPDATE bounce SET status=$1, txid=$2 WHERE id=$3 AND 
status=$4",
+                        &[&(BounceStatus::Sent as i16), &id.as_ref(), &row_id, 
&status],
                     )?;
                     if nb_row > 0 {
-                        warn!("|| (conflict) {} in {}", &bounced, &id);
-                    }
-                } else {
-                    // Get previous bounce
-                    let row = db.query_opt(
-                        "SELECT id, status FROM bounce WHERE bounced=$1",
-                        &[&bounced.as_ref()],
-                    )?;
-                    if let Some(row) = row {
-                        // If already in database sync status
-                        let row_id: i32 = row.get(0);
-                        let status: i16 = row.get(1);
-                        match BounceStatus::try_from(status as u8).unwrap() {
-                            BounceStatus::Requested | BounceStatus::Delayed => 
{
-                                let nb_row = db.execute(
-                                    "UPDATE bounce SET status=$1, txid=$2 
WHERE id=$3 AND status=$4",
-                                    &[&(BounceStatus::Sent as i16), 
&id.as_ref(), &row_id, &status],
-                                )?;
-                                if nb_row > 0 {
-                                    warn!("|| (recovered) {} in {}", &bounced, 
&id);
-                                }
-                            }
-                            BounceStatus::Ignored => error!(
-                                "watcher: ignored bounce {} found in chain at 
{}",
-                                bounced, id
-                            ),
-                            BounceStatus::Sent => { /* Status is correct */ }
-                        }
-                    } else {
-                        // Else add to database
-                        let nb = db.execute(
-                    "INSERT INTO bounce (bounced, txid, status) VALUES ($1, 
$2, $3) ON CONFLICT (txid) DO NOTHING",
-                    &[&bounced.as_ref(), &id.as_ref(), &(BounceStatus::Sent as 
i16)],
-                        )?;
-                        if nb > 0 {
-                            warn!("|| (onchain) {} in {}", &bounced, &id);
-                        }
+                        warn!("|| (recovered) {} in {}", &bounced, &id);
                     }
                 }
+                BounceStatus::Ignored => error!(
+                    "watcher: ignored bounce {} found in chain at {}",
+                    bounced, id
+                ),
+                BounceStatus::Sent => { /* Status is correct */ }
             }
-        },
-        Ok((_, Err(e))) => warn!("send: decode-info {} - {}", id, e),
-        Err(e) => match e {
-            GetOpReturnErr::MissingOpReturn => { /* Ignore */ }
-            GetOpReturnErr::RPC(e) => return Err(e)?,
-        },
+        } else {
+            // Else add to database
+            let nb = db.execute(
+        "INSERT INTO bounce (bounced, txid, status) VALUES ($1, $2, $3) ON 
CONFLICT (txid) DO NOTHING",
+        &[&bounced.as_ref(), &id.as_ref(), &(BounceStatus::Sent as i16)],
+            )?;
+            if nb > 0 {
+                warn!("|| (onchain) {} in {}", &bounced, &id);
+            }
+        }
     }
     Ok(())
 }
diff --git a/btc-wire/src/main.rs b/btc-wire/src/main.rs
index 218ada8..ab9cb6c 100644
--- a/btc-wire/src/main.rs
+++ b/btc-wire/src/main.rs
@@ -23,7 +23,7 @@ use reconnect::{AutoReconnectRPC, AutoReconnectSql};
 use std::{sync::atomic::AtomicU16, thread::JoinHandle};
 use taler_common::{config::Config, log::log::info};
 
-use crate::loops::{analysis::analysis, listener::block_listener, 
worker::worker};
+use crate::loops::{analysis::analysis, watcher::watcher, worker::worker};
 
 mod fail_point;
 mod info;
@@ -72,27 +72,27 @@ fn main() {
 
     let mut rpc = BtcRpc::common(&btc_config).unwrap();
     rpc.load_wallet(WIRE_WALLET_NAME).ok();
-    let rpc_listener = AutoReconnectRPC::new(btc_config.clone(), 
WIRE_WALLET_NAME);
+    let rpc_watcher = AutoReconnectRPC::new(btc_config.clone(), 
WIRE_WALLET_NAME);
     let rpc_analysis = AutoReconnectRPC::new(btc_config.clone(), 
WIRE_WALLET_NAME);
     let rpc_worker = AutoReconnectRPC::new(btc_config, WIRE_WALLET_NAME);
 
-    let db_listener = AutoReconnectSql::new(&config.db_url);
+    let db_watcher = AutoReconnectSql::new(&config.db_url);
     let db_analysis = AutoReconnectSql::new(&config.db_url);
     let db_worker = AutoReconnectSql::new(&config.db_url);
-    named_spawn("listener".to_string(), move || {
-        block_listener(rpc_listener, db_listener)
+    named_spawn("watcher", move || {
+        watcher(rpc_watcher, db_watcher)
     });
-    named_spawn("analysis".to_string(), move || {
+    named_spawn("analysis", move || {
         analysis(rpc_analysis, db_analysis, config, state)
     });
     worker(rpc_worker, db_worker, config, state);
 }
 
-pub fn named_spawn<F, T>(name: String, f: F) -> JoinHandle<T>
+pub fn named_spawn<F, T>(name: impl Into<String>, f: F) -> JoinHandle<T>
 where
     F: FnOnce() -> T,
     F: Send + 'static,
     T: Send + 'static,
 {
-    std::thread::Builder::new().name(name).spawn(f).unwrap()
+    std::thread::Builder::new().name(name.into()).spawn(f).unwrap()
 }
diff --git a/btc-wire/src/reconnect.rs b/btc-wire/src/reconnect.rs
index ea37f82..b2bdc79 100644
--- a/btc-wire/src/reconnect.rs
+++ b/btc-wire/src/reconnect.rs
@@ -18,8 +18,8 @@
 use std::time::Duration;
 
 use btc_wire::{config::BitcoinConfig, rpc::BtcRpc};
-use postgres::{Client, NoTls};
 use taler_common::log::log::error;
+use taler_common::postgres::{Client, NoTls};
 
 const RECONNECT_DELAY: Duration = Duration::from_secs(5);
 
diff --git a/btc-wire/src/rpc.rs b/btc-wire/src/rpc.rs
index f7b08b8..4f204b8 100644
--- a/btc-wire/src/rpc.rs
+++ b/btc-wire/src/rpc.rs
@@ -151,7 +151,7 @@ impl BtcRpc {
             writeln!(buf, "Content-Length: {}\r", body.len())?;
             // Write separator
             writeln!(buf, "\r")?;
-            sock.write_all(&buf)?;
+            sock.write_all(buf)?;
             buf.clear();
             // Write body
             sock.write_all(&body)?;
diff --git a/btc-wire/src/segwit.rs b/btc-wire/src/segwit.rs
index f8c2a8f..76e00d0 100644
--- a/btc-wire/src/segwit.rs
+++ b/btc-wire/src/segwit.rs
@@ -14,9 +14,7 @@
   TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
 */
 use bech32::{u5, FromBase32, ToBase32, Variant};
-use rand::{rngs::OsRng, RngCore};
-
-use crate::test::rand_data;
+use taler_common::rand::{rngs::OsRng, RngCore};
 
 /// Encode metadata into a segwit address
 fn encode_segwit_addr(hrp: &str, metada: &[u8; 20]) -> String {
@@ -122,31 +120,36 @@ pub fn decode_segwit_msg(segwit_addrs: &[impl 
AsRef<str>]) -> Result<[u8; 32], D
     Ok(key)
 }
 
+// TODO find a way to hide that function while using it in test and benchmark
 pub fn rand_addresses(hrp: &str, key: &[u8; 32]) -> Vec<String> {
+    use taler_common::{rand::prelude::SliceRandom, rand_slice};
+
     let mut rng_address: Vec<String> =
-        std::iter::repeat_with(|| encode_segwit_addr(hrp, &rand_data()))
+        std::iter::repeat_with(|| encode_segwit_addr(hrp, &rand_slice()))
             .take(2)
             .collect();
 
     let mut addresses = encode_segwit_key(hrp, key).to_vec();
     addresses.append(&mut rng_address);
-    fastrand::shuffle(&mut addresses);
+    addresses.shuffle(&mut OsRng);
     addresses
 }
 
 #[cfg(test)]
 mod test {
-    use crate::{
-        segwit::{decode_segwit_msg, encode_segwit_key, rand_addresses},
-        test::rand_key,
+    use taler_common::{
+        rand::{prelude::SliceRandom, rngs::OsRng},
+        rand_slice,
     };
 
+    use crate::segwit::{decode_segwit_msg, encode_segwit_key, rand_addresses};
+
     #[test]
     fn test_shuffle() {
         for _ in 0..1000 {
-            let key = rand_key();
+            let key = rand_slice();
             let mut addresses = encode_segwit_key("test", &key);
-            fastrand::shuffle(&mut addresses);
+            addresses.shuffle(&mut OsRng);
             let decoded =
                 decode_segwit_msg(&addresses.iter().map(|s| 
s.as_str()).collect::<Vec<&str>>())
                     .unwrap();
@@ -157,7 +160,7 @@ mod test {
     #[test]
     fn test_shuffle_many() {
         for _ in 0..1000 {
-            let key = rand_key();
+            let key = rand_slice();
             let addresses = rand_addresses("test", &key);
             let decoded =
                 decode_segwit_msg(&addresses.iter().map(|s| 
s.as_str()).collect::<Vec<&str>>())
diff --git a/btc-wire/src/sql.rs b/btc-wire/src/sql.rs
index 343f812..edcfcf3 100644
--- a/btc-wire/src/sql.rs
+++ b/btc-wire/src/sql.rs
@@ -15,7 +15,7 @@
 */
 
 use bitcoin::{hashes::Hash, Address, Amount as BtcAmount, Txid};
-use postgres::Row;
+use taler_common::postgres::Row;
 use taler_common::sql::{sql_amount, sql_url};
 
 use crate::taler_util::{btc_payto_addr, taler_to_btc};
diff --git a/btc-wire/src/taler_util.rs b/btc-wire/src/taler_util.rs
index 65e8e39..aabe70d 100644
--- a/btc-wire/src/taler_util.rs
+++ b/btc-wire/src/taler_util.rs
@@ -18,7 +18,7 @@
 use bitcoin::{Address, Amount as BtcAmount, SignedAmount};
 use std::str::FromStr;
 use taler_common::api_common::Amount;
-use url::Url;
+use taler_common::url::Url;
 
 /// Generate a payto uri from a btc address
 pub fn btc_payto_url(addr: &Address) -> Url {
diff --git a/btc-wire/src/test.rs b/btc-wire/src/test.rs
deleted file mode 100644
index 2a0ee58..0000000
--- a/btc-wire/src/test.rs
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
-  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/>
-*/
-pub fn rand_key() -> [u8; 32] {
-    let mut key = [0; 32];
-    key.fill_with(|| fastrand::u8(..));
-    key
-}
-
-pub fn rand_data() -> [u8; 20] {
-    let mut key = [0; 20];
-    key.fill_with(|| fastrand::u8(..));
-    key
-}
diff --git a/docs/fee.png b/docs/fee.png
new file mode 100644
index 0000000..283c286
Binary files /dev/null and b/docs/fee.png differ
diff --git a/docs/presentation.tex b/docs/presentation.tex
new file mode 100644
index 0000000..18d05c4
--- /dev/null
+++ b/docs/presentation.tex
@@ -0,0 +1,221 @@
+\documentclass{beamer}
+ 
+\usepackage{tikz}
+
+\usetikzlibrary{positioning,fit}
+
+\title{Depolymerization}
+\subtitle{Linking Taler with blockchain based cryptocurrencies}
+\author{Antoine d'Aligny}
+\institute{Bern University of Applied Sciences}
+\date{\today}
+\titlegraphic{\includegraphics[width=2.5cm]{taler.png}} 
+
+\begin{document}
+
+\begin{frame}
+    \titlepage
+\end{frame}
+
+\begin{frame}{Outline}
+    \tableofcontents
+\end{frame}
+
+\section{Introduction}
+
+\begin{frame}{Introduction}
+    \begin{block}{Biggest cryptocurrencies}
+        \begin{itemize}
+            \item \textbf{BTC} Bitcoin
+            \item \textbf{ETH} Ethereum
+        \end{itemize}
+    \end{block}
+
+    \begin{block}{Common blockchain limitation}
+        \begin{itemize}
+            \item \textbf{Delayed} block and confirmation delay
+            \item \textbf{Expensive} transaction fees
+            \item \textbf{Scalability} limited amount of transaction per 
seconds
+            \item \textbf{Ecological cost} computation redundancy
+            \item \textbf{Privacy}
+        \end{itemize}
+    \end{block}
+\end{frame}
+
+\section{Taler}
+
+\begin{frame}{Taler}{Architecture}
+    \begin{center}
+        \begin{tikzpicture}[
+                rect/.style={circle, draw=black},
+                sym/.style={->, shorten >= 2pt, shorten <= 2pt}
+            ]
+            \node[rect](1) {Exchange};
+            \node[rect, below left=1.5cm and 0.7cm of 1](2) {Customer};
+            \node[rect, below right=1.5cm and 0.7cm of 1](3) {Merchant};
+
+            \draw[sym] (1) -- node [midway, left] {\tiny Withdraw coins} (2);
+            \draw[sym] (2) -- node [midway, below] {\tiny Spend coins} (3);
+            \draw[sym] (3) -- node [midway, right] {\tiny Deposit coins} (1);
+
+            \node[left=2cm of 1](E1){};
+            \node[right=2cm of 1](E2){};
+            \draw[sym] (E1) -- node [midway, above] {\tiny Deposit money} (1);
+            \draw[sym] (1) -- node [midway, above] {\tiny Withdraw money} (E2);
+
+
+            \node[above= of 1](A){Auditor};
+            \draw[sym] (A) -- node [midway, right] {\tiny Audit} (1);
+        \end{tikzpicture}
+    \end{center}
+\end{frame}
+
+\begin{frame}{Taler}{Coins}
+    - Blind signatures
+    - Currency agnostic
+    - Change signature every year, Forget previous transactions (Pruning)
+    - Compatibility ?
+\end{frame}
+
+\begin{frame}{Taler}{Off the chain transaction}
+    \begin{center}
+        \begin{tikzpicture}[
+                rect/.style={rectangle, draw=black},
+                sym/.style={<->, shorten >= 2pt, shorten <= 2pt}
+            ]
+            \node(Tt){Taler};
+            \node[rect, below=0cm of Tt](Tc){Exchange};
+            \node[rect, fit={(Tt) (Tc)}](T){};
+
+            \node[rect, below= of Tc](D) {Depolymerization};
+
+            \node[rect, below= of D](Bc){Node};
+            \node[below=0cmof Bc](Bt){Blockchain};
+            \node[rect, fit={(Bt) (Bc)}](B){};
+
+            \draw[sym] (T) -- (D);
+            \draw[sym] (D) -- (B);
+        \end{tikzpicture}
+    \end{center}
+\end{frame}
+
+\section{Depolymerization}
+
+\begin{frame}{Depolymerization}{Metadata}
+    - Metadata
+    - Auditabilité
+\end{frame}
+
+\begin{frame}{Depolymerization}{Architecture}
+    \begin{center}
+        \begin{tikzpicture}[
+                rect/.style={rectangle, draw=black},
+                sym/.style={<->, shorten >= 2pt, shorten <= 2pt}
+            ]
+            \node[rect](1) {Taler Exchange};
+            \node[rect, below= of 1](2) {wire\_gateway};
+            \node[rect, right= of 2](3) {PostgreSQL};
+            \node[rect, right= of 3](4) {\#\#\#\_wire};
+            \node[rect, above= of 4](5) {Full Node};
+
+            \draw[sym] (1) -- node [midway, right] {\tiny HTTP} (2);
+            \draw[sym] (2) -- node [midway, above] {\tiny SQL} (3);
+            \draw[sym] (3) -- node [midway, above] {\tiny SQL} (4);
+            \draw[sym] (4) -- node [midway, left] {\tiny RPC} (5);
+        \end{tikzpicture}
+    \end{center}
+\end{frame}
+
+\section{btc\_wire}
+
+\begin{frame}{btc\_wire}{Architecture}
+    Three loops
+    Watcher: Notify other loops when a new block has been mined
+    Analyzer: Analyse blockchain to adapt defensively
+    Worker: Sync chain -> Send -> Bounce
+\end{frame}
+
+\begin{frame}{btc\_wire}{Security features}
+    \begin{itemize}
+        \item Reorg resilient
+        \item Handle stuck transaction
+        \item Adaptive confirmation
+    \end{itemize}
+\end{frame}
+
+\begin{frame}{btc\_wire}{Reorg resilient}
+\end{frame}
+
+\begin{frame}{btc\_wire}{Handle stuck transactions}
+    \only<1>{We want transactions to be confirmed in a bounded time period}
+    \begin{center}
+        \begin{tikzpicture}[
+                dot/.style={circle,fill,inner sep=1pt,}
+            ]
+
+            % TODO caption with source (Ychart)
+
+            \node (I) {\includegraphics[width=\textwidth]{fee.png}};
+            \only<2->{
+                \node [below left=-2.5mm and -1.5cm of I] (Tx) {\small Tx};
+                \node [dot, above=8.4mm of Tx](D) {};
+                \draw [dotted] (Tx) -- (D);
+            };
+            \only<2>{
+                \node [left=-4.5cm of Tx] (C) {\small conf};
+                \node [dot, above=8.4mm of C](D1) {};
+                \draw [dotted] (C) -- (D1);
+            };
+            \only<3>{
+                \node [left=-17mm of Tx] (Tx1) {\small Tx'};
+                \node [dot, above=15.5mm of Tx1](D1) {};
+                \draw [dotted] (Tx1) -- (D1);
+
+                \node [left=-14.3mm of Tx1] (C) {\small conf};
+                \node [dot, above=15.5mm of C](D2) {};
+                \draw [dotted] (C) -- (D2);
+            };
+
+        \end{tikzpicture}
+    \end{center}
+    \only<1>{However, transaction fees are variable and can only be predicted}
+    \only<2>{When a transaction is sent with a fee too small compared to other 
transaction,
+        it can take an unlimited amount of time for this transaction to be 
mined}
+    \only<3>{We monitor pending transaction and bump their fee if they take 
too muck time to be mined}
+
+\end{frame}
+
+
+\begin{frame}{btc\_wire}{Adaptive confirmation}
+\end{frame}
+
+
+
+\begin{frame}{Related work}
+    \begin{block}{Centralization - Coinbase off-chain sending}
+        \begin{itemize}
+            \item [$+$] Fast and cheap: off chain transaction
+            \item [$-$] Trust in Coinbase: privacy, security \& transparency
+        \end{itemize}
+    \end{block}
+    \begin{block}{Layering - Lightning Network}
+        \begin{itemize}
+            \item [$+$] Fast and cheap: off chain transaction
+            \item [$-$] Incompatible with Bitcoin: require setting up a 
Bidirectional Payment Channel
+            \item [$-$] Fraud attempts are mitigated via a complex penalty 
system
+        \end{itemize}
+    \end{block}
+\end{frame}
+
+\begin{frame}{Conclusion}
+    \begin{itemize}
+        \item [$-$] Trust exchange operator or auditors
+        \item [$+$] Fast and cheap, no blockchain
+        \item [$+$] Realtime, ms latency
+        \item [$+$] Scalability, close to 100k txs per second
+        \item [$+$] Ecological
+        \item [$+$] Privacy when it can, transparency when it must (avoid tax 
evasion and money laundering)
+        \item [$+$] Currency agnostic
+    \end{itemize}
+\end{frame}
+\end{document}
\ No newline at end of file
diff --git a/docs/taler.png b/docs/taler.png
new file mode 100644
index 0000000..503ae20
Binary files /dev/null and b/docs/taler.png differ
diff --git a/taler-common/Cargo.toml b/taler-common/Cargo.toml
index 8468564..816524b 100644
--- a/taler-common/Cargo.toml
+++ b/taler-common/Cargo.toml
@@ -30,3 +30,5 @@ flexi_logger = { version = "0.22.2", default-features = 
false, features = [
 time = { version = "0.3.5", features = ["formatting", "macros"] }
 # Postgres client
 postgres = "0.19.2"
+# Secure random
+rand = { version = "0.8.4", features = ["getrandom"] }
diff --git a/taler-common/src/lib.rs b/taler-common/src/lib.rs
index d935941..8bdf0ec 100644
--- a/taler-common/src/lib.rs
+++ b/taler-common/src/lib.rs
@@ -1,3 +1,4 @@
+use rand::{rngs::OsRng, RngCore};
 /*
   This file is part of TALER
   Copyright (C) 2022 Taler Systems SA
@@ -13,6 +14,8 @@
   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/>
 */
+pub use postgres;
+pub use rand;
 pub use url;
 
 pub mod api_common;
@@ -20,4 +23,11 @@ pub mod api_wire;
 pub mod config;
 pub mod error_codes;
 pub mod log;
-pub mod sql;
\ No newline at end of file
+pub mod sql;
+
+/// Secure random slice generator using getrandom
+pub fn rand_slice<const N: usize>() -> [u8; N] {
+    let mut slice = [0; N];
+    OsRng.fill_bytes(slice.as_mut_slice());
+    slice
+}
diff --git a/wire-gateway/Cargo.toml b/wire-gateway/Cargo.toml
index d798d17..44b2bda 100644
--- a/wire-gateway/Cargo.toml
+++ b/wire-gateway/Cargo.toml
@@ -27,11 +27,8 @@ serde_urlencoded = "0.7.1"
 thiserror = "1.0.30"
 # Deflate compression
 miniz_oxide = "0.5.1"
-# Rng
-rand = { version = "0.8.4", features = ["getrandom"] }
 # Async postgres client
 tokio-postgres = { version = "0.7.5" }
-postgres = { version = "0.19.2" }
 deadpool-postgres = "0.10.1"
 # Socket activation
 listenfd = "0.5.0"
diff --git a/wire-gateway/src/main.rs b/wire-gateway/src/main.rs
index 8ff5fd4..505602b 100644
--- a/wire-gateway/src/main.rs
+++ b/wire-gateway/src/main.rs
@@ -22,7 +22,6 @@ use hyper::{
 };
 use json::{encode_body, parse_body};
 use listenfd::ListenFd;
-use postgres::fallible_iterator::FallibleIterator;
 use std::{
     convert::Infallible,
     str::FromStr,
@@ -38,7 +37,7 @@ use taler_common::{
     error_codes::ErrorCode,
     log::log::{error, info, log, Level},
     sql::{sql_amount, sql_array, sql_safe_u64, sql_url},
-    url::Url,
+    url::Url, postgres::{Client, fallible_iterator::FallibleIterator},
 };
 use tokio::sync::Notify;
 use tokio_postgres::{config::Host, NoTls};
@@ -450,7 +449,7 @@ async fn router(
 /// Listen to backend status change
 fn status_watcher(state: &'static ServerState) {
     fn inner(state: &'static ServerState) -> Result<(), Box<dyn 
std::error::Error>> {
-        let mut db = postgres::Client::connect(&state.config.db_url, NoTls)?;
+        let mut db = Client::connect(&state.config.db_url, NoTls)?;
         // Register as listener
         db.batch_execute("LISTEN status")?;
         loop {

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]