let keys = self.context.get_holder_pubkeys();
msgs::OpenChannel {
- chain_hash,
- temporary_channel_id: self.context.channel_id,
- funding_satoshis: self.context.channel_value_satoshis,
+ common_fields: msgs::CommonOpenChannelFields {
+ chain_hash,
+ temporary_channel_id: self.context.channel_id,
+ funding_satoshis: self.context.channel_value_satoshis,
+ dust_limit_satoshis: self.context.holder_dust_limit_satoshis,
+ max_htlc_value_in_flight_msat: self.context.holder_max_htlc_value_in_flight_msat,
+ htlc_minimum_msat: self.context.holder_htlc_minimum_msat,
+ commitment_feerate_sat_per_1000_weight: self.context.feerate_per_kw as u32,
+ to_self_delay: self.context.get_holder_selected_contest_delay(),
+ max_accepted_htlcs: self.context.holder_max_accepted_htlcs,
+ funding_pubkey: keys.funding_pubkey,
+ revocation_basepoint: keys.revocation_basepoint.to_public_key(),
+ payment_basepoint: keys.payment_point,
+ delayed_payment_basepoint: keys.delayed_payment_basepoint.to_public_key(),
+ htlc_basepoint: keys.htlc_basepoint.to_public_key(),
+ first_per_commitment_point,
+ channel_flags: if self.context.config.announced_channel {1} else {0},
+ shutdown_scriptpubkey: Some(match &self.context.shutdown_scriptpubkey {
+ Some(script) => script.clone().into_inner(),
+ None => Builder::new().into_script(),
+ }),
+ channel_type: Some(self.context.channel_type.clone()),
+ },
push_msat: self.context.channel_value_satoshis * 1000 - self.context.value_to_self_msat,
- dust_limit_satoshis: self.context.holder_dust_limit_satoshis,
- max_htlc_value_in_flight_msat: self.context.holder_max_htlc_value_in_flight_msat,
channel_reserve_satoshis: self.context.holder_selected_channel_reserve_satoshis,
- htlc_minimum_msat: self.context.holder_htlc_minimum_msat,
- feerate_per_kw: self.context.feerate_per_kw as u32,
- to_self_delay: self.context.get_holder_selected_contest_delay(),
- max_accepted_htlcs: self.context.holder_max_accepted_htlcs,
- funding_pubkey: keys.funding_pubkey,
- revocation_basepoint: keys.revocation_basepoint.to_public_key(),
- payment_point: keys.payment_point,
- delayed_payment_basepoint: keys.delayed_payment_basepoint.to_public_key(),
- htlc_basepoint: keys.htlc_basepoint.to_public_key(),
- first_per_commitment_point,
- channel_flags: if self.context.config.announced_channel {1} else {0},
- shutdown_scriptpubkey: Some(match &self.context.shutdown_scriptpubkey {
- Some(script) => script.clone().into_inner(),
- None => Builder::new().into_script(),
- }),
- channel_type: Some(self.context.channel_type.clone()),
}
}
msg: &msgs::OpenChannel, their_features: &InitFeatures,
our_supported_features: &ChannelTypeFeatures
) -> Result<ChannelTypeFeatures, ChannelError> {
- if let Some(channel_type) = &msg.channel_type {
+ if let Some(channel_type) = &msg.common_fields.channel_type {
if channel_type.supports_any_optional_bits() {
return Err(ChannelError::Close("Channel Type field contained optional bits - this is not allowed".to_owned()));
}
if !channel_type.is_subset(our_supported_features) {
return Err(ChannelError::Close("Channel Type contains unsupported features".to_owned()));
}
- let announced_channel = if (msg.channel_flags & 1) == 1 { true } else { false };
+ let announced_channel = if (msg.common_fields.channel_flags & 1) == 1 { true } else { false };
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()));
}
F::Target: FeeEstimator,
L::Target: Logger,
{
- let logger = WithContext::from(logger, Some(counterparty_node_id), Some(msg.temporary_channel_id));
- let announced_channel = if (msg.channel_flags & 1) == 1 { true } else { false };
+ let logger = WithContext::from(logger, Some(counterparty_node_id), Some(msg.common_fields.temporary_channel_id));
+ let announced_channel = if (msg.common_fields.channel_flags & 1) == 1 { true } else { false };
// First check the channel type is known, failing before we do anything else if we don't
// support this channel type.
let channel_type = channel_type_from_open_channel(msg, their_features, our_supported_features)?;
- 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 channel_keys_id = signer_provider.generate_channel_keys_id(true, msg.common_fields.funding_satoshis, user_id);
+ let holder_signer = signer_provider.derive_channel_signer(msg.common_fields.funding_satoshis, channel_keys_id);
let pubkeys = holder_signer.pubkeys().clone();
let counterparty_pubkeys = ChannelPublicKeys {
- funding_pubkey: msg.funding_pubkey,
- revocation_basepoint: RevocationBasepoint::from(msg.revocation_basepoint),
- payment_point: msg.payment_point,
- delayed_payment_basepoint: DelayedPaymentBasepoint::from(msg.delayed_payment_basepoint),
- htlc_basepoint: HtlcBasepoint::from(msg.htlc_basepoint)
+ funding_pubkey: msg.common_fields.funding_pubkey,
+ revocation_basepoint: RevocationBasepoint::from(msg.common_fields.revocation_basepoint),
+ payment_point: msg.common_fields.payment_basepoint,
+ delayed_payment_basepoint: DelayedPaymentBasepoint::from(msg.common_fields.delayed_payment_basepoint),
+ htlc_basepoint: HtlcBasepoint::from(msg.common_fields.htlc_basepoint)
};
if config.channel_handshake_config.our_to_self_delay < BREAKDOWN_TIMEOUT {
}
// Check sanity of message fields:
- if msg.funding_satoshis > config.channel_handshake_limits.max_funding_satoshis {
- return Err(ChannelError::Close(format!("Per our config, funding must be at most {}. It was {}", config.channel_handshake_limits.max_funding_satoshis, msg.funding_satoshis)));
+ if msg.common_fields.funding_satoshis > config.channel_handshake_limits.max_funding_satoshis {
+ return Err(ChannelError::Close(format!("Per our config, funding must be at most {}. It was {}", config.channel_handshake_limits.max_funding_satoshis, msg.common_fields.funding_satoshis)));
}
- if msg.funding_satoshis >= TOTAL_BITCOIN_SUPPLY_SATOSHIS {
- return Err(ChannelError::Close(format!("Funding must be smaller than the total bitcoin supply. It was {}", msg.funding_satoshis)));
+ if msg.common_fields.funding_satoshis >= TOTAL_BITCOIN_SUPPLY_SATOSHIS {
+ return Err(ChannelError::Close(format!("Funding must be smaller than the total bitcoin supply. It was {}", msg.common_fields.funding_satoshis)));
}
- if msg.channel_reserve_satoshis > msg.funding_satoshis {
- return Err(ChannelError::Close(format!("Bogus channel_reserve_satoshis ({}). Must be not greater than funding_satoshis: {}", msg.channel_reserve_satoshis, msg.funding_satoshis)));
+ if msg.channel_reserve_satoshis > msg.common_fields.funding_satoshis {
+ return Err(ChannelError::Close(format!("Bogus channel_reserve_satoshis ({}). Must be not greater than funding_satoshis: {}", msg.channel_reserve_satoshis, msg.common_fields.funding_satoshis)));
}
- let full_channel_value_msat = (msg.funding_satoshis - msg.channel_reserve_satoshis) * 1000;
+ let full_channel_value_msat = (msg.common_fields.funding_satoshis - msg.channel_reserve_satoshis) * 1000;
if msg.push_msat > full_channel_value_msat {
return Err(ChannelError::Close(format!("push_msat {} was larger than channel amount minus reserve ({})", msg.push_msat, full_channel_value_msat)));
}
- if msg.dust_limit_satoshis > msg.funding_satoshis {
- return Err(ChannelError::Close(format!("dust_limit_satoshis {} was larger than funding_satoshis {}. Peer never wants payout outputs?", msg.dust_limit_satoshis, msg.funding_satoshis)));
+ if msg.common_fields.dust_limit_satoshis > msg.common_fields.funding_satoshis {
+ return Err(ChannelError::Close(format!("dust_limit_satoshis {} was larger than funding_satoshis {}. Peer never wants payout outputs?", msg.common_fields.dust_limit_satoshis, msg.common_fields.funding_satoshis)));
}
- if msg.htlc_minimum_msat >= full_channel_value_msat {
- return Err(ChannelError::Close(format!("Minimum htlc value ({}) was larger than full channel value ({})", msg.htlc_minimum_msat, full_channel_value_msat)));
+ if msg.common_fields.htlc_minimum_msat >= full_channel_value_msat {
+ return Err(ChannelError::Close(format!("Minimum htlc value ({}) was larger than full channel value ({})", msg.common_fields.htlc_minimum_msat, full_channel_value_msat)));
}
- Channel::<SP>::check_remote_fee(&channel_type, fee_estimator, msg.feerate_per_kw, None, &&logger)?;
+ Channel::<SP>::check_remote_fee(&channel_type, fee_estimator, msg.common_fields.commitment_feerate_sat_per_1000_weight, None, &&logger)?;
let max_counterparty_selected_contest_delay = u16::min(config.channel_handshake_limits.their_to_self_delay, MAX_LOCAL_BREAKDOWN_TIMEOUT);
- if msg.to_self_delay > max_counterparty_selected_contest_delay {
- return Err(ChannelError::Close(format!("They wanted our payments to be delayed by a needlessly long period. Upper limit: {}. Actual: {}", max_counterparty_selected_contest_delay, msg.to_self_delay)));
+ if msg.common_fields.to_self_delay > max_counterparty_selected_contest_delay {
+ return Err(ChannelError::Close(format!("They wanted our payments to be delayed by a needlessly long period. Upper limit: {}. Actual: {}", max_counterparty_selected_contest_delay, msg.common_fields.to_self_delay)));
}
- if msg.max_accepted_htlcs < 1 {
+ if msg.common_fields.max_accepted_htlcs < 1 {
return Err(ChannelError::Close("0 max_accepted_htlcs makes for a useless channel".to_owned()));
}
- if msg.max_accepted_htlcs > MAX_HTLCS {
- return Err(ChannelError::Close(format!("max_accepted_htlcs was {}. It must not be larger than {}", msg.max_accepted_htlcs, MAX_HTLCS)));
+ if msg.common_fields.max_accepted_htlcs > MAX_HTLCS {
+ return Err(ChannelError::Close(format!("max_accepted_htlcs was {}. It must not be larger than {}", msg.common_fields.max_accepted_htlcs, MAX_HTLCS)));
}
// Now check against optional parameters as set by config...
- if msg.funding_satoshis < config.channel_handshake_limits.min_funding_satoshis {
- return Err(ChannelError::Close(format!("Funding satoshis ({}) is less than the user specified limit ({})", msg.funding_satoshis, config.channel_handshake_limits.min_funding_satoshis)));
+ if msg.common_fields.funding_satoshis < config.channel_handshake_limits.min_funding_satoshis {
+ return Err(ChannelError::Close(format!("Funding satoshis ({}) is less than the user specified limit ({})", msg.common_fields.funding_satoshis, config.channel_handshake_limits.min_funding_satoshis)));
}
- if msg.htlc_minimum_msat > config.channel_handshake_limits.max_htlc_minimum_msat {
- return Err(ChannelError::Close(format!("htlc_minimum_msat ({}) is higher than the user specified limit ({})", msg.htlc_minimum_msat, config.channel_handshake_limits.max_htlc_minimum_msat)));
+ if msg.common_fields.htlc_minimum_msat > config.channel_handshake_limits.max_htlc_minimum_msat {
+ return Err(ChannelError::Close(format!("htlc_minimum_msat ({}) is higher than the user specified limit ({})", msg.common_fields.htlc_minimum_msat, config.channel_handshake_limits.max_htlc_minimum_msat)));
}
- if msg.max_htlc_value_in_flight_msat < config.channel_handshake_limits.min_max_htlc_value_in_flight_msat {
- return Err(ChannelError::Close(format!("max_htlc_value_in_flight_msat ({}) is less than the user specified limit ({})", msg.max_htlc_value_in_flight_msat, config.channel_handshake_limits.min_max_htlc_value_in_flight_msat)));
+ if msg.common_fields.max_htlc_value_in_flight_msat < config.channel_handshake_limits.min_max_htlc_value_in_flight_msat {
+ return Err(ChannelError::Close(format!("max_htlc_value_in_flight_msat ({}) is less than the user specified limit ({})", msg.common_fields.max_htlc_value_in_flight_msat, config.channel_handshake_limits.min_max_htlc_value_in_flight_msat)));
}
if msg.channel_reserve_satoshis > config.channel_handshake_limits.max_channel_reserve_satoshis {
return Err(ChannelError::Close(format!("channel_reserve_satoshis ({}) is higher than the user specified limit ({})", msg.channel_reserve_satoshis, config.channel_handshake_limits.max_channel_reserve_satoshis)));
}
- if msg.max_accepted_htlcs < config.channel_handshake_limits.min_max_accepted_htlcs {
- return Err(ChannelError::Close(format!("max_accepted_htlcs ({}) is less than the user specified limit ({})", msg.max_accepted_htlcs, config.channel_handshake_limits.min_max_accepted_htlcs)));
+ if msg.common_fields.max_accepted_htlcs < config.channel_handshake_limits.min_max_accepted_htlcs {
+ return Err(ChannelError::Close(format!("max_accepted_htlcs ({}) is less than the user specified limit ({})", msg.common_fields.max_accepted_htlcs, config.channel_handshake_limits.min_max_accepted_htlcs)));
}
- if msg.dust_limit_satoshis < MIN_CHAN_DUST_LIMIT_SATOSHIS {
- return Err(ChannelError::Close(format!("dust_limit_satoshis ({}) is less than the implementation limit ({})", msg.dust_limit_satoshis, MIN_CHAN_DUST_LIMIT_SATOSHIS)));
+ if msg.common_fields.dust_limit_satoshis < MIN_CHAN_DUST_LIMIT_SATOSHIS {
+ return Err(ChannelError::Close(format!("dust_limit_satoshis ({}) is less than the implementation limit ({})", msg.common_fields.dust_limit_satoshis, MIN_CHAN_DUST_LIMIT_SATOSHIS)));
}
- if msg.dust_limit_satoshis > MAX_CHAN_DUST_LIMIT_SATOSHIS {
- return Err(ChannelError::Close(format!("dust_limit_satoshis ({}) is greater than the implementation limit ({})", msg.dust_limit_satoshis, MAX_CHAN_DUST_LIMIT_SATOSHIS)));
+ if msg.common_fields.dust_limit_satoshis > MAX_CHAN_DUST_LIMIT_SATOSHIS {
+ return Err(ChannelError::Close(format!("dust_limit_satoshis ({}) is greater than the implementation limit ({})", msg.common_fields.dust_limit_satoshis, MAX_CHAN_DUST_LIMIT_SATOSHIS)));
}
// Convert things into internal flags and prep our state:
}
}
- let holder_selected_channel_reserve_satoshis = get_holder_selected_channel_reserve_satoshis(msg.funding_satoshis, config);
+ let holder_selected_channel_reserve_satoshis = get_holder_selected_channel_reserve_satoshis(msg.common_fields.funding_satoshis, config);
if holder_selected_channel_reserve_satoshis < MIN_CHAN_DUST_LIMIT_SATOSHIS {
// Protocol level safety check in place, although it should never happen because
// of `MIN_THEIR_CHAN_RESERVE_SATOSHIS`
log_debug!(logger, "channel_reserve_satoshis ({}) is smaller than our dust limit ({}). We can broadcast stale states without any risk, implying this channel is very insecure for our counterparty.",
msg.channel_reserve_satoshis, MIN_CHAN_DUST_LIMIT_SATOSHIS);
}
- if holder_selected_channel_reserve_satoshis < msg.dust_limit_satoshis {
- return Err(ChannelError::Close(format!("Dust limit ({}) too high for the channel reserve we require the remote to keep ({})", msg.dust_limit_satoshis, holder_selected_channel_reserve_satoshis)));
+ if holder_selected_channel_reserve_satoshis < msg.common_fields.dust_limit_satoshis {
+ return Err(ChannelError::Close(format!("Dust limit ({}) too high for the channel reserve we require the remote to keep ({})", msg.common_fields.dust_limit_satoshis, holder_selected_channel_reserve_satoshis)));
}
// check if the funder's amount for the initial commitment tx is sufficient
} else {
0
};
- let funders_amount_msat = msg.funding_satoshis * 1000 - msg.push_msat;
- let commitment_tx_fee = commit_tx_fee_msat(msg.feerate_per_kw, MIN_AFFORDABLE_HTLC_COUNT, &channel_type) / 1000;
+ let funders_amount_msat = msg.common_fields.funding_satoshis * 1000 - msg.push_msat;
+ let commitment_tx_fee = commit_tx_fee_msat(msg.common_fields.commitment_feerate_sat_per_1000_weight, MIN_AFFORDABLE_HTLC_COUNT, &channel_type) / 1000;
if (funders_amount_msat / 1000).saturating_sub(anchor_outputs_value) < commitment_tx_fee {
return Err(ChannelError::Close(format!("Funding amount ({} sats) can't even pay fee for initial commitment transaction fee of {} sats.", (funders_amount_msat / 1000).saturating_sub(anchor_outputs_value), commitment_tx_fee)));
}
}
let counterparty_shutdown_scriptpubkey = if their_features.supports_upfront_shutdown_script() {
- match &msg.shutdown_scriptpubkey {
+ match &msg.common_fields.shutdown_scriptpubkey {
&Some(ref script) => {
// Peer is signaling upfront_shutdown and has opt-out with a 0-length script. We don't enforce anything
if script.len() == 0 {
inbound_handshake_limits_override: None,
- temporary_channel_id: Some(msg.temporary_channel_id),
- channel_id: msg.temporary_channel_id,
+ temporary_channel_id: Some(msg.common_fields.temporary_channel_id),
+ channel_id: msg.common_fields.temporary_channel_id,
channel_state: ChannelState::NegotiatingFunding(
NegotiatingFundingFlags::OUR_INIT_SENT | NegotiatingFundingFlags::THEIR_INIT_SENT
),
signer_pending_funding: false,
#[cfg(debug_assertions)]
- holder_max_commitment_tx_output: Mutex::new((msg.push_msat, msg.funding_satoshis * 1000 - msg.push_msat)),
+ holder_max_commitment_tx_output: Mutex::new((msg.push_msat, msg.common_fields.funding_satoshis * 1000 - msg.push_msat)),
#[cfg(debug_assertions)]
- counterparty_max_commitment_tx_output: Mutex::new((msg.push_msat, msg.funding_satoshis * 1000 - msg.push_msat)),
+ counterparty_max_commitment_tx_output: Mutex::new((msg.push_msat, msg.common_fields.funding_satoshis * 1000 - msg.push_msat)),
last_sent_closing_fee: None,
pending_counterparty_closing_signed: None,
short_channel_id: None,
channel_creation_height: current_chain_height,
- feerate_per_kw: msg.feerate_per_kw,
- channel_value_satoshis: msg.funding_satoshis,
- counterparty_dust_limit_satoshis: msg.dust_limit_satoshis,
+ feerate_per_kw: msg.common_fields.commitment_feerate_sat_per_1000_weight,
+ channel_value_satoshis: msg.common_fields.funding_satoshis,
+ counterparty_dust_limit_satoshis: msg.common_fields.dust_limit_satoshis,
holder_dust_limit_satoshis: MIN_CHAN_DUST_LIMIT_SATOSHIS,
- counterparty_max_htlc_value_in_flight_msat: cmp::min(msg.max_htlc_value_in_flight_msat, msg.funding_satoshis * 1000),
- holder_max_htlc_value_in_flight_msat: get_holder_max_htlc_value_in_flight_msat(msg.funding_satoshis, &config.channel_handshake_config),
+ counterparty_max_htlc_value_in_flight_msat: cmp::min(msg.common_fields.max_htlc_value_in_flight_msat, msg.common_fields.funding_satoshis * 1000),
+ holder_max_htlc_value_in_flight_msat: get_holder_max_htlc_value_in_flight_msat(msg.common_fields.funding_satoshis, &config.channel_handshake_config),
counterparty_selected_channel_reserve_satoshis: Some(msg.channel_reserve_satoshis),
holder_selected_channel_reserve_satoshis,
- counterparty_htlc_minimum_msat: msg.htlc_minimum_msat,
+ counterparty_htlc_minimum_msat: msg.common_fields.htlc_minimum_msat,
holder_htlc_minimum_msat: if config.channel_handshake_config.our_htlc_minimum_msat == 0 { 1 } else { config.channel_handshake_config.our_htlc_minimum_msat },
- counterparty_max_accepted_htlcs: msg.max_accepted_htlcs,
+ counterparty_max_accepted_htlcs: msg.common_fields.max_accepted_htlcs,
holder_max_accepted_htlcs: cmp::min(config.channel_handshake_config.our_max_accepted_htlcs, MAX_HTLCS),
minimum_depth,
holder_selected_contest_delay: config.channel_handshake_config.our_to_self_delay,
is_outbound_from_holder: false,
counterparty_parameters: Some(CounterpartyChannelTransactionParameters {
- selected_contest_delay: msg.to_self_delay,
+ selected_contest_delay: msg.common_fields.to_self_delay,
pubkeys: counterparty_pubkeys,
}),
funding_outpoint: None,
funding_transaction: None,
is_batch_funding: None,
- counterparty_cur_commitment_point: Some(msg.first_per_commitment_point),
+ counterparty_cur_commitment_point: Some(msg.common_fields.first_per_commitment_point),
counterparty_prev_commitment_point: None,
counterparty_node_id,
// same as the old fee.
fee_est.fee_est = 500;
let open_channel_msg = node_a_chan.get_open_channel(ChainHash::using_genesis_block(network));
- assert_eq!(open_channel_msg.feerate_per_kw, original_fee);
+ assert_eq!(open_channel_msg.common_fields.commitment_feerate_sat_per_1000_weight, original_fee);
}
#[test]
channel_type_features.set_zero_conf_required();
let mut open_channel_msg = node_a_chan.get_open_channel(ChainHash::using_genesis_block(network));
- open_channel_msg.channel_type = Some(channel_type_features);
+ open_channel_msg.common_fields.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 = InboundV1Channel::<&TestKeysInterface>::new(&feeest, &&keys_provider, &&keys_provider,
node_b_node_id, &channelmanager::provided_channel_type_features(&config),
// Set `channel_type` to `None` to force the implicit feature negotiation.
let mut open_channel_msg = channel_a.get_open_channel(ChainHash::using_genesis_block(network));
- open_channel_msg.channel_type = None;
+ open_channel_msg.common_fields.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.
).unwrap();
let mut open_channel_msg = channel_a.get_open_channel(ChainHash::using_genesis_block(network));
- open_channel_msg.channel_type = Some(simple_anchors_channel_type.clone());
+ open_channel_msg.common_fields.channel_type = Some(simple_anchors_channel_type.clone());
let res = InboundV1Channel::<&TestKeysInterface>::new(
&fee_estimator, &&keys_provider, &&keys_provider, node_id_a,
fn internal_open_channel(&self, counterparty_node_id: &PublicKey, msg: &msgs::OpenChannel) -> Result<(), MsgHandleErrInternal> {
// Note that the ChannelManager is NOT re-persisted on disk after this, so any changes are
// likely to be lost on restart!
- if msg.chain_hash != self.chain_hash {
- return Err(MsgHandleErrInternal::send_err_msg_no_close("Unknown genesis block hash".to_owned(), msg.temporary_channel_id.clone()));
+ if msg.common_fields.chain_hash != self.chain_hash {
+ return Err(MsgHandleErrInternal::send_err_msg_no_close("Unknown genesis block hash".to_owned(),
+ msg.common_fields.temporary_channel_id.clone()));
}
if !self.default_configuration.accept_inbound_channels {
- return Err(MsgHandleErrInternal::send_err_msg_no_close("No inbound channels accepted".to_owned(), msg.temporary_channel_id.clone()));
+ return Err(MsgHandleErrInternal::send_err_msg_no_close("No inbound channels accepted".to_owned(),
+ msg.common_fields.temporary_channel_id.clone()));
}
// Get the number of peers with channels, but without funded ones. We don't care too much
let peer_state_mutex = per_peer_state.get(counterparty_node_id)
.ok_or_else(|| {
debug_assert!(false);
- MsgHandleErrInternal::send_err_msg_no_close(format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id), msg.temporary_channel_id.clone())
+ MsgHandleErrInternal::send_err_msg_no_close(
+ format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id),
+ msg.common_fields.temporary_channel_id.clone())
})?;
let mut peer_state_lock = peer_state_mutex.lock().unwrap();
let peer_state = &mut *peer_state_lock;
{
return Err(MsgHandleErrInternal::send_err_msg_no_close(
"Have too many peers with unfunded channels, not accepting new ones".to_owned(),
- msg.temporary_channel_id.clone()));
+ msg.common_fields.temporary_channel_id.clone()));
}
let best_block_height = self.best_block.read().unwrap().height();
if Self::unfunded_channel_count(peer_state, best_block_height) >= MAX_UNFUNDED_CHANS_PER_PEER {
return Err(MsgHandleErrInternal::send_err_msg_no_close(
format!("Refusing more than {} unfunded channels.", MAX_UNFUNDED_CHANS_PER_PEER),
- msg.temporary_channel_id.clone()));
+ msg.common_fields.temporary_channel_id.clone()));
}
- let channel_id = msg.temporary_channel_id;
+ let channel_id = msg.common_fields.temporary_channel_id;
let channel_exists = peer_state.has_channel(&channel_id);
if channel_exists {
- return Err(MsgHandleErrInternal::send_err_msg_no_close("temporary_channel_id collision for the same peer!".to_owned(), msg.temporary_channel_id.clone()));
+ return Err(MsgHandleErrInternal::send_err_msg_no_close(
+ "temporary_channel_id collision for the same peer!".to_owned(),
+ msg.common_fields.temporary_channel_id.clone()));
}
// If we're doing manual acceptance checks on the channel, then defer creation until we're sure we want to accept.
let channel_type = channel::channel_type_from_open_channel(
&msg, &peer_state.latest_features, &self.channel_type_features()
).map_err(|e|
- MsgHandleErrInternal::from_chan_no_close(e, msg.temporary_channel_id)
+ MsgHandleErrInternal::from_chan_no_close(e, msg.common_fields.temporary_channel_id)
)?;
let mut pending_events = self.pending_events.lock().unwrap();
pending_events.push_back((events::Event::OpenChannelRequest {
- temporary_channel_id: msg.temporary_channel_id.clone(),
+ temporary_channel_id: msg.common_fields.temporary_channel_id.clone(),
counterparty_node_id: counterparty_node_id.clone(),
- funding_satoshis: msg.funding_satoshis,
+ funding_satoshis: msg.common_fields.funding_satoshis,
push_msat: msg.push_msat,
channel_type,
}, None));
&self.default_configuration, best_block_height, &self.logger, /*is_0conf=*/false)
{
Err(e) => {
- return Err(MsgHandleErrInternal::from_chan_no_close(e, msg.temporary_channel_id));
+ return Err(MsgHandleErrInternal::from_chan_no_close(e, msg.common_fields.temporary_channel_id));
},
Ok(res) => res
};
let channel_type = channel.context.get_channel_type();
if channel_type.requires_zero_conf() {
- return Err(MsgHandleErrInternal::send_err_msg_no_close("No zero confirmation channels accepted".to_owned(), msg.temporary_channel_id.clone()));
+ return Err(MsgHandleErrInternal::send_err_msg_no_close(
+ "No zero confirmation channels accepted".to_owned(),
+ msg.common_fields.temporary_channel_id.clone()));
}
if channel_type.requires_anchors_zero_fee_htlc_tx() {
- return Err(MsgHandleErrInternal::send_err_msg_no_close("No channels with anchor outputs accepted".to_owned(), msg.temporary_channel_id.clone()));
+ return Err(MsgHandleErrInternal::send_err_msg_no_close(
+ "No channels with anchor outputs accepted".to_owned(),
+ msg.common_fields.temporary_channel_id.clone()));
}
let outbound_scid_alias = self.create_and_insert_outbound_scid_alias();
fn handle_open_channel_v2(&self, counterparty_node_id: &PublicKey, msg: &msgs::OpenChannelV2) {
let _: Result<(), _> = handle_error!(self, Err(MsgHandleErrInternal::send_err_msg_no_close(
"Dual-funded channels not supported".to_owned(),
- msg.temporary_channel_id.clone())), *counterparty_node_id);
+ msg.common_fields.temporary_channel_id.clone())), *counterparty_node_id);
}
fn handle_accept_channel(&self, counterparty_node_id: &PublicKey, msg: &msgs::AcceptChannel) {
check_added_monitors!(nodes[0], 1);
expect_channel_pending_event(&nodes[0], &nodes[1].node.get_our_node_id());
}
- open_channel_msg.temporary_channel_id = ChannelId::temporary_from_entropy_source(&nodes[0].keys_manager);
+ open_channel_msg.common_fields.temporary_channel_id = ChannelId::temporary_from_entropy_source(&nodes[0].keys_manager);
}
// A MAX_UNFUNDED_CHANS_PER_PEER + 1 channel will be summarily rejected
- open_channel_msg.temporary_channel_id = ChannelId::temporary_from_entropy_source(&nodes[0].keys_manager);
+ open_channel_msg.common_fields.temporary_channel_id = ChannelId::temporary_from_entropy_source(
+ &nodes[0].keys_manager);
nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), &open_channel_msg);
assert_eq!(get_err_msg(&nodes[1], &nodes[0].node.get_our_node_id()).channel_id,
- open_channel_msg.temporary_channel_id);
+ open_channel_msg.common_fields.temporary_channel_id);
// Further, because all of our channels with nodes[0] are inbound, and none of them funded,
// it doesn't count as a "protected" peer, i.e. it counts towards the MAX_NO_CHANNEL_PEERS
for i in 0..super::MAX_UNFUNDED_CHANNEL_PEERS - 1 {
nodes[1].node.handle_open_channel(&peer_pks[i], &open_channel_msg);
get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, peer_pks[i]);
- open_channel_msg.temporary_channel_id = ChannelId::temporary_from_entropy_source(&nodes[0].keys_manager);
+ open_channel_msg.common_fields.temporary_channel_id = ChannelId::temporary_from_entropy_source(&nodes[0].keys_manager);
}
nodes[1].node.handle_open_channel(&last_random_pk, &open_channel_msg);
assert_eq!(get_err_msg(&nodes[1], &last_random_pk).channel_id,
- open_channel_msg.temporary_channel_id);
+ open_channel_msg.common_fields.temporary_channel_id);
// Of course, however, outbound channels are always allowed
nodes[1].node.create_channel(last_random_pk, 100_000, 0, 42, None, None).unwrap();
for _ in 0..super::MAX_UNFUNDED_CHANS_PER_PEER {
nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), &open_channel_msg);
get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id());
- open_channel_msg.temporary_channel_id = ChannelId::temporary_from_entropy_source(&nodes[0].keys_manager);
+ open_channel_msg.common_fields.temporary_channel_id = ChannelId::temporary_from_entropy_source(&nodes[0].keys_manager);
}
// Once we have MAX_UNFUNDED_CHANS_PER_PEER unfunded channels, new inbound channels will be
// rejected.
nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), &open_channel_msg);
assert_eq!(get_err_msg(&nodes[1], &nodes[0].node.get_our_node_id()).channel_id,
- open_channel_msg.temporary_channel_id);
+ open_channel_msg.common_fields.temporary_channel_id);
// but we can still open an outbound channel.
nodes[1].node.create_channel(nodes[0].node.get_our_node_id(), 100_000, 0, 42, None, None).unwrap();
// but even with such an outbound channel, additional inbound channels will still fail.
nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), &open_channel_msg);
assert_eq!(get_err_msg(&nodes[1], &nodes[0].node.get_our_node_id()).channel_id,
- open_channel_msg.temporary_channel_id);
+ open_channel_msg.common_fields.temporary_channel_id);
}
#[test]
_ => panic!("Unexpected event"),
}
get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, random_pk);
- open_channel_msg.temporary_channel_id = ChannelId::temporary_from_entropy_source(&nodes[0].keys_manager);
+ open_channel_msg.common_fields.temporary_channel_id = ChannelId::temporary_from_entropy_source(&nodes[0].keys_manager);
}
// If we try to accept a channel from another peer non-0conf it will fail.
_ => panic!("Unexpected event"),
}
assert_eq!(get_err_msg(&nodes[1], &last_random_pk).channel_id,
- open_channel_msg.temporary_channel_id);
+ open_channel_msg.common_fields.temporary_channel_id);
// ...however if we accept the same channel 0conf it should work just fine.
nodes[1].node.handle_open_channel(&last_random_pk, &open_channel_msg);
nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100_000, 0, 0, None, None).unwrap();
let open_channel_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id());
- assert!(open_channel_msg.channel_type.as_ref().unwrap().supports_anchors_zero_fee_htlc_tx());
+ assert!(open_channel_msg.common_fields.channel_type.as_ref().unwrap().supports_anchors_zero_fee_htlc_tx());
nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), &open_channel_msg);
let events = nodes[1].node.get_and_clear_pending_events();
nodes[0].node.handle_error(&nodes[1].node.get_our_node_id(), &error_msg);
let open_channel_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id());
- assert!(!open_channel_msg.channel_type.unwrap().supports_anchors_zero_fee_htlc_tx());
+ assert!(!open_channel_msg.common_fields.channel_type.unwrap().supports_anchors_zero_fee_htlc_tx());
// Since nodes[1] should not have accepted the channel, it should
// not have generated any events.
pub fn exchange_open_accept_chan<'a, 'b, 'c>(node_a: &Node<'a, 'b, 'c>, node_b: &Node<'a, 'b, 'c>, channel_value: u64, push_msat: u64) -> ChannelId {
let create_chan_id = node_a.node.create_channel(node_b.node.get_our_node_id(), channel_value, push_msat, 42, None, None).unwrap();
let open_channel_msg = get_event_msg!(node_a, MessageSendEvent::SendOpenChannel, node_b.node.get_our_node_id());
- assert_eq!(open_channel_msg.temporary_channel_id, create_chan_id);
+ assert_eq!(open_channel_msg.common_fields.temporary_channel_id, create_chan_id);
assert_eq!(node_a.node.list_channels().iter().find(|channel| channel.channel_id == create_chan_id).unwrap().user_channel_id, 42);
node_b.node.handle_open_channel(&node_a.node.get_our_node_id(), &open_channel_msg);
if node_b.node.get_current_default_configuration().manually_accept_inbound_channels {
use crate::ln::channelmanager::MAX_LOCAL_BREAKDOWN_TIMEOUT;
// Test all mutations that would make the channel open message insane
- insane_open_helper(format!("Per our config, funding must be at most {}. It was {}", TOTAL_BITCOIN_SUPPLY_SATOSHIS + 1, TOTAL_BITCOIN_SUPPLY_SATOSHIS + 2).as_str(), |mut msg| { msg.funding_satoshis = TOTAL_BITCOIN_SUPPLY_SATOSHIS + 2; msg });
- insane_open_helper(format!("Funding must be smaller than the total bitcoin supply. It was {}", TOTAL_BITCOIN_SUPPLY_SATOSHIS).as_str(), |mut msg| { msg.funding_satoshis = TOTAL_BITCOIN_SUPPLY_SATOSHIS; msg });
+ insane_open_helper(format!("Per our config, funding must be at most {}. It was {}", TOTAL_BITCOIN_SUPPLY_SATOSHIS + 1, TOTAL_BITCOIN_SUPPLY_SATOSHIS + 2).as_str(), |mut msg| { msg.common_fields.funding_satoshis = TOTAL_BITCOIN_SUPPLY_SATOSHIS + 2; msg });
+ insane_open_helper(format!("Funding must be smaller than the total bitcoin supply. It was {}", TOTAL_BITCOIN_SUPPLY_SATOSHIS).as_str(), |mut msg| { msg.common_fields.funding_satoshis = TOTAL_BITCOIN_SUPPLY_SATOSHIS; msg });
- insane_open_helper("Bogus channel_reserve_satoshis", |mut msg| { msg.channel_reserve_satoshis = msg.funding_satoshis + 1; msg });
+ insane_open_helper("Bogus channel_reserve_satoshis", |mut msg| { msg.channel_reserve_satoshis = msg.common_fields.funding_satoshis + 1; msg });
- insane_open_helper(r"push_msat \d+ was larger than channel amount minus reserve \(\d+\)", |mut msg| { msg.push_msat = (msg.funding_satoshis - msg.channel_reserve_satoshis) * 1000 + 1; msg });
+ insane_open_helper(r"push_msat \d+ was larger than channel amount minus reserve \(\d+\)", |mut msg| { msg.push_msat = (msg.common_fields.funding_satoshis - msg.channel_reserve_satoshis) * 1000 + 1; msg });
- insane_open_helper("Peer never wants payout outputs?", |mut msg| { msg.dust_limit_satoshis = msg.funding_satoshis + 1 ; msg });
+ insane_open_helper("Peer never wants payout outputs?", |mut msg| { msg.common_fields.dust_limit_satoshis = msg.common_fields.funding_satoshis + 1 ; msg });
- insane_open_helper(r"Minimum htlc value \(\d+\) was larger than full channel value \(\d+\)", |mut msg| { msg.htlc_minimum_msat = (msg.funding_satoshis - msg.channel_reserve_satoshis) * 1000; msg });
+ insane_open_helper(r"Minimum htlc value \(\d+\) was larger than full channel value \(\d+\)", |mut msg| { msg.common_fields.htlc_minimum_msat = (msg.common_fields.funding_satoshis - msg.channel_reserve_satoshis) * 1000; msg });
- insane_open_helper("They wanted our payments to be delayed by a needlessly long period", |mut msg| { msg.to_self_delay = MAX_LOCAL_BREAKDOWN_TIMEOUT + 1; msg });
+ insane_open_helper("They wanted our payments to be delayed by a needlessly long period", |mut msg| { msg.common_fields.to_self_delay = MAX_LOCAL_BREAKDOWN_TIMEOUT + 1; msg });
- insane_open_helper("0 max_accepted_htlcs makes for a useless channel", |mut msg| { msg.max_accepted_htlcs = 0; msg });
+ insane_open_helper("0 max_accepted_htlcs makes for a useless channel", |mut msg| { msg.common_fields.max_accepted_htlcs = 0; msg });
- insane_open_helper("max_accepted_htlcs was 484. It must not be larger than 483", |mut msg| { msg.max_accepted_htlcs = 484; msg });
+ insane_open_helper("max_accepted_htlcs was 484. It must not be larger than 483", |mut msg| { msg.common_fields.max_accepted_htlcs = 484; msg });
}
#[test]
let mut open_channel_message = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id());
if !send_from_initiator {
open_channel_message.channel_reserve_satoshis = 0;
- open_channel_message.max_htlc_value_in_flight_msat = 100_000_000;
+ open_channel_message.common_fields.max_htlc_value_in_flight_msat = 100_000_000;
}
nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), &open_channel_message);
let push_msat=10001;
assert!(nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), channel_value_satoshis, push_msat, 42, None, None).is_ok()); //Create a valid channel
let node0_to_1_send_open_channel = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id());
- assert!(node0_to_1_send_open_channel.channel_reserve_satoshis>=node0_to_1_send_open_channel.dust_limit_satoshis);
+ assert!(node0_to_1_send_open_channel.channel_reserve_satoshis>=node0_to_1_send_open_channel.common_fields.dust_limit_satoshis);
// BOLT #2 spec: Sending node must set undefined bits in channel_flags to 0
// Only the least-significant bit of channel_flags is currently defined resulting in channel_flags only having one of two possible states 0 or 1
- assert!(node0_to_1_send_open_channel.channel_flags<=1);
+ assert!(node0_to_1_send_open_channel.common_fields.channel_flags<=1);
// BOLT #2 spec: Sending node should set to_self_delay sufficient to ensure the sender can irreversibly spend a commitment transaction output, in case of misbehaviour by the receiver.
assert!(BREAKDOWN_TIMEOUT>0);
- assert!(node0_to_1_send_open_channel.to_self_delay==BREAKDOWN_TIMEOUT);
+ assert!(node0_to_1_send_open_channel.common_fields.to_self_delay==BREAKDOWN_TIMEOUT);
// BOLT #2 spec: Sending node must ensure the chain_hash value identifies the chain it wishes to open the channel within.
let chain_hash = ChainHash::using_genesis_block(Network::Testnet);
- assert_eq!(node0_to_1_send_open_channel.chain_hash, chain_hash);
+ assert_eq!(node0_to_1_send_open_channel.common_fields.chain_hash, chain_hash);
// BOLT #2 spec: Sending node must set funding_pubkey, revocation_basepoint, htlc_basepoint, payment_basepoint, and delayed_payment_basepoint to valid DER-encoded, compressed, secp256k1 pubkeys.
- assert!(PublicKey::from_slice(&node0_to_1_send_open_channel.funding_pubkey.serialize()).is_ok());
- assert!(PublicKey::from_slice(&node0_to_1_send_open_channel.revocation_basepoint.serialize()).is_ok());
- assert!(PublicKey::from_slice(&node0_to_1_send_open_channel.htlc_basepoint.serialize()).is_ok());
- assert!(PublicKey::from_slice(&node0_to_1_send_open_channel.payment_point.serialize()).is_ok());
- assert!(PublicKey::from_slice(&node0_to_1_send_open_channel.delayed_payment_basepoint.serialize()).is_ok());
+ assert!(PublicKey::from_slice(&node0_to_1_send_open_channel.common_fields.funding_pubkey.serialize()).is_ok());
+ assert!(PublicKey::from_slice(&node0_to_1_send_open_channel.common_fields.revocation_basepoint.serialize()).is_ok());
+ assert!(PublicKey::from_slice(&node0_to_1_send_open_channel.common_fields.htlc_basepoint.serialize()).is_ok());
+ assert!(PublicKey::from_slice(&node0_to_1_send_open_channel.common_fields.payment_basepoint.serialize()).is_ok());
+ assert!(PublicKey::from_slice(&node0_to_1_send_open_channel.common_fields.delayed_payment_basepoint.serialize()).is_ok());
}
#[test]
let push_msat=10001;
nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), channel_value_satoshis, push_msat, 42, None, None).unwrap();
let mut node0_to_1_send_open_channel = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id());
- node0_to_1_send_open_channel.dust_limit_satoshis = 547;
+ node0_to_1_send_open_channel.common_fields.dust_limit_satoshis = 547;
node0_to_1_send_open_channel.channel_reserve_satoshis = 100001;
nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), &node0_to_1_send_open_channel);
// We test config.our_to_self > BREAKDOWN_TIMEOUT is enforced in InboundV1Channel::new()
nodes[1].node.create_channel(nodes[0].node.get_our_node_id(), 1000000, 1000000, 42, None, None).unwrap();
let mut open_channel = get_event_msg!(nodes[1], MessageSendEvent::SendOpenChannel, nodes[0].node.get_our_node_id());
- open_channel.to_self_delay = 200;
+ open_channel.common_fields.to_self_delay = 200;
if let Err(error) = InboundV1Channel::new(&LowerBoundedFeeEstimator::new(&test_utils::TestFeeEstimator { sat_per_kw: Mutex::new(253) }),
&nodes[0].keys_manager, &nodes[0].keys_manager, nodes[1].node.get_our_node_id(), &nodes[0].node.channel_type_features(), &nodes[1].node.init_features(), &open_channel, 0,
&low_our_to_self_config, 0, &nodes[0].logger, /*is_0conf=*/false)
// We test msg.to_self_delay <= config.their_to_self_delay is enforced in InboundV1Channel::new()
nodes[1].node.create_channel(nodes[0].node.get_our_node_id(), 1000000, 1000000, 42, None, None).unwrap();
let mut open_channel = get_event_msg!(nodes[1], MessageSendEvent::SendOpenChannel, nodes[0].node.get_our_node_id());
- open_channel.to_self_delay = 200;
+ open_channel.common_fields.to_self_delay = 200;
if let Err(error) = InboundV1Channel::new(&LowerBoundedFeeEstimator::new(&test_utils::TestFeeEstimator { sat_per_kw: Mutex::new(253) }),
&nodes[0].keys_manager, &nodes[0].keys_manager, nodes[1].node.get_our_node_id(), &nodes[0].node.channel_type_features(), &nodes[1].node.init_features(), &open_channel, 0,
&high_their_to_self_config, 0, &nodes[0].logger, /*is_0conf=*/false)
// Assert the channel created by node0 is using the override config.
let res = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id());
- assert_eq!(res.channel_flags, 0);
- assert_eq!(res.to_self_delay, 200);
+ assert_eq!(res.common_fields.channel_flags, 0);
+ assert_eq!(res.common_fields.to_self_delay, 200);
}
#[test]
nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 16_000_000, 12_000_000, 42, None, Some(zero_config)).unwrap();
let res = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id());
- assert_eq!(res.htlc_minimum_msat, 1);
+ assert_eq!(res.common_fields.htlc_minimum_msat, 1);
nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), &res);
let res = get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id());
// Modify the `OpenChannel` from `nodes[2]` to `nodes[0]` to ensure that it uses the same
// `temporary_channel_id` as the `OpenChannel` from nodes[1] to nodes[0].
- open_chan_msg_chan_2_0.temporary_channel_id = open_chan_msg_chan_1_0.temporary_channel_id;
+ open_chan_msg_chan_2_0.common_fields.temporary_channel_id = open_chan_msg_chan_1_0.common_fields.temporary_channel_id;
// Assert that `nodes[0]` can accept both `OpenChannel` requests, even though they use the same
// `temporary_channel_id` as they are from different peers.
match &events[0] {
MessageSendEvent::SendAcceptChannel { node_id, msg } => {
assert_eq!(node_id, &nodes[1].node.get_our_node_id());
- assert_eq!(msg.temporary_channel_id, open_chan_msg_chan_1_0.temporary_channel_id);
+ assert_eq!(msg.temporary_channel_id, open_chan_msg_chan_1_0.common_fields.temporary_channel_id);
},
_ => panic!("Unexpected event"),
}
match &events[0] {
MessageSendEvent::SendAcceptChannel { node_id, msg } => {
assert_eq!(node_id, &nodes[2].node.get_our_node_id());
- assert_eq!(msg.temporary_channel_id, open_chan_msg_chan_1_0.temporary_channel_id);
+ assert_eq!(msg.temporary_channel_id, open_chan_msg_chan_1_0.common_fields.temporary_channel_id);
},
_ => panic!("Unexpected event"),
}
nodes[2].node.create_channel(nodes[1].node.get_our_node_id(), 100_000, 0, 42, None, None).unwrap();
let mut open_chan_msg = get_event_msg!(nodes[2], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id());
- let node_c_temp_chan_id = open_chan_msg.temporary_channel_id;
- open_chan_msg.temporary_channel_id = real_channel_id;
+ let node_c_temp_chan_id = open_chan_msg.common_fields.temporary_channel_id;
+ open_chan_msg.common_fields.temporary_channel_id = real_channel_id;
nodes[1].node.handle_open_channel(&nodes[2].node.get_our_node_id(), &open_chan_msg);
let mut accept_chan_msg = get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[2].node.get_our_node_id());
accept_chan_msg.temporary_channel_id = node_c_temp_chan_id;
// first (valid) and second (invalid) channels are closed, given they both have
// the same non-temporary channel_id. However, currently we do not, so we just
// move forward with it.
- assert_eq!(msg.channel_id, open_chan_msg.temporary_channel_id);
+ assert_eq!(msg.channel_id, open_chan_msg.common_fields.temporary_channel_id);
assert_eq!(node_id, nodes[0].node.get_our_node_id());
},
_ => panic!("Unexpected event"),
// First try to open a second channel with a temporary channel id equal to the txid-based one.
// Technically this is allowed by the spec, but we don't support it and there's little reason
// to. Still, it shouldn't cause any other issues.
- open_chan_msg.temporary_channel_id = channel_id;
+ open_chan_msg.common_fields.temporary_channel_id = channel_id;
nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), &open_chan_msg);
{
let events = nodes[1].node.get_and_clear_pending_msg_events();
MessageSendEvent::HandleError { action: ErrorAction::SendErrorMessage { ref msg }, node_id } => {
// Technically, at this point, nodes[1] would be justified in thinking both
// channels are closed, but currently we do not, so we just move forward with it.
- assert_eq!(msg.channel_id, open_chan_msg.temporary_channel_id);
+ assert_eq!(msg.channel_id, open_chan_msg.common_fields.temporary_channel_id);
assert_eq!(node_id, nodes[0].node.get_our_node_id());
},
_ => panic!("Unexpected event"),
// another channel in the ChannelManager - an invalid state. Thus, we'd panic later when we
// try to create another channel. Instead, we drop the channel entirely here (leaving the
// channelmanager in a possibly nonsense state instead).
- match a_peer_state.channel_by_id.remove(&open_chan_2_msg.temporary_channel_id).unwrap() {
+ match a_peer_state.channel_by_id.remove(&open_chan_2_msg.common_fields.temporary_channel_id).unwrap() {
ChannelPhase::UnfundedOutboundV1(mut chan) => {
let logger = test_utils::TestLogger::new();
chan.get_funding_created(tx.clone(), funding_outpoint, false, &&logger).map_err(|_| ()).unwrap()
nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 1_000_000, 500_000_000, 42, None, None).unwrap();
let mut open_channel = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id());
- open_channel.max_htlc_value_in_flight_msat = 50_000_000;
- open_channel.max_accepted_htlcs = 60;
+ open_channel.common_fields.max_htlc_value_in_flight_msat = 50_000_000;
+ open_channel.common_fields.max_accepted_htlcs = 60;
if on_holder_tx {
- open_channel.dust_limit_satoshis = 546;
+ open_channel.common_fields.dust_limit_satoshis = 546;
}
nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), &open_channel);
let mut accept_channel = get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id());
(chan.context().get_dust_buffer_feerate(None) as u64,
chan.context().get_max_dust_htlc_exposure_msat(&LowerBoundedFeeEstimator(nodes[0].fee_estimator)))
};
- let dust_outbound_htlc_on_holder_tx_msat: u64 = (dust_buffer_feerate * htlc_timeout_tx_weight(&channel_type_features) / 1000 + open_channel.dust_limit_satoshis - 1) * 1000;
+ let dust_outbound_htlc_on_holder_tx_msat: u64 = (dust_buffer_feerate * htlc_timeout_tx_weight(&channel_type_features) / 1000 + open_channel.common_fields.dust_limit_satoshis - 1) * 1000;
let dust_outbound_htlc_on_holder_tx: u64 = max_dust_htlc_exposure_msat / dust_outbound_htlc_on_holder_tx_msat;
- let dust_inbound_htlc_on_holder_tx_msat: u64 = (dust_buffer_feerate * htlc_success_tx_weight(&channel_type_features) / 1000 + open_channel.dust_limit_satoshis - 1) * 1000;
+ let dust_inbound_htlc_on_holder_tx_msat: u64 = (dust_buffer_feerate * htlc_success_tx_weight(&channel_type_features) / 1000 + open_channel.common_fields.dust_limit_satoshis - 1) * 1000;
let dust_inbound_htlc_on_holder_tx: u64 = max_dust_htlc_exposure_msat / dust_inbound_htlc_on_holder_tx_msat;
let dust_htlc_on_counterparty_tx: u64 = 4;
pub byteslen: u16,
}
-/// An [`open_channel`] message to be sent to or received from a peer.
-///
-/// Used in V1 channel establishment
+/// Contains fields that are both common to [`open_channel`] and `open_channel2` messages.
///
/// [`open_channel`]: https://github.com/lightning/bolts/blob/master/02-peer-protocol.md#the-open_channel-message
+// TODO(dual_funding): Add spec link for `open_channel2`.
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
-pub struct OpenChannel {
+pub struct CommonOpenChannelFields {
/// The genesis hash of the blockchain where the channel is to be opened
pub chain_hash: ChainHash,
- /// A temporary channel ID, until the funding outpoint is announced
+ /// A temporary channel ID
+ /// For V2 channels: derived using a zeroed out value for the channel acceptor's revocation basepoint
+ /// For V1 channels: a temporary channel ID, until the funding outpoint is announced
pub temporary_channel_id: ChannelId,
- /// The channel value
+ /// For V1 channels: The channel value
+ /// For V2 channels: Part of the channel value contributed by the channel initiator
pub funding_satoshis: u64,
- /// The amount to push to the counterparty as part of the open, in milli-satoshi
- pub push_msat: u64,
- /// The threshold below which outputs on transactions broadcast by sender will be omitted
+ /// The threshold below which outputs on transactions broadcast by the channel initiator will be
+ /// omitted
pub dust_limit_satoshis: u64,
- /// The maximum inbound HTLC value in flight towards sender, in milli-satoshi
+ /// The maximum inbound HTLC value in flight towards channel initiator, in milli-satoshi
pub max_htlc_value_in_flight_msat: u64,
- /// The minimum value unencumbered by HTLCs for the counterparty to keep in the channel
- pub channel_reserve_satoshis: u64,
- /// The minimum HTLC size incoming to sender, in milli-satoshi
+ /// The minimum HTLC size incoming to channel initiator, in milli-satoshi
pub htlc_minimum_msat: u64,
- /// The feerate per 1000-weight of sender generated transactions, until updated by
+ /// The feerate for the commitment transaction set by the channel initiator until updated by
/// [`UpdateFee`]
- pub feerate_per_kw: u32,
- /// The number of blocks which the counterparty will have to wait to claim on-chain funds if
- /// they broadcast a commitment transaction
+ pub commitment_feerate_sat_per_1000_weight: u32,
+ /// The number of blocks which the counterparty will have to wait to claim on-chain funds if they
+ /// broadcast a commitment transaction
pub to_self_delay: u16,
- /// The maximum number of inbound HTLCs towards sender
+ /// The maximum number of inbound HTLCs towards channel initiator
pub max_accepted_htlcs: u16,
- /// The sender's key controlling the funding transaction
+ /// The channel initiator's key controlling the funding transaction
pub funding_pubkey: PublicKey,
/// Used to derive a revocation key for transactions broadcast by counterparty
pub revocation_basepoint: PublicKey,
- /// A payment key to sender for transactions broadcast by counterparty
- pub payment_point: PublicKey,
- /// Used to derive a payment key to sender for transactions broadcast by sender
+ /// A payment key to channel initiator for transactions broadcast by counterparty
+ pub payment_basepoint: PublicKey,
+ /// Used to derive a payment key to channel initiator for transactions broadcast by channel
+ /// initiator
pub delayed_payment_basepoint: PublicKey,
- /// Used to derive an HTLC payment key to sender
+ /// Used to derive an HTLC payment key to channel initiator
pub htlc_basepoint: PublicKey,
- /// The first to-be-broadcast-by-sender transaction's per commitment point
+ /// The first to-be-broadcast-by-channel-initiator transaction's per commitment point
pub first_per_commitment_point: PublicKey,
/// The channel flags to be used
pub channel_flags: u8,
- /// A request to pre-set the to-sender output's `scriptPubkey` for when we collaboratively close
+ /// Optionally, a request to pre-set the to-channel-initiator output's scriptPubkey for when we
+ /// collaboratively close
pub shutdown_scriptpubkey: Option<ScriptBuf>,
/// The channel type that this channel will represent
///
pub channel_type: Option<ChannelTypeFeatures>,
}
+/// An [`open_channel`] message to be sent to or received from a peer.
+///
+/// Used in V1 channel establishment
+///
+/// [`open_channel`]: https://github.com/lightning/bolts/blob/master/02-peer-protocol.md#the-open_channel-message
+#[derive(Clone, Debug, Hash, PartialEq, Eq)]
+pub struct OpenChannel {
+ /// Common fields of `open_channel(2)`-like messages
+ pub common_fields: CommonOpenChannelFields,
+ /// The amount to push to the counterparty as part of the open, in milli-satoshi
+ pub push_msat: u64,
+ /// The minimum value unencumbered by HTLCs for the counterparty to keep in the channel
+ pub channel_reserve_satoshis: u64,
+}
+
/// An open_channel2 message to be sent by or received from the channel initiator.
///
/// Used in V2 channel establishment
// TODO(dual_funding): Add spec link for `open_channel2`.
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub struct OpenChannelV2 {
- /// The genesis hash of the blockchain where the channel is to be opened
- pub chain_hash: ChainHash,
- /// A temporary channel ID derived using a zeroed out value for the channel acceptor's revocation basepoint
- pub temporary_channel_id: ChannelId,
+ /// Common fields of `open_channel(2)`-like messages
+ pub common_fields: CommonOpenChannelFields,
/// The feerate for the funding transaction set by the channel initiator
pub funding_feerate_sat_per_1000_weight: u32,
- /// The feerate for the commitment transaction set by the channel initiator
- pub commitment_feerate_sat_per_1000_weight: u32,
- /// Part of the channel value contributed by the channel initiator
- pub funding_satoshis: u64,
- /// The threshold below which outputs on transactions broadcast by the channel initiator will be
- /// omitted
- pub dust_limit_satoshis: u64,
- /// The maximum inbound HTLC value in flight towards channel initiator, in milli-satoshi
- pub max_htlc_value_in_flight_msat: u64,
- /// The minimum HTLC size incoming to channel initiator, in milli-satoshi
- pub htlc_minimum_msat: u64,
- /// The number of blocks which the counterparty will have to wait to claim on-chain funds if they
- /// broadcast a commitment transaction
- pub to_self_delay: u16,
- /// The maximum number of inbound HTLCs towards channel initiator
- pub max_accepted_htlcs: u16,
/// The locktime for the funding transaction
pub locktime: u32,
- /// The channel initiator's key controlling the funding transaction
- pub funding_pubkey: PublicKey,
- /// Used to derive a revocation key for transactions broadcast by counterparty
- pub revocation_basepoint: PublicKey,
- /// A payment key to channel initiator for transactions broadcast by counterparty
- pub payment_basepoint: PublicKey,
- /// Used to derive a payment key to channel initiator for transactions broadcast by channel
- /// initiator
- pub delayed_payment_basepoint: PublicKey,
- /// Used to derive an HTLC payment key to channel initiator
- pub htlc_basepoint: PublicKey,
- /// The first to-be-broadcast-by-channel-initiator transaction's per commitment point
- pub first_per_commitment_point: PublicKey,
/// The second to-be-broadcast-by-channel-initiator transaction's per commitment point
pub second_per_commitment_point: PublicKey,
- /// Channel flags
- pub channel_flags: u8,
- /// Optionally, a request to pre-set the to-channel-initiator output's scriptPubkey for when we
- /// collaboratively close
- pub shutdown_scriptpubkey: Option<ScriptBuf>,
- /// The channel type that this channel will represent. If none is set, we derive the channel
- /// type from the intersection of our feature bits with our counterparty's feature bits from
- /// the Init message.
- pub channel_type: Option<ChannelTypeFeatures>,
/// Optionally, a requirement that only confirmed inputs can be added
pub require_confirmed_inputs: Option<()>,
}
///
/// If this is `None`, we derive the channel type from the intersection of
/// our feature bits with our counterparty's feature bits from the [`Init`] message.
- /// This is required to match the equivalent field in [`OpenChannel::channel_type`].
+ /// This is required to match the equivalent field in [`OpenChannel`]'s [`CommonOpenChannelFields::channel_type`].
pub channel_type: Option<ChannelTypeFeatures>,
#[cfg(taproot)]
/// Next nonce the channel initiator should use to create a funding output signature against
/// type from the intersection of our feature bits with our counterparty's feature bits from
/// the Init message.
///
- /// This is required to match the equivalent field in [`OpenChannelV2::channel_type`].
+ /// This is required to match the equivalent field in [`OpenChannelV2`]'s [`CommonOpenChannelFields::channel_type`].
pub channel_type: Option<ChannelTypeFeatures>,
/// Optionally, a requirement that only confirmed inputs can be added
pub require_confirmed_inputs: Option<()>,
}
}
-impl_writeable_msg!(OpenChannel, {
- chain_hash,
- temporary_channel_id,
- funding_satoshis,
- push_msat,
- dust_limit_satoshis,
- max_htlc_value_in_flight_msat,
- channel_reserve_satoshis,
- htlc_minimum_msat,
- feerate_per_kw,
- to_self_delay,
- max_accepted_htlcs,
- funding_pubkey,
- revocation_basepoint,
- payment_point,
- delayed_payment_basepoint,
- htlc_basepoint,
- first_per_commitment_point,
- channel_flags,
-}, {
- (0, shutdown_scriptpubkey, (option, encoding: (ScriptBuf, WithoutLength))), // Don't encode length twice.
- (1, channel_type, option),
-});
+impl Writeable for OpenChannel {
+ fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
+ self.common_fields.chain_hash.write(w)?;
+ self.common_fields.temporary_channel_id.write(w)?;
+ self.common_fields.funding_satoshis.write(w)?;
+ self.push_msat.write(w)?;
+ self.common_fields.dust_limit_satoshis.write(w)?;
+ self.common_fields.max_htlc_value_in_flight_msat.write(w)?;
+ self.channel_reserve_satoshis.write(w)?;
+ self.common_fields.htlc_minimum_msat.write(w)?;
+ self.common_fields.commitment_feerate_sat_per_1000_weight.write(w)?;
+ self.common_fields.to_self_delay.write(w)?;
+ self.common_fields.max_accepted_htlcs.write(w)?;
+ self.common_fields.funding_pubkey.write(w)?;
+ self.common_fields.revocation_basepoint.write(w)?;
+ self.common_fields.payment_basepoint.write(w)?;
+ self.common_fields.delayed_payment_basepoint.write(w)?;
+ self.common_fields.htlc_basepoint.write(w)?;
+ self.common_fields.first_per_commitment_point.write(w)?;
+ self.common_fields.channel_flags.write(w)?;
+ encode_tlv_stream!(w, {
+ (0, self.common_fields.shutdown_scriptpubkey.as_ref().map(|s| WithoutLength(s)), option), // Don't encode length twice.
+ (1, self.common_fields.channel_type, option),
+ });
+ Ok(())
+ }
+}
-impl_writeable_msg!(OpenChannelV2, {
- chain_hash,
- temporary_channel_id,
- funding_feerate_sat_per_1000_weight,
- commitment_feerate_sat_per_1000_weight,
- funding_satoshis,
- dust_limit_satoshis,
- max_htlc_value_in_flight_msat,
- htlc_minimum_msat,
- to_self_delay,
- max_accepted_htlcs,
- locktime,
- funding_pubkey,
- revocation_basepoint,
- payment_basepoint,
- delayed_payment_basepoint,
- htlc_basepoint,
- first_per_commitment_point,
- second_per_commitment_point,
- channel_flags,
-}, {
- (0, shutdown_scriptpubkey, option),
- (1, channel_type, option),
- (2, require_confirmed_inputs, option),
-});
+impl Readable for OpenChannel {
+ fn read<R: Read>(r: &mut R) -> Result<Self, DecodeError> {
+ let chain_hash: ChainHash = Readable::read(r)?;
+ let temporary_channel_id: ChannelId = Readable::read(r)?;
+ let funding_satoshis: u64 = Readable::read(r)?;
+ let push_msat: u64 = Readable::read(r)?;
+ let dust_limit_satoshis: u64 = Readable::read(r)?;
+ let max_htlc_value_in_flight_msat: u64 = Readable::read(r)?;
+ let channel_reserve_satoshis: u64 = Readable::read(r)?;
+ let htlc_minimum_msat: u64 = Readable::read(r)?;
+ let commitment_feerate_sat_per_1000_weight: u32 = Readable::read(r)?;
+ let to_self_delay: u16 = Readable::read(r)?;
+ let max_accepted_htlcs: u16 = Readable::read(r)?;
+ let funding_pubkey: PublicKey = Readable::read(r)?;
+ let revocation_basepoint: PublicKey = Readable::read(r)?;
+ let payment_basepoint: PublicKey = Readable::read(r)?;
+ let delayed_payment_basepoint: PublicKey = Readable::read(r)?;
+ let htlc_basepoint: PublicKey = Readable::read(r)?;
+ let first_per_commitment_point: PublicKey = Readable::read(r)?;
+ let channel_flags: u8 = Readable::read(r)?;
+
+ let mut shutdown_scriptpubkey: Option<ScriptBuf> = None;
+ let mut channel_type: Option<ChannelTypeFeatures> = None;
+ decode_tlv_stream!(r, {
+ (0, shutdown_scriptpubkey, (option, encoding: (ScriptBuf, WithoutLength))),
+ (1, channel_type, option),
+ });
+ Ok(OpenChannel {
+ common_fields: CommonOpenChannelFields {
+ chain_hash,
+ temporary_channel_id,
+ funding_satoshis,
+ dust_limit_satoshis,
+ max_htlc_value_in_flight_msat,
+ htlc_minimum_msat,
+ commitment_feerate_sat_per_1000_weight,
+ to_self_delay,
+ max_accepted_htlcs,
+ funding_pubkey,
+ revocation_basepoint,
+ payment_basepoint,
+ delayed_payment_basepoint,
+ htlc_basepoint,
+ first_per_commitment_point,
+ channel_flags,
+ shutdown_scriptpubkey,
+ channel_type,
+ },
+ push_msat,
+ channel_reserve_satoshis,
+ })
+ }
+}
+
+impl Writeable for OpenChannelV2 {
+ fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
+ self.common_fields.chain_hash.write(w)?;
+ self.common_fields.temporary_channel_id.write(w)?;
+ self.funding_feerate_sat_per_1000_weight.write(w)?;
+ self.common_fields.commitment_feerate_sat_per_1000_weight.write(w)?;
+ self.common_fields.funding_satoshis.write(w)?;
+ self.common_fields.dust_limit_satoshis.write(w)?;
+ self.common_fields.max_htlc_value_in_flight_msat.write(w)?;
+ self.common_fields.htlc_minimum_msat.write(w)?;
+ self.common_fields.to_self_delay.write(w)?;
+ self.common_fields.max_accepted_htlcs.write(w)?;
+ self.locktime.write(w)?;
+ self.common_fields.funding_pubkey.write(w)?;
+ self.common_fields.revocation_basepoint.write(w)?;
+ self.common_fields.payment_basepoint.write(w)?;
+ self.common_fields.delayed_payment_basepoint.write(w)?;
+ self.common_fields.htlc_basepoint.write(w)?;
+ self.common_fields.first_per_commitment_point.write(w)?;
+ self.second_per_commitment_point.write(w)?;
+ self.common_fields.channel_flags.write(w)?;
+ encode_tlv_stream!(w, {
+ (0, self.common_fields.shutdown_scriptpubkey.as_ref().map(|s| WithoutLength(s)), option), // Don't encode length twice.
+ (1, self.common_fields.channel_type, option),
+ (2, self.require_confirmed_inputs, option),
+ });
+ Ok(())
+ }
+}
+
+impl Readable for OpenChannelV2 {
+ fn read<R: Read>(r: &mut R) -> Result<Self, DecodeError> {
+ let chain_hash: ChainHash = Readable::read(r)?;
+ let temporary_channel_id: ChannelId = Readable::read(r)?;
+ let funding_feerate_sat_per_1000_weight: u32 = Readable::read(r)?;
+ let commitment_feerate_sat_per_1000_weight: u32 = Readable::read(r)?;
+ let funding_satoshis: u64 = Readable::read(r)?;
+ let dust_limit_satoshis: u64 = Readable::read(r)?;
+ let max_htlc_value_in_flight_msat: u64 = Readable::read(r)?;
+ let htlc_minimum_msat: u64 = Readable::read(r)?;
+ let to_self_delay: u16 = Readable::read(r)?;
+ let max_accepted_htlcs: u16 = Readable::read(r)?;
+ let locktime: u32 = Readable::read(r)?;
+ let funding_pubkey: PublicKey = Readable::read(r)?;
+ let revocation_basepoint: PublicKey = Readable::read(r)?;
+ let payment_basepoint: PublicKey = Readable::read(r)?;
+ let delayed_payment_basepoint: PublicKey = Readable::read(r)?;
+ let htlc_basepoint: PublicKey = Readable::read(r)?;
+ let first_per_commitment_point: PublicKey = Readable::read(r)?;
+ let second_per_commitment_point: PublicKey = Readable::read(r)?;
+ let channel_flags: u8 = Readable::read(r)?;
+
+ let mut shutdown_scriptpubkey: Option<ScriptBuf> = None;
+ let mut channel_type: Option<ChannelTypeFeatures> = None;
+ let mut require_confirmed_inputs: Option<()> = None;
+ decode_tlv_stream!(r, {
+ (0, shutdown_scriptpubkey, (option, encoding: (ScriptBuf, WithoutLength))),
+ (1, channel_type, option),
+ (2, require_confirmed_inputs, option),
+ });
+ Ok(OpenChannelV2 {
+ common_fields: CommonOpenChannelFields {
+ chain_hash,
+ temporary_channel_id,
+ funding_satoshis,
+ dust_limit_satoshis,
+ max_htlc_value_in_flight_msat,
+ htlc_minimum_msat,
+ commitment_feerate_sat_per_1000_weight,
+ to_self_delay,
+ max_accepted_htlcs,
+ funding_pubkey,
+ revocation_basepoint,
+ payment_basepoint,
+ delayed_payment_basepoint,
+ htlc_basepoint,
+ first_per_commitment_point,
+ channel_flags,
+ shutdown_scriptpubkey,
+ channel_type,
+ },
+ funding_feerate_sat_per_1000_weight,
+ locktime,
+ second_per_commitment_point,
+ require_confirmed_inputs,
+ })
+ }
+}
#[cfg(not(taproot))]
impl_writeable_msg!(RevokeAndACK, {
use crate::ln::{PaymentPreimage, PaymentHash, PaymentSecret};
use crate::ln::ChannelId;
use crate::ln::features::{ChannelFeatures, ChannelTypeFeatures, InitFeatures, NodeFeatures};
- use crate::ln::msgs::{self, FinalOnionHopData, OnionErrorPacket};
+ use crate::ln::msgs::{self, FinalOnionHopData, OnionErrorPacket, CommonOpenChannelFields};
use crate::ln::msgs::SocketAddress;
use crate::routing::gossip::{NodeAlias, NodeId};
use crate::util::ser::{Writeable, Readable, ReadableArgs, Hostname, TransactionU16LenLimited};
let (_, pubkey_5) = get_keys_from!("0505050505050505050505050505050505050505050505050505050505050505", secp_ctx);
let (_, pubkey_6) = get_keys_from!("0606060606060606060606060606060606060606060606060606060606060606", secp_ctx);
let open_channel = msgs::OpenChannel {
- chain_hash: ChainHash::using_genesis_block(Network::Bitcoin),
- temporary_channel_id: ChannelId::from_bytes([2; 32]),
- funding_satoshis: 1311768467284833366,
+ common_fields: CommonOpenChannelFields {
+ chain_hash: ChainHash::using_genesis_block(Network::Bitcoin),
+ temporary_channel_id: ChannelId::from_bytes([2; 32]),
+ funding_satoshis: 1311768467284833366,
+ dust_limit_satoshis: 3608586615801332854,
+ max_htlc_value_in_flight_msat: 8517154655701053848,
+ htlc_minimum_msat: 2316138423780173,
+ commitment_feerate_sat_per_1000_weight: 821716,
+ to_self_delay: 49340,
+ max_accepted_htlcs: 49340,
+ funding_pubkey: pubkey_1,
+ revocation_basepoint: pubkey_2,
+ payment_basepoint: pubkey_3,
+ delayed_payment_basepoint: pubkey_4,
+ htlc_basepoint: pubkey_5,
+ first_per_commitment_point: pubkey_6,
+ channel_flags: if random_bit { 1 << 5 } else { 0 },
+ shutdown_scriptpubkey: if shutdown { Some(Address::p2pkh(&::bitcoin::PublicKey{compressed: true, inner: pubkey_1}, Network::Testnet).script_pubkey()) } else { None },
+ channel_type: if incl_chan_type { Some(ChannelTypeFeatures::empty()) } else { None },
+ },
push_msat: 2536655962884945560,
- dust_limit_satoshis: 3608586615801332854,
- max_htlc_value_in_flight_msat: 8517154655701053848,
channel_reserve_satoshis: 8665828695742877976,
- htlc_minimum_msat: 2316138423780173,
- feerate_per_kw: 821716,
- to_self_delay: 49340,
- max_accepted_htlcs: 49340,
- funding_pubkey: pubkey_1,
- revocation_basepoint: pubkey_2,
- payment_point: pubkey_3,
- delayed_payment_basepoint: pubkey_4,
- htlc_basepoint: pubkey_5,
- first_per_commitment_point: pubkey_6,
- channel_flags: if random_bit { 1 << 5 } else { 0 },
- shutdown_scriptpubkey: if shutdown { Some(Address::p2pkh(&::bitcoin::PublicKey{compressed: true, inner: pubkey_1}, Network::Testnet).script_pubkey()) } else { None },
- channel_type: if incl_chan_type { Some(ChannelTypeFeatures::empty()) } else { None },
};
let encoded_value = open_channel.encode();
let mut target_value = Vec::new();
let (_, pubkey_6) = get_keys_from!("0606060606060606060606060606060606060606060606060606060606060606", secp_ctx);
let (_, pubkey_7) = get_keys_from!("0707070707070707070707070707070707070707070707070707070707070707", secp_ctx);
let open_channelv2 = msgs::OpenChannelV2 {
- chain_hash: ChainHash::using_genesis_block(Network::Bitcoin),
- temporary_channel_id: ChannelId::from_bytes([2; 32]),
+ common_fields: CommonOpenChannelFields {
+ chain_hash: ChainHash::using_genesis_block(Network::Bitcoin),
+ temporary_channel_id: ChannelId::from_bytes([2; 32]),
+ commitment_feerate_sat_per_1000_weight: 821716,
+ funding_satoshis: 1311768467284833366,
+ dust_limit_satoshis: 3608586615801332854,
+ max_htlc_value_in_flight_msat: 8517154655701053848,
+ htlc_minimum_msat: 2316138423780173,
+ to_self_delay: 49340,
+ max_accepted_htlcs: 49340,
+ funding_pubkey: pubkey_1,
+ revocation_basepoint: pubkey_2,
+ payment_basepoint: pubkey_3,
+ delayed_payment_basepoint: pubkey_4,
+ htlc_basepoint: pubkey_5,
+ first_per_commitment_point: pubkey_6,
+ channel_flags: if random_bit { 1 << 5 } else { 0 },
+ shutdown_scriptpubkey: if shutdown { Some(Address::p2pkh(&::bitcoin::PublicKey{compressed: true, inner: pubkey_1}, Network::Testnet).script_pubkey()) } else { None },
+ channel_type: if incl_chan_type { Some(ChannelTypeFeatures::empty()) } else { None },
+ },
funding_feerate_sat_per_1000_weight: 821716,
- commitment_feerate_sat_per_1000_weight: 821716,
- funding_satoshis: 1311768467284833366,
- dust_limit_satoshis: 3608586615801332854,
- max_htlc_value_in_flight_msat: 8517154655701053848,
- htlc_minimum_msat: 2316138423780173,
- to_self_delay: 49340,
- max_accepted_htlcs: 49340,
locktime: 305419896,
- funding_pubkey: pubkey_1,
- revocation_basepoint: pubkey_2,
- payment_basepoint: pubkey_3,
- delayed_payment_basepoint: pubkey_4,
- htlc_basepoint: pubkey_5,
- first_per_commitment_point: pubkey_6,
second_per_commitment_point: pubkey_7,
- channel_flags: if random_bit { 1 << 5 } else { 0 },
- shutdown_scriptpubkey: if shutdown { Some(Address::p2pkh(&::bitcoin::PublicKey{compressed: true, inner: pubkey_1}, Network::Testnet).script_pubkey()) } else { None },
- channel_type: if incl_chan_type { Some(ChannelTypeFeatures::empty()) } else { None },
require_confirmed_inputs: if require_confirmed_inputs { Some(()) } else { None },
};
let encoded_value = open_channelv2.encode();
target_value.append(&mut <Vec<u8>>::from_hex("00").unwrap());
}
if shutdown {
- target_value.append(&mut <Vec<u8>>::from_hex("001b").unwrap()); // Type 0 + Length 27
target_value.append(&mut <Vec<u8>>::from_hex("001976a91479b000887626b294a914501a4cd226b58b23598388ac").unwrap());
}
if incl_chan_type {
// Any messages which are related to a specific channel generate an error message to let the
// peer know we don't care about channels.
fn handle_open_channel(&self, their_node_id: &PublicKey, msg: &msgs::OpenChannel) {
- ErroringMessageHandler::push_error(self, their_node_id, msg.temporary_channel_id);
+ ErroringMessageHandler::push_error(self, their_node_id, msg.common_fields.temporary_channel_id);
}
fn handle_accept_channel(&self, their_node_id: &PublicKey, msg: &msgs::AcceptChannel) {
ErroringMessageHandler::push_error(self, their_node_id, msg.temporary_channel_id);
}
fn handle_open_channel_v2(&self, their_node_id: &PublicKey, msg: &msgs::OpenChannelV2) {
- ErroringMessageHandler::push_error(self, their_node_id, msg.temporary_channel_id);
+ ErroringMessageHandler::push_error(self, their_node_id, msg.common_fields.temporary_channel_id);
}
fn handle_accept_channel_v2(&self, their_node_id: &PublicKey, msg: &msgs::AcceptChannelV2) {
self.enqueue_message(&mut *get_peer_for_forwarding!(node_id), msg);
},
MessageSendEvent::SendOpenChannel { ref node_id, ref msg } => {
- log_debug!(WithContext::from(&self.logger, Some(*node_id), Some(msg.temporary_channel_id)), "Handling SendOpenChannel event in peer_handler for node {} for channel {}",
+ log_debug!(WithContext::from(&self.logger, Some(*node_id), Some(msg.common_fields.temporary_channel_id)), "Handling SendOpenChannel event in peer_handler for node {} for channel {}",
log_pubkey!(node_id),
- &msg.temporary_channel_id);
+ &msg.common_fields.temporary_channel_id);
self.enqueue_message(&mut *get_peer_for_forwarding!(node_id), msg);
},
MessageSendEvent::SendOpenChannelV2 { ref node_id, ref msg } => {
- log_debug!(WithContext::from(&self.logger, Some(*node_id), Some(msg.temporary_channel_id)), "Handling SendOpenChannelV2 event in peer_handler for node {} for channel {}",
+ log_debug!(WithContext::from(&self.logger, Some(*node_id), Some(msg.common_fields.temporary_channel_id)), "Handling SendOpenChannelV2 event in peer_handler for node {} for channel {}",
log_pubkey!(node_id),
- &msg.temporary_channel_id);
+ &msg.common_fields.temporary_channel_id);
self.enqueue_message(&mut *get_peer_for_forwarding!(node_id), msg);
},
MessageSendEvent::SendFundingCreated { ref node_id, ref msg } => {
nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100000, 10001, 42, None, Some(scid_privacy_cfg)).unwrap();
let mut open_channel = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id());
- assert!(!open_channel.channel_type.as_ref().unwrap().supports_scid_privacy()); // we ignore `negotiate_scid_privacy` on pub channels
- open_channel.channel_type.as_mut().unwrap().set_scid_privacy_required();
- assert_eq!(open_channel.channel_flags & 1, 1); // The `announce_channel` bit is set.
+ assert!(!open_channel.common_fields.channel_type.as_ref().unwrap().supports_scid_privacy()); // we ignore `negotiate_scid_privacy` on pub channels
+ open_channel.common_fields.channel_type.as_mut().unwrap().set_scid_privacy_required();
+ assert_eq!(open_channel.common_fields.channel_flags & 1, 1); // The `announce_channel` bit is set.
nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), &open_channel);
let err = get_err_msg(&nodes[1], &nodes[0].node.get_our_node_id());
nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100000, 10001, 42, None, Some(scid_privacy_cfg)).unwrap();
let init_open_channel = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id());
- assert!(init_open_channel.channel_type.as_ref().unwrap().supports_scid_privacy());
+ assert!(init_open_channel.common_fields.channel_type.as_ref().unwrap().supports_scid_privacy());
assert!(nodes[0].node.list_channels()[0].channel_type.is_none()); // channel_type is none until counterparty accepts
// now simulate nodes[1] responding with an Error message, indicating it doesn't understand
// SCID alias.
nodes[0].node.handle_error(&nodes[1].node.get_our_node_id(), &msgs::ErrorMessage {
- channel_id: init_open_channel.temporary_channel_id,
+ channel_id: init_open_channel.common_fields.temporary_channel_id,
data: "Yo, no SCID aliases, no privacy here!".to_string()
});
assert!(nodes[0].node.list_channels()[0].channel_type.is_none()); // channel_type is none until counterparty accepts
let second_open_channel = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id());
- assert!(!second_open_channel.channel_type.as_ref().unwrap().supports_scid_privacy());
+ assert!(!second_open_channel.common_fields.channel_type.as_ref().unwrap().supports_scid_privacy());
nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), &second_open_channel);
nodes[0].node.handle_accept_channel(&nodes[1].node.get_our_node_id(), &get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id()));
nodes[1].node.create_channel(nodes[2].node.get_our_node_id(), 100_000, 10_000, 42, None, Some(no_announce_cfg)).unwrap();
let mut open_channel = get_event_msg!(nodes[1], MessageSendEvent::SendOpenChannel, nodes[2].node.get_our_node_id());
- assert!(open_channel.channel_type.as_ref().unwrap().requires_scid_privacy());
+ assert!(open_channel.common_fields.channel_type.as_ref().unwrap().requires_scid_privacy());
nodes[2].node.handle_open_channel(&nodes[1].node.get_our_node_id(), &open_channel);
let accept_channel = get_event_msg!(nodes[2], MessageSendEvent::SendAcceptChannel, nodes[1].node.get_our_node_id());
nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100000, 10001, 42, None, None).unwrap();
let mut open_channel_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id());
- open_channel_msg.channel_type = Some(channel_type_features.clone());
+ open_channel_msg.common_fields.channel_type = Some(channel_type_features.clone());
nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), &open_channel_msg);
let mut open_channel_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel,
nodes[1].node.get_our_node_id());
- open_channel_msg.channel_type = Some(channel_type_features.clone());
+ open_channel_msg.common_fields.channel_type = Some(channel_type_features.clone());
nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), &open_channel_msg);
let mut open_channel_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel,
nodes[1].node.get_our_node_id());
- open_channel_msg.channel_type = Some(channel_type_features);
+ open_channel_msg.common_fields.channel_type = Some(channel_type_features);
nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), &open_channel_msg);
.into_script();
nodes[0].node.handle_shutdown(&nodes[1].node.get_our_node_id(), &msgs::Shutdown {
- channel_id: open_chan.temporary_channel_id, scriptpubkey: script,
+ channel_id: open_chan.common_fields.temporary_channel_id, scriptpubkey: script,
});
check_closed_event!(nodes[0], 1, ClosureReason::CounterpartyCoopClosedUnfundedChannel, [nodes[1].node.get_our_node_id()], 1_000_000);
}
// Check script when handling an open_channel message
nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100000, 10001, 42, None, None).unwrap();
let mut open_channel = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id());
- open_channel.shutdown_scriptpubkey = Some(anysegwit_shutdown_script.clone());
+ open_channel.common_fields.shutdown_scriptpubkey = Some(anysegwit_shutdown_script.clone());
nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), &open_channel);
let events = nodes[1].node.get_and_clear_pending_msg_events();
// Use a segwit v0 script with an unsupported witness program
let mut open_channel = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id());
- open_channel.shutdown_scriptpubkey = Some(Builder::new().push_int(0)
+ open_channel.common_fields.shutdown_scriptpubkey = Some(Builder::new().push_int(0)
.push_slice(&[0, 0])
.into_script());
nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), &open_channel);