use crate::chain::chaininterface::{FeeEstimator, ConfirmationTarget, LowerBoundedFeeEstimator};
use crate::chain::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate, ChannelMonitorUpdateStep, LATENCY_GRACE_PERIOD_BLOCKS};
use crate::chain::transaction::{OutPoint, TransactionData};
-use crate::chain::keysinterface::{Sign, EntropySource, KeysInterface, BaseSign, SignerProvider};
+use crate::chain::keysinterface::{Sign, EntropySource, BaseSign, NodeSigner, Recipient, SignerProvider};
use crate::util::events::ClosureReason;
use crate::util::ser::{Readable, ReadableArgs, Writeable, Writer, VecWriter};
use crate::util::logger::Logger;
/// In order to avoid having to concern ourselves with standardness during the closing process, we
/// simply require our counterparty to use a dust limit which will leave any segwit output
/// standard.
-/// See https://github.com/lightning/bolts/issues/905 for more details.
+/// See <https://github.com/lightning/bolts/issues/905> for more details.
pub const MIN_CHAN_DUST_LIMIT_SATOSHIS: u64 = 354;
// Just a reasonable implementation-specific safe lower bound, higher than the dust limit.
self.channel_transaction_parameters.opt_anchors.is_some()
}
- fn get_initial_channel_type(config: &UserConfig) -> ChannelTypeFeatures {
+ fn get_initial_channel_type(config: &UserConfig, their_features: &InitFeatures) -> ChannelTypeFeatures {
// The default channel type (ie the first one we try) depends on whether the channel is
// public - if it is, we just go with `only_static_remotekey` as it's the only option
// available. If it's private, we first try `scid_privacy` as it provides better privacy
- // with no other changes, and fall back to `only_static_remotekey`
+ // with no other changes, and fall back to `only_static_remotekey`.
let mut ret = ChannelTypeFeatures::only_static_remote_key();
- if !config.channel_handshake_config.announced_channel && config.channel_handshake_config.negotiate_scid_privacy {
+ if !config.channel_handshake_config.announced_channel &&
+ config.channel_handshake_config.negotiate_scid_privacy &&
+ their_features.supports_scid_privacy() {
ret.set_scid_privacy_required();
}
+
+ // Optionally, if the user would like to negotiate the `anchors_zero_fee_htlc_tx` option, we
+ // set it now. If they don't understand it, we'll fall back to our default of
+ // `only_static_remotekey`.
+ #[cfg(anchors)]
+ { // Attributes are not allowed on if expressions on our current MSRV of 1.41.
+ if config.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx &&
+ their_features.supports_anchors_zero_fee_htlc_tx() {
+ ret.set_anchors_zero_fee_htlc_tx_required();
+ }
+ }
+
ret
}
// We've exhausted our options
return Err(());
}
- self.channel_type = ChannelTypeFeatures::only_static_remote_key(); // We only currently support two types
+ // We support opening a few different types of channels. Try removing our additional
+ // features one by one until we've either arrived at our default or the counterparty has
+ // accepted one.
+ //
+ // Due to the order below, we may not negotiate `option_anchors_zero_fee_htlc_tx` if the
+ // counterparty doesn't support `option_scid_privacy`. Since `get_initial_channel_type`
+ // checks whether the counterparty supports every feature, this would only happen if the
+ // counterparty is advertising the feature, but rejecting channels proposing the feature for
+ // whatever reason.
+ if self.channel_type.supports_anchors_zero_fee_htlc_tx() {
+ self.channel_type.clear_anchors_zero_fee_htlc_tx();
+ assert!(self.channel_transaction_parameters.opt_non_zero_fee_anchors.is_none());
+ self.channel_transaction_parameters.opt_anchors = None;
+ } else if self.channel_type.supports_scid_privacy() {
+ self.channel_type.clear_scid_privacy();
+ } else {
+ self.channel_type = ChannelTypeFeatures::only_static_remote_key();
+ }
Ok(self.get_open_channel(chain_hash))
}
// Constructors:
- pub fn new_outbound<K: Deref, F: Deref>(
- fee_estimator: &LowerBoundedFeeEstimator<F>, keys_provider: &K, counterparty_node_id: PublicKey, their_features: &InitFeatures,
+ pub fn new_outbound<ES: Deref, SP: Deref, F: Deref>(
+ fee_estimator: &LowerBoundedFeeEstimator<F>, entropy_source: &ES, signer_provider: &SP, counterparty_node_id: PublicKey, their_features: &InitFeatures,
channel_value_satoshis: u64, push_msat: u64, user_id: u128, config: &UserConfig, current_chain_height: u32,
outbound_scid_alias: u64
) -> Result<Channel<Signer>, APIError>
- where K::Target: KeysInterface<Signer = Signer>,
+ where ES::Target: EntropySource,
+ SP::Target: SignerProvider<Signer = Signer>,
F::Target: FeeEstimator,
{
- let opt_anchors = false; // TODO - should be based on features
-
let holder_selected_contest_delay = config.channel_handshake_config.our_to_self_delay;
- let channel_keys_id = keys_provider.generate_channel_keys_id(false, channel_value_satoshis, user_id);
- let holder_signer = keys_provider.derive_channel_signer(channel_value_satoshis, channel_keys_id);
+ let channel_keys_id = signer_provider.generate_channel_keys_id(false, channel_value_satoshis, user_id);
+ let holder_signer = signer_provider.derive_channel_signer(channel_value_satoshis, channel_keys_id);
let pubkeys = holder_signer.pubkeys().clone();
if !their_features.supports_wumbo() && channel_value_satoshis > MAX_FUNDING_SATOSHIS_NO_WUMBO {
return Err(APIError::APIMisuseError { err: format!("Holder selected channel reserve below implemention limit dust_limit_satoshis {}", holder_selected_channel_reserve_satoshis) });
}
+ let channel_type = Self::get_initial_channel_type(&config, their_features);
+ debug_assert!(channel_type.is_subset(&channelmanager::provided_channel_type_features(&config)));
+
let feerate = fee_estimator.bounded_sat_per_1000_weight(ConfirmationTarget::Normal);
let value_to_self_msat = channel_value_satoshis * 1000 - push_msat;
- let commitment_tx_fee = Self::commit_tx_fee_msat(feerate, MIN_AFFORDABLE_HTLC_COUNT, opt_anchors);
+ let commitment_tx_fee = Self::commit_tx_fee_msat(feerate, MIN_AFFORDABLE_HTLC_COUNT, channel_type.requires_anchors_zero_fee_htlc_tx());
if value_to_self_msat < commitment_tx_fee {
return Err(APIError::APIMisuseError{ err: format!("Funding amount ({}) can't even pay fee for initial commitment transaction fee of {}.", value_to_self_msat / 1000, commitment_tx_fee / 1000) });
}
let mut secp_ctx = Secp256k1::new();
- secp_ctx.seeded_randomize(&keys_provider.get_secure_random_bytes());
+ secp_ctx.seeded_randomize(&entropy_source.get_secure_random_bytes());
let shutdown_scriptpubkey = if config.channel_handshake_config.commit_upfront_shutdown_pubkey {
- Some(keys_provider.get_shutdown_scriptpubkey())
+ Some(signer_provider.get_shutdown_scriptpubkey())
} else { None };
if let Some(shutdown_scriptpubkey) = &shutdown_scriptpubkey {
inbound_handshake_limits_override: Some(config.channel_handshake_limits.clone()),
- channel_id: keys_provider.get_secure_random_bytes(),
+ channel_id: entropy_source.get_secure_random_bytes(),
channel_state: ChannelState::OurInitSent as u32,
announcement_sigs_state: AnnouncementSigsState::NotSent,
secp_ctx,
holder_signer,
shutdown_scriptpubkey,
- destination_script: keys_provider.get_destination_script(),
+ destination_script: signer_provider.get_destination_script(),
cur_holder_commitment_transaction_number: INITIAL_COMMITMENT_NUMBER,
cur_counterparty_commitment_transaction_number: INITIAL_COMMITMENT_NUMBER,
is_outbound_from_holder: true,
counterparty_parameters: None,
funding_outpoint: None,
- opt_anchors: if opt_anchors { Some(()) } else { None },
+ opt_anchors: if channel_type.requires_anchors_zero_fee_htlc_tx() { Some(()) } else { None },
opt_non_zero_fee_anchors: None
},
funding_transaction: None,
#[cfg(any(test, fuzzing))]
historical_inbound_htlc_fulfills: HashSet::new(),
- channel_type: Self::get_initial_channel_type(&config),
+ channel_type,
channel_keys_id,
})
}
/// Creates a new channel from a remote sides' request for one.
/// Assumes chain_hash has already been checked and corresponds with what we expect!
- pub fn new_from_req<K: Deref, F: Deref, L: Deref>(
- fee_estimator: &LowerBoundedFeeEstimator<F>, keys_provider: &K, counterparty_node_id: PublicKey, their_features: &InitFeatures,
- msg: &msgs::OpenChannel, user_id: u128, config: &UserConfig, current_chain_height: u32, logger: &L,
- outbound_scid_alias: u64
+ pub fn new_from_req<ES: Deref, SP: Deref, F: Deref, L: Deref>(
+ fee_estimator: &LowerBoundedFeeEstimator<F>, entropy_source: &ES, signer_provider: &SP,
+ counterparty_node_id: PublicKey, our_supported_features: &ChannelTypeFeatures,
+ their_features: &InitFeatures, msg: &msgs::OpenChannel, user_id: u128, config: &UserConfig,
+ current_chain_height: u32, logger: &L, outbound_scid_alias: u64
) -> Result<Channel<Signer>, ChannelError>
- where K::Target: KeysInterface<Signer = Signer>,
- F::Target: FeeEstimator,
- L::Target: Logger,
+ where ES::Target: EntropySource,
+ SP::Target: SignerProvider<Signer = Signer>,
+ F::Target: FeeEstimator,
+ L::Target: Logger,
{
- let opt_anchors = false; // TODO - should be based on features
let announced_channel = if (msg.channel_flags & 1) == 1 { true } else { false };
// First check the channel type is known, failing before we do anything else if we don't
return Err(ChannelError::Close("Channel Type field contained optional bits - this is not allowed".to_owned()));
}
- if channel_type.requires_unknown_bits() {
- return Err(ChannelError::Close("Channel Type field contains unknown bits".to_owned()));
+ // We only support the channel types defined by the `ChannelManager` in
+ // `provided_channel_type_features`. The channel type must always support
+ // `static_remote_key`.
+ if !channel_type.requires_static_remote_key() {
+ return Err(ChannelError::Close("Channel Type was not understood - we require static remote key".to_owned()));
}
-
- // We currently only allow four channel types, so write it all out here - we allow
- // `only_static_remote_key` or `static_remote_key | zero_conf` in all contexts, and
- // further allow `static_remote_key | scid_privacy` or
- // `static_remote_key | scid_privacy | zero_conf`, if the channel is not
- // publicly announced.
- if *channel_type != ChannelTypeFeatures::only_static_remote_key() {
- if !channel_type.requires_scid_privacy() && !channel_type.requires_zero_conf() {
- return Err(ChannelError::Close("Channel Type was not understood".to_owned()));
- }
-
- if channel_type.requires_scid_privacy() && announced_channel {
- return Err(ChannelError::Close("SCID Alias/Privacy Channel Type cannot be set on a public channel".to_owned()));
- }
+ // Make sure we support all of the features behind the channel type.
+ if !channel_type.is_subset(our_supported_features) {
+ return Err(ChannelError::Close("Channel Type contains unsupported features".to_owned()));
+ }
+ if channel_type.requires_scid_privacy() && announced_channel {
+ return Err(ChannelError::Close("SCID Alias/Privacy Channel Type cannot be set on a public channel".to_owned()));
}
channel_type.clone()
} else {
- ChannelTypeFeatures::from_counterparty_init(&their_features)
+ let channel_type = ChannelTypeFeatures::from_init(&their_features);
+ if channel_type != ChannelTypeFeatures::only_static_remote_key() {
+ return Err(ChannelError::Close("Only static_remote_key is supported for non-negotiated channel types".to_owned()));
+ }
+ channel_type
};
- if !channel_type.supports_static_remote_key() {
- return Err(ChannelError::Close("Channel Type was not understood - we require static remote key".to_owned()));
- }
+ let opt_anchors = channel_type.supports_anchors_zero_fee_htlc_tx();
- let channel_keys_id = keys_provider.generate_channel_keys_id(true, msg.funding_satoshis, user_id);
- let holder_signer = keys_provider.derive_channel_signer(msg.funding_satoshis, channel_keys_id);
+ let channel_keys_id = signer_provider.generate_channel_keys_id(true, msg.funding_satoshis, user_id);
+ let holder_signer = signer_provider.derive_channel_signer(msg.funding_satoshis, channel_keys_id);
let pubkeys = holder_signer.pubkeys().clone();
let counterparty_pubkeys = ChannelPublicKeys {
funding_pubkey: msg.funding_pubkey,
} else { None };
let shutdown_scriptpubkey = if config.channel_handshake_config.commit_upfront_shutdown_pubkey {
- Some(keys_provider.get_shutdown_scriptpubkey())
+ Some(signer_provider.get_shutdown_scriptpubkey())
} else { None };
if let Some(shutdown_scriptpubkey) = &shutdown_scriptpubkey {
}
let mut secp_ctx = Secp256k1::new();
- secp_ctx.seeded_randomize(&keys_provider.get_secure_random_bytes());
+ secp_ctx.seeded_randomize(&entropy_source.get_secure_random_bytes());
let chan = Channel {
user_id,
holder_signer,
shutdown_scriptpubkey,
- destination_script: keys_provider.get_destination_script(),
+ destination_script: signer_provider.get_destination_script(),
cur_holder_commitment_transaction_number: INITIAL_COMMITMENT_NUMBER,
cur_counterparty_commitment_transaction_number: INITIAL_COMMITMENT_NUMBER,
} else if their_features.supports_channel_type() {
// Assume they've accepted the channel type as they said they understand it.
} else {
- self.channel_type = ChannelTypeFeatures::from_counterparty_init(&their_features)
+ let channel_type = ChannelTypeFeatures::from_init(&their_features);
+ if channel_type != ChannelTypeFeatures::only_static_remote_key() {
+ return Err(ChannelError::Close("Only static_remote_key is supported for non-negotiated channel types".to_owned()));
+ }
+ self.channel_type = channel_type;
}
let counterparty_shutdown_scriptpubkey = if their_features.supports_upfront_shutdown_script() {
&self.get_counterparty_pubkeys().funding_pubkey
}
- pub fn funding_created<K: Deref, L: Deref>(
- &mut self, msg: &msgs::FundingCreated, best_block: BestBlock, keys_source: &K, logger: &L
- ) -> Result<(msgs::FundingSigned, ChannelMonitor<<K::Target as SignerProvider>::Signer>, Option<msgs::ChannelReady>), ChannelError>
+ pub fn funding_created<SP: Deref, L: Deref>(
+ &mut self, msg: &msgs::FundingCreated, best_block: BestBlock, signer_provider: &SP, logger: &L
+ ) -> Result<(msgs::FundingSigned, ChannelMonitor<<SP::Target as SignerProvider>::Signer>, Option<msgs::ChannelReady>), ChannelError>
where
- K::Target: KeysInterface,
+ SP::Target: SignerProvider,
L::Target: Logger
{
if self.is_outbound() {
let funding_txo_script = funding_redeemscript.to_v0_p2wsh();
let obscure_factor = get_commitment_transaction_number_obscure_factor(&self.get_holder_pubkeys().payment_point, &self.get_counterparty_pubkeys().payment_point, self.is_outbound());
let shutdown_script = self.shutdown_scriptpubkey.clone().map(|script| script.into_inner());
- let mut monitor_signer = keys_source.derive_channel_signer(self.channel_value_satoshis, self.channel_keys_id);
+ let mut monitor_signer = signer_provider.derive_channel_signer(self.channel_value_satoshis, self.channel_keys_id);
monitor_signer.provide_channel_parameters(&self.channel_transaction_parameters);
let channel_monitor = ChannelMonitor::new(self.secp_ctx.clone(), monitor_signer,
shutdown_script, self.get_holder_selected_contest_delay(),
/// Handles a funding_signed message from the remote end.
/// If this call is successful, broadcast the funding transaction (and not before!)
- pub fn funding_signed<K: Deref, L: Deref>(
- &mut self, msg: &msgs::FundingSigned, best_block: BestBlock, keys_source: &K, logger: &L
- ) -> Result<(ChannelMonitor<<K::Target as SignerProvider>::Signer>, Transaction, Option<msgs::ChannelReady>), ChannelError>
+ pub fn funding_signed<SP: Deref, L: Deref>(
+ &mut self, msg: &msgs::FundingSigned, best_block: BestBlock, signer_provider: &SP, logger: &L
+ ) -> Result<(ChannelMonitor<<SP::Target as SignerProvider>::Signer>, Transaction, Option<msgs::ChannelReady>), ChannelError>
where
- K::Target: KeysInterface,
+ SP::Target: SignerProvider,
L::Target: Logger
{
if !self.is_outbound() {
let funding_txo_script = funding_redeemscript.to_v0_p2wsh();
let obscure_factor = get_commitment_transaction_number_obscure_factor(&self.get_holder_pubkeys().payment_point, &self.get_counterparty_pubkeys().payment_point, self.is_outbound());
let shutdown_script = self.shutdown_scriptpubkey.clone().map(|script| script.into_inner());
- let mut monitor_signer = keys_source.derive_channel_signer(self.channel_value_satoshis, self.channel_keys_id);
+ let mut monitor_signer = signer_provider.derive_channel_signer(self.channel_value_satoshis, self.channel_keys_id);
monitor_signer.provide_channel_parameters(&self.channel_transaction_parameters);
let channel_monitor = ChannelMonitor::new(self.secp_ctx.clone(), monitor_signer,
shutdown_script, self.get_holder_selected_contest_delay(),
/// Handles a channel_ready message from our peer. If we've already sent our channel_ready
/// and the channel is now usable (and public), this may generate an announcement_signatures to
/// reply with.
- pub fn channel_ready<L: Deref>(&mut self, msg: &msgs::ChannelReady, node_pk: PublicKey, genesis_block_hash: BlockHash, best_block: &BestBlock, logger: &L) -> Result<Option<msgs::AnnouncementSignatures>, ChannelError> where L::Target: Logger {
+ pub fn channel_ready<NS: Deref, L: Deref>(
+ &mut self, msg: &msgs::ChannelReady, node_signer: &NS, genesis_block_hash: BlockHash,
+ user_config: &UserConfig, best_block: &BestBlock, logger: &L
+ ) -> Result<Option<msgs::AnnouncementSignatures>, ChannelError>
+ where
+ NS::Target: NodeSigner,
+ L::Target: Logger
+ {
if self.channel_state & (ChannelState::PeerDisconnected as u32) == ChannelState::PeerDisconnected as u32 {
self.workaround_lnd_bug_4006 = Some(msg.clone());
return Err(ChannelError::Ignore("Peer sent channel_ready when we needed a channel_reestablish. The peer is likely lnd, see https://github.com/lightningnetwork/lnd/issues/4006".to_owned()));
log_info!(logger, "Received channel_ready from peer for channel {}", log_bytes!(self.channel_id()));
- Ok(self.get_announcement_sigs(node_pk, genesis_block_hash, best_block.height(), logger))
+ Ok(self.get_announcement_sigs(node_signer, genesis_block_hash, user_config, best_block.height(), logger))
}
/// Returns transaction if there is pending funding transaction that is yet to broadcast
/// Indicates that the latest ChannelMonitor update has been committed by the client
/// successfully and we should restore normal operation. Returns messages which should be sent
/// to the remote side.
- pub fn monitor_updating_restored<L: Deref>(&mut self, logger: &L, node_pk: PublicKey, genesis_block_hash: BlockHash, best_block_height: u32) -> MonitorRestoreUpdates where L::Target: Logger {
+ pub fn monitor_updating_restored<L: Deref, NS: Deref>(
+ &mut self, logger: &L, node_signer: &NS, genesis_block_hash: BlockHash,
+ user_config: &UserConfig, best_block_height: u32
+ ) -> MonitorRestoreUpdates
+ where
+ L::Target: Logger,
+ NS::Target: NodeSigner
+ {
assert_eq!(self.channel_state & ChannelState::MonitorUpdateInProgress as u32, ChannelState::MonitorUpdateInProgress as u32);
self.channel_state &= !(ChannelState::MonitorUpdateInProgress as u32);
})
} else { None };
- let announcement_sigs = self.get_announcement_sigs(node_pk, genesis_block_hash, best_block_height, logger);
+ let announcement_sigs = self.get_announcement_sigs(node_signer, genesis_block_hash, user_config, best_block_height, logger);
let mut accepted_htlcs = Vec::new();
mem::swap(&mut accepted_htlcs, &mut self.monitor_pending_forwards);
/// `cargo doc --document-private-items`):
/// [`super::channelmanager::ChannelManager::force_close_without_broadcasting_txn`] and
/// [`super::channelmanager::ChannelManager::force_close_all_channels_without_broadcasting_txn`].
- pub fn channel_reestablish<L: Deref>(&mut self, msg: &msgs::ChannelReestablish, logger: &L,
- node_pk: PublicKey, genesis_block_hash: BlockHash, best_block: &BestBlock)
- -> Result<ReestablishResponses, ChannelError> where L::Target: Logger {
+ pub fn channel_reestablish<L: Deref, NS: Deref>(
+ &mut self, msg: &msgs::ChannelReestablish, logger: &L, node_signer: &NS,
+ genesis_block_hash: BlockHash, user_config: &UserConfig, best_block: &BestBlock
+ ) -> Result<ReestablishResponses, ChannelError>
+ where
+ L::Target: Logger,
+ NS::Target: NodeSigner
+ {
if self.channel_state & (ChannelState::PeerDisconnected as u32) == 0 {
// While BOLT 2 doesn't indicate explicitly we should error this channel here, it
// almost certainly indicates we are going to end up out-of-sync in some way, so we
})
} else { None };
- let announcement_sigs = self.get_announcement_sigs(node_pk, genesis_block_hash, best_block.height(), logger);
+ let announcement_sigs = self.get_announcement_sigs(node_signer, genesis_block_hash, user_config, best_block.height(), logger);
if self.channel_state & (ChannelState::FundingSent as u32) == ChannelState::FundingSent as u32 {
// If we're waiting on a monitor update, we shouldn't re-send any channel_ready's.
}), None))
}
- pub fn shutdown<K: Deref>(
- &mut self, keys_provider: &K, their_features: &InitFeatures, msg: &msgs::Shutdown
+ pub fn shutdown<SP: Deref>(
+ &mut self, signer_provider: &SP, their_features: &InitFeatures, msg: &msgs::Shutdown
) -> Result<(Option<msgs::Shutdown>, Option<ChannelMonitorUpdate>, Vec<(HTLCSource, PaymentHash)>), ChannelError>
- where K::Target: KeysInterface
+ where SP::Target: SignerProvider
{
if self.channel_state & (ChannelState::PeerDisconnected as u32) == ChannelState::PeerDisconnected as u32 {
return Err(ChannelError::Close("Peer sent shutdown when we needed a channel_reestablish".to_owned()));
Some(_) => false,
None => {
assert!(send_shutdown);
- let shutdown_scriptpubkey = keys_provider.get_shutdown_scriptpubkey();
+ let shutdown_scriptpubkey = signer_provider.get_shutdown_scriptpubkey();
if !shutdown_scriptpubkey.is_compatible(their_features) {
return Err(ChannelError::Close(format!("Provided a scriptpubkey format not accepted by peer: {}", shutdown_scriptpubkey)));
}
/// When a transaction is confirmed, we check whether it is or spends the funding transaction
/// In the first case, we store the confirmation height and calculating the short channel id.
/// In the second, we simply return an Err indicating we need to be force-closed now.
- pub fn transactions_confirmed<L: Deref>(&mut self, block_hash: &BlockHash, height: u32,
- txdata: &TransactionData, genesis_block_hash: BlockHash, node_pk: PublicKey, logger: &L)
- -> Result<(Option<msgs::ChannelReady>, Option<msgs::AnnouncementSignatures>), ClosureReason> where L::Target: Logger {
+ pub fn transactions_confirmed<NS: Deref, L: Deref>(
+ &mut self, block_hash: &BlockHash, height: u32, txdata: &TransactionData,
+ genesis_block_hash: BlockHash, node_signer: &NS, user_config: &UserConfig, logger: &L
+ ) -> Result<(Option<msgs::ChannelReady>, Option<msgs::AnnouncementSignatures>), ClosureReason>
+ where
+ NS::Target: NodeSigner,
+ L::Target: Logger
+ {
if let Some(funding_txo) = self.get_funding_txo() {
for &(index_in_block, tx) in txdata.iter() {
// Check if the transaction is the expected funding transaction, and if it is,
// may have already happened for this block).
if let Some(channel_ready) = self.check_get_channel_ready(height) {
log_info!(logger, "Sending a channel_ready to our peer for channel {}", log_bytes!(self.channel_id));
- let announcement_sigs = self.get_announcement_sigs(node_pk, genesis_block_hash, height, logger);
+ let announcement_sigs = self.get_announcement_sigs(node_signer, genesis_block_hash, user_config, height, logger);
return Ok((Some(channel_ready), announcement_sigs));
}
}
///
/// May return some HTLCs (and their payment_hash) which have timed out and should be failed
/// back.
- pub fn best_block_updated<L: Deref>(&mut self, height: u32, highest_header_time: u32, genesis_block_hash: BlockHash, node_pk: PublicKey, logger: &L)
- -> Result<(Option<msgs::ChannelReady>, Vec<(HTLCSource, PaymentHash)>, Option<msgs::AnnouncementSignatures>), ClosureReason> where L::Target: Logger {
- self.do_best_block_updated(height, highest_header_time, Some((genesis_block_hash, node_pk)), logger)
+ pub fn best_block_updated<NS: Deref, L: Deref>(
+ &mut self, height: u32, highest_header_time: u32, genesis_block_hash: BlockHash,
+ node_signer: &NS, user_config: &UserConfig, logger: &L
+ ) -> Result<(Option<msgs::ChannelReady>, Vec<(HTLCSource, PaymentHash)>, Option<msgs::AnnouncementSignatures>), ClosureReason>
+ where
+ NS::Target: NodeSigner,
+ L::Target: Logger
+ {
+ self.do_best_block_updated(height, highest_header_time, Some((genesis_block_hash, node_signer, user_config)), logger)
}
- fn do_best_block_updated<L: Deref>(&mut self, height: u32, highest_header_time: u32, genesis_node_pk: Option<(BlockHash, PublicKey)>, logger: &L)
- -> Result<(Option<msgs::ChannelReady>, Vec<(HTLCSource, PaymentHash)>, Option<msgs::AnnouncementSignatures>), ClosureReason> where L::Target: Logger {
+ fn do_best_block_updated<NS: Deref, L: Deref>(
+ &mut self, height: u32, highest_header_time: u32,
+ genesis_node_signer: Option<(BlockHash, &NS, &UserConfig)>, logger: &L
+ ) -> Result<(Option<msgs::ChannelReady>, Vec<(HTLCSource, PaymentHash)>, Option<msgs::AnnouncementSignatures>), ClosureReason>
+ where
+ NS::Target: NodeSigner,
+ L::Target: Logger
+ {
let mut timed_out_htlcs = Vec::new();
// This mirrors the check in ChannelManager::decode_update_add_htlc_onion, refusing to
// forward an HTLC when our counterparty should almost certainly just fail it for expiring
self.update_time_counter = cmp::max(self.update_time_counter, highest_header_time);
if let Some(channel_ready) = self.check_get_channel_ready(height) {
- let announcement_sigs = if let Some((genesis_block_hash, node_pk)) = genesis_node_pk {
- self.get_announcement_sigs(node_pk, genesis_block_hash, height, logger)
+ let announcement_sigs = if let Some((genesis_block_hash, node_signer, user_config)) = genesis_node_signer {
+ self.get_announcement_sigs(node_signer, genesis_block_hash, user_config, height, logger)
} else { None };
log_info!(logger, "Sending a channel_ready to our peer for channel {}", log_bytes!(self.channel_id));
return Ok((Some(channel_ready), timed_out_htlcs, announcement_sigs));
return Err(ClosureReason::FundingTimedOut);
}
- let announcement_sigs = if let Some((genesis_block_hash, node_pk)) = genesis_node_pk {
- self.get_announcement_sigs(node_pk, genesis_block_hash, height, logger)
+ let announcement_sigs = if let Some((genesis_block_hash, node_signer, user_config)) = genesis_node_signer {
+ self.get_announcement_sigs(node_signer, genesis_block_hash, user_config, height, logger)
} else { None };
Ok((None, timed_out_htlcs, announcement_sigs))
}
// larger. If we don't know that time has moved forward, we can just set it to the last
// time we saw and it will be ignored.
let best_time = self.update_time_counter;
- match self.do_best_block_updated(reorg_height, best_time, None, logger) {
+ match self.do_best_block_updated(reorg_height, best_time, None::<(BlockHash, &&NodeSigner, &UserConfig)>, logger) {
Ok((channel_ready, timed_out_htlcs, announcement_sigs)) => {
assert!(channel_ready.is_none(), "We can't generate a funding with 0 confirmations?");
assert!(timed_out_htlcs.is_empty(), "We can't have accepted HTLCs with a timeout before our funding confirmation?");
/// closing).
///
/// This will only return ChannelError::Ignore upon failure.
- fn get_channel_announcement(&self, node_id: PublicKey, chain_hash: BlockHash) -> Result<msgs::UnsignedChannelAnnouncement, ChannelError> {
+ fn get_channel_announcement<NS: Deref>(
+ &self, node_signer: &NS, chain_hash: BlockHash, user_config: &UserConfig,
+ ) -> Result<msgs::UnsignedChannelAnnouncement, ChannelError> where NS::Target: NodeSigner {
if !self.config.announced_channel {
return Err(ChannelError::Ignore("Channel is not available for public announcements".to_owned()));
}
return Err(ChannelError::Ignore("Cannot get a ChannelAnnouncement if the channel is not currently usable".to_owned()));
}
+ let node_id = node_signer.get_node_id(Recipient::Node)
+ .map_err(|_| ChannelError::Ignore("Failed to retrieve own public key".to_owned()))?;
let were_node_one = node_id.serialize()[..] < self.counterparty_node_id.serialize()[..];
let msg = msgs::UnsignedChannelAnnouncement {
- features: channelmanager::provided_channel_features(),
+ features: channelmanager::provided_channel_features(&user_config),
chain_hash,
short_channel_id: self.get_short_channel_id().unwrap(),
node_id_1: if were_node_one { node_id } else { self.get_counterparty_node_id() },
Ok(msg)
}
- fn get_announcement_sigs<L: Deref>(&mut self, node_pk: PublicKey, genesis_block_hash: BlockHash, best_block_height: u32, logger: &L)
- -> Option<msgs::AnnouncementSignatures> where L::Target: Logger {
+ fn get_announcement_sigs<NS: Deref, L: Deref>(
+ &mut self, node_signer: &NS, genesis_block_hash: BlockHash, user_config: &UserConfig,
+ best_block_height: u32, logger: &L
+ ) -> Option<msgs::AnnouncementSignatures>
+ where
+ NS::Target: NodeSigner,
+ L::Target: Logger
+ {
if self.funding_tx_confirmation_height == 0 || self.funding_tx_confirmation_height + 5 > best_block_height {
return None;
}
}
log_trace!(logger, "Creating an announcement_signatures message for channel {}", log_bytes!(self.channel_id()));
- let announcement = match self.get_channel_announcement(node_pk, genesis_block_hash) {
+ let announcement = match self.get_channel_announcement(node_signer, genesis_block_hash, user_config) {
Ok(a) => a,
- Err(_) => {
- log_trace!(logger, "Cannot create an announcement_signatures as channel is not public.");
+ Err(e) => {
+ log_trace!(logger, "{:?}", e);
return None;
}
};
- let (our_node_sig, our_bitcoin_sig) = match self.holder_signer.sign_channel_announcement(&announcement, &self.secp_ctx) {
+ let our_node_sig = match node_signer.sign_gossip_message(msgs::UnsignedGossipMessage::ChannelAnnouncement(&announcement)) {
+ Err(_) => {
+ log_error!(logger, "Failed to generate node signature for channel_announcement. Channel will not be announced!");
+ return None;
+ },
+ Ok(v) => v
+ };
+ let our_bitcoin_sig = match self.holder_signer.sign_channel_announcement_with_funding_key(&announcement, &self.secp_ctx) {
Err(_) => {
log_error!(logger, "Signer rejected channel_announcement signing. Channel will not be announced!");
return None;
/// Signs the given channel announcement, returning a ChannelError::Ignore if no keys are
/// available.
- fn sign_channel_announcement(&self, our_node_id: PublicKey, announcement: msgs::UnsignedChannelAnnouncement) -> Result<msgs::ChannelAnnouncement, ChannelError> {
+ fn sign_channel_announcement<NS: Deref>(
+ &self, node_signer: &NS, announcement: msgs::UnsignedChannelAnnouncement
+ ) -> Result<msgs::ChannelAnnouncement, ChannelError> where NS::Target: NodeSigner {
if let Some((their_node_sig, their_bitcoin_sig)) = self.announcement_sigs {
- let were_node_one = announcement.node_id_1 == our_node_id;
+ let our_node_key = node_signer.get_node_id(Recipient::Node)
+ .map_err(|_| ChannelError::Ignore("Signer failed to retrieve own public key".to_owned()))?;
+ let were_node_one = announcement.node_id_1 == our_node_key;
- let (our_node_sig, our_bitcoin_sig) = self.holder_signer.sign_channel_announcement(&announcement, &self.secp_ctx)
+ let our_node_sig = node_signer.sign_gossip_message(msgs::UnsignedGossipMessage::ChannelAnnouncement(&announcement))
+ .map_err(|_| ChannelError::Ignore("Failed to generate node signature for channel_announcement".to_owned()))?;
+ let our_bitcoin_sig = self.holder_signer.sign_channel_announcement_with_funding_key(&announcement, &self.secp_ctx)
.map_err(|_| ChannelError::Ignore("Signer rejected channel_announcement".to_owned()))?;
Ok(msgs::ChannelAnnouncement {
node_signature_1: if were_node_one { our_node_sig } else { their_node_sig },
/// Processes an incoming announcement_signatures message, providing a fully-signed
/// channel_announcement message which we can broadcast and storing our counterparty's
/// signatures for later reconstruction/rebroadcast of the channel_announcement.
- pub fn announcement_signatures(&mut self, our_node_id: PublicKey, chain_hash: BlockHash, best_block_height: u32, msg: &msgs::AnnouncementSignatures) -> Result<msgs::ChannelAnnouncement, ChannelError> {
- let announcement = self.get_channel_announcement(our_node_id.clone(), chain_hash)?;
+ pub fn announcement_signatures<NS: Deref>(
+ &mut self, node_signer: &NS, chain_hash: BlockHash, best_block_height: u32,
+ msg: &msgs::AnnouncementSignatures, user_config: &UserConfig
+ ) -> Result<msgs::ChannelAnnouncement, ChannelError> where NS::Target: NodeSigner {
+ let announcement = self.get_channel_announcement(node_signer, chain_hash, user_config)?;
let msghash = hash_to_message!(&Sha256d::hash(&announcement.encode()[..])[..]);
"Got announcement_signatures prior to the required six confirmations - we may not have received a block yet that our peer has".to_owned()));
}
- self.sign_channel_announcement(our_node_id, announcement)
+ self.sign_channel_announcement(node_signer, announcement)
}
/// Gets a signed channel_announcement for this channel, if we previously received an
/// announcement_signatures from our counterparty.
- pub fn get_signed_channel_announcement(&self, our_node_id: PublicKey, chain_hash: BlockHash, best_block_height: u32) -> Option<msgs::ChannelAnnouncement> {
+ pub fn get_signed_channel_announcement<NS: Deref>(
+ &self, node_signer: &NS, chain_hash: BlockHash, best_block_height: u32, user_config: &UserConfig
+ ) -> Option<msgs::ChannelAnnouncement> where NS::Target: NodeSigner {
if self.funding_tx_confirmation_height == 0 || self.funding_tx_confirmation_height + 5 > best_block_height {
return None;
}
- let announcement = match self.get_channel_announcement(our_node_id.clone(), chain_hash) {
+ let announcement = match self.get_channel_announcement(node_signer, chain_hash, user_config) {
Ok(res) => res,
Err(_) => return None,
};
- match self.sign_channel_announcement(our_node_id, announcement) {
+ match self.sign_channel_announcement(node_signer, announcement) {
Ok(res) => Some(res),
Err(_) => None,
}
/// Begins the shutdown process, getting a message for the remote peer and returning all
/// holding cell HTLCs for payment failure.
- pub fn get_shutdown<K: Deref>(&mut self, keys_provider: &K, their_features: &InitFeatures, target_feerate_sats_per_kw: Option<u32>)
+ pub fn get_shutdown<SP: Deref>(&mut self, signer_provider: &SP, their_features: &InitFeatures, target_feerate_sats_per_kw: Option<u32>)
-> Result<(msgs::Shutdown, Option<ChannelMonitorUpdate>, Vec<(HTLCSource, PaymentHash)>), APIError>
- where K::Target: KeysInterface {
+ where SP::Target: SignerProvider {
for htlc in self.pending_outbound_htlcs.iter() {
if let OutboundHTLCState::LocalAnnounced(_) = htlc.state {
return Err(APIError::APIMisuseError{err: "Cannot begin shutdown with pending HTLCs. Process pending events first".to_owned()});
let update_shutdown_script = match self.shutdown_scriptpubkey {
Some(_) => false,
None => {
- let shutdown_scriptpubkey = keys_provider.get_shutdown_scriptpubkey();
+ let shutdown_scriptpubkey = signer_provider.get_shutdown_scriptpubkey();
if !shutdown_scriptpubkey.is_compatible(their_features) {
return Err(APIError::IncompatibleShutdownScript { script: shutdown_scriptpubkey.clone() });
}
}
const MAX_ALLOC_SIZE: usize = 64*1024;
-impl<'a, K: Deref> ReadableArgs<(&'a K, u32)> for Channel<<K::Target as SignerProvider>::Signer>
- where K::Target: KeysInterface {
- fn read<R : io::Read>(reader: &mut R, args: (&'a K, u32)) -> Result<Self, DecodeError> {
- let (keys_source, serialized_height) = args;
+impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c ChannelTypeFeatures)> for Channel<<SP::Target as SignerProvider>::Signer>
+ where
+ ES::Target: EntropySource,
+ SP::Target: SignerProvider
+{
+ fn read<R : io::Read>(reader: &mut R, args: (&'a ES, &'b SP, u32, &'c ChannelTypeFeatures)) -> Result<Self, DecodeError> {
+ let (entropy_source, signer_provider, serialized_height, our_supported_features) = args;
let ver = read_ver_prefix!(reader, SERIALIZATION_VERSION);
// `user_id` used to be a single u64 value. In order to remain backwards compatible with
});
let (channel_keys_id, holder_signer) = if let Some(channel_keys_id) = channel_keys_id {
- let mut holder_signer = keys_source.derive_channel_signer(channel_value_satoshis, channel_keys_id);
+ let mut holder_signer = signer_provider.derive_channel_signer(channel_value_satoshis, channel_keys_id);
// If we've gotten to the funding stage of the channel, populate the signer with its
// required channel parameters.
let non_shutdown_state = channel_state & (!MULTI_STATE_FLAGS);
} else {
// `keys_data` can be `None` if we had corrupted data.
let keys_data = keys_data.ok_or(DecodeError::InvalidValue)?;
- let holder_signer = keys_source.read_chan_signer(&keys_data)?;
+ let holder_signer = signer_provider.read_chan_signer(&keys_data)?;
(holder_signer.channel_keys_id(), holder_signer)
};
}
let chan_features = channel_type.as_ref().unwrap();
- if chan_features.supports_unknown_bits() || chan_features.requires_unknown_bits() {
+ if !chan_features.is_subset(our_supported_features) {
// If the channel was written by a new version and negotiated with features we don't
// understand yet, refuse to read it.
return Err(DecodeError::UnknownRequiredFeature);
}
- if channel_parameters.opt_anchors.is_some() {
- // Relax this check when ChannelTypeFeatures supports anchors.
- return Err(DecodeError::InvalidValue);
- }
-
let mut secp_ctx = Secp256k1::new();
- secp_ctx.seeded_randomize(&keys_source.get_secure_random_bytes());
+ secp_ctx.seeded_randomize(&entropy_source.get_secure_random_bytes());
// `user_id` used to be a single u64 value. In order to remain backwards
// compatible with versions prior to 0.0.113, the u128 is serialized as two
use hex;
use crate::ln::PaymentHash;
use crate::ln::channelmanager::{self, HTLCSource, PaymentId};
+ #[cfg(anchors)]
+ use crate::ln::channel::InitFeatures;
use crate::ln::channel::{Channel, InboundHTLCOutput, OutboundHTLCOutput, InboundHTLCState, OutboundHTLCState, HTLCCandidate, HTLCInitiator};
use crate::ln::channel::{MAX_FUNDING_SATOSHIS_NO_WUMBO, TOTAL_BITCOIN_SUPPLY_SATOSHIS, MIN_THEIR_CHAN_RESERVE_SATOSHIS};
use crate::ln::features::ChannelTypeFeatures;
use crate::ln::chan_utils::{htlc_success_tx_weight, htlc_timeout_tx_weight};
use crate::chain::BestBlock;
use crate::chain::chaininterface::{FeeEstimator, LowerBoundedFeeEstimator, ConfirmationTarget};
- use crate::chain::keysinterface::{BaseSign, InMemorySigner, Recipient, KeyMaterial, KeysInterface, EntropySource, NodeSigner, SignerProvider};
+ use crate::chain::keysinterface::{BaseSign, InMemorySigner, EntropySource, SignerProvider};
use crate::chain::transaction::OutPoint;
use crate::util::config::UserConfig;
use crate::util::enforcing_trait_impls::EnforcingSigner;
use crate::util::errors::APIError;
use crate::util::test_utils;
use crate::util::test_utils::OnGetShutdownScriptpubkey;
- use bitcoin::secp256k1::{Secp256k1, ecdsa::Signature, Scalar};
+ use bitcoin::secp256k1::{Secp256k1, ecdsa::Signature};
use bitcoin::secp256k1::ffi::Signature as FFISignature;
use bitcoin::secp256k1::{SecretKey,PublicKey};
- use bitcoin::secp256k1::ecdh::SharedSecret;
- use bitcoin::secp256k1::ecdsa::RecoverableSignature;
use bitcoin::hashes::sha256::Hash as Sha256;
use bitcoin::hashes::Hash;
use bitcoin::hash_types::WPubkeyHash;
- use bitcoin::bech32::u5;
use bitcoin::PackedLockTime;
use bitcoin::util::address::WitnessVersion;
use crate::prelude::*;
fn get_secure_random_bytes(&self) -> [u8; 32] { [0; 32] }
}
- impl NodeSigner for Keys {
- fn get_node_secret(&self, _recipient: Recipient) -> Result<SecretKey, ()> { panic!(); }
-
- fn get_node_id(&self, recipient: Recipient) -> Result<PublicKey, ()> {
- let secp_ctx = Secp256k1::signing_only();
- Ok(PublicKey::from_secret_key(&secp_ctx, &self.get_node_secret(recipient)?))
- }
-
- fn ecdh(&self, _recipient: Recipient, _other_key: &PublicKey, _tweak: Option<&Scalar>) -> Result<SharedSecret, ()> { panic!(); }
-
- fn get_inbound_payment_key_material(&self) -> KeyMaterial { panic!(); }
-
- fn sign_invoice(&self, _hrp_bytes: &[u8], _invoice_data: &[u5], _recipient: Recipient) -> Result<RecoverableSignature, ()> { panic!(); }
- }
-
impl SignerProvider for Keys {
type Signer = InMemorySigner;
}
}
- impl KeysInterface for Keys {}
-
#[cfg(not(feature = "grind_signatures"))]
fn public_from_secret_hex(secp_ctx: &Secp256k1<bitcoin::secp256k1::All>, hex: &str) -> PublicKey {
PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&hex::decode(hex).unwrap()[..]).unwrap())
#[test]
fn upfront_shutdown_script_incompatibility() {
- let features = channelmanager::provided_init_features().clear_shutdown_anysegwit();
+ let features = channelmanager::provided_init_features(&UserConfig::default()).clear_shutdown_anysegwit();
let non_v0_segwit_shutdown_script =
ShutdownScript::new_witness_program(WitnessVersion::V16, &[0, 40]).unwrap();
let secp_ctx = Secp256k1::new();
let node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
let config = UserConfig::default();
- match Channel::<EnforcingSigner>::new_outbound(&LowerBoundedFeeEstimator::new(&TestFeeEstimator { fee_est: 253 }), &&keys_provider, node_id, &features, 10000000, 100000, 42, &config, 0, 42) {
+ match Channel::<EnforcingSigner>::new_outbound(&LowerBoundedFeeEstimator::new(&TestFeeEstimator { fee_est: 253 }), &&keys_provider, &&keys_provider, node_id, &features, 10000000, 100000, 42, &config, 0, 42) {
Err(APIError::IncompatibleShutdownScript { script }) => {
assert_eq!(script.into_inner(), non_v0_segwit_shutdown_script.into_inner());
},
let node_a_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
let config = UserConfig::default();
- let node_a_chan = Channel::<EnforcingSigner>::new_outbound(&bounded_fee_estimator, &&keys_provider, node_a_node_id, &channelmanager::provided_init_features(), 10000000, 100000, 42, &config, 0, 42).unwrap();
+ let node_a_chan = Channel::<EnforcingSigner>::new_outbound(&bounded_fee_estimator, &&keys_provider, &&keys_provider, node_a_node_id, &channelmanager::provided_init_features(&config), 10000000, 100000, 42, &config, 0, 42).unwrap();
// Now change the fee so we can check that the fee in the open_channel message is the
// same as the old fee.
// Create Node A's channel pointing to Node B's pubkey
let node_b_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
let config = UserConfig::default();
- let mut node_a_chan = Channel::<EnforcingSigner>::new_outbound(&feeest, &&keys_provider, node_b_node_id, &channelmanager::provided_init_features(), 10000000, 100000, 42, &config, 0, 42).unwrap();
+ let mut node_a_chan = Channel::<EnforcingSigner>::new_outbound(&feeest, &&keys_provider, &&keys_provider, node_b_node_id, &channelmanager::provided_init_features(&config), 10000000, 100000, 42, &config, 0, 42).unwrap();
// Create Node B's channel by receiving Node A's open_channel message
// Make sure A's dust limit is as we expect.
let open_channel_msg = node_a_chan.get_open_channel(genesis_block(network).header.block_hash());
let node_b_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[7; 32]).unwrap());
- let mut node_b_chan = Channel::<EnforcingSigner>::new_from_req(&feeest, &&keys_provider, node_b_node_id, &channelmanager::provided_init_features(), &open_channel_msg, 7, &config, 0, &&logger, 42).unwrap();
+ let mut node_b_chan = Channel::<EnforcingSigner>::new_from_req(&feeest, &&keys_provider, &&keys_provider, node_b_node_id, &channelmanager::provided_channel_type_features(&config), &channelmanager::provided_init_features(&config), &open_channel_msg, 7, &config, 0, &&logger, 42).unwrap();
// Node B --> Node A: accept channel, explicitly setting B's dust limit.
let mut accept_channel_msg = node_b_chan.accept_inbound_channel(0);
accept_channel_msg.dust_limit_satoshis = 546;
- node_a_chan.accept_channel(&accept_channel_msg, &config.channel_handshake_limits, &channelmanager::provided_init_features()).unwrap();
+ node_a_chan.accept_channel(&accept_channel_msg, &config.channel_handshake_limits, &channelmanager::provided_init_features(&config)).unwrap();
node_a_chan.holder_dust_limit_satoshis = 1560;
// Put some inbound and outbound HTLCs in A's channel.
let node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
let config = UserConfig::default();
- let mut chan = Channel::<EnforcingSigner>::new_outbound(&fee_est, &&keys_provider, node_id, &channelmanager::provided_init_features(), 10000000, 100000, 42, &config, 0, 42).unwrap();
+ let mut chan = Channel::<EnforcingSigner>::new_outbound(&fee_est, &&keys_provider, &&keys_provider, node_id, &channelmanager::provided_init_features(&config), 10000000, 100000, 42, &config, 0, 42).unwrap();
let commitment_tx_fee_0_htlcs = Channel::<EnforcingSigner>::commit_tx_fee_msat(chan.feerate_per_kw, 0, chan.opt_anchors());
let commitment_tx_fee_1_htlc = Channel::<EnforcingSigner>::commit_tx_fee_msat(chan.feerate_per_kw, 1, chan.opt_anchors());
// Create Node A's channel pointing to Node B's pubkey
let node_b_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
let config = UserConfig::default();
- let mut node_a_chan = Channel::<EnforcingSigner>::new_outbound(&feeest, &&keys_provider, node_b_node_id, &channelmanager::provided_init_features(), 10000000, 100000, 42, &config, 0, 42).unwrap();
+ let mut node_a_chan = Channel::<EnforcingSigner>::new_outbound(&feeest, &&keys_provider, &&keys_provider, node_b_node_id, &channelmanager::provided_init_features(&config), 10000000, 100000, 42, &config, 0, 42).unwrap();
// Create Node B's channel by receiving Node A's open_channel message
let open_channel_msg = node_a_chan.get_open_channel(chain_hash);
let node_b_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[7; 32]).unwrap());
- let mut node_b_chan = Channel::<EnforcingSigner>::new_from_req(&feeest, &&keys_provider, node_b_node_id, &channelmanager::provided_init_features(), &open_channel_msg, 7, &config, 0, &&logger, 42).unwrap();
+ let mut node_b_chan = Channel::<EnforcingSigner>::new_from_req(&feeest, &&keys_provider, &&keys_provider, node_b_node_id, &channelmanager::provided_channel_type_features(&config), &channelmanager::provided_init_features(&config), &open_channel_msg, 7, &config, 0, &&logger, 42).unwrap();
// Node B --> Node A: accept channel
let accept_channel_msg = node_b_chan.accept_inbound_channel(0);
- node_a_chan.accept_channel(&accept_channel_msg, &config.channel_handshake_limits, &channelmanager::provided_init_features()).unwrap();
+ node_a_chan.accept_channel(&accept_channel_msg, &config.channel_handshake_limits, &channelmanager::provided_init_features(&config)).unwrap();
// Node A --> Node B: funding created
let output_script = node_a_chan.get_funding_redeemscript();
// Test that `new_outbound` creates a channel with the correct value for
// `holder_max_htlc_value_in_flight_msat`, when configured with a valid percentage value,
// which is set to the lower bound + 1 (2%) of the `channel_value`.
- let chan_1 = Channel::<EnforcingSigner>::new_outbound(&feeest, &&keys_provider, outbound_node_id, &channelmanager::provided_init_features(), 10000000, 100000, 42, &config_2_percent, 0, 42).unwrap();
+ let chan_1 = Channel::<EnforcingSigner>::new_outbound(&feeest, &&keys_provider, &&keys_provider, outbound_node_id, &channelmanager::provided_init_features(&config_2_percent), 10000000, 100000, 42, &config_2_percent, 0, 42).unwrap();
let chan_1_value_msat = chan_1.channel_value_satoshis * 1000;
assert_eq!(chan_1.holder_max_htlc_value_in_flight_msat, (chan_1_value_msat as f64 * 0.02) as u64);
// Test with the upper bound - 1 of valid values (99%).
- let chan_2 = Channel::<EnforcingSigner>::new_outbound(&feeest, &&keys_provider, outbound_node_id, &channelmanager::provided_init_features(), 10000000, 100000, 42, &config_99_percent, 0, 42).unwrap();
+ let chan_2 = Channel::<EnforcingSigner>::new_outbound(&feeest, &&keys_provider, &&keys_provider, outbound_node_id, &channelmanager::provided_init_features(&config_99_percent), 10000000, 100000, 42, &config_99_percent, 0, 42).unwrap();
let chan_2_value_msat = chan_2.channel_value_satoshis * 1000;
assert_eq!(chan_2.holder_max_htlc_value_in_flight_msat, (chan_2_value_msat as f64 * 0.99) as u64);
// Test that `new_from_req` creates a channel with the correct value for
// `holder_max_htlc_value_in_flight_msat`, when configured with a valid percentage value,
// which is set to the lower bound - 1 (2%) of the `channel_value`.
- let chan_3 = Channel::<EnforcingSigner>::new_from_req(&feeest, &&keys_provider, inbound_node_id, &channelmanager::provided_init_features(), &chan_1_open_channel_msg, 7, &config_2_percent, 0, &&logger, 42).unwrap();
+ let chan_3 = Channel::<EnforcingSigner>::new_from_req(&feeest, &&keys_provider, &&keys_provider, inbound_node_id, &channelmanager::provided_channel_type_features(&config_2_percent), &channelmanager::provided_init_features(&config_2_percent), &chan_1_open_channel_msg, 7, &config_2_percent, 0, &&logger, 42).unwrap();
let chan_3_value_msat = chan_3.channel_value_satoshis * 1000;
assert_eq!(chan_3.holder_max_htlc_value_in_flight_msat, (chan_3_value_msat as f64 * 0.02) as u64);
// Test with the upper bound - 1 of valid values (99%).
- let chan_4 = Channel::<EnforcingSigner>::new_from_req(&feeest, &&keys_provider, inbound_node_id, &channelmanager::provided_init_features(), &chan_1_open_channel_msg, 7, &config_99_percent, 0, &&logger, 42).unwrap();
+ let chan_4 = Channel::<EnforcingSigner>::new_from_req(&feeest, &&keys_provider, &&keys_provider, inbound_node_id, &channelmanager::provided_channel_type_features(&config_99_percent), &channelmanager::provided_init_features(&config_99_percent), &chan_1_open_channel_msg, 7, &config_99_percent, 0, &&logger, 42).unwrap();
let chan_4_value_msat = chan_4.channel_value_satoshis * 1000;
assert_eq!(chan_4.holder_max_htlc_value_in_flight_msat, (chan_4_value_msat as f64 * 0.99) as u64);
// Test that `new_outbound` uses the lower bound of the configurable percentage values (1%)
// if `max_inbound_htlc_value_in_flight_percent_of_channel` is set to a value less than 1.
- let chan_5 = Channel::<EnforcingSigner>::new_outbound(&feeest, &&keys_provider, outbound_node_id, &channelmanager::provided_init_features(), 10000000, 100000, 42, &config_0_percent, 0, 42).unwrap();
+ let chan_5 = Channel::<EnforcingSigner>::new_outbound(&feeest, &&keys_provider, &&keys_provider, outbound_node_id, &channelmanager::provided_init_features(&config_0_percent), 10000000, 100000, 42, &config_0_percent, 0, 42).unwrap();
let chan_5_value_msat = chan_5.channel_value_satoshis * 1000;
assert_eq!(chan_5.holder_max_htlc_value_in_flight_msat, (chan_5_value_msat as f64 * 0.01) as u64);
// Test that `new_outbound` uses the upper bound of the configurable percentage values
// (100%) if `max_inbound_htlc_value_in_flight_percent_of_channel` is set to a larger value
// than 100.
- let chan_6 = Channel::<EnforcingSigner>::new_outbound(&feeest, &&keys_provider, outbound_node_id, &channelmanager::provided_init_features(), 10000000, 100000, 42, &config_101_percent, 0, 42).unwrap();
+ let chan_6 = Channel::<EnforcingSigner>::new_outbound(&feeest, &&keys_provider, &&keys_provider, outbound_node_id, &channelmanager::provided_init_features(&config_101_percent), 10000000, 100000, 42, &config_101_percent, 0, 42).unwrap();
let chan_6_value_msat = chan_6.channel_value_satoshis * 1000;
assert_eq!(chan_6.holder_max_htlc_value_in_flight_msat, chan_6_value_msat);
// Test that `new_from_req` uses the lower bound of the configurable percentage values (1%)
// if `max_inbound_htlc_value_in_flight_percent_of_channel` is set to a value less than 1.
- let chan_7 = Channel::<EnforcingSigner>::new_from_req(&feeest, &&keys_provider, inbound_node_id, &channelmanager::provided_init_features(), &chan_1_open_channel_msg, 7, &config_0_percent, 0, &&logger, 42).unwrap();
+ let chan_7 = Channel::<EnforcingSigner>::new_from_req(&feeest, &&keys_provider, &&keys_provider, inbound_node_id, &channelmanager::provided_channel_type_features(&config_0_percent), &channelmanager::provided_init_features(&config_0_percent), &chan_1_open_channel_msg, 7, &config_0_percent, 0, &&logger, 42).unwrap();
let chan_7_value_msat = chan_7.channel_value_satoshis * 1000;
assert_eq!(chan_7.holder_max_htlc_value_in_flight_msat, (chan_7_value_msat as f64 * 0.01) as u64);
// Test that `new_from_req` uses the upper bound of the configurable percentage values
// (100%) if `max_inbound_htlc_value_in_flight_percent_of_channel` is set to a larger value
// than 100.
- let chan_8 = Channel::<EnforcingSigner>::new_from_req(&feeest, &&keys_provider, inbound_node_id, &channelmanager::provided_init_features(), &chan_1_open_channel_msg, 7, &config_101_percent, 0, &&logger, 42).unwrap();
+ let chan_8 = Channel::<EnforcingSigner>::new_from_req(&feeest, &&keys_provider, &&keys_provider, inbound_node_id, &channelmanager::provided_channel_type_features(&config_101_percent), &channelmanager::provided_init_features(&config_101_percent), &chan_1_open_channel_msg, 7, &config_101_percent, 0, &&logger, 42).unwrap();
let chan_8_value_msat = chan_8.channel_value_satoshis * 1000;
assert_eq!(chan_8.holder_max_htlc_value_in_flight_msat, chan_8_value_msat);
}
let mut outbound_node_config = UserConfig::default();
outbound_node_config.channel_handshake_config.their_channel_reserve_proportional_millionths = (outbound_selected_channel_reserve_perc * 1_000_000.0) as u32;
- let chan = Channel::<EnforcingSigner>::new_outbound(&&fee_est, &&keys_provider, outbound_node_id, &channelmanager::provided_init_features(), channel_value_satoshis, 100_000, 42, &outbound_node_config, 0, 42).unwrap();
+ let chan = Channel::<EnforcingSigner>::new_outbound(&&fee_est, &&keys_provider, &&keys_provider, outbound_node_id, &channelmanager::provided_init_features(&outbound_node_config), channel_value_satoshis, 100_000, 42, &outbound_node_config, 0, 42).unwrap();
let expected_outbound_selected_chan_reserve = cmp::max(MIN_THEIR_CHAN_RESERVE_SATOSHIS, (chan.channel_value_satoshis as f64 * outbound_selected_channel_reserve_perc) as u64);
assert_eq!(chan.holder_selected_channel_reserve_satoshis, expected_outbound_selected_chan_reserve);
inbound_node_config.channel_handshake_config.their_channel_reserve_proportional_millionths = (inbound_selected_channel_reserve_perc * 1_000_000.0) as u32;
if outbound_selected_channel_reserve_perc + inbound_selected_channel_reserve_perc < 1.0 {
- let chan_inbound_node = Channel::<EnforcingSigner>::new_from_req(&&fee_est, &&keys_provider, inbound_node_id, &channelmanager::provided_init_features(), &chan_open_channel_msg, 7, &inbound_node_config, 0, &&logger, 42).unwrap();
+ let chan_inbound_node = Channel::<EnforcingSigner>::new_from_req(&&fee_est, &&keys_provider, &&keys_provider, inbound_node_id, &channelmanager::provided_channel_type_features(&inbound_node_config), &channelmanager::provided_init_features(&outbound_node_config), &chan_open_channel_msg, 7, &inbound_node_config, 0, &&logger, 42).unwrap();
let expected_inbound_selected_chan_reserve = cmp::max(MIN_THEIR_CHAN_RESERVE_SATOSHIS, (chan.channel_value_satoshis as f64 * inbound_selected_channel_reserve_perc) as u64);
assert_eq!(chan_inbound_node.counterparty_selected_channel_reserve_satoshis.unwrap(), expected_outbound_selected_chan_reserve);
} else {
// Channel Negotiations failed
- let result = Channel::<EnforcingSigner>::new_from_req(&&fee_est, &&keys_provider, inbound_node_id, &channelmanager::provided_init_features(), &chan_open_channel_msg, 7, &inbound_node_config, 0, &&logger, 42);
+ let result = Channel::<EnforcingSigner>::new_from_req(&&fee_est, &&keys_provider, &&keys_provider, inbound_node_id, &channelmanager::provided_channel_type_features(&inbound_node_config), &channelmanager::provided_init_features(&outbound_node_config), &chan_open_channel_msg, 7, &inbound_node_config, 0, &&logger, 42);
assert!(result.is_err());
}
}
// Create a channel.
let node_b_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
let config = UserConfig::default();
- let mut node_a_chan = Channel::<EnforcingSigner>::new_outbound(&feeest, &&keys_provider, node_b_node_id, &channelmanager::provided_init_features(), 10000000, 100000, 42, &config, 0, 42).unwrap();
+ let mut node_a_chan = Channel::<EnforcingSigner>::new_outbound(&feeest, &&keys_provider, &&keys_provider, node_b_node_id, &channelmanager::provided_init_features(&config), 10000000, 100000, 42, &config, 0, 42).unwrap();
assert!(node_a_chan.counterparty_forwarding_info.is_none());
assert_eq!(node_a_chan.holder_htlc_minimum_msat, 1); // the default
assert!(node_a_chan.counterparty_forwarding_info().is_none());
let mut signer = InMemorySigner::new(
&secp_ctx,
- SecretKey::from_slice(&hex::decode("4242424242424242424242424242424242424242424242424242424242424242").unwrap()[..]).unwrap(),
SecretKey::from_slice(&hex::decode("30ff4956bbdd3222d44cc5e8a1261dab1e07957bdac5ae88fe3261ef321f3749").unwrap()[..]).unwrap(),
SecretKey::from_slice(&hex::decode("0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap()[..]).unwrap(),
SecretKey::from_slice(&hex::decode("1111111111111111111111111111111111111111111111111111111111111111").unwrap()[..]).unwrap(),
let counterparty_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
let mut config = UserConfig::default();
config.channel_handshake_config.announced_channel = false;
- let mut chan = Channel::<InMemorySigner>::new_outbound(&LowerBoundedFeeEstimator::new(&feeest), &&keys_provider, counterparty_node_id, &channelmanager::provided_init_features(), 10_000_000, 100000, 42, &config, 0, 42).unwrap(); // Nothing uses their network key in this test
+ let mut chan = Channel::<InMemorySigner>::new_outbound(&LowerBoundedFeeEstimator::new(&feeest), &&keys_provider, &&keys_provider, counterparty_node_id, &channelmanager::provided_init_features(&config), 10_000_000, 100000, 42, &config, 0, 42).unwrap(); // Nothing uses their network key in this test
chan.holder_dust_limit_satoshis = 546;
chan.counterparty_selected_channel_reserve_satoshis = Some(0); // Filled in in accept_channel
let node_b_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
let config = UserConfig::default();
- let node_a_chan = Channel::<EnforcingSigner>::new_outbound(&feeest, &&keys_provider,
- node_b_node_id, &channelmanager::provided_init_features(), 10000000, 100000, 42, &config, 0, 42).unwrap();
+ let node_a_chan = Channel::<EnforcingSigner>::new_outbound(&feeest, &&keys_provider, &&keys_provider,
+ node_b_node_id, &channelmanager::provided_init_features(&config), 10000000, 100000, 42, &config, 0, 42).unwrap();
let mut channel_type_features = ChannelTypeFeatures::only_static_remote_key();
channel_type_features.set_zero_conf_required();
let mut open_channel_msg = node_a_chan.get_open_channel(genesis_block(network).header.block_hash());
open_channel_msg.channel_type = Some(channel_type_features);
let node_b_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[7; 32]).unwrap());
- let res = Channel::<EnforcingSigner>::new_from_req(&feeest, &&keys_provider,
- node_b_node_id, &channelmanager::provided_init_features(), &open_channel_msg, 7, &config, 0, &&logger, 42);
+ let res = Channel::<EnforcingSigner>::new_from_req(&feeest, &&keys_provider, &&keys_provider,
+ node_b_node_id, &channelmanager::provided_channel_type_features(&config),
+ &channelmanager::provided_init_features(&config), &open_channel_msg, 7, &config, 0, &&logger, 42);
assert!(res.is_ok());
}
+
+ #[cfg(anchors)]
+ #[test]
+ fn test_supports_anchors_zero_htlc_tx_fee() {
+ // Tests that if both sides support and negotiate `anchors_zero_fee_htlc_tx`, it is the
+ // resulting `channel_type`.
+ let secp_ctx = Secp256k1::new();
+ let fee_estimator = LowerBoundedFeeEstimator::new(&TestFeeEstimator{fee_est: 15000});
+ let network = Network::Testnet;
+ let keys_provider = test_utils::TestKeysInterface::new(&[42; 32], network);
+ let logger = test_utils::TestLogger::new();
+
+ let node_id_a = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[1; 32]).unwrap());
+ let node_id_b = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[2; 32]).unwrap());
+
+ let mut config = UserConfig::default();
+ config.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx = true;
+
+ // It is not enough for just the initiator to signal `option_anchors_zero_fee_htlc_tx`, both
+ // need to signal it.
+ let channel_a = Channel::<EnforcingSigner>::new_outbound(
+ &fee_estimator, &&keys_provider, &&keys_provider, node_id_b,
+ &channelmanager::provided_init_features(&UserConfig::default()), 10000000, 100000, 42,
+ &config, 0, 42
+ ).unwrap();
+ assert!(!channel_a.channel_type.supports_anchors_zero_fee_htlc_tx());
+
+ let mut expected_channel_type = ChannelTypeFeatures::empty();
+ expected_channel_type.set_static_remote_key_required();
+ expected_channel_type.set_anchors_zero_fee_htlc_tx_required();
+
+ let channel_a = Channel::<EnforcingSigner>::new_outbound(
+ &fee_estimator, &&keys_provider, &&keys_provider, node_id_b,
+ &channelmanager::provided_init_features(&config), 10000000, 100000, 42, &config, 0, 42
+ ).unwrap();
+
+ let open_channel_msg = channel_a.get_open_channel(genesis_block(network).header.block_hash());
+ let channel_b = Channel::<EnforcingSigner>::new_from_req(
+ &fee_estimator, &&keys_provider, &&keys_provider, node_id_a,
+ &channelmanager::provided_channel_type_features(&config), &channelmanager::provided_init_features(&config),
+ &open_channel_msg, 7, &config, 0, &&logger, 42
+ ).unwrap();
+
+ assert_eq!(channel_a.channel_type, expected_channel_type);
+ assert_eq!(channel_b.channel_type, expected_channel_type);
+ }
+
+ #[cfg(anchors)]
+ #[test]
+ fn test_rejects_implicit_simple_anchors() {
+ // Tests that if `option_anchors` is being negotiated implicitly through the intersection of
+ // each side's `InitFeatures`, it is rejected.
+ let secp_ctx = Secp256k1::new();
+ let fee_estimator = LowerBoundedFeeEstimator::new(&TestFeeEstimator{fee_est: 15000});
+ let network = Network::Testnet;
+ let keys_provider = test_utils::TestKeysInterface::new(&[42; 32], network);
+ let logger = test_utils::TestLogger::new();
+
+ let node_id_a = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[1; 32]).unwrap());
+ let node_id_b = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[2; 32]).unwrap());
+
+ let config = UserConfig::default();
+
+ // See feature bit assignments: https://github.com/lightning/bolts/blob/master/09-features.md
+ let static_remote_key_required: u64 = 1 << 12;
+ let simple_anchors_required: u64 = 1 << 20;
+ let raw_init_features = static_remote_key_required | simple_anchors_required;
+ let init_features_with_simple_anchors = InitFeatures::from_le_bytes(raw_init_features.to_le_bytes().to_vec());
+
+ let channel_a = Channel::<EnforcingSigner>::new_outbound(
+ &fee_estimator, &&keys_provider, &&keys_provider, node_id_b,
+ &channelmanager::provided_init_features(&config), 10000000, 100000, 42, &config, 0, 42
+ ).unwrap();
+
+ // Set `channel_type` to `None` to force the implicit feature negotiation.
+ let mut open_channel_msg = channel_a.get_open_channel(genesis_block(network).header.block_hash());
+ open_channel_msg.channel_type = None;
+
+ // Since A supports both `static_remote_key` and `option_anchors`, but B only accepts
+ // `static_remote_key`, it will fail the channel.
+ let channel_b = Channel::<EnforcingSigner>::new_from_req(
+ &fee_estimator, &&keys_provider, &&keys_provider, node_id_a,
+ &channelmanager::provided_channel_type_features(&config), &init_features_with_simple_anchors,
+ &open_channel_msg, 7, &config, 0, &&logger, 42
+ );
+ assert!(channel_b.is_err());
+ }
+
+ #[cfg(anchors)]
+ #[test]
+ fn test_rejects_simple_anchors_channel_type() {
+ // Tests that if `option_anchors` is being negotiated through the `channel_type` feature,
+ // it is rejected.
+ let secp_ctx = Secp256k1::new();
+ let fee_estimator = LowerBoundedFeeEstimator::new(&TestFeeEstimator{fee_est: 15000});
+ let network = Network::Testnet;
+ let keys_provider = test_utils::TestKeysInterface::new(&[42; 32], network);
+ let logger = test_utils::TestLogger::new();
+
+ let node_id_a = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[1; 32]).unwrap());
+ let node_id_b = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[2; 32]).unwrap());
+
+ let config = UserConfig::default();
+
+ // See feature bit assignments: https://github.com/lightning/bolts/blob/master/09-features.md
+ let static_remote_key_required: u64 = 1 << 12;
+ let simple_anchors_required: u64 = 1 << 20;
+ let simple_anchors_raw_features = static_remote_key_required | simple_anchors_required;
+ let simple_anchors_init = InitFeatures::from_le_bytes(simple_anchors_raw_features.to_le_bytes().to_vec());
+ let simple_anchors_channel_type = ChannelTypeFeatures::from_le_bytes(simple_anchors_raw_features.to_le_bytes().to_vec());
+ assert!(simple_anchors_init.requires_unknown_bits());
+ assert!(simple_anchors_channel_type.requires_unknown_bits());
+
+ // First, we'll try to open a channel between A and B where A requests a channel type for
+ // the original `option_anchors` feature (non zero fee htlc tx). This should be rejected by
+ // B as it's not supported by LDK.
+ let channel_a = Channel::<EnforcingSigner>::new_outbound(
+ &fee_estimator, &&keys_provider, &&keys_provider, node_id_b,
+ &channelmanager::provided_init_features(&config), 10000000, 100000, 42, &config, 0, 42
+ ).unwrap();
+
+ let mut open_channel_msg = channel_a.get_open_channel(genesis_block(network).header.block_hash());
+ open_channel_msg.channel_type = Some(simple_anchors_channel_type.clone());
+
+ let res = Channel::<EnforcingSigner>::new_from_req(
+ &fee_estimator, &&keys_provider, &&keys_provider, node_id_a,
+ &channelmanager::provided_channel_type_features(&config), &simple_anchors_init,
+ &open_channel_msg, 7, &config, 0, &&logger, 42
+ );
+ assert!(res.is_err());
+
+ // Then, we'll try to open another channel where A requests a channel type for
+ // `anchors_zero_fee_htlc_tx`. B is malicious and tries to downgrade the channel type to the
+ // original `option_anchors` feature, which should be rejected by A as it's not supported by
+ // LDK.
+ let mut channel_a = Channel::<EnforcingSigner>::new_outbound(
+ &fee_estimator, &&keys_provider, &&keys_provider, node_id_b, &simple_anchors_init,
+ 10000000, 100000, 42, &config, 0, 42
+ ).unwrap();
+
+ let open_channel_msg = channel_a.get_open_channel(genesis_block(network).header.block_hash());
+
+ let channel_b = Channel::<EnforcingSigner>::new_from_req(
+ &fee_estimator, &&keys_provider, &&keys_provider, node_id_a,
+ &channelmanager::provided_channel_type_features(&config), &channelmanager::provided_init_features(&config),
+ &open_channel_msg, 7, &config, 0, &&logger, 42
+ ).unwrap();
+
+ let mut accept_channel_msg = channel_b.get_accept_channel_message();
+ accept_channel_msg.channel_type = Some(simple_anchors_channel_type.clone());
+
+ let res = channel_a.accept_channel(
+ &accept_channel_msg, &config.channel_handshake_limits, &simple_anchors_init
+ );
+ assert!(res.is_err());
+ }
}