},
}
+impl Balance {
+ /// The amount claimable, in satoshis. This excludes balances that we are unsure if we are able
+ /// to claim, this is because we are waiting for a preimage or for a timeout to expire. For more
+ /// information on these balances see [`Balance::MaybeTimeoutClaimableHTLC`] and
+ /// [`Balance::MaybePreimageClaimableHTLC`].
+ ///
+ /// On-chain fees required to claim the balance are not included in this amount.
+ pub fn claimable_amount_satoshis(&self) -> u64 {
+ match self {
+ Balance::ClaimableOnChannelClose {
+ claimable_amount_satoshis,
+ } => *claimable_amount_satoshis,
+ Balance::ClaimableAwaitingConfirmations {
+ claimable_amount_satoshis,
+ ..
+ } => *claimable_amount_satoshis,
+ Balance::ContentiousClaimable {
+ claimable_amount_satoshis,
+ ..
+ } => *claimable_amount_satoshis,
+ Balance::MaybeTimeoutClaimableHTLC {
+ ..
+ } => 0,
+ Balance::MaybePreimageClaimableHTLC {
+ ..
+ } => 0,
+ Balance::CounterpartyRevokedOutputClaimable {
+ claimable_amount_satoshis,
+ ..
+ } => *claimable_amount_satoshis,
+ }
+ }
+}
+
/// An HTLC which has been irrevocably resolved on-chain, and has reached ANTI_REORG_DELAY.
#[derive(PartialEq, Eq)]
struct IrrevocablyResolvedHTLC {
where B::Target: BroadcasterInterface,
L::Target: Logger,
{
- for tx in self.get_latest_holder_commitment_txn(logger).iter() {
+ let commit_txs = self.get_latest_holder_commitment_txn(logger);
+ let mut txs = vec![];
+ for tx in commit_txs.iter() {
log_info!(logger, "Broadcasting local {}", log_tx!(tx));
- broadcaster.broadcast_transaction(tx);
+ txs.push(tx);
}
+ broadcaster.broadcast_transactions(&txs);
self.pending_monitor_events.push(MonitorEvent::CommitmentTxConfirmed(self.funding_info.0));
}
F::Target: FeeEstimator,
L::Target: Logger,
{
- log_info!(logger, "Applying update to monitor {}, bringing update_id from {} to {} with {} changes.",
- log_funding_info!(self), self.latest_update_id, updates.update_id, updates.updates.len());
+ if self.latest_update_id == CLOSED_CHANNEL_UPDATE_ID && updates.update_id == CLOSED_CHANNEL_UPDATE_ID {
+ log_info!(logger, "Applying post-force-closed update to monitor {} with {} change(s).",
+ log_funding_info!(self), updates.updates.len());
+ } else if updates.update_id == CLOSED_CHANNEL_UPDATE_ID {
+ log_info!(logger, "Applying force close update to monitor {} with {} change(s).",
+ log_funding_info!(self), updates.updates.len());
+ } else {
+ log_info!(logger, "Applying update to monitor {}, bringing update_id from {} to {} with {} change(s).",
+ log_funding_info!(self), self.latest_update_id, updates.update_id, updates.updates.len());
+ }
// ChannelMonitor updates may be applied after force close if we receive a preimage for a
// broadcasted commitment transaction HTLC output that we'd like to claim on-chain. If this
// is the case, we no longer have guaranteed access to the monitor's update ID, so we use a
_ => false,
}).is_some();
if detected_funding_spend {
+ log_trace!(logger, "Avoiding commitment broadcast, already detected confirmed spend onchain");
continue;
}
self.broadcast_latest_holder_commitment_txn(broadcaster, logger);
self.latest_update_id = updates.update_id;
- if ret.is_ok() && self.funding_spend_seen {
+ // Refuse updates after we've detected a spend onchain, but only if we haven't processed a
+ // force closed monitor update yet.
+ if ret.is_ok() && self.funding_spend_seen && self.latest_update_id != CLOSED_CHANNEL_UPDATE_ID {
log_error!(logger, "Refusing Channel Monitor Update as counterparty attempted to update commitment after funding was spent");
Err(())
} else { ret }
#[cfg(test)]
mod tests {
- use bitcoin::blockdata::block::BlockHeader;
use bitcoin::blockdata::script::{Script, Builder};
use bitcoin::blockdata::opcodes;
use bitcoin::blockdata::transaction::{Transaction, TxIn, TxOut, EcdsaSighashType};
use crate::util::ser::{ReadableArgs, Writeable};
use crate::sync::{Arc, Mutex};
use crate::io;
- use bitcoin::{PackedLockTime, Sequence, TxMerkleNode, Witness};
+ use bitcoin::{PackedLockTime, Sequence, Witness};
use crate::prelude::*;
fn do_test_funding_spend_refuses_updates(use_local_txn: bool) {
// Connect a commitment transaction, but only to the ChainMonitor/ChannelMonitor. The
// channel is now closed, but the ChannelManager doesn't know that yet.
- let new_header = BlockHeader {
- version: 2, time: 0, bits: 0, nonce: 0,
- prev_blockhash: nodes[0].best_block_info().0,
- merkle_root: TxMerkleNode::all_zeros() };
+ let new_header = create_dummy_header(nodes[0].best_block_info().0, 0);
let conf_height = nodes[0].best_block_info().1 + 1;
nodes[1].chain_monitor.chain_monitor.transactions_confirmed(&new_header,
&[(0, broadcast_tx)], conf_height);