Skip to content

Commit cc88119

Browse files
committed
wip: Add channelmanager dual-funding support
1 parent f4cdabf commit cc88119

File tree

3 files changed

+476
-131
lines changed

3 files changed

+476
-131
lines changed

Diff for: lightning/src/ln/channel.rs

+164-126
Original file line numberDiff line numberDiff line change
@@ -1111,6 +1111,141 @@ pub(super) trait ChannelInterface<'a, Signer: WriteableEcdsaChannelSigner + 'a>
11111111
self.get_context().channel_transaction_parameters.is_outbound_from_holder
11121112
}
11131113

1114+
fn do_accept_channel_checks(&'a mut self, default_limits: &ChannelHandshakeLimits,
1115+
their_features: &InitFeatures, msg_dust_limit_satoshis: u64, msg_channel_reserve_satoshis: u64,
1116+
msg_to_self_delay: u16, msg_max_accepted_htlcs: u16, msg_htlc_minimum_msat: u64,
1117+
msg_max_htlc_value_in_flight_msat: u64, msg_minimum_depth: u32, msg_channel_type: &Option<ChannelTypeFeatures>,
1118+
msg_shutdown_scriptpubkey: &Option<Script>, msg_funding_pubkey: PublicKey, msg_revocation_basepoint: PublicKey,
1119+
msg_payment_point: PublicKey, msg_delayed_payment_basepoint: PublicKey, msg_htlc_basepoint: PublicKey,
1120+
msg_first_per_commitment_point: PublicKey,
1121+
) -> Result<(), ChannelError> {
1122+
let mut context = self.get_context_mut();
1123+
1124+
let peer_limits = if let Some(ref limits) = context.inbound_handshake_limits_override { limits } else { default_limits };
1125+
1126+
// Check sanity of message fields:
1127+
if context.channel_state != ChannelState::OurInitSent as u32 {
1128+
return Err(ChannelError::Close("Got an accept_channel message at a strange time".to_owned()));
1129+
}
1130+
if msg_dust_limit_satoshis > 21000000 * 100000000 {
1131+
return Err(ChannelError::Close(format!("Peer never wants payout outputs? dust_limit_satoshis was {}", msg_dust_limit_satoshis)));
1132+
}
1133+
if msg_channel_reserve_satoshis > context.channel_value_satoshis {
1134+
return Err(ChannelError::Close(format!("Bogus channel_reserve_satoshis ({}). Must not be greater than ({})", msg_channel_reserve_satoshis, context.channel_value_satoshis)));
1135+
}
1136+
if msg_dust_limit_satoshis > context.holder_selected_channel_reserve_satoshis {
1137+
return Err(ChannelError::Close(format!("Dust limit ({}) is bigger than our channel reserve ({})", msg_dust_limit_satoshis, context.holder_selected_channel_reserve_satoshis)));
1138+
}
1139+
if msg_channel_reserve_satoshis > context.channel_value_satoshis - context.holder_selected_channel_reserve_satoshis {
1140+
return Err(ChannelError::Close(format!("Bogus channel_reserve_satoshis ({}). Must not be greater than channel value minus our reserve ({})",
1141+
msg_channel_reserve_satoshis, context.channel_value_satoshis - context.holder_selected_channel_reserve_satoshis)));
1142+
}
1143+
let full_channel_value_msat = (context.channel_value_satoshis - msg_channel_reserve_satoshis) * 1000;
1144+
if msg_htlc_minimum_msat >= full_channel_value_msat {
1145+
return Err(ChannelError::Close(format!("Minimum htlc value ({}) is full channel value ({})", msg_htlc_minimum_msat, full_channel_value_msat)));
1146+
}
1147+
let max_delay_acceptable = u16::min(peer_limits.their_to_self_delay, MAX_LOCAL_BREAKDOWN_TIMEOUT);
1148+
if msg_to_self_delay > max_delay_acceptable {
1149+
return Err(ChannelError::Close(format!("They wanted our payments to be delayed by a needlessly long period. Upper limit: {}. Actual: {}", max_delay_acceptable, msg_to_self_delay)));
1150+
}
1151+
if msg_max_accepted_htlcs < 1 {
1152+
return Err(ChannelError::Close("0 max_accepted_htlcs makes for a useless channel".to_owned()));
1153+
}
1154+
if msg_max_accepted_htlcs > MAX_HTLCS {
1155+
return Err(ChannelError::Close(format!("max_accepted_htlcs was {}. It must not be larger than {}", msg_max_accepted_htlcs, MAX_HTLCS)));
1156+
}
1157+
1158+
// Now check against optional parameters as set by config...
1159+
if msg_htlc_minimum_msat > peer_limits.max_htlc_minimum_msat {
1160+
return Err(ChannelError::Close(format!("htlc_minimum_msat ({}) is higher than the user specified limit ({})", msg_htlc_minimum_msat, peer_limits.max_htlc_minimum_msat)));
1161+
}
1162+
if msg_max_htlc_value_in_flight_msat < peer_limits.min_max_htlc_value_in_flight_msat {
1163+
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, peer_limits.min_max_htlc_value_in_flight_msat)));
1164+
}
1165+
if msg_channel_reserve_satoshis > peer_limits.max_channel_reserve_satoshis {
1166+
return Err(ChannelError::Close(format!("channel_reserve_satoshis ({}) is higher than the user specified limit ({})", msg_channel_reserve_satoshis, peer_limits.max_channel_reserve_satoshis)));
1167+
}
1168+
if msg_max_accepted_htlcs < peer_limits.min_max_accepted_htlcs {
1169+
return Err(ChannelError::Close(format!("max_accepted_htlcs ({}) is less than the user specified limit ({})", msg_max_accepted_htlcs, peer_limits.min_max_accepted_htlcs)));
1170+
}
1171+
if msg_dust_limit_satoshis < MIN_CHAN_DUST_LIMIT_SATOSHIS {
1172+
return Err(ChannelError::Close(format!("dust_limit_satoshis ({}) is less than the implementation limit ({})", msg_dust_limit_satoshis, MIN_CHAN_DUST_LIMIT_SATOSHIS)));
1173+
}
1174+
if msg_dust_limit_satoshis > MAX_CHAN_DUST_LIMIT_SATOSHIS {
1175+
return Err(ChannelError::Close(format!("dust_limit_satoshis ({}) is greater than the implementation limit ({})", msg_dust_limit_satoshis, MAX_CHAN_DUST_LIMIT_SATOSHIS)));
1176+
}
1177+
if msg_minimum_depth > peer_limits.max_minimum_depth {
1178+
return Err(ChannelError::Close(format!("We consider the minimum depth to be unreasonably large. Expected minimum: ({}). Actual: ({})", peer_limits.max_minimum_depth, msg_minimum_depth)));
1179+
}
1180+
1181+
if let Some(ty) = &msg_channel_type {
1182+
if *ty != context.channel_type {
1183+
return Err(ChannelError::Close("Channel Type in accept_channel didn't match the one sent in open_channel.".to_owned()));
1184+
}
1185+
} else if their_features.supports_channel_type() {
1186+
// Assume they've accepted the channel type as they said they understand it.
1187+
} else {
1188+
let channel_type = ChannelTypeFeatures::from_init(&their_features);
1189+
if channel_type != ChannelTypeFeatures::only_static_remote_key() {
1190+
return Err(ChannelError::Close("Only static_remote_key is supported for non-negotiated channel types".to_owned()));
1191+
}
1192+
context.channel_type = channel_type;
1193+
}
1194+
1195+
let counterparty_shutdown_scriptpubkey = if their_features.supports_upfront_shutdown_script() {
1196+
match &msg_shutdown_scriptpubkey {
1197+
&Some(ref script) => {
1198+
// Peer is signaling upfront_shutdown and has opt-out with a 0-length script. We don't enforce anything
1199+
if script.len() == 0 {
1200+
None
1201+
} else {
1202+
if !script::is_bolt2_compliant(&script, their_features) {
1203+
return Err(ChannelError::Close(format!("Peer is signaling upfront_shutdown but has provided an unacceptable scriptpubkey format: {}", script)));
1204+
}
1205+
Some(script.clone())
1206+
}
1207+
},
1208+
// Peer is signaling upfront shutdown but don't opt-out with correct mechanism (a.k.a 0-length script). Peer looks buggy, we fail the channel
1209+
&None => {
1210+
return Err(ChannelError::Close("Peer is signaling upfront_shutdown but we don't get any script. Use 0-length script to opt-out".to_owned()));
1211+
}
1212+
}
1213+
} else { None };
1214+
1215+
context.counterparty_dust_limit_satoshis = msg_dust_limit_satoshis;
1216+
context.counterparty_max_htlc_value_in_flight_msat = cmp::min(msg_max_htlc_value_in_flight_msat, context.channel_value_satoshis * 1000);
1217+
context.counterparty_selected_channel_reserve_satoshis = Some(msg_channel_reserve_satoshis);
1218+
context.counterparty_htlc_minimum_msat = msg_htlc_minimum_msat;
1219+
context.counterparty_max_accepted_htlcs = msg_max_accepted_htlcs;
1220+
1221+
if peer_limits.trust_own_funding_0conf {
1222+
context.minimum_depth = Some(msg_minimum_depth);
1223+
} else {
1224+
context.minimum_depth = Some(cmp::max(1, msg_minimum_depth));
1225+
}
1226+
1227+
let counterparty_pubkeys = ChannelPublicKeys {
1228+
funding_pubkey: msg_funding_pubkey,
1229+
revocation_basepoint: msg_revocation_basepoint,
1230+
payment_point: msg_payment_point,
1231+
delayed_payment_basepoint: msg_delayed_payment_basepoint,
1232+
htlc_basepoint: msg_htlc_basepoint
1233+
};
1234+
1235+
context.channel_transaction_parameters.counterparty_parameters = Some(CounterpartyChannelTransactionParameters {
1236+
selected_contest_delay: msg_to_self_delay,
1237+
pubkeys: counterparty_pubkeys,
1238+
});
1239+
1240+
context.counterparty_cur_commitment_point = Some(msg_first_per_commitment_point);
1241+
context.counterparty_shutdown_scriptpubkey = counterparty_shutdown_scriptpubkey;
1242+
1243+
context.channel_state = ChannelState::OurInitSent as u32 | ChannelState::TheirInitSent as u32;
1244+
context.inbound_handshake_limits_override = None; // We're done enforcing limits on our peer's handshake now.
1245+
1246+
Ok(())
1247+
}
1248+
11141249
fn counterparty_funding_pubkey(&'a self) -> &PublicKey {
11151250
&self.get_counterparty_pubkeys().funding_pubkey
11161251
}
@@ -5808,132 +5943,12 @@ impl<Signer: WriteableEcdsaChannelSigner> OutboundV1Channel<Signer> {
58085943

58095944
// Message handlers
58105945
pub fn accept_channel(&mut self, msg: &msgs::AcceptChannel, default_limits: &ChannelHandshakeLimits, their_features: &InitFeatures) -> Result<(), ChannelError> {
5811-
let peer_limits = if let Some(ref limits) = self.context.inbound_handshake_limits_override { limits } else { default_limits };
5812-
5813-
// Check sanity of message fields:
5814-
if !self.is_outbound() {
5815-
return Err(ChannelError::Close("Got an accept_channel message from an inbound peer".to_owned()));
5816-
}
5817-
if self.context.channel_state != ChannelState::OurInitSent as u32 {
5818-
return Err(ChannelError::Close("Got an accept_channel message at a strange time".to_owned()));
5819-
}
5820-
if msg.dust_limit_satoshis > 21000000 * 100000000 {
5821-
return Err(ChannelError::Close(format!("Peer never wants payout outputs? dust_limit_satoshis was {}", msg.dust_limit_satoshis)));
5822-
}
5823-
if msg.channel_reserve_satoshis > self.context.channel_value_satoshis {
5824-
return Err(ChannelError::Close(format!("Bogus channel_reserve_satoshis ({}). Must not be greater than ({})", msg.channel_reserve_satoshis, self.context.channel_value_satoshis)));
5825-
}
5826-
if msg.dust_limit_satoshis > self.context.holder_selected_channel_reserve_satoshis {
5827-
return Err(ChannelError::Close(format!("Dust limit ({}) is bigger than our channel reserve ({})", msg.dust_limit_satoshis, self.context.holder_selected_channel_reserve_satoshis)));
5828-
}
5829-
if msg.channel_reserve_satoshis > self.context.channel_value_satoshis - self.context.holder_selected_channel_reserve_satoshis {
5830-
return Err(ChannelError::Close(format!("Bogus channel_reserve_satoshis ({}). Must not be greater than channel value minus our reserve ({})",
5831-
msg.channel_reserve_satoshis, self.context.channel_value_satoshis - self.context.holder_selected_channel_reserve_satoshis)));
5832-
}
5833-
let full_channel_value_msat = (self.context.channel_value_satoshis - msg.channel_reserve_satoshis) * 1000;
5834-
if msg.htlc_minimum_msat >= full_channel_value_msat {
5835-
return Err(ChannelError::Close(format!("Minimum htlc value ({}) is full channel value ({})", msg.htlc_minimum_msat, full_channel_value_msat)));
5836-
}
5837-
let max_delay_acceptable = u16::min(peer_limits.their_to_self_delay, MAX_LOCAL_BREAKDOWN_TIMEOUT);
5838-
if msg.to_self_delay > max_delay_acceptable {
5839-
return Err(ChannelError::Close(format!("They wanted our payments to be delayed by a needlessly long period. Upper limit: {}. Actual: {}", max_delay_acceptable, msg.to_self_delay)));
5840-
}
5841-
if msg.max_accepted_htlcs < 1 {
5842-
return Err(ChannelError::Close("0 max_accepted_htlcs makes for a useless channel".to_owned()));
5843-
}
5844-
if msg.max_accepted_htlcs > MAX_HTLCS {
5845-
return Err(ChannelError::Close(format!("max_accepted_htlcs was {}. It must not be larger than {}", msg.max_accepted_htlcs, MAX_HTLCS)));
5846-
}
5847-
5848-
// Now check against optional parameters as set by config...
5849-
if msg.htlc_minimum_msat > peer_limits.max_htlc_minimum_msat {
5850-
return Err(ChannelError::Close(format!("htlc_minimum_msat ({}) is higher than the user specified limit ({})", msg.htlc_minimum_msat, peer_limits.max_htlc_minimum_msat)));
5851-
}
5852-
if msg.max_htlc_value_in_flight_msat < peer_limits.min_max_htlc_value_in_flight_msat {
5853-
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, peer_limits.min_max_htlc_value_in_flight_msat)));
5854-
}
5855-
if msg.channel_reserve_satoshis > peer_limits.max_channel_reserve_satoshis {
5856-
return Err(ChannelError::Close(format!("channel_reserve_satoshis ({}) is higher than the user specified limit ({})", msg.channel_reserve_satoshis, peer_limits.max_channel_reserve_satoshis)));
5857-
}
5858-
if msg.max_accepted_htlcs < peer_limits.min_max_accepted_htlcs {
5859-
return Err(ChannelError::Close(format!("max_accepted_htlcs ({}) is less than the user specified limit ({})", msg.max_accepted_htlcs, peer_limits.min_max_accepted_htlcs)));
5860-
}
5861-
if msg.dust_limit_satoshis < MIN_CHAN_DUST_LIMIT_SATOSHIS {
5862-
return Err(ChannelError::Close(format!("dust_limit_satoshis ({}) is less than the implementation limit ({})", msg.dust_limit_satoshis, MIN_CHAN_DUST_LIMIT_SATOSHIS)));
5863-
}
5864-
if msg.dust_limit_satoshis > MAX_CHAN_DUST_LIMIT_SATOSHIS {
5865-
return Err(ChannelError::Close(format!("dust_limit_satoshis ({}) is greater than the implementation limit ({})", msg.dust_limit_satoshis, MAX_CHAN_DUST_LIMIT_SATOSHIS)));
5866-
}
5867-
if msg.minimum_depth > peer_limits.max_minimum_depth {
5868-
return Err(ChannelError::Close(format!("We consider the minimum depth to be unreasonably large. Expected minimum: ({}). Actual: ({})", peer_limits.max_minimum_depth, msg.minimum_depth)));
5869-
}
5870-
5871-
if let Some(ty) = &msg.channel_type {
5872-
if *ty != self.context.channel_type {
5873-
return Err(ChannelError::Close("Channel Type in accept_channel didn't match the one sent in open_channel.".to_owned()));
5874-
}
5875-
} else if their_features.supports_channel_type() {
5876-
// Assume they've accepted the channel type as they said they understand it.
5877-
} else {
5878-
let channel_type = ChannelTypeFeatures::from_init(&their_features);
5879-
if channel_type != ChannelTypeFeatures::only_static_remote_key() {
5880-
return Err(ChannelError::Close("Only static_remote_key is supported for non-negotiated channel types".to_owned()));
5881-
}
5882-
self.context.channel_type = channel_type;
5883-
}
5884-
5885-
let counterparty_shutdown_scriptpubkey = if their_features.supports_upfront_shutdown_script() {
5886-
match &msg.shutdown_scriptpubkey {
5887-
&Some(ref script) => {
5888-
// Peer is signaling upfront_shutdown and has opt-out with a 0-length script. We don't enforce anything
5889-
if script.len() == 0 {
5890-
None
5891-
} else {
5892-
if !script::is_bolt2_compliant(&script, their_features) {
5893-
return Err(ChannelError::Close(format!("Peer is signaling upfront_shutdown but has provided an unacceptable scriptpubkey format: {}", script)));
5894-
}
5895-
Some(script.clone())
5896-
}
5897-
},
5898-
// Peer is signaling upfront shutdown but don't opt-out with correct mechanism (a.k.a 0-length script). Peer looks buggy, we fail the channel
5899-
&None => {
5900-
return Err(ChannelError::Close("Peer is signaling upfront_shutdown but we don't get any script. Use 0-length script to opt-out".to_owned()));
5901-
}
5902-
}
5903-
} else { None };
5904-
5905-
self.context.counterparty_dust_limit_satoshis = msg.dust_limit_satoshis;
5906-
self.context.counterparty_max_htlc_value_in_flight_msat = cmp::min(msg.max_htlc_value_in_flight_msat, self.context.channel_value_satoshis * 1000);
5907-
self.context.counterparty_selected_channel_reserve_satoshis = Some(msg.channel_reserve_satoshis);
5908-
self.context.counterparty_htlc_minimum_msat = msg.htlc_minimum_msat;
5909-
self.context.counterparty_max_accepted_htlcs = msg.max_accepted_htlcs;
5910-
5911-
if peer_limits.trust_own_funding_0conf {
5912-
self.context.minimum_depth = Some(msg.minimum_depth);
5913-
} else {
5914-
self.context.minimum_depth = Some(cmp::max(1, msg.minimum_depth));
5915-
}
5916-
5917-
let counterparty_pubkeys = ChannelPublicKeys {
5918-
funding_pubkey: msg.funding_pubkey,
5919-
revocation_basepoint: msg.revocation_basepoint,
5920-
payment_point: msg.payment_point,
5921-
delayed_payment_basepoint: msg.delayed_payment_basepoint,
5922-
htlc_basepoint: msg.htlc_basepoint
5923-
};
5924-
5925-
self.context.channel_transaction_parameters.counterparty_parameters = Some(CounterpartyChannelTransactionParameters {
5926-
selected_contest_delay: msg.to_self_delay,
5927-
pubkeys: counterparty_pubkeys,
5928-
});
5929-
5930-
self.context.counterparty_cur_commitment_point = Some(msg.first_per_commitment_point);
5931-
self.context.counterparty_shutdown_scriptpubkey = counterparty_shutdown_scriptpubkey;
5932-
5933-
self.context.channel_state = ChannelState::OurInitSent as u32 | ChannelState::TheirInitSent as u32;
5934-
self.context.inbound_handshake_limits_override = None; // We're done enforcing limits on our peer's handshake now.
5935-
5936-
Ok(())
5946+
self.do_accept_channel_checks(
5947+
default_limits, their_features, msg.dust_limit_satoshis, msg.channel_reserve_satoshis,
5948+
msg.to_self_delay, msg.max_accepted_htlcs, msg.htlc_minimum_msat,
5949+
msg.max_htlc_value_in_flight_msat, msg.minimum_depth, &msg.channel_type,
5950+
&msg.shutdown_scriptpubkey, msg.funding_pubkey, msg.revocation_basepoint, msg.payment_point,
5951+
msg.delayed_payment_basepoint, msg.htlc_basepoint, msg.first_per_commitment_point)
59375952
}
59385953
}
59395954

