Skip to content

Commit e266f3f

Browse files
Add would_broadcast_at_height functionality to Channel
In service to the larger refactor of removing the Channel's reference to its ChannelMonitor.
1 parent 7dca3a9 commit e266f3f

File tree

4 files changed

+203
-54
lines changed

4 files changed

+203
-54
lines changed

lightning/src/ln/chan_utils.rs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,44 @@ pub struct HTLCOutputInCommitment {
405405
pub transaction_output_index: Option<u32>,
406406
}
407407

408+
/// Used for ChannelMonitor's would_broadcast_at_height_given_htlcs because
409+
/// it needs to be able to take in an Iter of HTLCOutputInCommitments or of
410+
/// references to HTLCOutputInCommitments. Rust's `Borrow` trait is intended
411+
/// to accomplish +- the same thing, but 1.22.0 doesn't allow us to pass in a
412+
/// Item = impl Borrow<..>, so we do this instead.
413+
pub(crate) trait HTLCCommitmentOutput {
414+
/// Whether the HTLCOutputInCommitment is offered.
415+
fn offered(&self) -> bool;
416+
/// The CLTV expiry of the HTLCOutputInCommitment.
417+
fn cltv_expiry(&self) -> u32;
418+
/// The payment hash of the HTLCOutputInCommitment.
419+
fn payment_hash(&self) -> PaymentHash;
420+
}
421+
422+
impl HTLCCommitmentOutput for HTLCOutputInCommitment {
423+
fn offered(&self) -> bool {
424+
self.offered
425+
}
426+
fn cltv_expiry(&self) -> u32 {
427+
self.cltv_expiry
428+
}
429+
fn payment_hash(&self) -> PaymentHash {
430+
self.payment_hash
431+
}
432+
}
433+
434+
impl<'a> HTLCCommitmentOutput for &'a HTLCOutputInCommitment {
435+
fn offered(&self) -> bool {
436+
self.offered
437+
}
438+
fn cltv_expiry(&self) -> u32 {
439+
self.cltv_expiry
440+
}
441+
fn payment_hash(&self) -> PaymentHash {
442+
self.payment_hash
443+
}
444+
}
445+
408446
impl_writeable!(HTLCOutputInCommitment, 1 + 8 + 4 + 32 + 5, {
409447
offered,
410448
amount_msat,

lightning/src/ln/channel.rs

Lines changed: 130 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ use ln::chan_utils;
3333
use chain::chaininterface::{FeeEstimator,ConfirmationTarget};
3434
use chain::transaction::OutPoint;
3535
use chain::keysinterface::{ChannelKeys, KeysInterface};
36-
use util::transaction_utils;
36+
use util::{byte_utils, transaction_utils};
3737
use util::ser::{Readable, Writeable, Writer};
3838
use util::logger::Logger;
3939
use util::errors::APIError;
@@ -43,6 +43,7 @@ use std;
4343
use std::default::Default;
4444
use std::{cmp,mem,fmt};
4545
use std::ops::Deref;
46+
use std::collections::HashMap;
4647
use bitcoin::hashes::hex::ToHex;
4748

4849
#[cfg(test)]
@@ -104,16 +105,18 @@ enum InboundHTLCState {
104105
AwaitingAnnouncedRemoteRevoke(PendingHTLCStatus),
105106
Committed,
106107
/// Removed by us and a new commitment_signed was sent (if we were AwaitingRemoteRevoke when we
107-
/// created it we would have put it in the holding cell instead). When they next revoke_and_ack
108-
/// we'll drop it.
108+
/// created it we would have put it in the holding cell instead).
109109
/// Note that we have to keep an eye on the HTLC until we've received a broadcastable
110110
/// commitment transaction without it as otherwise we'll have to force-close the channel to
111111
/// claim it before the timeout (obviously doesn't apply to revoked HTLCs that we can't claim
112-
/// anyway). That said, ChannelMonitor does this for us (see
113-
/// ChannelMonitor::would_broadcast_at_height) so we actually remove the HTLC from our own
114-
/// local state before then, once we're sure that the next commitment_signed and
115-
/// ChannelMonitor::provide_latest_local_commitment_tx_info will not include this HTLC.
112+
/// anyway).
116113
LocalRemoved(InboundHTLCRemovalReason),
114+
/// Removed by us and by the remote.
115+
/// Note that we have to keep an eye on the HTLC until we've received a broadcastable
116+
/// commitment transaction without it as otherwise we'll have to force-close the channel to
117+
/// claim it before the timeout (obviously doesn't apply to revoked HTLCs that we can't claim
118+
/// anyway).
119+
RemoteRemoved,
117120
}
118121

119122
struct InboundHTLCOutput {
@@ -293,6 +296,7 @@ pub(super) struct Channel<ChanSigner: ChannelKeys> {
293296
pending_inbound_htlcs: Vec<InboundHTLCOutput>,
294297
pending_outbound_htlcs: Vec<OutboundHTLCOutput>,
295298
holding_cell_htlc_updates: Vec<HTLCUpdateAwaitingACK>,
299+
payment_preimages: HashMap<PaymentHash, PaymentPreimage>,
296300

297301
/// When resending CS/RAA messages on channel monitor restoration or on reconnect, we always
298302
/// need to ensure we resend them in the order we originally generated them. Note that because
@@ -510,6 +514,7 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
510514
pending_inbound_htlcs: Vec::new(),
511515
pending_outbound_htlcs: Vec::new(),
512516
holding_cell_htlc_updates: Vec::new(),
517+
payment_preimages: HashMap::new(),
513518
pending_update_fee: None,
514519
holding_cell_update_fee: None,
515520
next_local_htlc_id: 0,
@@ -738,6 +743,7 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
738743
pending_inbound_htlcs: Vec::new(),
739744
pending_outbound_htlcs: Vec::new(),
740745
holding_cell_htlc_updates: Vec::new(),
746+
payment_preimages: HashMap::new(),
741747
pending_update_fee: None,
742748
holding_cell_update_fee: None,
743749
next_local_htlc_id: 0,
@@ -795,6 +801,57 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
795801
Ok(chan)
796802
}
797803

804+
pub(super) fn monitor_would_broadcast_at_height<L: Deref>(&self, height: u32, logger: &L) -> bool where L::Target: Logger {
805+
macro_rules! get_htlc_output {
806+
($htlc: expr, $offered: expr) => {
807+
HTLCOutputInCommitment{
808+
offered: $offered,
809+
amount_msat: $htlc.amount_msat,
810+
cltv_expiry: $htlc.cltv_expiry,
811+
payment_hash: $htlc.payment_hash,
812+
transaction_output_index: None
813+
}
814+
}
815+
}
816+
let inbound_local_outputs = self.pending_inbound_htlcs.iter()
817+
.map(|htlc| get_htlc_output!(htlc, false));
818+
819+
let outbound_local_outputs = self.pending_outbound_htlcs.iter()
820+
.filter_map(|htlc| {
821+
match htlc.state {
822+
OutboundHTLCState::AwaitingRemovedRemoteRevoke(_) => None,
823+
_ => Some(get_htlc_output!(htlc, true))
824+
}
825+
});
826+
let awaiting_raa = (self.channel_state & ChannelState::AwaitingRemoteRevoke as u32) != 0;
827+
let inbound_remote_outputs = self.pending_inbound_htlcs.iter()
828+
.filter_map(|htlc| {
829+
match htlc.state {
830+
InboundHTLCState::LocalRemoved(_) => {
831+
if awaiting_raa {
832+
Some(get_htlc_output!(htlc, true))
833+
} else { None }
834+
},
835+
InboundHTLCState::AwaitingRemoteRevokeToAnnounce(_) => None,
836+
InboundHTLCState::RemoteRemoved => None,
837+
_ => Some(get_htlc_output!(htlc, true))
838+
}
839+
});
840+
let outbound_remote_outputs = self.pending_outbound_htlcs.iter()
841+
.filter_map(|htlc| {
842+
match htlc.state {
843+
OutboundHTLCState::AwaitingRemovedRemoteRevoke(_) => {
844+
if awaiting_raa {
845+
Some(get_htlc_output!(htlc, false))
846+
} else { None }
847+
},
848+
_ => Some(get_htlc_output!(htlc, false))
849+
}
850+
});
851+
852+
ChannelMonitor::<ChanSigner>::would_broadcast_at_height_given_htlcs(inbound_local_outputs.chain(outbound_local_outputs), inbound_remote_outputs.chain(outbound_remote_outputs), height, &self.payment_preimages, logger)
853+
}
854+
798855
// Utilities to build transactions:
799856

800857
fn get_commitment_transaction_number_obscure_factor(&self) -> u64 {
@@ -909,6 +966,7 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
909966
InboundHTLCState::AwaitingAnnouncedRemoteRevoke(_) => (true, "AwaitingAnnouncedRemoteRevoke"),
910967
InboundHTLCState::Committed => (true, "Committed"),
911968
InboundHTLCState::LocalRemoved(_) => (!generated_by_local, "LocalRemoved"),
969+
InboundHTLCState::RemoteRemoved => (false, "RemoteRemoved"),
912970
};
913971

914972
if include {
@@ -1216,6 +1274,7 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
12161274
// We have to put the payment_preimage in the channel_monitor right away here to ensure we
12171275
// can claim it even if the channel hits the chain before we see their next commitment.
12181276
self.latest_monitor_update_id += 1;
1277+
self.payment_preimages.insert(payment_hash_calc, payment_preimage_arg.clone());
12191278
let monitor_update = ChannelMonitorUpdate {
12201279
update_id: self.latest_monitor_update_id,
12211280
updates: vec![ChannelMonitorUpdateStep::PaymentPreimage {
@@ -2011,6 +2070,23 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
20112070
return Err((None, ChannelError::Close(format!("Got wrong number of HTLC signatures ({}) from remote. It must be {}", msg.htlc_signatures.len(), local_commitment_tx.1))));
20122071
}
20132072

2073+
{
2074+
2075+
let pending_inbound_htlcs: &mut Vec<_> = &mut self.pending_inbound_htlcs;
2076+
let payment_preimages: &mut HashMap<_, _> = &mut self.payment_preimages;
2077+
// A RemoteRemoved HTLC need to be monitored for expiration until we receive a
2078+
// broadcastable commitment tx without said HTLC. Now that we've confirmed that
2079+
// this commitment signed message provides said commitment tx, we can drop the
2080+
// RemoteRemoved HTLCs we were previously watching for.
2081+
pending_inbound_htlcs.retain(|htlc| {
2082+
log_trace!(logger, "Removing inbound RemovedRemoved {}", log_bytes!(htlc.payment_hash.0));
2083+
if let &InboundHTLCState::RemoteRemoved = &htlc.state {
2084+
payment_preimages.remove(&htlc.payment_hash);
2085+
false
2086+
} else { true }
2087+
});
2088+
}
2089+
20142090
// TODO: Merge these two, sadly they are currently both required to be passed separately to
20152091
// ChannelMonitor:
20162092
let mut htlcs_without_source = Vec::with_capacity(local_commitment_tx.2.len());
@@ -2303,30 +2379,20 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
23032379
// Take references explicitly so that we can hold multiple references to self.
23042380
let pending_inbound_htlcs: &mut Vec<_> = &mut self.pending_inbound_htlcs;
23052381
let pending_outbound_htlcs: &mut Vec<_> = &mut self.pending_outbound_htlcs;
2306-
2307-
// We really shouldnt have two passes here, but retain gives a non-mutable ref (Rust bug)
2308-
pending_inbound_htlcs.retain(|htlc| {
2382+
let payment_preimages: &mut HashMap<_, _> = &mut self.payment_preimages;
2383+
for htlc in pending_inbound_htlcs.iter_mut() {
2384+
let mut is_local_removed = false;
23092385
if let &InboundHTLCState::LocalRemoved(ref reason) = &htlc.state {
2310-
log_trace!(logger, " ...removing inbound LocalRemoved {}", log_bytes!(htlc.payment_hash.0));
23112386
if let &InboundHTLCRemovalReason::Fulfill(_) = reason {
23122387
value_to_self_msat_diff += htlc.amount_msat as i64;
23132388
}
2314-
false
2315-
} else { true }
2316-
});
2317-
pending_outbound_htlcs.retain(|htlc| {
2318-
if let &OutboundHTLCState::AwaitingRemovedRemoteRevoke(ref fail_reason) = &htlc.state {
2319-
log_trace!(logger, " ...removing outbound AwaitingRemovedRemoteRevoke {}", log_bytes!(htlc.payment_hash.0));
2320-
if let Some(reason) = fail_reason.clone() { // We really want take() here, but, again, non-mut ref :(
2321-
revoked_htlcs.push((htlc.source.clone(), htlc.payment_hash, reason));
2322-
} else {
2323-
// They fulfilled, so we sent them money
2324-
value_to_self_msat_diff -= htlc.amount_msat as i64;
2325-
}
2326-
false
2327-
} else { true }
2328-
});
2329-
for htlc in pending_inbound_htlcs.iter_mut() {
2389+
is_local_removed = true;
2390+
}
2391+
if is_local_removed {
2392+
let mut state = InboundHTLCState::RemoteRemoved;
2393+
mem::swap(&mut state, &mut htlc.state);
2394+
continue
2395+
}
23302396
let swap = if let &InboundHTLCState::AwaitingRemoteRevokeToAnnounce(_) = &htlc.state {
23312397
log_trace!(logger, " ...promoting inbound AwaitingRemoteRevokeToAnnounce {} to Committed", log_bytes!(htlc.payment_hash.0));
23322398
true
@@ -2364,6 +2430,20 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
23642430
}
23652431
}
23662432
}
2433+
// We really shouldnt have two passes here, but retain gives a non-mutable ref (Rust bug)
2434+
pending_outbound_htlcs.retain(|htlc| {
2435+
if let &OutboundHTLCState::AwaitingRemovedRemoteRevoke(ref fail_reason) = &htlc.state {
2436+
log_trace!(logger, " ...removing outbound AwaitingRemovedRemoteRevoke {}", log_bytes!(htlc.payment_hash.0));
2437+
if let Some(reason) = fail_reason.clone() { // We really want take() here, but, again, non-mut ref :(
2438+
revoked_htlcs.push((htlc.source.clone(), htlc.payment_hash, reason));
2439+
} else {
2440+
// They fulfilled, so we sent them money
2441+
value_to_self_msat_diff -= htlc.amount_msat as i64;
2442+
}
2443+
payment_preimages.remove(&htlc.payment_hash);
2444+
false
2445+
} else { true }
2446+
});
23672447
for htlc in pending_outbound_htlcs.iter_mut() {
23682448
if let OutboundHTLCState::LocalAnnounced(_) = htlc.state {
23692449
log_trace!(logger, " ...promoting outbound LocalAnnounced {} to Committed", log_bytes!(htlc.payment_hash.0));
@@ -2540,6 +2620,7 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
25402620
// the commitment_signed we can re-transmit the update then.
25412621
true
25422622
},
2623+
InboundHTLCState::RemoteRemoved => true,
25432624
}
25442625
});
25452626
self.next_remote_htlc_id -= inbound_drop_count;
@@ -3115,14 +3196,6 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
31153196
self.user_id
31163197
}
31173198

3118-
/// May only be called after funding has been initiated (ie is_funding_initiated() is true)
3119-
pub fn channel_monitor(&mut self) -> &mut ChannelMonitor<ChanSigner> {
3120-
if self.channel_state < ChannelState::FundingSent as u32 {
3121-
panic!("Can't get a channel monitor until funding has been created");
3122-
}
3123-
self.channel_monitor.as_mut().unwrap()
3124-
}
3125-
31263199
/// Guaranteed to be Some after both FundingLocked messages have been exchanged (and, thus,
31273200
/// is_usable() returns true).
31283201
/// Allowed in any state (including after shutdown)
@@ -4118,6 +4191,9 @@ impl<ChanSigner: ChannelKeys + Writeable> Writeable for Channel<ChanSigner> {
41184191
4u8.write(writer)?;
41194192
removal_reason.write(writer)?;
41204193
},
4194+
&InboundHTLCState::RemoteRemoved => {
4195+
5u8.write(writer)?;
4196+
}
41214197
}
41224198
}
41234199

