Skip to content

Commit

Permalink
begin to collect all segwit v0 stuff for to_local output
Browse files Browse the repository at this point in the history
  • Loading branch information
tankyleo committed Nov 27, 2024
1 parent 12920d8 commit 4c35203
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 60 deletions.
37 changes: 19 additions & 18 deletions lightning/src/chain/channelmonitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ use bitcoin::hashes::Hash;
use bitcoin::hashes::sha256::Hash as Sha256;
use bitcoin::hash_types::{Txid, BlockHash};

use bitcoin::ecdsa::Signature as BitcoinSignature;
use bitcoin::secp256k1::{self, SecretKey, PublicKey, Secp256k1, ecdsa::Signature};

use crate::ln::channel::INITIAL_COMMITMENT_NUMBER;
Expand Down Expand Up @@ -3433,14 +3432,18 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
&self.holder_revocation_basepoint, &their_per_commitment_point);
let delayed_key = DelayedPaymentKey::from_basepoint(&self.onchain_tx_handler.secp_ctx,
&self.counterparty_commitment_params.counterparty_delayed_payment_base_key, &their_per_commitment_point);
let revokeable_redeemscript = chan_utils::get_revokeable_redeemscript(&revocation_pubkey,
self.counterparty_commitment_params.on_counterparty_tx_csv, &delayed_key);

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)?;
justice_tx.input[input_idx].witness.push_ecdsa_signature(&BitcoinSignature::sighash_all(sig));
justice_tx.input[input_idx].witness.push(&[1u8]);
justice_tx.input[input_idx].witness.push(revokeable_redeemscript.as_bytes());
let witness = chan_utils::get_justice_witness(
&revocation_pubkey,
self.counterparty_commitment_params.on_counterparty_tx_csv,
&delayed_key,
&self.onchain_tx_handler.signer,
&justice_tx,
input_idx,
value,
&per_commitment_key,
&self.onchain_tx_handler.secp_ctx
);
justice_tx.input[input_idx].witness = witness;
Ok(justice_tx)
}

Expand Down Expand Up @@ -3495,13 +3498,11 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
let per_commitment_point = PublicKey::from_secret_key(&self.onchain_tx_handler.secp_ctx, &per_commitment_key);
let revocation_pubkey = RevocationKey::from_basepoint(&self.onchain_tx_handler.secp_ctx, &self.holder_revocation_basepoint, &per_commitment_point,);
let delayed_key = DelayedPaymentKey::from_basepoint(&self.onchain_tx_handler.secp_ctx, &self.counterparty_commitment_params.counterparty_delayed_payment_base_key, &PublicKey::from_secret_key(&self.onchain_tx_handler.secp_ctx, &per_commitment_key));

let revokeable_redeemscript = chan_utils::get_revokeable_redeemscript(&revocation_pubkey, self.counterparty_commitment_params.on_counterparty_tx_csv, &delayed_key);
let revokeable_p2wsh = revokeable_redeemscript.to_p2wsh();
let revokeable_spk = chan_utils::get_revokeable_spk(&revocation_pubkey, self.counterparty_commitment_params.on_counterparty_tx_csv, &delayed_key);

