diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e943bc06d5d..7077cb7c55b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -208,6 +208,24 @@ jobs: RUSTFLAGS: '--cfg=taproot' RUSTDOCFLAGS: '--cfg=taproot' + check_docs: + runs-on: self-hosted + env: + # While docs.rs builds using a nightly compiler (and we use some nightly features), + # nightly ends up randomly breaking builds occasionally, so we instead use beta + # and set RUSTC_BOOTSTRAP in check-docsrs.sh + TOOLCHAIN: beta + steps: + - name: Checkout source code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Install Rust ${{ env.TOOLCHAIN }} toolchain + run: | + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --profile=minimal --default-toolchain ${{ env.TOOLCHAIN }} + - name: Simulate docs.rs build + run: ci/check-docsrs.sh + fuzz: runs-on: ubuntu-latest env: diff --git a/CHANGELOG.md b/CHANGELOG.md index 66d88ad9dcb..2bd6029ff99 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# 0.1.7 - Oct 21, 2025 - "Unstable Release CI" + +## Bug Fixes + * Builds with the `docsrs` cfg flag (set automatically for builds on docs.rs + but otherwise not used) were fixed. + + # 0.1.6 - Oct 10, 2025 - "Async Preimage Claims" ## Performance Improvements @@ -36,6 +43,7 @@ it. This allows a peer which opens channels without funding them to bloat our memory and disk space, eventually leading to denial-of-service (#4081). + # 0.1.5 - Jul 16, 2025 - "Async Path Reduction" ## Performance Improvements diff --git a/ci/check-docsrs.sh b/ci/check-docsrs.sh new file mode 100755 index 00000000000..b8776f8ac57 --- /dev/null +++ b/ci/check-docsrs.sh @@ -0,0 +1,42 @@ +#!/bin/bash +#shellcheck disable=SC2002,SC2086,SC2207 + +set -ex + +# Attempt to simulate the docsrs builds. Sadly its not entirely trivial as +# docs.rs reads metadata out of Cargo.toml which we don't want to have a whole +# parser for. + +WORKSPACE_MEMBERS=( $(cat Cargo.toml | tr '\n' '\r' | sed 's/\r //g' | tr '\r' '\n' | grep '^members =' | sed 's/members.*=.*\[//' | tr -d '"' | tr ',' '\n') ) +echo "${WORKSPACE_MEMBERS[@]}" +for CRATE in "${WORKSPACE_MEMBERS[@]}"; do + pushd "$CRATE" + CARGO_ARGS="" + RUSTDOC_ARGS="" + cat Cargo.toml | grep -A 100 '\[package.metadata.docs.rs\]' | tail -n +2 > /tmp/ldk-docsrs-rustdoc-config.txt + while read -r LINE; do + case "$LINE" in + "["*) break;; + "features"*) + OG_IFS="$IFS" + IFS=',' + for FEATURE in $(echo "$LINE" | sed 's/features.*=.*\[//g' | tr -d '"] '); do + export CARGO_ARGS="$CARGO_ARGS --features $FEATURE" + done + IFS="$OG_IFS" + ;; + "all-features = true") + export CARGO_ARGS="$CARGO_ARGS --all-features" + ;; + "rustdoc-args"*) + RUSTDOC_ARGS="$(echo "$LINE" | sed 's/rustdoc-args.*=.*\[//g' | tr -d '"],')" + ;; + esac + done < /tmp/ldk-docsrs-rustdoc-config.txt + rm /tmp/ldk-docsrs-rustdoc-config.txt + echo "Building $CRATE with args $CARGO_ARGS and flags $RUSTDOC_ARGS" + # We rely on nightly features but want to use a stable release in CI to avoid + # spurous breakage, thus we set RUSTC_BOOTSTRAP=1 here. + RUSTC_BOOTSTRAP=1 cargo rustdoc $CARGO_ARGS -- $RUSTDOC_ARGS + popd +done diff --git a/ci/ci-tests.sh b/ci/ci-tests.sh index 20cdaf26431..100158ac71d 100755 --- a/ci/ci-tests.sh +++ b/ci/ci-tests.sh @@ -1,4 +1,5 @@ #!/bin/bash +#shellcheck disable=SC2002,SC2207 set -eox pipefail RUSTC_MINOR_VERSION=$(rustc --version | awk '{ split($2,a,"."); print a[2] }') @@ -41,23 +42,7 @@ export RUST_BACKTRACE=1 echo -e "\n\nChecking the workspace, except lightning-transaction-sync." cargo check --verbose --color always -# When the workspace members change, make sure to update the list here as well -# as in `Cargo.toml`. -WORKSPACE_MEMBERS=( - lightning - lightning-types - lightning-block-sync - lightning-invoice - lightning-net-tokio - lightning-persister - lightning-background-processor - lightning-rapid-gossip-sync - lightning-custom-message - lightning-macros - lightning-dns-resolver - lightning-liquidity - possiblyrandom -) +WORKSPACE_MEMBERS=( $(cat Cargo.toml | tr '\n' '\r' | sed 's/\r //g' | tr '\r' '\n' | grep '^members =' | sed 's/members.*=.*\[//' | tr -d '"' | tr ',' ' ') ) echo -e "\n\nChecking, testing, and building docs for all workspace members individually..." for DIR in "${WORKSPACE_MEMBERS[@]}"; do diff --git a/lightning-background-processor/src/lib.rs b/lightning-background-processor/src/lib.rs index ef889d4e80f..a6a6d52f27d 100644 --- a/lightning-background-processor/src/lib.rs +++ b/lightning-background-processor/src/lib.rs @@ -5,7 +5,7 @@ #![deny(rustdoc::private_intra_doc_links)] #![deny(missing_docs)] #![cfg_attr(not(feature = "futures"), deny(unsafe_code))] -#![cfg_attr(docsrs, feature(doc_auto_cfg))] +#![cfg_attr(docsrs, feature(doc_cfg))] #![cfg_attr(all(not(feature = "std"), not(test)), no_std)] #[cfg(any(test, feature = "std"))] diff --git a/lightning-block-sync/src/lib.rs b/lightning-block-sync/src/lib.rs index 3f981cd8786..22c05ed6a12 100644 --- a/lightning-block-sync/src/lib.rs +++ b/lightning-block-sync/src/lib.rs @@ -17,7 +17,7 @@ #![deny(rustdoc::private_intra_doc_links)] #![deny(missing_docs)] #![deny(unsafe_code)] -#![cfg_attr(docsrs, feature(doc_auto_cfg))] +#![cfg_attr(docsrs, feature(doc_cfg))] #[cfg(any(feature = "rest-client", feature = "rpc-client"))] pub mod http; diff --git a/lightning-invoice/src/lib.rs b/lightning-invoice/src/lib.rs index b814210b390..2d1282ee2cd 100644 --- a/lightning-invoice/src/lib.rs +++ b/lightning-invoice/src/lib.rs @@ -5,7 +5,7 @@ #![deny(non_camel_case_types)] #![deny(non_snake_case)] #![deny(unused_mut)] -#![cfg_attr(docsrs, feature(doc_auto_cfg))] +#![cfg_attr(docsrs, feature(doc_cfg))] #![cfg_attr(all(not(feature = "std"), not(test)), no_std)] //! This crate provides data structures to represent diff --git a/lightning-liquidity/src/lib.rs b/lightning-liquidity/src/lib.rs index 520c2009811..4b4eb51c15f 100644 --- a/lightning-liquidity/src/lib.rs +++ b/lightning-liquidity/src/lib.rs @@ -44,7 +44,7 @@ #![allow(bare_trait_objects)] #![allow(ellipsis_inclusive_range_patterns)] #![allow(clippy::drop_non_drop)] -#![cfg_attr(docsrs, feature(doc_auto_cfg))] +#![cfg_attr(docsrs, feature(doc_cfg))] #![cfg_attr(not(feature = "std"), no_std)] #[macro_use] diff --git a/lightning-macros/src/lib.rs b/lightning-macros/src/lib.rs index fd4707e5856..62fbd316087 100644 --- a/lightning-macros/src/lib.rs +++ b/lightning-macros/src/lib.rs @@ -16,7 +16,7 @@ #![forbid(unsafe_code)] #![deny(rustdoc::broken_intra_doc_links)] #![deny(rustdoc::private_intra_doc_links)] -#![cfg_attr(docsrs, feature(doc_auto_cfg))] +#![cfg_attr(docsrs, feature(doc_cfg))] use proc_macro::TokenStream; use quote::quote; diff --git a/lightning-net-tokio/src/lib.rs b/lightning-net-tokio/src/lib.rs index 944033102c6..a15700e60f6 100644 --- a/lightning-net-tokio/src/lib.rs +++ b/lightning-net-tokio/src/lib.rs @@ -25,7 +25,7 @@ #![deny(rustdoc::broken_intra_doc_links)] #![deny(rustdoc::private_intra_doc_links)] #![deny(missing_docs)] -#![cfg_attr(docsrs, feature(doc_auto_cfg))] +#![cfg_attr(docsrs, feature(doc_cfg))] use bitcoin::secp256k1::PublicKey; diff --git a/lightning-persister/src/lib.rs b/lightning-persister/src/lib.rs index 9d4df264d24..0e3541e1b27 100644 --- a/lightning-persister/src/lib.rs +++ b/lightning-persister/src/lib.rs @@ -3,7 +3,7 @@ #![deny(rustdoc::broken_intra_doc_links)] #![deny(rustdoc::private_intra_doc_links)] #![deny(missing_docs)] -#![cfg_attr(docsrs, feature(doc_auto_cfg))] +#![cfg_attr(docsrs, feature(doc_cfg))] #[cfg(ldk_bench)] extern crate criterion; diff --git a/lightning-transaction-sync/src/lib.rs b/lightning-transaction-sync/src/lib.rs index 19ebe007ec2..54de804e107 100644 --- a/lightning-transaction-sync/src/lib.rs +++ b/lightning-transaction-sync/src/lib.rs @@ -69,7 +69,7 @@ #![deny(rustdoc::private_intra_doc_links)] #![deny(missing_docs)] #![deny(unsafe_code)] -#![cfg_attr(docsrs, feature(doc_auto_cfg))] +#![cfg_attr(docsrs, feature(doc_cfg))] #[cfg(any(feature = "esplora-blocking", feature = "esplora-async"))] mod esplora; diff --git a/lightning-types/src/lib.rs b/lightning-types/src/lib.rs index 1539401d383..49e7e59084e 100644 --- a/lightning-types/src/lib.rs +++ b/lightning-types/src/lib.rs @@ -18,7 +18,7 @@ #![forbid(unsafe_code)] #![deny(rustdoc::broken_intra_doc_links)] #![deny(rustdoc::private_intra_doc_links)] -#![cfg_attr(docsrs, feature(doc_auto_cfg))] +#![cfg_attr(docsrs, feature(doc_cfg))] extern crate alloc; extern crate core; diff --git a/lightning/Cargo.toml b/lightning/Cargo.toml index 5959ae8ed58..9e04cffb2eb 100644 --- a/lightning/Cargo.toml +++ b/lightning/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "lightning" -version = "0.1.6" +version = "0.1.7" authors = ["Matt Corallo"] license = "MIT OR Apache-2.0" repository = "https://github.com/lightningdevkit/rust-lightning/" diff --git a/lightning/src/events/mod.rs b/lightning/src/events/mod.rs index 5bc446f9724..4b492b0607a 100644 --- a/lightning/src/events/mod.rs +++ b/lightning/src/events/mod.rs @@ -1364,7 +1364,7 @@ pub enum Event { /// To accept the request (and in the case of a dual-funded channel, not contribute funds), /// call [`ChannelManager::accept_inbound_channel`]. /// To reject the request, call [`ChannelManager::force_close_without_broadcasting_txn`]. - /// Note that a ['ChannelClosed`] event will _not_ be triggered if the channel is rejected. + /// Note that a [`ChannelClosed`] event will _not_ be triggered if the channel is rejected. /// /// The event is only triggered when a new open channel request is received and the /// [`UserConfig::manually_accept_inbound_channels`] config flag is set to true. @@ -1374,6 +1374,7 @@ pub enum Event { /// returning `Err(ReplayEvent ())`) and won't be persisted across restarts. /// /// [`ChannelManager::accept_inbound_channel`]: crate::ln::channelmanager::ChannelManager::accept_inbound_channel + /// [`ChannelClosed`]: Event::ChannelClosed /// [`ChannelManager::force_close_without_broadcasting_txn`]: crate::ln::channelmanager::ChannelManager::force_close_without_broadcasting_txn /// [`UserConfig::manually_accept_inbound_channels`]: crate::util::config::UserConfig::manually_accept_inbound_channels OpenChannelRequest { diff --git a/lightning/src/lib.rs b/lightning/src/lib.rs index 4fa2871ddcb..c35908ecf5e 100644 --- a/lightning/src/lib.rs +++ b/lightning/src/lib.rs @@ -41,7 +41,7 @@ #![allow(bare_trait_objects)] #![allow(ellipsis_inclusive_range_patterns)] -#![cfg_attr(docsrs, feature(doc_auto_cfg))] +#![cfg_attr(docsrs, feature(doc_cfg))] #![cfg_attr(all(not(feature = "std"), not(test)), no_std)] diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs index 4c976f3865b..7924511d799 100644 --- a/lightning/src/ln/channelmanager.rs +++ b/lightning/src/ln/channelmanager.rs @@ -2371,7 +2371,7 @@ where /// [`get_event_or_persistence_needed_future`]: Self::get_event_or_persistence_needed_future /// [`lightning-block-sync`]: https://docs.rs/lightning_block_sync/latest/lightning_block_sync /// [`lightning-transaction-sync`]: https://docs.rs/lightning_transaction_sync/latest/lightning_transaction_sync -/// [`lightning-background-processor`]: https://docs.rs/lightning_background_processor/lightning_background_processor +/// [`lightning-background-processor`]: https://docs.rs/lightning-background-processor/latest/lightning_background_processor /// [`list_channels`]: Self::list_channels /// [`list_usable_channels`]: Self::list_usable_channels /// [`create_channel`]: Self::create_channel @@ -3997,7 +3997,7 @@ where /// /// The `shutdown_script` provided will be used as the `scriptPubKey` for the closing transaction. /// Will fail if a shutdown script has already been set for this channel by - /// ['ChannelHandshakeConfig::commit_upfront_shutdown_pubkey`]. The given shutdown script must + /// [`ChannelHandshakeConfig::commit_upfront_shutdown_pubkey`]. The given shutdown script must /// also be compatible with our and the counterparty's features. /// /// May generate a [`SendShutdown`] message event on success, which should be relayed. @@ -4009,6 +4009,7 @@ where /// /// [`ChannelConfig::force_close_avoidance_max_fee_satoshis`]: crate::util::config::ChannelConfig::force_close_avoidance_max_fee_satoshis /// [`NonAnchorChannelFee`]: crate::chain::chaininterface::ConfirmationTarget::NonAnchorChannelFee + /// [`ChannelHandshakeConfig::commit_upfront_shutdown_pubkey`]: crate::util::config::ChannelHandshakeConfig::commit_upfront_shutdown_pubkey /// [`SendShutdown`]: crate::events::MessageSendEvent::SendShutdown pub fn close_channel_with_feerate_and_script(&self, channel_id: &ChannelId, counterparty_node_id: &PublicKey, target_feerate_sats_per_1000_weight: Option, shutdown_script: Option) -> Result<(), APIError> { self.close_channel_internal(channel_id, counterparty_node_id, target_feerate_sats_per_1000_weight, shutdown_script) @@ -10472,7 +10473,7 @@ where } /// Pays for an [`Offer`] looked up using [BIP 353] Human Readable Names resolved by the DNS - /// resolver(s) at `dns_resolvers` which resolve names according to bLIP 32. + /// resolver(s) at `dns_resolvers` which resolve names according to [bLIP 32]. /// /// If the wallet supports paying on-chain schemes, you should instead use /// [`OMNameResolver::resolve_name`] and [`OMNameResolver::handle_dnssec_proof_for_uri`] (by @@ -10490,18 +10491,19 @@ where /// /// To revoke the request, use [`ChannelManager::abandon_payment`] prior to receiving the /// invoice. If abandoned, or an invoice isn't received in a reasonable amount of time, the - /// payment will fail with an [`Event::InvoiceRequestFailed`]. + /// payment will fail with an [`PaymentFailureReason::UserAbandoned`] or + /// [`PaymentFailureReason::InvoiceRequestExpired`], respectively. /// /// # Privacy /// /// For payer privacy, uses a derived payer id and uses [`MessageRouter::create_blinded_paths`] - /// to construct a [`BlindedPath`] for the reply path. For further privacy implications, see the + /// to construct a [`BlindedMessagePath`] for the reply path. For further privacy implications, see the /// docs of the parameterized [`Router`], which implements [`MessageRouter`]. /// /// # Limitations /// /// Requires a direct connection to the given [`Destination`] as well as an introduction node in - /// [`Offer::paths`] or to [`Offer::signing_pubkey`], if empty. A similar restriction applies to + /// [`Offer::paths`] or to [`Offer::issuer_signing_pubkey`], if empty. A similar restriction applies to /// the responding [`Bolt12Invoice::payment_paths`]. /// /// # Errors @@ -10509,8 +10511,13 @@ where /// Errors if: /// - a duplicate `payment_id` is provided given the caveats in the aforementioned link, /// + /// [BIP 353]: https://github.com/bitcoin/bips/blob/master/bip-0353.mediawiki + /// [bLIP 32]: https://github.com/lightning/blips/blob/master/blip-0032.md /// [`Bolt12Invoice::payment_paths`]: crate::offers::invoice::Bolt12Invoice::payment_paths /// [Avoiding Duplicate Payments]: #avoiding-duplicate-payments + /// [`BlindedMessagePath`]: crate::blinded_path::message::BlindedMessagePath + /// [`PaymentFailureReason::UserAbandoned`]: crate::events::PaymentFailureReason::UserAbandoned + /// [`PaymentFailureReason::InvoiceRequestRejected`]: crate::events::PaymentFailureReason::InvoiceRequestRejected #[cfg(feature = "dnssec")] pub fn pay_for_offer_from_human_readable_name( &self, name: HumanReadableName, amount_msats: u64, payment_id: PaymentId, @@ -11365,7 +11372,7 @@ where // Most of our tests were written when we only broadcasted // `channel_announcement`s once and then never re-broadcasted // them again, so disable the re-broadcasting entirely in tests - #[cfg(test)] + #[cfg(any(test, feature = "_test_utils"))] { should_announce = announcement_sigs.is_some(); } diff --git a/lightning/src/ln/peer_handler.rs b/lightning/src/ln/peer_handler.rs index 629d6d12b96..0782f778b24 100644 --- a/lightning/src/ln/peer_handler.rs +++ b/lightning/src/ln/peer_handler.rs @@ -2102,6 +2102,8 @@ impl 0 { // If we're not the first event processor to get here, just return early, the increment