@@ -31,7 +31,7 @@ use bitcoin::hash_types::{Txid, BlockHash, WPubkeyHash};
3131
3232use bitcoin:: secp256k1:: { Secp256k1 , ecdsa:: Signature } ;
3333use bitcoin:: secp256k1:: { SecretKey , PublicKey } ;
34- use bitcoin:: secp256k1;
34+ use bitcoin:: { secp256k1, EcdsaSighashType } ;
3535
3636use crate :: ln:: channel:: INITIAL_COMMITMENT_NUMBER ;
3737use crate :: ln:: { PaymentHash , PaymentPreimage } ;
@@ -1430,7 +1430,8 @@ impl<Signer: WriteableEcdsaChannelSigner> ChannelMonitor<Signer> {
14301430 /// This is provided so that watchtower clients in the persistence pipeline are able to build
14311431 /// justice transactions for each counterparty commitment upon each update. It's intended to be
14321432 /// used within an implementation of [`Persist::update_persisted_channel`], which is provided
1433- /// with a monitor and an update.
1433+ /// with a monitor and an update. Once revoked, signing a justice transaction can be done using
1434+ /// [`Self::sign_to_local_justice_tx`].
14341435 ///
14351436 /// It is expected that a watchtower client may use this method to retrieve the latest counterparty
14361437 /// commitment transaction(s), and then hold the necessary data until a later update in which
@@ -1446,6 +1447,27 @@ impl<Signer: WriteableEcdsaChannelSigner> ChannelMonitor<Signer> {
14461447 self . inner . lock ( ) . unwrap ( ) . counterparty_commitment_txs_from_update ( update)
14471448 }
14481449
1450+ /// Wrapper around [`EcdsaChannelSigner::sign_justice_revoked_output`] to make
1451+ /// signing the justice transaction easier for implementors of
1452+ /// [`chain::chainmonitor::Persist`]. On success this method returns the provided transaction
1453+ /// signing the input at `input_idx`. This method will only produce a valid signature for
1454+ /// a transaction spending the `to_local` output of a commitment transaction, i.e. this cannot
1455+ /// be used for revoked HTLC outputs.
1456+ ///
1457+ /// `Value` is the value of the output being spent by the input at `input_idx`, committed
1458+ /// in the BIP 143 signature.
1459+ ///
1460+ /// This method will only succeed if this monitor has received the revocation secret for the
1461+ /// provided `commitment_number`. If a commitment number is provided that does not correspond
1462+ /// to the commitment transaction being revoked, this will return a signed transaction, but
1463+ /// the signature will not be valid.
1464+ ///
1465+ /// [`EcdsaChannelSigner::sign_justice_revoked_output`]: crate::sign::EcdsaChannelSigner::sign_justice_revoked_output
1466+ /// [`Persist`]: crate::chain::chainmonitor::Persist
1467+ pub fn sign_to_local_justice_tx ( & self , justice_tx : Transaction , input_idx : usize , value : u64 , commitment_number : u64 ) -> Result < Transaction , ( ) > {
1468+ self . inner . lock ( ) . unwrap ( ) . sign_to_local_justice_tx ( justice_tx, input_idx, value, commitment_number)
1469+ }
1470+
14491471 pub ( crate ) fn get_min_seen_secret ( & self ) -> u64 {
14501472 self . inner . lock ( ) . unwrap ( ) . get_min_seen_secret ( )
14511473 }
@@ -2810,6 +2832,31 @@ impl<Signer: WriteableEcdsaChannelSigner> ChannelMonitorImpl<Signer> {
28102832 } ) . collect ( )
28112833 }
28122834
2835+ pub ( crate ) fn sign_to_local_justice_tx (
2836+ & self , mut justice_tx : Transaction , input_idx : usize , value : u64 , commitment_number : u64
2837+ ) -> Result < Transaction , ( ) > {
2838+ let secret = self . get_secret ( commitment_number) . ok_or ( ( ) ) ?;
2839+ let per_commitment_key = SecretKey :: from_slice ( & secret) . map_err ( |_| ( ) ) ?;
2840+ let their_per_commitment_point = PublicKey :: from_secret_key (
2841+ & self . onchain_tx_handler . secp_ctx , & per_commitment_key) ;
2842+
2843+ let revocation_pubkey = chan_utils:: derive_public_revocation_key (
2844+ & self . onchain_tx_handler . secp_ctx , & their_per_commitment_point,
2845+ & self . holder_revocation_basepoint ) ;
2846+ let delayed_key = chan_utils:: derive_public_key ( & self . onchain_tx_handler . secp_ctx ,
2847+ & their_per_commitment_point,
2848+ & self . counterparty_commitment_params . counterparty_delayed_payment_base_key ) ;
2849+ let revokeable_redeemscript = chan_utils:: get_revokeable_redeemscript ( & revocation_pubkey,
2850+ self . counterparty_commitment_params . on_counterparty_tx_csv , & delayed_key) ;
2851+
2852+ let sig = self . onchain_tx_handler . signer . sign_justice_revoked_output (
2853+ & justice_tx, input_idx, value, & per_commitment_key, & self . onchain_tx_handler . secp_ctx ) ?;
2854+ justice_tx. input [ input_idx] . witness . push_bitcoin_signature ( & sig. serialize_der ( ) , EcdsaSighashType :: All ) ;
2855+ justice_tx. input [ input_idx] . witness . push ( & [ 1u8 ] ) ;
2856+ justice_tx. input [ input_idx] . witness . push ( revokeable_redeemscript. as_bytes ( ) ) ;
2857+ Ok ( justice_tx)
2858+ }
2859+
28132860 /// Can only fail if idx is < get_min_seen_secret
28142861 fn get_secret ( & self , idx : u64 ) -> Option < [ u8 ; 32 ] > {
28152862 self . commitment_secrets . get_secret ( idx)
0 commit comments