@@ -6752,6 +6767,21 @@ impl<Signer: WriteableEcdsaChannelSigner> OutboundV2Channel<Signer> {
67526767
require_confirmed_inputs: if self.context.we_require_confirmed_inputs { Some(()) } else { None },
67536768
}
67546769
}
6770+
6771+
pub fn accept_channel_v2(&mut self, msg: &msgs::AcceptChannelV2, default_limits: &ChannelHandshakeLimits,
6772+
their_features: &InitFeatures) -> Result<(), ChannelError> {
6773+
self.do_accept_channel_checks(
6774+
default_limits, their_features, msg.dust_limit_satoshis, Self::get_v2_channel_reserve_satoshis(
6775+
msg.funding_satoshis + self.context.our_funding_satoshis, msg.dust_limit_satoshis),
6776+
msg.to_self_delay, msg.max_accepted_htlcs, msg.htlc_minimum_msat,
6777+
msg.max_htlc_value_in_flight_msat, msg.minimum_depth, &msg.channel_type,
6778+
&msg.shutdown_scriptpubkey, msg.funding_pubkey, msg.revocation_basepoint, msg.payment_basepoint,
6779+
msg.delayed_payment_basepoint, msg.htlc_basepoint, msg.first_per_commitment_point)?;
6780+
6781+
// TODO(dual_funding): V2 Establishment Checks
6782+
6783+
Ok(())
6784+
}
67556785
}
67566786

67576787
// A not-yet-funded inbound (from counterparty) channel using V2 channel establishment.
@@ -7123,6 +7153,14 @@ impl<Signer: WriteableEcdsaChannelSigner> InboundV2Channel<Signer> {
71237153
Ok(chan)
71247154
}
71257155

7156+
pub fn set_funding_change_scriptpubkey(&mut self, change_script_pubkey: Script) {
7157+
self.context.our_change_script_pubkey = change_script_pubkey;
7158+
}
7159+
7160+
pub fn inbound_is_awaiting_accept(&self) -> bool {
7161+
self.context.common.inbound_awaiting_accept
7162+
}
7163+
71267164
/// Marks an inbound channel as accepted and generates a [`msgs::AcceptChannelV2`] message which
71277165
/// should be sent back to the counterparty node.
71287166
///

0 commit comments

Comments
 (0)