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
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ bip39 = { version = "2.0.0", features = ["rand"] }
bip21 = { version = "0.5", features = ["std"], default-features = false }

base64 = { version = "0.22.1", default-features = false, features = ["std"] }
rand = { version = "0.9.2", default-features = false, features = ["std", "thread_rng", "os_rng"] }
getrandom = { version = "0.3", default-features = false }
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 All @@ -85,6 +85,7 @@ winapi = { version = "0.3", features = ["winbase"] }

[dev-dependencies]
lightning = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "b6c17c593a5d7bacb18fe3b9f69074a0596ae8f0", features = ["std", "_test_utils"] }
rand = { version = "0.9.2", default-features = false, features = ["std", "thread_rng", "os_rng"] }
proptest = "1.0.0"
regex = "1.5.6"
criterion = { version = "0.7.0", features = ["async_tokio"] }
Expand Down
15 changes: 10 additions & 5 deletions src/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ use lightning::impl_writeable_tlv_based_enum;
use lightning::ln::channelmanager::PaymentId;
use lightning::ln::types::ChannelId;
use lightning::routing::gossip::NodeId;
use lightning::sign::EntropySource;
use lightning::util::config::{
ChannelConfigOverrides, ChannelConfigUpdate, ChannelHandshakeConfigUpdate,
};
Expand All @@ -30,7 +31,6 @@ use lightning::util::persist::KVStore;
use lightning::util::ser::{Readable, ReadableArgs, Writeable, Writer};
use lightning_liquidity::lsps2::utils::compute_opening_fee;
use lightning_types::payment::{PaymentHash, PaymentPreimage};
use rand::{rng, Rng};

use crate::config::{may_announce_channel, Config};
use crate::connection::ConnectionManager;
Expand All @@ -48,6 +48,7 @@ use crate::payment::store::{
PaymentDetails, PaymentDetailsUpdate, PaymentDirection, PaymentKind, PaymentStatus,
};
use crate::runtime::Runtime;
use crate::types::KeysManager;
use crate::types::{CustomTlvRecord, DynStore, OnionMessenger, PaymentStore, Sweeper, Wallet};
use crate::{
hex_utils, BumpTransactionEventHandler, ChannelManager, Error, Graph, PeerInfo, PeerStore,
Expand Down Expand Up @@ -488,6 +489,7 @@ where
liquidity_source: Option<Arc<LiquiditySource<Arc<Logger>>>>,
payment_store: Arc<PaymentStore>,
peer_store: Arc<PeerStore<L>>,
keys_manager: Arc<KeysManager>,
runtime: Arc<Runtime>,
logger: L,
config: Arc<Config>,
Expand All @@ -507,9 +509,9 @@ where
output_sweeper: Arc<Sweeper>, network_graph: Arc<Graph>,
liquidity_source: Option<Arc<LiquiditySource<Arc<Logger>>>>,
payment_store: Arc<PaymentStore>, peer_store: Arc<PeerStore<L>>,
static_invoice_store: Option<StaticInvoiceStore>, onion_messenger: Arc<OnionMessenger>,
om_mailbox: Option<Arc<OnionMessageMailbox>>, runtime: Arc<Runtime>, logger: L,
config: Arc<Config>,
keys_manager: Arc<KeysManager>, static_invoice_store: Option<StaticInvoiceStore>,
onion_messenger: Arc<OnionMessenger>, om_mailbox: Option<Arc<OnionMessageMailbox>>,
runtime: Arc<Runtime>, logger: L, config: Arc<Config>,
) -> Self {
Self {
event_queue,
Expand All @@ -522,6 +524,7 @@ where
liquidity_source,
payment_store,
peer_store,
keys_manager,
logger,
runtime,
config,
Expand Down Expand Up @@ -1218,7 +1221,9 @@ where
}
}

let user_channel_id: u128 = rng().random();
let user_channel_id: u128 = u128::from_ne_bytes(
self.keys_manager.get_secure_random_bytes()[..16].try_into().unwrap(),
);
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
4 changes: 1 addition & 3 deletions src/io/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,6 @@ use lightning::util::persist::{
};
use lightning::util::ser::{Readable, ReadableArgs, Writeable};
use lightning_types::string::PrintableString;
use rand::rngs::OsRng;
use rand::TryRngCore;

