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:
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 {