Skip to content

Commit 1eca282

Browse files
committed
Support HolderHTLCOutput inputs from anchor channels
1 parent 6ccf994 commit 1eca282

File tree

2 files changed

+64
-32
lines changed

2 files changed

+64
-32
lines changed

lightning/src/chain/channelmonitor.rs

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2642,18 +2642,28 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
26422642

26432643
for &(ref htlc, _, _) in holder_tx.htlc_outputs.iter() {
26442644
if let Some(transaction_output_index) = htlc.transaction_output_index {
2645-
let htlc_output = if htlc.offered {
2646-
HolderHTLCOutput::build_offered(htlc.amount_msat, htlc.cltv_expiry)
2645+
let (htlc_output, aggregable) = if htlc.offered {
2646+
let htlc_output = HolderHTLCOutput::build_offered(
2647+
htlc.amount_msat, htlc.cltv_expiry, self.onchain_tx_handler.opt_anchors()
2648+
);
2649+
(htlc_output, false)
2650+
} else {
2651+
let payment_preimage = if let Some(preimage) = self.payment_preimages.get(&htlc.payment_hash) {
2652+
preimage.clone()
26472653
} else {
2648-
let payment_preimage = if let Some(preimage) = self.payment_preimages.get(&htlc.payment_hash) {
2649-
preimage.clone()
2650-
} else {
2651-
// We can't build an HTLC-Success transaction without the preimage
2652-
continue;
2653-
};
2654-
HolderHTLCOutput::build_accepted(payment_preimage, htlc.amount_msat)
2654+
// We can't build an HTLC-Success transaction without the preimage
2655+
continue;
26552656
};
2656-
let htlc_package = PackageTemplate::build_package(holder_tx.txid, transaction_output_index, PackageSolvingData::HolderHTLCOutput(htlc_output), htlc.cltv_expiry, false, conf_height);
2657+
let htlc_output = HolderHTLCOutput::build_accepted(
2658+
payment_preimage, htlc.amount_msat, self.onchain_tx_handler.opt_anchors()
2659+
);
2660+
(htlc_output, self.onchain_tx_handler.opt_anchors())
2661+
};
2662+
let htlc_package = PackageTemplate::build_package(
2663+
holder_tx.txid, transaction_output_index,
2664+
PackageSolvingData::HolderHTLCOutput(htlc_output),
2665+
htlc.cltv_expiry, aggregable, conf_height
2666+
);
26572667
claim_requests.push(htlc_package);
26582668
}
26592669
}

lightning/src/chain/package.rs

Lines changed: 44 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -256,30 +256,38 @@ pub(crate) struct HolderHTLCOutput {
256256
amount_msat: u64,
257257
/// Defaults to 0 for HTLC-Success transactions, which have no expiry
258258
cltv_expiry: u32,
259+
opt_anchors: Option<()>,
259260
}
260261

261262
impl HolderHTLCOutput {
262-
pub(crate) fn build_offered(amount_msat: u64, cltv_expiry: u32) -> Self {
263+
pub(crate) fn build_offered(amount_msat: u64, cltv_expiry: u32, opt_anchors: bool) -> Self {
263264
HolderHTLCOutput {
264265
preimage: None,
265266
amount_msat,
266267
cltv_expiry,
268+
opt_anchors: if opt_anchors { Some(()) } else { None } ,
267269
}
268270
}
269271

270-
pub(crate) fn build_accepted(preimage: PaymentPreimage, amount_msat: u64) -> Self {
272+
pub(crate) fn build_accepted(preimage: PaymentPreimage, amount_msat: u64, opt_anchors: bool) -> Self {
271273
HolderHTLCOutput {
272274
preimage: Some(preimage),
273275
amount_msat,
274276
cltv_expiry: 0,
277+
opt_anchors: if opt_anchors { Some(()) } else { None } ,
275278
}
276279
}
280+
281+
fn opt_anchors(&self) -> bool {
282+
self.opt_anchors.is_some()
283+
}
277284
}
278285

279286
impl_writeable_tlv_based!(HolderHTLCOutput, {
280287
(0, amount_msat, required),
281288
(2, cltv_expiry, required),
282-
(4, preimage, option)
289+
(4, preimage, option),
290+
(6, opt_anchors, (default_value, None))
283291
});
284292

285293
/// A struct to describe the channel output on the funding transaction.
@@ -334,10 +342,10 @@ impl PackageSolvingData {
334342
PackageSolvingData::RevokedHTLCOutput(ref outp) => outp.amount,
335343
PackageSolvingData::CounterpartyOfferedHTLCOutput(ref outp) => outp.htlc.amount_msat / 1000,
336344
PackageSolvingData::CounterpartyReceivedHTLCOutput(ref outp) => outp.htlc.amount_msat / 1000,
337-
// Note: Currently, amounts of holder outputs spending witnesses aren't used
338-
// as we can't malleate spending package to increase their feerate. This
339-
// should change with the remaining anchor output patchset.
340-
PackageSolvingData::HolderHTLCOutput(..) => unreachable!(),
345+
PackageSolvingData::HolderHTLCOutput(ref outp) => {
346+
debug_assert!(outp.opt_anchors());
347+
outp.amount_msat / 1000
348+
},
341349
PackageSolvingData::HolderFundingOutput(ref outp) => {
342350
debug_assert!(outp.opt_anchors());
343351
outp.funding_amount.unwrap()
@@ -346,18 +354,23 @@ impl PackageSolvingData {
346354
amt
347355
}
348356
fn weight(&self) -> usize {
349-
let weight = match self {
350-
PackageSolvingData::RevokedOutput(ref outp) => { outp.weight as usize },
351-
PackageSolvingData::RevokedHTLCOutput(ref outp) => { outp.weight as usize },
352-
PackageSolvingData::CounterpartyOfferedHTLCOutput(ref outp) => { weight_offered_htlc(outp.opt_anchors()) as usize },
353-
PackageSolvingData::CounterpartyReceivedHTLCOutput(ref outp) => { weight_received_htlc(outp.opt_anchors()) as usize },
354-
// Note: Currently, weights of holder outputs spending witnesses aren't used
355-
// as we can't malleate spending package to increase their feerate. This
356-
// should change with the remaining anchor output patchset.
357-
PackageSolvingData::HolderHTLCOutput(..) => { unreachable!() },
358-
PackageSolvingData::HolderFundingOutput(..) => { unreachable!() },
359-
};
360-
weight
357+
match self {
358+
PackageSolvingData::RevokedOutput(ref outp) => outp.weight as usize,
359+
PackageSolvingData::RevokedHTLCOutput(ref outp) => outp.weight as usize,
360+
PackageSolvingData::CounterpartyOfferedHTLCOutput(ref outp) => weight_offered_htlc(outp.opt_anchors()) as usize,
361+
PackageSolvingData::CounterpartyReceivedHTLCOutput(ref outp) => weight_received_htlc(outp.opt_anchors()) as usize,
362+
PackageSolvingData::HolderHTLCOutput(ref outp) => {
363+
debug_assert!(outp.opt_anchors());
364+
if outp.preimage.is_none() {
365+
weight_offered_htlc(true) as usize
366+
} else {
367+
weight_received_htlc(true) as usize
368+
}
369+
},
370+
// Since HolderFundingOutput maps to an untractable package that is already signed, its
371+
// weight can be determined from the transaction itself.
372+
PackageSolvingData::HolderFundingOutput(..) => unreachable!(),
373+
}
361374
}
362375
fn is_compatible(&self, input: &PackageSolvingData) -> bool {
363376
match self {
@@ -745,6 +758,7 @@ impl PackageTemplate {
745758
pub(crate) fn requires_external_funding(&self) -> bool {
746759
self.inputs.iter().find(|input| match input.1 {
747760
PackageSolvingData::HolderFundingOutput(ref outp) => outp.opt_anchors(),
761+
PackageSolvingData::HolderHTLCOutput(ref outp) => outp.opt_anchors(),
748762
_ => false,
749763
}).is_some()
750764
}
@@ -755,7 +769,11 @@ impl PackageTemplate {
755769
PackageSolvingData::RevokedHTLCOutput(..) => PackageMalleability::Malleable,
756770
PackageSolvingData::CounterpartyOfferedHTLCOutput(..) => PackageMalleability::Malleable,
757771
PackageSolvingData::CounterpartyReceivedHTLCOutput(..) => PackageMalleability::Malleable,
758-
PackageSolvingData::HolderHTLCOutput(..) => PackageMalleability::Untractable,
772+
PackageSolvingData::HolderHTLCOutput(ref outp) => if outp.opt_anchors() {
773+
PackageMalleability::Malleable
774+
} else {
775+
PackageMalleability::Untractable
776+
},
759777
PackageSolvingData::HolderFundingOutput(..) => PackageMalleability::Untractable,
760778
};
761779
let mut inputs = Vec::with_capacity(1);
@@ -804,7 +822,11 @@ impl Readable for PackageTemplate {
804822
PackageSolvingData::RevokedHTLCOutput(..) => { (PackageMalleability::Malleable, true) },
805823
PackageSolvingData::CounterpartyOfferedHTLCOutput(..) => { (PackageMalleability::Malleable, true) },
806824
PackageSolvingData::CounterpartyReceivedHTLCOutput(..) => { (PackageMalleability::Malleable, false) },
807-
PackageSolvingData::HolderHTLCOutput(..) => { (PackageMalleability::Untractable, false) },
825+
PackageSolvingData::HolderHTLCOutput(ref outp) => if outp.opt_anchors() {
826+
(PackageMalleability::Malleable, outp.preimage.is_some())
827+
} else {
828+
(PackageMalleability::Untractable, false)
829+
},
808830
PackageSolvingData::HolderFundingOutput(..) => { (PackageMalleability::Untractable, false) },
809831
}
810832
} else { return Err(DecodeError::InvalidValue); };
@@ -964,7 +986,7 @@ mod tests {
964986
() => {
965987
{
966988
let preimage = PaymentPreimage([2;32]);
967-
PackageSolvingData::HolderHTLCOutput(HolderHTLCOutput::build_accepted(preimage, 0))
989+
PackageSolvingData::HolderHTLCOutput(HolderHTLCOutput::build_accepted(preimage, 0, false))
968990
}
969991
}
970992
}

0 commit comments

Comments
 (0)