Skip to content
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
2 changes: 2 additions & 0 deletions lightning/src/chain/channelmonitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5831,6 +5831,8 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
assert_eq!(&bitcoin::Address::p2wsh(&ScriptBuf::from(input.witness.last().unwrap().to_vec()), bitcoin::Network::Bitcoin).script_pubkey(), _script_pubkey);
} else if _script_pubkey.is_p2wpkh() {
assert_eq!(&bitcoin::Address::p2wpkh(&bitcoin::CompressedPublicKey(bitcoin::PublicKey::from_slice(&input.witness.last().unwrap()).unwrap().inner), bitcoin::Network::Bitcoin).script_pubkey(), _script_pubkey);
} else if _script_pubkey == &chan_utils::shared_anchor_script_pubkey() {
assert!(input.witness.is_empty());
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might also make sense to do this in check_spends.

} else { panic!(); }
}
return true;
Expand Down
2 changes: 0 additions & 2 deletions lightning/src/chain/package.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,6 @@ pub(crate) fn verify_channel_type_features(channel_type_features: &Option<Channe
let mut supported_feature_set = ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies();
supported_feature_set.set_scid_privacy_required();
supported_feature_set.set_zero_conf_required();

#[cfg(test)]
supported_feature_set.set_anchor_zero_fee_commitments_required();

// allow the passing of an additional necessary permitted flag
Expand Down
31 changes: 27 additions & 4 deletions lightning/src/events/bump_transaction/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ use crate::io_extras::sink;
use crate::ln::chan_utils;
use crate::ln::chan_utils::{
shared_anchor_script_pubkey, HTLCOutputInCommitment, ANCHOR_INPUT_WITNESS_WEIGHT,
HTLC_SUCCESS_INPUT_ANCHOR_WITNESS_WEIGHT, HTLC_TIMEOUT_INPUT_ANCHOR_WITNESS_WEIGHT,
HTLC_SUCCESS_INPUT_KEYED_ANCHOR_WITNESS_WEIGHT, HTLC_SUCCESS_INPUT_P2A_ANCHOR_WITNESS_WEIGHT,
HTLC_TIMEOUT_INPUT_KEYED_ANCHOR_WITNESS_WEIGHT, HTLC_TIMEOUT_INPUT_P2A_ANCHOR_WITNESS_WEIGHT,
P2A_ANCHOR_INPUT_WITNESS_WEIGHT,
};
use crate::ln::types::ChannelId;
Expand Down Expand Up @@ -849,23 +850,45 @@ where
&self, claim_id: ClaimId, target_feerate_sat_per_1000_weight: u32,
htlc_descriptors: &[HTLCDescriptor], tx_lock_time: LockTime,
) -> Result<(), ()> {
let channel_type = &htlc_descriptors[0]
.channel_derivation_parameters
.transaction_parameters
.channel_type_features;
let mut htlc_tx = Transaction {
version: Version::TWO,
version: if channel_type.supports_anchor_zero_fee_commitments() {
Version::non_standard(3)
} else {
Version::TWO
},
lock_time: tx_lock_time,
input: vec![],
output: vec![],
};
let mut must_spend = Vec::with_capacity(htlc_descriptors.len());
let (htlc_success_witness_weight, htlc_timeout_witness_weight) =
if channel_type.supports_anchor_zero_fee_commitments() {
(
HTLC_SUCCESS_INPUT_P2A_ANCHOR_WITNESS_WEIGHT,
HTLC_TIMEOUT_INPUT_P2A_ANCHOR_WITNESS_WEIGHT,
)
} else if channel_type.supports_anchors_zero_fee_htlc_tx() {
(
HTLC_SUCCESS_INPUT_KEYED_ANCHOR_WITNESS_WEIGHT,
HTLC_TIMEOUT_INPUT_KEYED_ANCHOR_WITNESS_WEIGHT,
)
} else {
panic!("channel type should be either zero-fee HTLCs, or zero-fee commitments");
};
for htlc_descriptor in htlc_descriptors {
let htlc_input = htlc_descriptor.unsigned_tx_input();
must_spend.push(Input {
outpoint: htlc_input.previous_output.clone(),
previous_utxo: htlc_descriptor.previous_utxo(&self.secp),
satisfaction_weight: EMPTY_SCRIPT_SIG_WEIGHT
+ if htlc_descriptor.preimage.is_some() {
HTLC_SUCCESS_INPUT_ANCHOR_WITNESS_WEIGHT
htlc_success_witness_weight
} else {
HTLC_TIMEOUT_INPUT_ANCHOR_WITNESS_WEIGHT
htlc_timeout_witness_weight
},
});
htlc_tx.input.push(htlc_input);
Expand Down
67 changes: 31 additions & 36 deletions lightning/src/ln/async_signer_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,10 @@
//! properly with a signer implementation that asynchronously derives signatures.

use crate::prelude::*;
use bitcoin::locktime::absolute::LockTime;
use bitcoin::secp256k1::Secp256k1;
use bitcoin::transaction::Version;
use bitcoin::{Amount, Transaction, TxIn, TxOut};

use crate::chain::channelmonitor::LATENCY_GRACE_PERIOD_BLOCKS;
use crate::chain::ChannelMonitorUpdateStatus;
use crate::events::bump_transaction::sync::WalletSourceSync;
use crate::events::{ClosureReason, Event};
use crate::ln::chan_utils::ClosingTransaction;
use crate::ln::channel::DISCONNECT_PEER_AWAITING_RESPONSE_TICKS;
Expand Down Expand Up @@ -972,15 +968,14 @@ fn do_test_async_commitment_signature_ordering(monitor_update_failure: bool) {
claim_payment(&nodes[0], &[&nodes[1]], payment_preimage_2);
}

fn do_test_async_holder_signatures(anchors: bool, remote_commitment: bool) {
fn do_test_async_holder_signatures(keyed_anchors: bool, p2a_anchor: bool, remote_commitment: bool) {
// Ensures that we can obtain holder signatures for commitment and HTLC transactions
// asynchronously by allowing their retrieval to fail and retrying via
// `ChannelMonitor::signer_unblocked`.
let mut config = test_default_channel_config();
if anchors {
config.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx = true;
config.manually_accept_inbound_channels = true;
}
config.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx = keyed_anchors;
config.channel_handshake_config.negotiate_anchor_zero_fee_commitments = p2a_anchor;
config.manually_accept_inbound_channels = keyed_anchors || p2a_anchor;

let chanmon_cfgs = create_chanmon_cfgs(2);
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
Expand All @@ -990,23 +985,8 @@ fn do_test_async_holder_signatures(anchors: bool, remote_commitment: bool) {
let node_b_id = nodes[1].node.get_our_node_id();

let closing_node = if remote_commitment { &nodes[1] } else { &nodes[0] };
let coinbase_tx = Transaction {
version: Version::TWO,
lock_time: LockTime::ZERO,
input: vec![TxIn { ..Default::default() }],
output: vec![TxOut {
value: Amount::ONE_BTC,
script_pubkey: closing_node.wallet_source.get_change_script().unwrap(),
}],
};
if anchors {
*nodes[0].fee_estimator.sat_per_kw.lock().unwrap() *= 2;
*nodes[1].fee_estimator.sat_per_kw.lock().unwrap() *= 2;
closing_node.wallet_source.add_utxo(
bitcoin::OutPoint { txid: coinbase_tx.compute_txid(), vout: 0 },
coinbase_tx.output[0].value,
);
}

let coinbase_tx = provide_anchor_reserves(&nodes);

// Route an HTLC and set the signer as unavailable.
let (_, _, chan_id, funding_tx) = create_announced_chan_between_nodes(&nodes, 0, 1);
Expand Down Expand Up @@ -1051,13 +1031,18 @@ fn do_test_async_holder_signatures(anchors: bool, remote_commitment: bool) {
&nodes[0].logger,
);
}
if anchors {
if keyed_anchors || p2a_anchor {
handle_bump_close_event(closing_node);
}

let commitment_tx = {
let mut txn = closing_node.tx_broadcaster.txn_broadcast();
if anchors || remote_commitment {
if p2a_anchor {
assert_eq!(txn.len(), 2);
check_spends!(txn[0], funding_tx);
check_spends!(txn[1], txn[0], coinbase_tx);
txn.remove(0)
} else if keyed_anchors || remote_commitment {
assert_eq!(txn.len(), 1);
check_spends!(txn[0], funding_tx);
txn.remove(0)
Expand Down Expand Up @@ -1102,7 +1087,7 @@ fn do_test_async_holder_signatures(anchors: bool, remote_commitment: bool) {
}

// No HTLC transaction should be broadcast as the signer is not available yet.
if anchors && !remote_commitment {
if (keyed_anchors || p2a_anchor) && !remote_commitment {
handle_bump_htlc_event(&nodes[0], 1);
}
let txn = nodes[0].tx_broadcaster.txn_broadcast();
Expand All @@ -1117,7 +1102,7 @@ fn do_test_async_holder_signatures(anchors: bool, remote_commitment: bool) {
&nodes[0].logger,
);

if anchors && !remote_commitment {
if (keyed_anchors || p2a_anchor) && !remote_commitment {
handle_bump_htlc_event(&nodes[0], 1);
}
{
Expand All @@ -1129,22 +1114,32 @@ fn do_test_async_holder_signatures(anchors: bool, remote_commitment: bool) {

#[test]
fn test_async_holder_signatures_no_anchors() {
do_test_async_holder_signatures(false, false);
do_test_async_holder_signatures(false, false, false);
}

#[test]
fn test_async_holder_signatures_remote_commitment_no_anchors() {
do_test_async_holder_signatures(false, true);
do_test_async_holder_signatures(false, false, true);
}

#[test]
fn test_async_holder_signatures_keyed_anchors() {
do_test_async_holder_signatures(true, false, false);
}

#[test]
fn test_async_holder_signatures_remote_commitment_keyed_anchors() {
do_test_async_holder_signatures(true, false, true);
}

#[test]
fn test_async_holder_signatures_anchors() {
do_test_async_holder_signatures(true, false);
fn test_async_holder_signatures_p2a_anchor() {
do_test_async_holder_signatures(false, true, false);
}

#[test]
fn test_async_holder_signatures_remote_commitment_anchors() {
do_test_async_holder_signatures(true, true);
fn test_async_holder_signatures_remote_commitment_p2a_anchor() {
do_test_async_holder_signatures(false, true, true);
}

#[test]
Expand Down
80 changes: 65 additions & 15 deletions lightning/src/ln/chan_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,10 @@ pub fn max_htlcs(channel_type: &ChannelTypeFeatures) -> u16 {
483
}
}
/// The weight of a BIP141 witnessScript for a BOLT3's "offered HTLC output" on a commitment transaction, non-anchor variant.
/// The weight of a BIP141 witnessScript for a BOLT3's "offered HTLC output" on a commitment transaction, non-anchor and p2a anchor variant.
pub const OFFERED_HTLC_SCRIPT_WEIGHT: usize = 133;
/// The weight of a BIP141 witnessScript for a BOLT3's "offered HTLC output" on a commitment transaction, anchor variant.
pub const OFFERED_HTLC_SCRIPT_WEIGHT_ANCHORS: usize = 136;
/// The weight of a BIP141 witnessScript for a BOLT3's "offered HTLC output" on a commitment transaction, keyed anchor variant.
pub const OFFERED_HTLC_SCRIPT_WEIGHT_KEYED_ANCHORS: usize = 136;

/// The weight of a BIP141 witnessScript for a BOLT3's "received HTLC output" can vary in function of its CLTV argument value.
/// We define a range that encompasses both its non-anchors and anchors variants.
Expand All @@ -95,12 +95,16 @@ pub const P2A_ANCHOR_INPUT_WITNESS_WEIGHT: u64 = 1;
/// The maximum value of a P2A anchor.
pub const P2A_MAX_VALUE: u64 = 240;

/// The upper bound weight of an HTLC timeout input from a commitment transaction with anchor
/// outputs.
pub const HTLC_TIMEOUT_INPUT_ANCHOR_WITNESS_WEIGHT: u64 = 288;
/// The upper bound weight of an HTLC success input from a commitment transaction with anchor
/// outputs.
pub const HTLC_SUCCESS_INPUT_ANCHOR_WITNESS_WEIGHT: u64 = 327;
/// The upper bound weight of an HTLC timeout input from a commitment transaction with keyed anchor outputs.
pub const HTLC_TIMEOUT_INPUT_KEYED_ANCHOR_WITNESS_WEIGHT: u64 = 288;
/// The upper bound weight of an HTLC timeout input from a commitment transaction with a p2a anchor output.
/// Note the corresponding outputs no longer have the 1 CSV lock.
pub const HTLC_TIMEOUT_INPUT_P2A_ANCHOR_WITNESS_WEIGHT: u64 = 285;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no coverage for this change. Tests pass if this is 288.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are used to pass estimates of the size of witness to coin selection in BumpTransactionEventHandler::handle_htlc_resolution - they both break the 1% max overestimate there if you push them high enough.

/// The upper bound weight of an HTLC success input from a commitment transaction with keyed anchor outputs.
pub const HTLC_SUCCESS_INPUT_KEYED_ANCHOR_WITNESS_WEIGHT: u64 = 327;
/// The upper bound weight of an HTLC success input from a commitment transaction with a p2a anchor output.
/// Note the corresponding outputs no longer have the 1 CSV lock.
pub const HTLC_SUCCESS_INPUT_P2A_ANCHOR_WITNESS_WEIGHT: u64 = 324;

/// The size of the 2-of-2 multisig script
const MULTISIG_SCRIPT_SIZE: u64 = 1 + // OP_2
Expand Down Expand Up @@ -158,7 +162,7 @@ impl HTLCClaim {
/// Check if a given input witness attempts to claim a HTLC.
#[rustfmt::skip]
pub fn from_witness(witness: &Witness) -> Option<Self> {
debug_assert_eq!(OFFERED_HTLC_SCRIPT_WEIGHT_ANCHORS, MIN_ACCEPTED_HTLC_SCRIPT_WEIGHT);
debug_assert_eq!(OFFERED_HTLC_SCRIPT_WEIGHT_KEYED_ANCHORS, MIN_ACCEPTED_HTLC_SCRIPT_WEIGHT);
if witness.len() < 2 {
return None;
}
Expand All @@ -177,7 +181,7 @@ impl HTLCClaim {
} else {
None
}
} else if witness_script.len() == OFFERED_HTLC_SCRIPT_WEIGHT_ANCHORS {
} else if witness_script.len() == OFFERED_HTLC_SCRIPT_WEIGHT_KEYED_ANCHORS {
// It's possible for the weight of `offered_htlc_script` and `accepted_htlc_script` to
// match so we check for both here.
if witness.len() == 3 && second_to_last.len() == 33 {
Expand Down Expand Up @@ -2202,7 +2206,8 @@ mod tests {
use super::{ChannelPublicKeys, CounterpartyCommitmentSecrets};
use crate::chain;
use crate::ln::chan_utils::{
get_htlc_redeemscript, get_to_countersigner_keyed_anchor_redeemscript,
get_htlc_redeemscript, get_keyed_anchor_redeemscript,
get_to_countersigner_keyed_anchor_redeemscript, shared_anchor_script_pubkey,
BuiltCommitmentTransaction, ChannelTransactionParameters, CommitmentTransaction,
CounterpartyChannelTransactionParameters, HTLCOutputInCommitment,
TrustedCommitmentTransaction,
Expand Down Expand Up @@ -2250,7 +2255,7 @@ mod tests {
funding_outpoint: Some(chain::transaction::OutPoint { txid: Txid::all_zeros(), index: 0 }),
splice_parent_funding_txid: None,
channel_type_features: ChannelTypeFeatures::only_static_remote_key(),
channel_value_satoshis: 3000,
channel_value_satoshis: 4000,
};

Self {
Expand Down Expand Up @@ -2293,14 +2298,42 @@ mod tests {
let tx = builder.build(1000, 2000, Vec::new());
assert_eq!(tx.built.transaction.output.len(), 4);
assert_eq!(tx.built.transaction.output[3].script_pubkey, get_to_countersigner_keyed_anchor_redeemscript(&builder.counterparty_pubkeys.payment_point).to_p2wsh());
assert_eq!(tx.built.transaction.output[0].script_pubkey, get_keyed_anchor_redeemscript(&builder.channel_parameters.holder_pubkeys.funding_pubkey).to_p2wsh());
assert_eq!(tx.built.transaction.output[0].value.to_sat(), 330);
assert_eq!(tx.built.transaction.output[1].script_pubkey, get_keyed_anchor_redeemscript(&builder.counterparty_pubkeys.funding_pubkey).to_p2wsh());
assert_eq!(tx.built.transaction.output[1].value.to_sat(), 330);

// Generate broadcaster output and anchor
let tx = builder.build(3000, 0, Vec::new());
assert_eq!(tx.built.transaction.output.len(), 2);
assert_eq!(tx.built.transaction.output[0].script_pubkey, get_keyed_anchor_redeemscript(&builder.channel_parameters.holder_pubkeys.funding_pubkey).to_p2wsh());
assert_eq!(tx.built.transaction.output[0].value.to_sat(), 330);

// Generate counterparty output and anchor
let tx = builder.build(0, 3000, Vec::new());
assert_eq!(tx.built.transaction.output.len(), 2);
assert_eq!(tx.built.transaction.output[0].script_pubkey, get_keyed_anchor_redeemscript(&builder.counterparty_pubkeys.funding_pubkey).to_p2wsh());
assert_eq!(tx.built.transaction.output[0].value.to_sat(), 330);

// Generate broadcaster and counterparty outputs as well as a single anchor
builder.channel_parameters.channel_type_features = ChannelTypeFeatures::anchors_zero_fee_commitments();
let tx = builder.build(1000, 2000, Vec::new());
assert_eq!(tx.built.transaction.output.len(), 3);
assert_eq!(tx.built.transaction.output[2].script_pubkey, bitcoin::address::Address::p2wpkh(&CompressedPublicKey(builder.counterparty_pubkeys.payment_point), Network::Testnet).script_pubkey());
assert_eq!(tx.built.transaction.output[0].script_pubkey, shared_anchor_script_pubkey());
assert_eq!(tx.built.transaction.output[0].value.to_sat(), 240); // remember total channel value is 4000sat

// Generate broadcaster output and anchor
let tx = builder.build(3000, 0, Vec::new());
assert_eq!(tx.built.transaction.output.len(), 2);
assert_eq!(tx.built.transaction.output[0].script_pubkey, shared_anchor_script_pubkey());
assert_eq!(tx.built.transaction.output[0].value.to_sat(), 240); // remember total channel value is 4000sat

// Generate counterparty output and anchor
let tx = builder.build(0, 3000, Vec::new());
assert_eq!(tx.built.transaction.output.len(), 2);
assert_eq!(tx.built.transaction.output[0].script_pubkey, shared_anchor_script_pubkey());
assert_eq!(tx.built.transaction.output[0].value.to_sat(), 240); // remember total channel value is 4000sat

let received_htlc = HTLCOutputInCommitment {
offered: false,
Expand All @@ -2318,7 +2351,7 @@ mod tests {
transaction_output_index: None,
};

// Generate broadcaster output and received and offered HTLC outputs, w/o anchors
// Generate broadcaster output and received and offered HTLC outputs, w/o anchors
builder.channel_parameters.channel_type_features = ChannelTypeFeatures::only_static_remote_key();
let tx = builder.build(3000, 0, vec![received_htlc.clone(), offered_htlc.clone()]);
let keys = tx.trust().keys();
Expand All @@ -2330,16 +2363,33 @@ mod tests {
assert_eq!(get_htlc_redeemscript(&offered_htlc, &ChannelTypeFeatures::only_static_remote_key(), &keys).to_p2wsh().to_hex_string(),
"0020215d61bba56b19e9eadb6107f5a85d7f99c40f65992443f69229c290165bc00d");

// Generate broadcaster output and received and offered HTLC outputs, with anchors
// Generate broadcaster output and received and offered HTLC outputs, with keyed anchors
builder.channel_parameters.channel_type_features = ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies();
let tx = builder.build(3000, 0, vec![received_htlc.clone(), offered_htlc.clone()]);
assert_eq!(tx.built.transaction.output.len(), 5);
assert_eq!(tx.built.transaction.output[0].script_pubkey, get_keyed_anchor_redeemscript(&builder.channel_parameters.holder_pubkeys.funding_pubkey).to_p2wsh());
assert_eq!(tx.built.transaction.output[0].value.to_sat(), 330);
assert_eq!(tx.built.transaction.output[1].script_pubkey, get_keyed_anchor_redeemscript(&builder.counterparty_pubkeys.funding_pubkey).to_p2wsh());
assert_eq!(tx.built.transaction.output[1].value.to_sat(), 330);
assert_eq!(tx.built.transaction.output[2].script_pubkey, get_htlc_redeemscript(&received_htlc, &ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies(), &keys).to_p2wsh());
assert_eq!(tx.built.transaction.output[3].script_pubkey, get_htlc_redeemscript(&offered_htlc, &ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies(), &keys).to_p2wsh());
assert_eq!(get_htlc_redeemscript(&received_htlc, &ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies(), &keys).to_p2wsh().to_hex_string(),
"0020b70d0649c72b38756885c7a30908d912a7898dd5d79457a7280b8e9a20f3f2bc");
assert_eq!(get_htlc_redeemscript(&offered_htlc, &ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies(), &keys).to_p2wsh().to_hex_string(),
"002087a3faeb1950a469c0e2db4a79b093a41b9526e5a6fc6ef5cb949bde3be379c7");

// Generate broadcaster output and received and offered HTLC outputs, with P2A anchors
builder.channel_parameters.channel_type_features = ChannelTypeFeatures::anchors_zero_fee_commitments();
let tx = builder.build(3000, 0, vec![received_htlc.clone(), offered_htlc.clone()]);
assert_eq!(tx.built.transaction.output.len(), 4);
assert_eq!(tx.built.transaction.output[0].script_pubkey, shared_anchor_script_pubkey());
assert_eq!(tx.built.transaction.output[0].value.to_sat(), 0);
assert_eq!(tx.built.transaction.output[1].script_pubkey, get_htlc_redeemscript(&received_htlc, &ChannelTypeFeatures::anchors_zero_fee_commitments(), &keys).to_p2wsh());
assert_eq!(tx.built.transaction.output[2].script_pubkey, get_htlc_redeemscript(&offered_htlc, &ChannelTypeFeatures::anchors_zero_fee_commitments(), &keys).to_p2wsh());
assert_eq!(get_htlc_redeemscript(&received_htlc, &ChannelTypeFeatures::anchors_zero_fee_commitments(), &keys).to_p2wsh().to_hex_string(),
"0020e43a7c068553003fe68fcae424fb7b28ec5ce48cd8b6744b3945631389bad2fb");
assert_eq!(get_htlc_redeemscript(&offered_htlc, &ChannelTypeFeatures::anchors_zero_fee_commitments(), &keys).to_p2wsh().to_hex_string(),
"0020215d61bba56b19e9eadb6107f5a85d7f99c40f65992443f69229c290165bc00d");
}

#[test]
Expand Down
2 changes: 1 addition & 1 deletion lightning/src/ln/channel_open_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -622,7 +622,7 @@ pub fn test_insane_channel_opens() {
});
}

#[test]
#[xtest(feature = "_externalize_tests")]
fn test_insane_zero_fee_channel_open() {
let mut cfg = UserConfig::default();
cfg.manually_accept_inbound_channels = true;
Expand Down
Loading
Loading