Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ bip39 = "2.0.0"
bip21 = { version = "0.5", features = ["std"], default-features = false }

base64 = { version = "0.22.1", default-features = false, features = ["std"] }
rand = "0.8.5"
rand = { version = "0.9.2", default-features = false, features = ["std", "thread_rng", "os_rng"] }
chrono = { version = "0.4", default-features = false, features = ["clock"] }
tokio = { version = "1.37", default-features = false, features = [ "rt-multi-thread", "time", "sync", "macros" ] }
esplora-client = { version = "0.12", default-features = false, features = ["tokio", "async-https-rustls"] }
Expand Down
4 changes: 2 additions & 2 deletions src/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ use lightning::util::persist::KVStoreSync;
use lightning::util::ser::{Readable, ReadableArgs, Writeable, Writer};
use lightning_liquidity::lsps2::utils::compute_opening_fee;
use lightning_types::payment::{PaymentHash, PaymentPreimage};
use rand::{thread_rng, Rng};
use rand::{rng, Rng};

use crate::config::{may_announce_channel, Config};
use crate::connection::ConnectionManager;
Expand Down Expand Up @@ -1137,7 +1137,7 @@ where
}
}

let user_channel_id: u128 = thread_rng().gen::<u128>();
let user_channel_id: u128 = rng().random();
let allow_0conf = self.config.trusted_peers_0conf.contains(&counterparty_node_id);
let mut channel_override_config = None;
if let Some((lsp_node_id, _)) = self
Expand Down
6 changes: 3 additions & 3 deletions src/io/test_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ use lightning::util::persist::{
};
use lightning::util::test_utils;
use lightning::{check_added_monitors, check_closed_broadcast, check_closed_event};
use rand::distributions::Alphanumeric;
use rand::{thread_rng, Rng};
use rand::distr::Alphanumeric;
use rand::{rng, Rng};

type TestMonitorUpdatePersister<'a, K> = MonitorUpdatingPersister<
&'a K,
Expand All @@ -34,7 +34,7 @@ const EXPECTED_UPDATES_PER_PAYMENT: u64 = 5;

