Skip to content

Commit 4c4d99b

Browse files
authored
Merge pull request #1055 from lightning-signer/2021-08-anchor-tx
2 parents 6bd1af4 + 8275698 commit 4c4d99b

File tree

4 files changed

+177
-14
lines changed

4 files changed

+177
-14
lines changed

lightning/src/ln/chan_utils.rs

+153-9
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_SATOSHI};
4040
use core::ops::Deref;
4141
use chain;
4242

@@ -564,6 +564,24 @@ pub fn build_htlc_transaction(commitment_txid: &Txid, feerate_per_kw: u32, conte
564564
}
565565
}
566566

567+
/// Gets the witnessScript for an anchor output from the funding public key.
568+
/// The witness in the spending input must be:
569+
/// <BIP 143 funding_signature>
570+
/// After 16 blocks of confirmation, an alternative satisfying witness could be:
571+
/// <>
572+
/// (empty vector required to satisfy compliance with MINIMALIF-standard rule)
573+
#[inline]
574+
pub(crate) fn get_anchor_redeemscript(funding_pubkey: &PublicKey) -> Script {
575+
Builder::new().push_slice(&funding_pubkey.serialize()[..])
576+
.push_opcode(opcodes::all::OP_CHECKSIG)
577+
.push_opcode(opcodes::all::OP_IFDUP)
578+
.push_opcode(opcodes::all::OP_NOTIF)
579+
.push_int(16)
580+
.push_opcode(opcodes::all::OP_CSV)
581+
.push_opcode(opcodes::all::OP_ENDIF)
582+
.into_script()
583+
}
584+
567585
/// Per-channel data used to build transactions in conjunction with the per-commitment data (CommitmentTransaction).
568586
/// The fields are organized by holder/counterparty.
569587
///
@@ -754,7 +772,7 @@ impl HolderCommitmentTransaction {
754772
funding_outpoint: Some(chain::transaction::OutPoint { txid: Default::default(), index: 0 })
755773
};
756774
let mut htlcs_with_aux: Vec<(_, ())> = Vec::new();
757-
let inner = CommitmentTransaction::new_with_auxiliary_htlc_data(0, 0, 0, keys, 0, &mut htlcs_with_aux, &channel_parameters.as_counterparty_broadcastable());
775+
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());
758776
HolderCommitmentTransaction {
759777
inner,
760778
counterparty_sig: dummy_sig,
@@ -841,6 +859,8 @@ pub struct CommitmentTransaction {
841859
to_countersignatory_value_sat: u64,
842860
feerate_per_kw: u32,
843861
htlcs: Vec<HTLCOutputInCommitment>,
862+
// A boolean that is serialization backwards-compatible
863+
opt_anchors: Option<()>,
844864
// A cache of the parties' pubkeys required to construct the transaction, see doc for trust()
845865
keys: TxCreationKeys,
846866
// For access to the pre-built transaction, see doc for trust()
@@ -854,6 +874,7 @@ impl PartialEq for CommitmentTransaction {
854874
self.to_countersignatory_value_sat == o.to_countersignatory_value_sat &&
855875
self.feerate_per_kw == o.feerate_per_kw &&
856876
self.htlcs == o.htlcs &&
877+
self.opt_anchors == o.opt_anchors &&
857878
self.keys == o.keys;
858879
if eq {
859880
debug_assert_eq!(self.built.transaction, o.built.transaction);
@@ -871,6 +892,7 @@ impl_writeable_tlv_based!(CommitmentTransaction, {
871892
(8, keys, required),
872893
(10, built, required),
873894
(12, htlcs, vec_type),
895+
(14, opt_anchors, option),
874896
});
875897

876898
impl CommitmentTransaction {
@@ -884,9 +906,9 @@ impl CommitmentTransaction {
884906
/// Only include HTLCs that are above the dust limit for the channel.
885907
///
886908
/// (C-not exported) due to the generic though we likely should expose a version without
887-
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 {
909+
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 {
888910
// Sort outputs and populate output indices while keeping track of the auxiliary data
889-
let (outputs, htlcs) = Self::internal_build_outputs(&keys, to_broadcaster_value_sat, to_countersignatory_value_sat, htlcs_with_aux, channel_parameters).unwrap();
911+
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();
890912

891913
let (obscured_commitment_transaction_number, txins) = Self::internal_build_inputs(commitment_number, channel_parameters);
892914
let transaction = Self::make_transaction(obscured_commitment_transaction_number, txins, outputs);
@@ -897,6 +919,7 @@ impl CommitmentTransaction {
897919
to_countersignatory_value_sat,
898920
feerate_per_kw,
899921
htlcs,
922+
opt_anchors: if opt_anchors { Some(()) } else { None },
900923
keys,
901924
built: BuiltCommitmentTransaction {
902925
transaction,
@@ -905,11 +928,11 @@ impl CommitmentTransaction {
905928
}
906929
}
907930

908-
fn internal_rebuild_transaction(&self, keys: &TxCreationKeys, channel_parameters: &DirectedChannelTransactionParameters) -> Result<BuiltCommitmentTransaction, ()> {
931+
fn internal_rebuild_transaction(&self, keys: &TxCreationKeys, channel_parameters: &DirectedChannelTransactionParameters, broadcaster_funding_key: &PublicKey, countersignatory_funding_key: &PublicKey) -> Result<BuiltCommitmentTransaction, ()> {
909932
let (obscured_commitment_transaction_number, txins) = Self::internal_build_inputs(self.commitment_number, channel_parameters);
910933

911934
let mut htlcs_with_aux = self.htlcs.iter().map(|h| (h.clone(), ())).collect();
912-
let (outputs, _) = Self::internal_build_outputs(keys, self.to_broadcaster_value_sat, self.to_countersignatory_value_sat, &mut htlcs_with_aux, channel_parameters)?;
935+
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.is_some(), broadcaster_funding_key, countersignatory_funding_key)?;
913936

914937
let transaction = Self::make_transaction(obscured_commitment_transaction_number, txins, outputs);
915938
let txid = transaction.txid();
@@ -933,7 +956,7 @@ impl CommitmentTransaction {
933956
// - initial sorting of outputs / HTLCs in the constructor, in which case T is auxiliary data the
934957
// caller needs to have sorted together with the HTLCs so it can keep track of the output index
935958
// - building of a bitcoin transaction during a verify() call, in which case T is just ()
936-
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>), ()> {
959+
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>), ()> {
937960
let countersignatory_pubkeys = channel_parameters.countersignatory_pubkeys();
938961
let contest_delay = channel_parameters.contest_delay();
939962

@@ -965,6 +988,30 @@ impl CommitmentTransaction {
965988
));
966989
}
967990

991+
if opt_anchors {
992+
if to_broadcaster_value_sat > 0 || !htlcs_with_aux.is_empty() {
993+
let anchor_script = get_anchor_redeemscript(broadcaster_funding_key);
994+
txouts.push((
995+
TxOut {
996+
script_pubkey: anchor_script.to_v0_p2wsh(),
997+
value: ANCHOR_OUTPUT_VALUE_SATOSHI,
998+
},
999+
None,
1000+
));
1001+
}
1002+
1003+
if to_countersignatory_value_sat > 0 || !htlcs_with_aux.is_empty() {
1004+
let anchor_script = get_anchor_redeemscript(countersignatory_funding_key);
1005+
txouts.push((
1006+
TxOut {
1007+
script_pubkey: anchor_script.to_v0_p2wsh(),
1008+
value: ANCHOR_OUTPUT_VALUE_SATOSHI,
1009+
},
1010+
None,
1011+
));
1012+
}
1013+
}
1014+
9681015
let mut htlcs = Vec::with_capacity(htlcs_with_aux.len());
9691016
for (htlc, _) in htlcs_with_aux {
9701017
let script = chan_utils::get_htlc_redeemscript(&htlc, &keys);
@@ -1081,7 +1128,7 @@ impl CommitmentTransaction {
10811128
if keys != self.keys {
10821129
return Err(());
10831130
}
1084-
let tx = self.internal_rebuild_transaction(&keys, channel_parameters)?;
1131+
let tx = self.internal_rebuild_transaction(&keys, channel_parameters, &broadcaster_keys.funding_pubkey, &countersignatory_keys.funding_pubkey)?;
10851132
if self.built.transaction != tx.transaction || self.built.txid != tx.txid {
10861133
return Err(());
10871134
}
@@ -1219,8 +1266,105 @@ fn script_for_p2wpkh(key: &PublicKey) -> Script {
12191266
#[cfg(test)]
12201267
mod tests {
12211268
use super::CounterpartyCommitmentSecrets;
1222-
use hex;
1269+
use ::{hex, chain};
12231270
use prelude::*;
1271+
use ln::chan_utils::{CommitmentTransaction, TxCreationKeys, ChannelTransactionParameters, CounterpartyChannelTransactionParameters, HTLCOutputInCommitment};
1272+
use bitcoin::secp256k1::{PublicKey, SecretKey, Secp256k1};
1273+
use util::test_utils;
1274+
use chain::keysinterface::{KeysInterface, BaseSign};
1275+
use bitcoin::Network;
1276+
use ln::PaymentHash;
1277+
1278+
#[test]
1279+
fn test_anchors() {
1280+
let secp_ctx = Secp256k1::new();
1281+
1282+
let seed = [42; 32];
1283+
let network = Network::Testnet;
1284+
let keys_provider = test_utils::TestKeysInterface::new(&seed, network);
1285+
let signer = keys_provider.get_channel_signer(false, 3000);
1286+
let counterparty_signer = keys_provider.get_channel_signer(false, 3000);
1287+
let delayed_payment_base = &signer.pubkeys().delayed_payment_basepoint;
1288+
let per_commitment_secret = SecretKey::from_slice(&hex::decode("1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100").unwrap()[..]).unwrap();
1289+
let per_commitment_point = PublicKey::from_secret_key(&secp_ctx, &per_commitment_secret);
1290+
let htlc_basepoint = &signer.pubkeys().htlc_basepoint;
1291+
let holder_pubkeys = signer.pubkeys();
1292+
let counterparty_pubkeys = counterparty_signer.pubkeys();
1293+
let keys = TxCreationKeys::derive_new(&secp_ctx, &per_commitment_point, delayed_payment_base, htlc_basepoint, &counterparty_pubkeys.revocation_basepoint, &counterparty_pubkeys.htlc_basepoint).unwrap();
1294+
let channel_parameters = ChannelTransactionParameters {
1295+
holder_pubkeys: holder_pubkeys.clone(),
1296+
holder_selected_contest_delay: 0,
1297+
is_outbound_from_holder: false,
1298+
counterparty_parameters: Some(CounterpartyChannelTransactionParameters { pubkeys: counterparty_pubkeys.clone(), selected_contest_delay: 0 }),
1299+
funding_outpoint: Some(chain::transaction::OutPoint { txid: Default::default(), index: 0 })
1300+
};
1301+
1302+
let mut htlcs_with_aux: Vec<(_, ())> = Vec::new();
1303+
1304+
// Generate broadcaster and counterparty outputs
1305+
let tx = CommitmentTransaction::new_with_auxiliary_htlc_data(
1306+
0, 1000, 2000,
1307+
false,
1308+
holder_pubkeys.funding_pubkey,
1309+
counterparty_pubkeys.funding_pubkey,
1310+
keys.clone(), 1,
1311+
&mut htlcs_with_aux, &channel_parameters.as_holder_broadcastable()
1312+
);
1313+
assert_eq!(tx.built.transaction.output.len(), 2);
1314+
1315+
// Generate broadcaster and counterparty outputs as well as two anchors
1316+
let tx = CommitmentTransaction::new_with_auxiliary_htlc_data(
1317+
0, 1000, 2000,
1318+
true,
1319+
holder_pubkeys.funding_pubkey,
1320+
counterparty_pubkeys.funding_pubkey,
1321+
keys.clone(), 1,
1322+
&mut htlcs_with_aux, &channel_parameters.as_holder_broadcastable()
1323+
);
1324+
assert_eq!(tx.built.transaction.output.len(), 4);
1325+
1326+
// Generate broadcaster output and anchor
1327+
let tx = CommitmentTransaction::new_with_auxiliary_htlc_data(
1328+
0, 3000, 0,
1329+
true,
1330+
holder_pubkeys.funding_pubkey,
1331+
counterparty_pubkeys.funding_pubkey,
1332+
keys.clone(), 1,
1333+
&mut htlcs_with_aux, &channel_parameters.as_holder_broadcastable()
1334+
);
1335+
assert_eq!(tx.built.transaction.output.len(), 2);
1336+
1337+
// Generate counterparty output and anchor
1338+
let tx = CommitmentTransaction::new_with_auxiliary_htlc_data(
1339+
0, 0, 3000,
1340+
true,
1341+
holder_pubkeys.funding_pubkey,
1342+
counterparty_pubkeys.funding_pubkey,
1343+
keys.clone(), 1,
1344+
&mut htlcs_with_aux, &channel_parameters.as_holder_broadcastable()
1345+
);
1346+
assert_eq!(tx.built.transaction.output.len(), 2);
1347+
1348+
// Generate broadcaster output, an HTLC output and two anchors
1349+
let payment_hash = PaymentHash([42; 32]);
1350+
let htlc_info = HTLCOutputInCommitment {
1351+
offered: false,
1352+
amount_msat: 1000000,
1353+
cltv_expiry: 100,
1354+
payment_hash,
1355+
transaction_output_index: None,
1356+
};
1357+
1358+
let tx = CommitmentTransaction::new_with_auxiliary_htlc_data(
1359+
0, 3000, 0,
1360+
true,
1361+
holder_pubkeys.funding_pubkey,
1362+
counterparty_pubkeys.funding_pubkey,
1363+
keys.clone(), 1,
1364+
&mut vec![(htlc_info, ())], &channel_parameters.as_holder_broadcastable()
1365+
);
1366+
assert_eq!(tx.built.transaction.output.len(), 4);
1367+
}
12241368

12251369
#[test]
12261370
fn test_per_commitment_storage() {

lightning/src/ln/channel.rs

+11-1
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_SATOSHI: 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

+7-4
Original file line numberDiff line numberDiff line change
@@ -1297,7 +1297,7 @@ 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();
@@ -1307,15 +1307,17 @@ fn test_fee_spike_violation_fails_htlc() {
13071307
let pubkeys = chan_signer.pubkeys();
13081308
(pubkeys.revocation_basepoint, pubkeys.htlc_basepoint,
13091309
chan_signer.release_commitment_secret(INITIAL_COMMITMENT_NUMBER),
1310-
chan_signer.get_per_commitment_point(INITIAL_COMMITMENT_NUMBER - 2, &secp_ctx))
1310+
chan_signer.get_per_commitment_point(INITIAL_COMMITMENT_NUMBER - 2, &secp_ctx),
1311+
chan_signer.pubkeys().funding_pubkey)
13111312
};
1312-
let (remote_delayed_payment_basepoint, remote_htlc_basepoint,remote_point) = {
1313+
let (remote_delayed_payment_basepoint, remote_htlc_basepoint, remote_point, remote_funding) = {
13131314
let chan_lock = nodes[1].node.channel_state.lock().unwrap();
13141315
let remote_chan = chan_lock.by_id.get(&chan.2).unwrap();
13151316
let chan_signer = remote_chan.get_signer();
13161317
let pubkeys = chan_signer.pubkeys();
13171318
(pubkeys.delayed_payment_basepoint, pubkeys.htlc_basepoint,
1318-
chan_signer.get_per_commitment_point(INITIAL_COMMITMENT_NUMBER - 1, &secp_ctx))
1319+
chan_signer.get_per_commitment_point(INITIAL_COMMITMENT_NUMBER - 1, &secp_ctx),
1320+
chan_signer.pubkeys().funding_pubkey)
13191321
};
13201322

13211323
// Assemble the set of keys we can use for signatures for our commitment_signed message.
@@ -1344,6 +1346,7 @@ fn test_fee_spike_violation_fails_htlc() {
13441346
commitment_number,
13451347
95000,
13461348
local_chan_balance,
1349+
false, local_funding, remote_funding,
13471350
commit_tx_keys.clone(),
13481351
feerate_per_kw,
13491352
&mut vec![(accepted_htlc_info, ())],

lightning/src/util/ser.rs

+6
Original file line numberDiff line numberDiff line change
@@ -861,3 +861,9 @@ impl<A: Writeable, B: Writeable, C: Writeable> Writeable for (A, B, C) {
861861
self.2.write(w)
862862
}
863863
}
864+
865+
impl Readable for () {
866+
fn read<R: Read>(_r: &mut R) -> Result<Self, DecodeError> {
867+
Ok(())
868+
}
869+
}

0 commit comments

Comments
 (0)