2222
2323use bitcoin:: amount:: Amount ;
2424use bitcoin:: block:: Header ;
25+ use bitcoin:: locktime:: absolute:: LockTime ;
2526use bitcoin:: script:: { Script , ScriptBuf } ;
26- use bitcoin:: transaction:: { OutPoint as BitcoinOutPoint , Transaction , TxOut } ;
27+ use bitcoin:: transaction:: { OutPoint as BitcoinOutPoint , Transaction , TxIn , TxOut , Version } ;
28+ use bitcoin:: { Sequence , Witness } ;
2729
2830use bitcoin:: hash_types:: { BlockHash , Txid } ;
2931use bitcoin:: hashes:: sha256:: Hash as Sha256 ;
3032use bitcoin:: hashes:: Hash ;
3133
3234use bitcoin:: ecdsa:: Signature as BitcoinSignature ;
3335use bitcoin:: secp256k1:: { self , ecdsa:: Signature , PublicKey , Secp256k1 , SecretKey } ;
36+ use bitcoin:: sighash:: EcdsaSighashType ;
3437
3538use crate :: chain;
3639use crate :: chain:: chaininterface:: {
@@ -47,7 +50,7 @@ use crate::events::bump_transaction::{AnchorDescriptor, BumpTransactionEvent};
4750use crate :: events:: { ClosureReason , Event , EventHandler , ReplayEvent } ;
4851use crate :: ln:: chan_utils:: {
4952 self , ChannelTransactionParameters , CommitmentTransaction , CounterpartyCommitmentSecrets ,
50- HTLCClaim , HTLCOutputInCommitment , HolderCommitmentTransaction ,
53+ HTLCClaim , HTLCOutputInCommitment , HolderCommitmentTransaction , TxCreationKeys ,
5154} ;
5255use crate :: ln:: channel:: INITIAL_COMMITMENT_NUMBER ;
5356use crate :: ln:: channel_keys:: {
@@ -141,6 +144,20 @@ impl ChannelMonitorUpdate {
141144 pub fn renegotiated_funding_data ( & self ) -> impl Iterator < Item = ( OutPoint , ScriptBuf ) > + ' _ {
142145 self . internal_renegotiated_funding_data ( )
143146 }
147+
148+ /// Returns `true` if this update contains counterparty commitment data
149+ /// relevant to a watchtower (a new commitment or a revocation secret).
150+ pub fn updates_watchtower_state ( & self ) -> bool {
151+ self . updates . iter ( ) . any ( |step| {
152+ matches ! (
153+ step,
154+ ChannelMonitorUpdateStep :: LatestCounterpartyCommitmentTXInfo { .. }
155+ | ChannelMonitorUpdateStep :: LatestCounterpartyCommitment { .. }
156+ | ChannelMonitorUpdateStep :: CommitmentSecret { .. }
157+ | ChannelMonitorUpdateStep :: RenegotiatedFunding { .. }
158+ )
159+ } )
160+ }
144161}
145162
146163/// LDK prior to 0.1 used this constant as the [`ChannelMonitorUpdate::update_id`] for any
@@ -262,6 +279,17 @@ impl_writeable_tlv_based!(HTLCUpdate, {
262279 ( 4 , payment_preimage, option) ,
263280} ) ;
264281
282+ /// A signed justice transaction ready for broadcast or watchtower submission.
283+ #[ derive( Clone , Debug ) ]
284+ pub struct JusticeTransaction {
285+ /// The fully signed justice transaction.
286+ pub tx : Transaction ,
287+ /// The txid of the revoked counterparty commitment transaction.
288+ pub revoked_commitment_txid : Txid ,
289+ /// The commitment number of the revoked commitment transaction.
290+ pub commitment_number : u64 ,
291+ }
292+
265293/// If an output goes from claimable only by us to claimable by us or our counterparty within this
266294/// many blocks, we consider it pinnable for the purposes of aggregating claims in a single
267295/// transaction.
@@ -1166,6 +1194,11 @@ struct FundingScope {
11661194 // transaction for which we have deleted claim information on some watchtowers.
11671195 current_holder_commitment_tx : HolderCommitmentTransaction ,
11681196 prev_holder_commitment_tx : Option < HolderCommitmentTransaction > ,
1197+
1198+ /// The current counterparty commitment transaction, stored for justice tx signing.
1199+ cur_counterparty_commitment_tx : Option < CommitmentTransaction > ,
1200+ /// The previous counterparty commitment transaction, stored for justice tx signing.
1201+ prev_counterparty_commitment_tx : Option < CommitmentTransaction > ,
11691202}
11701203
11711204impl FundingScope {
@@ -1194,6 +1227,8 @@ impl_writeable_tlv_based!(FundingScope, {
11941227 ( 7 , current_holder_commitment_tx, required) ,
11951228 ( 9 , prev_holder_commitment_tx, option) ,
11961229 ( 11 , counterparty_claimable_outpoints, required) ,
1230+ ( 13 , cur_counterparty_commitment_tx, option) ,
1231+ ( 15 , prev_counterparty_commitment_tx, option) ,
11971232} ) ;
11981233
11991234#[ derive( Clone , PartialEq ) ]
@@ -1756,6 +1791,8 @@ pub(crate) fn write_chanmon_internal<Signer: EcdsaChannelSigner, W: Writer>(
17561791 ( 35 , channel_monitor. is_manual_broadcast, required) ,
17571792 ( 37 , channel_monitor. funding_seen_onchain, required) ,
17581793 ( 39 , channel_monitor. best_block. previous_blocks, required) ,
1794+ ( 43 , channel_monitor. funding. cur_counterparty_commitment_tx, option) ,
1795+ ( 45 , channel_monitor. funding. prev_counterparty_commitment_tx, option) ,
17591796 } ) ;
17601797
17611798 Ok ( ( ) )
@@ -1905,6 +1942,9 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
19051942
19061943 current_holder_commitment_tx : initial_holder_commitment_tx,
19071944 prev_holder_commitment_tx : None ,
1945+
1946+ cur_counterparty_commitment_tx : None ,
1947+ prev_counterparty_commitment_tx : None ,
19081948 } ,
19091949 pending_funding : vec ! [ ] ,
19101950
@@ -2272,6 +2312,27 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
22722312 self . inner . lock ( ) . unwrap ( ) . sign_to_local_justice_tx ( justice_tx, input_idx, value, commitment_number)
22732313 }
22742314
2315+ /// Returns signed justice transactions for all revoked counterparty commitments
2316+ /// currently stored in this monitor.
2317+ ///
2318+ /// Call this after persisting the monitor when
2319+ /// [`ChannelMonitorUpdate::updates_watchtower_state`] returns `true`. Also call on
2320+ /// startup for each loaded monitor to recover any justice transactions not yet
2321+ /// delivered to a watchtower.
2322+ ///
2323+ /// To avoid losing justice data when the watchtower is unreachable, the
2324+ /// [`Persist`] implementation should delay completing monitor updates until
2325+ /// previously obtained justice transactions have been delivered.
2326+ ///
2327+ /// Idempotent: returns the same results on repeated calls for the same monitor state.
2328+ ///
2329+ /// [`Persist`]: crate::chain::chainmonitor::Persist
2330+ pub fn get_pending_justice_txs (
2331+ & self , feerate_per_kw : u64 , destination_script : ScriptBuf ,
2332+ ) -> Vec < JusticeTransaction > {
2333+ self . inner . lock ( ) . unwrap ( ) . get_pending_justice_txs ( feerate_per_kw, destination_script)
2334+ }
2335+
22752336 pub ( crate ) fn get_min_seen_secret ( & self ) -> u64 {
22762337 self . inner . lock ( ) . unwrap ( ) . get_min_seen_secret ( )
22772338 }
@@ -3486,6 +3547,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
34863547 self . provide_latest_counterparty_commitment_tx ( commitment_tx. trust ( ) . txid ( ) , Vec :: new ( ) , commitment_tx. commitment_number ( ) ,
34873548 commitment_tx. per_commitment_point ( ) ) ;
34883549 // Soon, we will only populate this field
3550+ self . funding . cur_counterparty_commitment_tx = Some ( commitment_tx. clone ( ) ) ;
34893551 self . initial_counterparty_commitment_tx = Some ( commitment_tx) ;
34903552 }
34913553
@@ -3563,6 +3625,9 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
35633625 current_funding_commitment_tx. commitment_number ( ) ,
35643626 current_funding_commitment_tx. per_commitment_point ( ) ,
35653627 ) ;
3628+ self . funding . prev_counterparty_commitment_tx =
3629+ self . funding . cur_counterparty_commitment_tx . take ( ) ;
3630+ self . funding . cur_counterparty_commitment_tx = Some ( current_funding_commitment_tx. clone ( ) ) ;
35663631
35673632 for ( pending_funding, commitment_tx) in
35683633 self . pending_funding . iter_mut ( ) . zip ( commitment_txs. iter ( ) . skip ( 1 ) )
@@ -3574,6 +3639,9 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
35743639 pending_funding
35753640 . counterparty_claimable_outpoints
35763641 . insert ( commitment_txid, htlcs_for_commitment ( commitment_tx) ) ;
3642+ pending_funding. prev_counterparty_commitment_tx =
3643+ pending_funding. cur_counterparty_commitment_tx . take ( ) ;
3644+ pending_funding. cur_counterparty_commitment_tx = Some ( commitment_tx. clone ( ) ) ;
35773645 }
35783646
35793647 Ok ( ( ) )
@@ -4025,6 +4093,9 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
40254093 counterparty_claimable_outpoints,
40264094 current_holder_commitment_tx : alternative_holder_commitment_tx. clone ( ) ,
40274095 prev_holder_commitment_tx : None ,
4096+
4097+ cur_counterparty_commitment_tx : None ,
4098+ prev_counterparty_commitment_tx : None ,
40284099 } ;
40294100 let alternative_funding_outpoint = alternative_funding. funding_outpoint ( ) ;
40304101
@@ -4294,8 +4365,21 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
42944365 }
42954366 }
42964367
4297- #[ cfg( debug_assertions) ] {
4298- self . counterparty_commitment_txs_from_update ( updates) ;
4368+ // Populate cur/prev for the LatestCounterpartyCommitmentTXInfo path, which
4369+ // doesn't go through update_counterparty_commitment_data.
4370+ for commitment_tx in self . counterparty_commitment_txs_from_update ( updates) {
4371+ let txid = commitment_tx. trust ( ) . built_transaction ( ) . txid ;
4372+ let funding = core:: iter:: once ( & mut self . funding )
4373+ . chain ( self . pending_funding . iter_mut ( ) )
4374+ . find ( |f| f. current_counterparty_commitment_txid == Some ( txid) ) ;
4375+ if let Some ( funding) = funding {
4376+ if funding. cur_counterparty_commitment_tx . as_ref ( )
4377+ . map ( |c| c. trust ( ) . built_transaction ( ) . txid ) != Some ( txid)
4378+ {
4379+ funding. prev_counterparty_commitment_tx = funding. cur_counterparty_commitment_tx . take ( ) ;
4380+ funding. cur_counterparty_commitment_tx = Some ( commitment_tx) ;
4381+ }
4382+ }
42994383 }
43004384
43014385 self . latest_update_id = updates. update_id ;
@@ -4742,6 +4826,163 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
47424826 self . commitment_secrets . get_secret ( idx)
47434827 }
47444828
4829+ /// Returns signed justice transactions for all revoked counterparty commitments
4830+ /// currently stored in this monitor. Idempotent.
4831+ fn get_pending_justice_txs (
4832+ & self , feerate_per_kw : u64 , destination_script : ScriptBuf ,
4833+ ) -> Vec < JusticeTransaction > {
4834+ let mut result = Vec :: new ( ) ;
4835+ for funding in core:: iter:: once ( & self . funding ) . chain ( self . pending_funding . iter ( ) ) {
4836+ if let Some ( ref prev) = funding. prev_counterparty_commitment_tx {
4837+ if self . commitment_secrets . get_secret ( prev. commitment_number ( ) ) . is_some ( ) {
4838+ result. extend ( self . try_sign_justice_txs (
4839+ prev,
4840+ feerate_per_kw,
4841+ destination_script. clone ( ) ,
4842+ ) ) ;
4843+ }
4844+ }
4845+ }
4846+ result
4847+ }
4848+
4849+ fn try_sign_justice_txs (
4850+ & self , commitment_tx : & CommitmentTransaction , feerate_per_kw : u64 ,
4851+ destination_script : ScriptBuf ,
4852+ ) -> Vec < JusticeTransaction > {
4853+ let commitment_number = commitment_tx. commitment_number ( ) ;
4854+ let secret = match self . get_secret ( commitment_number) {
4855+ Some ( s) => s,
4856+ None => return Vec :: new ( ) ,
4857+ } ;
4858+ let per_commitment_key = match SecretKey :: from_slice ( & secret) {
4859+ Ok ( k) => k,
4860+ Err ( _) => return Vec :: new ( ) ,
4861+ } ;
4862+
4863+ let trusted = commitment_tx. trust ( ) ;
4864+ let built = trusted. built_transaction ( ) ;
4865+ let txid = built. txid ;
4866+ let mut result = Vec :: new ( ) ;
4867+
4868+ // to_local justice tx
4869+ if let Some ( output_idx) = trusted. revokeable_output_index ( ) {
4870+ let value = built. transaction . output [ output_idx] . value ;
4871+ if let Ok ( justice_tx) =
4872+ trusted. build_to_local_justice_tx ( feerate_per_kw, destination_script. clone ( ) )
4873+ {
4874+ if let Ok ( signed) =
4875+ self . sign_to_local_justice_tx ( justice_tx, 0 , value. to_sat ( ) , commitment_number)
4876+ {
4877+ result. push ( JusticeTransaction {
4878+ tx : signed,
4879+ revoked_commitment_txid : txid,
4880+ commitment_number,
4881+ } ) ;
4882+ }
4883+ }
4884+ }
4885+
4886+ // HTLC justice txs
4887+ let channel_parameters = core:: iter:: once ( & self . funding )
4888+ . chain ( & self . pending_funding )
4889+ . find ( |funding| funding. counterparty_claimable_outpoints . contains_key ( & txid) )
4890+ . map ( |funding| & funding. channel_parameters ) ;
4891+ if let Some ( channel_parameters) = channel_parameters {
4892+ let per_commitment_point =
4893+ PublicKey :: from_secret_key ( & self . onchain_tx_handler . secp_ctx , & per_commitment_key) ;
4894+ let directed = channel_parameters. as_counterparty_broadcastable ( ) ;
4895+ let keys = TxCreationKeys :: from_channel_static_keys (
4896+ & per_commitment_point,
4897+ directed. broadcaster_pubkeys ( ) ,
4898+ directed. countersignatory_pubkeys ( ) ,
4899+ & self . onchain_tx_handler . secp_ctx ,
4900+ ) ;
4901+
4902+ for htlc in commitment_tx. nondust_htlcs ( ) {
4903+ if let Some ( output_index) = htlc. transaction_output_index {
4904+ let htlc_value = built. transaction . output [ output_index as usize ] . value ;
4905+ let witness_script = chan_utils:: get_htlc_redeemscript (
4906+ htlc,
4907+ & channel_parameters. channel_type_features ,
4908+ & keys,
4909+ ) ;
4910+
4911+ // Build a spending tx for this HTLC output
4912+ let input = vec ! [ TxIn {
4913+ previous_output: bitcoin:: OutPoint { txid, vout: output_index } ,
4914+ script_sig: ScriptBuf :: new( ) ,
4915+ sequence: Sequence :: ENABLE_RBF_NO_LOCKTIME ,
4916+ witness: Witness :: new( ) ,
4917+ } ] ;
4918+ let weight_estimate = if htlc. offered {
4919+ crate :: chain:: package:: weight_revoked_offered_htlc (
4920+ & channel_parameters. channel_type_features ,
4921+ )
4922+ } else {
4923+ crate :: chain:: package:: weight_revoked_received_htlc (
4924+ & channel_parameters. channel_type_features ,
4925+ )
4926+ } ;
4927+ let fee = Amount :: from_sat ( crate :: chain:: chaininterface:: fee_for_weight (
4928+ feerate_per_kw as u32 ,
4929+ // Base tx weight + witness weight
4930+ Transaction {
4931+ version : Version :: TWO ,
4932+ lock_time : LockTime :: ZERO ,
4933+ input : input. clone ( ) ,
4934+ output : vec ! [ TxOut {
4935+ script_pubkey: destination_script. clone( ) ,
4936+ value: htlc_value,
4937+ } ] ,
4938+ }
4939+ . weight ( )
4940+ . to_wu ( ) + weight_estimate,
4941+ ) ) ;
4942+ let output_value = match htlc_value. checked_sub ( fee) {
4943+ Some ( v) => v,
4944+ None => continue , // Dust, skip
4945+ } ;
4946+
4947+ let mut justice_tx = Transaction {
4948+ version : Version :: TWO ,
4949+ lock_time : LockTime :: ZERO ,
4950+ input,
4951+ output : vec ! [ TxOut {
4952+ script_pubkey: destination_script. clone( ) ,
4953+ value: output_value,
4954+ } ] ,
4955+ } ;
4956+
4957+ if let Ok ( sig) = self . onchain_tx_handler . signer . sign_justice_revoked_htlc (
4958+ channel_parameters,
4959+ & justice_tx,
4960+ 0 ,
4961+ htlc_value. to_sat ( ) ,
4962+ & per_commitment_key,
4963+ htlc,
4964+ & self . onchain_tx_handler . secp_ctx ,
4965+ ) {
4966+ let mut ser_sig = sig. serialize_der ( ) . to_vec ( ) ;
4967+ ser_sig. push ( EcdsaSighashType :: All as u8 ) ;
4968+ justice_tx. input [ 0 ] . witness . push ( ser_sig) ;
4969+ justice_tx. input [ 0 ]
4970+ . witness
4971+ . push ( keys. revocation_key . to_public_key ( ) . serialize ( ) . to_vec ( ) ) ;
4972+ justice_tx. input [ 0 ] . witness . push ( witness_script. into_bytes ( ) ) ;
4973+ result. push ( JusticeTransaction {
4974+ tx : justice_tx,
4975+ revoked_commitment_txid : txid,
4976+ commitment_number,
4977+ } ) ;
4978+ }
4979+ }
4980+ }
4981+ }
4982+
4983+ result
4984+ }
4985+
47454986 fn get_min_seen_secret ( & self ) -> u64 {
47464987 self . commitment_secrets . get_min_seen_secret ( )
47474988 }
@@ -6696,6 +6937,8 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
66966937 let mut is_manual_broadcast = RequiredWrapper ( None ) ;
66976938 let mut funding_seen_onchain = RequiredWrapper ( None ) ;
66986939 let mut best_block_previous_blocks = None ;
6940+ let mut cur_counterparty_commitment_tx: Option < CommitmentTransaction > = None ;
6941+ let mut prev_counterparty_commitment_tx_deser: Option < CommitmentTransaction > = None ;
66996942 read_tlv_fields ! ( reader, {
67006943 ( 1 , funding_spend_confirmed, option) ,
67016944 ( 3 , htlcs_resolved_on_chain, optional_vec) ,
@@ -6719,6 +6962,8 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
67196962 ( 35 , is_manual_broadcast, ( default_value, false ) ) ,
67206963 ( 37 , funding_seen_onchain, ( default_value, true ) ) ,
67216964 ( 39 , best_block_previous_blocks, option) , // Added and always set in 0.3
6965+ ( 43 , cur_counterparty_commitment_tx, option) ,
6966+ ( 45 , prev_counterparty_commitment_tx_deser, option) ,
67226967 } ) ;
67236968 if let Some ( previous_blocks) = best_block_previous_blocks {
67246969 best_block. previous_blocks = previous_blocks;
@@ -6837,6 +7082,9 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
68377082
68387083 current_holder_commitment_tx,
68397084 prev_holder_commitment_tx,
7085+
7086+ cur_counterparty_commitment_tx,
7087+ prev_counterparty_commitment_tx : prev_counterparty_commitment_tx_deser,
68407088 } ,
68417089 pending_funding : pending_funding. unwrap_or ( vec ! [ ] ) ,
68427090 is_manual_broadcast : is_manual_broadcast. 0 . unwrap ( ) ,
0 commit comments