Skip to content

Commit c5433aa

Browse files
committed
Add method to note transaction unconfirmed/reorged-out
1 parent e23c270 commit c5433aa

File tree

2 files changed

+68
-24
lines changed

2 files changed

+68
-24
lines changed

lightning/src/ln/channel.rs

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -377,7 +377,7 @@ pub(super) struct Channel<Signer: Sign> {
377377

378378
/// The hash of the block in which the funding transaction was included.
379379
funding_tx_confirmed_in: Option<BlockHash>,
380-
funding_tx_confirmation_height: u64,
380+
funding_tx_confirmation_height: u32,
381381
short_channel_id: Option<u64>,
382382

383383
counterparty_dust_limit_satoshis: u64,
@@ -3588,7 +3588,7 @@ impl<Signer: Sign> Channel<Signer> {
35883588
}
35893589
}
35903590
}
3591-
self.funding_tx_confirmation_height = height as u64;
3591+
self.funding_tx_confirmation_height = height;
35923592
self.funding_tx_confirmed_in = Some(*block_hash);
35933593
self.short_channel_id = match scid_from_parts(height as u64, index_in_block as u64, txo_idx as u64) {
35943594
Ok(scid) => Some(scid),
@@ -3675,6 +3675,24 @@ impl<Signer: Sign> Channel<Signer> {
36753675
Ok((None, timed_out_htlcs))
36763676
}
36773677

3678+
pub fn funding_transaction_unconfirmed(&mut self) -> Result<(), msgs::ErrorMessage> {
3679+
if self.funding_tx_confirmation_height != 0 {
3680+
let effective_new_height = self.funding_tx_confirmation_height - 1;
3681+
let best_time = self.update_time_counter;
3682+
match self.update_best_block(effective_new_height, best_time) {
3683+
Ok((funding_locked, timed_out_htlcs)) => {
3684+
assert!(funding_locked.is_none(), "We can't generate a funding with 0 confirmations?");
3685+
assert!(timed_out_htlcs.is_empty(), "We can't have accepted HTLCs with a timeout before our funding confirmation?");
3686+
Ok(())
3687+
},
3688+
Err(e) => Err(e)
3689+
}
3690+
} else {
3691+
// We never learned about the funding confirmation anyway, just ignore
3692+
Ok(())
3693+
}
3694+
}
3695+
36783696
// Methods to get unprompted messages to send to the remote end (or where we already returned
36793697
// something in the handler for the message that prompted this message):
36803698

lightning/src/ln/channelmanager.rs

Lines changed: 48 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ use bitcoin::hashes::hmac::{Hmac, HmacEngine};
2727
use bitcoin::hashes::sha256::Hash as Sha256;
2828
use bitcoin::hashes::sha256d::Hash as Sha256dHash;
2929
use bitcoin::hashes::cmp::fixed_time_eq;
30-
use bitcoin::hash_types::BlockHash;
30+
use bitcoin::hash_types::{BlockHash, Txid};
3131

3232
use bitcoin::secp256k1::key::{SecretKey,PublicKey};
3333
use bitcoin::secp256k1::Secp256k1;
@@ -3314,7 +3314,7 @@ where
33143314
"Blocks must be disconnected in chain-order - the disconnected block must have the correct height");
33153315
*self.last_block_hash.write().unwrap() = header.prev_blockhash;
33163316

3317-
self.do_chain_event(new_height, |channel| channel.update_best_block(new_height, header.time));
3317+
self.do_chain_event(Some(new_height), |channel| channel.update_best_block(new_height, header.time));
33183318
}
33193319
}
33203320

