@@ -28,7 +28,7 @@ use bitcoin::hashes::hmac::{Hmac, HmacEngine};
28
28
use bitcoin:: hashes:: sha256:: Hash as Sha256 ;
29
29
use bitcoin:: hashes:: sha256d:: Hash as Sha256dHash ;
30
30
use bitcoin:: hashes:: cmp:: fixed_time_eq;
31
- use bitcoin:: hash_types:: BlockHash ;
31
+ use bitcoin:: hash_types:: { BlockHash , Txid } ;
32
32
33
33
use bitcoin:: secp256k1:: key:: { SecretKey , PublicKey } ;
34
34
use bitcoin:: secp256k1:: Secp256k1 ;
@@ -3353,7 +3353,7 @@ where
3353
3353
"Blocks must be disconnected in chain-order - the disconnected block must have the correct height" ) ;
3354
3354
* self . last_block_hash . write ( ) . unwrap ( ) = header. prev_blockhash ;
3355
3355
3356
- self . do_chain_event ( new_height, |channel| channel. update_best_block ( new_height, header. time ) ) ;
3356
+ self . do_chain_event ( Some ( new_height) , |channel| channel. update_best_block ( new_height, header. time ) ) ;
3357
3357
}
3358
3358
}
3359
3359
@@ -3364,8 +3364,11 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
3364
3364
F :: Target : FeeEstimator ,
3365
3365
L :: Target : Logger ,
3366
3366
{
3367
+ /// Calls a function which handles an on-chain event (blocks dis/connected, transactions
3368
+ /// un/confirmed, etc) on each channel, handling any resulting errors or messages generated by
3369
+ /// the function.
3367
3370
fn do_chain_event < FN : Fn ( & mut Channel < Signer > ) -> Result < ( Option < msgs:: FundingLocked > , Vec < ( HTLCSource , PaymentHash ) > ) , msgs:: ErrorMessage > >
3368
- ( & self , height : u32 , f : FN ) {
3371
+ ( & self , height_opt : Option < u32 > , f : FN ) {
3369
3372
// Note that we MUST NOT end up calling methods on self.chain_monitor here - we're called
3370
3373
// during initialization prior to the chain_monitor being fully configured in some cases.
3371
3374
// See the docs for `ChannelManagerReadArgs` for more.
@@ -3424,24 +3427,26 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
3424
3427
true
3425
3428
} ) ;
3426
3429
3427
- channel_state. claimable_htlcs . retain ( |& ( ref payment_hash, _) , htlcs| {
3428
- htlcs. retain ( |htlc| {
3429
- // If height is approaching the number of blocks we think it takes us to get
3430
- // our commitment transaction confirmed before the HTLC expires, plus the
3431
- // number of blocks we generally consider it to take to do a commitment update,
3432
- // just give up on it and fail the HTLC.
3433
- if height >= htlc. cltv_expiry - HTLC_FAIL_BACK_BUFFER {
3434
- let mut htlc_msat_height_data = byte_utils:: be64_to_array ( htlc. value ) . to_vec ( ) ;
3435
- htlc_msat_height_data. extend_from_slice ( & byte_utils:: be32_to_array ( height) ) ;
3436
- timed_out_htlcs. push ( ( HTLCSource :: PreviousHopData ( htlc. prev_hop . clone ( ) ) , payment_hash. clone ( ) , HTLCFailReason :: Reason {
3437
- failure_code : 0x4000 | 15 ,
3438
- data : htlc_msat_height_data
3439
- } ) ) ;
3440
- false
3441
- } else { true }
3430
+ if let Some ( height) = height_opt {
3431
+ channel_state. claimable_htlcs . retain ( |& ( ref payment_hash, _) , htlcs| {
3432
+ htlcs. retain ( |htlc| {
3433
+ // If height is approaching the number of blocks we think it takes us to get
3434
+ // our commitment transaction confirmed before the HTLC expires, plus the
3435
+ // number of blocks we generally consider it to take to do a commitment update,
3436
+ // just give up on it and fail the HTLC.
3437
+ if height >= htlc. cltv_expiry - HTLC_FAIL_BACK_BUFFER {
3438
+ let mut htlc_msat_height_data = byte_utils:: be64_to_array ( htlc. value ) . to_vec ( ) ;
3439
+ htlc_msat_height_data. extend_from_slice ( & byte_utils:: be32_to_array ( height) ) ;
3440
+ timed_out_htlcs. push ( ( HTLCSource :: PreviousHopData ( htlc. prev_hop . clone ( ) ) , payment_hash. clone ( ) , HTLCFailReason :: Reason {
3441
+ failure_code : 0x4000 | 15 ,
3442
+ data : htlc_msat_height_data
3443
+ } ) ) ;
3444
+ false
3445
+ } else { true }
3446
+ } ) ;
3447
+ !htlcs. is_empty ( ) // Only retain this entry if htlcs has at least one entry.
3442
3448
} ) ;
3443
- !htlcs. is_empty ( ) // Only retain this entry if htlcs has at least one entry.
3444
- } ) ;
3449
+ }
3445
3450
}
3446
3451
3447
3452
self . handle_init_event_channel_failures ( failed_channels) ;
@@ -3477,7 +3482,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
3477
3482
log_trace ! ( self . logger, "{} transactions included in block {} at height {} provided" , txdata. len( ) , block_hash, height) ;
3478
3483
3479
3484
let _persistence_guard = PersistenceNotifierGuard :: new ( & self . total_consistency_lock , & self . persistence_notifier ) ;
3480
- self . do_chain_event ( height, |channel| channel. transactions_confirmed ( & block_hash, height, txdata, & self . logger ) . map ( |a| ( a, Vec :: new ( ) ) ) ) ;
3485
+ self . do_chain_event ( Some ( height) , |channel| channel. transactions_confirmed ( & block_hash, height, txdata, & self . logger ) . map ( |a| ( a, Vec :: new ( ) ) ) ) ;
3481
3486
}
3482
3487
3483
3488
/// Updates channel state with the current best blockchain tip. You should attempt to call this
@@ -3506,7 +3511,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
3506
3511
self . latest_block_height . store ( height as usize , Ordering :: Release ) ;
3507
3512
* self . last_block_hash . write ( ) . unwrap ( ) = block_hash;
3508
3513
3509
- self . do_chain_event ( height, |channel| channel. update_best_block ( height, header. time ) ) ;
3514
+ self . do_chain_event ( Some ( height) , |channel| channel. update_best_block ( height, header. time ) ) ;
3510
3515
3511
3516
loop {
3512
3517
// Update last_node_announcement_serial to be the max of its current value and the
@@ -3522,6 +3527,60 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
3522
3527
}
3523
3528
}
3524
3529
3530
+ /// Gets the set of txids which should be monitored for their confirmation state.
3531
+ ///
3532
+ /// If you're providing information about reorganizations via [`transaction_unconfirmed`], this
3533
+ /// is the set of transactions which you may need to call [`transaction_unconfirmed`] for.
3534
+ ///
3535
+ /// This may be useful to poll to determine the set of transactions which must be registered
3536
+ /// with an Electrum server or for which an Electrum server needs to be polled to determine
3537
+ /// transaction confirmation state.
3538
+ ///
3539
+ /// This may update after any [`transactions_confirmed`] or [`block_connected`] call.
3540
+ ///
3541
+ /// Note that this is NOT the set of transactions which must be included in calls to
3542
+ /// [`transactions_confirmed`] if they are confirmed, but a small subset of it.
3543
+ ///
3544
+ /// [`transactions_confirmed`]: Self::transactions_confirmed
3545
+ /// [`transaction_unconfirmed`]: Self::transaction_unconfirmed
3546
+ pub fn get_relevant_txids ( & self ) -> Vec < Txid > {
3547
+ let channel_state = self . channel_state . lock ( ) . unwrap ( ) ;
3548
+ let mut res = Vec :: with_capacity ( channel_state. short_to_id . len ( ) ) ;
3549
+ for chan in channel_state. by_id . values ( ) {
3550
+ if let Some ( funding_txo) = chan. get_funding_txo ( ) {
3551
+ res. push ( funding_txo. txid ) ;
3552
+ }
3553
+ }
3554
+ res
3555
+ }
3556
+
3557
+ /// Marks a transaction as having been reorganized out of the blockchain.
3558
+ ///
3559
+ /// If a transaction is included in [`get_relevant_txids`], and is no longer in the main branch
3560
+ /// of the blockchain, this function should be called to indicate that the transaction should
3561
+ /// be considered reorganized out.
3562
+ ///
3563
+ /// Once this is called, the given transaction will no longer appear on [`get_relevant_txids`],
3564
+ /// though this may be called repeatedly for a given transaction without issue.
3565
+ ///
3566
+ /// Note that if the transaction is confirmed on the main chain in a different block (indicated
3567
+ /// via a call to [`transactions_confirmed`]), it may re-appear in [`get_relevant_txids`], thus
3568
+ /// be very wary of race-conditions wherein the final state of a transaction indicated via
3569
+ /// these APIs is not the same as its state on the blockchain.
3570
+ ///
3571
+ /// [`transactions_confirmed`]: Self::transactions_confirmed
3572
+ /// [`get_relevant_txids`]: Self::get_relevant_txids
3573
+ pub fn transaction_unconfirmed ( & self , txid : & Txid ) {
3574
+ let _persistence_guard = PersistenceNotifierGuard :: new ( & self . total_consistency_lock , & self . persistence_notifier ) ;
3575
+ self . do_chain_event ( None , |channel| {
3576
+ if let Some ( funding_txo) = channel. get_funding_txo ( ) {
3577
+ if funding_txo. txid == * txid {
3578
+ channel. funding_transaction_unconfirmed ( ) . map ( |_| ( None , Vec :: new ( ) ) )
3579
+ } else { Ok ( ( None , Vec :: new ( ) ) ) }
3580
+ } else { Ok ( ( None , Vec :: new ( ) ) ) }
3581
+ } ) ;
3582
+ }
3583
+
3525
3584
/// Blocks until ChannelManager needs to be persisted or a timeout is reached. It returns a bool
3526
3585
/// indicating whether persistence is necessary. Only one listener on
3527
3586
/// `await_persistable_update` or `await_persistable_update_timeout` is guaranteed to be woken
0 commit comments