pub(crate) fn random_storage_path() -> PathBuf {
let mut temp_path = std::env::temp_dir();
let mut rng = thread_rng();
let mut rng = rng();
let rand_dir: String = (0..7).map(|_| rng.sample(Alphanumeric) as char).collect();
temp_path.push(rand_dir);
temp_path
Expand Down
10 changes: 7 additions & 3 deletions src/io/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ use lightning::util::persist::{
};
use lightning::util::ser::{Readable, ReadableArgs, Writeable};
use lightning_types::string::PrintableString;
use rand::{thread_rng, RngCore};
use rand::rngs::OsRng;
use rand::TryRngCore;

use super::*;
use crate::chain::ChainSource;
Expand Down Expand Up @@ -63,7 +64,7 @@ pub const EXTERNAL_PATHFINDING_SCORES_CACHE_KEY: &str = "external_pathfinding_sc
pub fn generate_entropy_mnemonic() -> Mnemonic {
// bip39::Mnemonic supports 256 bit entropy max
let mut entropy = [0; 32];
thread_rng().fill_bytes(&mut entropy);
OsRng.try_fill_bytes(&mut entropy).expect("Failed to generate entropy");
Mnemonic::from_entropy(&entropy).unwrap()
}

Expand Down Expand Up @@ -96,7 +97,10 @@ where
Ok(key)
} else {
let mut key = [0; WALLET_KEYS_SEED_LEN];
thread_rng().fill_bytes(&mut key);
OsRng.try_fill_bytes(&mut key).map_err(|e| {
log_error!(logger, "Failed to generate entropy: {}", e);
std::io::Error::new(std::io::ErrorKind::Other, "Failed to generate seed bytes")
})?;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we propagate the Err from the OsRng here should we also propagate the Err in generate_entropy_mnemonic above ?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess I am looking for consistency here, but maybe the difference is a public API function vs a function internal to the crate ?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we propagate the Err from the OsRng here should we also propagate the Err in generate_entropy_mnemonic above ?

Well, we would need to introduce an enum error type just for this case, which seems like overkill. It could even be argued that we should to panic in this case, as according to the docs of OsRng failing is only expected in case of system misconfiguration and we fail to actually provide sufficient entropy, i.e., every operation after this could be considered unsafe.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm ok would you consider panicking here ? sounds to me like OsRng returning an Error is very rare, but if it ever does, user should probably stop what they are doing and consider running ldk-node on a different machine.

Copy link
Collaborator Author

@tnull tnull Oct 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm ok would you consider panicking here ? sounds to me like OsRng returning an Error is very rare, but if it ever does, user should probably stop what they are doing and consider running ldk-node on a different machine.

Well, the other path will happen on build only, so instead of panicking we'd just be erroring out before we did anything really.


if let Some(parent_dir) = Path::new(&keys_seed_path).parent() {
fs::create_dir_all(parent_dir).map_err(|e| {
Expand Down
10 changes: 5 additions & 5 deletions src/io/vss_store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -592,7 +592,7 @@ pub(crate) struct RandEntropySource;

impl EntropySource for RandEntropySource {
fn fill_bytes(&self, buffer: &mut [u8]) {
rand::thread_rng().fill_bytes(buffer);
rand::rng().fill_bytes(buffer);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the next commit, I would have used OsRng here too since it's used for cryptographic nonces.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am conscious of the performance tradeoff here as this is a frequent operation, maybe OsRng would be overkill ? Cryptographic nonces have stronger requirements than the identifiers we use ThreadRng for elsewhere

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that's why I kept it with the thread RNG, which should be perfectly fine for cryptographic operations. I guess if we'd want to be super cautious we could look into periodic re-seeding via ReseedingRng, but not even sure if that is warranted. WDYT?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looked into the current reseed behaviour, it's already automatically called every 64kB, I think we are good there.

They do recommend to explicitly reseed on any fork, but I don't think we ever fork right ? If so I think I am good with the current choice.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They do recommend to explicitly reseed on any fork, but I don't think we ever fork right ? If so I think I am good with the current choice.

Yeah, was also tripping over that and considered reseeding on any new thread spawned by tokio. But, IIUC, that should happen automatically in the rng() call.

}
}

Expand All @@ -604,8 +604,8 @@ impl RefUnwindSafe for VssStore {}
mod tests {
use std::collections::HashMap;

use rand::distributions::Alphanumeric;
use rand::{thread_rng, Rng, RngCore};
use rand::distr::Alphanumeric;
use rand::{rng, Rng, RngCore};
use vss_client::headers::FixedHeaders;

use super::*;
Expand All @@ -615,7 +615,7 @@ mod tests {
#[test]
fn vss_read_write_remove_list_persist() {
let vss_base_url = std::env::var("TEST_VSS_BASE_URL").unwrap();
let mut rng = thread_rng();
let mut rng = rng();
let rand_store_id: String = (0..7).map(|_| rng.sample(Alphanumeric) as char).collect();
let mut vss_seed = [0u8; 32];
rng.fill_bytes(&mut vss_seed);
Expand All @@ -631,7 +631,7 @@ mod tests {
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
async fn vss_read_write_remove_list_persist_in_runtime_context() {
let vss_base_url = std::env::var("TEST_VSS_BASE_URL").unwrap();
let mut rng = thread_rng();
let mut rng = rng();
let rand_store_id: String = (0..7).map(|_| rng.sample(Alphanumeric) as char).collect();
let mut vss_seed = [0u8; 32];
rng.fill_bytes(&mut vss_seed);
Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1117,7 +1117,7 @@ impl Node {
}

let push_msat = push_to_counterparty_msat.unwrap_or(0);
let user_channel_id: u128 = rand::thread_rng().gen::<u128>();
let user_channel_id: u128 = rand::rng().random();

match self.channel_manager.create_channel(
peer_info.node_id,
Expand Down
2 changes: 1 addition & 1 deletion src/liquidity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -562,7 +562,7 @@ where
return;
};

let user_channel_id: u128 = rand::thread_rng().gen::<u128>();
let user_channel_id: u128 = rand::rng().random();
let intercept_scid = self.channel_manager.get_intercept_scid();

if let Some(payment_size_msat) = payment_size_msat {
Expand Down
6 changes: 3 additions & 3 deletions src/payment/bolt12.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ impl Bolt12Payment {
let offer = maybe_deref(offer);

let mut random_bytes = [0u8; 32];
rand::thread_rng().fill_bytes(&mut random_bytes);
rand::rng().fill_bytes(&mut random_bytes);
let payment_id = PaymentId(random_bytes);
let retry_strategy = Retry::Timeout(LDK_PAYMENT_RETRY_TIMEOUT);
let route_params_config = RouteParametersConfig::default();
Expand Down Expand Up @@ -191,7 +191,7 @@ impl Bolt12Payment {
let offer = maybe_deref(offer);

let mut random_bytes = [0u8; 32];
rand::thread_rng().fill_bytes(&mut random_bytes);
rand::rng().fill_bytes(&mut random_bytes);
let payment_id = PaymentId(random_bytes);
let retry_strategy = Retry::Timeout(LDK_PAYMENT_RETRY_TIMEOUT);
let route_params_config = RouteParametersConfig::default();
Expand Down Expand Up @@ -408,7 +408,7 @@ impl Bolt12Payment {
payer_note: Option<String>,
) -> Result<Refund, Error> {
let mut random_bytes = [0u8; 32];
rand::thread_rng().fill_bytes(&mut random_bytes);
rand::rng().fill_bytes(&mut random_bytes);
let payment_id = PaymentId(random_bytes);

let absolute_expiry = (SystemTime::now() + Duration::from_secs(expiry_secs as u64))
Expand Down
14 changes: 7 additions & 7 deletions tests/common/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ use lightning_invoice::{Bolt11InvoiceDescription, Description};
use lightning_persister::fs_store::FilesystemStore;
use lightning_types::payment::{PaymentHash, PaymentPreimage};
use logging::TestLogWriter;
use rand::distributions::Alphanumeric;
use rand::{thread_rng, Rng};
use rand::distr::Alphanumeric;
use rand::{rng, Rng};
use serde_json::{json, Value};

macro_rules! expect_event {
Expand Down Expand Up @@ -191,15 +191,15 @@ pub(crate) fn setup_bitcoind_and_electrsd() -> (BitcoinD, ElectrsD) {

pub(crate) fn random_storage_path() -> PathBuf {
let mut temp_path = std::env::temp_dir();
let mut rng = thread_rng();
let mut rng = rng();
let rand_dir: String = (0..7).map(|_| rng.sample(Alphanumeric) as char).collect();
temp_path.push(rand_dir);
temp_path
}

pub(crate) fn random_port() -> u16 {
let mut rng = thread_rng();
rng.gen_range(5000..32768)
let mut rng = rng();
rng.random_range(5000..32768)
}

pub(crate) fn random_listening_addresses() -> Vec<SocketAddress> {
Expand All @@ -216,8 +216,8 @@ pub(crate) fn random_listening_addresses() -> Vec<SocketAddress> {
}

pub(crate) fn random_node_alias() -> Option<NodeAlias> {
let mut rng = thread_rng();
let rand_val = rng.gen_range(0..1000);
let mut rng = rng();
let rand_val = rng.random_range(0..1000);
let alias = format!("ldk-node-{}", rand_val);
let mut bytes = [0u8; 32];
bytes[..alias.as_bytes().len()].copy_from_slice(alias.as_bytes());
Expand Down
6 changes: 3 additions & 3 deletions tests/integration_tests_cln.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ use ldk_node::bitcoin::Amount;
use ldk_node::lightning::ln::msgs::SocketAddress;
use ldk_node::{Builder, Event};
use lightning_invoice::{Bolt11Invoice, Bolt11InvoiceDescription, Description};
use rand::distributions::Alphanumeric;
use rand::{thread_rng, Rng};
use rand::distr::Alphanumeric;
use rand::{rng, Rng};

#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
async fn test_cln() {
Expand Down Expand Up @@ -99,7 +99,7 @@ async fn test_cln() {
let user_channel_id = common::expect_channel_ready_event!(node, cln_node_id);

// Send a payment to CLN
let mut rng = thread_rng();
let mut rng = rng();
let rand_label: String = (0..7).map(|_| rng.sample(Alphanumeric) as char).collect();
let cln_invoice =
cln_client.invoice(Some(10_000_000), &rand_label, &rand_label, None, None, None).unwrap();
Expand Down
Loading