Skip to content

Commit

Permalink
customize to_remote output
Browse files Browse the repository at this point in the history
  • Loading branch information
tankyleo committed Dec 4, 2024
1 parent 7cfcb14 commit feb8b76
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 20 deletions.
5 changes: 3 additions & 2 deletions lightning/src/chain/channelmonitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1338,7 +1338,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
) -> ChannelMonitor<Signer> {

assert!(commitment_transaction_number_obscure_factor <= (1 << 48));
let counterparty_payment_script = chan_utils::get_counterparty_payment_script(
let counterparty_payment_script = keys.get_counterparty_payment_script(
&channel_parameters.channel_type_features, &keys.pubkeys().payment_point
);

Expand Down Expand Up @@ -3388,9 +3388,10 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
&broadcaster_keys, &countersignatory_keys, &self.onchain_tx_handler.secp_ctx);
let channel_parameters =
&self.onchain_tx_handler.channel_transaction_parameters.as_counterparty_broadcastable();
let counterparty_payment_script = self.onchain_tx_handler.signer.get_counterparty_payment_script(&channel_parameters.channel_type_features(), &channel_parameters.countersignatory_pubkeys().payment_point);

CommitmentTransaction::new_with_auxiliary_htlc_data(commitment_number,
to_broadcaster_value, to_countersignatory_value, broadcaster_funding_key,
to_broadcaster_value, to_countersignatory_value, counterparty_payment_script, broadcaster_funding_key,
countersignatory_funding_key, keys, feerate_per_kw, &mut nondust_htlcs,
channel_parameters)
}
Expand Down
35 changes: 19 additions & 16 deletions lightning/src/ln/chan_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ use bitcoin::sighash::EcdsaSighashType;
use bitcoin::transaction::Version;

use bitcoin::hashes::{Hash, HashEngine};
use bitcoin::hashes::hash160::Hash as Hash160;
use bitcoin::hashes::sha256::Hash as Sha256;
use bitcoin::hashes::ripemd160::Hash as Ripemd160;
use bitcoin::hash_types::Txid;
Expand Down Expand Up @@ -1135,7 +1134,9 @@ impl HolderCommitmentTransaction {
for _ in 0..htlcs.len() {
counterparty_htlc_sigs.push(dummy_sig);
}
let inner = CommitmentTransaction::new_with_auxiliary_htlc_data(0, 0, 0, dummy_key.clone(), dummy_key.clone(), keys, 0, htlcs, &channel_parameters.as_counterparty_broadcastable());
let channel_parameters = channel_parameters.as_counterparty_broadcastable();
let counterparty_payment_script = get_counterparty_payment_script(&channel_parameters.channel_type_features(), &channel_parameters.countersignatory_pubkeys().payment_point);
let inner = CommitmentTransaction::new_with_auxiliary_htlc_data(0, 0, 0, counterparty_payment_script, dummy_key.clone(), dummy_key.clone(), keys, 0, htlcs, &channel_parameters);
htlcs.sort_by_key(|htlc| htlc.0.transaction_output_index);
HolderCommitmentTransaction {
inner,
Expand Down Expand Up @@ -1362,6 +1363,7 @@ pub struct CommitmentTransaction {
keys: TxCreationKeys,
// For access to the pre-built transaction, see doc for trust()
built: BuiltCommitmentTransaction,
counterparty_payment_script: ScriptBuf,
}

impl Eq for CommitmentTransaction {}
Expand Down Expand Up @@ -1396,6 +1398,7 @@ impl Writeable for CommitmentTransaction {
(12, self.htlcs, required_vec),
(14, legacy_deserialization_prevention_marker, option),
(15, self.channel_type_features, required),
(16, Some(self.counterparty_payment_script.clone()), option),
});
Ok(())
}
Expand All @@ -1414,6 +1417,7 @@ impl Readable for CommitmentTransaction {
(12, htlcs, required_vec),
(14, _legacy_deserialization_prevention_marker, (option, explicit_type: ())),
(15, channel_type_features, option),
(16, counterparty_payment_script, option),
});

