Skip to content

Commit 3fa527a

Browse files
author
Antoine Riard
committed
Move justice transaction signature behind ChanSigner
1 parent dbb0bbf commit 3fa527a

File tree

5 files changed

+35
-23
lines changed

5 files changed

+35
-23
lines changed

lightning/src/chain/keysinterface.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,9 @@ pub trait ChannelKeys : Send+Clone {
227227
/// HTLC-Success transaction (ie htlc.offered is false), preimage must be set!
228228
fn sign_htlc_transaction<T: secp256k1::Signing>(&self, htlc_tx: &mut Transaction, their_sig: &Signature, preimage: &Option<PaymentPreimage>, htlc: &HTLCOutputInCommitment, a_htlc_key: &PublicKey, b_htlc_key: &PublicKey, revocation_key: &PublicKey, per_commitment_point: &PublicKey, secp_ctx: &Secp256k1<T>);
229229

230+
/// Signs a justice transaction.
231+
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>);
232+
230233
/// Create a signature for a (proposed) closing transaction.
231234
///
232235
/// Note that, due to rounding, there may be one "missing" satoshi, and either party may have
@@ -417,6 +420,22 @@ impl ChannelKeys for InMemoryChannelKeys {
417420
} else { return; }
418421
}
419422

423+
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>) {
424+
if let Ok(revocation_key) = chan_utils::derive_private_revocation_key(&secp_ctx, &per_commitment_key, &self.revocation_base_key) {
425+
let sighash_parts = bip143::SighashComponents::new(&bumped_tx);
426+
let sighash = hash_to_message!(&sighash_parts.sighash_all(&bumped_tx.input[input], &witness_script, amount)[..]);
427+
let sig = secp_ctx.sign(&sighash, &revocation_key);
428+
bumped_tx.input[input].witness.push(sig.serialize_der().to_vec());
429+
bumped_tx.input[input].witness[0].push(SigHashType::All as u8);
430+
if is_htlc {
431+
bumped_tx.input[input].witness.push(revocation_pubkey.clone().serialize().to_vec());
432+
} else {
433+
bumped_tx.input[input].witness.push(vec!(1));
434+
}
435+
bumped_tx.input[input].witness.push(witness_script.clone().into_bytes());
436+
}
437+
}
438+
420439
fn sign_closing_transaction<T: secp256k1::Signing>(&self, closing_tx: &Transaction, secp_ctx: &Secp256k1<T>) -> Result<Signature, ()> {
421440
if closing_tx.input.len() != 1 { return Err(()); }
422441
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
@@ -193,7 +193,7 @@ pub(super) fn derive_public_key<T: secp256k1::Signing>(secp_ctx: &Secp256k1<T>,
193193
/// Derives a revocation key from its constituent parts.
194194
/// Note that this is infallible iff we trust that at least one of the two input keys are randomly
195195
/// generated (ie our own).
196-
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> {
196+
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> {
197197
let revocation_base_point = PublicKey::from_secret_key(&secp_ctx, &revocation_base_secret);
198198
let per_commitment_point = PublicKey::from_secret_key(&secp_ctx, &per_commitment_secret);
199199

lightning/src/ln/channelmonitor.rs

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -425,7 +425,7 @@ struct LocalSignedTx {
425425
pub(crate) enum InputMaterial {
426426
Revoked {
427427
per_commitment_point: PublicKey,
428-
key: SecretKey,
428+
per_commitment_key: SecretKey,
429429
input_descriptor: InputDescriptors,
430430
amount: u64,
431431
},
@@ -448,10 +448,10 @@ pub(crate) enum InputMaterial {
448448
impl Writeable for InputMaterial {
449449
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ::std::io::Error> {
450450
match self {
451-
&InputMaterial::Revoked { ref per_commitment_point, ref key, ref input_descriptor, ref amount} => {
451+
&InputMaterial::Revoked { ref per_commitment_point, ref per_commitment_key, ref input_descriptor, ref amount} => {
452452
writer.write_all(&[0; 1])?;
453453
per_commitment_point.write(writer)?;
454-
writer.write_all(&key[..])?;
454+
writer.write_all(&per_commitment_key[..])?;
455455
input_descriptor.write(writer)?;
456456
writer.write_all(&byte_utils::be64_to_array(*amount))?;
457457
},
@@ -482,12 +482,12 @@ impl Readable for InputMaterial {
482482
let input_material = match <u8 as Readable>::read(reader)? {
483483
0 => {
484484
let per_commitment_point = Readable::read(reader)?;
485-
let key = Readable::read(reader)?;
485+
let per_commitment_key = Readable::read(reader)?;
486486
let input_descriptor = Readable::read(reader)?;
487487
let amount = Readable::read(reader)?;
488488
InputMaterial::Revoked {
489489
per_commitment_point,
490-
key,
490+
per_commitment_key,
491491
input_descriptor,
492492
amount
493493
}
@@ -1445,7 +1445,6 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
14451445
let per_commitment_key = ignore_error!(SecretKey::from_slice(&secret));
14461446
let per_commitment_point = PublicKey::from_secret_key(&self.secp_ctx, &per_commitment_key);
14471447
let revocation_pubkey = ignore_error!(chan_utils::derive_public_revocation_key(&self.secp_ctx, &per_commitment_point, &self.onchain_detection.keys.pubkeys().revocation_basepoint));
1448-
let revocation_key = ignore_error!(chan_utils::derive_private_revocation_key(&self.secp_ctx, &per_commitment_key, &self.onchain_detection.keys.revocation_base_key()));
14491448
let local_payment_key = ignore_error!(chan_utils::derive_private_key(&self.secp_ctx, &per_commitment_point, &self.onchain_detection.keys.payment_base_key()));
14501449
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.unwrap()));
14511450

@@ -1462,7 +1461,7 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
14621461
// First, process non-htlc outputs (to_local & to_remote)
14631462
for (idx, outp) in tx.output.iter().enumerate() {
14641463
if outp.script_pubkey == revokeable_p2wsh {
1465-
let witness_data = InputMaterial::Revoked { per_commitment_point, key: revocation_key, input_descriptor: InputDescriptors::RevokedOutput, amount: outp.value };
1464+
let witness_data = InputMaterial::Revoked { per_commitment_point, per_commitment_key, input_descriptor: InputDescriptors::RevokedOutput, amount: outp.value };
14661465
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});
14671466
}
14681467
}
@@ -1475,7 +1474,7 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
14751474
tx.output[transaction_output_index as usize].value != htlc.amount_msat / 1000 {
14761475
return (claimable_outpoints, (commitment_txid, watch_outputs)); // Corrupted per_commitment_data, fuck this user
14771476
}
1478-
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 };
1477+
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 };
14791478
claimable_outpoints.push(ClaimRequest { absolute_timelock: htlc.cltv_expiry, aggregable: true, outpoint: BitcoinOutPoint { txid: commitment_txid, vout: transaction_output_index }, witness_data });
14801479
}
14811480
}
@@ -1651,10 +1650,9 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
16511650
let secret = if let Some(secret) = self.get_secret(commitment_number) { secret } else { return (Vec::new(), None); };
16521651
let per_commitment_key = ignore_error!(SecretKey::from_slice(&secret));
16531652
let per_commitment_point = PublicKey::from_secret_key(&self.secp_ctx, &per_commitment_key);
1654-
let revocation_key = ignore_error!(chan_utils::derive_private_revocation_key(&self.secp_ctx, &per_commitment_key, &self.onchain_detection.keys.revocation_base_key()));
16551653

16561654
log_trace!(self, "Remote HTLC broadcast {}:{}", htlc_txid, 0);
1657-
let witness_data = InputMaterial::Revoked { per_commitment_point, key: revocation_key, input_descriptor: InputDescriptors::RevokedOutput, amount: tx.output[0].value };
1655+
let witness_data = InputMaterial::Revoked { per_commitment_point, per_commitment_key, input_descriptor: InputDescriptors::RevokedOutput, amount: tx.output[0].value };
16581656
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 });
16591657
(claimable_outpoints, Some((htlc_txid, tx.output.clone())))
16601658
}

lightning/src/ln/onchaintx.rs

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

666666
for (i, (outp, per_outp_material)) in cached_claim_datas.per_input_material.iter().enumerate() {
667667
match per_outp_material {
668-
&InputMaterial::Revoked { ref per_commitment_point, ref key, ref input_descriptor, ref amount } => {
668+
&InputMaterial::Revoked { ref per_commitment_point, ref per_commitment_key, ref input_descriptor, ref amount } => {
669669
if let Ok(chan_keys) = TxCreationKeys::new(&self.secp_ctx, &per_commitment_point, &self.justice_tx_cache.remote_delayed_payment_base_key, &self.justice_tx_cache.remote_htlc_base_key, &self.key_storage.pubkeys().revocation_basepoint, &self.key_storage.pubkeys().payment_basepoint, &self.key_storage.pubkeys().htlc_basepoint) {
670670

671671
let mut this_htlc = None;
@@ -687,17 +687,8 @@ impl<ChanSigner: ChannelKeys> OnchainTxHandler<ChanSigner> {
687687
chan_utils::get_revokeable_redeemscript(&chan_keys.revocation_key, self.remote_csv, &chan_keys.a_delayed_payment_key)
688688
};
689689

690-
let sighash_parts = bip143::SighashComponents::new(&bumped_tx);
691-
let sighash = hash_to_message!(&sighash_parts.sighash_all(&bumped_tx.input[i], &witness_script, *amount)[..]);
692-
let sig = self.secp_ctx.sign(&sighash, &key);
693-
bumped_tx.input[i].witness.push(sig.serialize_der().to_vec());
694-
bumped_tx.input[i].witness[0].push(SigHashType::All as u8);
695-
if *input_descriptor != InputDescriptors::RevokedOutput {
696-
bumped_tx.input[i].witness.push(chan_keys.revocation_key.clone().serialize().to_vec());
697-
} else {
698-
bumped_tx.input[i].witness.push(vec!(1));
699-
}
700-
bumped_tx.input[i].witness.push(witness_script.clone().into_bytes());
690+
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);
691+
701692
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);
702693
}
703694
},

lightning/src/util/enforcing_trait_impls.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,10 @@ impl ChannelKeys for EnforcingChannelKeys {
8989
self.inner.sign_htlc_transaction(htlc_tx, their_sig, preimage, htlc, a_htlc_key, b_htlc_key, revocation_key, per_commitment_point, secp_ctx);
9090
}
9191

92+
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>) {
93+
self.inner.sign_justice_transaction(bumped_tx, input, witness_script, amount, per_commitment_key, revocation_pubkey, is_htlc, secp_ctx);
94+
}
95+
9296
fn sign_closing_transaction<T: secp256k1::Signing>(&self, closing_tx: &Transaction, secp_ctx: &Secp256k1<T>) -> Result<Signature, ()> {
9397
Ok(self.inner.sign_closing_transaction(closing_tx, secp_ctx).unwrap())
9498
}

0 commit comments

Comments
 (0)