diff --git a/lightningd/opening_control.c b/lightningd/opening_control.c index f25e86f3d..622b9522c 100644 --- a/lightningd/opening_control.c +++ b/lightningd/opening_control.c @@ -1146,12 +1146,6 @@ static struct command_result *json_fund_channel_start(struct command *cmd, NULL)) return command_param_failed(); - if (amount_sat_greater(*amount, chainparams->max_funding)) - return command_fail(cmd, FUND_MAX_EXCEEDED, - "Amount exceeded %s", - type_to_string(tmpctx, struct amount_sat, - &chainparams->max_funding)); - if (push_msat && amount_msat_greater_sat(*push_msat, *amount)) return command_fail(cmd, FUND_CANNOT_AFFORD, "Requested to push_msat of %s is greater than " @@ -1199,6 +1193,20 @@ static struct command_result *json_fund_channel_start(struct command *cmd, return command_fail(cmd, LIGHTNINGD, "Already funding channel"); } + /* BOLT #2: + * - if both nodes advertised `option_support_large_channel`: + * - MAY set `funding_satoshis` greater than or equal to 2^24 satoshi. + * - otherwise: + * - MUST set `funding_satoshis` to less than 2^24 satoshi. + */ + if (!feature_negotiated(cmd->ld->feature_set, + peer->features, OPT_LARGE_CHANNELS) + && amount_sat_greater(*amount, chainparams->max_funding)) + return command_fail(cmd, FUND_MAX_EXCEEDED, + "Amount exceeded %s", + type_to_string(tmpctx, struct amount_sat, + &chainparams->max_funding)); + fc->push = push_msat ? *push_msat : AMOUNT_MSAT(0); fc->channel_flags = OUR_CHANNEL_FLAGS; if (!*announce_channel) { @@ -1207,7 +1215,6 @@ static struct command_result *json_fund_channel_start(struct command *cmd, type_to_string(fc, struct node_id, id)); } - assert(!amount_sat_greater(*amount, chainparams->max_funding)); peer->uncommitted_channel->fc = tal_steal(peer->uncommitted_channel, fc); fc->uc = peer->uncommitted_channel; diff --git a/openingd/openingd.c b/openingd/openingd.c index 82dcdb321..aed7ce18c 100644 --- a/openingd/openingd.c +++ b/openingd/openingd.c @@ -487,9 +487,13 @@ static bool setup_channel_funder(struct state *state) * * The sending node: *... - * - MUST set `funding_satoshis` to less than 2^24 satoshi. + * - if both nodes advertised `option_support_large_channel`: + * - MAY set `funding_satoshis` greater than or equal to 2^24 satoshi. + * - otherwise: + * - MUST set `funding_satoshis` to less than 2^24 satoshi. */ - if (amount_sat_greater(state->funding, chainparams->max_funding)) { + if (!feature_negotiated(state->fset, state->features, OPT_LARGE_CHANNELS) + && amount_sat_greater(state->funding, chainparams->max_funding)) { status_failed(STATUS_FAIL_MASTER_IO, "funding_satoshis must be < %s, not %s", type_to_string(tmpctx, struct amount_sat, @@ -969,11 +973,15 @@ static u8 *fundee_channel(struct state *state, const u8 *open_channel_msg) return NULL; } - /* BOLT #2 FIXME: + /* BOLT #2: * - * The receiving node ... MUST fail the channel if `funding-satoshis` - * is greater than or equal to 2^24 */ - if (amount_sat_greater(state->funding, chainparams->max_funding)) { + * The receiving node MUST fail the channel if: + *... + * - `funding_satoshis` is greater than or equal to 2^24 and the receiver does not support + * `option_support_large_channel`. */ + /* We choose to require *negotiation*, not just support! */ + if (!feature_negotiated(state->fset, state->features, OPT_LARGE_CHANNELS) + && amount_sat_greater(state->funding, chainparams->max_funding)) { negotiation_failed(state, false, "funding_satoshis %s too large", type_to_string(tmpctx, struct amount_sat, diff --git a/tests/test_connection.py b/tests/test_connection.py index 3e8020445..89a1d08a3 100644 --- a/tests/test_connection.py +++ b/tests/test_connection.py @@ -888,10 +888,6 @@ def test_funding_external_wallet_corners(node_factory, bitcoind): amount = 2**24 l1.fundwallet(amount + 10000000) - # Fail to open (too large) - with pytest.raises(RpcError, match=r'Amount exceeded 16777215'): - l1.rpc.fundchannel_start(l2.info['id'], amount) - amount = amount - 1 fake_txid = '929764844a8f9938b669a60a1d51a11c9e2613c7eb4776e4126f1f20c0a685c3' fake_txout = 0 @@ -907,6 +903,10 @@ def test_funding_external_wallet_corners(node_factory, bitcoind): with pytest.raises(RpcError, match=r'No channel funding in progress.'): l1.rpc.fundchannel_complete(l2.info['id'], fake_txid, fake_txout) + # Fail to open (too large) + with pytest.raises(RpcError, match=r'Amount exceeded 16777215'): + l1.rpc.fundchannel_start(l2.info['id'], amount + 1) + l1.rpc.fundchannel_start(l2.info['id'], amount) with pytest.raises(RpcError, match=r'Already funding channel'): l1.rpc.fundchannel(l2.info['id'], amount)