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,21 @@ 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+ /// Idempotent: returns the same results on repeated calls for the same monitor state.
2324+ pub fn get_pending_justice_txs (
2325+ & self , feerate_per_kw : u64 , destination_script : ScriptBuf ,
2326+ ) -> Vec < JusticeTransaction > {
2327+ self . inner . lock ( ) . unwrap ( ) . get_pending_justice_txs ( feerate_per_kw, destination_script)
2328+ }
2329+
22752330 pub ( crate ) fn get_min_seen_secret ( & self ) -> u64 {
22762331 self . inner . lock ( ) . unwrap ( ) . get_min_seen_secret ( )
22772332 }
@@ -3486,6 +3541,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
34863541 self . provide_latest_counterparty_commitment_tx ( commitment_tx. trust ( ) . txid ( ) , Vec :: new ( ) , commitment_tx. commitment_number ( ) ,
34873542 commitment_tx. per_commitment_point ( ) ) ;
34883543 // Soon, we will only populate this field
3544+ self . funding . cur_counterparty_commitment_tx = Some ( commitment_tx. clone ( ) ) ;
34893545 self . initial_counterparty_commitment_tx = Some ( commitment_tx) ;
34903546 }
34913547
@@ -3563,6 +3619,9 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
35633619 current_funding_commitment_tx. commitment_number ( ) ,
35643620 current_funding_commitment_tx. per_commitment_point ( ) ,
35653621 ) ;
3622+ self . funding . prev_counterparty_commitment_tx =
3623+ self . funding . cur_counterparty_commitment_tx . take ( ) ;
3624+ self . funding . cur_counterparty_commitment_tx = Some ( current_funding_commitment_tx. clone ( ) ) ;
35663625
35673626 for ( pending_funding, commitment_tx) in
35683627 self . pending_funding . iter_mut ( ) . zip ( commitment_txs. iter ( ) . skip ( 1 ) )
@@ -3574,6 +3633,9 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
35743633 pending_funding
35753634 . counterparty_claimable_outpoints
35763635 . insert ( commitment_txid, htlcs_for_commitment ( commitment_tx) ) ;
3636+ pending_funding. prev_counterparty_commitment_tx =
3637+ pending_funding. cur_counterparty_commitment_tx . take ( ) ;
3638+ pending_funding. cur_counterparty_commitment_tx = Some ( commitment_tx. clone ( ) ) ;
35773639 }
35783640
35793641 Ok ( ( ) )
@@ -4025,6 +4087,9 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
40254087 counterparty_claimable_outpoints,
40264088 current_holder_commitment_tx : alternative_holder_commitment_tx. clone ( ) ,
40274089 prev_holder_commitment_tx : None ,
4090+
4091+ cur_counterparty_commitment_tx : None ,
4092+ prev_counterparty_commitment_tx : None ,
40284093 } ;
40294094 let alternative_funding_outpoint = alternative_funding. funding_outpoint ( ) ;
40304095
@@ -4294,8 +4359,21 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
42944359 }
42954360 }
42964361
4297- #[ cfg( debug_assertions) ] {
4298- self . counterparty_commitment_txs_from_update ( updates) ;
4362+ // Populate cur/prev for the LatestCounterpartyCommitmentTXInfo path, which
4363+ // doesn't go through update_counterparty_commitment_data.
4364+ for commitment_tx in self . counterparty_commitment_txs_from_update ( updates) {
4365+ let txid = commitment_tx. trust ( ) . built_transaction ( ) . txid ;
4366+ let funding = core:: iter:: once ( & mut self . funding )
4367+ . chain ( self . pending_funding . iter_mut ( ) )
4368+ . find ( |f| f. current_counterparty_commitment_txid == Some ( txid) ) ;
4369+ if let Some ( funding) = funding {
4370+ if funding. cur_counterparty_commitment_tx . as_ref ( )
4371+ . map ( |c| c. trust ( ) . built_transaction ( ) . txid ) != Some ( txid)
4372+ {
4373+ funding. prev_counterparty_commitment_tx = funding. cur_counterparty_commitment_tx . take ( ) ;
4374+ funding. cur_counterparty_commitment_tx = Some ( commitment_tx) ;
4375+ }
4376+ }
42994377 }
43004378
43014379 self . latest_update_id = updates. update_id ;
@@ -4742,6 +4820,163 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
47424820 self . commitment_secrets . get_secret ( idx)
47434821 }
47444822
4823+ /// Returns signed justice transactions for all revoked counterparty commitments
4824+ /// currently stored in this monitor. Idempotent.
4825+ fn get_pending_justice_txs (
4826+ & self , feerate_per_kw : u64 , destination_script : ScriptBuf ,
4827+ ) -> Vec < JusticeTransaction > {
4828+ let mut result = Vec :: new ( ) ;
4829+ for funding in core:: iter:: once ( & self . funding ) . chain ( self . pending_funding . iter ( ) ) {
4830+ if let Some ( ref prev) = funding. prev_counterparty_commitment_tx {
4831+ if self . commitment_secrets . get_secret ( prev. commitment_number ( ) ) . is_some ( ) {
4832+ result. extend ( self . try_sign_justice_txs (
4833+ prev,
4834+ feerate_per_kw,
4835+ destination_script. clone ( ) ,
4836+ ) ) ;
4837+ }
4838+ }
4839+ }
4840+ result
4841+ }
4842+
4843+ fn try_sign_justice_txs (
4844+ & self , commitment_tx : & CommitmentTransaction , feerate_per_kw : u64 ,
4845+ destination_script : ScriptBuf ,
4846+ ) -> Vec < JusticeTransaction > {
4847+ let commitment_number = commitment_tx. commitment_number ( ) ;
4848+ let secret = match self . get_secret ( commitment_number) {
4849+ Some ( s) => s,
4850+ None => return Vec :: new ( ) ,
4851+ } ;
4852+ let per_commitment_key = match SecretKey :: from_slice ( & secret) {
4853+ Ok ( k) => k,
4854+ Err ( _) => return Vec :: new ( ) ,
4855+ } ;
4856+
4857+ let trusted = commitment_tx. trust ( ) ;
4858+ let built = trusted. built_transaction ( ) ;
4859+ let txid = built. txid ;
4860+ let mut result = Vec :: new ( ) ;
4861+
4862+ // to_local justice tx
4863+ if let Some ( output_idx) = trusted. revokeable_output_index ( ) {
4864+ let value = built. transaction . output [ output_idx] . value ;
4865+ if let Ok ( justice_tx) =
4866+ trusted. build_to_local_justice_tx ( feerate_per_kw, destination_script. clone ( ) )
4867+ {
4868+ if let Ok ( signed) =
4869+ self . sign_to_local_justice_tx ( justice_tx, 0 , value. to_sat ( ) , commitment_number)
4870+ {
4871+ result. push ( JusticeTransaction {
4872+ tx : signed,
4873+ revoked_commitment_txid : txid,
4874+ commitment_number,
4875+ } ) ;
4876+ }
4877+ }
4878+ }
4879+
4880+ // HTLC justice txs
4881+ let channel_parameters = core:: iter:: once ( & self . funding )
4882+ . chain ( & self . pending_funding )
4883+ . find ( |funding| funding. counterparty_claimable_outpoints . contains_key ( & txid) )
4884+ . map ( |funding| & funding. channel_parameters ) ;
4885+ if let Some ( channel_parameters) = channel_parameters {
4886+ let per_commitment_point =
4887+ PublicKey :: from_secret_key ( & self . onchain_tx_handler . secp_ctx , & per_commitment_key) ;
4888+ let directed = channel_parameters. as_counterparty_broadcastable ( ) ;
4889+ let keys = TxCreationKeys :: from_channel_static_keys (
4890+ & per_commitment_point,
4891+ directed. broadcaster_pubkeys ( ) ,
4892+ directed. countersignatory_pubkeys ( ) ,
4893+ & self . onchain_tx_handler . secp_ctx ,
4894+ ) ;
4895+
4896+ for htlc in commitment_tx. nondust_htlcs ( ) {
4897+ if let Some ( output_index) = htlc. transaction_output_index {
4898+ let htlc_value = built. transaction . output [ output_index as usize ] . value ;
4899+ let witness_script = chan_utils:: get_htlc_redeemscript (
4900+ htlc,
4901+ & channel_parameters. channel_type_features ,
4902+ & keys,
4903+ ) ;
4904+
4905+ // Build a spending tx for this HTLC output
4906+ let input = vec ! [ TxIn {
4907+ previous_output: bitcoin:: OutPoint { txid, vout: output_index } ,
4908+ script_sig: ScriptBuf :: new( ) ,
4909+ sequence: Sequence :: ENABLE_RBF_NO_LOCKTIME ,
4910+ witness: Witness :: new( ) ,
4911+ } ] ;
4912+ let weight_estimate = if htlc. offered {
4913+ crate :: chain:: package:: weight_revoked_offered_htlc (
4914+ & channel_parameters. channel_type_features ,
4915+ )
4916+ } else {
4917+ crate :: chain:: package:: weight_revoked_received_htlc (
4918+ & channel_parameters. channel_type_features ,
4919+ )
4920+ } ;
4921+ let fee = Amount :: from_sat ( crate :: chain:: chaininterface:: fee_for_weight (
4922+ feerate_per_kw as u32 ,
4923+ // Base tx weight + witness weight
4924+ Transaction {
4925+ version : Version :: TWO ,
4926+ lock_time : LockTime :: ZERO ,
4927+ input : input. clone ( ) ,
4928+ output : vec ! [ TxOut {
4929+ script_pubkey: destination_script. clone( ) ,
4930+ value: htlc_value,
4931+ } ] ,
4932+ }
4933+ . weight ( )
4934+ . to_wu ( ) + weight_estimate,
4935+ ) ) ;
4936+ let output_value = match htlc_value. checked_sub ( fee) {
4937+ Some ( v) => v,
4938+ None => continue , // Dust, skip
4939+ } ;
4940+
4941+ let mut justice_tx = Transaction {
4942+ version : Version :: TWO ,
4943+ lock_time : LockTime :: ZERO ,
4944+ input,
4945+ output : vec ! [ TxOut {
4946+ script_pubkey: destination_script. clone( ) ,
4947+ value: output_value,
4948+ } ] ,
4949+ } ;
4950+
4951+ if let Ok ( sig) = self . onchain_tx_handler . signer . sign_justice_revoked_htlc (
4952+ channel_parameters,
4953+ & justice_tx,
4954+ 0 ,
4955+ htlc_value. to_sat ( ) ,
4956+ & per_commitment_key,
4957+ htlc,
4958+ & self . onchain_tx_handler . secp_ctx ,
4959+ ) {
4960+ let mut ser_sig = sig. serialize_der ( ) . to_vec ( ) ;
4961+ ser_sig. push ( EcdsaSighashType :: All as u8 ) ;
4962+ justice_tx. input [ 0 ] . witness . push ( ser_sig) ;
4963+ justice_tx. input [ 0 ]
4964+ . witness
4965+ . push ( keys. revocation_key . to_public_key ( ) . serialize ( ) . to_vec ( ) ) ;
4966+ justice_tx. input [ 0 ] . witness . push ( witness_script. into_bytes ( ) ) ;
4967+ result. push ( JusticeTransaction {
4968+ tx : justice_tx,
4969+ revoked_commitment_txid : txid,
4970+ commitment_number,
4971+ } ) ;
4972+ }
4973+ }
4974+ }
4975+ }
4976+
4977+ result
4978+ }
4979+
47454980 fn get_min_seen_secret ( & self ) -> u64 {
47464981 self . commitment_secrets . get_min_seen_secret ( )
47474982 }
@@ -6696,6 +6931,8 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
66966931 let mut is_manual_broadcast = RequiredWrapper ( None ) ;
66976932 let mut funding_seen_onchain = RequiredWrapper ( None ) ;
66986933 let mut best_block_previous_blocks = None ;
6934+ let mut cur_counterparty_commitment_tx: Option < CommitmentTransaction > = None ;
6935+ let mut prev_counterparty_commitment_tx_deser: Option < CommitmentTransaction > = None ;
66996936 read_tlv_fields ! ( reader, {
67006937 ( 1 , funding_spend_confirmed, option) ,
67016938 ( 3 , htlcs_resolved_on_chain, optional_vec) ,
@@ -6719,6 +6956,8 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
67196956 ( 35 , is_manual_broadcast, ( default_value, false ) ) ,
67206957 ( 37 , funding_seen_onchain, ( default_value, true ) ) ,
67216958 ( 39 , best_block_previous_blocks, option) , // Added and always set in 0.3
6959+ ( 43 , cur_counterparty_commitment_tx, option) ,
6960+ ( 45 , prev_counterparty_commitment_tx_deser, option) ,
67226961 } ) ;
67236962 if let Some ( previous_blocks) = best_block_previous_blocks {
67246963 best_block. previous_blocks = previous_blocks;
@@ -6837,6 +7076,9 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
68377076
68387077 current_holder_commitment_tx,
68397078 prev_holder_commitment_tx,
7079+
7080+ cur_counterparty_commitment_tx,
7081+ prev_counterparty_commitment_tx : prev_counterparty_commitment_tx_deser,
68407082 } ,
68417083 pending_funding : pending_funding. unwrap_or ( vec ! [ ] ) ,
68427084 is_manual_broadcast : is_manual_broadcast. 0 . unwrap ( ) ,
0 commit comments