// First, process non-htlc outputs (to_holder & to_counterparty)
for (idx, outp) in tx.output.iter().enumerate() {
if outp.script_pubkey == revokeable_p2wsh {
if outp.script_pubkey == revokeable_spk {
let revk_outp = RevokedOutput::build(per_commitment_point, self.counterparty_commitment_params.counterparty_delayed_payment_base_key, self.counterparty_commitment_params.counterparty_htlc_base_key, per_commitment_key, outp.value, self.counterparty_commitment_params.on_counterparty_tx_csv, self.onchain_tx_handler.channel_type_features().supports_anchors_zero_fee_htlc_tx());
let justice_package = PackageTemplate::build_package(
commitment_txid, idx as u32,
Expand Down Expand Up @@ -3616,11 +3617,11 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {

let delayed_key = DelayedPaymentKey::from_basepoint(&self.onchain_tx_handler.secp_ctx, &self.counterparty_commitment_params.counterparty_delayed_payment_base_key, &per_commitment_point);

let revokeable_p2wsh = chan_utils::get_revokeable_redeemscript(&revocation_pubkey,
let revokeable_spk = chan_utils::get_revokeable_spk(&revocation_pubkey,
self.counterparty_commitment_params.on_counterparty_tx_csv,
&delayed_key).to_p2wsh();
&delayed_key);
for (idx, outp) in transaction.output.iter().enumerate() {
if outp.script_pubkey == revokeable_p2wsh {
if outp.script_pubkey == revokeable_spk {
to_counterparty_output_info =
Some((idx.try_into().expect("Can't have > 2^32 outputs"), outp.value));
}
Expand Down Expand Up @@ -3713,8 +3714,8 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
fn get_broadcasted_holder_claims(&self, holder_tx: &HolderSignedTx, conf_height: u32) -> (Vec<PackageTemplate>, Option<(ScriptBuf, PublicKey, RevocationKey)>) {
let mut claim_requests = Vec::with_capacity(holder_tx.htlc_outputs.len());

let redeemscript = chan_utils::get_revokeable_redeemscript(&holder_tx.revocation_key, self.on_holder_tx_csv, &holder_tx.delayed_payment_key);
let broadcasted_holder_revokable_script = Some((redeemscript.to_p2wsh(), holder_tx.per_commitment_point.clone(), holder_tx.revocation_key.clone()));
let revokeable_spk = chan_utils::get_revokeable_spk(&holder_tx.revocation_key, self.on_holder_tx_csv, &holder_tx.delayed_payment_key);
let broadcasted_holder_revokable_script = Some((revokeable_spk, holder_tx.per_commitment_point.clone(), holder_tx.revocation_key.clone()));

for &(ref htlc, _, _) in holder_tx.htlc_outputs.iter() {
if let Some(transaction_output_index) = htlc.transaction_output_index {
Expand Down
11 changes: 2 additions & 9 deletions lightning/src/chain/package.rs
Original file line number Diff line number Diff line change
Expand Up @@ -592,15 +592,8 @@ impl PackageSolvingData {
match self {
PackageSolvingData::RevokedOutput(ref outp) => {
let chan_keys = TxCreationKeys::derive_new(&onchain_handler.secp_ctx, &outp.per_commitment_point, &outp.counterparty_delayed_payment_base_key, &outp.counterparty_htlc_base_key, &onchain_handler.signer.pubkeys().revocation_basepoint, &onchain_handler.signer.pubkeys().htlc_basepoint);
let witness_script = chan_utils::get_revokeable_redeemscript(&chan_keys.revocation_key, outp.on_counterparty_tx_csv, &chan_keys.broadcaster_delayed_payment_key);
//TODO: should we panic on signer failure ?
if let Ok(sig) = onchain_handler.signer.sign_justice_revoked_output(&bumped_tx, i, outp.amount.to_sat(), &outp.per_commitment_key, &onchain_handler.secp_ctx) {
let mut ser_sig = sig.serialize_der().to_vec();
ser_sig.push(EcdsaSighashType::All as u8);
bumped_tx.input[i].witness.push(ser_sig);
bumped_tx.input[i].witness.push(vec!(1));
bumped_tx.input[i].witness.push(witness_script.clone().into_bytes());
} else { return false; }
let witness = chan_utils::get_justice_witness(&chan_keys.revocation_key, outp.on_counterparty_tx_csv, &chan_keys.broadcaster_delayed_payment_key, &onchain_handler.signer, &bumped_tx, i, outp.amount.to_sat(), &outp.per_commitment_key, &onchain_handler.secp_ctx);
bumped_tx.input[i].witness = witness;
},
PackageSolvingData::RevokedHTLCOutput(ref outp) => {
let chan_keys = TxCreationKeys::derive_new(&onchain_handler.secp_ctx, &outp.per_commitment_point, &outp.counterparty_delayed_payment_base_key, &outp.counterparty_htlc_base_key, &onchain_handler.signer.pubkeys().revocation_basepoint, &onchain_handler.signer.pubkeys().htlc_basepoint);
Expand Down
62 changes: 55 additions & 7 deletions lightning/src/ln/chan_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ use bitcoin::hash_types::Txid;
use crate::chain::chaininterface::fee_for_weight;
use crate::chain::package::WEIGHT_REVOKED_OUTPUT;
use crate::sign::EntropySource;
use crate::sign::ecdsa::EcdsaChannelSigner;
use crate::types::payment::{PaymentHash, PaymentPreimage};
use crate::ln::msgs::DecodeError;
use crate::util::ser::{Readable, RequiredWrapper, Writeable, Writer};
Expand All @@ -36,7 +37,7 @@ use crate::util::transaction_utils;
use bitcoin::locktime::absolute::LockTime;
use bitcoin::ecdsa::Signature as BitcoinSignature;
use bitcoin::secp256k1::{SecretKey, PublicKey, Scalar};
use bitcoin::secp256k1::{Secp256k1, ecdsa::Signature, Message};
use bitcoin::secp256k1::{Secp256k1, ecdsa::Signature, Message, All};
use bitcoin::{secp256k1, Sequence, Witness};

use crate::io;
Expand Down Expand Up @@ -548,6 +549,54 @@ pub fn get_revokeable_redeemscript(revocation_key: &RevocationKey, contest_delay
res
}

/// Document this
pub fn get_revokeable_spk(revocation_key: &RevocationKey, contest_delay: u16, broadcaster_delayed_payment_key: &DelayedPaymentKey) -> ScriptBuf {
let revokeable_redeemscript = get_revokeable_redeemscript(revocation_key, contest_delay, broadcaster_delayed_payment_key);
revokeable_redeemscript.to_p2wsh()
}

/// Document this please
pub fn get_justice_witness<S: EcdsaChannelSigner>(revocation_key: &RevocationKey, contest_delay: u16, broadcaster_delayed_payment_key: &DelayedPaymentKey, signer: &S, justice_tx: &Transaction, input_idx: usize, amount: u64, per_commitment_key: &SecretKey, secp_ctx: &Secp256k1<All>) -> Witness {
let sig = signer.sign_justice_revoked_output(justice_tx, input_idx, amount, per_commitment_key, secp_ctx).unwrap();
let revokeable_redeemscript = get_revokeable_redeemscript(revocation_key, contest_delay, broadcaster_delayed_payment_key);
let mut witness = Witness::new();
witness.push_ecdsa_signature(&BitcoinSignature::sighash_all(sig));
witness.push(&[1u8]);
witness.push(revokeable_redeemscript.as_bytes());
witness
}

/// Document this please
pub fn get_to_local_witness<C: secp256k1::Signing, ES: Deref>(revocation_key: &RevocationKey, contest_delay: u16, delayed_payment_key: &SecretKey, spend_tx: &Transaction, input_idx: usize, amount: Amount, secp_ctx: &Secp256k1<C>, entropy_source: &ES) -> Witness
where ES::Target: crate::sign::EntropySource
{
let delayed_payment_pubkey = DelayedPaymentKey::from_secret_key(secp_ctx, delayed_payment_key);
let witness_script = get_revokeable_redeemscript(
revocation_key,
contest_delay,
&delayed_payment_pubkey
);
let sighash = hash_to_message!(
&sighash::SighashCache::new(spend_tx)
.p2wsh_signature_hash(
input_idx,
&witness_script,
amount,
EcdsaSighashType::All
)
.unwrap()[..]
);
let local_delayedsig = bitcoin::ecdsa::Signature {
signature: sign_with_aux_rand(secp_ctx, &sighash, delayed_payment_key, entropy_source),
sighash_type: EcdsaSighashType::All,
};
Witness::from_slice(&[
&local_delayedsig.serialize()[..],
&[],
witness_script.as_bytes(),
])
}

/// Returns the script for the counterparty's output on a holder's commitment transaction based on
/// the channel type.
pub fn get_counterparty_payment_script(channel_type_features: &ChannelTypeFeatures, payment_key: &PublicKey) -> ScriptBuf {
Expand Down Expand Up @@ -750,7 +799,7 @@ pub(crate) fn build_htlc_output(
};

TxOut {
script_pubkey: get_revokeable_redeemscript(revocation_key, contest_delay, broadcaster_delayed_payment_key).to_p2wsh(),
script_pubkey: get_revokeable_spk(revocation_key, contest_delay, broadcaster_delayed_payment_key),
value: output_value,
}
}
Expand Down Expand Up @@ -1529,14 +1578,14 @@ impl CommitmentTransaction {
}

if to_broadcaster_value_sat > Amount::ZERO {
let redeem_script = get_revokeable_redeemscript(
let script_pubkey = get_revokeable_spk(
&keys.revocation_key,
contest_delay,
&keys.broadcaster_delayed_payment_key,
);
txouts.push((
TxOut {
script_pubkey: redeem_script.to_p2wsh(),
script_pubkey,
value: to_broadcaster_value_sat,
},
None,
Expand Down Expand Up @@ -1806,15 +1855,14 @@ impl<'a> TrustedCommitmentTransaction<'a> {
/// commitment transaction previously didn't contain enough information to locate the
/// revokeable output.
pub fn revokeable_output_index(&self) -> Option<usize> {
let revokeable_redeemscript = get_revokeable_redeemscript(
let revokeable_scriptpubkey = get_revokeable_spk(
&self.keys.revocation_key,
self.to_broadcaster_delay?,
&self.keys.broadcaster_delayed_payment_key,
);
let revokeable_p2wsh = revokeable_redeemscript.to_p2wsh();
let outputs = &self.inner.built.transaction.output;
outputs.iter().enumerate()
.find(|(_, out)| out.script_pubkey == revokeable_p2wsh)
.find(|(_, out)| out.script_pubkey == revokeable_scriptpubkey)
.map(|(idx, _)| idx)
}

Expand Down
40 changes: 14 additions & 26 deletions lightning/src/sign/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
use bitcoin::amount::Amount;
use bitcoin::bip32::{ChildNumber, Xpriv, Xpub};
use bitcoin::ecdsa::Signature as EcdsaSignature;
use bitcoin::locktime::absolute::LockTime;
use bitcoin::network::Network;
use bitcoin::opcodes;
Expand Down Expand Up @@ -42,7 +41,7 @@ use crate::chain::transaction::OutPoint;
use crate::crypto::utils::{hkdf_extract_expand_twice, sign, sign_with_aux_rand};
use crate::ln::chan_utils;
use crate::ln::chan_utils::{
get_revokeable_redeemscript, make_funding_redeemscript, ChannelPublicKeys,
get_revokeable_redeemscript, get_revokeable_spk, make_funding_redeemscript, ChannelPublicKeys,
ChannelTransactionParameters, ClosingTransaction, CommitmentTransaction,
HTLCOutputInCommitment, HolderCommitmentTransaction,
};
Expand Down Expand Up @@ -1294,37 +1293,26 @@ impl InMemorySigner {
);
let delayed_payment_pubkey =
DelayedPaymentKey::from_secret_key(&secp_ctx, &delayed_payment_key);
let witness_script = chan_utils::get_revokeable_redeemscript(

let revokeable_spk = get_revokeable_spk(
&descriptor.revocation_pubkey,
descriptor.to_self_delay,
&delayed_payment_pubkey,
);
let sighash = hash_to_message!(
&sighash::SighashCache::new(spend_tx)
.p2wsh_signature_hash(
input_idx,
&witness_script,
descriptor.output.value,
EcdsaSighashType::All
)
.unwrap()[..]
);
let local_delayedsig = EcdsaSignature {
signature: sign_with_aux_rand(secp_ctx, &sighash, &delayed_payment_key, &self),
sighash_type: EcdsaSighashType::All,
};
let payment_script =
bitcoin::Address::p2wsh(&witness_script, Network::Bitcoin).script_pubkey();

if descriptor.output.script_pubkey != payment_script {
if descriptor.output.script_pubkey != revokeable_spk {
return Err(());
}

Ok(Witness::from_slice(&[
&local_delayedsig.serialize()[..],
&[], // MINIMALIF
witness_script.as_bytes(),
]))
Ok(chan_utils::get_to_local_witness(
&descriptor.revocation_pubkey,
descriptor.to_self_delay,
&delayed_payment_key,
spend_tx,
input_idx,
descriptor.output.value,
secp_ctx,
&self,
))
}
}

Expand Down

0 comments on commit 4c35203

Please sign in to comment.