diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 3b6d1a0388c..6795c618c2b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -194,7 +194,6 @@ jobs: cargo check --no-default-features --features=no-std --release cargo check --no-default-features --features=futures --release cargo doc --release - RUSTDOCFLAGS="--cfg=anchors" cargo doc --release - name: Run cargo check for Taproot build. run: | cargo check --release @@ -202,8 +201,8 @@ jobs: cargo check --no-default-features --features=futures --release cargo doc --release env: - RUSTFLAGS: '--cfg=anchors --cfg=taproot' - RUSTDOCFLAGS: '--cfg=anchors --cfg=taproot' + RUSTFLAGS: '--cfg=taproot' + RUSTDOCFLAGS: '--cfg=taproot' fuzz: runs-on: ubuntu-latest diff --git a/ci/ci-tests.sh b/ci/ci-tests.sh index 69bf7dd2e14..b3af73f2169 100755 --- a/ci/ci-tests.sh +++ b/ci/ci-tests.sh @@ -101,9 +101,7 @@ if [ "$RUSTC_MINOR_VERSION" -gt 55 ]; then popd fi -echo -e "\n\nTest anchors builds" -pushd lightning -RUSTFLAGS="$RUSTFLAGS --cfg=anchors" cargo test --verbose --color always -p lightning echo -e "\n\nTest Taproot builds" -RUSTFLAGS="$RUSTFLAGS --cfg=anchors --cfg=taproot" cargo test --verbose --color always -p lightning +pushd lightning +RUSTFLAGS="$RUSTFLAGS --cfg=taproot" cargo test --verbose --color always -p lightning popd diff --git a/lightning/src/chain/chainmonitor.rs b/lightning/src/chain/chainmonitor.rs index 8ce59597d84..562c76fa3e2 100644 --- a/lightning/src/chain/chainmonitor.rs +++ b/lightning/src/chain/chainmonitor.rs @@ -782,30 +782,13 @@ impl, { - #[cfg(not(anchors))] - /// Processes [`SpendableOutputs`] events produced from each [`ChannelMonitor`] upon maturity. - /// - /// An [`EventHandler`] may safely call back to the provider, though this shouldn't be needed in - /// order to handle these events. - /// - /// [`SpendableOutputs`]: events::Event::SpendableOutputs - fn process_pending_events(&self, handler: H) where H::Target: EventHandler { - let mut pending_events = Vec::new(); - for monitor_state in self.monitors.read().unwrap().values() { - pending_events.append(&mut monitor_state.monitor.get_and_clear_pending_events()); - } - for event in pending_events { - handler.handle_event(event); - } - } - #[cfg(anchors)] /// Processes [`SpendableOutputs`] events produced from each [`ChannelMonitor`] upon maturity. /// /// For channels featuring anchor outputs, this method will also process [`BumpTransaction`] /// events produced from each [`ChannelMonitor`] while there is a balance to claim onchain /// within each channel. As the confirmation of a commitment transaction may be critical to the - /// safety of funds, this method must be invoked frequently, ideally once for every chain tip - /// update (block connected or disconnected). + /// safety of funds, we recommend invoking this every 30 seconds, or lower if running in an + /// environment with spotty connections, like on mobile. /// /// An [`EventHandler`] may safely call back to the provider, though this shouldn't be needed in /// order to handle these events. diff --git a/lightning/src/chain/channelmonitor.rs b/lightning/src/chain/channelmonitor.rs index fc3079271c6..904d9941349 100644 --- a/lightning/src/chain/channelmonitor.rs +++ b/lightning/src/chain/channelmonitor.rs @@ -43,16 +43,13 @@ use crate::chain::{BestBlock, WatchedOutput}; use crate::chain::chaininterface::{BroadcasterInterface, FeeEstimator, LowerBoundedFeeEstimator}; use crate::chain::transaction::{OutPoint, TransactionData}; use crate::sign::{SpendableOutputDescriptor, StaticPaymentOutputDescriptor, DelayedPaymentOutputDescriptor, WriteableEcdsaChannelSigner, SignerProvider, EntropySource}; -#[cfg(anchors)] -use crate::chain::onchaintx::ClaimEvent; -use crate::chain::onchaintx::OnchainTxHandler; +use crate::chain::onchaintx::{ClaimEvent, OnchainTxHandler}; use crate::chain::package::{CounterpartyOfferedHTLCOutput, CounterpartyReceivedHTLCOutput, HolderFundingOutput, HolderHTLCOutput, PackageSolvingData, PackageTemplate, RevokedOutput, RevokedHTLCOutput}; use crate::chain::Filter; use crate::util::logger::Logger; use crate::util::ser::{Readable, ReadableArgs, RequiredWrapper, MaybeReadable, UpgradableRequired, Writer, Writeable, U48}; use crate::util::byte_utils; use crate::events::Event; -#[cfg(anchors)] use crate::events::bump_transaction::{AnchorDescriptor, HTLCDescriptor, BumpTransactionEvent}; use crate::prelude::*; @@ -268,7 +265,6 @@ impl_writeable_tlv_based!(HolderSignedTx, { (14, htlc_outputs, vec_type) }); -#[cfg(anchors)] impl HolderSignedTx { fn non_dust_htlcs(&self) -> Vec { self.htlc_outputs.iter().filter_map(|(htlc, _, _)| { @@ -2538,7 +2534,6 @@ impl ChannelMonitorImpl { pub fn get_and_clear_pending_events(&mut self) -> Vec { let mut ret = Vec::new(); mem::swap(&mut ret, &mut self.pending_events); - #[cfg(anchors)] for (claim_id, claim_event) in self.onchain_tx_handler.get_and_clear_pending_claim_events().drain(..) { match claim_event { ClaimEvent::BumpCommitment { diff --git a/lightning/src/chain/onchaintx.rs b/lightning/src/chain/onchaintx.rs index 42cfb91bd0a..6b0c7485610 100644 --- a/lightning/src/chain/onchaintx.rs +++ b/lightning/src/chain/onchaintx.rs @@ -12,15 +12,11 @@ //! OnchainTxHandler objects are fully-part of ChannelMonitor and encapsulates all //! building, tracking, bumping and notifications functions. -#[cfg(anchors)] use bitcoin::PackedLockTime; use bitcoin::blockdata::transaction::Transaction; use bitcoin::blockdata::transaction::OutPoint as BitcoinOutPoint; use bitcoin::blockdata::script::Script; -use bitcoin::hashes::Hash; -#[cfg(anchors)] -use bitcoin::hashes::HashEngine; -#[cfg(anchors)] +use bitcoin::hashes::{Hash, HashEngine}; use bitcoin::hashes::sha256::Hash as Sha256; use bitcoin::hash_types::{Txid, BlockHash}; use bitcoin::secp256k1::{Secp256k1, ecdsa::Signature}; @@ -29,18 +25,12 @@ use bitcoin::secp256k1; use crate::sign::{ChannelSigner, EntropySource, SignerProvider}; use crate::ln::msgs::DecodeError; use crate::ln::PaymentPreimage; -#[cfg(anchors)] -use crate::ln::chan_utils::{self, HTLCOutputInCommitment}; -use crate::ln::chan_utils::{ChannelTransactionParameters, HolderCommitmentTransaction}; +use crate::ln::chan_utils::{self, ChannelTransactionParameters, HTLCOutputInCommitment, HolderCommitmentTransaction}; use crate::chain::ClaimId; -#[cfg(anchors)] -use crate::chain::chaininterface::ConfirmationTarget; -use crate::chain::chaininterface::{FeeEstimator, BroadcasterInterface, LowerBoundedFeeEstimator}; +use crate::chain::chaininterface::{ConfirmationTarget, FeeEstimator, BroadcasterInterface, LowerBoundedFeeEstimator}; use crate::chain::channelmonitor::{ANTI_REORG_DELAY, CLTV_SHARED_CLAIM_BUFFER}; use crate::sign::WriteableEcdsaChannelSigner; -#[cfg(anchors)] -use crate::chain::package::PackageSolvingData; -use crate::chain::package::PackageTemplate; +use crate::chain::package::{PackageSolvingData, PackageTemplate}; use crate::util::logger::Logger; use crate::util::ser::{Readable, ReadableArgs, MaybeReadable, UpgradableRequired, Writer, Writeable, VecWriter}; @@ -50,7 +40,6 @@ use alloc::collections::BTreeMap; use core::cmp; use core::ops::Deref; use core::mem::replace; -#[cfg(anchors)] use core::mem::swap; use crate::ln::features::ChannelTypeFeatures; @@ -181,7 +170,6 @@ impl Writeable for Option>> { } } -#[cfg(anchors)] /// The claim commonly referred to as the pre-signed second-stage HTLC transaction. pub(crate) struct ExternalHTLCClaim { pub(crate) commitment_txid: Txid, @@ -193,7 +181,6 @@ pub(crate) struct ExternalHTLCClaim { // Represents the different types of claims for which events are yielded externally to satisfy said // claims. -#[cfg(anchors)] pub(crate) enum ClaimEvent { /// Event yielded to signal that the commitment transaction fee must be bumped to claim any /// encumbered funds and proceed to HTLC resolution, if any HTLCs exist. @@ -216,7 +203,6 @@ pub(crate) enum ClaimEvent { pub(crate) enum OnchainClaim { /// A finalized transaction pending confirmation spending the output to claim. Tx(Transaction), - #[cfg(anchors)] /// An event yielded externally to signal additional inputs must be added to a transaction /// pending confirmation spending the output to claim. Event(ClaimEvent), @@ -263,7 +249,6 @@ pub struct OnchainTxHandler { // - A channel has been force closed by broadcasting the holder's latest commitment transaction // - A block being connected/disconnected // - Learning the preimage for an HTLC we can claim onchain - #[cfg(anchors)] pending_claim_events: Vec<(ClaimId, ClaimEvent)>, // Used to link outpoints claimed in a connected block to a pending claim request. The keys @@ -440,7 +425,6 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP locktimed_packages, pending_claim_requests, onchain_events_awaiting_threshold_conf, - #[cfg(anchors)] pending_claim_events: Vec::new(), secp_ctx, }) @@ -461,7 +445,6 @@ impl OnchainTxHandler claimable_outpoints: HashMap::new(), locktimed_packages: BTreeMap::new(), onchain_events_awaiting_threshold_conf: Vec::new(), - #[cfg(anchors)] pending_claim_events: Vec::new(), secp_ctx, } @@ -475,7 +458,6 @@ impl OnchainTxHandler self.holder_commitment.to_broadcaster_value_sat() } - #[cfg(anchors)] pub(crate) fn get_and_clear_pending_claim_events(&mut self) -> Vec<(ClaimId, ClaimEvent)> { let mut events = Vec::new(); swap(&mut events, &mut self.pending_claim_events); @@ -516,7 +498,6 @@ impl OnchainTxHandler log_info!(logger, "{} onchain {}", log_start, log_tx!(tx)); broadcaster.broadcast_transactions(&[&tx]); }, - #[cfg(anchors)] OnchainClaim::Event(event) => { let log_start = if bumped_feerate { "Yielding fee-bumped" } else { "Replaying" }; log_info!(logger, "{} onchain event to spend inputs {:?}", log_start, @@ -593,25 +574,22 @@ impl OnchainTxHandler // didn't receive confirmation of it before, or not enough reorg-safe depth on top of it). let new_timer = cached_request.get_height_timer(cur_height); if cached_request.is_malleable() { - #[cfg(anchors)] - { // Attributes are not allowed on if expressions on our current MSRV of 1.41. - if cached_request.requires_external_funding() { - let target_feerate_sat_per_1000_weight = cached_request.compute_package_feerate( - fee_estimator, ConfirmationTarget::HighPriority, force_feerate_bump - ); - if let Some(htlcs) = cached_request.construct_malleable_package_with_external_funding(self) { - return Some(( - new_timer, - target_feerate_sat_per_1000_weight as u64, - OnchainClaim::Event(ClaimEvent::BumpHTLC { - target_feerate_sat_per_1000_weight, - htlcs, - tx_lock_time: PackedLockTime(cached_request.package_locktime(cur_height)), - }), - )); - } else { - return None; - } + if cached_request.requires_external_funding() { + let target_feerate_sat_per_1000_weight = cached_request.compute_package_feerate( + fee_estimator, ConfirmationTarget::HighPriority, force_feerate_bump + ); + if let Some(htlcs) = cached_request.construct_malleable_package_with_external_funding(self) { + return Some(( + new_timer, + target_feerate_sat_per_1000_weight as u64, + OnchainClaim::Event(ClaimEvent::BumpHTLC { + target_feerate_sat_per_1000_weight, + htlcs, + tx_lock_time: PackedLockTime(cached_request.package_locktime(cur_height)), + }), + )); + } else { + return None; } } @@ -633,9 +611,6 @@ impl OnchainTxHandler // Untractable packages cannot have their fees bumped through Replace-By-Fee. Some // packages may support fee bumping through Child-Pays-For-Parent, indicated by those // which require external funding. - #[cfg(not(anchors))] - let inputs = cached_request.inputs(); - #[cfg(anchors)] let mut inputs = cached_request.inputs(); debug_assert_eq!(inputs.len(), 1); let tx = match cached_request.finalize_untractable_package(self, logger) { @@ -645,7 +620,6 @@ impl OnchainTxHandler if !cached_request.requires_external_funding() { return Some((new_timer, 0, OnchainClaim::Tx(tx))); } - #[cfg(anchors)] return inputs.find_map(|input| match input { // Commitment inputs with anchors support are the only untractable inputs supported // thus far that require external funding. @@ -771,7 +745,6 @@ impl OnchainTxHandler broadcaster.broadcast_transactions(&[&tx]); ClaimId(tx.txid().into_inner()) }, - #[cfg(anchors)] OnchainClaim::Event(claim_event) => { log_info!(logger, "Yielding onchain event to spend inputs {:?}", req.outpoints()); let claim_id = match claim_event { @@ -886,14 +859,12 @@ impl OnchainTxHandler // input(s) that already have a confirmed spend. If such spend is // reorged out of the chain, then we'll attempt to re-spend the // inputs once we see it. - #[cfg(anchors)] { - #[cfg(debug_assertions)] { - let existing = self.pending_claim_events.iter() - .filter(|entry| entry.0 == *claim_id).count(); - assert!(existing == 0 || existing == 1); - } - self.pending_claim_events.retain(|entry| entry.0 != *claim_id); + #[cfg(debug_assertions)] { + let existing = self.pending_claim_events.iter() + .filter(|entry| entry.0 == *claim_id).count(); + assert!(existing == 0 || existing == 1); } + self.pending_claim_events.retain(|entry| entry.0 != *claim_id); } } break; //No need to iterate further, either tx is our or their @@ -930,14 +901,12 @@ impl OnchainTxHandler outpoint, log_bytes!(claim_id.0)); self.claimable_outpoints.remove(outpoint); } - #[cfg(anchors)] { - #[cfg(debug_assertions)] { - let num_existing = self.pending_claim_events.iter() - .filter(|entry| entry.0 == claim_id).count(); - assert!(num_existing == 0 || num_existing == 1); - } - self.pending_claim_events.retain(|(id, _)| *id != claim_id); + #[cfg(debug_assertions)] { + let num_existing = self.pending_claim_events.iter() + .filter(|entry| entry.0 == claim_id).count(); + assert!(num_existing == 0 || num_existing == 1); } + self.pending_claim_events.retain(|(id, _)| *id != claim_id); } }, OnchainEvent::ContentiousOutpoint { package } => { @@ -969,7 +938,6 @@ impl OnchainTxHandler log_info!(logger, "Broadcasting RBF-bumped onchain {}", log_tx!(bump_tx)); broadcaster.broadcast_transactions(&[&bump_tx]); }, - #[cfg(anchors)] OnchainClaim::Event(claim_event) => { log_info!(logger, "Yielding RBF-bumped onchain event to spend inputs {:?}", request.outpoints()); #[cfg(debug_assertions)] { @@ -1055,7 +1023,6 @@ impl OnchainTxHandler log_info!(logger, "Broadcasting onchain {}", log_tx!(bump_tx)); broadcaster.broadcast_transactions(&[&bump_tx]); }, - #[cfg(anchors)] OnchainClaim::Event(claim_event) => { log_info!(logger, "Yielding onchain event after reorg to spend inputs {:?}", request.outpoints()); #[cfg(debug_assertions)] { @@ -1185,7 +1152,6 @@ impl OnchainTxHandler htlc_tx } - #[cfg(anchors)] pub(crate) fn generate_external_htlc_claim( &self, outp: &::bitcoin::OutPoint, preimage: &Option ) -> Option { diff --git a/lightning/src/chain/package.rs b/lightning/src/chain/package.rs index 891d7d1da33..4576fde0215 100644 --- a/lightning/src/chain/package.rs +++ b/lightning/src/chain/package.rs @@ -26,16 +26,13 @@ use crate::ln::chan_utils; use crate::ln::msgs::DecodeError; use crate::chain::chaininterface::{FeeEstimator, ConfirmationTarget, MIN_RELAY_FEE_SAT_PER_1000_WEIGHT}; use crate::sign::WriteableEcdsaChannelSigner; -#[cfg(anchors)] -use crate::chain::onchaintx::ExternalHTLCClaim; -use crate::chain::onchaintx::OnchainTxHandler; +use crate::chain::onchaintx::{ExternalHTLCClaim, OnchainTxHandler}; use crate::util::logger::Logger; use crate::util::ser::{Readable, Writer, Writeable, RequiredWrapper}; use crate::io; use crate::prelude::*; use core::cmp; -#[cfg(anchors)] use core::convert::TryInto; use core::mem; use core::ops::Deref; @@ -866,7 +863,6 @@ impl PackageTemplate { let output_weight = (8 + 1 + destination_script.len()) * WITNESS_SCALE_FACTOR; inputs_weight + witnesses_weight + transaction_weight + output_weight } - #[cfg(anchors)] pub(crate) fn construct_malleable_package_with_external_funding( &self, onchain_handler: &mut OnchainTxHandler, ) -> Option> { @@ -971,7 +967,6 @@ impl PackageTemplate { None } - #[cfg(anchors)] /// Computes a feerate based on the given confirmation target. If a previous feerate was used, /// the new feerate is below it, and `force_feerate_bump` is set, we'll use a 25% increase of /// the previous feerate instead of the new feerate. diff --git a/lightning/src/events/bump_transaction.rs b/lightning/src/events/bump_transaction.rs index ffc5456f832..6d8a5bb6c65 100644 --- a/lightning/src/events/bump_transaction.rs +++ b/lightning/src/events/bump_transaction.rs @@ -14,16 +14,17 @@ use core::ops::Deref; use crate::chain::chaininterface::BroadcasterInterface; use crate::chain::ClaimId; -use crate::sign::{ChannelSigner, EcdsaChannelSigner, SignerProvider}; +use crate::events::Event; use crate::io_extras::sink; -use crate::ln::PaymentPreimage; use crate::ln::chan_utils; use crate::ln::chan_utils::{ ANCHOR_INPUT_WITNESS_WEIGHT, HTLC_SUCCESS_INPUT_ANCHOR_WITNESS_WEIGHT, HTLC_TIMEOUT_INPUT_ANCHOR_WITNESS_WEIGHT, ChannelTransactionParameters, HTLCOutputInCommitment }; -use crate::events::Event; -use crate::prelude::HashMap; +use crate::ln::features::ChannelTypeFeatures; +use crate::ln::PaymentPreimage; +use crate::prelude::*; +use crate::sign::{ChannelSigner, EcdsaChannelSigner, SignerProvider}; use crate::sync::Mutex; use crate::util::logger::Logger; @@ -33,7 +34,6 @@ use bitcoin::consensus::Encodable; use bitcoin::secp256k1; use bitcoin::secp256k1::{PublicKey, Secp256k1}; use bitcoin::secp256k1::ecdsa::Signature; -use crate::ln::features::ChannelTypeFeatures; const EMPTY_SCRIPT_SIG_WEIGHT: u64 = 1 /* empty script_sig */ * WITNESS_SCALE_FACTOR as u64; diff --git a/lightning/src/events/mod.rs b/lightning/src/events/mod.rs index f4c4af7e90f..b9fb955a5a2 100644 --- a/lightning/src/events/mod.rs +++ b/lightning/src/events/mod.rs @@ -14,10 +14,8 @@ //! future, as well as generate and broadcast funding transactions handle payment preimages and a //! few other things. -#[cfg(anchors)] pub mod bump_transaction; -#[cfg(anchors)] pub use bump_transaction::BumpTransactionEvent; use crate::sign::SpendableOutputDescriptor; @@ -832,7 +830,6 @@ pub enum Event { /// Destination of the HTLC that failed to be processed. failed_next_destination: HTLCDestination, }, - #[cfg(anchors)] /// Indicates that a transaction originating from LDK needs to have its fee bumped. This event /// requires confirmed external funds to be readily available to spend. /// @@ -1029,7 +1026,6 @@ impl Writeable for Event { (2, failed_next_destination, required), }) }, - #[cfg(anchors)] &Event::BumpTransaction(ref event)=> { 27u8.write(writer)?; match event { diff --git a/lightning/src/ln/chan_utils.rs b/lightning/src/ln/chan_utils.rs index 7fa2308d001..0f5a453461a 100644 --- a/lightning/src/ln/chan_utils.rs +++ b/lightning/src/ln/chan_utils.rs @@ -829,7 +829,6 @@ pub fn get_anchor_redeemscript(funding_pubkey: &PublicKey) -> Script { .into_script() } -#[cfg(anchors)] /// Locates the output with an anchor script paying to `funding_pubkey` within `commitment_tx`. pub(crate) fn get_anchor_output<'a>(commitment_tx: &'a Transaction, funding_pubkey: &PublicKey) -> Option<(u32, &'a TxOut)> { let anchor_script = chan_utils::get_anchor_redeemscript(funding_pubkey).to_v0_p2wsh(); diff --git a/lightning/src/ln/channel.rs b/lightning/src/ln/channel.rs index 664448f56f6..ba9fd5eb03f 100644 --- a/lightning/src/ln/channel.rs +++ b/lightning/src/ln/channel.rs @@ -5727,12 +5727,9 @@ impl OutboundV1Channel { // Optionally, if the user would like to negotiate the `anchors_zero_fee_htlc_tx` option, we // set it now. If they don't understand it, we'll fall back to our default of // `only_static_remotekey`. - #[cfg(anchors)] - { // Attributes are not allowed on if expressions on our current MSRV of 1.41. - if config.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx && - their_features.supports_anchors_zero_fee_htlc_tx() { - ret.set_anchors_zero_fee_htlc_tx_required(); - } + if config.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx && + their_features.supports_anchors_zero_fee_htlc_tx() { + ret.set_anchors_zero_fee_htlc_tx_required(); } ret @@ -7379,7 +7376,6 @@ mod tests { use hex; use crate::ln::PaymentHash; use crate::ln::channelmanager::{self, HTLCSource, PaymentId}; - #[cfg(anchors)] use crate::ln::channel::InitFeatures; use crate::ln::channel::{Channel, InboundHTLCOutput, OutboundV1Channel, InboundV1Channel, OutboundHTLCOutput, InboundHTLCState, OutboundHTLCState, HTLCCandidate, HTLCInitiator, commit_tx_fee_msat}; use crate::ln::channel::{MAX_FUNDING_SATOSHIS_NO_WUMBO, TOTAL_BITCOIN_SUPPLY_SATOSHIS, MIN_THEIR_CHAN_RESERVE_SATOSHIS}; @@ -8703,7 +8699,6 @@ mod tests { assert!(res.is_ok()); } - #[cfg(anchors)] #[test] fn test_supports_anchors_zero_htlc_tx_fee() { // Tests that if both sides support and negotiate `anchors_zero_fee_htlc_tx`, it is the @@ -8749,7 +8744,6 @@ mod tests { assert_eq!(channel_b.context.channel_type, expected_channel_type); } - #[cfg(anchors)] #[test] fn test_rejects_implicit_simple_anchors() { // Tests that if `option_anchors` is being negotiated implicitly through the intersection of @@ -8790,7 +8784,6 @@ mod tests { assert!(channel_b.is_err()); } - #[cfg(anchors)] #[test] fn test_rejects_simple_anchors_channel_type() { // Tests that if `option_anchors` is being negotiated through the `channel_type` feature, diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs index eb682c34e01..a8e19e738e3 100644 --- a/lightning/src/ln/channelmanager.rs +++ b/lightning/src/ln/channelmanager.rs @@ -5103,9 +5103,13 @@ where return Err(MsgHandleErrInternal::send_err_msg_no_close("temporary_channel_id collision for the same peer!".to_owned(), msg.temporary_channel_id.clone())) } else { if !self.default_configuration.manually_accept_inbound_channels { - if channel.context.get_channel_type().requires_zero_conf() { + let channel_type = channel.context.get_channel_type(); + if channel_type.requires_zero_conf() { return Err(MsgHandleErrInternal::send_err_msg_no_close("No zero confirmation channels accepted".to_owned(), msg.temporary_channel_id.clone())); } + if channel_type.requires_anchors_zero_fee_htlc_tx() { + return Err(MsgHandleErrInternal::send_err_msg_no_close("No channels with anchor outputs accepted".to_owned(), msg.temporary_channel_id.clone())); + } peer_state.pending_msg_events.push(events::MessageSendEvent::SendAcceptChannel { node_id: counterparty_node_id.clone(), msg: channel.accept_inbound_channel(user_channel_id), @@ -7232,7 +7236,7 @@ pub(crate) fn provided_channel_type_features(config: &UserConfig) -> ChannelType /// Fetches the set of [`InitFeatures`] flags which are provided by or required by /// [`ChannelManager`]. -pub fn provided_init_features(_config: &UserConfig) -> InitFeatures { +pub fn provided_init_features(config: &UserConfig) -> InitFeatures { // Note that if new features are added here which other peers may (eventually) require, we // should also add the corresponding (optional) bit to the [`ChannelMessageHandler`] impl for // [`ErroringMessageHandler`]. @@ -7248,11 +7252,8 @@ pub fn provided_init_features(_config: &UserConfig) -> InitFeatures { features.set_channel_type_optional(); features.set_scid_privacy_optional(); features.set_zero_conf_optional(); - #[cfg(anchors)] - { // Attributes are not allowed on if expressions on our current MSRV of 1.41. - if _config.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx { - features.set_anchors_zero_fee_htlc_tx_optional(); - } + if config.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx { + features.set_anchors_zero_fee_htlc_tx_optional(); } features } @@ -8735,7 +8736,7 @@ mod tests { use crate::ln::{PaymentPreimage, PaymentHash, PaymentSecret}; use crate::ln::channelmanager::{inbound_payment, PaymentId, PaymentSendFailure, RecipientOnionFields, InterceptId}; use crate::ln::functional_test_utils::*; - use crate::ln::msgs; + use crate::ln::msgs::{self, ErrorAction}; use crate::ln::msgs::ChannelMessageHandler; use crate::routing::router::{PaymentParameters, RouteParameters, find_route}; use crate::util::errors::APIError; @@ -9731,7 +9732,50 @@ mod tests { sender_intended_amt_msat - extra_fee_msat, 42, None, true, Some(extra_fee_msat)).is_ok()); } - #[cfg(anchors)] + #[test] + fn test_inbound_anchors_manual_acceptance() { + // Tests that we properly limit inbound channels when we have the manual-channel-acceptance + // flag set and (sometimes) accept channels as 0conf. + let mut anchors_cfg = test_default_channel_config(); + anchors_cfg.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx = true; + + let mut anchors_manual_accept_cfg = anchors_cfg.clone(); + anchors_manual_accept_cfg.manually_accept_inbound_channels = true; + + let chanmon_cfgs = create_chanmon_cfgs(3); + let node_cfgs = create_node_cfgs(3, &chanmon_cfgs); + let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, + &[Some(anchors_cfg.clone()), Some(anchors_cfg.clone()), Some(anchors_manual_accept_cfg.clone())]); + let nodes = create_network(3, &node_cfgs, &node_chanmgrs); + + nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100_000, 0, 42, None).unwrap(); + let open_channel_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id()); + + nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), &open_channel_msg); + assert!(nodes[1].node.get_and_clear_pending_events().is_empty()); + let msg_events = nodes[1].node.get_and_clear_pending_msg_events(); + match &msg_events[0] { + MessageSendEvent::HandleError { node_id, action } => { + assert_eq!(*node_id, nodes[0].node.get_our_node_id()); + match action { + ErrorAction::SendErrorMessage { msg } => + assert_eq!(msg.data, "No channels with anchor outputs accepted".to_owned()), + _ => panic!("Unexpected error action"), + } + } + _ => panic!("Unexpected event"), + } + + nodes[2].node.handle_open_channel(&nodes[0].node.get_our_node_id(), &open_channel_msg); + let events = nodes[2].node.get_and_clear_pending_events(); + match events[0] { + Event::OpenChannelRequest { temporary_channel_id, .. } => + nodes[2].node.accept_inbound_channel(&temporary_channel_id, &nodes[0].node.get_our_node_id(), 23).unwrap(), + _ => panic!("Unexpected event"), + } + get_event_msg!(nodes[2], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id()); + } + #[test] fn test_anchors_zero_fee_htlc_tx_fallback() { // Tests that if both nodes support anchors, but the remote node does not want to accept diff --git a/lightning/src/ln/functional_test_utils.rs b/lightning/src/ln/functional_test_utils.rs index 27002679ed7..a1ac66a800a 100644 --- a/lightning/src/ln/functional_test_utils.rs +++ b/lightning/src/ln/functional_test_utils.rs @@ -1100,6 +1100,15 @@ pub fn create_chan_between_nodes_with_value_init<'a, 'b, 'c>(node_a: &Node<'a, ' assert_eq!(open_channel_msg.temporary_channel_id, create_chan_id); assert_eq!(node_a.node.list_channels().iter().find(|channel| channel.channel_id == create_chan_id).unwrap().user_channel_id, 42); node_b.node.handle_open_channel(&node_a.node.get_our_node_id(), &open_channel_msg); + if node_b.node.get_current_default_configuration().manually_accept_inbound_channels { + let events = node_b.node.get_and_clear_pending_events(); + assert_eq!(events.len(), 1); + match &events[0] { + Event::OpenChannelRequest { temporary_channel_id, counterparty_node_id, .. } => + node_b.node.accept_inbound_channel(temporary_channel_id, counterparty_node_id, 42).unwrap(), + _ => panic!("Unexpected event"), + }; + } let accept_channel_msg = get_event_msg!(node_b, MessageSendEvent::SendAcceptChannel, node_a.node.get_our_node_id()); assert_eq!(accept_channel_msg.temporary_channel_id, create_chan_id); node_a.node.handle_accept_channel(&node_b.node.get_our_node_id(), &accept_channel_msg); diff --git a/lightning/src/ln/monitor_tests.rs b/lightning/src/ln/monitor_tests.rs index 3e1aa7e9c5b..2a3f5849b95 100644 --- a/lightning/src/ln/monitor_tests.rs +++ b/lightning/src/ln/monitor_tests.rs @@ -9,41 +9,26 @@ //! Further functional tests which test blockchain reorganizations. -#[cfg(anchors)] use crate::sign::{ChannelSigner, EcdsaChannelSigner}; -#[cfg(anchors)] -use crate::chain::channelmonitor::LATENCY_GRACE_PERIOD_BLOCKS; -use crate::chain::channelmonitor::{ANTI_REORG_DELAY, Balance}; +use crate::chain::channelmonitor::{ANTI_REORG_DELAY, LATENCY_GRACE_PERIOD_BLOCKS, Balance}; use crate::chain::transaction::OutPoint; use crate::chain::chaininterface::LowerBoundedFeeEstimator; -#[cfg(anchors)] use crate::events::bump_transaction::BumpTransactionEvent; use crate::events::{Event, MessageSendEvent, MessageSendEventsProvider, ClosureReason, HTLCDestination}; use crate::ln::channel; -#[cfg(anchors)] use crate::ln::chan_utils; -#[cfg(anchors)] -use crate::ln::channelmanager::ChannelManager; -use crate::ln::channelmanager::{BREAKDOWN_TIMEOUT, PaymentId, RecipientOnionFields}; +use crate::ln::channelmanager::{BREAKDOWN_TIMEOUT, ChannelManager, PaymentId, RecipientOnionFields}; use crate::ln::msgs::ChannelMessageHandler; -#[cfg(anchors)] use crate::util::config::UserConfig; -#[cfg(anchors)] use crate::util::crypto::sign; use crate::util::ser::Writeable; use crate::util::test_utils; -#[cfg(anchors)] use bitcoin::blockdata::transaction::EcdsaSighashType; use bitcoin::blockdata::script::Builder; use bitcoin::blockdata::opcodes; -use bitcoin::secp256k1::Secp256k1; -#[cfg(anchors)] -use bitcoin::secp256k1::SecretKey; -#[cfg(anchors)] -use bitcoin::{Amount, PublicKey, Script, TxIn, TxOut, PackedLockTime, Witness}; -use bitcoin::Transaction; -#[cfg(anchors)] +use bitcoin::secp256k1::{Secp256k1, SecretKey}; +use bitcoin::{Amount, PublicKey, Script, Transaction, TxIn, TxOut, PackedLockTime, Witness}; use bitcoin::util::sighash::SighashCache; use crate::prelude::*; @@ -1731,16 +1716,12 @@ fn test_restored_packages_retry() { fn do_test_monitor_rebroadcast_pending_claims(anchors: bool) { // Test that we will retry broadcasting pending claims for a force-closed channel on every // `ChainMonitor::rebroadcast_pending_claims` call. - if anchors { - assert!(cfg!(anchors)); - } let mut chanmon_cfgs = create_chanmon_cfgs(2); let node_cfgs = create_node_cfgs(2, &chanmon_cfgs); let mut config = test_default_channel_config(); if anchors { - #[cfg(anchors)] { - config.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx = true; - } + config.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx = true; + config.manually_accept_inbound_channels = true; } let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[Some(config), Some(config)]); let nodes = create_network(2, &node_cfgs, &node_chanmgrs); @@ -1783,34 +1764,32 @@ fn do_test_monitor_rebroadcast_pending_claims(anchors: bool) { }; #[allow(unused_assignments)] let mut feerate = 0; - #[cfg(anchors)] { - feerate = if let Event::BumpTransaction(BumpTransactionEvent::HTLCResolution { - target_feerate_sat_per_1000_weight, mut htlc_descriptors, tx_lock_time, .. - }) = events.pop().unwrap() { - let secp = Secp256k1::new(); - assert_eq!(htlc_descriptors.len(), 1); - let descriptor = htlc_descriptors.pop().unwrap(); - assert_eq!(descriptor.commitment_txid, commitment_txn[0].txid()); - let htlc_output_idx = descriptor.htlc.transaction_output_index.unwrap() as usize; - assert!(htlc_output_idx < commitment_txn[0].output.len()); - tx.lock_time = tx_lock_time; - // Note that we don't care about actually making the HTLC transaction meet the - // feerate for the test, we just want to make sure the feerates we receive from - // the events never decrease. - tx.input.push(descriptor.unsigned_tx_input()); - let signer = nodes[0].keys_manager.derive_channel_keys( - descriptor.channel_value_satoshis, &descriptor.channel_keys_id, - ); - let per_commitment_point = signer.get_per_commitment_point( - descriptor.per_commitment_number, &secp - ); - tx.output.push(descriptor.tx_output(&per_commitment_point, &secp)); - let our_sig = signer.sign_holder_htlc_transaction(&mut tx, 0, &descriptor, &secp).unwrap(); - let witness_script = descriptor.witness_script(&per_commitment_point, &secp); - tx.input[0].witness = descriptor.tx_input_witness(&our_sig, &witness_script); - target_feerate_sat_per_1000_weight as u64 - } else { panic!("unexpected event"); }; - } + feerate = if let Event::BumpTransaction(BumpTransactionEvent::HTLCResolution { + target_feerate_sat_per_1000_weight, mut htlc_descriptors, tx_lock_time, .. + }) = events.pop().unwrap() { + let secp = Secp256k1::new(); + assert_eq!(htlc_descriptors.len(), 1); + let descriptor = htlc_descriptors.pop().unwrap(); + assert_eq!(descriptor.commitment_txid, commitment_txn[0].txid()); + let htlc_output_idx = descriptor.htlc.transaction_output_index.unwrap() as usize; + assert!(htlc_output_idx < commitment_txn[0].output.len()); + tx.lock_time = tx_lock_time; + // Note that we don't care about actually making the HTLC transaction meet the + // feerate for the test, we just want to make sure the feerates we receive from + // the events never decrease. + tx.input.push(descriptor.unsigned_tx_input()); + let signer = nodes[0].keys_manager.derive_channel_keys( + descriptor.channel_value_satoshis, &descriptor.channel_keys_id, + ); + let per_commitment_point = signer.get_per_commitment_point( + descriptor.per_commitment_number, &secp + ); + tx.output.push(descriptor.tx_output(&per_commitment_point, &secp)); + let our_sig = signer.sign_holder_htlc_transaction(&mut tx, 0, &descriptor, &secp).unwrap(); + let witness_script = descriptor.witness_script(&per_commitment_point, &secp); + tx.input[0].witness = descriptor.tx_input_witness(&our_sig, &witness_script); + target_feerate_sat_per_1000_weight as u64 + } else { panic!("unexpected event"); }; (tx, feerate) } else { assert!(nodes[0].chain_monitor.chain_monitor.get_and_clear_pending_events().is_empty()); @@ -1875,11 +1854,9 @@ fn do_test_monitor_rebroadcast_pending_claims(anchors: bool) { #[test] fn test_monitor_timer_based_claim() { do_test_monitor_rebroadcast_pending_claims(false); - #[cfg(anchors)] do_test_monitor_rebroadcast_pending_claims(true); } -#[cfg(anchors)] #[test] fn test_yield_anchors_events() { // Tests that two parties supporting anchor outputs can open a channel, route payments over @@ -1894,6 +1871,7 @@ fn test_yield_anchors_events() { let mut anchors_config = UserConfig::default(); anchors_config.channel_handshake_config.announced_channel = true; anchors_config.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx = true; + anchors_config.manually_accept_inbound_channels = true; let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[Some(anchors_config), Some(anchors_config)]); let nodes = create_network(2, &node_cfgs, &node_chanmgrs); @@ -2013,7 +1991,6 @@ fn test_yield_anchors_events() { nodes[0].node.get_and_clear_pending_events(); } -#[cfg(anchors)] #[test] fn test_anchors_aggregated_revoked_htlc_tx() { // Test that `ChannelMonitor`s can properly detect and claim funds from a counterparty claiming @@ -2027,6 +2004,7 @@ fn test_anchors_aggregated_revoked_htlc_tx() { let mut anchors_config = UserConfig::default(); anchors_config.channel_handshake_config.announced_channel = true; anchors_config.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx = true; + anchors_config.manually_accept_inbound_channels = true; let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[Some(anchors_config), Some(anchors_config)]); let bob_persister: test_utils::TestPersister; diff --git a/lightning/src/sign/mod.rs b/lightning/src/sign/mod.rs index 8e77c67a958..66217de28ac 100644 --- a/lightning/src/sign/mod.rs +++ b/lightning/src/sign/mod.rs @@ -36,7 +36,6 @@ use crate::util::transaction_utils; use crate::util::crypto::{hkdf_extract_expand_twice, sign, sign_with_aux_rand}; use crate::util::ser::{Writeable, Writer, Readable, ReadableArgs}; use crate::chain::transaction::OutPoint; -#[cfg(anchors)] use crate::events::bump_transaction::HTLCDescriptor; use crate::ln::channel::ANCHOR_OUTPUT_VALUE_SATOSHI; use crate::ln::{chan_utils, PaymentPreimage}; @@ -489,7 +488,6 @@ pub trait EcdsaChannelSigner: ChannelSigner { fn sign_justice_revoked_htlc(&self, justice_tx: &Transaction, input: usize, amount: u64, per_commitment_key: &SecretKey, htlc: &HTLCOutputInCommitment, secp_ctx: &Secp256k1) -> Result; - #[cfg(anchors)] /// Computes the signature for a commitment transaction's HTLC output used as an input within /// `htlc_tx`, which spends the commitment transaction at index `input`. The signature returned /// must be be computed using [`EcdsaSighashType::All`]. Note that this should only be used to @@ -1028,7 +1026,6 @@ impl EcdsaChannelSigner for InMemorySigner { return Ok(sign_with_aux_rand(secp_ctx, &sighash, &revocation_key, &self)) } - #[cfg(anchors)] fn sign_holder_htlc_transaction( &self, htlc_tx: &Transaction, input: usize, htlc_descriptor: &HTLCDescriptor, secp_ctx: &Secp256k1 diff --git a/lightning/src/util/config.rs b/lightning/src/util/config.rs index 1faf595ac8f..5c8d5b6c554 100644 --- a/lightning/src/util/config.rs +++ b/lightning/src/util/config.rs @@ -149,11 +149,18 @@ pub struct ChannelHandshakeConfig { /// Maximum value: 1,000,000, any values larger than 1 Million will be treated as 1 Million (or 100%) /// instead, although channel negotiations will fail in that case. pub their_channel_reserve_proportional_millionths: u32, - #[cfg(anchors)] - /// If set, we attempt to negotiate the `anchors_zero_fee_htlc_tx`option for outbound channels. + /// If set, we attempt to negotiate the `anchors_zero_fee_htlc_tx`option for all future + /// channels. This feature requires having a reserve of onchain funds readily available to bump + /// transactions in the event of a channel force close to avoid the possibility of losing funds. + /// + /// Note that if you wish accept inbound channels with anchor outputs, you must enable + /// [`UserConfig::manually_accept_inbound_channels`] and manually accept them with + /// [`ChannelManager::accept_inbound_channel`]. This is done to give you the chance to check + /// whether your reserve of onchain funds is enough to cover the fees for all existing and new + /// channels featuring anchor outputs in the event of a force close. /// /// If this option is set, channels may be created that will not be readable by LDK versions - /// prior to 0.0.114, causing [`ChannelManager`]'s read method to return a + /// prior to 0.0.116, causing [`ChannelManager`]'s read method to return a /// [`DecodeError::InvalidValue`]. /// /// Note that setting this to true does *not* prevent us from opening channels with @@ -167,6 +174,7 @@ pub struct ChannelHandshakeConfig { /// Default value: false. This value is likely to change to true in the future. /// /// [`ChannelManager`]: crate::ln::channelmanager::ChannelManager + /// [`ChannelManager::accept_inbound_channel`]: crate::ln::channelmanager::ChannelManager::accept_inbound_channel /// [`DecodeError::InvalidValue`]: crate::ln::msgs::DecodeError::InvalidValue /// [`SIGHASH_SINGLE + update_fee Considered Harmful`]: https://lists.linuxfoundation.org/pipermail/lightning-dev/2020-September/002796.html pub negotiate_anchors_zero_fee_htlc_tx: bool, @@ -196,7 +204,6 @@ impl Default for ChannelHandshakeConfig { announced_channel: false, commit_upfront_shutdown_pubkey: true, their_channel_reserve_proportional_millionths: 10_000, - #[cfg(anchors)] negotiate_anchors_zero_fee_htlc_tx: false, our_max_accepted_htlcs: 50, } diff --git a/lightning/src/util/enforcing_trait_impls.rs b/lightning/src/util/enforcing_trait_impls.rs index acdd851ee7b..a9a6e8e0933 100644 --- a/lightning/src/util/enforcing_trait_impls.rs +++ b/lightning/src/util/enforcing_trait_impls.rs @@ -23,7 +23,6 @@ use bitcoin::util::sighash; use bitcoin::secp256k1; use bitcoin::secp256k1::{SecretKey, PublicKey}; use bitcoin::secp256k1::{Secp256k1, ecdsa::Signature}; -#[cfg(anchors)] use crate::events::bump_transaction::HTLCDescriptor; use crate::util::ser::{Writeable, Writer}; use crate::io::Error; @@ -206,7 +205,6 @@ impl EcdsaChannelSigner for EnforcingSigner { Ok(self.inner.sign_justice_revoked_htlc(justice_tx, input, amount, per_commitment_key, htlc, secp_ctx).unwrap()) } - #[cfg(anchors)] fn sign_holder_htlc_transaction( &self, htlc_tx: &Transaction, input: usize, htlc_descriptor: &HTLCDescriptor, secp_ctx: &Secp256k1