diff --git a/doc/lightning-listpeers.7.md b/doc/lightning-listpeers.7.md index 569f53e58..9835e0e25 100644 --- a/doc/lightning-listpeers.7.md +++ b/doc/lightning-listpeers.7.md @@ -370,7 +370,7 @@ SEE ALSO -------- lightning-connect(7), lightning-fundchannel\_start(7), -lightning-setchannelfee(7) +lightning-setchannel(7) RESOURCES --------- diff --git a/doc/lightning-setchannelfee.7.md b/doc/lightning-setchannelfee.7.md index 7f94d4872..b0f97ca3e 100644 --- a/doc/lightning-setchannelfee.7.md +++ b/doc/lightning-setchannelfee.7.md @@ -4,7 +4,7 @@ lightning-setchannelfee -- Command for setting specific routing fees on a lightn SYNOPSIS -------- -**setchannelfee** *id* [*base*] [*ppm*] [*enforcedelay*] +(DEPRECATED) **setchannelfee** *id* [*base*] [*ppm*] [*enforcedelay*] DESCRIPTION ----------- @@ -73,8 +73,7 @@ responsible for the c-lightning project. SEE ALSO -------- -lightningd-config(5), lightning-fundchannel(7), -lightning-listchannels(7), lightning-listpeers(7) +lightningd-setchannel(7) RESOURCES --------- diff --git a/doc/lightningd-config.5.md b/doc/lightningd-config.5.md index bc45c789a..9fe83e46f 100644 --- a/doc/lightningd-config.5.md +++ b/doc/lightningd-config.5.md @@ -236,14 +236,14 @@ Default: 1000. The base fee to charge for every payment which passes through. Note that millisatoshis are a very, very small unit! Changing this value will only affect new channels and not existing ones. If you want to change fees for existing channels, use the RPC call -lightning-setchannelfee(7). +lightning-setchannel(7). **fee-per-satoshi**=*MILLIONTHS* Default: 10 (0.001%). This is the proportional fee to charge for every payment which passes through. As percentages are too coarse, it's in millionths, so 10000 is 1%, 1000 is 0.1%. Changing this value will only affect new channels and not existing ones. If you want to change fees -for existing channels, use the RPC call lightning-setchannelfee(7). +for existing channels, use the RPC call lightning-setchannel(7). **min-capacity-sat**=*SATOSHI* Default: 10000. This value defines the minimal effective channel @@ -563,7 +563,7 @@ actually implementing these options. SEE ALSO -------- -lightning-listconfigs(7) lightning-setchannelfee(7) lightningd(8) +lightning-listconfigs(7) lightning-setchannel(7) lightningd(8) lightning-hsmtool(8) RESOURCES diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index 675b00b77..f25dc0006 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -2135,7 +2135,8 @@ static const struct json_command setchannelfee_command = { "and a {ppm} (proportional per millionth) value. " "If values for {base} or {ppm} are left out, defaults will be used. " "{base} can also be defined in other units, for example '1sat'. " - "If {id} is 'all', the fees will be applied for all channels. " + "If {id} is 'all', the fees will be applied for all channels. ", + true /* deprecated */ }; AUTODATA(json_command, &setchannelfee_command); diff --git a/tests/test_gossip.py b/tests/test_gossip.py index 4899f5971..9e6b463ce 100644 --- a/tests/test_gossip.py +++ b/tests/test_gossip.py @@ -1583,7 +1583,7 @@ def setup_gossip_store_test(node_factory, bitcoind): wait_for(lambda: ['alias' in n for n in l2.rpc.listnodes()['nodes']] == [True, True]) # Now, replace the one channel_update, so it's past the node announcements. - l2.rpc.setchannelfee(l3.info['id'], 20, 1000) + l2.rpc.setchannel(l3.info['id'], 20, 1000) # Old base feerate is 1. wait_for(lambda: sum([c['base_fee_millisatoshi'] for c in l2.rpc.listchannels()['channels']]) == 21) @@ -1592,12 +1592,12 @@ def setup_gossip_store_test(node_factory, bitcoind): # Now insert channel_update for previous channel; now they're both past the # node announcements. - l3.rpc.setchannelfee(l2.info['id'], 20, 1000) + l3.rpc.setchannel(l2.info['id'], feebase=20, feeppm=1000) wait_for(lambda: [c['base_fee_millisatoshi'] for c in l2.rpc.listchannels(scid23)['channels']] == [20, 20]) # Replace both (private) updates for scid12. - l1.rpc.setchannelfee(l2.info['id'], 20, 1000) - l2.rpc.setchannelfee(l1.info['id'], 20, 1000) + l1.rpc.setchannel(l2.info['id'], feebase=20, feeppm=1000) + l2.rpc.setchannel(l1.info['id'], feebase=20, feeppm=1000) wait_for(lambda: [c['base_fee_millisatoshi'] for c in l2.rpc.listchannels(scid12)['channels']] == [20, 20]) # Records in store now looks (something) like: diff --git a/tests/test_pay.py b/tests/test_pay.py index ea450a8eb..1716f4d58 100644 --- a/tests/test_pay.py +++ b/tests/test_pay.py @@ -1854,7 +1854,7 @@ def test_pay_routeboost(node_factory, bitcoind, compat): @pytest.mark.developer("updates are delayed without --dev-fast-gossip") -def test_setchannelfee_usage(node_factory, bitcoind): +def test_setchannel_usage(node_factory, bitcoind): # TEST SETUP # # [l1] ---> [l2] (channel funded) @@ -1862,7 +1862,7 @@ def test_setchannelfee_usage(node_factory, bitcoind): # o - - > [l3] (only connected) # # - check initial SQL values - # - check setchannelfee can be used + # - check setchannel can be used # - checks command's return object format # - check custom SQL fee values # - check values in local nodes listchannels output @@ -1872,77 +1872,99 @@ def test_setchannelfee_usage(node_factory, bitcoind): DEF_BASE = 10 DEF_BASE_MSAT = Millisatoshi(DEF_BASE) DEF_PPM = 100 + # Minus reserve + MAX_HTLC = Millisatoshi(int(FUNDAMOUNT * 1000 * 0.99)) l1, l2, l3 = node_factory.get_nodes(3, opts={'fee-base': DEF_BASE, 'fee-per-satoshi': DEF_PPM}) node_factory.join_nodes([l1, l2]) l1.rpc.connect(l3.info['id'], 'localhost', l3.port) - def channel_get_fees(scid): + def channel_get_config(scid): return l1.db.query( - 'SELECT feerate_base, feerate_ppm FROM channels ' + 'SELECT feerate_base, feerate_ppm, htlc_maximum_msat FROM channels ' 'WHERE short_channel_id=\'{}\';'.format(scid)) # get short channel id scid = l1.get_channel_scid(l2) # feerates should be init with global config - db_fees = l1.db_query('SELECT feerate_base, feerate_ppm FROM channels;') + db_fees = l1.db_query('SELECT feerate_base, feerate_ppm, htlc_maximum_msat FROM channels;') assert(db_fees[0]['feerate_base'] == DEF_BASE) assert(db_fees[0]['feerate_ppm'] == DEF_PPM) + # This will be the capacity - reserves: + assert(db_fees[0]['htlc_maximum_msat'] == MAX_HTLC) # this is also what listpeers should return peers = l1.rpc.listpeers()['peers'] assert peers[0]['channels'][0]['fee_base_msat'] == DEF_BASE_MSAT assert peers[0]['channels'][0]['fee_proportional_millionths'] == DEF_PPM + assert peers[0]['channels'][0]['maximum_htlc_out_msat'] == MAX_HTLC - # custom setchannelfee scid - result = l1.rpc.setchannelfee(scid, 1337, 137) + # custom setchannel scid + result = l1.rpc.setchannel(scid, 1337, 137, 133337) # check result format - assert(result['base'] == 1337) - assert(result['ppm'] == 137) assert(len(result['channels']) == 1) assert(re.match('^[0-9a-f]{64}$', result['channels'][0]['channel_id'])) assert(result['channels'][0]['peer_id'] == l2.info['id']) assert(result['channels'][0]['short_channel_id'] == scid) + assert(result['channels'][0]['fee_base_msat'] == 1337) + assert(result['channels'][0]['fee_proportional_millionths'] == 137) + assert(result['channels'][0]['maximum_htlc_out_msat'] == 133337) # check if custom values made it into the database - db_fees = channel_get_fees(scid) + db_fees = channel_get_config(scid) assert(db_fees[0]['feerate_base'] == 1337) assert(db_fees[0]['feerate_ppm'] == 137) + assert(db_fees[0]['htlc_maximum_msat'] == 133337) # also check for updated values in `listpeers` peers = l1.rpc.listpeers()['peers'] assert peers[0]['channels'][0]['fee_base_msat'] == Millisatoshi(1337) assert peers[0]['channels'][0]['fee_proportional_millionths'] == 137 + assert peers[0]['channels'][0]['maximum_htlc_out_msat'] == 133337 # wait for gossip and check if l1 sees new fees in listchannels wait_for(lambda: [c['base_fee_millisatoshi'] for c in l1.rpc.listchannels(scid)['channels']] == [DEF_BASE, 1337]) wait_for(lambda: [c['fee_per_millionth'] for c in l1.rpc.listchannels(scid)['channels']] == [DEF_PPM, 137]) + wait_for(lambda: [c['htlc_maximum_msat'] for c in l1.rpc.listchannels(scid)['channels']] == [MAX_HTLC, 133337]) # also test with named and missing parameters - result = l1.rpc.setchannelfee(ppm=42, id=scid) - assert(result['base'] == DEF_BASE) - assert(result['ppm'] == 42) + result = l1.rpc.setchannel(feeppm=42, id=scid) assert(len(result['channels']) == 1) assert(re.match('^[0-9a-f]{64}$', result['channels'][0]['channel_id'])) assert(result['channels'][0]['short_channel_id'] == scid) - result = l1.rpc.setchannelfee(base=42, id=scid) - assert(result['base'] == 42) - assert(result['ppm'] == DEF_PPM) + assert(result['channels'][0]['fee_base_msat'] == 1337) + assert(result['channels'][0]['fee_proportional_millionths'] == 42) + assert(result['channels'][0]['maximum_htlc_out_msat'] == 133337) + + result = l1.rpc.setchannel(feebase=43, id=scid) assert(len(result['channels']) == 1) assert(re.match('^[0-9a-f]{64}$', result['channels'][0]['channel_id'])) assert(result['channels'][0]['short_channel_id'] == scid) + assert(result['channels'][0]['fee_base_msat'] == 43) + assert(result['channels'][0]['fee_proportional_millionths'] == 42) + assert(result['channels'][0]['maximum_htlc_out_msat'] == 133337) + + result = l1.rpc.setchannel(htlcmax=43333, id=scid) + assert(len(result['channels']) == 1) + assert(re.match('^[0-9a-f]{64}$', result['channels'][0]['channel_id'])) + assert(result['channels'][0]['short_channel_id'] == scid) + assert(result['channels'][0]['fee_base_msat'] == 43) + assert(result['channels'][0]['fee_proportional_millionths'] == 42) + assert(result['channels'][0]['maximum_htlc_out_msat'] == 43333) # check if negative fees raise error and DB keeps values # JSONRPC2_INVALID_PARAMS := -32602 with pytest.raises(RpcError, match=r'-32602'): - l1.rpc.setchannelfee(scid, -1, -1) + l1.rpc.setchannel(scid, -1, -1) # test if zero fees is possible - result = l1.rpc.setchannelfee(scid, 0, 0) - assert(result['base'] == 0) - assert(result['ppm'] == 0) - db_fees = channel_get_fees(scid) + result = l1.rpc.setchannel(scid, 0, 0) + assert(result['channels'][0]['short_channel_id'] == scid) + assert(result['channels'][0]['fee_base_msat'] == 0) + assert(result['channels'][0]['fee_proportional_millionths'] == 0) + + db_fees = channel_get_config(scid) assert(db_fees[0]['feerate_base'] == 0) assert(db_fees[0]['feerate_ppm'] == 0) # also check for updated values in `listpeers` @@ -1950,53 +1972,44 @@ def test_setchannelfee_usage(node_factory, bitcoind): assert peers[0]['channels'][0]['fee_base_msat'] == Millisatoshi(0) assert peers[0]['channels'][0]['fee_proportional_millionths'] == 0 - # disable and check for global values to be returned - result = l1.rpc.setchannelfee(scid) - assert(result['base'] == DEF_BASE) - assert(result['ppm'] == DEF_PPM) - # check default values in DB - db_fees = channel_get_fees(scid) - assert(db_fees[0]['feerate_base'] == DEF_BASE) - assert(db_fees[0]['feerate_ppm'] == DEF_PPM) - # also check for updated values in `listpeers` - peers = l1.rpc.listpeers()['peers'] - assert peers[0]['channels'][0]['fee_base_msat'] == DEF_BASE_MSAT - assert peers[0]['channels'][0]['fee_proportional_millionths'] == DEF_PPM - # check also peer id can be used - result = l1.rpc.setchannelfee(l2.info['id'], 42, 43) - assert(result['base'] == 42) - assert(result['ppm'] == 43) + result = l1.rpc.setchannel(l2.info['id'], 142, 143) assert(len(result['channels']) == 1) assert(result['channels'][0]['peer_id'] == l2.info['id']) assert(result['channels'][0]['short_channel_id'] == scid) - db_fees = channel_get_fees(scid) - assert(db_fees[0]['feerate_base'] == 42) - assert(db_fees[0]['feerate_ppm'] == 43) + assert(result['channels'][0]['fee_base_msat'] == 142) + assert(result['channels'][0]['fee_proportional_millionths'] == 143) + + db_fees = channel_get_config(scid) + assert(db_fees[0]['feerate_base'] == 142) + assert(db_fees[0]['feerate_ppm'] == 143) # check if invalid scid raises proper error with pytest.raises(RpcError, match=r'-1.*Could not find active channel of peer with that id'): - result = l1.rpc.setchannelfee(l3.info['id'], 42, 43) + result = l1.rpc.setchannel(l3.info['id'], 42, 43) with pytest.raises(RpcError, match=r'-32602.*id: should be a channel ID or short channel ID: invalid token'): - result = l1.rpc.setchannelfee('f42' + scid[3:], 42, 43) + result = l1.rpc.setchannel('f42' + scid[3:], 42, 43) # check if 'base' unit can be modified to satoshi - result = l1.rpc.setchannelfee(scid, '1sat') - assert(result['base'] == 1000) - db_fees = channel_get_fees(scid) + result = l1.rpc.setchannel(scid, '1sat') + assert(len(result['channels']) == 1) + assert(result['channels'][0]['peer_id'] == l2.info['id']) + assert(result['channels'][0]['short_channel_id'] == scid) + assert(result['channels'][0]['fee_base_msat'] == 1000) + db_fees = channel_get_config(scid) assert(db_fees[0]['feerate_base'] == 1000) # check if 'ppm' values greater than u32_max fail with pytest.raises(RpcError, match=r'-32602.*ppm: should be an integer: invalid token'): - l1.rpc.setchannelfee(scid, 0, 2**32) + l1.rpc.setchannel(scid, 0, 2**32) # check if 'base' values greater than u32_max fail with pytest.raises(RpcError, match=r'-32602.*base: exceeds u32 max: invalid token'): - l1.rpc.setchannelfee(scid, 2**32) + l1.rpc.setchannel(scid, 2**32) @pytest.mark.developer("gossip without DEVELOPER=1 is slow") -def test_setchannelfee_state(node_factory, bitcoind): +def test_setchannel_state(node_factory, bitcoind): # TEST SETUP # # [l0] --> [l1] --> [l2] @@ -2020,7 +2033,7 @@ def test_setchannelfee_state(node_factory, bitcoind): # try setting the fee in state AWAITING_LOCKIN should be possible # assert(l1.channel_state(l2) == "CHANNELD_AWAITING_LOCKIN") - result = l1.rpc.setchannelfee(l2.info['id'], 42, 0) + result = l1.rpc.setchannel(l2.info['id'], 42, 0) assert(result['channels'][0]['peer_id'] == l2.info['id']) # cid = result['channels'][0]['channel_id'] @@ -2028,7 +2041,7 @@ def test_setchannelfee_state(node_factory, bitcoind): mine_funding_to_announce(bitcoind, [l0, l1, l2]) l0.wait_for_route(l2) - inv = l2.rpc.invoice(100000, 'test_setchannelfee_state', 'desc')['bolt11'] + inv = l2.rpc.invoice(100000, 'test_setchannel_state', 'desc')['bolt11'] result = l0.rpc.dev_pay(inv, use_shadow=False) assert result['status'] == 'complete' assert result['msatoshi_sent'] == 100042 @@ -2044,15 +2057,15 @@ def test_setchannelfee_state(node_factory, bitcoind): bitcoind.generate_block(1) # assert l1.channel_state(l2) == "FUNDING_SPEND_SEEN" - # Try to setchannelfee in order to raise expected error. + # Try to setchannel in order to raise expected error. # To reduce false positive flakes, only test if state is not NORMAL anymore. with pytest.raises(RpcError, match=r'-1.*'): - # l1.rpc.setchannelfee(l2.info['id'], 10, 1) - l1.rpc.setchannelfee(l2.info['id'], 10, 1) + # l1.rpc.setchannel(l2.info['id'], 10, 1) + l1.rpc.setchannel(l2.info['id'], 10, 1) @pytest.mark.developer("gossip without DEVELOPER=1 is slow") -def test_setchannelfee_routing(node_factory, bitcoind): +def test_setchannel_routing(node_factory, bitcoind): # TEST SETUP # # [l1] <--default_fees--> [l2] <--specific_fees--> [l3] @@ -2062,8 +2075,10 @@ def test_setchannelfee_routing(node_factory, bitcoind): # - payment can be done using specific fees # - channel specific fees can be disabled again # - payment can be done using global fees + # - htlc max is honored DEF_BASE = 1 DEF_PPM = 10 + MAX_HTLC = Millisatoshi(int(FUNDAMOUNT * 1000 * 0.99)) l1, l2, l3 = node_factory.line_graph( 3, announce_channels=True, wait_for_announce=True, @@ -2073,11 +2088,12 @@ def test_setchannelfee_routing(node_factory, bitcoind): scid = l2.get_channel_scid(l3) # TEST CUSTOM VALUES - l2.rpc.setchannelfee(scid, 1337, 137) + l2.rpc.setchannel(scid, 1337, 137, 4000000, enforcedelay=0) # wait for l1 to see updated channel via gossip wait_for(lambda: [c['base_fee_millisatoshi'] for c in l1.rpc.listchannels(scid)['channels']] == [1337, DEF_BASE]) wait_for(lambda: [c['fee_per_millionth'] for c in l1.rpc.listchannels(scid)['channels']] == [137, DEF_PPM]) + wait_for(lambda: [c['htlc_maximum_msat'] for c in l1.rpc.listchannels(scid)['channels']] == [4000000, MAX_HTLC]) # test fees are applied to HTLC forwards # @@ -2085,50 +2101,48 @@ def test_setchannelfee_routing(node_factory, bitcoind): # If l1 were to send 4,999,999 millisatoshi to l3 via l2, it needs to # pay l2 the fee it specified in the l2->l3 `channel_update`, calculated as # per [HTLC Fees](#htlc_fees): base + amt * pm / 10**6 - # - # 1337 + 4999999 * 137 / 1000000 = 2021.999 (2021) - route = l1.rpc.getroute(l3.info['id'], 4999999, 1)["route"] - assert len(route) == 2 - assert route[0]['msatoshi'] == 5002020 - assert route[1]['msatoshi'] == 4999999 + + # FIXME! +# # Should refuse to route this! +# with pytest.raises(RpcError, match=r'Could not find a route'): +# l1.rpc.getroute(l3.info['id'], 4000001, 1, fuzzpercent=0)["route"] + + # 1337 + 4000000 * 137 / 1000000 = 1885 + route_ok = l1.rpc.getroute(l3.info['id'], 4000000, 1)["route"] + assert len(route_ok) == 2 + assert route_ok[0]['msatoshi'] == 4001885 + assert route_ok[1]['msatoshi'] == 4000000 + + # Make variant that tries to pay more than allowed htlc! + route_bad = copy.deepcopy(route_ok) + route_bad[0]['msatoshi'] = 4001887 + route_bad[1]['msatoshi'] = 4000001 + route_bad[0]['amount_msat'] = Millisatoshi(4001887) + route_bad[1]['amount_msat'] = Millisatoshi(4000001) + assert route_bad != route_ok # In case l3 includes a routehint, we need to make sure they also know # about the new fees, otherwise we may end up with the old feerate - wait_for(lambda: [(c['base_fee_millisatoshi'], c['fee_per_millionth'], c['active']) for c in l3.rpc.listchannels(scid)['channels']] == [(1337, 137, True), (DEF_BASE, DEF_PPM, True)]) + wait_for(lambda: [(c['base_fee_millisatoshi'], c['fee_per_millionth'], c['htlc_maximum_msat'], c['active']) for c in l3.rpc.listchannels(scid)['channels']] == [(1337, 137, 4000000, True), (DEF_BASE, DEF_PPM, MAX_HTLC, True)]) # do and check actual payment - inv = l3.rpc.invoice(4999999, 'test_setchannelfee_1', 'desc')['bolt11'] - result = l1.rpc.dev_pay(inv, use_shadow=False) - assert result['status'] == 'complete' - assert result['msatoshi_sent'] == 5002020 + inv = l3.rpc.invoice(4000000, 'test_setchannel_1', 'desc') + # Check that routehint from l3 incorporated new feerate! + decoded = l1.rpc.decodepay(inv['bolt11']) + assert decoded['routes'] == [[{'pubkey': l2.info['id'], 'short_channel_id': scid, 'fee_base_msat': 1337, 'fee_proportional_millionths': 137, 'cltv_expiry_delta': 6}]] - # TEST DISABLE and check global fee routing - l2.rpc.setchannelfee(scid) + # This will fail. + l1.rpc.sendpay(route_bad, inv['payment_hash'], payment_secret=inv['payment_secret']) + with pytest.raises(RpcError, match='WIRE_TEMPORARY_CHANNEL_FAILURE'): + l1.rpc.waitsendpay(inv['payment_hash']) - # wait for l1 to see default values again via gossip - wait_for(lambda: [c['base_fee_millisatoshi'] for c in l1.rpc.listchannels(scid)['channels']] == [DEF_BASE, DEF_BASE]) - wait_for(lambda: [c['fee_per_millionth'] for c in l1.rpc.listchannels(scid)['channels']] == [DEF_PPM, DEF_PPM]) - - # test if global fees are applied again (base 1 ppm 10) - # 1 + 4999999 * 10 / 1000000 = 50.999 (50) - route = l1.rpc.getroute(l3.info['id'], 4999999, 1)["route"] - assert len(route) == 2 - assert route[0]['msatoshi'] == 5000049 - assert route[1]['msatoshi'] == 4999999 - - # In case l3 includes a routehint, we need to make sure they also know - # about the new fees, otherwise we may end up with the old feerate - wait_for(lambda: [(c['base_fee_millisatoshi'], c['fee_per_millionth'], c['active']) for c in l3.rpc.listchannels(scid)['channels']] == [(DEF_BASE, DEF_PPM, True), (DEF_BASE, DEF_PPM, True)]) - - # do and check actual payment - inv = l3.rpc.invoice(4999999, 'test_setchannelfee_2', 'desc')['bolt11'] - result = l1.rpc.dev_pay(inv, use_shadow=False) - assert result['status'] == 'complete' - assert result['msatoshi_sent'] == 5000049 + # This will succeed + l1.rpc.sendpay(route_ok, inv['payment_hash'], payment_secret=inv['payment_secret']) + l1.rpc.waitsendpay(inv['payment_hash']) @pytest.mark.developer("gossip without DEVELOPER=1 is slow") -def test_setchannelfee_zero(node_factory, bitcoind): +def test_setchannel_zero(node_factory, bitcoind): # TEST SETUP # # [l1] <--default_fees--> [l2] <--specific_fees--> [l3] @@ -2147,7 +2161,7 @@ def test_setchannelfee_zero(node_factory, bitcoind): scid = l2.get_channel_scid(l3) # TEST ZERO fees possible - l2.rpc.setchannelfee(scid, 0, 0) + l2.rpc.setchannel(scid, 0, 0) wait_for(lambda: [c['base_fee_millisatoshi'] for c in l1.rpc.listchannels(scid)['channels']] == [0, DEF_BASE]) wait_for(lambda: [c['fee_per_millionth'] for c in l1.rpc.listchannels(scid)['channels']] == [0, DEF_PPM]) @@ -2162,14 +2176,14 @@ def test_setchannelfee_zero(node_factory, bitcoind): wait_for(lambda: [(c['base_fee_millisatoshi'], c['fee_per_millionth'], c['active']) for c in l3.rpc.listchannels(scid)['channels']] == [(0, 0, True), (DEF_BASE, DEF_PPM, True)]) # do and check actual payment - inv = l3.rpc.invoice(4999999, 'test_setchannelfee_3', 'desc')['bolt11'] + inv = l3.rpc.invoice(4999999, 'test_setchannel_3', 'desc')['bolt11'] result = l1.rpc.dev_pay(inv, use_shadow=False) assert result['status'] == 'complete' assert result['msatoshi_sent'] == 4999999 @pytest.mark.developer("gossip without DEVELOPER=1 is slow") -def test_setchannelfee_restart(node_factory, bitcoind): +def test_setchannel_restart(node_factory, bitcoind): # TEST SETUP # # [l1] <--default_fees--> [l2] <--specific_fees--> [l3] @@ -2180,6 +2194,7 @@ def test_setchannelfee_restart(node_factory, bitcoind): # - l1 routing can be made to l3 and global (1 10) fees are applied DEF_BASE = 1 DEF_PPM = 10 + MAX_HTLC = Millisatoshi(int(FUNDAMOUNT * 1000 * 0.99)) OPTS = {'may_reconnect': True, 'fee-base': DEF_BASE, 'fee-per-satoshi': DEF_PPM} l1, l2, l3 = node_factory.line_graph(3, announce_channels=True, wait_for_announce=True, opts=OPTS) @@ -2189,7 +2204,7 @@ def test_setchannelfee_restart(node_factory, bitcoind): scid23 = l2.get_channel_scid(l3) # l2 set custom fees - l2.rpc.setchannelfee(scid23, 1337, 137) + l2.rpc.setchannel(scid23, 1337, 137, 500001) # restart l2 and reconnect l2.restart() @@ -2200,22 +2215,22 @@ def test_setchannelfee_restart(node_factory, bitcoind): wait_for(lambda: [c['active'] for c in l1.rpc.listchannels(scid12)['channels']] == [True, True]) # l1 wait for channel update from l2 - wait_for(lambda: [(c['base_fee_millisatoshi'], c['fee_per_millionth'], c['active']) for c in l1.rpc.listchannels(scid23)['channels']] == [(1337, 137, True), (DEF_BASE, DEF_PPM, True)]) + wait_for(lambda: [(c['base_fee_millisatoshi'], c['fee_per_millionth'], c['htlc_maximum_msat'], c['active']) for c in l1.rpc.listchannels(scid23)['channels']] == [(1337, 137, 500001, True), (DEF_BASE, DEF_PPM, MAX_HTLC, True)]) # In case l3 includes a routehint, we need to make sure they also know # about the new fees, otherwise we may end up with the old feerate - wait_for(lambda: [(c['base_fee_millisatoshi'], c['fee_per_millionth'], c['active']) for c in l3.rpc.listchannels(scid23)['channels']] == [(1337, 137, True), (DEF_BASE, DEF_PPM, True)]) + wait_for(lambda: [(c['base_fee_millisatoshi'], c['fee_per_millionth'], c['htlc_maximum_msat'], c['active']) for c in l3.rpc.listchannels(scid23)['channels']] == [(1337, 137, 500001, True), (DEF_BASE, DEF_PPM, MAX_HTLC, True)]) # l1 can make payment to l3 with custom fees being applied - # Note: BOLT #7 math works out to 2021 msat fees - inv = l3.rpc.invoice(4999999, 'test_setchannelfee_1', 'desc')['bolt11'] + # Note: BOLT #7 math works out to 1405 msat fees + inv = l3.rpc.invoice(499999, 'test_setchannel_1', 'desc')['bolt11'] result = l1.rpc.dev_pay(inv, use_shadow=False) assert result['status'] == 'complete' - assert result['msatoshi_sent'] == 5002020 + assert result['msatoshi_sent'] == 501404 @pytest.mark.developer("updates are delayed without --dev-fast-gossip") -def test_setchannelfee_all(node_factory, bitcoind): +def test_setchannel_all(node_factory, bitcoind): # TEST SETUP # # [l1]----> [l2] @@ -2235,7 +2250,7 @@ def test_setchannelfee_all(node_factory, bitcoind): scid3 = l1.get_channel_scid(l3) # now try to set all (two) channels using wildcard syntax - result = l1.rpc.setchannelfee("all", 0xDEAD, 0xBEEF) + result = l1.rpc.setchannel("all", 0xDEAD, 0xBEEF, 0xCAFE) wait_for(lambda: [c['base_fee_millisatoshi'] for c in l1.rpc.listchannels(scid2)['channels']] == [DEF_BASE, 0xDEAD]) wait_for(lambda: [c['fee_per_millionth'] for c in l1.rpc.listchannels(scid2)['channels']] == [DEF_PPM, 0xBEEF]) @@ -2243,12 +2258,16 @@ def test_setchannelfee_all(node_factory, bitcoind): wait_for(lambda: [c['fee_per_millionth'] for c in l1.rpc.listchannels(scid3)['channels']] == [0xBEEF, DEF_PPM]) assert len(result['channels']) == 2 - assert result['base'] == 0xDEAD - assert result['ppm'] == 0xBEEF assert result['channels'][0]['peer_id'] == l2.info['id'] assert result['channels'][0]['short_channel_id'] == scid2 + assert result['channels'][0]['fee_base_msat'] == 0xDEAD + assert result['channels'][0]['fee_proportional_millionths'] == 0xBEEF + assert result['channels'][0]['maximum_htlc_out_msat'] == 0xCAFE assert result['channels'][1]['peer_id'] == l3.info['id'] assert result['channels'][1]['short_channel_id'] == scid3 + assert result['channels'][1]['fee_base_msat'] == 0xDEAD + assert result['channels'][1]['fee_proportional_millionths'] == 0xBEEF + assert result['channels'][1]['maximum_htlc_out_msat'] == 0xCAFE @pytest.mark.developer("gossip without DEVELOPER=1 is slow") @@ -4898,7 +4917,7 @@ def test_pay_low_max_htlcs(node_factory): ) -def test_setchannelfee_enforcement_delay(node_factory, bitcoind): +def test_setchannel_enforcement_delay(node_factory, bitcoind): # Fees start at 1msat + 1% l1, l2, l3 = node_factory.line_graph(3, wait_for_announce=True, opts={'fee-base': 1, @@ -4924,7 +4943,7 @@ def test_setchannelfee_enforcement_delay(node_factory, bitcoind): l1.rpc.waitsendpay(inv['payment_hash']) # Increase fee immediately; l1 payment rejected. - l2.rpc.setchannelfee("all", 2, 10000, 0) + l2.rpc.setchannel("all", 2, 10000, enforcedelay=0) inv = l3.rpc.invoice(1000, "test2", "test2") l1.rpc.sendpay(route, @@ -4942,7 +4961,7 @@ def test_setchannelfee_enforcement_delay(node_factory, bitcoind): l1.rpc.waitsendpay(inv['payment_hash']) # Now, give us 30 seconds please. - l2.rpc.setchannelfee("all", 3, 10000, 30) + l2.rpc.setchannel("all", 3, 10000, enforcedelay=30) inv = l3.rpc.invoice(1000, "test4", "test4") l1.rpc.sendpay(route, payment_hash=inv['payment_hash'],