Skip to content

Commit ebcd3f3

Browse files
author
Antoine Riard
committed
Access signed local commitment through OnchainTxHandler
Implementing dynamic fee bumping implied to cache transaction material including its witness, to generate a bumped version if needed. ChannelMonitor is slowly rescoped to its parsing function with ongoing patchset and data duplicata are removed. If signed local commitment tx access is needed, it's done through OnchainTxHandler extended API For test framework purpose, we use the test-only method ChannelMonitor::unsafe_get_latest_local_commitment_txn to intentionally generate unsafe local commitment to exerce revocation logic.
1 parent 97f5f40 commit ebcd3f3

File tree

3 files changed

+60
-27
lines changed

3 files changed

+60
-27
lines changed

lightning/src/ln/channelmonitor.rs

Lines changed: 41 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1687,7 +1687,7 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
16871687
(claimable_outpoints, Some((htlc_txid, tx.output.clone())))
16881688
}
16891689

1690-
fn broadcast_by_local_state(&self, local_tx: &LocalSignedTx) -> (Vec<Transaction>, Vec<TxOut>, Option<(Script, SecretKey, Script)>) {
1690+
fn broadcast_by_local_state(&self, commitment_tx: &Transaction, local_tx: &LocalSignedTx) -> (Vec<Transaction>, Vec<TxOut>, Option<(Script, SecretKey, Script)>) {
16911691
let mut res = Vec::with_capacity(local_tx.htlc_outputs.len());
16921692
let mut watch_outputs = Vec::with_capacity(local_tx.htlc_outputs.len());
16931693

@@ -1730,7 +1730,7 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
17301730
res.push(htlc_success_tx);
17311731
}
17321732
}
1733-
watch_outputs.push(local_tx.tx.without_valid_witness().output[transaction_output_index as usize].clone());
1733+
watch_outputs.push(commitment_tx.output[transaction_output_index as usize].clone());
17341734
} else { panic!("Should have sigs for non-dust local tx outputs!") }
17351735
}
17361736
}
@@ -1784,16 +1784,15 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
17841784
if local_tx.txid == commitment_txid {
17851785
is_local_tx = true;
17861786
log_trace!(self, "Got latest local commitment tx broadcast, searching for available HTLCs to claim");
1787-
let mut res = self.broadcast_by_local_state(local_tx);
1787+
let mut res = self.broadcast_by_local_state(tx, local_tx);
17881788
append_onchain_update!(res);
17891789
}
17901790
}
17911791
if let &Some(ref local_tx) = &self.prev_local_signed_commitment_tx {
17921792
if local_tx.txid == commitment_txid {
17931793
is_local_tx = true;
17941794
log_trace!(self, "Got previous local commitment tx broadcast, searching for available HTLCs to claim");
1795-
assert!(local_tx.tx.has_local_sig());
1796-
let mut res = self.broadcast_by_local_state(local_tx);
1795+
let mut res = self.broadcast_by_local_state(tx, local_tx);
17971796
append_onchain_update!(res);
17981797
}
17991798
}
@@ -1832,22 +1831,35 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
18321831
/// out-of-band the other node operator to coordinate with him if option is available to you.
18331832
/// In any-case, choice is up to the user.
18341833
pub fn get_latest_local_commitment_txn(&mut self) -> Vec<Transaction> {
1835-
// TODO: We should likely move all of the logic in here into OnChainTxHandler and unify it
1836-
// to ensure add_local_sig is only ever called once no matter what. This likely includes
1837-
// tracking state and panic!()ing if we get an update after force-closure/local-tx signing.
18381834
log_trace!(self, "Getting signed latest local commitment transaction!");
1839-
if let &mut Some(ref mut local_tx) = &mut self.current_local_signed_commitment_tx {
1840-
self.onchain_detection.keys.sign_local_commitment(&mut local_tx.tx, self.funding_redeemscript.as_ref().unwrap(), self.channel_value_satoshis.unwrap(), &self.secp_ctx);
1835+
if let Some(commitment_tx) = self.onchain_tx_handler.get_fully_signed_local_tx(self.channel_value_satoshis.unwrap()) {
1836+
let mut res = vec![commitment_tx];
1837+
if let &Some(ref local_tx) = &self.current_local_signed_commitment_tx {
1838+
let mut htlc_txn = self.broadcast_by_local_state(res.get(0).unwrap(), local_tx).0;
1839+
res.append(&mut htlc_txn);
1840+
// We throw away the generated waiting_first_conf data as we aren't (yet) confirmed and we don't actually know what the caller wants to do.
1841+
// The data will be re-generated and tracked in check_spend_local_transaction if we get a confirmation.
1842+
}
1843+
return res
18411844
}
1842-
if let &Some(ref local_tx) = &self.current_local_signed_commitment_tx {
1843-
let mut res = vec![local_tx.tx.with_valid_witness().clone()];
1844-
res.append(&mut self.broadcast_by_local_state(local_tx).0);
1845-
// We throw away the generated waiting_first_conf data as we aren't (yet) confirmed and we don't actually know what the caller wants to do.
1846-
// The data will be re-generated and tracked in check_spend_local_transaction if we get a confirmation.
1847-
res
1848-
} else {
1849-
Vec::new()
1845+
Vec::new()
1846+
}
1847+
1848+
/// Unsafe test-only version of get_latest_local_commitment_txn used by our test framework
1849+
/// to bypass LocalCommitmentTransaction state update lockdown after signature and generate
1850+
/// revoked commitment transaction.
1851+
#[cfg(test)]
1852+
pub fn unsafe_get_latest_local_commitment_txn(&mut self) -> Vec<Transaction> {
1853+
log_trace!(self, "Getting signed copy of latest local commitment transaction!");
1854+
if let Some(commitment_tx) = self.onchain_tx_handler.get_fully_signed_copy_local_tx(self.channel_value_satoshis.unwrap()) {
1855+
let mut res = vec![commitment_tx];
1856+
if let &Some(ref local_tx) = &self.current_local_signed_commitment_tx {
1857+
let mut htlc_txn = self.broadcast_by_local_state(res.get(0).unwrap(), local_tx).0;
1858+
res.append(&mut htlc_txn);
1859+
}
1860+
return res
18501861
}
1862+
Vec::new()
18511863
}
18521864

18531865
/// Called by SimpleManyChannelMonitor::block_connected, which implements
@@ -1922,13 +1934,15 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
19221934
}
19231935
if let Some(ref cur_local_tx) = self.current_local_signed_commitment_tx {
19241936
if should_broadcast {
1925-
let (txs, new_outputs, _) = self.broadcast_by_local_state(&cur_local_tx);
1926-
if !new_outputs.is_empty() {
1927-
watch_outputs.push((cur_local_tx.txid.clone(), new_outputs));
1928-
}
1929-
for tx in txs {
1930-
log_trace!(self, "Broadcast onchain {}", log_tx!(tx));
1931-
broadcaster.broadcast_transaction(&tx);
1937+
if let Some(commitment_tx) = self.onchain_tx_handler.get_fully_signed_local_tx(self.channel_value_satoshis.unwrap()) {
1938+
let (txs, new_outputs, _) = self.broadcast_by_local_state(&commitment_tx, cur_local_tx);
1939+
if !new_outputs.is_empty() {
1940+
watch_outputs.push((cur_local_tx.txid.clone(), new_outputs));
1941+
}
1942+
for tx in txs {
1943+
log_trace!(self, "Broadcast onchain {}", log_tx!(tx));
1944+
broadcaster.broadcast_transaction(&tx);
1945+
}
19321946
}
19331947
}
19341948
}
@@ -2401,7 +2415,8 @@ impl<ChanSigner: ChannelKeys + Readable> ReadableArgs<Arc<Logger>> for (Sha256dH
24012415

24022416
LocalSignedTx {
24032417
txid: tx.txid(),
2404-
tx, revocation_key, a_htlc_key, b_htlc_key, delayed_payment_key, per_commitment_point, feerate_per_kw,
2418+
tx,
2419+
revocation_key, a_htlc_key, b_htlc_key, delayed_payment_key, per_commitment_point, feerate_per_kw,
24052420
htlc_outputs: htlcs
24062421
}
24072422
}

lightning/src/ln/functional_test_utils.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@ macro_rules! get_local_commitment_txn {
264264
let mut commitment_txn = None;
265265
for (funding_txo, monitor) in monitors.iter_mut() {
266266
if funding_txo.to_channel_id() == $channel_id {
267-
commitment_txn = Some(monitor.get_latest_local_commitment_txn());
267+
commitment_txn = Some(monitor.unsafe_get_latest_local_commitment_txn());
268268
break;
269269
}
270270
}

lightning/src/ln/onchaintx.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -769,4 +769,22 @@ impl<ChanSigner: ChannelKeys> OnchainTxHandler<ChanSigner> {
769769
self.local_commitment = Some(tx);
770770
Ok(())
771771
}
772+
773+
pub(super) fn get_fully_signed_local_tx(&mut self, channel_value_satoshis: u64) -> Option<Transaction> {
774+
if let Some(ref mut local_commitment) = self.local_commitment {
775+
self.key_storage.sign_local_commitment(local_commitment, &self.funding_redeemscript, channel_value_satoshis, &self.secp_ctx);
776+
return Some(local_commitment.with_valid_witness().clone());
777+
}
778+
None
779+
}
780+
781+
#[cfg(test)]
782+
pub(super) fn get_fully_signed_copy_local_tx(&mut self, channel_value_satoshis: u64) -> Option<Transaction> {
783+
if let Some(ref mut local_commitment) = self.local_commitment {
784+
let mut local_commitment = local_commitment.clone();
785+
self.key_storage.sign_local_commitment(&mut local_commitment, &self.funding_redeemscript, channel_value_satoshis, &self.secp_ctx);
786+
return Some(local_commitment.with_valid_witness().clone());
787+
}
788+
None
789+
}
772790
}

0 commit comments

Comments
 (0)