@@ -4151,6 +4227,11 @@ impl<ChanSigner: ChannelKeys + Writeable> Writeable for Channel<ChanSigner> {
41514227
}
41524228
}
41534229

4230+
writer.write_all(&byte_utils::be64_to_array(self.payment_preimages.len() as u64))?;
4231+
for payment_preimage in self.payment_preimages.values() {
4232+
writer.write_all(&payment_preimage.0[..])?;
4233+
}
4234+
41544235
(self.holding_cell_htlc_updates.len() as u64).write(writer)?;
41554236
for update in self.holding_cell_htlc_updates.iter() {
41564237
match update {
@@ -4248,6 +4329,8 @@ impl<ChanSigner: ChannelKeys + Writeable> Writeable for Channel<ChanSigner> {
42484329
}
42494330
}
42504331

4332+
const MAX_ALLOC_SIZE: usize = 64*1024;
4333+
42514334
impl<ChanSigner: ChannelKeys + Readable> Readable for Channel<ChanSigner> {
42524335
fn read<R : ::std::io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
42534336
let _ver: u8 = Readable::read(reader)?;
@@ -4287,6 +4370,7 @@ impl<ChanSigner: ChannelKeys + Readable> Readable for Channel<ChanSigner> {
42874370
2 => InboundHTLCState::AwaitingAnnouncedRemoteRevoke(Readable::read(reader)?),
42884371
3 => InboundHTLCState::Committed,
42894372
4 => InboundHTLCState::LocalRemoved(Readable::read(reader)?),
4373+
5 => InboundHTLCState::RemoteRemoved,
42904374
_ => return Err(DecodeError::InvalidValue),
42914375
},
42924376
});
@@ -4312,6 +4396,16 @@ impl<ChanSigner: ChannelKeys + Readable> Readable for Channel<ChanSigner> {
43124396
});
43134397
}
43144398

