Skip to content

Commit 2f041ee

Browse files
author
Antoine Riard
committed
Move justice transaction signature behind ChanSigner
1 parent beef1e7 commit 2f041ee

File tree

5 files changed

+37
-24
lines changed

5 files changed

+37
-24
lines changed

lightning/src/chain/keysinterface.rs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//! spendable on-chain outputs which the user owns and is responsible for using just as any other
33
//! on-chain output which is theirs.
44
5-
use bitcoin::blockdata::transaction::{Transaction, OutPoint, TxOut};
5+
use bitcoin::blockdata::transaction::{Transaction, OutPoint, TxOut, SigHashType};
66
use bitcoin::blockdata::script::{Script, Builder};
77
use bitcoin::blockdata::opcodes;
88
use bitcoin::network::constants::Network;
@@ -245,6 +245,9 @@ pub trait ChannelKeys : Send+Clone {
245245
/// return value must contain a signature.
246246
fn sign_local_commitment_htlc_transactions<T: secp256k1::Signing + secp256k1::Verification>(&self, local_commitment_tx: &LocalCommitmentTransaction, local_csv: u16, secp_ctx: &Secp256k1<T>) -> Result<Vec<Option<Signature>>, ()>;
247247

248+
/// Signs a justice transaction.
249+
fn sign_justice_transaction<T: secp256k1::Signing>(&self, bumped_tx: &mut Transaction, input: usize, witness_script: &Script, amount: u64, per_commitment_key: &SecretKey, revocation_pubkey: &PublicKey, is_htlc: bool, secp_ctx: &Secp256k1<T>);
250+
248251
/// Create a signature for a (proposed) closing transaction.
249252
///
250253
/// Note that, due to rounding, there may be one "missing" satoshi, and either party may have
@@ -393,6 +396,22 @@ impl ChannelKeys for InMemoryChannelKeys {
393396
local_commitment_tx.get_htlc_sigs(&self.htlc_base_key, local_csv, secp_ctx)
394397
}
395398

399+
fn sign_justice_transaction<T: secp256k1::Signing>(&self, bumped_tx: &mut Transaction, input: usize, witness_script: &Script, amount: u64, per_commitment_key: &SecretKey, revocation_pubkey: &PublicKey, is_htlc: bool, secp_ctx: &Secp256k1<T>) {
400+
if let Ok(revocation_key) = chan_utils::derive_private_revocation_key(&secp_ctx, &per_commitment_key, &self.revocation_base_key) {
401+
let sighash_parts = bip143::SighashComponents::new(&bumped_tx);
402+
let sighash = hash_to_message!(&sighash_parts.sighash_all(&bumped_tx.input[input], &witness_script, amount)[..]);
403+
let sig = secp_ctx.sign(&sighash, &revocation_key);
404+
bumped_tx.input[input].witness.push(sig.serialize_der().to_vec());
405+
bumped_tx.input[input].witness[0].push(SigHashType::All as u8);
406+
if is_htlc {
407+
bumped_tx.input[input].witness.push(revocation_pubkey.clone().serialize().to_vec());
408+
} else {
409+
bumped_tx.input[input].witness.push(vec!(1));
410+
}
411+
bumped_tx.input[input].witness.push(witness_script.clone().into_bytes());
412+
}
413+
}
414+
396415
fn sign_closing_transaction<T: secp256k1::Signing>(&self, closing_tx: &Transaction, secp_ctx: &Secp256k1<T>) -> Result<Signature, ()> {
397416
if closing_tx.input.len() != 1 { return Err(()); }
398417
if closing_tx.input[0].witness.len() != 0 { return Err(()); }

lightning/src/ln/chan_utils.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ pub(super) fn derive_public_key<T: secp256k1::Signing>(secp_ctx: &Secp256k1<T>,
198198
/// Derives a revocation key from its constituent parts.
199199
/// Note that this is infallible iff we trust that at least one of the two input keys are randomly
200200
/// generated (ie our own).
201-
pub(super) fn derive_private_revocation_key<T: secp256k1::Signing>(secp_ctx: &Secp256k1<T>, per_commitment_secret: &SecretKey, revocation_base_secret: &SecretKey) -> Result<SecretKey, secp256k1::Error> {
201+
pub fn derive_private_revocation_key<T: secp256k1::Signing>(secp_ctx: &Secp256k1<T>, per_commitment_secret: &SecretKey, revocation_base_secret: &SecretKey) -> Result<SecretKey, secp256k1::Error> {
202202
let revocation_base_point = PublicKey::from_secret_key(&secp_ctx, &revocation_base_secret);
203203
let per_commitment_point = PublicKey::from_secret_key(&secp_ctx, &per_commitment_secret);
204204

lightning/src/ln/channelmonitor.rs

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -426,7 +426,7 @@ struct LocalSignedTx {
426426
pub(crate) enum InputMaterial {
427427
Revoked {
428428
per_commitment_point: PublicKey,
429-
key: SecretKey,
429+
per_commitment_key: SecretKey,
430430
input_descriptor: InputDescriptors,
431431
amount: u64,
432432
},
@@ -449,10 +449,10 @@ pub(crate) enum InputMaterial {
449449
impl Writeable for InputMaterial {
450450
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ::std::io::Error> {
451451
match self {
452-
&InputMaterial::Revoked { ref per_commitment_point, ref key, ref input_descriptor, ref amount} => {
452+
&InputMaterial::Revoked { ref per_commitment_point, ref per_commitment_key, ref input_descriptor, ref amount} => {
453453
writer.write_all(&[0; 1])?;
454454
per_commitment_point.write(writer)?;
455-
writer.write_all(&key[..])?;
455+
writer.write_all(&per_commitment_key[..])?;
456456
input_descriptor.write(writer)?;
457457
writer.write_all(&byte_utils::be64_to_array(*amount))?;
458458
},
@@ -483,12 +483,12 @@ impl Readable for InputMaterial {
483483
let input_material = match <u8 as Readable>::read(reader)? {
484484
0 => {
485485
let per_commitment_point = Readable::read(reader)?;
486-
let key = Readable::read(reader)?;
486+
let per_commitment_key = Readable::read(reader)?;
487487
let input_descriptor = Readable::read(reader)?;
488488
let amount = Readable::read(reader)?;
489489
InputMaterial::Revoked {
490490
per_commitment_point,
491-
key,
491+
per_commitment_key,
492492
input_descriptor,
493493
amount
494494
}
@@ -1451,7 +1451,6 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
14511451
let per_commitment_key = ignore_error!(SecretKey::from_slice(&secret));
14521452
let per_commitment_point = PublicKey::from_secret_key(&self.secp_ctx, &per_commitment_key);
14531453
let revocation_pubkey = ignore_error!(chan_utils::derive_public_revocation_key(&self.secp_ctx, &per_commitment_point, &self.keys.pubkeys().revocation_basepoint));
1454-
let revocation_key = ignore_error!(chan_utils::derive_private_revocation_key(&self.secp_ctx, &per_commitment_key, &self.keys.revocation_base_key()));
14551454
let local_payment_key = ignore_error!(chan_utils::derive_private_key(&self.secp_ctx, &per_commitment_point, &self.keys.payment_base_key()));
14561455
let delayed_key = ignore_error!(chan_utils::derive_public_key(&self.secp_ctx, &PublicKey::from_secret_key(&self.secp_ctx, &per_commitment_key), &self.their_delayed_payment_base_key));
14571456

@@ -1468,7 +1467,7 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
14681467
// First, process non-htlc outputs (to_local & to_remote)
14691468
for (idx, outp) in tx.output.iter().enumerate() {
14701469
if outp.script_pubkey == revokeable_p2wsh {
1471-
let witness_data = InputMaterial::Revoked { per_commitment_point, key: revocation_key, input_descriptor: InputDescriptors::RevokedOutput, amount: outp.value };
1470+
let witness_data = InputMaterial::Revoked { per_commitment_point, per_commitment_key, input_descriptor: InputDescriptors::RevokedOutput, amount: outp.value };
14721471
claimable_outpoints.push(ClaimRequest { absolute_timelock: height + self.our_to_self_delay as u32, aggregable: true, outpoint: BitcoinOutPoint { txid: commitment_txid, vout: idx as u32 }, witness_data});
14731472
}
14741473
}
@@ -1481,7 +1480,7 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
14811480
tx.output[transaction_output_index as usize].value != htlc.amount_msat / 1000 {
14821481
return (claimable_outpoints, (commitment_txid, watch_outputs)); // Corrupted per_commitment_data, fuck this user
14831482
}
1484-
let witness_data = InputMaterial::Revoked { per_commitment_point, key: revocation_key, input_descriptor: if htlc.offered { InputDescriptors::RevokedOfferedHTLC } else { InputDescriptors::RevokedReceivedHTLC }, amount: tx.output[transaction_output_index as usize].value };
1483+
let witness_data = InputMaterial::Revoked { per_commitment_point, per_commitment_key, input_descriptor: if htlc.offered { InputDescriptors::RevokedOfferedHTLC } else { InputDescriptors::RevokedReceivedHTLC }, amount: tx.output[transaction_output_index as usize].value };
14851484
claimable_outpoints.push(ClaimRequest { absolute_timelock: htlc.cltv_expiry, aggregable: true, outpoint: BitcoinOutPoint { txid: commitment_txid, vout: transaction_output_index }, witness_data });
14861485
}
14871486
}
@@ -1654,10 +1653,9 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
16541653
let secret = if let Some(secret) = self.get_secret(commitment_number) { secret } else { return (Vec::new(), None); };
16551654
let per_commitment_key = ignore_error!(SecretKey::from_slice(&secret));
16561655
let per_commitment_point = PublicKey::from_secret_key(&self.secp_ctx, &per_commitment_key);
1657-
let revocation_key = ignore_error!(chan_utils::derive_private_revocation_key(&self.secp_ctx, &per_commitment_key, &self.keys.revocation_base_key()));
16581656

16591657
log_trace!(self, "Remote HTLC broadcast {}:{}", htlc_txid, 0);
1660-
let witness_data = InputMaterial::Revoked { per_commitment_point, key: revocation_key, input_descriptor: InputDescriptors::RevokedOutput, amount: tx.output[0].value };
1658+
let witness_data = InputMaterial::Revoked { per_commitment_point, per_commitment_key, input_descriptor: InputDescriptors::RevokedOutput, amount: tx.output[0].value };
16611659
let claimable_outpoints = vec!(ClaimRequest { absolute_timelock: height + self.our_to_self_delay as u32, aggregable: true, outpoint: BitcoinOutPoint { txid: htlc_txid, vout: 0}, witness_data });
16621660
(claimable_outpoints, Some((htlc_txid, tx.output.clone())))
16631661
}

lightning/src/ln/onchaintx.rs

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -635,7 +635,7 @@ impl<ChanSigner: ChannelKeys> OnchainTxHandler<ChanSigner> {
635635

636636
for (i, (outp, per_outp_material)) in cached_claim_datas.per_input_material.iter().enumerate() {
637637
match per_outp_material {
638-
&InputMaterial::Revoked { ref per_commitment_point, ref key, ref input_descriptor, ref amount } => {
638+
&InputMaterial::Revoked { ref per_commitment_point, ref per_commitment_key, ref input_descriptor, ref amount } => {
639639
if let Ok(chan_keys) = TxCreationKeys::new(&self.secp_ctx, &per_commitment_point, &self.remote_tx_cache.remote_delayed_payment_base_key, &self.remote_tx_cache.remote_htlc_base_key, &self.key_storage.pubkeys().revocation_basepoint, &self.key_storage.pubkeys().payment_basepoint, &self.key_storage.pubkeys().htlc_basepoint) {
640640

641641
let mut this_htlc = None;
@@ -657,17 +657,8 @@ impl<ChanSigner: ChannelKeys> OnchainTxHandler<ChanSigner> {
657657
chan_utils::get_revokeable_redeemscript(&chan_keys.revocation_key, self.remote_csv, &chan_keys.a_delayed_payment_key)
658658
};
659659

660-
let sighash_parts = bip143::SighashComponents::new(&bumped_tx);
661-
let sighash = hash_to_message!(&sighash_parts.sighash_all(&bumped_tx.input[i], &witness_script, *amount)[..]);
662-
let sig = self.secp_ctx.sign(&sighash, &key);
663-
bumped_tx.input[i].witness.push(sig.serialize_der().to_vec());
664-
bumped_tx.input[i].witness[0].push(SigHashType::All as u8);
665-
if *input_descriptor != InputDescriptors::RevokedOutput {
666-
bumped_tx.input[i].witness.push(chan_keys.revocation_key.clone().serialize().to_vec());
667-
} else {
668-
bumped_tx.input[i].witness.push(vec!(1));
669-
}
670-
bumped_tx.input[i].witness.push(witness_script.clone().into_bytes());
660+
self.key_storage.sign_justice_transaction(&mut bumped_tx, i, &witness_script, *amount, &per_commitment_key, &chan_keys.revocation_key, *input_descriptor != InputDescriptors::RevokedOutput, &self.secp_ctx);
661+
671662
log_trace!(self, "Going to broadcast Penalty Transaction {} claiming revoked {} output {} from {} with new feerate {}...", bumped_tx.txid(), if *input_descriptor == InputDescriptors::RevokedOutput { "to_local" } else if *input_descriptor == InputDescriptors::RevokedOfferedHTLC { "offered" } else if *input_descriptor == InputDescriptors::RevokedReceivedHTLC { "received" } else { "" }, outp.vout, outp.txid, new_feerate);
672663
}
673664
},

lightning/src/util/enforcing_trait_impls.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use std::cmp;
66
use std::sync::{Mutex, Arc};
77

88
use bitcoin::blockdata::transaction::Transaction;
9+
use bitcoin::blockdata::script::Script;
910
use bitcoin::util::bip143;
1011

1112
use secp256k1;
@@ -105,6 +106,10 @@ impl ChannelKeys for EnforcingChannelKeys {
105106
Ok(self.inner.sign_local_commitment_htlc_transactions(local_commitment_tx, local_csv, secp_ctx).unwrap())
106107
}
107108

109+
fn sign_justice_transaction<T: secp256k1::Signing>(&self, bumped_tx: &mut Transaction, input: usize, witness_script: &Script, amount: u64, per_commitment_key: &SecretKey, revocation_pubkey: &PublicKey, is_htlc: bool, secp_ctx: &Secp256k1<T>) {
110+
self.inner.sign_justice_transaction(bumped_tx, input, witness_script, amount, per_commitment_key, revocation_pubkey, is_htlc, secp_ctx);
111+
}
112+
108113
fn sign_closing_transaction<T: secp256k1::Signing>(&self, closing_tx: &Transaction, secp_ctx: &Secp256k1<T>) -> Result<Signature, ()> {
109114
Ok(self.inner.sign_closing_transaction(closing_tx, secp_ctx).unwrap())
110115
}

0 commit comments

Comments
 (0)