Skip to content

Commit d7027c2

Browse files
committed
Support HolderHTLCOutput inputs from anchor channels
1 parent baf2dec commit d7027c2

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
@@ -2701,18 +2701,28 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
27012701

27022702
for &(ref htlc, _, _) in holder_tx.htlc_outputs.iter() {
27032703
if let Some(transaction_output_index) = htlc.transaction_output_index {
2704-
let htlc_output = if htlc.offered {
2705-
HolderHTLCOutput::build_offered(htlc.amount_msat, htlc.cltv_expiry)
2704+
let (htlc_output, aggregable) = if htlc.offered {
2705+
let htlc_output = HolderHTLCOutput::build_offered(
2706+
htlc.amount_msat, htlc.cltv_expiry, self.onchain_tx_handler.opt_anchors()
2707+
);
2708+
(htlc_output, false)
2709+
} else {
2710+
let payment_preimage = if let Some(preimage) = self.payment_preimages.get(&htlc.payment_hash) {
2711+
preimage.clone()
27062712
} else {
2707-
let payment_preimage = if let Some(preimage) = self.payment_preimages.get(&htlc.payment_hash) {
2708-
preimage.clone()
2709-
} else {
2710-
// We can't build an HTLC-Success transaction without the preimage
2711-
continue;
2712-
};
2713-
HolderHTLCOutput::build_accepted(payment_preimage, htlc.amount_msat)
2713+
// We can't build an HTLC-Success transaction without the preimage
2714+
continue;
27142715
};
2715-
let htlc_package = PackageTemplate::build_package(holder_tx.txid, transaction_output_index, PackageSolvingData::HolderHTLCOutput(htlc_output), htlc.cltv_expiry, false, conf_height);
2716+
let htlc_output = HolderHTLCOutput::build_accepted(
2717+
payment_preimage, htlc.amount_msat, self.onchain_tx_handler.opt_anchors()
2718+
);
2719+
(htlc_output, self.onchain_tx_handler.opt_anchors())
2720+
};
2721+
let htlc_package = PackageTemplate::build_package(
2722+
holder_tx.txid, transaction_output_index,
2723+
PackageSolvingData::HolderHTLCOutput(htlc_output),
2724+
htlc.cltv_expiry, aggregable, conf_height
2725+
);
27162726
claim_requests.push(htlc_package);
27172727
}
27182728
}

lightning/src/chain/package.rs

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

260261
impl HolderHTLCOutput {
261-
pub(crate) fn build_offered(amount_msat: u64, cltv_expiry: u32) -> Self {
262+
pub(crate) fn build_offered(amount_msat: u64, cltv_expiry: u32, opt_anchors: bool) -> Self {
262263
HolderHTLCOutput {
263264
preimage: None,
264265
amount_msat,
265266
cltv_expiry,
267+
opt_anchors: if opt_anchors { Some(()) } else { None } ,
266268
}
267269
}
268270

269-
pub(crate) fn build_accepted(preimage: PaymentPreimage, amount_msat: u64) -> Self {
271+
pub(crate) fn build_accepted(preimage: PaymentPreimage, amount_msat: u64, opt_anchors: bool) -> Self {
270272
HolderHTLCOutput {
271273
preimage: Some(preimage),
272274
amount_msat,
273275
cltv_expiry: 0,
276+
opt_anchors: if opt_anchors { Some(()) } else { None } ,
274277
}
275278
}
279+
280+
fn opt_anchors(&self) -> bool {
281+
self.opt_anchors.is_some()
282+
}
276283
}
277284

278285
impl_writeable_tlv_based!(HolderHTLCOutput, {
279286
(0, amount_msat, required),
280287
(2, cltv_expiry, required),
281-
(4, preimage, option)
288+
(4, preimage, option),
289+
(6, opt_anchors, option)
282290
});
283291

284292
/// A struct to describe the channel output on the funding transaction.
@@ -333,10 +341,10 @@ impl PackageSolvingData {
333341
PackageSolvingData::RevokedHTLCOutput(ref outp) => outp.amount,
334342
PackageSolvingData::CounterpartyOfferedHTLCOutput(ref outp) => outp.htlc.amount_msat / 1000,
335343
PackageSolvingData::CounterpartyReceivedHTLCOutput(ref outp) => outp.htlc.amount_msat / 1000,
336-
// Note: Currently, amounts of holder outputs spending witnesses aren't used
337-
// as we can't malleate spending package to increase their feerate. This
338-
// should change with the remaining anchor output patchset.
339-
PackageSolvingData::HolderHTLCOutput(..) => unreachable!(),
344+
PackageSolvingData::HolderHTLCOutput(ref outp) => {
345+
debug_assert!(outp.opt_anchors());
346+
outp.amount_msat / 1000
347+
},
340348
PackageSolvingData::HolderFundingOutput(ref outp) => {
341349
debug_assert!(outp.opt_anchors());
342350
outp.funding_amount.unwrap()
@@ -345,18 +353,23 @@ impl PackageSolvingData {
345353
amt
346354
}
347355
fn weight(&self) -> usize {
348-
let weight = match self {
349-
PackageSolvingData::RevokedOutput(ref outp) => { outp.weight as usize },
350-
PackageSolvingData::RevokedHTLCOutput(ref outp) => { outp.weight as usize },
351-
PackageSolvingData::CounterpartyOfferedHTLCOutput(ref outp) => { weight_offered_htlc(outp.opt_anchors()) as usize },
352-
PackageSolvingData::CounterpartyReceivedHTLCOutput(ref outp) => { weight_received_htlc(outp.opt_anchors()) as usize },
353-
// Note: Currently, weights of holder outputs spending witnesses aren't used
354-
// as we can't malleate spending package to increase their feerate. This
355-
// should change with the remaining anchor output patchset.
356-
PackageSolvingData::HolderHTLCOutput(..) => { unreachable!() },
357-
PackageSolvingData::HolderFundingOutput(..) => { unreachable!() },
358-
};
359-
weight
356+
match self {
357+
PackageSolvingData::RevokedOutput(ref outp) => outp.weight as usize,
358+
PackageSolvingData::RevokedHTLCOutput(ref outp) => outp.weight as usize,
359+
PackageSolvingData::CounterpartyOfferedHTLCOutput(ref outp) => weight_offered_htlc(outp.opt_anchors()) as usize,
360+
PackageSolvingData::CounterpartyReceivedHTLCOutput(ref outp) => weight_received_htlc(outp.opt_anchors()) as usize,
361+
PackageSolvingData::HolderHTLCOutput(ref outp) => {
362+
debug_assert!(outp.opt_anchors());
363+
if outp.preimage.is_none() {
364+
weight_offered_htlc(true) as usize
365+
} else {
366+
weight_received_htlc(true) as usize
367+
}
368+
},
369+
// Since HolderFundingOutput maps to an untractable package that is already signed, its
370+
// weight can be determined from the transaction itself.
371+
PackageSolvingData::HolderFundingOutput(..) => unreachable!(),
372+
}
360373
}
361374
fn is_compatible(&self, input: &PackageSolvingData) -> bool {
362375
match self {
@@ -740,6 +753,7 @@ impl PackageTemplate {
740753
pub(crate) fn requires_external_funding(&self) -> bool {
741754
self.inputs.iter().find(|input| match input.1 {
742755
PackageSolvingData::HolderFundingOutput(ref outp) => outp.opt_anchors(),
756+
PackageSolvingData::HolderHTLCOutput(ref outp) => outp.opt_anchors(),
743757
_ => false,
744758
}).is_some()
745759
}
@@ -750,7 +764,11 @@ impl PackageTemplate {
750764
PackageSolvingData::RevokedHTLCOutput(..) => PackageMalleability::Malleable,
751765
PackageSolvingData::CounterpartyOfferedHTLCOutput(..) => PackageMalleability::Malleable,
752766
PackageSolvingData::CounterpartyReceivedHTLCOutput(..) => PackageMalleability::Malleable,
753-
PackageSolvingData::HolderHTLCOutput(..) => PackageMalleability::Untractable,
767+
PackageSolvingData::HolderHTLCOutput(ref outp) => if outp.opt_anchors() {
768+
PackageMalleability::Malleable
769+
} else {
770+
PackageMalleability::Untractable
771+
},
754772
PackageSolvingData::HolderFundingOutput(..) => PackageMalleability::Untractable,
755773
};
756774
let mut inputs = Vec::with_capacity(1);
@@ -799,7 +817,11 @@ impl Readable for PackageTemplate {
799817
PackageSolvingData::RevokedHTLCOutput(..) => { (PackageMalleability::Malleable, true) },
800818
PackageSolvingData::CounterpartyOfferedHTLCOutput(..) => { (PackageMalleability::Malleable, true) },
801819
PackageSolvingData::CounterpartyReceivedHTLCOutput(..) => { (PackageMalleability::Malleable, false) },
802-
PackageSolvingData::HolderHTLCOutput(..) => { (PackageMalleability::Untractable, false) },
820+
PackageSolvingData::HolderHTLCOutput(ref outp) => if outp.opt_anchors() {
821+
(PackageMalleability::Malleable, outp.preimage.is_some())
822+
} else {
823+
(PackageMalleability::Untractable, false)
824+
},
803825
PackageSolvingData::HolderFundingOutput(..) => { (PackageMalleability::Untractable, false) },
804826
}
805827
} else { return Err(DecodeError::InvalidValue); };
@@ -959,7 +981,7 @@ mod tests {
959981
() => {
960982
{
961983
let preimage = PaymentPreimage([2;32]);
962-
PackageSolvingData::HolderHTLCOutput(HolderHTLCOutput::build_accepted(preimage, 0))
984+
PackageSolvingData::HolderHTLCOutput(HolderHTLCOutput::build_accepted(preimage, 0, false))
963985
}
964986
}
965987
}

0 commit comments

Comments
 (0)