Skip to content

Commit 445bd2b

Browse files
author
Antoine Riard
committed
Add anchor outputs pair in commitment tx
The anchor ouputs pair is added if there are pending HTLCs. Or a a per-party anchor is added if this party has a pending balance.
1 parent 1cefd9c commit 445bd2b

File tree

4 files changed

+102
-29
lines changed

4 files changed

+102
-29
lines changed

lightning/src/ln/channel.rs

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -906,8 +906,6 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
906906
}
907907
}
908908

909-
// If we initiate the commitment update, inbound HTLC flowing from our counterparty
910-
// to us
911909
for ref htlc in self.pending_inbound_htlcs.iter() {
912910
let (include, state_name) = match htlc.state {
913911
InboundHTLCState::RemoteAnnounced(_) => (!building_for_counterparty, "RemoteAnnounced"),
@@ -987,14 +985,27 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
987985
broadcaster_max_commitment_tx_output.1 = cmp::max(broadcaster_max_commitment_tx_output.1, counterparty_value_msat as u64);
988986
}
989987

990-
let total_fee = feerate_per_kw as u64 * (COMMITMENT_TX_BASE_WEIGHT + (txouts.len() as u64) * COMMITMENT_TX_WEIGHT_PER_HTLC) / 1000;
988+
// If `option_anchor_output` applies to the commitment transaction,
989+
// * we account anchor output weight in commitment *expected weight*
990+
// * we substract two times the fixed anchor sizze of 330 sats from funder balance
991+
//
992+
// Note, we already enforced that funder can afford two anchors at `update_add_htlc`
993+
// acceptance.
994+
995+
let total_fee: u64 = feerate_per_kw as u64 * (COMMITMENT_TX_BASE_WEIGHT + (txouts.len() as u64) * COMMITMENT_TX_WEIGHT_PER_HTLC + 2 * COMMITMENT_TX_WEIGHT_PER_ANCHOR) / (1000 as u64);
996+
991997
let (holder_value, counterparty_value) = if self.channel_outbound {
992-
(holder_value_msat / 1000 - total_fee as i64, counterparty_value_msat / 1000)
998+
(holder_value_msat / 1000 - total_fee as i64 - 2 * ANCHOR_OUTPUT_VALUE as i64, counterparty_value_msat / 1000)
993999
} else {
994-
(holder_value_msat / 1000, counterparty_value_msat / 1000 - total_fee as i64)
1000+
(holder_value_msat / 1000, counterparty_value_msat / 1000 - total_fee as i64 - 2 * ANCHOR_OUTPUT_VALUE as i64)
9951001
};
9961002

9971003
let (value_to_a, value_to_b) = if !building_for_counterparty { (holder_value, counterparty_value) } else { (counterparty_value, holder_value) };
1004+
let (funding_pubkey_a, funding_pubkey_b) = if !building_for_counterparty {
1005+
(self.holder_keys.pubkeys().funding_pubkey, self.counterparty_pubkeys.as_ref().unwrap().funding_pubkey)
1006+
} else {
1007+
(self.counterparty_pubkeys.as_ref().unwrap().funding_pubkey, self.holder_keys.pubkeys().funding_pubkey)
1008+
};
9981009

9991010
if value_to_a >= (broadcaster_dust_limit_satoshis as i64) {
10001011
log_trace!(logger, " ...including {} output with value {}", if !building_for_counterparty { "to_local" } else { "to_remote" }, value_to_a);
@@ -1021,6 +1032,27 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
10211032
}, None));
10221033
}
10231034

