Skip to content

Commit

Permalink
Drop no-std feature
Browse files Browse the repository at this point in the history
We drop the `lightning/no-std` feature and just take
`hashbrown`,`possiblyrandom` and `libm` as required dependencies.
  • Loading branch information
tnull committed Sep 13, 2024
1 parent 4d7897d commit 0e8a736
Show file tree
Hide file tree
Showing 17 changed files with 31 additions and 105 deletions.
7 changes: 0 additions & 7 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -149,16 +149,11 @@ jobs:
run: |
cd lightning
RUSTFLAGS="--cfg=require_route_graph_test" cargo test
RUSTFLAGS="--cfg=require_route_graph_test" cargo test --features hashbrown
cd ..
- name: Run benchmarks on Rust ${{ matrix.toolchain }}
run: |
cd bench
RUSTFLAGS="--cfg=ldk_bench --cfg=require_route_graph_test" cargo bench
- name: Run benchmarks with hashbrown on Rust ${{ matrix.toolchain }}
run: |
cd bench
RUSTFLAGS="--cfg=ldk_bench --cfg=require_route_graph_test" cargo bench --features hashbrown
check_commits:
runs-on: ubuntu-latest
Expand Down Expand Up @@ -199,13 +194,11 @@ jobs:
- name: Run cargo check for release build.
run: |
cargo check --release
cargo check --no-default-features --features=no-std --release
cargo check --no-default-features --features=futures,std --release
cargo doc --release
- name: Run cargo check for Taproot build.
run: |
cargo check --release
cargo check --no-default-features --features=no-std --release
cargo check --no-default-features --features=futures,std --release
cargo doc --release
env:
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ Crates
-----------
1. [lightning](./lightning)
The core of the LDK library, implements the Lightning protocol, channel state machine,
and on-chain logic. Supports `no-std` and exposes only relatively low-level interfaces.
and on-chain logic. Supports `no_std` and exposes only relatively low-level interfaces.
2. [lightning-background-processor](./lightning-background-processor)
Utilities to perform required background tasks for Rust Lightning.
3. [lightning-block-sync](./lightning-block-sync)
Expand Down
3 changes: 0 additions & 3 deletions bench/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,6 @@ edition = "2021"
name = "bench"
harness = false

[features]
hashbrown = ["lightning/hashbrown"]

[dependencies]
lightning = { path = "../lightning", features = ["_test_utils", "criterion"] }
lightning-persister = { path = "../lightning-persister", features = ["criterion"] }
Expand Down
3 changes: 0 additions & 3 deletions bench/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
This crate uses criterion to benchmark various LDK functions.

It can be run as `RUSTFLAGS=--cfg=ldk_bench cargo bench`.

For routing or other HashMap-bottlenecked functions, the `hashbrown` feature
should also be benchmarked.
14 changes: 6 additions & 8 deletions ci/ci-tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -100,38 +100,36 @@ grep '^max_level_' lightning/Cargo.toml | awk '{ print $1 }'| while read -r FEAT
RUSTFLAGS="$RUSTFLAGS -A unused_variables -A unused_macros -A unused_imports -A dead_code" cargo check -p lightning --verbose --color always --features "$FEATURE"
done

echo -e "\n\nTesting no-std builds"
echo -e "\n\nTesting no_std builds"
for DIR in lightning-invoice lightning-rapid-gossip-sync; do
cargo test -p $DIR --verbose --color always --no-default-features
done

cargo test -p lightning --verbose --color always --no-default-features --features no-std
# check if there is a conflict between no-std and the default std feature
cargo test -p lightning --verbose --color always --features no-std
cargo test -p lightning --verbose --color always --no-default-features

echo -e "\n\nTesting c_bindings builds"
# Note that because `$RUSTFLAGS` is not passed through to doctest builds we cannot selectively
# disable doctests in `c_bindings` so we skip doctests entirely here.
RUSTFLAGS="$RUSTFLAGS --cfg=c_bindings" cargo test --verbose --color always --lib --bins --tests

for DIR in lightning-invoice lightning-rapid-gossip-sync; do
# check if there is a conflict between no-std and the c_bindings cfg
# check if there is a conflict between no_std and the c_bindings cfg
RUSTFLAGS="$RUSTFLAGS --cfg=c_bindings" cargo test -p $DIR --verbose --color always --no-default-features
done

