use bitcoin::secp256k1::{Secp256k1, ecdsa::Signature};
use bitcoin::secp256k1;
+use crate::chain::chaininterface::compute_feerate_sat_per_1000_weight;
use crate::sign::{ChannelSigner, EntropySource, SignerProvider};
use crate::ln::msgs::DecodeError;
use crate::ln::PaymentPreimage;
/// 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,
/// Events for claims the [`OnchainTxHandler`] has generated. Once the events are considered safe
/// from a chain reorg, the [`OnchainTxHandler`] will act accordingly.
-#[derive(PartialEq, Eq)]
+#[derive(Clone, PartialEq, Eq)]
enum OnchainEvent {
/// A pending request has been claimed by a transaction spending the exact same set of outpoints
/// as the request. This claim can either be ours or from the counterparty. Once the claiming
}
/// The claim commonly referred to as the pre-signed second-stage HTLC transaction.
+#[derive(Clone, PartialEq, Eq)]
pub(crate) struct ExternalHTLCClaim {
pub(crate) commitment_txid: Txid,
pub(crate) per_commitment_number: u64,
// Represents the different types of claims for which events are yielded externally to satisfy said
// claims.
+#[derive(Clone, PartialEq, Eq)]
pub(crate) enum ClaimEvent {
/// Event yielded to signal that the commitment transaction fee must be bumped to claim any
/// encumbered funds and proceed to HTLC resolution, if any HTLCs exist.
/// OnchainTxHandler receives claiming requests, aggregates them if it's sound, broadcast and
/// do RBF bumping if possible.
+#[derive(Clone)]
pub struct OnchainTxHandler<ChannelSigner: WriteableEcdsaChannelSigner> {
destination_script: Script,
holder_commitment: HolderCommitmentTransaction,
return inputs.find_map(|input| match input {
// Commitment inputs with anchors support are the only untractable inputs supported
// thus far that require external funding.
- PackageSolvingData::HolderFundingOutput(..) => {
+ PackageSolvingData::HolderFundingOutput(output) => {
debug_assert_eq!(tx.txid(), self.holder_commitment.trust().txid(),
"Holder commitment transaction mismatch");
+
+ let conf_target = ConfirmationTarget::HighPriority;
+ let package_target_feerate_sat_per_1000_weight = cached_request
+ .compute_package_feerate(fee_estimator, conf_target, force_feerate_bump);
+ if let Some(input_amount_sat) = output.funding_amount {
+ let fee_sat = input_amount_sat - tx.output.iter().map(|output| output.value).sum::<u64>();
+ let commitment_tx_feerate_sat_per_1000_weight =
+ compute_feerate_sat_per_1000_weight(fee_sat, tx.weight() as u64);
+ if commitment_tx_feerate_sat_per_1000_weight >= package_target_feerate_sat_per_1000_weight {
+ log_debug!(logger, "Pre-signed {} already has feerate {} sat/kW above required {} sat/kW",
+ log_tx!(tx), commitment_tx_feerate_sat_per_1000_weight,
+ package_target_feerate_sat_per_1000_weight);
+ return Some((new_timer, 0, OnchainClaim::Tx(tx.clone())));
+ }
+ }
+
// We'll locate an anchor output we can spend within the commitment transaction.
let funding_pubkey = &self.channel_transaction_parameters.holder_pubkeys.funding_pubkey;
match chan_utils::get_anchor_output(&tx, funding_pubkey) {
Some((idx, _)) => {
// TODO: Use a lower confirmation target when both our and the
// counterparty's latest commitment don't have any HTLCs present.
- let conf_target = ConfirmationTarget::HighPriority;
- let package_target_feerate_sat_per_1000_weight = cached_request
- .compute_package_feerate(fee_estimator, conf_target, force_feerate_bump);
Some((
new_timer,
package_target_feerate_sat_per_1000_weight as u64,
) {
req.set_timer(new_timer);
req.set_feerate(new_feerate);
+ // Once a pending claim has an id assigned, it remains fixed until the claim is
+ // satisfied, regardless of whether the claim switches between different variants of
+ // `OnchainClaim`.
let claim_id = match claim {
OnchainClaim::Tx(tx) => {
log_info!(logger, "Broadcasting onchain {}", log_tx!(tx));
ret
}
+ pub(crate) fn get_unsigned_holder_commitment_tx(&self) -> &Transaction {
+ &self.holder_commitment.trust().built_transaction().transaction
+ }
+
//TODO: getting lastest holder transactions should be infallible and result in us "force-closing the channel", but we may
- // have empty holder commitment transaction if a ChannelMonitor is asked to force-close just after Channel::get_outbound_funding_created,
+ // have empty holder commitment transaction if a ChannelMonitor is asked to force-close just after OutboundV1Channel::get_funding_created,
// before providing a initial commitment transaction. For outbound channel, init ChannelMonitor at Channel::funding_signed, there is nothing
// to monitor before.
pub(crate) fn get_fully_signed_holder_tx(&mut self, funding_redeemscript: &Script) -> Transaction {