Skip to content

Commit 40f688e

Browse files
committed
Enable signing a justice tx using the channel monitor
1 parent 82d31a3 commit 40f688e

File tree

1 file changed

+34
-1
lines changed

1 file changed

+34
-1
lines changed

lightning/src/chain/channelmonitor.rs

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ use bitcoin::hash_types::{Txid, BlockHash, WPubkeyHash};
3131

3232
use bitcoin::secp256k1::{Secp256k1, ecdsa::Signature};
3333
use bitcoin::secp256k1::{SecretKey, PublicKey};
34-
use bitcoin::secp256k1;
34+
use bitcoin::{secp256k1, EcdsaSighashType};
3535

3636
use crate::ln::channel::INITIAL_COMMITMENT_NUMBER;
3737
use crate::ln::{PaymentHash, PaymentPreimage};
@@ -1427,6 +1427,14 @@ impl<Signer: WriteableEcdsaChannelSigner> ChannelMonitor<Signer> {
14271427
self.inner.lock().unwrap().counterparty_commitment_txs_from_update(update)
14281428
}
14291429

1430+
/// Wrapper around [`crate::sign::EcdsaChannelSigner::sign_justice_revoked_output`] to make
1431+
/// signing the justice transaction easier for implementors of
1432+
/// [`chain::chainmonitor::Persist`]. On success this method returns a fully signed
1433+
/// transaction that is ready to be broadcasted.
1434+
pub fn sign_justice_tx(&self, justice_tx: Transaction, input_idx: usize, value: u64, commitment_number: u64) -> Result<Transaction, ()> {
1435+
self.inner.lock().unwrap().sign_justice_tx(justice_tx, input_idx, value, commitment_number)
1436+
}
1437+
14301438
pub(crate) fn get_min_seen_secret(&self) -> u64 {
14311439
self.inner.lock().unwrap().get_min_seen_secret()
14321440
}
@@ -2766,6 +2774,31 @@ impl<Signer: WriteableEcdsaChannelSigner> ChannelMonitorImpl<Signer> {
27662774
}).collect()
27672775
}
27682776

2777+
pub(crate) fn sign_justice_tx(&self, mut justice_tx: Transaction, input_idx: usize, value: u64, commitment_number: u64) -> Result<Transaction, ()> {
2778+
2779+
let secret = self.get_secret(commitment_number).ok_or(())?;
2780+
let per_commitment_key = SecretKey::from_slice(&secret).map_err(|_| ())?;
2781+
let their_per_commitment_point = PublicKey::from_secret_key(
2782+
&self.onchain_tx_handler.secp_ctx, &per_commitment_key);
2783+
2784+
let revocation_pubkey = chan_utils::derive_public_revocation_key(
2785+
&self.onchain_tx_handler.secp_ctx, &their_per_commitment_point,
2786+
&self.holder_revocation_basepoint);
2787+
let delayed_key = chan_utils::derive_public_key(&self.onchain_tx_handler.secp_ctx,
2788+
&their_per_commitment_point,
2789+
&self.counterparty_commitment_params.counterparty_delayed_payment_base_key);
2790+
let revokeable_redeemscript = chan_utils::get_revokeable_redeemscript(&revocation_pubkey,
2791+
self.counterparty_commitment_params.on_counterparty_tx_csv, &delayed_key);
2792+
2793+
let sig = self.onchain_tx_handler.signer.sign_justice_revoked_output(&justice_tx, input_idx, value, &per_commitment_key, &self.onchain_tx_handler.secp_ctx)?;
2794+
let mut ser_sig = sig.serialize_der().to_vec();
2795+
ser_sig.push(EcdsaSighashType::All as u8);
2796+
justice_tx.input[input_idx].witness.push(ser_sig);
2797+
justice_tx.input[input_idx].witness.push(vec!(1));
2798+
justice_tx.input[input_idx].witness.push(revokeable_redeemscript.clone().into_bytes());
2799+
Ok(justice_tx)
2800+
}
2801+
27692802
/// Can only fail if idx is < get_min_seen_secret
27702803
fn get_secret(&self, idx: u64) -> Option<[u8; 32]> {
27712804
self.commitment_secrets.get_secret(idx)

0 commit comments

Comments
 (0)