let mut additional_features = ChannelTypeFeatures::empty();
Expand All @@ -1429,7 +1433,8 @@ impl Readable for CommitmentTransaction {
keys: keys.0.unwrap(),
built: built.0.unwrap(),
htlcs,
channel_type_features: channel_type_features.unwrap_or(ChannelTypeFeatures::only_static_remote_key())
channel_type_features: channel_type_features.unwrap_or(ChannelTypeFeatures::only_static_remote_key()),
counterparty_payment_script: counterparty_payment_script.unwrap_or(ScriptBuf::new()),
})
}
}
Expand All @@ -1445,12 +1450,12 @@ impl CommitmentTransaction {
/// Only include HTLCs that are above the dust limit for the channel.
///
/// This is not exported to bindings users due to the generic though we likely should expose a version without
pub fn new_with_auxiliary_htlc_data<T>(commitment_number: u64, to_broadcaster_value_sat: u64, to_countersignatory_value_sat: u64, broadcaster_funding_key: PublicKey, countersignatory_funding_key: PublicKey, keys: TxCreationKeys, feerate_per_kw: u32, htlcs_with_aux: &mut Vec<(HTLCOutputInCommitment, T)>, channel_parameters: &DirectedChannelTransactionParameters) -> CommitmentTransaction {
pub fn new_with_auxiliary_htlc_data<T>(commitment_number: u64, to_broadcaster_value_sat: u64, to_countersignatory_value_sat: u64, counterparty_payment_script: ScriptBuf, broadcaster_funding_key: PublicKey, countersignatory_funding_key: PublicKey, keys: TxCreationKeys, feerate_per_kw: u32, htlcs_with_aux: &mut Vec<(HTLCOutputInCommitment, T)>, channel_parameters: &DirectedChannelTransactionParameters) -> CommitmentTransaction {
let to_broadcaster_value_sat = Amount::from_sat(to_broadcaster_value_sat);
let to_countersignatory_value_sat = Amount::from_sat(to_countersignatory_value_sat);

// Sort outputs and populate output indices while keeping track of the auxiliary data
let (outputs, htlcs) = Self::internal_build_outputs(&keys, to_broadcaster_value_sat, to_countersignatory_value_sat, htlcs_with_aux, channel_parameters, &broadcaster_funding_key, &countersignatory_funding_key).unwrap();
let (outputs, htlcs) = Self::internal_build_outputs(&keys, to_broadcaster_value_sat, to_countersignatory_value_sat, counterparty_payment_script.clone(), htlcs_with_aux, channel_parameters, &broadcaster_funding_key, &countersignatory_funding_key).unwrap();

let (obscured_commitment_transaction_number, txins) = Self::internal_build_inputs(commitment_number, channel_parameters);
let transaction = Self::make_transaction(obscured_commitment_transaction_number, txins, outputs);
Expand All @@ -1468,6 +1473,7 @@ impl CommitmentTransaction {
transaction,
txid
},
counterparty_payment_script,
}
}

Expand All @@ -1483,7 +1489,7 @@ impl CommitmentTransaction {
let (obscured_commitment_transaction_number, txins) = Self::internal_build_inputs(self.commitment_number, channel_parameters);

let mut htlcs_with_aux = self.htlcs.iter().map(|h| (h.clone(), ())).collect();
let (outputs, _) = Self::internal_build_outputs(keys, self.to_broadcaster_value_sat, self.to_countersignatory_value_sat, &mut htlcs_with_aux, channel_parameters, broadcaster_funding_key, countersignatory_funding_key)?;
let (outputs, _) = Self::internal_build_outputs(keys, self.to_broadcaster_value_sat, self.to_countersignatory_value_sat, self.counterparty_payment_script.clone(), &mut htlcs_with_aux, channel_parameters, broadcaster_funding_key, countersignatory_funding_key)?;

let transaction = Self::make_transaction(obscured_commitment_transaction_number, txins, outputs);
let txid = transaction.compute_txid();
Expand All @@ -1507,21 +1513,15 @@ impl CommitmentTransaction {
// - initial sorting of outputs / HTLCs in the constructor, in which case T is auxiliary data the
// caller needs to have sorted together with the HTLCs so it can keep track of the output index
// - building of a bitcoin transaction during a verify() call, in which case T is just ()
fn internal_build_outputs<T>(keys: &TxCreationKeys, to_broadcaster_value_sat: Amount, to_countersignatory_value_sat: Amount, htlcs_with_aux: &mut Vec<(HTLCOutputInCommitment, T)>, channel_parameters: &DirectedChannelTransactionParameters, broadcaster_funding_key: &PublicKey, countersignatory_funding_key: &PublicKey) -> Result<(Vec<TxOut>, Vec<HTLCOutputInCommitment>), ()> {
let countersignatory_pubkeys = channel_parameters.countersignatory_pubkeys();
fn internal_build_outputs<T>(keys: &TxCreationKeys, to_broadcaster_value_sat: Amount, to_countersignatory_value_sat: Amount, counterparty_payment_script: ScriptBuf, htlcs_with_aux: &mut Vec<(HTLCOutputInCommitment, T)>, channel_parameters: &DirectedChannelTransactionParameters, broadcaster_funding_key: &PublicKey, countersignatory_funding_key: &PublicKey) -> Result<(Vec<TxOut>, Vec<HTLCOutputInCommitment>), ()> {
let contest_delay = channel_parameters.contest_delay();

let mut txouts: Vec<(TxOut, Option<&mut HTLCOutputInCommitment>)> = Vec::new();

if to_countersignatory_value_sat > Amount::ZERO {
let script = if channel_parameters.channel_type_features().supports_anchors_zero_fee_htlc_tx() {
get_to_countersignatory_with_anchors_redeemscript(&countersignatory_pubkeys.payment_point).to_p2wsh()
} else {
ScriptBuf::new_p2wpkh(&Hash160::hash(&countersignatory_pubkeys.payment_point.serialize()).into())
};
txouts.push((
TxOut {
script_pubkey: script.clone(),
script_pubkey: counterparty_payment_script,
value: to_countersignatory_value_sat,
},
None,
Expand Down Expand Up @@ -1894,7 +1894,7 @@ pub fn get_commitment_transaction_number_obscure_factor(
mod tests {
use super::{CounterpartyCommitmentSecrets, ChannelPublicKeys};
use crate::chain;
use crate::ln::chan_utils::{get_htlc_redeemscript, get_to_countersignatory_with_anchors_redeemscript, CommitmentTransaction, TxCreationKeys, ChannelTransactionParameters, CounterpartyChannelTransactionParameters, HTLCOutputInCommitment};
use crate::ln::chan_utils::{get_counterparty_payment_script, get_htlc_redeemscript, get_to_countersignatory_with_anchors_redeemscript, CommitmentTransaction, TxCreationKeys, ChannelTransactionParameters, CounterpartyChannelTransactionParameters, HTLCOutputInCommitment};
use bitcoin::secp256k1::{PublicKey, SecretKey, Secp256k1};
use crate::util::test_utils;
use crate::sign::{ChannelSigner, SignerProvider};
Expand Down Expand Up @@ -1957,12 +1957,15 @@ mod tests {
}

fn build(&mut self, to_broadcaster_sats: u64, to_countersignatory_sats: u64) -> CommitmentTransaction {
let channel_parameters = self.channel_parameters.as_holder_broadcastable();
let counterparty_payment_script = get_counterparty_payment_script(&channel_parameters.channel_type_features(), &channel_parameters.countersignatory_pubkeys().payment_point);
CommitmentTransaction::new_with_auxiliary_htlc_data(
self.commitment_number, to_broadcaster_sats, to_countersignatory_sats,
counterparty_payment_script,
self.holder_funding_pubkey.clone(),
self.counterparty_funding_pubkey.clone(),
self.keys.clone(), self.feerate_per_kw,
&mut self.htlcs_with_aux, &self.channel_parameters.as_holder_broadcastable()
&mut self.htlcs_with_aux, &channel_parameters,
)
}
}
Expand Down
2 changes: 2 additions & 0 deletions lightning/src/ln/channel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3165,9 +3165,11 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
let channel_parameters =
if local { self.channel_transaction_parameters.as_holder_broadcastable() }
else { self.channel_transaction_parameters.as_counterparty_broadcastable() };
let counterparty_payment_script = self.holder_signer.as_ref().get_counterparty_payment_script(channel_parameters.channel_type_features(), &channel_parameters.countersignatory_pubkeys().payment_point);
let tx = CommitmentTransaction::new_with_auxiliary_htlc_data(commitment_number,
value_to_a as u64,
value_to_b as u64,
counterparty_payment_script,
funding_pubkey_a,
funding_pubkey_b,
keys.clone(),
Expand Down
10 changes: 8 additions & 2 deletions lightning/src/ln/functional_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -766,16 +766,19 @@ fn test_update_fee_that_funder_cannot_afford() {
|phase| if let ChannelPhase::Funded(chan) = phase { Some(chan) } else { None }
).flatten().unwrap();
let local_chan_signer = local_chan.get_signer();
let channel_parameters = local_chan.context.channel_transaction_parameters.as_counterparty_broadcastable();
let counterparty_payment_script = local_chan_signer.as_ref().get_counterparty_payment_script(&channel_parameters.channel_type_features(), &channel_parameters.countersignatory_pubkeys().payment_point);
let mut htlcs: Vec<(HTLCOutputInCommitment, ())> = vec![];
let commitment_tx = CommitmentTransaction::new_with_auxiliary_htlc_data(
INITIAL_COMMITMENT_NUMBER - 1,
push_sats,
channel_value - push_sats - commit_tx_fee_msat(non_buffer_feerate + 4, 0, &channel_type_features) / 1000,
counterparty_payment_script,
local_funding, remote_funding,
commit_tx_keys.clone(),
non_buffer_feerate + 4,
&mut htlcs,
&local_chan.context.channel_transaction_parameters.as_counterparty_broadcastable()
&channel_parameters,
);
local_chan_signer.as_ecdsa().unwrap().sign_counterparty_commitment(&commitment_tx, Vec::new(), Vec::new(), &secp_ctx).unwrap()
};
Expand Down Expand Up @@ -1517,15 +1520,18 @@ fn test_fee_spike_violation_fails_htlc() {
|phase| if let ChannelPhase::Funded(chan) = phase { Some(chan) } else { None }
).flatten().unwrap();
let local_chan_signer = local_chan.get_signer();
let channel_parameters = local_chan.context.channel_transaction_parameters.as_counterparty_broadcastable();
let counterparty_payment_script = local_chan_signer.as_ref().get_counterparty_payment_script(&channel_parameters.channel_type_features(), &channel_parameters.countersignatory_pubkeys().payment_point);
let commitment_tx = CommitmentTransaction::new_with_auxiliary_htlc_data(
commitment_number,
95000,
local_chan_balance,
counterparty_payment_script,
local_funding, remote_funding,
commit_tx_keys.clone(),
feerate_per_kw,
&mut vec![(accepted_htlc_info, ())],
&local_chan.context.channel_transaction_parameters.as_counterparty_broadcastable()
&channel_parameters,
);
local_chan_signer.as_ecdsa().unwrap().sign_counterparty_commitment(&commitment_tx, Vec::new(), Vec::new(), &secp_ctx).unwrap()
};
Expand Down
6 changes: 6 additions & 0 deletions lightning/src/sign/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -729,6 +729,12 @@ impl HTLCDescriptor {
/// is not yet complete, and panics may occur in certain situations when returning errors
/// for these methods.
pub trait ChannelSigner {
/// Document this next
fn get_counterparty_payment_script(
&self, channel_type_features: &ChannelTypeFeatures, payment_key: &PublicKey,
) -> ScriptBuf {
chan_utils::get_counterparty_payment_script(channel_type_features, payment_key)
}
/// Gets the per-commitment point for a specific commitment number
///
/// Note that the commitment number starts at `(1 << 48) - 1` and counts backwards.
Expand Down

0 comments on commit feb8b76

Please sign in to comment.