Skip to content

Commit f53d13b

Browse files
authored
Merge pull request #1425 from valentinewallace/2021-04-wumbo
Wumbo!
2 parents 62edee5 + 5cfe19e commit f53d13b

File tree

5 files changed

+77
-22
lines changed

5 files changed

+77
-22
lines changed

lightning/src/ln/channel.rs

+23-12
Original file line numberDiff line numberDiff line change
@@ -745,9 +745,13 @@ pub const COMMITMENT_TX_WEIGHT_PER_HTLC: u64 = 172;
745745

746746
pub const ANCHOR_OUTPUT_VALUE_SATOSHI: u64 = 330;
747747

748-
/// Maximum `funding_satoshis` value, according to the BOLT #2 specification
749-
/// it's 2^24.
750-
pub const MAX_FUNDING_SATOSHIS: u64 = 1 << 24;
748+
/// Maximum `funding_satoshis` value according to the BOLT #2 specification, if
749+
/// `option_support_large_channel` (aka wumbo channels) is not supported.
750+
/// It's 2^24 - 1.
751+
pub const MAX_FUNDING_SATOSHIS_NO_WUMBO: u64 = (1 << 24) - 1;
752+
753+
/// Total bitcoin supply in satoshis.
754+
pub const TOTAL_BITCOIN_SUPPLY_SATOSHIS: u64 = 21_000_000 * 1_0000_0000;
751755

