/// exceeding this age limit will be force-closed and purged from memory.
pub(crate) const UNFUNDED_CHANNEL_AGE_LIMIT_TICKS: usize = 60;
+/// Number of blocks needed for an output from a coinbase transaction to be spendable.
+pub(crate) const COINBASE_MATURITY: u32 = 100;
+
struct PendingChannelMonitorUpdate {
update: ChannelMonitorUpdate,
}
(commitment_tx_base_weight(channel_type_features) + num_htlcs as u64 * COMMITMENT_TX_WEIGHT_PER_HTLC) * feerate_per_kw as u64 / 1000 * 1000
}
-// TODO: We should refactor this to be an Inbound/OutboundChannel until initial setup handshaking
-// has been completed, and then turn into a Channel to get compiler-time enforcement of things like
-// calling channel_id() before we're set up or things like get_funding_signed on an
-// inbound channel.
-//
// Holder designates channel data owned for the benefit of the user client.
// Counterparty designates channel data owned by the another channel participant entity.
pub(super) struct Channel<SP: Deref> where SP::Target: SignerProvider {
return Err(ClosureReason::ProcessingError { err: err_reason.to_owned() });
} else {
if self.context.is_outbound() {
- for input in tx.input.iter() {
- if input.witness.is_empty() {
- // We generated a malleable funding transaction, implying we've
- // just exposed ourselves to funds loss to our counterparty.
- #[cfg(not(fuzzing))]
- panic!("Client called ChannelManager::funding_transaction_generated with bogus transaction!");
+ if !tx.is_coin_base() {
+ for input in tx.input.iter() {
+ if input.witness.is_empty() {
+ // We generated a malleable funding transaction, implying we've
+ // just exposed ourselves to funds loss to our counterparty.
+ #[cfg(not(fuzzing))]
+ panic!("Client called ChannelManager::funding_transaction_generated with bogus transaction!");
+ }
}
}
}
Err(_) => panic!("Block was bogus - either height was > 16 million, had > 16 million transactions, or had > 65k outputs"),
}
}
+ // If this is a coinbase transaction and not a 0-conf channel
+ // we should update our min_depth to 100 to handle coinbase maturity
+ if tx.is_coin_base() &&
+ self.context.minimum_depth.unwrap_or(0) > 0 &&
+ self.context.minimum_depth.unwrap_or(0) < COINBASE_MATURITY {
+ self.context.minimum_depth = Some(COINBASE_MATURITY);
+ }
}
// If we allow 1-conf funding, we may need to check for channel_ready here and
// send it immediately instead of waiting for a best_block_updated call (which
self.context.channel_state = ChannelState::FundingCreated as u32;
self.context.channel_id = funding_txo.to_channel_id();
+
+ // If the funding transaction is a coinbase transaction, we need to set the minimum depth to 100.
+ // We can skip this if it is a zero-conf channel.
+ if funding_transaction.is_coin_base() &&
+ self.context.minimum_depth.unwrap_or(0) > 0 &&
+ self.context.minimum_depth.unwrap_or(0) < COINBASE_MATURITY {
+ self.context.minimum_depth = Some(COINBASE_MATURITY);
+ }
+
self.context.funding_transaction = Some(funding_transaction);
let channel = Channel {