use util::ser::{Readable, ReadableArgs, Writeable, Writer, VecWriter};
use util::logger::Logger;
use util::errors::APIError;
-use util::config::{UserConfig, ChannelConfig, ChannelHandshakeConfig, ChannelHandshakeLimits};
+use util::config::{UserConfig, LegacyChannelConfig, ChannelHandshakeConfig, ChannelHandshakeLimits};
use util::scid_utils::scid_from_parts;
use io;
// Counterparty designates channel data owned by the another channel participant entity.
pub(super) struct Channel<Signer: Sign> {
#[cfg(any(test, feature = "_test_utils"))]
- pub(crate) config: ChannelConfig,
+ pub(crate) config: LegacyChannelConfig,
#[cfg(not(any(test, feature = "_test_utils")))]
- config: ChannelConfig,
+ config: LegacyChannelConfig,
inbound_handshake_limits_override: Option<ChannelHandshakeLimits>,
// 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`
let mut ret = ChannelTypeFeatures::only_static_remote_key();
- if !config.channel_options.announced_channel && config.own_channel_config.negotiate_scid_privacy {
+ if !config.own_channel_config.announced_channel && config.own_channel_config.negotiate_scid_privacy {
ret.set_scid_privacy_required();
}
ret
let mut secp_ctx = Secp256k1::new();
secp_ctx.seeded_randomize(&keys_provider.get_secure_random_bytes());
- let shutdown_scriptpubkey = if config.channel_options.commit_upfront_shutdown_pubkey {
+ let shutdown_scriptpubkey = if config.own_channel_config.commit_upfront_shutdown_pubkey {
Some(keys_provider.get_shutdown_scriptpubkey())
} else { None };
Ok(Channel {
user_id,
- config: config.channel_options.clone(),
+
+ config: LegacyChannelConfig {
+ mutable: config.channel_options.clone(),
+ announced_channel: config.own_channel_config.announced_channel,
+ commit_upfront_shutdown_pubkey: config.own_channel_config.commit_upfront_shutdown_pubkey,
+ },
+
inbound_handshake_limits_override: Some(config.peer_channel_config_limits.clone()),
channel_id: keys_provider.get_secure_random_bytes(),
if channel_type.supports_any_optional_bits() {
return Err(ChannelError::Close("Channel Type field contained optional bits - this is not allowed".to_owned()));
}
- // We currently only allow two channel types, so write it all out here - we allow
- // `only_static_remote_key` in all contexts, and further allow
- // `static_remote_key|scid_privacy` if the channel is not publicly announced.
- let mut allowed_type = ChannelTypeFeatures::only_static_remote_key();
- if *channel_type != allowed_type {
- allowed_type.set_scid_privacy_required();
- if *channel_type != allowed_type {
+
+ if channel_type.requires_unknown_bits() {
+ return Err(ChannelError::Close("Channel Type field contains unknown bits".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 announced_channel {
+
+ 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()));
}
}
delayed_payment_basepoint: msg.delayed_payment_basepoint,
htlc_basepoint: msg.htlc_basepoint
};
- let mut local_config = (*config).channel_options.clone();
if config.own_channel_config.our_to_self_delay < BREAKDOWN_TIMEOUT {
return Err(ChannelError::Close(format!("Configured with an unreasonable our_to_self_delay ({}) putting user funds at risks. It must be greater than {}", config.own_channel_config.our_to_self_delay, BREAKDOWN_TIMEOUT)));
// Convert things into internal flags and prep our state:
if config.peer_channel_config_limits.force_announced_channel_preference {
- if local_config.announced_channel != announced_channel {
+ if config.own_channel_config.announced_channel != announced_channel {
return Err(ChannelError::Close("Peer tried to open channel but their announcement preference is different from ours".to_owned()));
}
}
- // we either accept their preference or the preferences match
- local_config.announced_channel = announced_channel;
let holder_selected_channel_reserve_satoshis = Channel::<Signer>::get_holder_selected_channel_reserve_satoshis(msg.funding_satoshis);
if holder_selected_channel_reserve_satoshis < MIN_CHAN_DUST_LIMIT_SATOSHIS {
}
} else { None };
- let shutdown_scriptpubkey = if config.channel_options.commit_upfront_shutdown_pubkey {
+ let shutdown_scriptpubkey = if config.own_channel_config.commit_upfront_shutdown_pubkey {
Some(keys_provider.get_shutdown_scriptpubkey())
} else { None };
let chan = Channel {
user_id,
- config: local_config,
+
+ config: LegacyChannelConfig {
+ mutable: config.channel_options.clone(),
+ announced_channel,
+ commit_upfront_shutdown_pubkey: config.own_channel_config.commit_upfront_shutdown_pubkey,
+ },
+
inbound_handshake_limits_override: None,
channel_id: msg.temporary_channel_id,
// We always add force_close_avoidance_max_fee_satoshis to our normal
// feerate-calculated fee, but allow the max to be overridden if we're using a
// target feerate-calculated fee.
- cmp::max(normal_feerate as u64 * tx_weight / 1000 + self.config.force_close_avoidance_max_fee_satoshis,
+ cmp::max(normal_feerate as u64 * tx_weight / 1000 + self.config.mutable.force_close_avoidance_max_fee_satoshis,
proposed_max_feerate as u64 * tx_weight / 1000)
} else {
self.channel_value_satoshis - (self.value_to_self_msat + 999) / 1000
}
pub fn get_fee_proportional_millionths(&self) -> u32 {
- self.config.forwarding_fee_proportional_millionths
+ self.config.mutable.forwarding_fee_proportional_millionths
}
pub fn get_cltv_expiry_delta(&self) -> u16 {
- cmp::max(self.config.cltv_expiry_delta, MIN_CLTV_EXPIRY_DELTA)
+ cmp::max(self.config.mutable.cltv_expiry_delta, MIN_CLTV_EXPIRY_DELTA)
}
pub fn get_max_dust_htlc_exposure_msat(&self) -> u64 {
- self.config.max_dust_htlc_exposure_msat
+ self.config.mutable.max_dust_htlc_exposure_msat
}
pub fn get_feerate(&self) -> u32 {
/// Gets the fee we'd want to charge for adding an HTLC output to this Channel
/// Allowed in any state (including after shutdown)
pub fn get_outbound_forwarding_fee_base_msat(&self) -> u32 {
- self.config.forwarding_fee_base_msat
+ self.config.mutable.forwarding_fee_base_msat
}
/// Returns true if we've ever received a message from the remote end for this Channel
} else if non_shutdown_state == (ChannelState::FundingSent as u32 | ChannelState::OurChannelReady as u32) {
// We got a reorg but not enough to trigger a force close, just ignore.
false
- } else if self.channel_state < ChannelState::ChannelFunded as u32 {
- panic!("Started confirming a channel in a state pre-FundingSent?: {}", self.channel_state);
} else {
+ if self.channel_state < ChannelState::ChannelFunded as u32 {
+ // We should never see a funding transaction on-chain until we've received
+ // funding_signed (if we're an outbound channel), or seen funding_generated (if we're
+ // an inbound channel - before that we have no known funding TXID). The fuzzer,
+ // however, may do this and we shouldn't treat it as a bug.
+ #[cfg(not(fuzzing))]
+ panic!("Started confirming a channel in a state pre-FundingSent: {}.\n\
+ Do NOT broadcast a funding transaction manually - let LDK do it for you!",
+ self.channel_state);
+ }
// We got a reorg but not enough to trigger a force close, just ignore.
false
};
let user_id = Readable::read(reader)?;
- let mut config = Some(ChannelConfig::default());
+ let mut config = Some(LegacyChannelConfig::default());
if ver == 1 {
// Read the old serialization of the ChannelConfig from version 0.0.98.
- config.as_mut().unwrap().forwarding_fee_proportional_millionths = Readable::read(reader)?;
- config.as_mut().unwrap().cltv_expiry_delta = Readable::read(reader)?;
+ config.as_mut().unwrap().mutable.forwarding_fee_proportional_millionths = Readable::read(reader)?;
+ config.as_mut().unwrap().mutable.cltv_expiry_delta = Readable::read(reader)?;
config.as_mut().unwrap().announced_channel = Readable::read(reader)?;
config.as_mut().unwrap().commit_upfront_shutdown_pubkey = Readable::read(reader)?;
} else {
use ln::channelmanager::{HTLCSource, PaymentId};
use ln::channel::{Channel, InboundHTLCOutput, OutboundHTLCOutput, InboundHTLCState, OutboundHTLCState, HTLCCandidate, HTLCInitiator};
use ln::channel::{MAX_FUNDING_SATOSHIS_NO_WUMBO, TOTAL_BITCOIN_SUPPLY_SATOSHIS};
- use ln::features::InitFeatures;
+ use ln::features::{InitFeatures, ChannelTypeFeatures};
use ln::msgs::{ChannelUpdate, DataLossProtect, DecodeError, OptionalField, UnsignedChannelUpdate};
use ln::script::ShutdownScript;
use ln::chan_utils;
let counterparty_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
let mut config = UserConfig::default();
- config.channel_options.announced_channel = false;
+ config.own_channel_config.announced_channel = false;
let mut chan = Channel::<InMemorySigner>::new_outbound(&&feeest, &&keys_provider, counterparty_node_id, &InitFeatures::known(), 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
assert_eq!(chan_utils::derive_private_revocation_key(&secp_ctx, &per_commitment_secret, &base_secret).unwrap(),
SecretKey::from_slice(&hex::decode("d09ffff62ddb2297ab000cc85bcb4283fdeb6aa052affbc9dddcf33b61078110").unwrap()[..]).unwrap());
}
+
+ #[test]
+ fn test_zero_conf_channel_type_support() {
+ let feeest = TestFeeEstimator{fee_est: 15000};
+ let secp_ctx = Secp256k1::new();
+ let seed = [42; 32];
+ let network = Network::Testnet;
+ let keys_provider = test_utils::TestKeysInterface::new(&seed, network);
+ let logger = test_utils::TestLogger::new();
+
+ 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, &InitFeatures::known(), 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, &InitFeatures::known(), &open_channel_msg, 7, &config, 0, &&logger, 42);
+ assert!(res.is_ok());
+ }
}