Skip to content

Commit 8bc9ce5

Browse files
committed
Add anchor outputs pair in CommitmentTransaction
The anchor ouputs pair is added if there are pending HTLCs. Or a a per-party anchor is added if the party has a pending balance.
1 parent c53ccf1 commit 8bc9ce5

File tree

3 files changed

+54
-13
lines changed

3 files changed

+54
-13
lines changed

lightning/src/ln/chan_utils.rs

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ use prelude::*;
3636
use core::cmp;
3737
use ln::chan_utils;
3838
use util::transaction_utils::sort_outputs;
39-
use ln::channel::INITIAL_COMMITMENT_NUMBER;
39+
use ln::channel::{INITIAL_COMMITMENT_NUMBER, ANCHOR_OUTPUT_VALUE};
4040
use core::ops::Deref;
4141
use chain;
4242

@@ -771,7 +771,7 @@ impl HolderCommitmentTransaction {
771771
funding_outpoint: Some(chain::transaction::OutPoint { txid: Default::default(), index: 0 })
772772
};
773773
let mut htlcs_with_aux: Vec<(_, ())> = Vec::new();
774-
let inner = CommitmentTransaction::new_with_auxiliary_htlc_data(0, 0, 0, keys, 0, &mut htlcs_with_aux, &channel_parameters.as_counterparty_broadcastable());
774+
let inner = CommitmentTransaction::new_with_auxiliary_htlc_data(0, 0, 0, false, dummy_key.clone(), dummy_key.clone(), keys, 0, &mut htlcs_with_aux, &channel_parameters.as_counterparty_broadcastable());
775775
HolderCommitmentTransaction {
776776
inner,
777777
counterparty_sig: dummy_sig,
@@ -858,6 +858,7 @@ pub struct CommitmentTransaction {
858858
to_countersignatory_value_sat: u64,
859859
feerate_per_kw: u32,
860860
htlcs: Vec<HTLCOutputInCommitment>,
861+
opt_anchors: bool,
861862
// A cache of the parties' pubkeys required to construct the transaction, see doc for trust()
862863
keys: TxCreationKeys,
863864
// For access to the pre-built transaction, see doc for trust()
@@ -871,6 +872,7 @@ impl PartialEq for CommitmentTransaction {
871872
self.to_countersignatory_value_sat == o.to_countersignatory_value_sat &&
872873
self.feerate_per_kw == o.feerate_per_kw &&
873874
self.htlcs == o.htlcs &&
875+
self.opt_anchors == o.opt_anchors &&
874876
self.keys == o.keys;
875877
if eq {
876878
debug_assert_eq!(self.built.transaction, o.built.transaction);
@@ -888,6 +890,7 @@ impl_writeable_tlv_based!(CommitmentTransaction, {
888890
(8, keys, required),
889891
(10, built, required),
890892
(12, htlcs, vec_type),
893+
(14, opt_anchors, required),
891894
});
892895

893896
impl CommitmentTransaction {
@@ -901,9 +904,9 @@ impl CommitmentTransaction {
901904
/// Only include HTLCs that are above the dust limit for the channel.
902905
///
903906
/// (C-not exported) due to the generic though we likely should expose a version without
904-
pub fn new_with_auxiliary_htlc_data<T>(commitment_number: u64, to_broadcaster_value_sat: u64, to_countersignatory_value_sat: u64, keys: TxCreationKeys, feerate_per_kw: u32, htlcs_with_aux: &mut Vec<(HTLCOutputInCommitment, T)>, channel_parameters: &DirectedChannelTransactionParameters) -> CommitmentTransaction {
907+
pub fn new_with_auxiliary_htlc_data<T>(commitment_number: u64, to_broadcaster_value_sat: u64, to_countersignatory_value_sat: u64, opt_anchors: bool, 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 {
905908
// Sort outputs and populate output indices while keeping track of the auxiliary data
906-
let (outputs, htlcs) = Self::internal_build_outputs(&keys, to_broadcaster_value_sat, to_countersignatory_value_sat, htlcs_with_aux, channel_parameters).unwrap();
909+
let (outputs, htlcs) = Self::internal_build_outputs(&keys, to_broadcaster_value_sat, to_countersignatory_value_sat, htlcs_with_aux, channel_parameters, opt_anchors, &broadcaster_funding_key, &countersignatory_funding_key).unwrap();
907910

908911
let (obscured_commitment_transaction_number, txins) = Self::internal_build_inputs(commitment_number, channel_parameters);
909912
let transaction = Self::make_transaction(obscured_commitment_transaction_number, txins, outputs);
@@ -914,6 +917,7 @@ impl CommitmentTransaction {
914917
to_countersignatory_value_sat,
915918
feerate_per_kw,
916919
htlcs,
920+
opt_anchors,
917921
keys,
918922
built: BuiltCommitmentTransaction {
919923
transaction,
@@ -922,11 +926,11 @@ impl CommitmentTransaction {
922926
}
923927
}
924928

925-
fn internal_rebuild_transaction(&self, keys: &TxCreationKeys, channel_parameters: &DirectedChannelTransactionParameters) -> Result<BuiltCommitmentTransaction, ()> {
929+
fn internal_rebuild_transaction(&self, keys: &TxCreationKeys, channel_parameters: &DirectedChannelTransactionParameters, broadcaster_funding_key: &PublicKey, countersignatory_funding_key: &PublicKey) -> Result<BuiltCommitmentTransaction, ()> {
926930
let (obscured_commitment_transaction_number, txins) = Self::internal_build_inputs(self.commitment_number, channel_parameters);
927931

928932
let mut htlcs_with_aux = self.htlcs.iter().map(|h| (h.clone(), ())).collect();
929-
let (outputs, _) = Self::internal_build_outputs(keys, self.to_broadcaster_value_sat, self.to_countersignatory_value_sat, &mut htlcs_with_aux, channel_parameters)?;
933+
let (outputs, _) = Self::internal_build_outputs(keys, self.to_broadcaster_value_sat, self.to_countersignatory_value_sat, &mut htlcs_with_aux, channel_parameters, self.opt_anchors, broadcaster_funding_key, countersignatory_funding_key)?;
930934

931935
let transaction = Self::make_transaction(obscured_commitment_transaction_number, txins, outputs);
932936
let txid = transaction.txid();
@@ -950,7 +954,7 @@ impl CommitmentTransaction {
950954
// - initial sorting of outputs / HTLCs in the constructor, in which case T is auxiliary data the
951955
// caller needs to have sorted together with the HTLCs so it can keep track of the output index
952956
// - building of a bitcoin transaction during a verify() call, in which case T is just ()
953-
fn internal_build_outputs<T>(keys: &TxCreationKeys, to_broadcaster_value_sat: u64, to_countersignatory_value_sat: u64, htlcs_with_aux: &mut Vec<(HTLCOutputInCommitment, T)>, channel_parameters: &DirectedChannelTransactionParameters) -> Result<(Vec<TxOut>, Vec<HTLCOutputInCommitment>), ()> {
957+
fn internal_build_outputs<T>(keys: &TxCreationKeys, to_broadcaster_value_sat: u64, to_countersignatory_value_sat: u64, htlcs_with_aux: &mut Vec<(HTLCOutputInCommitment, T)>, channel_parameters: &DirectedChannelTransactionParameters, opt_anchors: bool, broadcaster_funding_key: &PublicKey, countersignatory_funding_key: &PublicKey) -> Result<(Vec<TxOut>, Vec<HTLCOutputInCommitment>), ()> {
954958
let countersignatory_pubkeys = channel_parameters.countersignatory_pubkeys();
955959
let contest_delay = channel_parameters.contest_delay();
956960

@@ -982,6 +986,30 @@ impl CommitmentTransaction {
982986
));
983987
}
984988

989+
if opt_anchors {
990+
if to_broadcaster_value_sat > 0 || !htlcs_with_aux.is_empty() {
991+
let anchor_script = get_anchor_redeemscript(broadcaster_funding_key);
992+
txouts.push((
993+
TxOut {
994+
script_pubkey: anchor_script.to_v0_p2wsh(),
995+
value: ANCHOR_OUTPUT_VALUE,
996+
},
997+
None,
998+
));
999+
}
1000+
1001+
if to_countersignatory_value_sat > 0 || !htlcs_with_aux.is_empty() {
1002+
let anchor_script = get_anchor_redeemscript(countersignatory_funding_key);
1003+
txouts.push((
1004+
TxOut {
1005+
script_pubkey: anchor_script.to_v0_p2wsh(),
1006+
value: ANCHOR_OUTPUT_VALUE,
1007+
},
1008+
None,
1009+
));
1010+
}
1011+
}
1012+
9851013
let mut htlcs = Vec::with_capacity(htlcs_with_aux.len());
9861014
for (htlc, _) in htlcs_with_aux {
9871015
let script = chan_utils::get_htlc_redeemscript(&htlc, &keys);
@@ -1098,7 +1126,7 @@ impl CommitmentTransaction {
10981126
if keys != self.keys {
10991127
return Err(());
11001128
}
1101-
let tx = self.internal_rebuild_transaction(&keys, channel_parameters)?;
1129+
let tx = self.internal_rebuild_transaction(&keys, channel_parameters, &broadcaster_keys.funding_pubkey, &countersignatory_keys.funding_pubkey)?;
11021130
if self.built.transaction != tx.transaction || self.built.txid != tx.txid {
11031131
return Err(());
11041132
}

lightning/src/ln/channel.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -567,7 +567,9 @@ const COMMITMENT_TX_WEIGHT_PER_HTLC: u64 = 172;
567567
#[cfg(test)]
568568
pub const COMMITMENT_TX_WEIGHT_PER_HTLC: u64 = 172;
569569

570-
/// Maximmum `funding_satoshis` value, according to the BOLT #2 specification
570+
pub const ANCHOR_OUTPUT_VALUE: u64 = 330;
571+
572+
/// Maximum `funding_satoshis` value, according to the BOLT #2 specification
571573
/// it's 2^24.
572574
pub const MAX_FUNDING_SATOSHIS: u64 = 1 << 24;
573575

@@ -1206,6 +1208,11 @@ impl<Signer: Sign> Channel<Signer> {
12061208

12071209
let mut value_to_a = if local { value_to_self } else { value_to_remote };
12081210
let mut value_to_b = if local { value_to_remote } else { value_to_self };
1211+
let (funding_pubkey_a, funding_pubkey_b) = if local {
1212+
(self.get_holder_pubkeys().funding_pubkey, self.get_counterparty_pubkeys().funding_pubkey)
1213+
} else {
1214+
(self.get_counterparty_pubkeys().funding_pubkey, self.get_holder_pubkeys().funding_pubkey)
1215+
};
12091216

12101217
if value_to_a >= (broadcaster_dust_limit_satoshis as i64) {
12111218
log_trace!(logger, " ...including {} output with value {}", if local { "to_local" } else { "to_remote" }, value_to_a);
@@ -1227,6 +1234,9 @@ impl<Signer: Sign> Channel<Signer> {
12271234
let tx = CommitmentTransaction::new_with_auxiliary_htlc_data(commitment_number,
12281235
value_to_a as u64,
12291236
value_to_b as u64,
1237+
false,
1238+
funding_pubkey_a,
1239+
funding_pubkey_b,
12301240
keys.clone(),
12311241
feerate_per_kw,
12321242
&mut included_non_dust_htlcs,

lightning/src/ln/functional_tests.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1297,22 +1297,24 @@ fn test_fee_spike_violation_fails_htlc() {
12971297

12981298
// Get the EnforcingSigner for each channel, which will be used to (1) get the keys
12991299
// needed to sign the new commitment tx and (2) sign the new commitment tx.
1300-
let (local_revocation_basepoint, local_htlc_basepoint, local_secret, next_local_point) = {
1300+
let (local_revocation_basepoint, local_htlc_basepoint, local_secret, next_local_point, local_funding) = {
13011301
let chan_lock = nodes[0].node.channel_state.lock().unwrap();
13021302
let local_chan = chan_lock.by_id.get(&chan.2).unwrap();
13031303
let chan_signer = local_chan.get_signer();
13041304
let pubkeys = chan_signer.pubkeys();
13051305
(pubkeys.revocation_basepoint, pubkeys.htlc_basepoint,
13061306
chan_signer.release_commitment_secret(INITIAL_COMMITMENT_NUMBER),
1307-
chan_signer.get_per_commitment_point(INITIAL_COMMITMENT_NUMBER - 2, &secp_ctx))
1307+
chan_signer.get_per_commitment_point(INITIAL_COMMITMENT_NUMBER - 2, &secp_ctx),
1308+
chan_signer.pubkeys().funding_pubkey)
13081309
};
1309-
let (remote_delayed_payment_basepoint, remote_htlc_basepoint,remote_point) = {
1310+
let (remote_delayed_payment_basepoint, remote_htlc_basepoint, remote_point, remote_funding) = {
13101311
let chan_lock = nodes[1].node.channel_state.lock().unwrap();
13111312
let remote_chan = chan_lock.by_id.get(&chan.2).unwrap();
13121313
let chan_signer = remote_chan.get_signer();
13131314
let pubkeys = chan_signer.pubkeys();
13141315
(pubkeys.delayed_payment_basepoint, pubkeys.htlc_basepoint,
1315-
chan_signer.get_per_commitment_point(INITIAL_COMMITMENT_NUMBER - 1, &secp_ctx))
1316+
chan_signer.get_per_commitment_point(INITIAL_COMMITMENT_NUMBER - 1, &secp_ctx),
1317+
chan_signer.pubkeys().funding_pubkey)
13161318
};
13171319

13181320
// Assemble the set of keys we can use for signatures for our commitment_signed message.
@@ -1341,6 +1343,7 @@ fn test_fee_spike_violation_fails_htlc() {
13411343
commitment_number,
13421344
95000,
13431345
local_chan_balance,
1346+
false, local_funding, remote_funding,
13441347
commit_tx_keys.clone(),
13451348
feerate_per_kw,
13461349
&mut vec![(accepted_htlc_info, ())],

0 commit comments

Comments
 (0)