depolymerization

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

commit 906264dbbae37428d96d07d993c1466bc908df8d
parent 32fc54e7fc2db2e4f68d7bf96ab0e46c66d0de6e
Author: Antoine A <>
Date:   Tue, 25 Jan 2022 15:47:56 +0100

Remove fastrand when rand is used and improve taler_common

Diffstat:
MCargo.lock | 7+------
Mbtc-wire/Cargo.toml | 9---------
Mbtc-wire/benches/metadata.rs | 10++++------
Mbtc-wire/src/bin/btc-wire-cli.rs | 2+-
Mbtc-wire/src/bin/btc-wire-utils.rs | 12+++++-------
Mbtc-wire/src/bin/test.rs | 4++--
Mbtc-wire/src/fail_point.rs | 2+-
Mbtc-wire/src/info.rs | 9++++-----
Mbtc-wire/src/lib.rs | 1-
Mbtc-wire/src/loops.rs | 1+
Mbtc-wire/src/loops/analysis.rs | 2+-
Mbtc-wire/src/loops/worker.rs | 3++-
Mbtc-wire/src/reconnect.rs | 2+-
Mbtc-wire/src/rpc.rs | 2+-
Mbtc-wire/src/segwit.rs | 25++++++++++++++-----------
Mbtc-wire/src/sql.rs | 2+-
Mbtc-wire/src/taler_util.rs | 2+-
Dbtc-wire/src/test.rs | 26--------------------------
Mtaler-common/Cargo.toml | 2++
Mtaler-common/src/lib.rs | 13+++++++++++--
Mwire-gateway/Cargo.toml | 3---
Mwire-gateway/src/main.rs | 5++---
22 files changed, 55 insertions(+), 89 deletions(-)

diff --git 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]] @@ -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/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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -15,6 +15,7 @@ */ use btc_wire::rpc; +use taler_common::postgres; use crate::fail_point::Injected; diff --git 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/worker.rs b/btc-wire/src/loops/worker.rs @@ -31,6 +31,7 @@ use taler_common::{ api_common::base32, config::Config, log::log::{error, info, warn}, + postgres, sql::{sql_array, sql_url}, }; @@ -497,7 +498,7 @@ fn sync_chain_outgoing_send( } } else { // Else add to database - let debit_addr = sender_address(rpc, &full)?; + 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", diff --git 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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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/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 @@ -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 @@ -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 @@ -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 {