Skip to content

Commit 5d74cae

Browse files
authored
Merge pull request #923 from ariard/2021-05-split-sign-justice
Split `sign_justice_transaction` in two halves
2 parents e0986de + 6319690 commit 5d74cae

File tree

3 files changed

+53
-38
lines changed

3 files changed

+53
-38
lines changed

lightning/src/chain/keysinterface.rs

Lines changed: 42 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -279,12 +279,28 @@ pub trait BaseSign {
279279
#[cfg(any(test,feature = "unsafe_revoked_tx_signing"))]
280280
fn unsafe_sign_holder_commitment_and_htlcs(&self, commitment_tx: &HolderCommitmentTransaction, secp_ctx: &Secp256k1<secp256k1::All>) -> Result<(Signature, Vec<Signature>), ()>;
281281

282-
/// Create a signature for the given input in a transaction spending an HTLC or commitment
283-
/// transaction output when our counterparty broadcasts an old state.
282+
/// Create a signature for the given input in a transaction spending an HTLC transaction output
283+
/// or a commitment transaction `to_local` output when our counterparty broadcasts an old state.
284284
///
285-
/// A justice transaction may claim multiples outputs at the same time if timelocks are
285+
/// A justice transaction may claim multiple outputs at the same time if timelocks are
286286
/// similar, but only a signature for the input at index `input` should be signed for here.
287-
/// It may be called multiples time for same output(s) if a fee-bump is needed with regards
287+
/// It may be called multiple times for same output(s) if a fee-bump is needed with regards
288+
/// to an upcoming timelock expiration.
289+
///
290+
/// Amount is value of the output spent by this input, committed to in the BIP 143 signature.
291+
///
292+
/// per_commitment_key is revocation secret which was provided by our counterparty when they
293+
/// revoked the state which they eventually broadcast. It's not a _holder_ secret key and does
294+
/// not allow the spending of any funds by itself (you need our holder revocation_secret to do
295+
/// so).
296+
fn sign_justice_revoked_output(&self, justice_tx: &Transaction, input: usize, amount: u64, per_commitment_key: &SecretKey, secp_ctx: &Secp256k1<secp256k1::All>) -> Result<Signature, ()>;
297+
298+
/// Create a signature for the given input in a transaction spending a commitment transaction
299+
/// HTLC output when our counterparty broadcasts an old state.
300+
///
301+
/// A justice transaction may claim multiple outputs at the same time if timelocks are
302+
/// similar, but only a signature for the input at index `input` should be signed for here.
303+
/// It may be called multiple times for same output(s) if a fee-bump is needed with regards
288304
/// to an upcoming timelock expiration.
289305
///
290306
/// Amount is value of the output spent by this input, committed to in the BIP 143 signature.
@@ -294,10 +310,9 @@ pub trait BaseSign {
294310
/// not allow the spending of any funds by itself (you need our holder revocation_secret to do
295311
/// so).
296312
///
297-
/// htlc holds HTLC elements (hash, timelock) if the output being spent is a HTLC output, thus
298-
/// changing the format of the witness script (which is committed to in the BIP 143
299-
/// signatures).
300-
fn sign_justice_transaction(&self, justice_tx: &Transaction, input: usize, amount: u64, per_commitment_key: &SecretKey, htlc: &Option<HTLCOutputInCommitment>, secp_ctx: &Secp256k1<secp256k1::All>) -> Result<Signature, ()>;
313+
/// htlc holds HTLC elements (hash, timelock), thus changing the format of the witness script
314+
/// (which is committed to in the BIP 143 signatures).
315+
fn sign_justice_revoked_htlc(&self, justice_tx: &Transaction, input: usize, amount: u64, per_commitment_key: &SecretKey, htlc: &HTLCOutputInCommitment, secp_ctx: &Secp256k1<secp256k1::All>) -> Result<Signature, ()>;
301316

302317
/// Create a signature for a claiming transaction for a HTLC output on a counterparty's commitment
303318
/// transaction, either offered or received.
@@ -593,10 +608,7 @@ impl BaseSign for InMemorySigner {
593608
let htlc_tx = chan_utils::build_htlc_transaction(&commitment_txid, commitment_tx.feerate_per_kw(), self.holder_selected_contest_delay(), htlc, &keys.broadcaster_delayed_payment_key, &keys.revocation_key);
594609
let htlc_redeemscript = chan_utils::get_htlc_redeemscript(&htlc, &keys);
595610
let htlc_sighash = hash_to_message!(&bip143::SigHashCache::new(&htlc_tx).signature_hash(0, &htlc_redeemscript, htlc.amount_msat / 1000, SigHashType::All)[..]);
596-
let holder_htlc_key = match chan_utils::derive_private_key(&secp_ctx, &keys.per_commitment_point, &self.htlc_base_key) {
597-
Ok(s) => s,
598-
Err(_) => return Err(()),
599-
};
611+
let holder_htlc_key = chan_utils::derive_private_key(&secp_ctx, &keys.per_commitment_point, &self.htlc_base_key).map_err(|_| ())?;
600612
htlc_sigs.push(secp_ctx.sign(&htlc_sighash, &holder_htlc_key));
601613
}
602614

@@ -624,32 +636,27 @@ impl BaseSign for InMemorySigner {
624636
Ok((sig, htlc_sigs))
625637
}
626638

627-
fn sign_justice_transaction(&self, justice_tx: &Transaction, input: usize, amount: u64, per_commitment_key: &SecretKey, htlc: &Option<HTLCOutputInCommitment>, secp_ctx: &Secp256k1<secp256k1::All>) -> Result<Signature, ()> {
628-
let revocation_key = match chan_utils::derive_private_revocation_key(&secp_ctx, &per_commitment_key, &self.revocation_base_key) {
629-
Ok(revocation_key) => revocation_key,
630-
Err(_) => return Err(())
631-
};
639+
fn sign_justice_revoked_output(&self, justice_tx: &Transaction, input: usize, amount: u64, per_commitment_key: &SecretKey, secp_ctx: &Secp256k1<secp256k1::All>) -> Result<Signature, ()> {
640+
let revocation_key = chan_utils::derive_private_revocation_key(&secp_ctx, &per_commitment_key, &self.revocation_base_key).map_err(|_| ())?;
632641
let per_commitment_point = PublicKey::from_secret_key(secp_ctx, &per_commitment_key);
633-
let revocation_pubkey = match chan_utils::derive_public_revocation_key(&secp_ctx, &per_commitment_point, &self.pubkeys().revocation_basepoint) {
634-
Ok(revocation_pubkey) => revocation_pubkey,
635-
Err(_) => return Err(())
642+
let revocation_pubkey = chan_utils::derive_public_revocation_key(&secp_ctx, &per_commitment_point, &self.pubkeys().revocation_basepoint).map_err(|_| ())?;
643+
let witness_script = {
644+
let counterparty_delayedpubkey = chan_utils::derive_public_key(&secp_ctx, &per_commitment_point, &self.counterparty_pubkeys().delayed_payment_basepoint).map_err(|_| ())?;
645+
chan_utils::get_revokeable_redeemscript(&revocation_pubkey, self.holder_selected_contest_delay(), &counterparty_delayedpubkey)
636646
};
637-
let witness_script = if let &Some(ref htlc) = htlc {
638-
let counterparty_htlcpubkey = match chan_utils::derive_public_key(&secp_ctx, &per_commitment_point, &self.counterparty_pubkeys().htlc_basepoint) {
639-
Ok(counterparty_htlcpubkey) => counterparty_htlcpubkey,
640-
Err(_) => return Err(())
641-
};
642-
let holder_htlcpubkey = match chan_utils::derive_public_key(&secp_ctx, &per_commitment_point, &self.pubkeys().htlc_basepoint) {
643-
Ok(holder_htlcpubkey) => holder_htlcpubkey,
644-
Err(_) => return Err(())
645-
};
647+
let mut sighash_parts = bip143::SigHashCache::new(justice_tx);
648+
let sighash = hash_to_message!(&sighash_parts.signature_hash(input, &witness_script, amount, SigHashType::All)[..]);
649+
return Ok(secp_ctx.sign(&sighash, &revocation_key))
650+
}
651+
652+
fn sign_justice_revoked_htlc(&self, justice_tx: &Transaction, input: usize, amount: u64, per_commitment_key: &SecretKey, htlc: &HTLCOutputInCommitment, secp_ctx: &Secp256k1<secp256k1::All>) -> Result<Signature, ()> {
653+
let revocation_key = chan_utils::derive_private_revocation_key(&secp_ctx, &per_commitment_key, &self.revocation_base_key).map_err(|_| ())?;
654+
let per_commitment_point = PublicKey::from_secret_key(secp_ctx, &per_commitment_key);
655+
let revocation_pubkey = chan_utils::derive_public_revocation_key(&secp_ctx, &per_commitment_point, &self.pubkeys().revocation_basepoint).map_err(|_| ())?;
656+
let witness_script = {
657+
let counterparty_htlcpubkey = chan_utils::derive_public_key(&secp_ctx, &per_commitment_point, &self.counterparty_pubkeys().htlc_basepoint).map_err(|_| ())?;
658+
let holder_htlcpubkey = chan_utils::derive_public_key(&secp_ctx, &per_commitment_point, &self.pubkeys().htlc_basepoint).map_err(|_| ())?;
646659
chan_utils::get_htlc_redeemscript_with_explicit_keys(&htlc, &counterparty_htlcpubkey, &holder_htlcpubkey, &revocation_pubkey)
647-
} else {
648-
let counterparty_delayedpubkey = match chan_utils::derive_public_key(&secp_ctx, &per_commitment_point, &self.counterparty_pubkeys().delayed_payment_basepoint) {
649-
Ok(counterparty_delayedpubkey) => counterparty_delayedpubkey,
650-
Err(_) => return Err(())
651-
};
652-
chan_utils::get_revokeable_redeemscript(&revocation_pubkey, self.holder_selected_contest_delay(), &counterparty_delayedpubkey)
653660
};
654661
let mut sighash_parts = bip143::SigHashCache::new(justice_tx);
655662
let sighash = hash_to_message!(&sighash_parts.signature_hash(input, &witness_script, amount, SigHashType::All)[..]);

lightning/src/ln/onchaintx.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -628,7 +628,11 @@ impl<ChannelSigner: Sign> OnchainTxHandler<ChannelSigner> {
628628
chan_utils::get_revokeable_redeemscript(&tx_keys.revocation_key, *on_counterparty_tx_csv, &tx_keys.broadcaster_delayed_payment_key)
629629
};
630630

631-
let sig = self.signer.sign_justice_transaction(&bumped_tx, i, *amount, &per_commitment_key, htlc, &self.secp_ctx).expect("sign justice tx");
631+
let sig = if let Some(ref htlc) = *htlc {
632+
self.signer.sign_justice_revoked_htlc(&bumped_tx, i, *amount, &per_commitment_key, &htlc, &self.secp_ctx).expect("sign justice tx")
633+
} else {
634+
self.signer.sign_justice_revoked_output(&bumped_tx, i, *amount, &per_commitment_key, &self.secp_ctx).expect("sign justice tx")
635+
};
632636
bumped_tx.input[i].witness.push(sig.serialize_der().to_vec());
633637
bumped_tx.input[i].witness[0].push(SigHashType::All as u8);
634638
if htlc.is_some() {

lightning/src/util/enforcing_trait_impls.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,8 +140,12 @@ impl BaseSign for EnforcingSigner {
140140
Ok(self.inner.unsafe_sign_holder_commitment_and_htlcs(commitment_tx, secp_ctx).unwrap())
141141
}
142142

143-
fn sign_justice_transaction(&self, justice_tx: &Transaction, input: usize, amount: u64, per_commitment_key: &SecretKey, htlc: &Option<HTLCOutputInCommitment>, secp_ctx: &Secp256k1<secp256k1::All>) -> Result<Signature, ()> {
144-
Ok(self.inner.sign_justice_transaction(justice_tx, input, amount, per_commitment_key, htlc, secp_ctx).unwrap())
143+
fn sign_justice_revoked_output(&self, justice_tx: &Transaction, input: usize, amount: u64, per_commitment_key: &SecretKey, secp_ctx: &Secp256k1<secp256k1::All>) -> Result<Signature, ()> {
144+
Ok(self.inner.sign_justice_revoked_output(justice_tx, input, amount, per_commitment_key, secp_ctx).unwrap())
145+
}
146+
147+
fn sign_justice_revoked_htlc(&self, justice_tx: &Transaction, input: usize, amount: u64, per_commitment_key: &SecretKey, htlc: &HTLCOutputInCommitment, secp_ctx: &Secp256k1<secp256k1::All>) -> Result<Signature, ()> {
148+
Ok(self.inner.sign_justice_revoked_htlc(justice_tx, input, amount, per_commitment_key, htlc, secp_ctx).unwrap())
145149
}
146150

147151
fn sign_counterparty_htlc_transaction(&self, htlc_tx: &Transaction, input: usize, amount: u64, per_commitment_point: &PublicKey, htlc: &HTLCOutputInCommitment, secp_ctx: &Secp256k1<secp256k1::All>) -> Result<Signature, ()> {

0 commit comments

Comments
 (0)