@@ -31,7 +31,7 @@ use bitcoin::hash_types::{Txid, BlockHash, WPubkeyHash};
31
31
32
32
use bitcoin:: secp256k1:: { Secp256k1 , ecdsa:: Signature } ;
33
33
use bitcoin:: secp256k1:: { SecretKey , PublicKey } ;
34
- use bitcoin:: secp256k1;
34
+ use bitcoin:: { secp256k1, EcdsaSighashType } ;
35
35
36
36
use crate :: ln:: channel:: INITIAL_COMMITMENT_NUMBER ;
37
37
use crate :: ln:: { PaymentHash , PaymentPreimage } ;
@@ -1438,7 +1438,8 @@ impl<Signer: WriteableEcdsaChannelSigner> ChannelMonitor<Signer> {
1438
1438
/// This is provided so that watchtower clients in the persistence pipeline are able to build
1439
1439
/// justice transactions for each counterparty commitment upon each update. It's intended to be
1440
1440
/// used within an implementation of [`Persist::update_persisted_channel`], which is provided
1441
- /// with a monitor and an update.
1441
+ /// with a monitor and an update. Once revoked, signing a justice transaction can be done using
1442
+ /// [`Self::sign_justice_tx`].
1442
1443
///
1443
1444
/// It is expected that a watchtower may use this method to retrieve the latest counterparty
1444
1445
/// commitment transaction(s), and then hold the necessary data until a later update in which
@@ -1454,6 +1455,20 @@ impl<Signer: WriteableEcdsaChannelSigner> ChannelMonitor<Signer> {
1454
1455
self . inner . lock ( ) . unwrap ( ) . counterparty_commitment_txs_from_update ( update)
1455
1456
}
1456
1457
1458
+ /// Wrapper around [`EcdsaChannelSigner::sign_justice_revoked_output`] to make
1459
+ /// signing the justice transaction easier for implementors of
1460
+ /// [`chain::chainmonitor::Persist`]. On success this method returns a fully signed
1461
+ /// transaction that is ready to be broadcasted.
1462
+ ///
1463
+ /// This method will only succeed if this monitor has received the revocation secret for the
1464
+ /// provided commitment number.
1465
+ ///
1466
+ /// [`EcdsaChannelSigner::sign_justice_revoked_output`]: crate::sign::EcdsaChannelSigner::sign_justice_revoked_output
1467
+ /// [`Persist`]: crate::chain::chainmonitor::Persist
1468
+ pub fn sign_justice_tx ( & self , justice_tx : Transaction , input_idx : usize , value : u64 , commitment_number : u64 ) -> Result < Transaction , ( ) > {
1469
+ self . inner . lock ( ) . unwrap ( ) . sign_justice_tx ( justice_tx, input_idx, value, commitment_number)
1470
+ }
1471
+
1457
1472
pub ( crate ) fn get_min_seen_secret ( & self ) -> u64 {
1458
1473
self . inner . lock ( ) . unwrap ( ) . get_min_seen_secret ( )
1459
1474
}
@@ -2834,6 +2849,31 @@ impl<Signer: WriteableEcdsaChannelSigner> ChannelMonitorImpl<Signer> {
2834
2849
} ) . collect ( )
2835
2850
}
2836
2851
2852
+ pub ( crate ) fn sign_justice_tx (
2853
+ & self , mut justice_tx : Transaction , input_idx : usize , value : u64 , commitment_number : u64
2854
+ ) -> Result < Transaction , ( ) > {
2855
+ let secret = self . get_secret ( commitment_number) . ok_or ( ( ) ) ?;
2856
+ let per_commitment_key = SecretKey :: from_slice ( & secret) . map_err ( |_| ( ) ) ?;
2857
+ let their_per_commitment_point = PublicKey :: from_secret_key (
2858
+ & self . onchain_tx_handler . secp_ctx , & per_commitment_key) ;
2859
+
2860
+ let revocation_pubkey = chan_utils:: derive_public_revocation_key (
2861
+ & self . onchain_tx_handler . secp_ctx , & their_per_commitment_point,
2862
+ & self . holder_revocation_basepoint ) ;
2863
+ let delayed_key = chan_utils:: derive_public_key ( & self . onchain_tx_handler . secp_ctx ,
2864
+ & their_per_commitment_point,
2865
+ & self . counterparty_commitment_params . counterparty_delayed_payment_base_key ) ;
2866
+ let revokeable_redeemscript = chan_utils:: get_revokeable_redeemscript ( & revocation_pubkey,
2867
+ self . counterparty_commitment_params . on_counterparty_tx_csv , & delayed_key) ;
2868
+
2869
+ let sig = self . onchain_tx_handler . signer . sign_justice_revoked_output (
2870
+ & justice_tx, input_idx, value, & per_commitment_key, & self . onchain_tx_handler . secp_ctx ) ?;
2871
+ justice_tx. input [ input_idx] . witness . push_bitcoin_signature ( & sig. serialize_der ( ) , EcdsaSighashType :: All ) ;
2872
+ justice_tx. input [ input_idx] . witness . push ( & [ 1u8 ] ) ;
2873
+ justice_tx. input [ input_idx] . witness . push ( revokeable_redeemscript. as_bytes ( ) ) ;
2874
+ Ok ( justice_tx)
2875
+ }
2876
+
2837
2877
/// Can only fail if idx is < get_min_seen_secret
2838
2878
fn get_secret ( & self , idx : u64 ) -> Option < [ u8 ; 32 ] > {
2839
2879
self . commitment_secrets . get_secret ( idx)
0 commit comments