Skip to content

Commit

Permalink
Add ability to retrieve latest commitment transactions from ChannelMa…
Browse files Browse the repository at this point in the history
…nager
  • Loading branch information
Tibo-lg committed Jul 20, 2023
1 parent 74690be commit 40a4627
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 2 deletions.
6 changes: 6 additions & 0 deletions lightning/src/chain/chainmonitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -669,6 +669,12 @@ where C::Target: chain::Filter,
}
}

fn get_latest_holder_commitment_txn(&self, funding_txo: OutPoint) -> Vec<bitcoin::Transaction> {
let monitors = self.monitors.read().unwrap();
let monitor = monitors.get(&funding_txo).expect("To have a monitor for the requested channel");
monitor.monitor.get_latest_holder_commitment_txn_internal(&self.logger)
}

/// Note that we persist the given `ChannelMonitor` update while holding the
/// `ChainMonitor` monitors lock.
fn update_channel(&self, funding_txo: OutPoint, update: &ChannelMonitorUpdate) -> ChannelMonitorUpdateStatus {
Expand Down
11 changes: 10 additions & 1 deletion lightning/src/chain/channelmonitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1357,6 +1357,11 @@ impl<Signer: WriteableEcdsaChannelSigner> ChannelMonitor<Signer> {
self.inner.lock().unwrap().get_latest_holder_commitment_txn(logger)
}

pub(crate) fn get_latest_holder_commitment_txn_internal<L: Deref>(&self, logger: &L) -> Vec<Transaction>
where L::Target: Logger {
self.inner.lock().unwrap().get_latest_holder_commitment_txn_internal(logger)
}

/// Unsafe test-only version of get_latest_holder_commitment_txn used by our test framework
/// to bypass HolderCommitmentTransaction state update lockdown after signature and generate
/// revoked commitment transaction.
Expand Down Expand Up @@ -2848,8 +2853,12 @@ impl<Signer: WriteableEcdsaChannelSigner> ChannelMonitorImpl<Signer> {
}

pub fn get_latest_holder_commitment_txn<L: Deref>(&mut self, logger: &L) -> Vec<Transaction> where L::Target: Logger {
log_debug!(logger, "Getting signed latest holder commitment transaction!");
self.holder_tx_signed = true;
self.get_latest_holder_commitment_txn_internal(logger)
}

pub(crate) fn get_latest_holder_commitment_txn_internal<L: Deref>(&mut self, logger: &L) -> Vec<Transaction> where L::Target: Logger {
log_debug!(logger, "Getting signed latest holder commitment transaction!");
let commitment_tx = self.onchain_tx_handler.get_fully_signed_holder_tx(&self.funding_redeemscript);
let txid = commitment_tx.txid();
let mut holder_transactions = vec![commitment_tx];
Expand Down
3 changes: 3 additions & 0 deletions lightning/src/chain/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,9 @@ pub trait Watch<ChannelSigner: WriteableEcdsaChannelSigner> {
/// Update the outpoint funding the channel.
fn update_channel_funding_txo(&self, old_funding_txo: OutPoint, new_funding_txo: OutPoint, channel_value_satoshis: u64) -> ChannelMonitorUpdateStatus;

/// Get the latest commitment transaction to broadcast
fn get_latest_holder_commitment_txn(&self, funding_txo: OutPoint) -> Vec<bitcoin::Transaction>;

/// Returns any monitor events since the last call. Subsequent calls must only return new
/// events.
///
Expand Down
16 changes: 15 additions & 1 deletion lightning/src/ln/channel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5119,8 +5119,22 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
return Ok((Some(channel_ready), announcement_sigs));
}
}

let original_funding_outpoint = self.get_original_funding_txo().map(|x| x.into_bitcoin_outpoint());
let funding_bitcoin_outpoint = funding_txo.into_bitcoin_outpoint();
let funding_match = |prev_outpoint: &bitcoin::OutPoint| -> bool {
prev_outpoint == &funding_bitcoin_outpoint
};
let original_funding_match = |prev_outpoint: &bitcoin::OutPoint, outputs: &[bitcoin::TxOut]| -> bool {
if let Some(original_funding_outpoint) = original_funding_outpoint {
// We want to filter for the split tx which is not closing the LN channel.
prev_outpoint == &original_funding_outpoint && !(outputs.len() == 2 && outputs[0].script_pubkey == outputs[1].script_pubkey)
} else {
false
}
};
for inp in tx.input.iter() {
if inp.previous_output == funding_txo.into_bitcoin_outpoint() {
if funding_match(&inp.previous_output) || original_funding_match(&inp.previous_output, &tx.output) {
log_info!(logger, "Detected channel-closing tx {} spending {}:{}, closing channel {}", tx.txid(), inp.previous_output.txid, inp.previous_output.vout, log_bytes!(self.channel_id()));
return Err(ClosureReason::CommitmentTxConfirmed);
}
Expand Down
14 changes: 14 additions & 0 deletions lightning/src/ln/channelmanager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2012,6 +2012,15 @@ where
let chan = &mut channel_lock.channel;

chan.set_funding_outpoint(funding_outpoint, channel_value, own_balance, false, &self.logger);
if ChannelMonitorUpdateStatus::Completed != self.chain_monitor.update_channel_funding_txo(chan.get_original_funding_txo().unwrap(), *funding_outpoint, channel_value) {
log_error!(self.logger, "Error setting funding txo on chain monitor");
}
}

fn get_latest_holder_commitment_txn_internal(&self, channel_lock: &ChannelLock<<SP::Target as SignerProvider>::Signer>) -> Vec<Transaction> {
let chan = &channel_lock.channel;

self.chain_monitor.get_latest_holder_commitment_txn(chan.get_original_funding_txo().expect("To have a funding txo"))
}

fn close_channel_internal(&self, channel_id: &[u8; 32], counterparty_node_id: &PublicKey, target_feerate_sats_per_1000_weight: Option<u32>) -> Result<(), APIError> {
Expand Down Expand Up @@ -2143,6 +2152,11 @@ where
self.set_funding_outpoint_internal(channel_lock, funding_output, channel_value_satoshis, value_to_self_msat);
}

///
pub fn get_latest_holder_commitment_txn(&self, channel_lock: &ChannelLock<<SP::Target as SignerProvider>::Signer>) -> Vec<Transaction> {
self.get_latest_holder_commitment_txn_internal(channel_lock)
}

#[inline]
fn finish_force_close_channel(&self, shutdown_res: ShutdownResult) {
let (monitor_update_option, mut failed_htlcs) = shutdown_res;
Expand Down

0 comments on commit 40a4627

Please sign in to comment.