Test we don't exceed spendable limits on a real network on nodes
(node_factory, bitcoind)
| 1262 | |
| 1263 | |
| 1264 | def test_live_spendable(node_factory, bitcoind): |
| 1265 | """Test we don't exceed spendable limits on a real network on nodes""" |
| 1266 | l1, l2, l3 = node_factory.get_nodes(3) |
| 1267 | l1.fundwallet(10_000_000) |
| 1268 | l2.fundwallet(10_000_000) |
| 1269 | l1.rpc.connect(l2.info['id'], 'localhost', port=l2.port) |
| 1270 | l2.rpc.connect(l3.info['id'], 'localhost', port=l3.port) |
| 1271 | |
| 1272 | capacities = (100_000, 100_000, 200_000, 300_000, 400_000) |
| 1273 | for capacity in capacities: |
| 1274 | l1.rpc.fundchannel(l2.info["id"], capacity, mindepth=1) |
| 1275 | l2.rpc.fundchannel(l3.info["id"], capacity, mindepth=1) |
| 1276 | |
| 1277 | bitcoind.generate_block(1, wait_for_mempool=2) |
| 1278 | sync_blockheight(bitcoind, [l1, l2]) |
| 1279 | |
| 1280 | bitcoind.generate_block(5) |
| 1281 | wait_for(lambda: len(l1.rpc.listchannels()["channels"]) == 2 * 2 * len(capacities)) |
| 1282 | |
| 1283 | routes = l1.rpc.getroutes( |
| 1284 | source=l1.info["id"], |
| 1285 | destination=l3.info["id"], |
| 1286 | amount_msat=800_000_001, |
| 1287 | layers=["auto.localchans", "auto.sourcefree"], |
| 1288 | maxfee_msat=50_000_000, |
| 1289 | final_cltv=10, |
| 1290 | ) |
| 1291 | |
| 1292 | # Don't exceed spendable_msat |
| 1293 | maxes = {} |
| 1294 | for chan in l1.rpc.listpeerchannels()["channels"]: |
| 1295 | maxes["{}/{}".format(chan["short_channel_id"], chan["direction"])] = chan[ |
| 1296 | "spendable_msat" |
| 1297 | ] |
| 1298 | |
| 1299 | path_total = {} |
| 1300 | num_htlcs = {} |
| 1301 | for r in routes["routes"]: |
| 1302 | key = r["path"][0]["short_channel_id_dir"] |
| 1303 | path_total[key] = path_total.get(key, 0) + r["path"][0]["amount_in_msat"] |
| 1304 | num_htlcs[key] = num_htlcs.get(key, 0) + 1 |
| 1305 | |
| 1306 | # Take into account 645000msat (3750 feerate x 172 weight) per-HTLC reduction in capacity. |
| 1307 | for k in path_total.keys(): |
| 1308 | if k in maxes: |
| 1309 | maxes[k] -= (3750 * 172) * (num_htlcs[k] - 1) |
| 1310 | |
| 1311 | exceeded = {} |
| 1312 | for scidd in maxes.keys(): |
| 1313 | if scidd in path_total: |
| 1314 | if path_total[scidd] > maxes[scidd]: |
| 1315 | exceeded[scidd] = f"Path total {path_total[scidd]} > spendable {maxes[scidd]}" |
| 1316 | |
| 1317 | assert exceeded == {} |
| 1318 | |
| 1319 | # No duplicate paths! |
| 1320 | for i in range(0, len(routes["routes"])): |
| 1321 | path_i = [p['short_channel_id_dir'] for p in routes["routes"][i]['path']] |
nothing calls this directly
no test coverage detected