use crate::util::ser::{Readable, ReadableArgs, RequiredWrapper, MaybeReadable, UpgradableRequired, Writer, Writeable, U48};
use crate::util::byte_utils;
use crate::events::{Event, EventHandler};
-use crate::events::bump_transaction::{AnchorDescriptor, HTLCDescriptor, BumpTransactionEvent};
+use crate::events::bump_transaction::{ChannelDerivationParameters, AnchorDescriptor, HTLCDescriptor, BumpTransactionEvent};
use crate::prelude::*;
use core::{cmp, mem};
(8, delayed_payment_key, required),
(10, per_commitment_point, required),
(12, feerate_per_kw, required),
- (14, htlc_outputs, vec_type)
+ (14, htlc_outputs, required_vec)
});
impl HolderSignedTx {
/// We use this to track static counterparty commitment transaction data and to generate any
/// justice or 2nd-stage preimage/timeout transactions.
-#[derive(PartialEq, Eq)]
+#[derive(Clone, PartialEq, Eq)]
struct CounterpartyCommitmentParameters {
counterparty_delayed_payment_base_key: PublicKey,
counterparty_htlc_base_key: PublicKey,
/// observed, as well as the transaction causing it.
///
/// Used to determine when the on-chain event can be considered safe from a chain reorganization.
-#[derive(PartialEq, Eq)]
+#[derive(Clone, PartialEq, Eq)]
struct OnchainEventEntry {
txid: Txid,
height: u32,
/// Upon discovering of some classes of onchain tx by ChannelMonitor, we may have to take actions on it
/// once they mature to enough confirmations (ANTI_REORG_DELAY)
-#[derive(PartialEq, Eq)]
+#[derive(Clone, PartialEq, Eq)]
enum OnchainEvent {
/// An outbound HTLC failing after a transaction is confirmed. Used
/// * when an outbound HTLC output is spent by us after the HTLC timed out
impl_writeable_tlv_based_enum_upgradable!(ChannelMonitorUpdateStep,
(0, LatestHolderCommitmentTXInfo) => {
(0, commitment_tx, required),
- (1, claimed_htlcs, vec_type),
- (2, htlc_outputs, vec_type),
+ (1, claimed_htlcs, optional_vec),
+ (2, htlc_outputs, required_vec),
(4, nondust_htlc_sources, optional_vec),
},
(1, LatestCounterpartyCommitmentTXInfo) => {
(0, commitment_txid, required),
(2, commitment_number, required),
(4, their_per_commitment_point, required),
- (6, htlc_outputs, vec_type),
+ (6, htlc_outputs, required_vec),
},
(2, PaymentPreimage) => {
(0, payment_preimage, required),
ClaimableOnChannelClose {
/// The amount available to claim, in satoshis, excluding the on-chain fees which will be
/// required to do so.
- claimable_amount_satoshis: u64,
+ amount_satoshis: u64,
},
/// The channel has been closed, and the given balance is ours but awaiting confirmations until
/// we consider it spendable.
ClaimableAwaitingConfirmations {
/// The amount available to claim, in satoshis, possibly excluding the on-chain fees which
/// were spent in broadcasting the transaction.
- claimable_amount_satoshis: u64,
+ amount_satoshis: u64,
/// The height at which an [`Event::SpendableOutputs`] event will be generated for this
/// amount.
confirmation_height: u32,
ContentiousClaimable {
/// The amount available to claim, in satoshis, excluding the on-chain fees which will be
/// required to do so.
- claimable_amount_satoshis: u64,
+ amount_satoshis: u64,
/// The height at which the counterparty may be able to claim the balance if we have not
/// done so.
timeout_height: u32,
MaybeTimeoutClaimableHTLC {
/// The amount potentially available to claim, in satoshis, excluding the on-chain fees
/// which will be required to do so.
- claimable_amount_satoshis: u64,
+ amount_satoshis: u64,
/// The height at which we will be able to claim the balance if our counterparty has not
/// done so.
claimable_height: u32,
MaybePreimageClaimableHTLC {
/// The amount potentially available to claim, in satoshis, excluding the on-chain fees
/// which will be required to do so.
- claimable_amount_satoshis: u64,
+ amount_satoshis: u64,
/// The height at which our counterparty will be able to claim the balance if we have not
/// yet received the preimage and claimed it ourselves.
expiry_height: u32,
///
/// Note that for outputs from HTLC balances this may be excluding some on-chain fees that
/// were already spent.
- claimable_amount_satoshis: u64,
+ amount_satoshis: u64,
},
}
/// 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,
+ Balance::ClaimableOnChannelClose { amount_satoshis, .. }|
+ Balance::ClaimableAwaitingConfirmations { amount_satoshis, .. }|
+ Balance::ContentiousClaimable { amount_satoshis, .. }|
+ Balance::CounterpartyRevokedOutputClaimable { amount_satoshis, .. }
+ => *amount_satoshis,
+ Balance::MaybeTimeoutClaimableHTLC { .. }|
+ Balance::MaybePreimageClaimableHTLC { .. }
+ => 0,
}
}
}
/// An HTLC which has been irrevocably resolved on-chain, and has reached ANTI_REORG_DELAY.
-#[derive(PartialEq, Eq)]
+#[derive(Clone, PartialEq, Eq)]
struct IrrevocablyResolvedHTLC {
commitment_tx_output_idx: Option<u32>,
/// The txid of the transaction which resolved the HTLC, this may be a commitment (if the HTLC
pub(super) inner: Mutex<ChannelMonitorImpl<Signer>>,
}
-#[derive(PartialEq)]
+impl<Signer: WriteableEcdsaChannelSigner> Clone for ChannelMonitor<Signer> where Signer: Clone {
+ fn clone(&self) -> Self {
+ let inner = self.inner.lock().unwrap().clone();
+ ChannelMonitor::from_impl(inner)
+ }
+}
+
+#[derive(Clone, PartialEq)]
pub(crate) struct ChannelMonitorImpl<Signer: WriteableEcdsaChannelSigner> {
latest_update_id: u64,
commitment_transaction_number_obscure_factor: u64,
write_tlv_fields!(writer, {
(1, self.funding_spend_confirmed, option),
- (3, self.htlcs_resolved_on_chain, vec_type),
- (5, self.pending_monitor_events, vec_type),
+ (3, self.htlcs_resolved_on_chain, required_vec),
+ (5, self.pending_monitor_events, required_vec),
(7, self.funding_spend_seen, required),
(9, self.counterparty_node_id, option),
(11, self.confirmed_commitment_tx_counterparty_output, option),
- (13, self.spendable_txids_confirmed, vec_type),
+ (13, self.spendable_txids_confirmed, required_vec),
(15, self.counterparty_fulfilled_htlcs, required),
});
if let Some(conf_thresh) = holder_delayed_output_pending {
debug_assert!(holder_commitment);
return Some(Balance::ClaimableAwaitingConfirmations {
- claimable_amount_satoshis: htlc.amount_msat / 1000,
+ amount_satoshis: htlc.amount_msat / 1000,
confirmation_height: conf_thresh,
});
} else if htlc_resolved.is_some() && !htlc_output_spend_pending {
debug_assert!(!htlc.offered || htlc_spend_pending.is_none() || !htlc_spend_pending.unwrap().1,
"We don't (currently) generate preimage claims against revoked outputs, where did you get one?!");
return Some(Balance::CounterpartyRevokedOutputClaimable {
- claimable_amount_satoshis: htlc.amount_msat / 1000,
+ amount_satoshis: htlc.amount_msat / 1000,
});
}
} else if htlc.offered == holder_commitment {
// and awaiting confirmations on it.
if let Some(conf_thresh) = holder_timeout_spend_pending {
return Some(Balance::ClaimableAwaitingConfirmations {
- claimable_amount_satoshis: htlc.amount_msat / 1000,
+ amount_satoshis: htlc.amount_msat / 1000,
confirmation_height: conf_thresh,
});
} else {
return Some(Balance::MaybeTimeoutClaimableHTLC {
- claimable_amount_satoshis: htlc.amount_msat / 1000,
+ amount_satoshis: htlc.amount_msat / 1000,
claimable_height: htlc.cltv_expiry,
payment_hash: htlc.payment_hash,
});
debug_assert!(holder_timeout_spend_pending.is_none());
if let Some((conf_thresh, true)) = htlc_spend_pending {
return Some(Balance::ClaimableAwaitingConfirmations {
- claimable_amount_satoshis: htlc.amount_msat / 1000,
+ amount_satoshis: htlc.amount_msat / 1000,
confirmation_height: conf_thresh,
});
} else {
return Some(Balance::ContentiousClaimable {
- claimable_amount_satoshis: htlc.amount_msat / 1000,
+ amount_satoshis: htlc.amount_msat / 1000,
timeout_height: htlc.cltv_expiry,
payment_hash: htlc.payment_hash,
payment_preimage: *payment_preimage,
}
} else if htlc_resolved.is_none() {
return Some(Balance::MaybePreimageClaimableHTLC {
- claimable_amount_satoshis: htlc.amount_msat / 1000,
+ amount_satoshis: htlc.amount_msat / 1000,
expiry_height: htlc.cltv_expiry,
payment_hash: htlc.payment_hash,
});
} else { None }
}) {
res.push(Balance::ClaimableAwaitingConfirmations {
- claimable_amount_satoshis: value,
+ amount_satoshis: value,
confirmation_height: conf_thresh,
});
} else {
descriptor: SpendableOutputDescriptor::StaticOutput { output, .. }
} = &event.event {
res.push(Balance::ClaimableAwaitingConfirmations {
- claimable_amount_satoshis: output.value,
+ amount_satoshis: output.value,
confirmation_height: event.confirmation_threshold(),
});
if let Some(confirmed_to_self_idx) = confirmed_counterparty_output.map(|(idx, _)| idx) {
.is_output_spend_pending(&BitcoinOutPoint::new(txid, confirmed_to_self_idx));
if output_spendable {
res.push(Balance::CounterpartyRevokedOutputClaimable {
- claimable_amount_satoshis: amt,
+ amount_satoshis: amt,
});
}
} else {
walk_htlcs!(true, false, us.current_holder_commitment_tx.htlc_outputs.iter().map(|(a, _, _)| a));
if let Some(conf_thresh) = pending_commitment_tx_conf_thresh {
res.push(Balance::ClaimableAwaitingConfirmations {
- claimable_amount_satoshis: us.current_holder_commitment_tx.to_self_value_sat,
+ amount_satoshis: us.current_holder_commitment_tx.to_self_value_sat,
confirmation_height: conf_thresh,
});
}
walk_htlcs!(true, false, prev_commitment.htlc_outputs.iter().map(|(a, _, _)| a));
if let Some(conf_thresh) = pending_commitment_tx_conf_thresh {
res.push(Balance::ClaimableAwaitingConfirmations {
- claimable_amount_satoshis: prev_commitment.to_self_value_sat,
+ amount_satoshis: prev_commitment.to_self_value_sat,
confirmation_height: conf_thresh,
});
}
// neither us nor our counterparty misbehaved. At worst we've under-estimated
// the amount we can claim as we'll punish a misbehaving counterparty.
res.push(Balance::ClaimableAwaitingConfirmations {
- claimable_amount_satoshis: us.current_holder_commitment_tx.to_self_value_sat,
+ amount_satoshis: us.current_holder_commitment_tx.to_self_value_sat,
confirmation_height: conf_thresh,
});
}
if htlc.transaction_output_index.is_none() { continue; }
if htlc.offered {
res.push(Balance::MaybeTimeoutClaimableHTLC {
- claimable_amount_satoshis: htlc.amount_msat / 1000,
+ amount_satoshis: htlc.amount_msat / 1000,
claimable_height: htlc.cltv_expiry,
payment_hash: htlc.payment_hash,
});
// As long as the HTLC is still in our latest commitment state, treat
// it as potentially claimable, even if it has long-since expired.
res.push(Balance::MaybePreimageClaimableHTLC {
- claimable_amount_satoshis: htlc.amount_msat / 1000,
+ amount_satoshis: htlc.amount_msat / 1000,
expiry_height: htlc.cltv_expiry,
payment_hash: htlc.payment_hash,
});
}
}
res.push(Balance::ClaimableOnChannelClose {
- claimable_amount_satoshis: us.current_holder_commitment_tx.to_self_value_sat + claimable_inbound_htlc_value_sat,
+ amount_satoshis: us.current_holder_commitment_tx.to_self_value_sat + claimable_inbound_htlc_value_sat,
});
}
commitment_tx,
commitment_tx_fee_satoshis,
anchor_descriptor: AnchorDescriptor {
- channel_keys_id: self.channel_keys_id,
- channel_value_satoshis: self.channel_value_satoshis,
+ channel_derivation_parameters: ChannelDerivationParameters {
+ keys_id: self.channel_keys_id,
+ value_satoshis: self.channel_value_satoshis,
+ transaction_parameters: self.onchain_tx_handler.channel_transaction_parameters.clone(),
+ },
outpoint: BitcoinOutPoint {
txid: commitment_txid,
vout: anchor_output_idx,
let mut htlc_descriptors = Vec::with_capacity(htlcs.len());
for htlc in htlcs {
htlc_descriptors.push(HTLCDescriptor {
- channel_keys_id: self.channel_keys_id,
- channel_value_satoshis: self.channel_value_satoshis,
- channel_parameters: self.onchain_tx_handler.channel_transaction_parameters.clone(),
+ channel_derivation_parameters: ChannelDerivationParameters {
+ keys_id: self.channel_keys_id,
+ value_satoshis: self.channel_value_satoshis,
+ transaction_parameters: self.onchain_tx_handler.channel_transaction_parameters.clone(),
+ },
commitment_txid: htlc.commitment_txid,
per_commitment_number: htlc.per_commitment_number,
per_commitment_point: self.onchain_tx_handler.signer.get_per_commitment_point(
let mut counterparty_fulfilled_htlcs = Some(HashMap::new());
read_tlv_fields!(reader, {
(1, funding_spend_confirmed, option),
- (3, htlcs_resolved_on_chain, vec_type),
- (5, pending_monitor_events, vec_type),
+ (3, htlcs_resolved_on_chain, optional_vec),
+ (5, pending_monitor_events, optional_vec),
(7, funding_spend_seen, option),
(9, counterparty_node_id, option),
(11, confirmed_commitment_tx_counterparty_output, option),
- (13, spendable_txids_confirmed, vec_type),
+ (13, spendable_txids_confirmed, optional_vec),
(15, counterparty_fulfilled_htlcs, option),
});
assert!(err.contains("ChannelMonitor storage failure")));
check_added_monitors!(nodes[1], 2); // After the failure we generate a close-channel monitor update
check_closed_broadcast!(nodes[1], true);
- check_closed_event!(nodes[1], 1, ClosureReason::ProcessingError { err: "ChannelMonitor storage failure".to_string() });
+ check_closed_event!(nodes[1], 1, ClosureReason::ProcessingError { err: "ChannelMonitor storage failure".to_string() },
+ [nodes[0].node.get_our_node_id()], 100000);
// Build a new ChannelMonitorUpdate which contains both the failing commitment tx update
// and provides the claim preimages for the two pending HTLCs. The first update generates