# Note that because `$RUSTFLAGS` is not passed through to doctest builds we cannot selectively
# disable doctests in `c_bindings` so we skip doctests entirely here.
RUSTFLAGS="$RUSTFLAGS --cfg=c_bindings" cargo test -p lightning-background-processor --verbose --color always --features futures --no-default-features --lib --bins --tests
RUSTFLAGS="$RUSTFLAGS --cfg=c_bindings" cargo test -p lightning --verbose --color always --no-default-features --features=no-std --lib --bins --tests
RUSTFLAGS="$RUSTFLAGS --cfg=c_bindings" cargo test -p lightning --verbose --color always --no-default-features --lib --bins --tests

echo -e "\n\nTesting other crate-specific builds"
# Note that outbound_commitment_test only runs in this mode because of hardcoded signature values
RUSTFLAGS="$RUSTFLAGS --cfg=ldk_test_vectors" cargo test -p lightning --verbose --color always --no-default-features --features=std
# This one only works for lightning-invoice
# check that compile with no-std and serde works in lightning-invoice
# check that compile with no_std and serde works in lightning-invoice
cargo test -p lightning-invoice --verbose --color always --no-default-features --features serde

echo -e "\n\nTesting no-std build on a downstream no-std crate"
echo -e "\n\nTesting no_std build on a downstream no-std crate"
# check no-std compatibility across dependencies
pushd no-std-check
cargo check --verbose --color always --features lightning-transaction-sync
Expand Down
2 changes: 1 addition & 1 deletion fuzz/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ libfuzzer_fuzz = ["libfuzzer-sys"]
stdin_fuzz = []

[dependencies]
lightning = { path = "../lightning", features = ["regex", "hashbrown", "_test_utils"] }
lightning = { path = "../lightning", features = ["regex", "_test_utils"] }
lightning-invoice = { path = "../lightning-invoice" }
lightning-rapid-gossip-sync = { path = "../lightning-rapid-gossip-sync" }
bech32 = "0.9.1"
Expand Down
4 changes: 2 additions & 2 deletions lightning-rapid-gossip-sync/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@
//! let network_graph = NetworkGraph::new(Network::Bitcoin, &logger);
//! let rapid_sync = RapidGossipSync::new(&network_graph, &logger);
//! let snapshot_contents: &[u8] = &[0; 0];
//! // In no-std you need to provide the current time in unix epoch seconds
//! // otherwise you can use update_network_graph
//! // In non-`std` environments you need to provide the current time in unix epoch seconds
//! // otherwise you can use `update_network_graph`
//! let current_time_unix = 0;
//! let new_last_sync_timestamp_result = rapid_sync.update_network_graph_no_std(snapshot_contents, Some(current_time_unix));
//! ```
Expand Down
7 changes: 3 additions & 4 deletions lightning/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ max_level_trace = []
# This is unsafe to use in production because it may result in the counterparty publishing taking our funds.
unsafe_revoked_tx_signing = []

no-std = ["hashbrown", "possiblyrandom", "libm"]
std = []