use super::*;
use crate::chain::ChainSource;
Expand Down Expand Up @@ -72,7 +70,7 @@ pub(crate) fn read_or_generate_seed_file(
Ok(key)
} else {
let mut key = [0; WALLET_KEYS_SEED_LEN];
OsRng.try_fill_bytes(&mut key).map_err(|_| {
getrandom::fill(&mut key).map_err(|_| {
std::io::Error::new(std::io::ErrorKind::Other, "Failed to generate seed bytes")
})?;

Expand Down
36 changes: 25 additions & 11 deletions src/io/vss_store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@ use bitcoin::key::Secp256k1;
use bitcoin::Network;
use lightning::impl_writeable_tlv_based_enum;
use lightning::io::{self, Error, ErrorKind};
use lightning::sign::{EntropySource as LdkEntropySource, RandomBytes};
use lightning::util::persist::{KVStore, KVStoreSync};
use lightning::util::ser::{Readable, Writeable};
use prost::Message;
use rand::RngCore;
use vss_client::client::VssClient;
use vss_client::error::VssError;
use vss_client::headers::{FixedHeaders, LnurlAuthToJwtProvider, VssHeaderProvider};
Expand Down Expand Up @@ -114,6 +114,10 @@ impl VssStore {
derive_data_encryption_and_obfuscation_keys(&vss_seed);
let key_obfuscator = KeyObfuscator::new(obfuscation_master_key);

let mut entropy_seed = [0u8; 32];
getrandom::fill(&mut entropy_seed).expect("Failed to generate random bytes");
let entropy_source = RandomBytes::new(entropy_seed);

let sync_retry_policy = retry_policy();
let blocking_client = VssClient::new_with_headers(
base_url.clone(),
Expand All @@ -129,6 +133,7 @@ impl VssStore {
&store_id,
data_encryption_key,
&key_obfuscator,
&entropy_source,
)
.await
})
Expand All @@ -145,6 +150,7 @@ impl VssStore {
store_id,
data_encryption_key,
key_obfuscator,
entropy_source,
));

Ok(Self { inner, next_version, internal_runtime: Some(internal_runtime) })
Expand Down Expand Up @@ -385,6 +391,7 @@ struct VssStoreInner {
store_id: String,
data_encryption_key: [u8; 32],
key_obfuscator: KeyObfuscator,
entropy_source: RandomBytes,
// Per-key locks that ensures that we don't have concurrent writes to the same namespace/key.
// The lock also encapsulates the latest written version per key.
locks: Mutex<HashMap<String, Arc<tokio::sync::Mutex<u64>>>>,
Expand All @@ -394,7 +401,7 @@ impl VssStoreInner {
pub(crate) fn new(
schema_version: VssSchemaVersion, blocking_client: VssClient<CustomRetryPolicy>,
async_client: VssClient<CustomRetryPolicy>, store_id: String,
data_encryption_key: [u8; 32], key_obfuscator: KeyObfuscator,
data_encryption_key: [u8; 32], key_obfuscator: KeyObfuscator, entropy_source: RandomBytes,
) -> Self {
let locks = Mutex::new(HashMap::new());
Self {
Expand All @@ -404,6 +411,7 @@ impl VssStoreInner {
store_id,
data_encryption_key,
key_obfuscator,
entropy_source,
locks,
}
}
Expand Down Expand Up @@ -524,7 +532,7 @@ impl VssStoreInner {
Error::new(ErrorKind::Other, msg)
})?;

let storable_builder = StorableBuilder::new(RandEntropySource);
let storable_builder = StorableBuilder::new(VssEntropySource(&self.entropy_source));
let aad =
if self.schema_version == VssSchemaVersion::V1 { store_key.as_bytes() } else { &[] };
let decrypted = storable_builder.deconstruct(storable, &self.data_encryption_key, aad)?.0;
Expand All @@ -545,7 +553,7 @@ impl VssStoreInner {

let store_key = self.build_obfuscated_key(&primary_namespace, &secondary_namespace, &key);
let vss_version = -1;
let storable_builder = StorableBuilder::new(RandEntropySource);
let storable_builder = StorableBuilder::new(VssEntropySource(&self.entropy_source));
let aad =
if self.schema_version == VssSchemaVersion::V1 { store_key.as_bytes() } else { &[] };
let storable =
Expand Down Expand Up @@ -703,7 +711,7 @@ fn retry_policy() -> CustomRetryPolicy {

async fn determine_and_write_schema_version(
client: &VssClient<CustomRetryPolicy>, store_id: &String, data_encryption_key: [u8; 32],
key_obfuscator: &KeyObfuscator,
key_obfuscator: &KeyObfuscator, entropy_source: &RandomBytes,
) -> io::Result<VssSchemaVersion> {
// Build the obfuscated `vss_schema_version` key.
let obfuscated_prefix = key_obfuscator.obfuscate(&format! {"{}#{}", "", ""});
Expand Down Expand Up @@ -734,7 +742,7 @@ async fn determine_and_write_schema_version(
Error::new(ErrorKind::Other, msg)
})?;

let storable_builder = StorableBuilder::new(RandEntropySource);
let storable_builder = StorableBuilder::new(VssEntropySource(entropy_source));
// Schema version was added starting with V1, so if set at all, we use the key as `aad`
let aad = store_key.as_bytes();
let decrypted = storable_builder
Expand Down Expand Up @@ -778,7 +786,7 @@ async fn determine_and_write_schema_version(
let schema_version = VssSchemaVersion::V1;
let encoded_version = schema_version.encode();

let storable_builder = StorableBuilder::new(RandEntropySource);
let storable_builder = StorableBuilder::new(VssEntropySource(entropy_source));
let vss_version = -1;
let aad = store_key.as_bytes();
let storable =
Expand All @@ -805,12 +813,18 @@ async fn determine_and_write_schema_version(
}
}

/// A source for generating entropy/randomness using [`rand`].
pub(crate) struct RandEntropySource;
/// A thin wrapper bridging LDK's [`RandomBytes`] to the vss-client [`EntropySource`] trait.
struct VssEntropySource<'a>(&'a RandomBytes);

impl EntropySource for RandEntropySource {
impl EntropySource for VssEntropySource<'_> {
fn fill_bytes(&self, buffer: &mut [u8]) {
rand::rng().fill_bytes(buffer);
let mut offset = 0;
while offset < buffer.len() {
let random = self.0.get_secure_random_bytes();
let to_copy = (buffer.len() - offset).min(32);
buffer[offset..offset + to_copy].copy_from_slice(&random[..to_copy]);
offset += to_copy;
}
}
}

Expand Down
9 changes: 7 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ use lightning::ln::channelmanager::PaymentId;
use lightning::ln::funding::SpliceContribution;
use lightning::ln::msgs::SocketAddress;
use lightning::routing::gossip::NodeAlias;
use lightning::sign::EntropySource;
use lightning::util::persist::KVStoreSync;
use lightning_background_processor::process_events_async;
use liquidity::{LSPS1Liquidity, LiquiditySource};
Expand All @@ -157,7 +158,6 @@ use payment::{
UnifiedPayment,
};
use peer_store::{PeerInfo, PeerStore};
use rand::Rng;
use runtime::Runtime;
use types::{
Broadcaster, BumpTransactionEventHandler, ChainMonitor, ChannelManager, DynStore, Graph,
Expand Down Expand Up @@ -574,6 +574,7 @@ impl Node {
self.liquidity_source.clone(),
Arc::clone(&self.payment_store),
Arc::clone(&self.peer_store),
Arc::clone(&self.keys_manager),
static_invoice_store,
Arc::clone(&self.onion_messenger),
self.om_mailbox.clone(),
Expand Down Expand Up @@ -889,6 +890,7 @@ impl Node {
pub fn bolt12_payment(&self) -> Bolt12Payment {
Bolt12Payment::new(
Arc::clone(&self.channel_manager),
Arc::clone(&self.keys_manager),
Arc::clone(&self.payment_store),
Arc::clone(&self.config),
Arc::clone(&self.is_running),
Expand All @@ -904,6 +906,7 @@ impl Node {
pub fn bolt12_payment(&self) -> Arc<Bolt12Payment> {
Arc::new(Bolt12Payment::new(
Arc::clone(&self.channel_manager),
Arc::clone(&self.keys_manager),
Arc::clone(&self.payment_store),
Arc::clone(&self.config),
Arc::clone(&self.is_running),
Expand Down Expand Up @@ -1127,7 +1130,9 @@ impl Node {
}

let push_msat = push_to_counterparty_msat.unwrap_or(0);
let user_channel_id: u128 = rand::rng().random();
let user_channel_id: u128 = u128::from_ne_bytes(
self.keys_manager.get_secure_random_bytes()[..16].try_into().unwrap(),
);

match self.channel_manager.create_channel(
peer_info.node_id,
Expand Down
6 changes: 4 additions & 2 deletions src/liquidity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ use lightning::ln::channelmanager::{InterceptId, MIN_FINAL_CLTV_EXPIRY_DELTA};
use lightning::ln::msgs::SocketAddress;
use lightning::ln::types::ChannelId;
use lightning::routing::router::{RouteHint, RouteHintHop};
use lightning::sign::EntropySource;
use lightning_invoice::{Bolt11Invoice, Bolt11InvoiceDescription, InvoiceBuilder, RoutingFees};
use lightning_liquidity::events::LiquidityEvent;
use lightning_liquidity::lsps0::ser::{LSPSDateTime, LSPSRequestId};
Expand All @@ -35,7 +36,6 @@ use lightning_liquidity::lsps2::service::LSPS2ServiceConfig as LdkLSPS2ServiceCo
use lightning_liquidity::lsps2::utils::compute_opening_fee;
use lightning_liquidity::{LiquidityClientConfig, LiquidityServiceConfig};
use lightning_types::payment::PaymentHash;
use rand::Rng;
use tokio::sync::oneshot;

use crate::builder::BuildError;
Expand Down Expand Up @@ -641,7 +641,9 @@ where
return;
};

let user_channel_id: u128 = rand::rng().random();
let user_channel_id: u128 = u128::from_ne_bytes(
self.keys_manager.get_secure_random_bytes()[..16].try_into().unwrap(),
);
let intercept_scid = self.channel_manager.get_intercept_scid();

if let Some(payment_size_msat) = payment_size_msat {
Expand Down
33 changes: 18 additions & 15 deletions src/payment/bolt12.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,17 @@ use lightning::ln::outbound_payment::Retry;
use lightning::offers::offer::{Amount, Offer as LdkOffer, OfferFromHrn, Quantity};
use lightning::offers::parse::Bolt12SemanticError;
use lightning::routing::router::RouteParametersConfig;
use lightning::sign::EntropySource;
#[cfg(feature = "uniffi")]
use lightning::util::ser::{Readable, Writeable};
use lightning_types::string::UntrustedString;
use rand::RngCore;

use crate::config::{AsyncPaymentsRole, Config, LDK_PAYMENT_RETRY_TIMEOUT};
use crate::error::Error;
use crate::ffi::{maybe_deref, maybe_wrap};
use crate::logger::{log_error, log_info, LdkLogger, Logger};
use crate::payment::store::{PaymentDetails, PaymentDirection, PaymentKind, PaymentStatus};
use crate::types::{ChannelManager, PaymentStore};
use crate::types::{ChannelManager, KeysManager, PaymentStore};

#[cfg(not(feature = "uniffi"))]
type Bolt12Invoice = lightning::offers::invoice::Bolt12Invoice;
Expand Down Expand Up @@ -59,6 +59,7 @@ type HumanReadableName = Arc<crate::ffi::HumanReadableName>;
/// [`Node::bolt12_payment`]: crate::Node::bolt12_payment
pub struct Bolt12Payment {
channel_manager: Arc<ChannelManager>,
keys_manager: Arc<KeysManager>,
payment_store: Arc<PaymentStore>,
config: Arc<Config>,
is_running: Arc<RwLock<bool>>,
Expand All @@ -68,11 +69,19 @@ pub struct Bolt12Payment {

impl Bolt12Payment {
pub(crate) fn new(
channel_manager: Arc<ChannelManager>, payment_store: Arc<PaymentStore>,
config: Arc<Config>, is_running: Arc<RwLock<bool>>, logger: Arc<Logger>,
async_payments_role: Option<AsyncPaymentsRole>,
channel_manager: Arc<ChannelManager>, keys_manager: Arc<KeysManager>,
payment_store: Arc<PaymentStore>, config: Arc<Config>, is_running: Arc<RwLock<bool>>,
logger: Arc<Logger>, async_payments_role: Option<AsyncPaymentsRole>,
) -> Self {
Self { channel_manager, payment_store, config, is_running, logger, async_payments_role }
Self {
channel_manager,
keys_manager,
payment_store,
config,
is_running,
logger,
async_payments_role,
}
}

/// Send a payment given an offer.
Expand All @@ -94,9 +103,7 @@ impl Bolt12Payment {

let offer = maybe_deref(offer);

let mut random_bytes = [0u8; 32];
rand::rng().fill_bytes(&mut random_bytes);
let payment_id = PaymentId(random_bytes);
let payment_id = PaymentId(self.keys_manager.get_secure_random_bytes());
let retry_strategy = Retry::Timeout(LDK_PAYMENT_RETRY_TIMEOUT);
let route_parameters =
route_parameters.or(self.config.route_parameters).unwrap_or_default();
Expand Down Expand Up @@ -237,9 +244,7 @@ impl Bolt12Payment {

let offer = maybe_deref(offer);

let mut random_bytes = [0u8; 32];
rand::rng().fill_bytes(&mut random_bytes);
let payment_id = PaymentId(random_bytes);
let payment_id = PaymentId(self.keys_manager.get_secure_random_bytes());
let retry_strategy = Retry::Timeout(LDK_PAYMENT_RETRY_TIMEOUT);
let route_parameters =
route_parameters.or(self.config.route_parameters).unwrap_or_default();
Expand Down Expand Up @@ -462,9 +467,7 @@ impl Bolt12Payment {
&self, amount_msat: u64, expiry_secs: u32, quantity: Option<u64>,
payer_note: Option<String>, route_parameters: Option<RouteParametersConfig>,
) -> Result<Refund, Error> {
let mut random_bytes = [0u8; 32];
rand::rng().fill_bytes(&mut random_bytes);
let payment_id = PaymentId(random_bytes);
let payment_id = PaymentId(self.keys_manager.get_secure_random_bytes());

let absolute_expiry = (SystemTime::now() + Duration::from_secs(expiry_secs as u64))
.duration_since(UNIX_EPOCH)
Expand Down
Loading