Skip to content

Commit 5a8c244

Browse files
committed
Refactor BroadcastType with channel context
We add the `ChannelId` as context to the just-added `BroadcastType` enum. Co-Authored-By: HAL 9000 Signed-off-by: Elias Rohrer <dev@tnull.de>
1 parent 060e6ec commit 5a8c244

File tree

7 files changed

+184
-100
lines changed

7 files changed

+184
-100
lines changed

lightning-liquidity/src/lsps2/service.rs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2023,23 +2023,24 @@ where
20232023
// (for example when a forwarded HTLC nears expiry). Broadcasting funding after a
20242024
// close could then confirm the commitment and trigger unintended on‑chain handling.
20252025
// To avoid this, we check ChannelManager’s view (`is_channel_ready`) before broadcasting.
2026-
let channel_id_opt = jit_channel.get_channel_id();
2027-
if let Some(ch_id) = channel_id_opt {
2026+
if let Some(ch_id) = jit_channel.get_channel_id() {
20282027
let is_channel_ready = self
20292028
.channel_manager
20302029
.get_cm()
20312030
.list_channels()
20322031
.into_iter()
20332032
.any(|cd| cd.channel_id == ch_id && cd.is_channel_ready);
2033+
20342034
if !is_channel_ready {
20352035
return;
20362036
}
2037-
} else {
2038-
return;
2039-
}
20402037

2041-
if let Some(funding_tx) = jit_channel.get_funding_tx() {
2042-
self.tx_broadcaster.broadcast_transactions(&[(funding_tx, BroadcastType::Funding)]);
2038+
if let Some(funding_tx) = jit_channel.get_funding_tx() {
2039+
self.tx_broadcaster.broadcast_transactions(&[(
2040+
funding_tx,
2041+
BroadcastType::Funding { channel_ids: vec![ch_id] },
2042+
)]);
2043+
}
20432044
}
20442045
}
20452046
}

lightning/src/chain/chaininterface.rs

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
1616
use core::{cmp, ops::Deref};
1717

18+
use crate::ln::types::ChannelId;
1819
use crate::prelude::*;
1920

2021
use bitcoin::transaction::Transaction;
@@ -23,22 +24,47 @@ use bitcoin::transaction::Transaction;
2324
///
2425
/// This is used to provide context about the type of transaction being broadcast, which may be
2526
/// useful for logging, filtering, or prioritization purposes.
26-
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
27+
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
2728
pub enum BroadcastType {
2829
/// A funding transaction establishing a new channel.
29-
Funding,
30+
Funding {
31+
/// The IDs of the channels being funded.
32+
///
33+
/// A single funding transaction may establish multiple channels when using batch funding.
34+
channel_ids: Vec<ChannelId>,
35+
},
3036
/// A cooperative close transaction mutually agreed upon by both parties.
31-
CooperativeClose,
37+
CooperativeClose {
38+
/// The ID of the channel being closed.
39+
channel_id: ChannelId,
40+
},
3241
/// A commitment transaction being broadcast to force-close the channel.
33-
Commitment,
42+
Commitment {
43+
/// The ID of the channel being force-closed.
44+
channel_id: ChannelId,
45+
},
3446
/// An anchor transaction used for CPFP fee-bumping a commitment transaction.
35-
Anchor,
47+
Anchor {
48+
/// The ID of the channel whose commitment transaction is being fee-bumped.
49+
channel_id: ChannelId,
50+
},
3651
/// A transaction claiming outputs from a commitment transaction (HTLC claims, penalty/justice).
37-
Claim,
52+
Claim {
53+
/// The ID of the channel from which outputs are being claimed.
54+
channel_id: ChannelId,
55+
},
3856
/// An HTLC resolution transaction (HTLC-timeout or HTLC-success) for anchor channels.
39-
HtlcResolution,
57+
HtlcResolution {
58+
/// The ID of the channel whose HTLCs are being resolved.
59+
channel_id: ChannelId,
60+
},
4061
/// A transaction sweeping spendable outputs to the user's wallet.
41-
Sweep,
62+
Sweep {
63+
/// The IDs of the channels from which outputs are being swept, if known.
64+
///
65+
/// A single sweep transaction may aggregate outputs from multiple channels.
66+
channel_ids: Vec<ChannelId>,
67+
},
4268
}
4369

4470
// TODO: Define typed abstraction over feerates to handle their conversions.

lightning/src/chain/channelmonitor.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1904,8 +1904,9 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
19041904
initial_holder_commitment_tx.trust().commitment_number();
19051905