@@ -3326,7 +3326,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
33263326
L::Target: Logger,
33273327
{
33283328
fn do_chain_event<FN: Fn(&mut Channel<Signer>) -> Result<(Option<msgs::FundingLocked>, Vec<(HTLCSource, PaymentHash)>), msgs::ErrorMessage>>
3329-
(&self, height: u32, f: FN) {
3329+
(&self, height_opt: Option<u32>, f: FN) {
33303330
// Note that we MUST NOT end up calling methods on self.chain_monitor here - we're called
33313331
// during initialization prior to the chain_monitor being fully configured in some cases.
33323332
// See the docs for `ChannelManagerReadArgs` for more.
@@ -3385,24 +3385,26 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
33853385
true
33863386
});
33873387

3388-
channel_state.claimable_htlcs.retain(|&(ref payment_hash, _), htlcs| {
3389-
htlcs.retain(|htlc| {
3390-
// If height is approaching the number of blocks we think it takes us to get
3391-
// our commitment transaction confirmed before the HTLC expires, plus the
3392-
// number of blocks we generally consider it to take to do a commitment update,
3393-
// just give up on it and fail the HTLC.
3394-
if height >= htlc.cltv_expiry - HTLC_FAIL_BACK_BUFFER {
3395-
let mut htlc_msat_height_data = byte_utils::be64_to_array(htlc.value).to_vec();
3396-
htlc_msat_height_data.extend_from_slice(&byte_utils::be32_to_array(height));
3397-
timed_out_htlcs.push((HTLCSource::PreviousHopData(htlc.prev_hop.clone()), payment_hash.clone(), HTLCFailReason::Reason {
3398-
failure_code: 0x4000 | 15,
3399-
data: htlc_msat_height_data
3400-
}));
3401-
false
3402-
} else { true }
3388+
if let Some(height) = height_opt {
3389+
channel_state.claimable_htlcs.retain(|&(ref payment_hash, _), htlcs| {
3390+
htlcs.retain(|htlc| {
3391+
// If height is approaching the number of blocks we think it takes us to get
3392+
// our commitment transaction confirmed before the HTLC expires, plus the
3393+
// number of blocks we generally consider it to take to do a commitment update,
3394+
// just give up on it and fail the HTLC.
3395+
if height >= htlc.cltv_expiry - HTLC_FAIL_BACK_BUFFER {
3396+
let mut htlc_msat_height_data = byte_utils::be64_to_array(htlc.value).to_vec();
3397+
htlc_msat_height_data.extend_from_slice(&byte_utils::be32_to_array(height));
3398+
timed_out_htlcs.push((HTLCSource::PreviousHopData(htlc.prev_hop.clone()), payment_hash.clone(), HTLCFailReason::Reason {
3399+
failure_code: 0x4000 | 15,
3400+
data: htlc_msat_height_data
3401+
}));
3402+
false
3403+
} else { true }
3404+
});
3405+
!htlcs.is_empty() // Only retain this entry if htlcs has at least one entry.
34033406
});
3404-
!htlcs.is_empty() // Only retain this entry if htlcs has at least one entry.
3405-
});
3407+
}
34063408
}
34073409

34083410
self.handle_init_event_channel_failures(failed_channels);
@@ -3438,7 +3440,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
34383440
log_trace!(self.logger, "{} transactions included in block {} at height {} provided", txdata.len(), block_hash, height);
34393441

34403442
let _persistence_guard = PersistenceNotifierGuard::new(&self.total_consistency_lock, &self.persistence_notifier);
3441-
self.do_chain_event(height, |channel| channel.transactions_confirmed(&block_hash, height, txdata, &self.logger).map(|a| (a, Vec::new())));
3443+
self.do_chain_event(Some(height), |channel| channel.transactions_confirmed(&block_hash, height, txdata, &self.logger).map(|a| (a, Vec::new())));
34423444
}
34433445

34443446
/// Updates channel state with the current best blockchain tip. You should attempt to call this
@@ -3467,7 +3469,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
34673469
self.latest_block_height.store(height as usize, Ordering::Release);
34683470
*self.last_block_hash.write().unwrap() = block_hash;
34693471

3470-
self.do_chain_event(height, |channel| channel.update_best_block(height, header.time));
3472+
self.do_chain_event(Some(height), |channel| channel.update_best_block(height, header.time));
34713473

34723474
loop {
34733475
// Update last_node_announcement_serial to be the max of its current value and the
@@ -3483,6 +3485,30 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
34833485
}
34843486
}
34853487

3488+
/// Gets the set of txids which should be monitored for their confirmation state. XXX: Docs
3489+
pub fn get_relevant_txids(&self) -> Vec<Txid> {
3490+
let channel_state = self.channel_state.lock().unwrap();
3491+
let mut res = Vec::with_capacity(channel_state.short_to_id.len());
3492+
for chan in channel_state.by_id.values() {
3493+
if let Some(funding_txo) = chan.get_funding_txo() {
3494+
res.push(funding_txo.txid);
3495+
}
3496+
}
3497+
res
3498+
}
3499+
3500+
/// Marks a transaction as having been reorganized out of the blockchain XXX: Docs
3501+
pub fn transaction_unconfirmed(&self, txid: &Txid) {
3502+
let _persistence_guard = PersistenceNotifierGuard::new(&self.total_consistency_lock, &self.persistence_notifier);
3503+
self.do_chain_event(None, |channel| {
3504+
if let Some(funding_txo) = channel.get_funding_txo() {
3505+
if funding_txo.txid == *txid {
3506+
channel.funding_transaction_unconfirmed().map(|_| (None, Vec::new()))
3507+
} else { Ok((None, Vec::new())) }
3508+
} else { Ok((None, Vec::new())) }
3509+
});
3510+
}
3511+
34863512
/// Blocks until ChannelManager needs to be persisted or a timeout is reached. It returns a bool
34873513
/// indicating whether persistence is necessary. Only one listener on
34883514
/// `await_persistable_update` or `await_persistable_update_timeout` is guaranteed to be woken

0 commit comments

Comments
 (0)