Skip to content

Commit 953bbbe

Browse files
author
Antoine Riard
committed
Split sign_justice_transaction in two halves
To avoid caller data struct storing HTLC-related information when a revokeable output is claimed on top of a commitment/second-stage HTLC transactions, we split `keysinterface::sign_justice_transaction` in two new halves `keysinterfaces::sign_justice_revoked_output` and `keysinterfaces::sign_justice_revoked_htlc`. Further, this split offers more flexibility to signer policy as a commitment revokeable output might be of a value far more significant than HTLC ones.
1 parent fcc0723 commit 953bbbe

File tree

3 files changed

+56
-16
lines changed

3 files changed

+56
-16
lines changed

lightning/src/chain/keysinterface.rs

Lines changed: 45 additions & 13 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.
@@ -297,7 +313,7 @@ pub trait BaseSign {
297313
/// htlc holds HTLC elements (hash, timelock) if the output being spent is a HTLC output, thus
298314
/// changing the format of the witness script (which is committed to in the BIP 143
299315
/// 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, ()>;
316+
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, ()>;
301317

302318
/// Create a signature for a claiming transaction for a HTLC output on a counterparty's commitment
303319
/// transaction, either offered or received.
@@ -624,7 +640,29 @@ impl BaseSign for InMemorySigner {
624640
Ok((sig, htlc_sigs))
625641
}
626642

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, ()> {
643+
fn sign_justice_revoked_output(&self, justice_tx: &Transaction, input: usize, amount: u64, per_commitment_key: &SecretKey, secp_ctx: &Secp256k1<secp256k1::All>) -> Result<Signature, ()> {
644+
let revocation_key = match chan_utils::derive_private_revocation_key(&secp_ctx, &per_commitment_key, &self.revocation_base_key) {
645+
Ok(revocation_key) => revocation_key,
646+
Err(_) => return Err(())
647+
};
648+
let per_commitment_point = PublicKey::from_secret_key(secp_ctx, &per_commitment_key);
649+
let revocation_pubkey = match chan_utils::derive_public_revocation_key(&secp_ctx, &per_commitment_point, &self.pubkeys().revocation_basepoint) {
650+
Ok(revocation_pubkey) => revocation_pubkey,
651+
Err(_) => return Err(())
652+
};
653+
let witness_script = {
654+
let counterparty_delayedpubkey = match chan_utils::derive_public_key(&secp_ctx, &per_commitment_point, &self.counterparty_pubkeys().delayed_payment_basepoint) {
655+
Ok(counterparty_delayedpubkey) => counterparty_delayedpubkey,
656+
Err(_) => return Err(())
657+
};
658+
chan_utils::get_revokeable_redeemscript(&revocation_pubkey, self.holder_selected_contest_delay(), &counterparty_delayedpubkey)
659+
};
660+
let mut sighash_parts = bip143::SigHashCache::new(justice_tx);
661+
let sighash = hash_to_message!(&sighash_parts.signature_hash(input, &witness_script, amount, SigHashType::All)[..]);
662+
return Ok(secp_ctx.sign(&sighash, &revocation_key))
663+
}
664+
665+
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, ()> {
628666
let revocation_key = match chan_utils::derive_private_revocation_key(&secp_ctx, &per_commitment_key, &self.revocation_base_key) {
629667
Ok(revocation_key) => revocation_key,
630668
Err(_) => return Err(())
@@ -634,7 +672,7 @@ impl BaseSign for InMemorySigner {
634672
Ok(revocation_pubkey) => revocation_pubkey,
635673
Err(_) => return Err(())
636674
};
637-
let witness_script = if let &Some(ref htlc) = htlc {
675+
let witness_script = {
638676
let counterparty_htlcpubkey = match chan_utils::derive_public_key(&secp_ctx, &per_commitment_point, &self.counterparty_pubkeys().htlc_basepoint) {
639677
Ok(counterparty_htlcpubkey) => counterparty_htlcpubkey,
640678
Err(_) => return Err(())
@@ -644,12 +682,6 @@ impl BaseSign for InMemorySigner {
644682
Err(_) => return Err(())
645683
};
646684
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)
653685
};
654686
let mut sighash_parts = bip143::SigHashCache::new(justice_tx);
655687
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)