19061906
let onchain_tx_handler = OnchainTxHandler::new(
1907-
channel_parameters.channel_value_satoshis, channel_keys_id, destination_script.into(),
1908-
keys, channel_parameters.clone(), initial_holder_commitment_tx.clone(), secp_ctx
1907+
channel_id, channel_parameters.channel_value_satoshis, channel_keys_id,
1908+
destination_script.into(), keys, channel_parameters.clone(),
1909+
initial_holder_commitment_tx.clone(), secp_ctx,
19091910
);
19101911

19111912
let funding_outpoint = channel_parameters.funding_outpoint

lightning/src/chain/onchaintx.rs

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ use crate::ln::chan_utils::{
3535
HTLCOutputInCommitment, HolderCommitmentTransaction,
3636
};
3737
use crate::ln::msgs::DecodeError;
38+
use crate::ln::types::ChannelId;
3839
use crate::sign::{ecdsa::EcdsaChannelSigner, EntropySource, HTLCDescriptor, SignerProvider};
3940
use crate::util::logger::Logger;
4041
use crate::util::ser::{
@@ -223,6 +224,7 @@ pub(crate) enum FeerateStrategy {
223224
/// do RBF bumping if possible.
224225
#[derive(Clone)]
225226
pub struct OnchainTxHandler<ChannelSigner: EcdsaChannelSigner> {
227+
channel_id: ChannelId,
226228
channel_value_satoshis: u64, // Deprecated as of 0.2.
227229
channel_keys_id: [u8; 32], // Deprecated as of 0.2.
228230
destination_script: ScriptBuf, // Deprecated as of 0.2.
@@ -285,7 +287,8 @@ impl<ChannelSigner: EcdsaChannelSigner> PartialEq for OnchainTxHandler<ChannelSi
285287
#[rustfmt::skip]
286288
fn eq(&self, other: &Self) -> bool {
287289
// `signer`, `secp_ctx`, and `pending_claim_events` are excluded on purpose.
288-
self.channel_value_satoshis == other.channel_value_satoshis &&
290+
self.channel_id == other.channel_id &&
291+
self.channel_value_satoshis == other.channel_value_satoshis &&
289292
self.channel_keys_id == other.channel_keys_id &&
290293
self.destination_script == other.destination_script &&
291294
self.holder_commitment == other.holder_commitment &&
@@ -345,7 +348,9 @@ impl<ChannelSigner: EcdsaChannelSigner> OnchainTxHandler<ChannelSigner> {
345348
entry.write(writer)?;
346349
}
347350

348-
write_tlv_fields!(writer, {});
351+
write_tlv_fields!(writer, {
352+
(1, self.channel_id, required),
353+
});
349354
Ok(())
350355
}
351356
}
@@ -369,7 +374,7 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
369374
let prev_holder_commitment = Readable::read(reader)?;
370375
let _prev_holder_htlc_sigs: Option<Vec<Option<(usize, Signature)>>> = Readable::read(reader)?;
371376

372-
let channel_parameters = ReadableArgs::<Option<u64>>::read(reader, Some(channel_value_satoshis))?;
377+
let channel_parameters: ChannelTransactionParameters = ReadableArgs::<Option<u64>>::read(reader, Some(channel_value_satoshis))?;
373378

374379
// Read the serialized signer bytes, but don't deserialize them, as we'll obtain our signer
375380
// by re-deriving the private key material.
@@ -421,12 +426,24 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
421426
}
422427
}
423428

424-
read_tlv_fields!(reader, {});
429+
let mut channel_id = None;
430+
read_tlv_fields!(reader, {
431+
(1, channel_id, option),
432+
});
433+
434+
// For backwards compatibility with monitors serialized before channel_id was added,
435+
// we derive a channel_id from the funding outpoint if not present.
436+
let channel_id = channel_id.or_else(|| {
437+
channel_parameters.funding_outpoint
438+
.map(|op| ChannelId::v1_from_funding_outpoint(op))
439+
}) // funding_outpoint must be known during intialization.
440+
.ok_or(DecodeError::InvalidValue)?;
425441

426442
let mut secp_ctx = Secp256k1::new();
427443
secp_ctx.seeded_randomize(&entropy_source.get_secure_random_bytes());
428444