1035+
// If `option_anchor_output` applies to the commitment transaction, we materialize
1036+
// anchors :
1037+
// * we add anchors for both parties, if we have untrimmed HTLCs outputs
1038+
// * we add anchor for a party, if its balance is present
1039+
let has_htlcs = counterparty_htlc_total_msat + holder_htlc_total_msat > 0;
1040+
if has_htlcs || value_to_a >= (broadcaster_dust_limit_satoshis as i64) {
1041+
log_trace!(logger, " ...including {} anchor output with value {}", if !building_for_counterparty { "to_local" } else { "to_remote" }, ANCHOR_OUTPUT_VALUE);
1042+
txouts.push((TxOut {
1043+
script_pubkey: chan_utils::get_anchor_redeemscript(&funding_pubkey_a).to_v0_p2wsh(),
1044+
value: ANCHOR_OUTPUT_VALUE,
1045+
}, None));
1046+
}
1047+
1048+
if has_htlcs || value_to_b >= (broadcaster_dust_limit_satoshis as i64) {
1049+
log_trace!(logger, " ...including {} anchor output with value {}", if !building_for_counterparty { "to_remote" } else { "to_local" }, ANCHOR_OUTPUT_VALUE);
1050+
txouts.push((TxOut {
1051+
script_pubkey: chan_utils::get_anchor_redeemscript(&funding_pubkey_b).to_v0_p2wsh(),
1052+
value: ANCHOR_OUTPUT_VALUE,
1053+
}, None));
1054+
}
1055+
10241056
transaction_utils::sort_outputs(&mut txouts, |a, b| {
10251057
if let &Some(ref a_htlc) = a {
10261058
if let &Some(ref b_htlc) = b {

lightning/src/ln/functional_test_utils.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
1313
use chain::chaininterface;
1414
use chain::transaction::OutPoint;
15+
use ln::channel::ANCHOR_OUTPUT_VALUE;
1516
use ln::channelmanager::{ChannelManager, ChannelManagerReadArgs, RAACommitmentOrder, PaymentPreimage, PaymentHash, PaymentSecret, PaymentSendFailure};
1617
use ln::channelmonitor::{ChannelMonitor, ManyChannelMonitor};
1718
use routing::router::{Route, get_route};
@@ -1229,6 +1230,16 @@ pub fn check_preimage_claim<'a, 'b, 'c>(node: &Node<'a, 'b, 'c>, prev_txn: &Vec<
12291230
res
12301231
}
12311232

1233+
pub fn check_anchor_output(tx: &Transaction, anchors: u32) {
1234+
let mut counting = 0;
1235+
for outp in &tx.output {
1236+
if outp.value == ANCHOR_OUTPUT_VALUE {
1237+
counting += 1;
1238+
}
1239+
}
1240+
assert_eq!(counting, anchors);
1241+
}
1242+
12321243
pub fn get_announce_close_broadcast_events<'a, 'b, 'c>(nodes: &Vec<Node<'a, 'b, 'c>>, a: usize, b: usize) {
12331244
let events_1 = nodes[a].node.get_and_clear_pending_msg_events();
12341245
assert_eq!(events_1.len(), 1);

lightning/src/ln/functional_tests.rs

Lines changed: 46 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -596,8 +596,8 @@ fn test_update_fee_that_funder_cannot_afford() {
596596
let commitment_tx = get_local_commitment_txn!(nodes[1], channel_id)[0].clone();
597597

598598
//We made sure neither party's funds are below the dust limit so -2 non-HTLC txns from number of outputs and -2 for anchor outputs
599-
let num_htlcs = commitment_tx.output.len() - 2; //TODO: add +2 in next commit
600-
let mut total_fee: u64 = feerate as u64 * (COMMITMENT_TX_BASE_WEIGHT + (num_htlcs as u64) * COMMITMENT_TX_WEIGHT_PER_HTLC) / 1000; //TODO: add anchor weight in next commit
599+
let num_htlcs = commitment_tx.output.len() - 4;
600+
let mut total_fee: u64 = feerate as u64 * (COMMITMENT_TX_BASE_WEIGHT + (num_htlcs as u64) * COMMITMENT_TX_WEIGHT_PER_HTLC + 2 * COMMITMENT_TX_WEIGHT_PER_ANCHOR) / 1000;
601601
let mut actual_fee = commitment_tx.output.iter().fold(0, |acc, output| acc + output.value);
602602
actual_fee = channel_value - actual_fee;
603603
assert_eq!(total_fee, actual_fee);
@@ -1487,7 +1487,8 @@ fn test_duplicate_htlc_different_direction_onchain() {
14871487
// Broadcast node 1 commitment txn
14881488
let remote_txn = get_local_commitment_txn!(nodes[1], chan_1.2);
14891489

1490-
assert_eq!(remote_txn[0].output.len(), 4); // 1 local, 1 remote, 1 htlc inbound, 1 htlc outbound
1490+
assert_eq!(remote_txn[0].output.len(), 6); // 1 local, 1 remote, 1 htlc inbound, 1 htlc outbound, 2 anchors
1491+
check_anchor_output(&remote_txn[0], 2);
14911492
let mut has_both_htlcs = 0; // check htlcs match ones committed
14921493
for outp in remote_txn[0].output.iter() {
14931494
if outp.value == 800_000 / 1000 {
@@ -1617,21 +1618,21 @@ fn test_fee_spike_violation_fails_htlc() {
16171618

16181619
// Get the EnforcingChannelKeys for each channel, which will be used to (1) get the keys
16191620
// needed to sign the new commitment tx and (2) sign the new commitment tx.
1620-
let (local_revocation_basepoint, local_htlc_basepoint, local_payment_point, local_secret, local_secret2) = {
1621+
let (local_revocation_basepoint, local_htlc_basepoint, local_payment_point, local_secret, local_secret2, local_funding_pubkey) = {
16211622
let chan_lock = nodes[0].node.channel_state.lock().unwrap();
16221623
let local_chan = chan_lock.by_id.get(&chan.2).unwrap();
16231624
let chan_keys = local_chan.get_keys();
16241625
let pubkeys = chan_keys.pubkeys();
16251626
(pubkeys.revocation_basepoint, pubkeys.htlc_basepoint, pubkeys.payment_point,
1626-
chan_keys.release_commitment_secret(INITIAL_COMMITMENT_NUMBER), chan_keys.release_commitment_secret(INITIAL_COMMITMENT_NUMBER - 2))
1627+
chan_keys.release_commitment_secret(INITIAL_COMMITMENT_NUMBER), chan_keys.release_commitment_secret(INITIAL_COMMITMENT_NUMBER - 2), pubkeys.funding_pubkey)
16271628
};
1628-
let (remote_delayed_payment_basepoint, remote_htlc_basepoint, remote_payment_point, remote_secret1) = {
1629+
let (remote_delayed_payment_basepoint, remote_htlc_basepoint, remote_payment_point, remote_secret1, remote_funding_pubkey) = {
16291630
let chan_lock = nodes[1].node.channel_state.lock().unwrap();
16301631
let remote_chan = chan_lock.by_id.get(&chan.2).unwrap();
16311632
let chan_keys = remote_chan.get_keys();
16321633
let pubkeys = chan_keys.pubkeys();
16331634
(pubkeys.delayed_payment_basepoint, pubkeys.htlc_basepoint, pubkeys.payment_point,
1634-
chan_keys.release_commitment_secret(INITIAL_COMMITMENT_NUMBER - 1))
1635+
chan_keys.release_commitment_secret(INITIAL_COMMITMENT_NUMBER - 1), pubkeys.funding_pubkey)
16351636
};
16361637

16371638
// Assemble the set of keys we can use for signatures for our commitment_signed message.
@@ -1642,7 +1643,7 @@ fn test_fee_spike_violation_fails_htlc() {
16421643

16431644
// Build the remote commitment transaction so we can sign it, and then later use the
16441645
// signature for the commitment_signed message.
1645-
let local_chan_balance = 2058;
1646+
let local_chan_balance = 1311;
16461647
let static_payment_pk = local_payment_point.serialize();
16471648
let remote_commit_tx_output = TxOut {
16481649
script_pubkey: Builder::new().push_opcode(opcodes::all::OP_PUSHBYTES_0)
@@ -1663,7 +1664,17 @@ fn test_fee_spike_violation_fails_htlc() {
16631664
amount_msat: 3460001,
16641665
cltv_expiry: htlc_cltv,
16651666
payment_hash: payment_hash,
1666-
transaction_output_index: Some(1),
1667+
transaction_output_index: Some(3),
1668+
};
1669+
1670+
let local_anchor_output = TxOut {
1671+
script_pubkey: chan_utils::get_anchor_redeemscript(&local_funding_pubkey).to_v0_p2wsh(),
1672+
value: 330,
1673+
};
1674+
1675+
let remote_anchor_output = TxOut {
1676+
script_pubkey: chan_utils::get_anchor_redeemscript(&remote_funding_pubkey).to_v0_p2wsh(),
1677+
value: 330,
16671678
};
16681679

16691680
let htlc_output = TxOut {
@@ -1699,8 +1710,11 @@ fn test_fee_spike_violation_fails_htlc() {
16991710
version: 2,
17001711
lock_time,
17011712
input: vec![input],
1702-
output: vec![remote_commit_tx_output, htlc_output, local_commit_tx_output],
1713+
output: vec![remote_anchor_output, local_anchor_output, remote_commit_tx_output, htlc_output, local_commit_tx_output],
17031714
};
1715+
for outp in commit_tx.output.iter() {
1716+
println!("Scriptpubkey {} value {}", outp.script_pubkey, outp.value);
1717+
}
17041718
let res = {
17051719
let local_chan_lock = nodes[0].node.channel_state.lock().unwrap();
17061720
let local_chan = local_chan_lock.by_id.get(&chan.2).unwrap();
@@ -2509,7 +2523,8 @@ fn test_justice_tx() {
25092523
assert_eq!(revoked_local_txn.len(), 2); // First commitment tx, then HTLC tx
25102524
assert_eq!(revoked_local_txn[0].input.len(), 1);
25112525
assert_eq!(revoked_local_txn[0].input[0].previous_output.txid, chan_5.3.txid());
2512-
assert_eq!(revoked_local_txn[0].output.len(), 2); // Only HTLC and output back to 0 are present
2526+
assert_eq!(revoked_local_txn[0].output.len(), 4); // Only HTLC and output back to 0 are present (+ 0's anchor)
2527+
check_anchor_output(&revoked_local_txn[0], 2);
25132528
assert_eq!(revoked_local_txn[1].input.len(), 1);
25142529
assert_eq!(revoked_local_txn[1].input[0].previous_output.txid, revoked_local_txn[0].txid());
25152530
assert_eq!(revoked_local_txn[1].input[0].witness.last().unwrap().len(), OFFERED_HTLC_SCRIPT_WEIGHT); // HTLC-Timeout
@@ -2560,7 +2575,8 @@ fn test_justice_tx() {
25602575
assert_eq!(revoked_local_txn.len(), 1); // Only commitment tx
25612576
assert_eq!(revoked_local_txn[0].input.len(), 1);
25622577
assert_eq!(revoked_local_txn[0].input[0].previous_output.txid, chan_6.3.txid());
2563-
assert_eq!(revoked_local_txn[0].output.len(), 2); // Only HTLC and output back to A are present
2578+
assert_eq!(revoked_local_txn[0].output.len(), 4); // Only HTLC and output back to A are present (+ A's anchor)
2579+
check_anchor_output(&revoked_local_txn[0], 2);
25642580
// Revoke the old state
25652581
claim_payment(&nodes[0], &vec!(&nodes[1])[..], payment_preimage_4, 3_000_000);
25662582
{
@@ -2602,7 +2618,8 @@ fn revoked_output_claim() {
26022618
let revoked_local_txn = get_local_commitment_txn!(nodes[0], chan_1.2);
26032619
assert_eq!(revoked_local_txn.len(), 1);
26042620
// Only output is the full channel value back to nodes[0]:
2605-
assert_eq!(revoked_local_txn[0].output.len(), 1);
2621+
assert_eq!(revoked_local_txn[0].output.len(), 2);
2622+
check_anchor_output(&revoked_local_txn[0], 1);
26062623
// Send a payment through, updating everyone's latest commitment txn
26072624
send_payment(&nodes[0], &vec!(&nodes[1])[..], 5000000, 5_000_000);
26082625

@@ -3141,7 +3158,8 @@ fn do_test_commitment_revoked_fail_backward_exhaustive(deliver_bs_raa: bool, use
31413158
let (payment_preimage, _payment_hash) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], if no_to_remote { 10_000 } else { 3_000_000 });
31423159
// Get the will-be-revoked local txn from nodes[2]
31433160
let revoked_local_txn = get_local_commitment_txn!(nodes[2], chan_2.2);
3144-
assert_eq!(revoked_local_txn[0].output.len(), if no_to_remote { 1 } else { 2 });
3161+
assert_eq!(revoked_local_txn[0].output.len(), if no_to_remote { 3 } else { 4 });
3162+
check_anchor_output(&revoked_local_txn[0], 2);
31453163
// Revoke the old state
31463164
claim_payment(&nodes[0], &[&nodes[1], &nodes[2]], payment_preimage, if no_to_remote { 10_000 } else { 3_000_000});
31473165

@@ -4804,6 +4822,7 @@ fn test_claim_sizeable_push_msat() {
48044822
assert_eq!(node_txn.len(), 1);
48054823
check_spends!(node_txn[0], chan.3);
48064824
assert_eq!(node_txn[0].output.len(), 2); // We can't force trimming of to_remote output as channel_reserve_satoshis block us to do so at channel opening
4825+
check_anchor_output(&node_txn[0], 1);
48074826

48084827
let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
48094828
nodes[1].block_notifier.block_connected(&Block { header, txdata: vec![node_txn[0].clone()] }, 0);
@@ -4832,6 +4851,7 @@ fn test_claim_on_remote_sizeable_push_msat() {
48324851
assert_eq!(node_txn.len(), 1);
48334852
check_spends!(node_txn[0], chan.3);
48344853
assert_eq!(node_txn[0].output.len(), 2); // We can't force trimming of to_remote output as channel_reserve_satoshis block us to do so at channel opening
4854+
check_anchor_output(&node_txn[0], 1);
48354855

48364856
let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
48374857
nodes[1].block_notifier.block_connected(&Block { header, txdata: vec![node_txn[0].clone()] }, 0);
@@ -5415,7 +5435,8 @@ fn do_test_fail_backwards_unrevoked_remote_announce(deliver_last_raa: bool, anno
54155435
// Rebalance and check output sanity...
54165436
send_payment(&nodes[0], &[&nodes[2], &nodes[3], &nodes[4]], 500000, 500_000);
54175437
send_payment(&nodes[1], &[&nodes[2], &nodes[3], &nodes[5]], 500000, 500_000);
5418-
assert_eq!(get_local_commitment_txn!(nodes[3], chan.2)[0].output.len(), 2);
5438+
assert_eq!(get_local_commitment_txn!(nodes[3], chan.2)[0].output.len(), 4);
5439+
check_anchor_output(&get_local_commitment_txn!(nodes[3], chan.2)[0], 2);
54195440

54205441
let ds_dust_limit = nodes[3].node.channel_state.lock().unwrap().by_id.get(&chan.2).unwrap().holder_dust_limit_satoshis;
54215442
// 0th HTLC:
@@ -5455,7 +5476,8 @@ fn do_test_fail_backwards_unrevoked_remote_announce(deliver_last_raa: bool, anno
54555476
// We now have six HTLCs pending over the dust limit and six HTLCs under the dust limit (ie,
54565477
// with to_local and to_remote outputs, 8 outputs and 6 HTLCs not included).
54575478
assert_eq!(get_local_commitment_txn!(nodes[3], chan.2).len(), 1);
5458-
assert_eq!(get_local_commitment_txn!(nodes[3], chan.2)[0].output.len(), 8);
5479+
assert_eq!(get_local_commitment_txn!(nodes[3], chan.2)[0].output.len(), 10);
5480+
check_anchor_output(&get_local_commitment_txn!(nodes[3], chan.2)[0], 2);
54595481

54605482
// Now fail back three of the over-dust-limit and three of the under-dust-limit payments in one go.
54615483
// Fail 0th below-dust, 4th above-dust, 8th above-dust, 10th below-dust HTLCs
@@ -7510,7 +7532,8 @@ fn test_data_loss_protect() {
75107532
let node_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap().clone();
75117533
assert_eq!(node_txn.len(), 1);
75127534
check_spends!(node_txn[0], chan.3);
7513-
assert_eq!(node_txn[0].output.len(), 2);
7535+
assert_eq!(node_txn[0].output.len(), 4);
7536+
check_anchor_output(&node_txn[0], 2);
75147537
let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42};
75157538
nodes[0].block_notifier.block_connected(&Block { header, txdata: vec![node_txn[0].clone()]}, 0);
75167539
connect_blocks(&nodes[0].block_notifier, ANTI_REORG_DELAY - 1, 0, true, header.block_hash());
@@ -7648,7 +7671,8 @@ fn test_bump_penalty_txn_on_revoked_commitment() {
76487671

76497672
let revoked_txn = get_local_commitment_txn!(nodes[0], chan.2);
76507673
// Revoked commitment txn with 4 outputs : to_local, to_remote, 1 outgoing HTLC, 1 incoming HTLC
7651-
assert_eq!(revoked_txn[0].output.len(), 4);
7674+
assert_eq!(revoked_txn[0].output.len(), 6);
7675+
check_anchor_output(&revoked_txn[0], 2);
76527676
assert_eq!(revoked_txn[0].input.len(), 1);
76537677
assert_eq!(revoked_txn[0].input[0].previous_output.txid, chan.3.txid());
76547678
let revoked_txid = revoked_txn[0].txid();
@@ -7873,7 +7897,8 @@ fn test_bump_penalty_txn_on_remote_commitment() {
78737897

78747898
// Remote commitment txn with 4 outputs : to_local, to_remote, 1 outgoing HTLC, 1 incoming HTLC
78757899
let remote_txn = get_local_commitment_txn!(nodes[0], chan.2);
7876-
assert_eq!(remote_txn[0].output.len(), 4);
7900+
assert_eq!(remote_txn[0].output.len(), 6);
7901+
check_anchor_output(&remote_txn[0], 2);
78777902
assert_eq!(remote_txn[0].input.len(), 1);
78787903
assert_eq!(remote_txn[0].input[0].previous_output.txid, chan.3.txid());
78797904

@@ -7982,7 +8007,8 @@ fn test_set_outpoints_partial_claiming() {
79828007
// Remote commitment txn with 4 outputs: to_local, to_remote, 2 outgoing HTLC
79838008
let remote_txn = get_local_commitment_txn!(nodes[1], chan.2);
79848009
assert_eq!(remote_txn.len(), 3);
7985-
assert_eq!(remote_txn[0].output.len(), 4);
8010+
assert_eq!(remote_txn[0].output.len(), 6);
8011+
check_anchor_output(&remote_txn[0], 2);
79868012
assert_eq!(remote_txn[0].input.len(), 1);
79878013
assert_eq!(remote_txn[0].input[0].previous_output.txid, chan.3.txid());
79888014
check_spends!(remote_txn[1], remote_txn[0]);

0 commit comments

Comments
 (0)