Skip to content

Commit 9c9c881

Browse files
authored
Merge pull request #742 from lightning-signer/tx-phase2
Introduce CommitmentTransactionInfo
2 parents 74cd96f + 9291a38 commit 9c9c881

9 files changed

+1235
-878
lines changed

lightning/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ Still missing tons of error-handling. See GitHub issues for suggested projects i
1212

1313
[features]
1414
fuzztarget = ["bitcoin/fuzztarget"]
15+
# Internal test utilities exposed to other repo crates
1516
_test_utils = ["hex", "regex"]
1617
# Unlog messages superior at targeted level.
1718
max_level_off = []

lightning/src/chain/channelmonitor.rs

+100-69
Large diffs are not rendered by default.

lightning/src/chain/keysinterface.rs

+83-99
Large diffs are not rendered by default.

lightning/src/ln/chan_utils.rs

+623-225
Large diffs are not rendered by default.

lightning/src/ln/channel.rs

+308-327
Large diffs are not rendered by default.

lightning/src/ln/functional_tests.rs

+19-59
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,12 @@ use util::ser::{Writeable, ReadableArgs, Readable};
3232
use util::config::UserConfig;
3333

3434
use bitcoin::hashes::sha256d::Hash as Sha256dHash;
35-
use bitcoin::hashes::HashEngine;
36-
use bitcoin::hash_types::{Txid, BlockHash, WPubkeyHash};
35+
use bitcoin::hash_types::{Txid, BlockHash};
3736
use bitcoin::util::bip143;
3837
use bitcoin::util::address::Address;
3938
use bitcoin::util::bip32::{ChildNumber, ExtendedPubKey, ExtendedPrivKey};
4039
use bitcoin::blockdata::block::{Block, BlockHeader};
41-
use bitcoin::blockdata::transaction::{Transaction, TxOut, TxIn, SigHashType, OutPoint as BitcoinOutPoint};
40+
use bitcoin::blockdata::transaction::{Transaction, TxOut, TxIn, SigHashType};
4241
use bitcoin::blockdata::script::{Builder, Script};
4342
use bitcoin::blockdata::opcodes;
4443
use bitcoin::blockdata::constants::genesis_block;
@@ -59,7 +58,7 @@ use std::sync::atomic::Ordering;
5958
use std::mem;
6059

6160
use ln::functional_test_utils::*;
62-
use ln::chan_utils::PreCalculatedTxCreationKeys;
61+
use ln::chan_utils::CommitmentTransaction;
6362

