Skip to content

Commit 6b693e6

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 d735a24 commit 6b693e6

File tree

3 files changed

+164
-64
lines changed

3 files changed

+164
-64
lines changed

lightning/src/ln/channel.rs

Lines changed: 137 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ use ln::chan_utils;
2424
use chain::chaininterface::{FeeEstimator,ConfirmationTarget};
2525
use chain::transaction::OutPoint;
2626
use chain::keysinterface::{ChannelKeys, KeysInterface};
27-
use util::transaction_utils;
27+
use util::{byte_utils, transaction_utils};
2828
use util::ser::{Readable, Writeable, Writer};
2929
use util::logger::Logger;
3030
use util::errors::APIError;
@@ -34,6 +34,7 @@ use std;
3434
use std::default::Default;
3535
use std::{cmp,mem,fmt};
3636
use std::ops::Deref;
37+
use std::collections::HashMap;
3738
use bitcoin::hashes::hex::ToHex;
3839

3940
#[cfg(test)]
@@ -100,11 +101,8 @@ enum InboundHTLCState {
100101
/// Note that we have to keep an eye on the HTLC until we've received a broadcastable
101102
/// commitment transaction without it as otherwise we'll have to force-close the channel to
102103
/// claim it before the timeout (obviously doesn't apply to revoked HTLCs that we can't claim
103-
/// anyway). That said, ChannelMonitor does this for us (see
104-
/// ChannelMonitor::would_broadcast_at_height) so we actually remove the HTLC from our own
105-
/// local state before then, once we're sure that the next commitment_signed and
106-
/// ChannelMonitor::provide_latest_local_commitment_tx_info will not include this HTLC.
107-
LocalRemoved(InboundHTLCRemovalReason),
104+
/// anyway).
105+
LocalRemoved(bool, InboundHTLCRemovalReason),
108106
}
109107

