Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Require inbound channels with anchor outputs to be accepted manually #2368

Merged
Merged
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
5 changes: 2 additions & 3 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -194,16 +194,15 @@ 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
cargo check --no-default-features --features=no-std --release
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
Expand Down
6 changes: 2 additions & 4 deletions ci/ci-tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
21 changes: 2 additions & 19 deletions lightning/src/chain/chainmonitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -782,30 +782,13 @@ impl<ChannelSigner: WriteableEcdsaChannelSigner, C: Deref, T: Deref, F: Deref, L
L::Target: Logger,
P::Target: Persist<ChannelSigner>,
{
#[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<H: Deref>(&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.
Expand Down
7 changes: 1 addition & 6 deletions lightning/src/chain/channelmonitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::*;
Expand Down Expand Up @@ -268,7 +265,6 @@ impl_writeable_tlv_based!(HolderSignedTx, {
(14, htlc_outputs, vec_type)
});

#[cfg(anchors)]
impl HolderSignedTx {
fn non_dust_htlcs(&self) -> Vec<HTLCOutputInCommitment> {
self.htlc_outputs.iter().filter_map(|(htlc, _, _)| {
Expand Down Expand Up @@ -2538,7 +2534,6 @@ impl<Signer: WriteableEcdsaChannelSigner> ChannelMonitorImpl<Signer> {
pub fn get_and_clear_pending_events(&mut self) -> Vec<Event> {
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 {
Expand Down
94 changes: 30 additions & 64 deletions lightning/src/chain/onchaintx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand All @@ -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};

Expand All @@ -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;

Expand Down Expand Up @@ -181,7 +170,6 @@ impl Writeable for Option<Vec<Option<(usize, Signature)>>> {
}
}

#[cfg(anchors)]
/// The claim commonly referred to as the pre-signed second-stage HTLC transaction.
pub(crate) struct ExternalHTLCClaim {
pub(crate) commitment_txid: Txid,
Expand All @@ -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.
Expand All @@ -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),
Expand Down Expand Up @@ -263,7 +249,6 @@ pub struct OnchainTxHandler<ChannelSigner: WriteableEcdsaChannelSigner> {
// - 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
Expand Down Expand Up @@ -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,
})
Expand All @@ -461,7 +445,6 @@ impl<ChannelSigner: WriteableEcdsaChannelSigner> OnchainTxHandler<ChannelSigner>
claimable_outpoints: HashMap::new(),
locktimed_packages: BTreeMap::new(),
onchain_events_awaiting_threshold_conf: Vec::new(),
#[cfg(anchors)]
pending_claim_events: Vec::new(),
secp_ctx,
}
Expand All @@ -475,7 +458,6 @@ impl<ChannelSigner: WriteableEcdsaChannelSigner> OnchainTxHandler<ChannelSigner>
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);
Expand Down Expand Up @@ -516,7 +498,6 @@ impl<ChannelSigner: WriteableEcdsaChannelSigner> OnchainTxHandler<ChannelSigner>
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,
Expand Down Expand Up @@ -593,25 +574,22 @@ impl<ChannelSigner: WriteableEcdsaChannelSigner> OnchainTxHandler<ChannelSigner>
// 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;
}
}

Expand All @@ -633,9 +611,6 @@ impl<ChannelSigner: WriteableEcdsaChannelSigner> OnchainTxHandler<ChannelSigner>
// 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) {
Expand All @@ -645,7 +620,6 @@ impl<ChannelSigner: WriteableEcdsaChannelSigner> OnchainTxHandler<ChannelSigner>
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.
Expand Down Expand Up @@ -771,7 +745,6 @@ impl<ChannelSigner: WriteableEcdsaChannelSigner> OnchainTxHandler<ChannelSigner>
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 {
Expand Down Expand Up @@ -886,14 +859,12 @@ impl<ChannelSigner: WriteableEcdsaChannelSigner> OnchainTxHandler<ChannelSigner>
// 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
Expand Down Expand Up @@ -930,14 +901,12 @@ impl<ChannelSigner: WriteableEcdsaChannelSigner> OnchainTxHandler<ChannelSigner>
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 } => {
Expand Down Expand Up @@ -969,7 +938,6 @@ impl<ChannelSigner: WriteableEcdsaChannelSigner> OnchainTxHandler<ChannelSigner>
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)] {
Expand Down Expand Up @@ -1055,7 +1023,6 @@ impl<ChannelSigner: WriteableEcdsaChannelSigner> OnchainTxHandler<ChannelSigner>
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)] {
Expand Down Expand Up @@ -1185,7 +1152,6 @@ impl<ChannelSigner: WriteableEcdsaChannelSigner> OnchainTxHandler<ChannelSigner>
htlc_tx
}

#[cfg(anchors)]
pub(crate) fn generate_external_htlc_claim(
&self, outp: &::bitcoin::OutPoint, preimage: &Option<PaymentPreimage>
) -> Option<ExternalHTLCClaim> {
Expand Down
7 changes: 1 addition & 6 deletions lightning/src/chain/package.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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<Signer: WriteableEcdsaChannelSigner>(
&self, onchain_handler: &mut OnchainTxHandler<Signer>,
) -> Option<Vec<ExternalHTLCClaim>> {
Expand Down Expand Up @@ -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.
Expand Down
Loading
Loading