752756
/// The maximum network dust limit for standard script formats. This currently represents the
753757
/// minimum output value for a P2SH output before Bitcoin Core 22 considers the entire
@@ -861,8 +865,11 @@ impl<Signer: Sign> Channel<Signer> {
861865
let holder_signer = keys_provider.get_channel_signer(false, channel_value_satoshis);
862866
let pubkeys = holder_signer.pubkeys().clone();
863867

864-
if channel_value_satoshis >= MAX_FUNDING_SATOSHIS {
865-
return Err(APIError::APIMisuseError{err: format!("funding_value must be smaller than {}, it was {}", MAX_FUNDING_SATOSHIS, channel_value_satoshis)});
868+
if !their_features.supports_wumbo() && channel_value_satoshis > MAX_FUNDING_SATOSHIS_NO_WUMBO {
869+
return Err(APIError::APIMisuseError{err: format!("funding_value must not exceed {}, it was {}", MAX_FUNDING_SATOSHIS_NO_WUMBO, channel_value_satoshis)});
870+
}
871+
if channel_value_satoshis >= TOTAL_BITCOIN_SUPPLY_SATOSHIS {
872+
return Err(APIError::APIMisuseError{err: format!("funding_value must be smaller than the total bitcoin supply, it was {}", channel_value_satoshis)});
866873
}
867874
let channel_value_msat = channel_value_satoshis * 1000;
868875
if push_msat > channel_value_msat {
@@ -1087,8 +1094,11 @@ impl<Signer: Sign> Channel<Signer> {
10871094
}
10881095

10891096
// Check sanity of message fields:
1090-
if msg.funding_satoshis >= MAX_FUNDING_SATOSHIS {
1091-
return Err(ChannelError::Close(format!("Funding must be smaller than {}. It was {}", MAX_FUNDING_SATOSHIS, msg.funding_satoshis)));
1097+
if msg.funding_satoshis > config.peer_channel_config_limits.max_funding_satoshis {
1098+
return Err(ChannelError::Close(format!("Per our config, funding must be at most {}. It was {}", config.peer_channel_config_limits.max_funding_satoshis, msg.funding_satoshis)));
1099+
}
1100+
if msg.funding_satoshis >= TOTAL_BITCOIN_SUPPLY_SATOSHIS {
1101+
return Err(ChannelError::Close(format!("Funding must be smaller than the total bitcoin supply. It was {}", msg.funding_satoshis)));
10921102
}
10931103
if msg.channel_reserve_satoshis > msg.funding_satoshis {
10941104
return Err(ChannelError::Close(format!("Bogus channel_reserve_satoshis ({}). Must be not greater than funding_satoshis: {}", msg.channel_reserve_satoshis, msg.funding_satoshis)));
@@ -4120,7 +4130,7 @@ impl<Signer: Sign> Channel<Signer> {
41204130
if !self.pending_inbound_htlcs.is_empty() || !self.pending_outbound_htlcs.is_empty() {
41214131
return Err(ChannelError::Close("Remote end sent us a closing_signed while there were still pending HTLCs".to_owned()));
41224132
}
4123-
if msg.fee_satoshis > 21_000_000 * 1_0000_0000 { //this is required to stop potential overflow in build_closing_transaction
4133+
if msg.fee_satoshis > TOTAL_BITCOIN_SUPPLY_SATOSHIS { // this is required to stop potential overflow in build_closing_transaction
41244134
return Err(ChannelError::Close("Remote tried to send us a closing tx with > 21 million BTC fee".to_owned()));
41254135
}
41264136

@@ -6327,7 +6337,7 @@ mod tests {
63276337
use ln::PaymentHash;
63286338
use ln::channelmanager::{HTLCSource, PaymentId};
63296339
use ln::channel::{Channel, InboundHTLCOutput, OutboundHTLCOutput, InboundHTLCState, OutboundHTLCState, HTLCCandidate, HTLCInitiator};
6330-
use ln::channel::MAX_FUNDING_SATOSHIS;
6340+
use ln::channel::{MAX_FUNDING_SATOSHIS_NO_WUMBO, TOTAL_BITCOIN_SUPPLY_SATOSHIS};
63316341
use ln::features::InitFeatures;
63326342
use ln::msgs::{ChannelUpdate, DataLossProtect, DecodeError, OptionalField, UnsignedChannelUpdate};
63336343
use ln::script::ShutdownScript;
@@ -6363,9 +6373,10 @@ mod tests {
63636373
}
63646374

63656375
#[test]
6366-
fn test_max_funding_satoshis() {
6367-
assert!(MAX_FUNDING_SATOSHIS <= 21_000_000 * 100_000_000,
6368-
"MAX_FUNDING_SATOSHIS is greater than all satoshis in existence");
6376+
fn test_max_funding_satoshis_no_wumbo() {
6377+
assert_eq!(TOTAL_BITCOIN_SUPPLY_SATOSHIS, 21_000_000 * 100_000_000);
6378+
assert!(MAX_FUNDING_SATOSHIS_NO_WUMBO <= TOTAL_BITCOIN_SUPPLY_SATOSHIS,
6379+
"MAX_FUNDING_SATOSHIS_NO_WUMBO is greater than all satoshis in existence");
63696380
}
63706381

63716382
#[test]

lightning/src/ln/channelmanager.rs

-2
Original file line numberDiff line numberDiff line change
@@ -1516,8 +1516,6 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
15161516
///
15171517
/// Non-proportional fees are fixed according to our risk using the provided fee estimator.
15181518
///
1519-
/// panics if channel_value_satoshis is >= `MAX_FUNDING_SATOSHIS`!
1520-
///
15211519
/// Users need to notify the new ChannelManager when a new block is connected or
15221520
/// disconnected using its `block_connected` and `block_disconnected` methods, starting
15231521
/// from after `params.latest_hash`.

lightning/src/ln/features.rs

+21-4
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ mod sealed {
137137
// Byte 1
138138
,
139139
// Byte 2
140-
BasicMPP,
140+
BasicMPP | Wumbo,
141141
// Byte 3
142142
ShutdownAnySegwit,
143143
// Byte 4
@@ -169,7 +169,7 @@ mod sealed {
169169
// Byte 1
170170
,
171171
// Byte 2
172-
BasicMPP,
172+
BasicMPP | Wumbo,
173173
// Byte 3
174174
ShutdownAnySegwit,
175175
// Byte 4
@@ -390,6 +390,9 @@ mod sealed {
390390
define_feature!(17, BasicMPP, [InitContext, NodeContext, InvoiceContext],
391391
"Feature flags for `basic_mpp`.", set_basic_mpp_optional, set_basic_mpp_required,
392392
supports_basic_mpp, requires_basic_mpp);
393+
define_feature!(19, Wumbo, [InitContext, NodeContext],
394+
"Feature flags for `option_support_large_channel` (aka wumbo channels).", set_wumbo_optional, set_wumbo_required,
395+
supports_wumbo, requires_wumbo);
393396
define_feature!(27, ShutdownAnySegwit, [InitContext, NodeContext],
394397
"Feature flags for `opt_shutdown_anysegwit`.", set_shutdown_any_segwit_optional,
395398
set_shutdown_any_segwit_required, supports_shutdown_anysegwit, requires_shutdown_anysegwit);
@@ -740,6 +743,15 @@ impl<T: sealed::ShutdownAnySegwit> Features<T> {
740743
self
741744
}
742745
}
746+
747+
impl<T: sealed::Wumbo> Features<T> {
748+
#[cfg(test)]
749+
pub(crate) fn clear_wumbo(mut self) -> Self {
750+
<T as sealed::Wumbo>::clear_bits(&mut self.flags);
751+
self
752+
}
753+
}
754+
743755
macro_rules! impl_feature_len_prefixed_write {
744756
($features: ident) => {
745757
impl Writeable for $features {
@@ -843,6 +855,11 @@ mod tests {
843855
assert!(!InitFeatures::known().requires_scid_privacy());
844856
assert!(!NodeFeatures::known().requires_scid_privacy());
845857

858+
assert!(InitFeatures::known().supports_wumbo());
859+
assert!(NodeFeatures::known().supports_wumbo());
860+
assert!(!InitFeatures::known().requires_wumbo());
861+
assert!(!NodeFeatures::known().requires_wumbo());
862+
846863
let mut init_features = InitFeatures::known();
847864
assert!(init_features.initial_routing_sync());
848865
init_features.clear_initial_routing_sync();
@@ -878,14 +895,14 @@ mod tests {
878895
// Check that the flags are as expected:
879896
// - option_data_loss_protect
880897
// - var_onion_optin (req) | static_remote_key (req) | payment_secret(req)
881-
// - basic_mpp
898+
// - basic_mpp | wumbo
882899
// - opt_shutdown_anysegwit
883900
// -
884901
// - option_channel_type | option_scid_alias
885902
assert_eq!(node_features.flags.len(), 6);
886903
assert_eq!(node_features.flags[0], 0b00000010);
887904
assert_eq!(node_features.flags[1], 0b01010001);
888-
assert_eq!(node_features.flags[2], 0b00000010);
905+
assert_eq!(node_features.flags[2], 0b00001010);
889906
assert_eq!(node_features.flags[3], 0b00001000);
890907
assert_eq!(node_features.flags[4], 0b00000000);
891908
assert_eq!(node_features.flags[5], 0b10100000);

lightning/src/ln/functional_tests.rs

+25-3
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,12 @@ use ln::chan_utils::CommitmentTransaction;
5858
#[test]
5959
fn test_insane_channel_opens() {
6060
// Stand up a network of 2 nodes
61+
use ln::channel::TOTAL_BITCOIN_SUPPLY_SATOSHIS;
62+
let mut cfg = UserConfig::default();
63+
cfg.peer_channel_config_limits.max_funding_satoshis = TOTAL_BITCOIN_SUPPLY_SATOSHIS + 1;
6164
let chanmon_cfgs = create_chanmon_cfgs(2);
6265
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
63-
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
66+
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, Some(cfg)]);
6467
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
6568

6669
// Instantiate channel parameters where we push the maximum msats given our
@@ -92,11 +95,11 @@ fn test_insane_channel_opens() {
9295
} else { assert!(false); }
9396
};
9497

95-
use ln::channel::MAX_FUNDING_SATOSHIS;
9698
use ln::channelmanager::MAX_LOCAL_BREAKDOWN_TIMEOUT;
9799

98100
// Test all mutations that would make the channel open message insane
99-
insane_open_helper(format!("Funding must be smaller than {}. It was {}", MAX_FUNDING_SATOSHIS, MAX_FUNDING_SATOSHIS).as_str(), |mut msg| { msg.funding_satoshis = MAX_FUNDING_SATOSHIS; msg });
101+
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 });
102+
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 });
100103

101104
insane_open_helper("Bogus channel_reserve_satoshis", |mut msg| { msg.channel_reserve_satoshis = msg.funding_satoshis + 1; msg });
102105

@@ -113,6 +116,25 @@ fn test_insane_channel_opens() {
113116
insane_open_helper("max_accepted_htlcs was 484. It must not be larger than 483", |mut msg| { msg.max_accepted_htlcs = 484; msg });
114117
}
115118

119+
#[test]
120+
fn test_funding_exceeds_no_wumbo_limit() {
121+
// Test that if a peer does not support wumbo channels, we'll refuse to open a wumbo channel to
122+
// them.
123+
use ln::channel::MAX_FUNDING_SATOSHIS_NO_WUMBO;
124+
let chanmon_cfgs = create_chanmon_cfgs(2);
125+
let mut node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
126+
node_cfgs[1].features = InitFeatures::known().clear_wumbo();
127+
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
128+
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
129+
130+
match nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), MAX_FUNDING_SATOSHIS_NO_WUMBO + 1, 0, 42, None) {
131+
Err(APIError::APIMisuseError { err }) => {
132+
assert_eq!(format!("funding_value must not exceed {}, it was {}", MAX_FUNDING_SATOSHIS_NO_WUMBO, MAX_FUNDING_SATOSHIS_NO_WUMBO + 1), err);
133+
},
134+
_ => panic!()
135+
}
136+
}
137+
116138
fn do_test_counterparty_no_reserve(send_from_initiator: bool) {
117139
// A peer providing a channel_reserve_satoshis of 0 (or less than our dust limit) is insecure,
118140
// but only for them. Because some LSPs do it with some level of trust of the clients (for a

lightning/src/util/config.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
//! Various user-configurable channel limits and settings which ChannelManager
1111
//! applies for you.
1212
13+
use ln::channel::MAX_FUNDING_SATOSHIS_NO_WUMBO;
1314
use ln::channelmanager::{BREAKDOWN_TIMEOUT, MAX_LOCAL_BREAKDOWN_TIMEOUT};
1415

1516
/// Configuration we set when applicable.
@@ -95,11 +96,16 @@ impl Default for ChannelHandshakeConfig {
9596
/// are applied mostly only to incoming channels that's not much of a problem.
9697
#[derive(Copy, Clone, Debug)]
9798
pub struct ChannelHandshakeLimits {
98-
/// Minimum allowed satoshis when a channel is funded, this is supplied by the sender and so
99+
/// Minimum allowed satoshis when a channel is funded. This is supplied by the sender and so
99100
/// only applies to inbound channels.
100101
///
101102
/// Default value: 0.
102103
pub min_funding_satoshis: u64,
104+
/// Maximum allowed satoshis when a channel is funded. This is supplied by the sender and so
105+
/// only applies to inbound channels.
106+
///
107+
/// Default value: 2^24 - 1.
108+
pub max_funding_satoshis: u64,
103109
/// The remote node sets a limit on the minimum size of HTLCs we can send to them. This allows
104110
/// you to limit the maximum minimum-size they can require.
105111
///
@@ -151,6 +157,7 @@ impl Default for ChannelHandshakeLimits {
151157
fn default() -> Self {
152158
ChannelHandshakeLimits {
153159
min_funding_satoshis: 0,
160+
max_funding_satoshis: MAX_FUNDING_SATOSHIS_NO_WUMBO,
154161
max_htlc_minimum_msat: <u64>::max_value(),
155162
min_max_htlc_value_in_flight_msat: 0,
156163
max_channel_reserve_satoshis: <u64>::max_value(),

0 commit comments

Comments
 (0)