6463
#[test]
6564
fn test_insane_channel_opens() {
@@ -1617,20 +1616,20 @@ fn test_fee_spike_violation_fails_htlc() {
16171616

16181617
// Get the EnforcingChannelKeys for each channel, which will be used to (1) get the keys
16191618
// 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) = {
1619+
let (local_revocation_basepoint, local_htlc_basepoint, local_secret, local_secret2) = {
16211620
let chan_lock = nodes[0].node.channel_state.lock().unwrap();
16221621
let local_chan = chan_lock.by_id.get(&chan.2).unwrap();
16231622
let chan_keys = local_chan.get_keys();
16241623
let pubkeys = chan_keys.pubkeys();
1625-
(pubkeys.revocation_basepoint, pubkeys.htlc_basepoint, pubkeys.payment_point,
1624+
(pubkeys.revocation_basepoint, pubkeys.htlc_basepoint,
16261625
chan_keys.release_commitment_secret(INITIAL_COMMITMENT_NUMBER), chan_keys.release_commitment_secret(INITIAL_COMMITMENT_NUMBER - 2))
16271626
};
1628-
let (remote_delayed_payment_basepoint, remote_htlc_basepoint, remote_payment_point, remote_secret1) = {
1627+
let (remote_delayed_payment_basepoint, remote_htlc_basepoint, remote_secret1) = {
16291628
let chan_lock = nodes[1].node.channel_state.lock().unwrap();
16301629
let remote_chan = chan_lock.by_id.get(&chan.2).unwrap();
16311630
let chan_keys = remote_chan.get_keys();
16321631
let pubkeys = chan_keys.pubkeys();
1633-
(pubkeys.delayed_payment_basepoint, pubkeys.htlc_basepoint, pubkeys.payment_point,
1632+
(pubkeys.delayed_payment_basepoint, pubkeys.htlc_basepoint,
16341633
chan_keys.release_commitment_secret(INITIAL_COMMITMENT_NUMBER - 1))
16351634
};
16361635

@@ -1643,70 +1642,31 @@ fn test_fee_spike_violation_fails_htlc() {
16431642
// Build the remote commitment transaction so we can sign it, and then later use the
16441643
// signature for the commitment_signed message.
16451644
let local_chan_balance = 1313;
1646-
let static_payment_pk = local_payment_point.serialize();
1647-
let remote_commit_tx_output = TxOut {
1648-
script_pubkey: Builder::new().push_opcode(opcodes::all::OP_PUSHBYTES_0)
1649-
.push_slice(&WPubkeyHash::hash(&static_payment_pk)[..])
1650-
.into_script(),
1651-
value: local_chan_balance as u64
1652-
};
1653-
1654-
let local_commit_tx_output = TxOut {
1655-
script_pubkey: chan_utils::get_revokeable_redeemscript(&commit_tx_keys.revocation_key,
1656-
BREAKDOWN_TIMEOUT,
1657-
&commit_tx_keys.broadcaster_delayed_payment_key).to_v0_p2wsh(),
1658-
value: 95000,
1659-
};
16601645

16611646
let accepted_htlc_info = chan_utils::HTLCOutputInCommitment {
16621647
offered: false,
16631648
amount_msat: 3460001,
16641649
cltv_expiry: htlc_cltv,
1665-
payment_hash: payment_hash,
1650+
payment_hash,
16661651
transaction_output_index: Some(1),
16671652
};
16681653

1669-
let htlc_output = TxOut {
1670-
script_pubkey: chan_utils::get_htlc_redeemscript(&accepted_htlc_info, &commit_tx_keys).to_v0_p2wsh(),
1671-
value: 3460001 / 1000
1672-
};
1673-
1674-
let commit_tx_obscure_factor = {
1675-
let mut sha = Sha256::engine();
1676-
let remote_payment_point = &remote_payment_point.serialize();
1677-
sha.input(&local_payment_point.serialize());
1678-
sha.input(remote_payment_point);
1679-
let res = Sha256::from_engine(sha).into_inner();
1680-
1681-
((res[26] as u64) << 5*8) |
1682-
((res[27] as u64) << 4*8) |
1683-
((res[28] as u64) << 3*8) |
1684-
((res[29] as u64) << 2*8) |
1685-
((res[30] as u64) << 1*8) |
1686-
((res[31] as u64) << 0*8)
1687-
};
1688-
let commitment_number = 1;
1689-
let obscured_commitment_transaction_number = commit_tx_obscure_factor ^ commitment_number;
1690-
let lock_time = ((0x20 as u32) << 8*3) | ((obscured_commitment_transaction_number & 0xffffffu64) as u32);
1691-
let input = TxIn {
1692-
previous_output: BitcoinOutPoint { txid: chan.3.txid(), vout: 0 },
1693-
script_sig: Script::new(),
1694-
sequence: ((0x80 as u32) << 8*3) | ((obscured_commitment_transaction_number >> 3*8) as u32),
1695-
witness: Vec::new(),
1696-
};
1654+
let commitment_number = INITIAL_COMMITMENT_NUMBER - 1;
16971655

1698-
let commit_tx = Transaction {
1699-
version: 2,
1700-
lock_time,
1701-
input: vec![input],
1702-
output: vec![remote_commit_tx_output, htlc_output, local_commit_tx_output],
1703-
};
17041656
let res = {
17051657
let local_chan_lock = nodes[0].node.channel_state.lock().unwrap();
17061658
let local_chan = local_chan_lock.by_id.get(&chan.2).unwrap();
17071659
let local_chan_keys = local_chan.get_keys();
1708-
let pre_commit_tx_keys = PreCalculatedTxCreationKeys::new(commit_tx_keys);
1709-
local_chan_keys.sign_counterparty_commitment(feerate_per_kw, &commit_tx, &pre_commit_tx_keys, &[&accepted_htlc_info], &secp_ctx).unwrap()
1660+
let commitment_tx = CommitmentTransaction::new_with_auxiliary_htlc_data(
1661+
commitment_number,
1662+
95000,
1663+
local_chan_balance,
1664+
commit_tx_keys.clone(),
1665+
feerate_per_kw,
1666+
&mut vec![(accepted_htlc_info, ())],
1667+
&local_chan.channel_transaction_parameters.as_counterparty_broadcastable()
1668+
);
1669+
local_chan_keys.sign_counterparty_commitment(&commitment_tx, &secp_ctx).unwrap()
17101670
};
17111671

17121672
let commit_signed_msg = msgs::CommitmentSigned {

lightning/src/ln/onchaintx.rs

+44-45
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
//! The logic to build claims and bump in-flight transactions until confirmations.
1111
//!
12-
//! OnchainTxHandler objetcs are fully-part of ChannelMonitor and encapsulates all
12+
//! OnchainTxHandler objects are fully-part of ChannelMonitor and encapsulates all
1313
//! building, tracking, bumping and notifications functions.
1414
1515
use bitcoin::blockdata::transaction::{Transaction, TxIn, TxOut, SigHashType};
@@ -24,7 +24,7 @@ use bitcoin::secp256k1;
2424
use ln::msgs::DecodeError;
2525
use ln::channelmanager::PaymentPreimage;
2626
use ln::chan_utils;
27-
use ln::chan_utils::{TxCreationKeys, HolderCommitmentTransaction};
27+
use ln::chan_utils::{TxCreationKeys, ChannelTransactionParameters, HolderCommitmentTransaction};
2828
use chain::chaininterface::{FeeEstimator, BroadcasterInterface, ConfirmationTarget, MIN_RELAY_FEE_SAT_PER_1000_WEIGHT};
2929
use chain::channelmonitor::{ANTI_REORG_DELAY, CLTV_SHARED_CLAIM_BUFFER, InputMaterial, ClaimRequest};
3030
use chain::keysinterface::ChannelKeys;
@@ -244,14 +244,13 @@ pub struct OnchainTxHandler<ChanSigner: ChannelKeys> {
244244
holder_commitment: Option<HolderCommitmentTransaction>,
245245
// holder_htlc_sigs and prev_holder_htlc_sigs are in the order as they appear in the commitment
246246
// transaction outputs (hence the Option<>s inside the Vec). The first usize is the index in
247-
// the set of HTLCs in the HolderCommitmentTransaction (including those which do not appear in
248-
// the commitment transaction).
247+
// the set of HTLCs in the HolderCommitmentTransaction.
249248
holder_htlc_sigs: Option<Vec<Option<(usize, Signature)>>>,
250249
prev_holder_commitment: Option<HolderCommitmentTransaction>,
251250
prev_holder_htlc_sigs: Option<Vec<Option<(usize, Signature)>>>,
252-
on_holder_tx_csv: u16,
253251

254252
key_storage: ChanSigner,
253+
pub(crate) channel_transaction_parameters: ChannelTransactionParameters,
255254

256255
// Used to track claiming requests. If claim tx doesn't confirm before height timer expiration we need to bump
257256
// it (RBF or CPFP). If an input has been part of an aggregate tx at first claim try, we need to keep it within
@@ -295,9 +294,8 @@ impl<ChanSigner: ChannelKeys + Writeable> OnchainTxHandler<ChanSigner> {
295294
self.prev_holder_commitment.write(writer)?;
296295
self.prev_holder_htlc_sigs.write(writer)?;
297296

298-
self.on_holder_tx_csv.write(writer)?;
299-
300297
self.key_storage.write(writer)?;
298+
self.channel_transaction_parameters.write(writer)?;
301299

302300
writer.write_all(&byte_utils::be64_to_array(self.pending_claim_requests.len() as u64))?;
303301
for (ref ancestor_claim_txid, claim_tx_data) in self.pending_claim_requests.iter() {
@@ -344,9 +342,8 @@ impl<ChanSigner: ChannelKeys + Readable> Readable for OnchainTxHandler<ChanSigne
344342
let prev_holder_commitment = Readable::read(reader)?;
345343
let prev_holder_htlc_sigs = Readable::read(reader)?;
346344

347-
let on_holder_tx_csv = Readable::read(reader)?;
348-
349345
let key_storage = Readable::read(reader)?;
346+
let channel_parameters = Readable::read(reader)?;
350347

351348
let pending_claim_requests_len: u64 = Readable::read(reader)?;
352349
let mut pending_claim_requests = HashMap::with_capacity(cmp::min(pending_claim_requests_len as usize, MAX_ALLOC_SIZE / 128));
@@ -398,8 +395,8 @@ impl<ChanSigner: ChannelKeys + Readable> Readable for OnchainTxHandler<ChanSigne
398395
holder_htlc_sigs,
399396
prev_holder_commitment,
400397
prev_holder_htlc_sigs,
401-
on_holder_tx_csv,
402398
key_storage,
399+
channel_transaction_parameters: channel_parameters,
403400
claimable_outpoints,
404401
pending_claim_requests,
405402
onchain_events_waiting_threshold_conf,
@@ -410,7 +407,7 @@ impl<ChanSigner: ChannelKeys + Readable> Readable for OnchainTxHandler<ChanSigne
410407
}
411408

412409
impl<ChanSigner: ChannelKeys> OnchainTxHandler<ChanSigner> {
413-
pub(crate) fn new(destination_script: Script, keys: ChanSigner, on_holder_tx_csv: u16) -> Self {
410+
pub(crate) fn new(destination_script: Script, keys: ChanSigner, channel_parameters: ChannelTransactionParameters) -> Self {
414411

415412
let key_storage = keys;
416413

@@ -420,8 +417,8 @@ impl<ChanSigner: ChannelKeys> OnchainTxHandler<ChanSigner> {
420417
holder_htlc_sigs: None,
421418
prev_holder_commitment: None,
422419
prev_holder_htlc_sigs: None,
423-
on_holder_tx_csv,
424420
key_storage,
421+
channel_transaction_parameters: channel_parameters,
425422
pending_claim_requests: HashMap::new(),
426423
claimable_outpoints: HashMap::new(),
427424
onchain_events_waiting_threshold_conf: HashMap::new(),
@@ -654,7 +651,7 @@ impl<ChanSigner: ChannelKeys> OnchainTxHandler<ChanSigner> {
654651
let signed_tx = self.get_fully_signed_holder_tx(funding_redeemscript).unwrap();
655652
// Timer set to $NEVER given we can't bump tx without anchor outputs
656653
log_trace!(logger, "Going to broadcast Holder Transaction {} claiming funding output {} from {}...", signed_tx.txid(), outp.vout, outp.txid);
657-
return Some((None, self.holder_commitment.as_ref().unwrap().feerate_per_kw, signed_tx));
654+
return Some((None, self.holder_commitment.as_ref().unwrap().feerate_per_kw(), signed_tx));
658655
}
659656
_ => unreachable!()
660657
}
@@ -899,44 +896,39 @@ impl<ChanSigner: ChannelKeys> OnchainTxHandler<ChanSigner> {
899896
fn sign_latest_holder_htlcs(&mut self) {
900897
if let Some(ref holder_commitment) = self.holder_commitment {
901898
if let Ok(sigs) = self.key_storage.sign_holder_commitment_htlc_transactions(holder_commitment, &self.secp_ctx) {
902-
self.holder_htlc_sigs = Some(Vec::new());
903-
let ret = self.holder_htlc_sigs.as_mut().unwrap();
904-
for (htlc_idx, (holder_sig, &(ref htlc, _))) in sigs.iter().zip(holder_commitment.per_htlc.iter()).enumerate() {
905-
if let Some(tx_idx) = htlc.transaction_output_index {
906-
if ret.len() <= tx_idx as usize { ret.resize(tx_idx as usize + 1, None); }
907-
ret[tx_idx as usize] = Some((htlc_idx, holder_sig.expect("Did not receive a signature for a non-dust HTLC")));
908-
} else {
909-
assert!(holder_sig.is_none(), "Received a signature for a dust HTLC");
910-
}
911-
}
899+
self.holder_htlc_sigs = Some(Self::extract_holder_sigs(holder_commitment, sigs));
912900
}
913901
}
914902
}
903+
915904
fn sign_prev_holder_htlcs(&mut self) {
916905
if let Some(ref holder_commitment) = self.prev_holder_commitment {
917906
if let Ok(sigs) = self.key_storage.sign_holder_commitment_htlc_transactions(holder_commitment, &self.secp_ctx) {
918-
self.prev_holder_htlc_sigs = Some(Vec::new());
919-
let ret = self.prev_holder_htlc_sigs.as_mut().unwrap();
920-
for (htlc_idx, (holder_sig, &(ref htlc, _))) in sigs.iter().zip(holder_commitment.per_htlc.iter()).enumerate() {
921-
if let Some(tx_idx) = htlc.transaction_output_index {
922-
if ret.len() <= tx_idx as usize { ret.resize(tx_idx as usize + 1, None); }
923-
ret[tx_idx as usize] = Some((htlc_idx, holder_sig.expect("Did not receive a signature for a non-dust HTLC")));
924-
} else {
925-
assert!(holder_sig.is_none(), "Received a signature for a dust HTLC");
926-
}
927-
}
907+
self.prev_holder_htlc_sigs = Some(Self::extract_holder_sigs(holder_commitment, sigs));
928908
}
929909
}
930910
}
931911

932-
//TODO: getting lastest holder transactions should be infaillible and result in us "force-closing the channel", but we may
912+
fn extract_holder_sigs(holder_commitment: &HolderCommitmentTransaction, sigs: Vec<Signature>) -> Vec<Option<(usize, Signature)>> {
913+
let mut ret = Vec::new();
914+
for (htlc_idx, (holder_sig, htlc)) in sigs.iter().zip(holder_commitment.htlcs().iter()).enumerate() {
915+
let tx_idx = htlc.transaction_output_index.unwrap();
916+
if ret.len() <= tx_idx as usize { ret.resize(tx_idx as usize + 1, None); }
917+
ret[tx_idx as usize] = Some((htlc_idx, holder_sig.clone()));
918+
}
919+
ret
920+
}
921+
922+
//TODO: getting lastest holder transactions should be infallible and result in us "force-closing the channel", but we may
933923
// have empty holder commitment transaction if a ChannelMonitor is asked to force-close just after Channel::get_outbound_funding_created,
934924
// before providing a initial commitment transaction. For outbound channel, init ChannelMonitor at Channel::funding_signed, there is nothing
935925
// to monitor before.
936926
pub(crate) fn get_fully_signed_holder_tx(&mut self, funding_redeemscript: &Script) -> Option<Transaction> {
937927
if let Some(ref mut holder_commitment) = self.holder_commitment {
938-
match self.key_storage.sign_holder_commitment(holder_commitment, &self.secp_ctx) {
939-
Ok(sig) => Some(holder_commitment.add_holder_sig(funding_redeemscript, sig)),
928+
match self.key_storage.sign_holder_commitment(&holder_commitment, &self.secp_ctx) {
929+
Ok(sig) => {
930+
Some(holder_commitment.add_holder_sig(funding_redeemscript, sig))
931+
},
940932
Err(_) => return None,
941933
}
942934
} else {
@@ -947,9 +939,10 @@ impl<ChanSigner: ChannelKeys> OnchainTxHandler<ChanSigner> {
947939
#[cfg(any(test, feature="unsafe_revoked_tx_signing"))]
948940
pub(crate) fn get_fully_signed_copy_holder_tx(&mut self, funding_redeemscript: &Script) -> Option<Transaction> {
949941
if let Some(ref mut holder_commitment) = self.holder_commitment {
950-
let holder_commitment = holder_commitment.clone();
951-
match self.key_storage.sign_holder_commitment(&holder_commitment, &self.secp_ctx) {
952-
Ok(sig) => Some(holder_commitment.add_holder_sig(funding_redeemscript, sig)),
942+
match self.key_storage.sign_holder_commitment(holder_commitment, &self.secp_ctx) {
943+
Ok(sig) => {
944+
Some(holder_commitment.add_holder_sig(funding_redeemscript, sig))
945+
},
953946
Err(_) => return None,
954947
}
955948
} else {
@@ -960,24 +953,30 @@ impl<ChanSigner: ChannelKeys> OnchainTxHandler<ChanSigner> {
960953
pub(crate) fn get_fully_signed_htlc_tx(&mut self, outp: &::bitcoin::OutPoint, preimage: &Option<PaymentPreimage>) -> Option<Transaction> {
961954
let mut htlc_tx = None;
962955
if self.holder_commitment.is_some() {
963-
let commitment_txid = self.holder_commitment.as_ref().unwrap().txid();
956+
let commitment_txid = self.holder_commitment.as_ref().unwrap().trust().txid();
964957
if commitment_txid == outp.txid {
965958
self.sign_latest_holder_htlcs();
966959
if let &Some(ref htlc_sigs) = &self.holder_htlc_sigs {
967960
let &(ref htlc_idx, ref htlc_sig) = htlc_sigs[outp.vout as usize].as_ref().unwrap();
968-
htlc_tx = Some(self.holder_commitment.as_ref().unwrap()
969-
.get_signed_htlc_tx(*htlc_idx, htlc_sig, preimage, self.on_holder_tx_csv));
961+
let holder_commitment = self.holder_commitment.as_ref().unwrap();
962+
let trusted_tx = holder_commitment.trust();
963+
let counterparty_htlc_sig = holder_commitment.counterparty_htlc_sigs[*htlc_idx];
964+
htlc_tx = Some(trusted_tx
965+
.get_signed_htlc_tx(&self.channel_transaction_parameters.as_holder_broadcastable(), *htlc_idx, &counterparty_htlc_sig, htlc_sig, preimage));
970966
}
971967
}
972968
}
973969
if self.prev_holder_commitment.is_some() {
974-
let commitment_txid = self.prev_holder_commitment.as_ref().unwrap().txid();
970+
let commitment_txid = self.prev_holder_commitment.as_ref().unwrap().trust().txid();
975971
if commitment_txid == outp.txid {
976972
self.sign_prev_holder_htlcs();
977973
if let &Some(ref htlc_sigs) = &self.prev_holder_htlc_sigs {
978974
let &(ref htlc_idx, ref htlc_sig) = htlc_sigs[outp.vout as usize].as_ref().unwrap();
979-
htlc_tx = Some(self.prev_holder_commitment.as_ref().unwrap()
980-
.get_signed_htlc_tx(*htlc_idx, htlc_sig, preimage, self.on_holder_tx_csv));
975+
let holder_commitment = self.prev_holder_commitment.as_ref().unwrap();
976+
let trusted_tx = holder_commitment.trust();
977+
let counterparty_htlc_sig = holder_commitment.counterparty_htlc_sigs[*htlc_idx];
978+
htlc_tx = Some(trusted_tx
979+
.get_signed_htlc_tx(&self.channel_transaction_parameters.as_holder_broadcastable(), *htlc_idx, &counterparty_htlc_sig, htlc_sig, preimage));
981980
}
982981
}
983982
}

0 commit comments

Comments
 (0)