429445
Ok(OnchainTxHandler {
446+
channel_id,
430447
channel_value_satoshis,
431448
channel_keys_id,
432449
destination_script,
@@ -446,11 +463,13 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
446463

447464
impl<ChannelSigner: EcdsaChannelSigner> OnchainTxHandler<ChannelSigner> {
448465
pub(crate) fn new(
449-
channel_value_satoshis: u64, channel_keys_id: [u8; 32], destination_script: ScriptBuf,
450-
signer: ChannelSigner, channel_parameters: ChannelTransactionParameters,
466+
channel_id: ChannelId, channel_value_satoshis: u64, channel_keys_id: [u8; 32],
467+
destination_script: ScriptBuf, signer: ChannelSigner,
468+
channel_parameters: ChannelTransactionParameters,
451469
holder_commitment: HolderCommitmentTransaction, secp_ctx: Secp256k1<secp256k1::All>,
452470
) -> Self {
453471
OnchainTxHandler {
472+
channel_id,
454473
channel_value_satoshis,
455474
channel_keys_id,
456475
destination_script,
@@ -518,7 +537,7 @@ impl<ChannelSigner: EcdsaChannelSigner> OnchainTxHandler<ChannelSigner> {
518537
if tx.is_fully_signed() {
519538
let log_start = if feerate_was_bumped { "Broadcasting RBF-bumped" } else { "Rebroadcasting" };
520539
log_info!(logger, "{} onchain {}", log_start, log_tx!(tx.0));
521-
broadcaster.broadcast_transactions(&[(&tx.0, BroadcastType::Claim)]);
540+
broadcaster.broadcast_transactions(&[(&tx.0, BroadcastType::Claim { channel_id: self.channel_id })]);
522541
} else {
523542
log_info!(logger, "Waiting for signature of unsigned onchain transaction {}", tx.0.compute_txid());
524543
}
@@ -865,7 +884,7 @@ impl<ChannelSigner: EcdsaChannelSigner> OnchainTxHandler<ChannelSigner> {
865884
OnchainClaim::Tx(tx) => {
866885
if tx.is_fully_signed() {
867886
log_info!(logger, "Broadcasting onchain {}", log_tx!(tx.0));
868-
broadcaster.broadcast_transactions(&[(&tx.0, BroadcastType::Claim)]);
887+
broadcaster.broadcast_transactions(&[(&tx.0, BroadcastType::Claim { channel_id: self.channel_id })]);
869888
} else {
870889
log_info!(logger, "Waiting for signature of unsigned onchain transaction {}", tx.0.compute_txid());
871890
}
@@ -1086,7 +1105,7 @@ impl<ChannelSigner: EcdsaChannelSigner> OnchainTxHandler<ChannelSigner> {
10861105
OnchainClaim::Tx(bump_tx) => {
10871106
if bump_tx.is_fully_signed() {
10881107
log_info!(logger, "Broadcasting RBF-bumped onchain {}", log_tx!(bump_tx.0));
1089-
broadcaster.broadcast_transactions(&[(&bump_tx.0, BroadcastType::Claim)]);
1108+
broadcaster.broadcast_transactions(&[(&bump_tx.0, BroadcastType::Claim { channel_id: self.channel_id })]);
10901109
} else {
10911110
log_info!(logger, "Waiting for signature of RBF-bumped unsigned onchain transaction {}",
10921111
bump_tx.0.compute_txid());
@@ -1189,7 +1208,7 @@ impl<ChannelSigner: EcdsaChannelSigner> OnchainTxHandler<ChannelSigner> {
11891208
OnchainClaim::Tx(bump_tx) => {
11901209
if bump_tx.is_fully_signed() {
11911210
log_info!(logger, "Broadcasting onchain {}", log_tx!(bump_tx.0));
1192-
broadcaster.broadcast_transactions(&[(&bump_tx.0, BroadcastType::Claim)]);
1211+
broadcaster.broadcast_transactions(&[(&bump_tx.0, BroadcastType::Claim { channel_id: self.channel_id })]);
11931212
} else {
11941213
log_info!(logger, "Waiting for signature of unsigned onchain transaction {}", bump_tx.0.compute_txid());
11951214
}
@@ -1283,6 +1302,7 @@ mod tests {
12831302
};
12841303
use crate::ln::channel_keys::{DelayedPaymentBasepoint, HtlcBasepoint, RevocationBasepoint};
12851304
use crate::ln::functional_test_utils::create_dummy_block;
1305+
use crate::ln::types::ChannelId;
12861306
use crate::sign::{ChannelDerivationParameters, ChannelSigner, HTLCDescriptor, InMemorySigner};
12871307
use crate::types::payment::{PaymentHash, PaymentPreimage};
12881308
use crate::util::test_utils::{TestBroadcaster, TestFeeEstimator, TestLogger};
@@ -1367,6 +1387,7 @@ mod tests {
13671387
let holder_commit = HolderCommitmentTransaction::dummy(1000000, funding_outpoint, nondust_htlcs);
13681388
let destination_script = ScriptBuf::new();
13691389
let mut tx_handler = OnchainTxHandler::new(
1390+
ChannelId::from_bytes([0; 32]),
13701391
1000000,
13711392
[0; 32],
13721393
destination_script.clone(),

lightning/src/events/bump_transaction/mod.rs

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -765,9 +765,9 @@ where
765765
/// transaction spending an anchor output of the commitment transaction to bump its fee and
766766
/// broadcasts them to the network as a package.
767767
async fn handle_channel_close(
768-
&self, claim_id: ClaimId, package_target_feerate_sat_per_1000_weight: u32,
769-
commitment_tx: &Transaction, commitment_tx_fee_sat: u64,
770-
anchor_descriptor: &AnchorDescriptor,
768+
&self, channel_id: ChannelId, claim_id: ClaimId,
769+
package_target_feerate_sat_per_1000_weight: u32, commitment_tx: &Transaction,
770+
commitment_tx_fee_sat: u64, anchor_descriptor: &AnchorDescriptor,
771771
) -> Result<(), ()> {
772772
let channel_type = &anchor_descriptor
773773
.channel_derivation_parameters
@@ -788,7 +788,10 @@ where
788788
log_debug!(self.logger, "Pre-signed commitment {} already has feerate {} sat/kW above required {} sat/kW, broadcasting.",
789789
commitment_tx.compute_txid(), commitment_tx_feerate_sat_per_1000_weight,
790790
package_target_feerate_sat_per_1000_weight);
791-
self.broadcaster.broadcast_transactions(&[(&commitment_tx, BroadcastType::Commitment)]);
791+
self.broadcaster.broadcast_transactions(&[(
792+
&commitment_tx,
793+
BroadcastType::Commitment { channel_id },
794+
)]);
792795
return Ok(());
793796
}
794797

@@ -956,8 +959,8 @@ where
956959
commitment_tx.compute_txid()
957960
);
958961
self.broadcaster.broadcast_transactions(&[
959-
(&commitment_tx, BroadcastType::Commitment),
960-
(&anchor_tx, BroadcastType::Anchor),
962+
(&commitment_tx, BroadcastType::Commitment { channel_id }),
963+
(&anchor_tx, BroadcastType::Anchor { channel_id }),
961964
]);
962965
return Ok(());
963966
}
@@ -966,7 +969,7 @@ where
966969
/// Handles a [`BumpTransactionEvent::HTLCResolution`] event variant by producing a
967970
/// fully-signed, fee-bumped HTLC transaction that is broadcast to the network.
968971
async fn handle_htlc_resolution(
969-
&self, claim_id: ClaimId, target_feerate_sat_per_1000_weight: u32,
972+
&self, channel_id: ChannelId, claim_id: ClaimId, target_feerate_sat_per_1000_weight: u32,
970973
htlc_descriptors: &[HTLCDescriptor], tx_lock_time: LockTime,
971974
) -> Result<(), ()> {
972975
let channel_type = &htlc_descriptors[0]
@@ -1191,7 +1194,10 @@ where
11911194
}
11921195

11931196
log_info!(self.logger, "Broadcasting {}", log_tx!(htlc_tx));
1194-
self.broadcaster.broadcast_transactions(&[(&htlc_tx, BroadcastType::HtlcResolution)]);
1197+
self.broadcaster.broadcast_transactions(&[(
1198+
&htlc_tx,
1199+
BroadcastType::HtlcResolution { channel_id },
1200+
)]);
11951201
}
11961202

11971203
Ok(())
@@ -1201,6 +1207,7 @@ where
12011207
pub async fn handle_event(&self, event: &BumpTransactionEvent) {
12021208
match event {
12031209
BumpTransactionEvent::ChannelClose {
1210+
channel_id,
12041211
claim_id,
12051212
package_target_feerate_sat_per_1000_weight,
12061213
commitment_tx,
@@ -1215,6 +1222,7 @@ where
12151222
commitment_tx.compute_txid()
12161223
);
12171224
self.handle_channel_close(
1225+
*channel_id,
12181226
*claim_id,
12191227
*package_target_feerate_sat_per_1000_weight,
12201228
commitment_tx,
@@ -1231,6 +1239,7 @@ where
12311239
});
12321240
},
12331241
BumpTransactionEvent::HTLCResolution {
1242+
channel_id,
12341243
claim_id,
12351244
target_feerate_sat_per_1000_weight,
12361245
htlc_descriptors,
@@ -1244,6 +1253,7 @@ where
12441253
log_iter!(htlc_descriptors.iter().map(|d| d.outpoint()))
12451254
);
12461255
self.handle_htlc_resolution(
1256+
*channel_id,
12471257
*claim_id,
12481258
*target_feerate_sat_per_1000_weight,
12491259
htlc_descriptors,

0 commit comments

Comments
 (0)