Skip to content

Commit 6cf265e

Browse files
committed
Enable signing a justice tx using the channel monitor
1 parent 686365b commit 6cf265e

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};
@@ -1369,6 +1369,14 @@ impl<Signer: WriteableEcdsaChannelSigner> ChannelMonitor<Signer> {
13691369
self.inner.lock().unwrap().counterparty_commitment_txs_from_update(update)
13701370
}
13711371

1372+
/// Wrapper around [`crate::sign::EcdsaChannelSigner::sign_justice_revoked_output`] to make
1373+
/// signing the justice transaction easier for implementors of
1374+
/// [`chain::chainmonitor::Persist`]. On success this method returns a fully signed
1375+
/// transaction that is ready to be broadcasted.
1376+
pub fn sign_justice_tx(&self, justice_tx: Transaction, input_idx: usize, value: u64, commitment_number: u64) -> Result<Transaction, ()> {
1377+
self.inner.lock().unwrap().sign_justice_tx(justice_tx, input_idx, value, commitment_number)
1378+
}
1379+
13721380
pub(crate) fn get_min_seen_secret(&self) -> u64 {
13731381
self.inner.lock().unwrap().get_min_seen_secret()
13741382
}
@@ -2697,6 +2705,31 @@ impl<Signer: WriteableEcdsaChannelSigner> ChannelMonitorImpl<Signer> {
26972705
}).collect()
26982706
}
26992707

2708+
pub(crate) fn sign_justice_tx(&self, mut justice_tx: Transaction, input_idx: usize, value: u64, commitment_number: u64) -> Result<Transaction, ()> {
2709+
2710+
let secret = self.get_secret(commitment_number).ok_or(())?;
2711+
let per_commitment_key = SecretKey::from_slice(&secret).map_err(|_| ())?;
2712+
let their_per_commitment_point = PublicKey::from_secret_key(
2713+
&self.onchain_tx_handler.secp_ctx, &per_commitment_key);
2714+
2715+
let revocation_pubkey = chan_utils::derive_public_revocation_key(
2716+
&self.onchain_tx_handler.secp_ctx, &their_per_commitment_point,
2717+
&self.holder_revocation_basepoint);
2718+
let delayed_key = chan_utils::derive_public_key(&self.onchain_tx_handler.secp_ctx,
2719+
&their_per_commitment_point,
2720+
&self.counterparty_commitment_params.counterparty_delayed_payment_base_key);
2721+
let revokeable_redeemscript = chan_utils::get_revokeable_redeemscript(&revocation_pubkey,
2722+
self.counterparty_commitment_params.on_counterparty_tx_csv, &delayed_key);
2723+
2724+
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)?;
2725+
let mut ser_sig = sig.serialize_der().to_vec();
2726+
ser_sig.push(EcdsaSighashType::All as u8);
2727+
justice_tx.input[input_idx].witness.push(ser_sig);
2728+
justice_tx.input[input_idx].witness.push(vec!(1));
2729+
justice_tx.input[input_idx].witness.push(revokeable_redeemscript.clone().into_bytes());
2730+
Ok(justice_tx)
2731+
}
2732+
27002733
/// Can only fail if idx is < get_min_seen_secret
27012734
fn get_secret(&self, idx: u64) -> Option<[u8; 32]> {
27022735
self.commitment_secrets.get_secret(idx)

0 commit comments

Comments
 (0)