#[cfg(not(test))]
onchain_tx_handler: OnchainTxHandler<ChanSigner>,
- // Used to detect programming bug due to unsafe monitor update sequence { ChannelForceClosed, LatestLocalCommitmentTXInfo }
+ // This is set when the Channel[Manager] generated a ChannelMonitorUpdate which indicated the
+ // channel has been force-closed. After this is set, no further local commitment transaction
+ // updates may occur, and we panic!() if one is provided.
lockdown_from_offchain: bool,
+ // Set once we've signed a local commitment transaction and handed it over to our
+ // OnchainTxHandler. After this is set, no future updates to our local commitment transactions
+ // may occur, and we fail any such monitor updates.
+ local_tx_signed: bool,
+
// We simply modify last_block_hash in Channel's block_connected so that serialization is
// consistent but hopefully the users' copy handles block_connected in a consistent way.
// (we do *not*, however, update them in update_monitor to ensure any local user copies keep
self.pending_htlcs_updated != other.pending_htlcs_updated ||
self.pending_events.len() != other.pending_events.len() || // We trust events to round-trip properly
self.onchain_events_waiting_threshold_conf != other.onchain_events_waiting_threshold_conf ||
- self.outputs_to_watch != other.outputs_to_watch
+ self.outputs_to_watch != other.outputs_to_watch ||
+ self.lockdown_from_offchain != other.lockdown_from_offchain ||
+ self.local_tx_signed != other.local_tx_signed
{
false
} else {
self.onchain_tx_handler.write(writer)?;
self.lockdown_from_offchain.write(writer)?;
+ self.local_tx_signed.write(writer)?;
Ok(())
}
onchain_tx_handler,
lockdown_from_offchain: false,
+ local_tx_signed: false,
last_block_hash: Default::default(),
secp_ctx: Secp256k1::new(),
/// up-to-date as our local commitment transaction is updated.
/// Panics if set_their_to_self_delay has never been called.
pub(super) fn provide_latest_local_commitment_tx_info(&mut self, commitment_tx: LocalCommitmentTransaction, htlc_outputs: Vec<(HTLCOutputInCommitment, Option<Signature>, Option<HTLCSource>)>) -> Result<(), MonitorUpdateError> {
+ if self.local_tx_signed {
+ return Err(MonitorUpdateError("A local commitment tx has already been signed, no new local commitment txn can be sent to our counterparty"));
+ }
let txid = commitment_tx.txid();
let sequence = commitment_tx.without_valid_witness().input[0].sequence as u64;
let locktime = commitment_tx.without_valid_witness().lock_time as u64;
/// In any-case, choice is up to the user.
pub fn get_latest_local_commitment_txn(&mut self) -> Vec<Transaction> {
log_trace!(self, "Getting signed latest local commitment transaction!");
+ self.local_tx_signed = true;
if let Some(commitment_tx) = self.onchain_tx_handler.get_fully_signed_local_tx() {
let txid = commitment_tx.txid();
let mut res = vec![commitment_tx];
let onchain_tx_handler = ReadableArgs::read(reader, logger.clone())?;
let lockdown_from_offchain = Readable::read(reader)?;
+ let local_tx_signed = Readable::read(reader)?;
Ok((last_block_hash.clone(), ChannelMonitor {
latest_update_id,
onchain_tx_handler,
lockdown_from_offchain,
+ local_tx_signed,
last_block_hash,
secp_ctx: Secp256k1::new(),