# Generates low-r bitcoin signatures, which saves 1 byte in 50% of the cases
Expand All @@ -44,12 +43,12 @@ lightning-invoice = { version = "0.32.0", path = "../lightning-invoice", default
bech32 = { version = "0.9.1", default-features = false }
bitcoin = { version = "0.32.2", default-features = false, features = ["secp-recovery"] }

hashbrown = { version = "0.13", optional = true, default-features = false }
possiblyrandom = { version = "0.2", path = "../possiblyrandom", optional = true, default-features = false }
hashbrown = { version = "0.13", default-features = false }
possiblyrandom = { version = "0.2", path = "../possiblyrandom", default-features = false }
regex = { version = "1.5.6", optional = true }
backtrace = { version = "0.3", optional = true }

libm = { version = "0.2", optional = true, default-features = false }
libm = { version = "0.2", default-features = false }

[dev-dependencies]
regex = "1.5.6"
Expand Down
4 changes: 0 additions & 4 deletions lightning/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
//!
//! * `std`
//! * `grind_signatures`
//! * `no-std ` - exposes write trait implementations from the `core2` crate (at least one of `no-std` or `std` are required)
//! * Skip logging of messages at levels below the given log level:
//! * `max_level_off`
//! * `max_level_error`
Expand All @@ -53,9 +52,6 @@

#![cfg_attr(all(not(feature = "std"), not(test)), no_std)]

#[cfg(not(any(feature = "std", feature = "no-std")))]
compile_error!("at least one of the `std` or `no-std` features must be enabled");

#[cfg(all(fuzzing, test))]
compile_error!("Tests will always fail with cfg=fuzzing");

Expand Down
4 changes: 2 additions & 2 deletions lightning/src/ln/channelmanager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5920,7 +5920,7 @@ where
/// * Forgetting about stale outbound payments, either those that have already been fulfilled
/// or those awaiting an invoice that hasn't been delivered in the necessary amount of time.
/// The latter is determined using the system clock in `std` and the highest seen block time
/// minus two hours in `no-std`.
/// minus two hours in non-`std`.
///
/// Note that this may cause reentrancy through [`chain::Watch::update_channel`] calls or feerate
/// estimate fetches.
Expand Down Expand Up @@ -8942,7 +8942,7 @@ macro_rules! create_refund_builder { ($self: ident, $builder: ty) => {
/// See [Avoiding Duplicate Payments] for other requirements once the payment has been sent.
///
/// The builder will have the provided expiration set. Any changes to the expiration on the
/// returned builder will not be honored by [`ChannelManager`]. For `no-std`, the highest seen
/// returned builder will not be honored by [`ChannelManager`]. For non-`std`, the highest seen
/// block time minus two hours is used for the current time when determining if the refund has
/// expired.
///
Expand Down
2 changes: 1 addition & 1 deletion lightning/src/offers/invoice_request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -719,7 +719,7 @@ macro_rules! invoice_request_respond_with_explicit_signing_pubkey_methods { (
/// Creates an [`InvoiceBuilder`] for the request with the given required fields.
///
/// Unless [`InvoiceBuilder::relative_expiry`] is set, the invoice will expire two hours after
/// `created_at`, which is used to set [`Bolt12Invoice::created_at`]. Useful for `no-std` builds
/// `created_at`, which is used to set [`Bolt12Invoice::created_at`]. Useful for non-`std` builds
/// where [`std::time::SystemTime`] is not available.
///
/// The caller is expected to remember the preimage of `payment_hash` in order to claim a payment
Expand Down
2 changes: 1 addition & 1 deletion lightning/src/offers/refund.rs
Original file line number Diff line number Diff line change
Expand Up @@ -545,7 +545,7 @@ macro_rules! respond_with_explicit_signing_pubkey_methods { ($self: ident, $buil
/// Creates an [`InvoiceBuilder`] for the refund with the given required fields.
///
/// Unless [`InvoiceBuilder::relative_expiry`] is set, the invoice will expire two hours after
/// `created_at`, which is used to set [`Bolt12Invoice::created_at`]. Useful for `no-std` builds
/// `created_at`, which is used to set [`Bolt12Invoice::created_at`]. Useful for non-`std` builds
/// where [`std::time::SystemTime`] is not available.
///
/// The caller is expected to remember the preimage of `payment_hash` in order to
Expand Down
16 changes: 8 additions & 8 deletions lightning/src/routing/gossip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ pub struct NetworkGraph<L: Deref> where L::Target: Logger {
//
// NOTE: In the following `removed_*` maps, we use seconds since UNIX epoch to track time instead
// of `std::time::Instant`s for a few reasons:
// * We want it to be possible to do tracking in no-std environments where we can compare
// * We want it to be possible to do tracking in non-`std` environments where we can compare
// a provided current UNIX timestamp with the time at which we started tracking.
// * In the future, if we decide to persist these maps, they will already be serializable.
// * Although we lose out on the platform's monotonic clock, the system clock in a std
Expand Down Expand Up @@ -612,7 +612,7 @@ where U::Target: UtxoLookup, L::Target: Logger
// our peers and never receiving gossip from peers at all, we send all of our peers a
// `gossip_timestamp_filter`, with the filter time set either two weeks ago or an hour ago.
//
// For no-std builds, we bury our head in the sand and do a full sync on each connection.
// For non-`std` builds, we bury our head in the sand and do a full sync on each connection.
#[allow(unused_mut, unused_assignments)]
let mut gossip_start_time = 0;
#[allow(unused)]
Expand Down Expand Up @@ -934,7 +934,7 @@ pub struct ChannelInfo {
/// Not stored if contains excess data to prevent DoS.
pub announcement_message: Option<ChannelAnnouncement>,
/// The timestamp when we received the announcement, if we are running with feature = "std"
/// (which we can probably assume we are - no-std environments probably won't have a full
/// (which we can probably assume we are - non-`std` environments probably won't have a full
/// network graph in memory!).
announcement_received_time: u64,
}
Expand Down Expand Up @@ -2105,7 +2105,7 @@ impl<L: Deref> NetworkGraph<L> where L::Target: Logger {
/// in the map for a while so that these can be resynced from gossip in the future.
///
/// This method is only available with the `std` feature. See
/// [`NetworkGraph::remove_stale_channels_and_tracking_with_time`] for `no-std` use.
/// [`NetworkGraph::remove_stale_channels_and_tracking_with_time`] for non-`std` use.
pub fn remove_stale_channels_and_tracking(&self) {
let time = SystemTime::now().duration_since(UNIX_EPOCH).expect("Time must be > 1970").as_secs();
self.remove_stale_channels_and_tracking_with_time(time);
Expand Down Expand Up @@ -2169,7 +2169,7 @@ impl<L: Deref> NetworkGraph<L> where L::Target: Logger {
if let Some(time) = time {
current_time_unix.saturating_sub(*time) < REMOVED_ENTRIES_TRACKING_AGE_LIMIT_SECS
} else {
// NOTE: In the case of no-std, we won't have access to the current UNIX time at the time of removal,
// NOTE: In the case of non-`std`, we won't have access to the current UNIX time at the time of removal,
// so we'll just set the removal time here to the current UNIX time on the very next invocation
// of this function.
#[cfg(not(feature = "std"))]
Expand All @@ -2193,7 +2193,7 @@ impl<L: Deref> NetworkGraph<L> where L::Target: Logger {
/// [`RoutingMessageHandler`] implementation to call it indirectly. This may be useful to accept
/// routing messages from a source using a protocol other than the lightning P2P protocol.
///
/// If built with `no-std`, any updates with a timestamp more than two weeks in the past or
/// If not built with `std`, any updates with a timestamp more than two weeks in the past or
/// materially in the future will be rejected.
pub fn update_channel(&self, msg: &msgs::ChannelUpdate) -> Result<(), LightningError> {
self.update_channel_internal(&msg.contents, Some(&msg), Some(&msg.signature), false)
Expand All @@ -2203,7 +2203,7 @@ impl<L: Deref> NetworkGraph<L> where L::Target: Logger {
/// of the channel without verifying the associated signatures. Because we aren't given the
/// associated signatures here we cannot relay the channel update to any of our peers.
///
/// If built with `no-std`, any updates with a timestamp more than two weeks in the past or
/// If not built with `std`, any updates with a timestamp more than two weeks in the past or
/// materially in the future will be rejected.
pub fn update_channel_unsigned(&self, msg: &msgs::UnsignedChannelUpdate) -> Result<(), LightningError> {
self.update_channel_internal(msg, None, None, false)
Expand All @@ -2213,7 +2213,7 @@ impl<L: Deref> NetworkGraph<L> where L::Target: Logger {
///
/// This checks whether the update currently is applicable by [`Self::update_channel`].
///
/// If built with `no-std`, any updates with a timestamp more than two weeks in the past or
/// If not built with `std`, any updates with a timestamp more than two weeks in the past or
/// materially in the future will be rejected.
pub fn verify_channel_update(&self, msg: &msgs::ChannelUpdate) -> Result<(), LightningError> {
self.update_channel_internal(&msg.contents, Some(&msg), Some(&msg.signature), true)
Expand Down
2 changes: 1 addition & 1 deletion lightning/src/routing/scoring.rs
Original file line number Diff line number Diff line change
Expand Up @@ -749,7 +749,7 @@ pub struct ProbabilisticScoringDecayParameters {
///
/// # Note
///
/// When built with the `no-std` feature, time will never elapse. Therefore, the channel
/// When not built with the `std` feature, time will never elapse. Therefore, the channel
/// liquidity knowledge will never decay except when the bounds cross.
pub liquidity_offset_half_life: Duration,
}
Expand Down
60 changes: 3 additions & 57 deletions lightning/src/util/hash_tables.rs
Original file line number Diff line number Diff line change
@@ -1,67 +1,13 @@
//! Generally LDK uses `std`'s `HashMap`s, however when building for no-std, LDK uses `hashbrown`'s
//! `HashMap`s with the `std` `SipHasher` and uses `getrandom` to opportunistically randomize it,
//! if randomization is available.
//! Generally LDK uses `hashbrown`'s `HashMap`s with the `std` `SipHasher` and uses `getrandom` to
//! opportunistically randomize it, if randomization is available.
//!
//! This module simply re-exports the `HashMap` used in LDK for public consumption.

#[cfg(feature = "hashbrown")]
extern crate hashbrown;
#[cfg(feature = "possiblyrandom")]
extern crate possiblyrandom;

// For no-std builds, we need to use hashbrown, however, by default, it doesn't randomize the
// hashing and is vulnerable to HashDoS attacks. Thus, we use the core SipHasher when not using
// std, but use `getrandom` to randomize it if its available.

#[cfg(not(feature = "hashbrown"))]
mod std_hashtables {
pub use std::collections::hash_map::RandomState;
pub use std::collections::HashMap;

pub(crate) use std::collections::{hash_map, HashSet};

pub(crate) type OccupiedHashMapEntry<'a, K, V> =
std::collections::hash_map::OccupiedEntry<'a, K, V>;
pub(crate) type VacantHashMapEntry<'a, K, V> =
std::collections::hash_map::VacantEntry<'a, K, V>;

/// Builds a new [`HashMap`].
pub fn new_hash_map<K, V>() -> HashMap<K, V> {
HashMap::new()
}
/// Builds a new [`HashMap`] with the given capacity.
pub fn hash_map_with_capacity<K, V>(cap: usize) -> HashMap<K, V> {
HashMap::with_capacity(cap)
}
pub(crate) fn hash_map_from_iter<
K: core::hash::Hash + Eq,
V,
I: IntoIterator<Item = (K, V)>,
>(
iter: I,
) -> HashMap<K, V> {
HashMap::from_iter(iter)
}

pub(crate) fn new_hash_set<K>() -> HashSet<K> {
HashSet::new()
}
pub(crate) fn hash_set_with_capacity<K>(cap: usize) -> HashSet<K> {
HashSet::with_capacity(cap)
}
pub(crate) fn hash_set_from_iter<K: core::hash::Hash + Eq, I: IntoIterator<Item = K>>(
iter: I,
) -> HashSet<K> {
HashSet::from_iter(iter)
}
}
#[cfg(not(feature = "hashbrown"))]
pub use std_hashtables::*;

#[cfg(feature = "hashbrown")]
pub(crate) use self::hashbrown::hash_map;

#[cfg(feature = "hashbrown")]
mod hashbrown_tables {
#[cfg(feature = "std")]
mod hasher {
Expand Down Expand Up @@ -170,5 +116,5 @@ mod hashbrown_tables {
res
}
}
#[cfg(feature = "hashbrown")]

pub use hashbrown_tables::*;
2 changes: 1 addition & 1 deletion lightning/src/util/test_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1053,7 +1053,7 @@ impl msgs::RoutingMessageHandler for TestRoutingMessageHandler {

#[allow(unused_mut, unused_assignments)]
let mut gossip_start_time = 0;
#[cfg(not(feature = "no-std"))]
#[cfg(feature = "std")]
{
use std::time::{SystemTime, UNIX_EPOCH};
gossip_start_time = SystemTime::now().duration_since(UNIX_EPOCH).expect("Time must be > 1970").as_secs();
Expand Down
2 changes: 1 addition & 1 deletion no-std-check/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ version = "0.1.0"
edition = "2021"

[features]
default = ["lightning/no-std"]
default = []

[dependencies]
lightning = { path = "../lightning", default-features = false }
Expand Down

0 comments on commit 0e8a736

Please sign in to comment.