4399+
let payment_preimages_len: u64 = Readable::read(reader)?;
4400+
let mut payment_preimages = HashMap::with_capacity(cmp::min(payment_preimages_len as usize, MAX_ALLOC_SIZE / 32));
4401+
for _ in 0..payment_preimages_len {
4402+
let preimage: PaymentPreimage = Readable::read(reader)?;
4403+
let hash = PaymentHash(Sha256::hash(&preimage.0[..]).into_inner());
4404+
if let Some(_) = payment_preimages.insert(hash, preimage) {
4405+
return Err(DecodeError::InvalidValue);
4406+
}
4407+
}
4408+
43154409
let holding_cell_htlc_update_count: u64 = Readable::read(reader)?;
43164410
let mut holding_cell_htlc_updates = Vec::with_capacity(cmp::min(holding_cell_htlc_update_count as usize, OUR_MAX_HTLCS as usize*2));
43174411
for _ in 0..holding_cell_htlc_update_count {
@@ -4428,6 +4522,7 @@ impl<ChanSigner: ChannelKeys + Readable> Readable for Channel<ChanSigner> {
44284522
pending_inbound_htlcs,
44294523
pending_outbound_htlcs,
44304524
holding_cell_htlc_updates,
4525+
payment_preimages,
44314526

44324527
resend_order,
44334528

lightning/src/ln/channelmanager.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3104,7 +3104,7 @@ impl<ChanSigner: ChannelKeys, M: Deref + Sync + Send, T: Deref + Sync + Send, K:
31043104
}
31053105
}
31063106
}
3107-
if channel.is_funding_initiated() && channel.channel_monitor().would_broadcast_at_height(height, &self.logger) {
3107+
if channel.is_funding_initiated() && channel.monitor_would_broadcast_at_height(height, &self.logger) {
31083108
if let Some(short_id) = channel.get_short_channel_id() {
31093109
short_to_id.remove(&short_id);
31103110
}

0 commit comments

Comments
 (0)