110108
struct InboundHTLCOutput {
@@ -284,6 +282,7 @@ pub(super) struct Channel<ChanSigner: ChannelKeys> {
284282
pending_inbound_htlcs: Vec<InboundHTLCOutput>,
285283
pending_outbound_htlcs: Vec<OutboundHTLCOutput>,
286284
holding_cell_htlc_updates: Vec<HTLCUpdateAwaitingACK>,
285+
payment_preimages: HashMap<PaymentHash, PaymentPreimage>,
287286

288287
/// When resending CS/RAA messages on channel monitor restoration or on reconnect, we always
289288
/// need to ensure we resend them in the order we originally generated them. Note that because
@@ -501,6 +500,7 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
501500
pending_inbound_htlcs: Vec::new(),
502501
pending_outbound_htlcs: Vec::new(),
503502
holding_cell_htlc_updates: Vec::new(),
503+
payment_preimages: HashMap::new(),
504504
pending_update_fee: None,
505505
holding_cell_update_fee: None,
506506
next_local_htlc_id: 0,
@@ -729,6 +729,7 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
729729
pending_inbound_htlcs: Vec::new(),
730730
pending_outbound_htlcs: Vec::new(),
731731
holding_cell_htlc_updates: Vec::new(),
732+
payment_preimages: HashMap::new(),
732733
pending_update_fee: None,
733734
holding_cell_update_fee: None,
734735
next_local_htlc_id: 0,
@@ -786,6 +787,71 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
786787
Ok(chan)
787788
}
788789

790+
pub(super) fn monitor_would_broadcast_at_height<L: Deref>(&self, height: u32, logger: &L) -> bool where L::Target: Logger {
791+
macro_rules! add_htlc_output {
792+
($htlc: expr, $offered: expr, $list: expr) => {
793+
$list.push(HTLCOutputInCommitment{
794+
offered: $offered,
795+
amount_msat: $htlc.amount_msat,
796+
cltv_expiry: $htlc.cltv_expiry,
797+
payment_hash: $htlc.payment_hash,
798+
transaction_output_index: None
799+
});
800+
}
801+
}
802+
803+
let cap = self.pending_inbound_htlcs.len() + self.pending_outbound_htlcs.len();
804+
let mut remote_outputs = Vec::with_capacity(cap);
805+
let mut local_outputs = Vec::with_capacity(cap);
806+
let awaiting_raa = (self.channel_state & ChannelState::AwaitingRemoteRevoke as u32) != 0;
807+
for ref htlc in self.pending_inbound_htlcs.iter() {
808+
match htlc.state {
809+
InboundHTLCState::AwaitingAnnouncedRemoteRevoke(_) => {
810+
add_htlc_output!(htlc, false, local_outputs);
811+
add_htlc_output!(htlc, true, remote_outputs);
812+
},
813+
InboundHTLCState::Committed => {
814+
add_htlc_output!(htlc, false, local_outputs);
815+
add_htlc_output!(htlc, true, remote_outputs);
816+
},
817+
InboundHTLCState::LocalRemoved(revoked, _) => {
818+
add_htlc_output!(htlc, false, local_outputs);
819+
if awaiting_raa && !revoked {
820+
add_htlc_output!(htlc, true, remote_outputs)
821+
}
822+
},
823+
_ => {},
824+
}
825+
}
826+
for ref htlc in self.pending_outbound_htlcs.iter() {
827+
match htlc.state {
828+
OutboundHTLCState::LocalAnnounced(_) => {
829+
add_htlc_output!(htlc, true, local_outputs);
830+
add_htlc_output!(htlc, false, remote_outputs);
831+
},
832+
OutboundHTLCState::Committed => {
833+
add_htlc_output!(htlc, true, local_outputs);
834+
add_htlc_output!(htlc, false, remote_outputs);
835+
},
836+
OutboundHTLCState::RemoteRemoved(_) => {
837+
add_htlc_output!(htlc, true, local_outputs);
838+
add_htlc_output!(htlc, false, remote_outputs)
839+
},
840+
OutboundHTLCState::AwaitingRemoteRevokeToRemove(_) => {
841+
add_htlc_output!(htlc, true, local_outputs);
842+
add_htlc_output!(htlc, false, remote_outputs);
843+
},
844+
OutboundHTLCState::AwaitingRemovedRemoteRevoke(_) => {
845+
if awaiting_raa {
846+
add_htlc_output!(htlc, false, remote_outputs)
847+
}
848+
},
849+
}
850+
}
851+
852+
ChannelMonitor::<ChanSigner>::would_broadcast_at_height_given_htlcs(local_outputs.iter(), remote_outputs.iter(), height, &self.payment_preimages, logger)
853+
}
854+
789855
// Utilities to build transactions:
790856

791857
fn get_commitment_transaction_number_obscure_factor(&self) -> u64 {
@@ -899,7 +965,7 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
899965
InboundHTLCState::AwaitingRemoteRevokeToAnnounce(_) => (!generated_by_local, "AwaitingRemoteRevokeToAnnounce"),
900966
InboundHTLCState::AwaitingAnnouncedRemoteRevoke(_) => (true, "AwaitingAnnouncedRemoteRevoke"),
901967
InboundHTLCState::Committed => (true, "Committed"),
902-
InboundHTLCState::LocalRemoved(_) => (!generated_by_local, "LocalRemoved"),
968+
InboundHTLCState::LocalRemoved(revoked, _) => (!generated_by_local && !revoked, "LocalRemoved"),
903969
};
904970

905971
if include {
@@ -908,7 +974,7 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
908974
} else {
909975
log_trace!(logger, " ...not including inbound HTLC {} (hash {}) with value {} due to state ({})", htlc.htlc_id, log_bytes!(htlc.payment_hash.0), htlc.amount_msat, state_name);
910976
match &htlc.state {
911-
&InboundHTLCState::LocalRemoved(ref reason) => {
977+
&InboundHTLCState::LocalRemoved(false, ref reason) => {
912978
if generated_by_local {
913979
if let &InboundHTLCRemovalReason::Fulfill(_) = reason {
914980
value_to_self_msat_offset += htlc.amount_msat as i64;
@@ -1181,7 +1247,7 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
11811247
assert_eq!(htlc.payment_hash, payment_hash_calc);
11821248
match htlc.state {
11831249
InboundHTLCState::Committed => {},
1184-
InboundHTLCState::LocalRemoved(ref reason) => {
1250+
InboundHTLCState::LocalRemoved(_, ref reason) => {
11851251
if let &InboundHTLCRemovalReason::Fulfill(_) = reason {
11861252
} else {
11871253
log_warn!(logger, "Have preimage and want to fulfill HTLC with payment hash {} we already failed against channel {}", log_bytes!(htlc.payment_hash.0), log_bytes!(self.channel_id()));
@@ -1207,6 +1273,7 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
12071273
// We have to put the payment_preimage in the channel_monitor right away here to ensure we
12081274
// can claim it even if the channel hits the chain before we see their next commitment.
12091275
self.latest_monitor_update_id += 1;
1276+
self.payment_preimages.insert(payment_hash_calc, payment_preimage_arg.clone());
12101277
let monitor_update = ChannelMonitorUpdate {
12111278
update_id: self.latest_monitor_update_id,
12121279
updates: vec![ChannelMonitorUpdateStep::PaymentPreimage {
@@ -1253,7 +1320,7 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
12531320
return Ok((None, Some(monitor_update)));
12541321
}
12551322
log_trace!(logger, "Upgrading HTLC {} to LocalRemoved with a Fulfill!", log_bytes!(htlc.payment_hash.0));
1256-
htlc.state = InboundHTLCState::LocalRemoved(InboundHTLCRemovalReason::Fulfill(payment_preimage_arg.clone()));
1323+
htlc.state = InboundHTLCState::LocalRemoved(false, InboundHTLCRemovalReason::Fulfill(payment_preimage_arg.clone()));
12571324
}
12581325

12591326
Ok((Some(msgs::UpdateFulfillHTLC {
@@ -1303,7 +1370,7 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
13031370
if htlc.htlc_id == htlc_id_arg {
13041371
match htlc.state {
13051372
InboundHTLCState::Committed => {},
1306-
InboundHTLCState::LocalRemoved(_) => {
1373+
InboundHTLCState::LocalRemoved(_, _) => {
13071374
debug_assert!(false, "Tried to fail an HTLC that was already fail/fulfilled");
13081375
return Ok(None);
13091376
},
@@ -1347,7 +1414,7 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
13471414

13481415
{
13491416
let htlc = &mut self.pending_inbound_htlcs[pending_idx];
1350-
htlc.state = InboundHTLCState::LocalRemoved(InboundHTLCRemovalReason::FailRelay(err_packet.clone()));
1417+
htlc.state = InboundHTLCState::LocalRemoved(false, InboundHTLCRemovalReason::FailRelay(err_packet.clone()));
13511418
}
13521419

13531420
Ok(Some(msgs::UpdateFailHTLC {
@@ -2001,6 +2068,17 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
20012068
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))));
20022069
}
20032070

2071+
// A LocalRemoved HTLC need to be monitored for expiration until we receive a
2072+
// broadcastable commitment tx without said HTLC. Now that we've confirmed that
2073+
// this commitment signed message provides said commitment tx, we can drop the
2074+
// LocalRemoved HTLCs we were previously watching for.
2075+
self.pending_inbound_htlcs.retain(|htlc| {
2076+
log_trace!(logger, "Removing inbound LocalRemoved {}", log_bytes!(htlc.payment_hash.0));
2077+
if let &InboundHTLCState::LocalRemoved(true, _) = &htlc.state {
2078+
false
2079+
} else { true }
2080+
});
2081+
20042082
// TODO: Merge these two, sadly they are currently both required to be passed separately to
20052083
// ChannelMonitor:
20062084
let mut htlcs_without_source = Vec::with_capacity(local_commitment_tx.2.len());
@@ -2309,30 +2387,16 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
23092387
// Take references explicitly so that we can hold multiple references to self.
23102388
let pending_inbound_htlcs: &mut Vec<_> = &mut self.pending_inbound_htlcs;
23112389
let pending_outbound_htlcs: &mut Vec<_> = &mut self.pending_outbound_htlcs;
2312-
2313-
// We really shouldnt have two passes here, but retain gives a non-mutable ref (Rust bug)
2314-
pending_inbound_htlcs.retain(|htlc| {
2315-
if let &InboundHTLCState::LocalRemoved(ref reason) = &htlc.state {
2316-
log_trace!(logger, " ...removing inbound LocalRemoved {}", log_bytes!(htlc.payment_hash.0));
2390+
for htlc in pending_inbound_htlcs.iter_mut() {
2391+
if let &mut InboundHTLCState::LocalRemoved(ref mut revoked, ref reason) = &mut htlc.state {
23172392
if let &InboundHTLCRemovalReason::Fulfill(_) = reason {
2318-
value_to_self_msat_diff += htlc.amount_msat as i64;
2319-
}
2320-
false
2321-
} else { true }
2322-
});
2323-
pending_outbound_htlcs.retain(|htlc| {
2324-
if let &OutboundHTLCState::AwaitingRemovedRemoteRevoke(ref fail_reason) = &htlc.state {
2325-
log_trace!(logger, " ...removing outbound AwaitingRemovedRemoteRevoke {}", log_bytes!(htlc.payment_hash.0));
2326-
if let Some(reason) = fail_reason.clone() { // We really want take() here, but, again, non-mut ref :(
2327-
revoked_htlcs.push((htlc.source.clone(), htlc.payment_hash, reason));
2328-
} else {
2329-
// They fulfilled, so we sent them money
2330-
value_to_self_msat_diff -= htlc.amount_msat as i64;
2393+
if !*revoked {
2394+
value_to_self_msat_diff += htlc.amount_msat as i64;
2395+
}
23312396
}
2332-
false
2333-
} else { true }
2334-
});
2335-
for htlc in pending_inbound_htlcs.iter_mut() {
2397+
*revoked = true;
2398+
continue
2399+
}
23362400
let swap = if let &InboundHTLCState::AwaitingRemoteRevokeToAnnounce(_) = &htlc.state {
23372401
log_trace!(logger, " ...promoting inbound AwaitingRemoteRevokeToAnnounce {} to Committed", log_bytes!(htlc.payment_hash.0));
23382402
true
@@ -2353,11 +2417,11 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
23532417
require_commitment = true;
23542418
match fail_msg {
23552419
HTLCFailureMsg::Relay(msg) => {
2356-
htlc.state = InboundHTLCState::LocalRemoved(InboundHTLCRemovalReason::FailRelay(msg.reason.clone()));
2420+
htlc.state = InboundHTLCState::LocalRemoved(false, InboundHTLCRemovalReason::FailRelay(msg.reason.clone()));
23572421
update_fail_htlcs.push(msg)
23582422
},
23592423
HTLCFailureMsg::Malformed(msg) => {
2360-
htlc.state = InboundHTLCState::LocalRemoved(InboundHTLCRemovalReason::FailMalformed((msg.sha256_of_onion, msg.failure_code)));
2424+
htlc.state = InboundHTLCState::LocalRemoved(false, InboundHTLCRemovalReason::FailMalformed((msg.sha256_of_onion, msg.failure_code)));
23612425
update_fail_malformed_htlcs.push(msg)
23622426
},
23632427
}
@@ -2370,6 +2434,19 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
23702434
}
23712435
}
23722436
}
2437+
// We really shouldnt have two passes here, but retain gives a non-mutable ref (Rust bug)
2438+
pending_outbound_htlcs.retain(|htlc| {
2439+
if let &OutboundHTLCState::AwaitingRemovedRemoteRevoke(ref fail_reason) = &htlc.state {
2440+
log_trace!(logger, " ...removing outbound AwaitingRemovedRemoteRevoke {}", log_bytes!(htlc.payment_hash.0));
2441+
if let Some(reason) = fail_reason.clone() { // We really want take() here, but, again, non-mut ref :(
2442+
revoked_htlcs.push((htlc.source.clone(), htlc.payment_hash, reason));
2443+
} else {
2444+
// They fulfilled, so we sent them money
2445+
value_to_self_msat_diff -= htlc.amount_msat as i64;
2446+
}
2447+
false
2448+
} else { true }
2449+
});
23732450
for htlc in pending_outbound_htlcs.iter_mut() {
23742451
if let OutboundHTLCState::LocalAnnounced(_) = htlc.state {
23752452
log_trace!(logger, " ...promoting outbound LocalAnnounced {} to Committed", log_bytes!(htlc.payment_hash.0));
@@ -2539,7 +2616,7 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
25392616
true
25402617
},
25412618
InboundHTLCState::Committed => true,
2542-
InboundHTLCState::LocalRemoved(_) => {
2619+
InboundHTLCState::LocalRemoved(_, _) => {
25432620
// We (hopefully) sent a commitment_signed updating this HTLC (which we can
25442621
// re-transmit if needed) and they may have even sent a revoke_and_ack back
25452622
// (that we missed). Keep this around for now and if they tell us they missed
@@ -2689,7 +2766,7 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
26892766
}
26902767

26912768
for htlc in self.pending_inbound_htlcs.iter() {
2692-
if let &InboundHTLCState::LocalRemoved(ref reason) = &htlc.state {
2769+
if let &InboundHTLCState::LocalRemoved(false, ref reason) = &htlc.state {
26932770
match reason {
26942771
&InboundHTLCRemovalReason::FailRelay(ref err_packet) => {
26952772
update_fail_htlcs.push(msgs::UpdateFailHTLC {
@@ -3098,14 +3175,6 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
30983175
self.user_id
30993176
}
31003177

3101-
/// May only be called after funding has been initiated (ie is_funding_initiated() is true)
3102-
pub fn channel_monitor(&mut self) -> &mut ChannelMonitor<ChanSigner> {
3103-
if self.channel_state < ChannelState::FundingSent as u32 {
3104-
panic!("Can't get a channel monitor until funding has been created");
3105-
}
3106-
self.channel_monitor.as_mut().unwrap()
3107-
}
3108-
31093178
/// Guaranteed to be Some after both FundingLocked messages have been exchanged (and, thus,
31103179
/// is_usable() returns true).
31113180
/// Allowed in any state (including after shutdown)
@@ -3801,7 +3870,7 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
38013870
if have_updates { break; }
38023871
}
38033872
for htlc in self.pending_inbound_htlcs.iter() {
3804-
if let InboundHTLCState::LocalRemoved(_) = htlc.state {
3873+
if let InboundHTLCState::LocalRemoved(false, _) = htlc.state {
38053874
have_updates = true;
38063875
}
38073876
if have_updates { break; }
@@ -4094,8 +4163,9 @@ impl<ChanSigner: ChannelKeys + Writeable> Writeable for Channel<ChanSigner> {
40944163
&InboundHTLCState::Committed => {
40954164
3u8.write(writer)?;
40964165
},
4097-
&InboundHTLCState::LocalRemoved(ref removal_reason) => {
4166+
&InboundHTLCState::LocalRemoved(ref revoked, ref removal_reason) => {
40984167
4u8.write(writer)?;
4168+
revoked.write(writer)?;
40994169
removal_reason.write(writer)?;
41004170
},
41014171
}
@@ -4131,6 +4201,11 @@ impl<ChanSigner: ChannelKeys + Writeable> Writeable for Channel<ChanSigner> {
41314201
}
41324202
}
41334203

4204+
writer.write_all(&byte_utils::be64_to_array(self.payment_preimages.len() as u64))?;
4205+
for payment_preimage in self.payment_preimages.values() {
4206+
writer.write_all(&payment_preimage.0[..])?;
4207+
}
4208+
41344209
(self.holding_cell_htlc_updates.len() as u64).write(writer)?;
41354210
for update in self.holding_cell_htlc_updates.iter() {
41364211
match update {
@@ -4228,6 +4303,8 @@ impl<ChanSigner: ChannelKeys + Writeable> Writeable for Channel<ChanSigner> {
42284303
}
42294304
}
42304305

4306+
const MAX_ALLOC_SIZE: usize = 64*1024;
4307+
42314308
impl<ChanSigner: ChannelKeys + Readable> Readable for Channel<ChanSigner> {
42324309
fn read<R : ::std::io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
42334310
let _ver: u8 = Readable::read(reader)?;
@@ -4266,7 +4343,7 @@ impl<ChanSigner: ChannelKeys + Readable> Readable for Channel<ChanSigner> {
42664343
1 => InboundHTLCState::AwaitingRemoteRevokeToAnnounce(Readable::read(reader)?),
42674344
2 => InboundHTLCState::AwaitingAnnouncedRemoteRevoke(Readable::read(reader)?),
42684345
3 => InboundHTLCState::Committed,
4269-
4 => InboundHTLCState::LocalRemoved(Readable::read(reader)?),
4346+
4 => InboundHTLCState::LocalRemoved(Readable::read(reader)?, Readable::read(reader)?),
42704347
_ => return Err(DecodeError::InvalidValue),
42714348
},
42724349
});
@@ -4292,6 +4369,16 @@ impl<ChanSigner: ChannelKeys + Readable> Readable for Channel<ChanSigner> {
42924369
});
42934370
}
42944371

4372+
let payment_preimages_len: u64 = Readable::read(reader)?;
4373+
let mut payment_preimages = HashMap::with_capacity(cmp::min(payment_preimages_len as usize, MAX_ALLOC_SIZE / 32));
4374+
for _ in 0..payment_preimages_len {
4375+
let preimage: PaymentPreimage = Readable::read(reader)?;
4376+
let hash = PaymentHash(Sha256::hash(&preimage.0[..]).into_inner());
4377+
if let Some(_) = payment_preimages.insert(hash, preimage) {
4378+
return Err(DecodeError::InvalidValue);
4379+
}
4380+
}
4381+
42954382
let holding_cell_htlc_update_count: u64 = Readable::read(reader)?;
42964383
let mut holding_cell_htlc_updates = Vec::with_capacity(cmp::min(holding_cell_htlc_update_count as usize, OUR_MAX_HTLCS as usize*2));
42974384
for _ in 0..holding_cell_htlc_update_count {
@@ -4408,6 +4495,7 @@ impl<ChanSigner: ChannelKeys + Readable> Readable for Channel<ChanSigner> {
44084495
pending_inbound_htlcs,
44094496
pending_outbound_htlcs,
44104497
holding_cell_htlc_updates,
4498+
payment_preimages,
44114499

44124500
resend_order,
44134501

lightning/src/ln/channelmanager.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3044,7 +3044,7 @@ impl<ChanSigner: ChannelKeys, M: Deref + Sync + Send, T: Deref + Sync + Send, K:
30443044
}
30453045
}
30463046
}
3047-
if channel.is_funding_initiated() && channel.channel_monitor().would_broadcast_at_height(height, &self.logger) {
3047+
if channel.is_funding_initiated() && channel.monitor_would_broadcast_at_height(height, &self.logger) {
30483048
if let Some(short_id) = channel.get_short_channel_id() {
30493049
short_to_id.remove(&short_id);
30503050
}

0 commit comments

Comments
 (0)