Skip to content

Commit d212cd9

Browse files
committed
Add RPC cmd for 'alt-addr' and config param for 'alt-bind-addr'
Signed-off-by: Max Rantil <[email protected]>
1 parent b001741 commit d212cd9

File tree

13 files changed

+344
-37
lines changed

13 files changed

+344
-37
lines changed

channeld/channeld.c

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -545,10 +545,8 @@ static void handle_peer_splice_locked(struct peer *peer, const u8 *msg)
545545
static void send_peer_our_alt_address(struct peer *peer) {
546546
struct pubkey node_id;
547547

548-
if (pubkey_from_node_id(&node_id, &peer->id)) {
549-
u8 *msg = towire_peer_alt_address(peer, &node_id, peer->our_alt_addr);
550-
peer_write(peer->pps, take(msg));
551-
}
548+
if (pubkey_from_node_id(&node_id, &peer->id))
549+
peer_write(peer->pps, take(towire_peer_alt_address(peer, &node_id, peer->our_alt_addr)));
552550
}
553551

554552
static void handle_peer_channel_ready(struct peer *peer, const u8 *msg)
@@ -5702,11 +5700,27 @@ static void handle_dev_quiesce(struct peer *peer, const u8 *msg)
57025700
maybe_send_stfu(peer);
57035701
}
57045702

5703+
static void handle_channeld_alt_address(struct peer *peer, const u8 *msg)
5704+
{
5705+
struct pubkey peer_pk;
5706+
u8 *our_alt_addr;
5707+
5708+
if (!fromwire_channeld_alt_address(peer, msg, &peer_pk, &our_alt_addr)) {
5709+
master_badmsg(WIRE_CHANNELD_ALT_ADDRESS, msg);
5710+
}
5711+
5712+
if (pubkey_from_node_id(&peer_pk, &peer->id))
5713+
peer_write(peer->pps, take(towire_peer_alt_address(peer, &peer_pk, our_alt_addr)));
5714+
}
5715+
57055716
static void req_in(struct peer *peer, const u8 *msg)
57065717
{
57075718
enum channeld_wire t = fromwire_peektype(msg);
57085719

57095720
switch (t) {
5721+
case WIRE_CHANNELD_ALT_ADDRESS:
5722+
handle_channeld_alt_address(peer, msg);
5723+
return;
57105724
case WIRE_CHANNELD_FUNDING_DEPTH:
57115725
handle_funding_depth(peer, msg);
57125726
return;

channeld/channeld_wire.csv

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,3 +352,9 @@ msgdata,channeld_upgraded,new_type,channel_type,
352352
# Tell peer about our latest and greatest blockheight.
353353
msgtype,channeld_blockheight,1012
354354
msgdata,channeld_blockheight,blockheight,u32,
355+
356+
# master -> channeld Send peer alternative addresses
357+
msgtype,channeld_alt_address,1014
358+
msgdata,channeld_alt_address,node_id,point,
359+
msgdata,channeld_alt_address,alt_addr_len,u16,
360+
msgdata,channeld_alt_address,alt_addr,u8,alt_addr_len,

connectd/connectd.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -520,8 +520,7 @@ void handle_peer_alt_address(struct peer *peer, const u8 *msg)
520520
master_badmsg(WIRE_PEER_ALT_ADDRESS, msg);
521521
}
522522

523-
msg = towire_connectd_alt_address(NULL, &peer_id, peer_alt_addr);
524-
daemon_conn_send(peer->daemon->master, take(msg));
523+
daemon_conn_send(peer->daemon->master, take(towire_connectd_alt_address(NULL, &peer_id, peer_alt_addr)));
525524

526525
tal_free(peer_alt_addr);
527526
}

contrib/startup_regtest.sh

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,10 @@ start_nodes() {
184184
log-level=debug
185185
log-file=$LIGHTNING_DIR/l$i/log
186186
addr=localhost:$socket
187-
alt-addr=127.21.21.21:$socket
187+
# alt-addr=127.20.20.20:$socket #TODO, Test what happends when both default and RPC are used.
188+
alt-bind-addr=127.21.21.21:$socket
189+
alt-bind-addr=127.22.22.22:$socket
190+
bind-addr=127.29.29.29:$socket
188191
allow-deprecated-apis=false
189192
developer
190193
dev-fast-gossip

lightningd/channel_control.c

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1468,6 +1468,7 @@ static unsigned channel_msg(struct subd *sd, const u8 *msg, const int *fds)
14681468
break;
14691469
/* And we never get these from channeld. */
14701470
case WIRE_CHANNELD_INIT:
1471+
case WIRE_CHANNELD_ALT_ADDRESS:
14711472
case WIRE_CHANNELD_FUNDING_DEPTH:
14721473
case WIRE_CHANNELD_OFFER_HTLC:
14731474
case WIRE_CHANNELD_FULFILL_HTLC:
@@ -2341,3 +2342,63 @@ static const struct json_command dev_quiesce_command = {
23412342
.dev_only = true,
23422343
};
23432344
AUTODATA(json_command, &dev_quiesce_command);
2345+
2346+
static struct command_result *json_alt_addr(struct command *cmd,
2347+
const char *buffer,
2348+
const jsmntok_t *obj UNNEEDED,
2349+
const jsmntok_t *params)
2350+
{
2351+
struct node_id *peer_node_id;
2352+
struct pubkey p_pk; //maybe take this away again (send node_id struct instead) to clean it up?
2353+
struct peer *peer;
2354+
struct channel *channel;
2355+
const char *our_alt_addr;
2356+
bool more_than_one;
2357+
2358+
if (!param_check(cmd, buffer, params,
2359+
p_req("node_id", param_node_id, &peer_node_id),
2360+
p_req("alt_addr", param_string, &our_alt_addr),
2361+
NULL))
2362+
return command_param_failed();
2363+
2364+
peer = peer_by_id(cmd->ld, peer_node_id);
2365+
if (!peer) {
2366+
return command_fail(cmd, JSONRPC2_INVALID_REQUEST,
2367+
"No such peer: %s",
2368+
fmt_node_id(cmd, peer_node_id));
2369+
}
2370+
2371+
channel = peer_any_channel(peer, channel_state_can_add_htlc, &more_than_one);
2372+
if (!channel || !channel->owner)
2373+
return command_fail(cmd, LIGHTNINGD, "Peer bad state");
2374+
/* This is a dev command: fix the api if you need this! */
2375+
if (more_than_one)
2376+
return command_fail(cmd, LIGHTNINGD, "More than one channel");
2377+
2378+
if (command_check_only(cmd))
2379+
return command_check_done(cmd);
2380+
2381+
if (pubkey_from_node_id(&p_pk, peer_node_id)) {
2382+
//TODO, make 'our_alt_addr into a double pointer, array of arrays, for sending many.
2383+
subd_send_msg(channel->owner, take(towire_channeld_alt_address(peer, &p_pk, (u8 *)our_alt_addr)));
2384+
}
2385+
2386+
//TODO, After adding the 'our_alt_addr' here,
2387+
// we need to check against that when accepting the incoming connection.
2388+
//ADD our_alt_addr into our db under the peer with the id we specify here to create the whitelist for later confirmation when accepting incomming connection.
2389+
wallet_add_alt_addr(cmd->ld->wallet->db, peer_node_id, our_alt_addr, true);
2390+
2391+
//TODO, We need to add this to 'listnodes' command too!
2392+
//TODO, How can we send the peer msg without having a channel to the peer?
2393+
2394+
return command_success(cmd, json_stream_success(cmd));
2395+
}
2396+
2397+
static const struct json_command alt_addr_command = {
2398+
"alt-addr",
2399+
"developer",
2400+
json_alt_addr,
2401+
"Select an alternative private address for peer-to-peer connections",
2402+
.dev_only = true,
2403+
};
2404+
AUTODATA(json_command, &alt_addr_command);

lightningd/connect_control.c

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -333,11 +333,23 @@ static void try_connect(const tal_t *ctx,
333333
const struct wireaddr_internal *addrhint,
334334
bool dns_fallback)
335335
{
336+
const struct wireaddr_internal *peer_alt_addr = NULL;
336337
struct delayed_reconnect *d;
337338
struct peer *peer;
338-
const struct wireaddr_internal *alt_addr;
339339

340-
alt_addr = wallet_get_peer_alt_addr(ld->wallet, id);
340+
/* This is where we handle the whitelist of alt addr,
341+
TODO: whitelist of addr(s!)*/
342+
if (ld->alt_bind_addr) {
343+
peer_alt_addr = wallet_get_peer_alt_addr(ld->wallet, id);
344+
if (peer_alt_addr) {
345+
const char *formatted_peer_addr = fmt_wireaddr_internal(ctx, peer_alt_addr);
346+
if (strcmp((char *)ld->alt_bind_addr, formatted_peer_addr) != 0) {
347+
log_debug(ld->log, "No match for alt_bind_addr and peer_alt_addr: '%s' != '%s'\n", ld->alt_bind_addr, formatted_peer_addr);
348+
tal_free(peer_alt_addr);
349+
peer_alt_addr = NULL;
350+
}
351+
}
352+
}
341353

342354
/* Don't stack, unless this is an instant reconnect */
343355
d = delayed_reconnect_map_get(ld->delayed_reconnect_map, id);
@@ -352,7 +364,7 @@ static void try_connect(const tal_t *ctx,
352364
d = tal(ctx, struct delayed_reconnect);
353365
d->ld = ld;
354366
d->id = *id;
355-
d->addrhint = tal_dup_or_null(d, struct wireaddr_internal, alt_addr ? alt_addr : addrhint);
367+
d->addrhint = tal_dup_or_null(d, struct wireaddr_internal, peer_alt_addr ? peer_alt_addr : addrhint);
356368
d->dns_fallback = dns_fallback;
357369
delayed_reconnect_map_add(ld->delayed_reconnect_map, d);
358370
tal_add_destructor(d, destroy_delayed_reconnect);
@@ -566,13 +578,13 @@ static void handle_peer_alt_addr_in(struct lightningd *ld, const u8 *msg)
566578

567579
if (!fromwire_connectd_alt_address(tmpctx, msg, &peer_node_id, &peer_alt_addr)) {
568580
log_broken(ld->log, "Malformed peer_alt_addr_msg: %s",
569-
tal_hex(tmpctx, msg));
581+
tal_hex(tmpctx, msg));
570582
return;
571583
}
572584

573585
struct node_id id;
574586
node_id_from_pubkey(&id, &peer_node_id);
575-
wallet_add_peer_alt_addr(ld->wallet->db, &id, (char *)peer_alt_addr);
587+
wallet_add_alt_addr(ld->wallet->db, &id, (char *)peer_alt_addr, false);
576588
}
577589

578590
static void connectd_start_shutdown_reply(struct subd *connectd,

lightningd/lightningd.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,8 @@ static struct lightningd *new_lightningd(const tal_t *ctx)
256256
ld->recover_secret = NULL;
257257
ld->db_upgrade_ok = NULL;
258258
ld->num_startup_connects = 0;
259+
ld->our_alt_addr = NULL;
260+
ld->alt_bind_addr = NULL;
259261

260262
/* --experimental-upgrade-protocol */
261263
ld->experimental_upgrade_protocol = false;

lightningd/lightningd.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,10 @@ struct lightningd {
194194
struct wireaddr *announceable;
195195

196196
/* Alternative address for peer connections not publicly announced */
197-
u8 *our_alt_addr;
197+
u8 *our_alt_addr; //TODO, make into double pointer
198+
199+
/* Alternative binding address for peer connections not publicly announced */
200+
u8 *alt_bind_addr; //TODO, make into double pointer
198201

199202
/* Current node announcement (if any) */
200203
const u8 *node_announcement;

lightningd/options.c

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -450,6 +450,26 @@ static char *opt_add_alt_addr(const char *arg, struct lightningd *ld)
450450
return opt_add_addr_withtype(arg, ld, ADDR_LISTEN);
451451
}
452452

453+
static char *opt_add_alt_bind_addr(const char *arg, struct lightningd *ld)
454+
{
455+
assert(arg != NULL);
456+
457+
//TODO, Add somewhat a flag here to check later with whitelist.
458+
//TODO, This needs to be a list later I think...
459+
ld->alt_bind_addr = tal_free(ld->alt_bind_addr);
460+
ld->alt_bind_addr = (u8 *)tal_strdup(ld, arg); //tal_arr_expand?
461+
462+
return opt_add_addr_withtype(arg, ld, ADDR_LISTEN);
463+
}
464+
465+
static char *opt_add_alt_announce_addr(const char *arg, struct lightningd *ld)
466+
{
467+
assert(arg != NULL);
468+
//TODO, MAKE THIS FUNCTION.
469+
470+
return opt_add_addr_withtype(arg, ld, ADDR_LISTEN);
471+
}
472+
453473
static char *opt_subdaemon(const char *arg, struct lightningd *ld)
454474
{
455475
char *subdaemon;
@@ -1610,9 +1630,17 @@ static void register_opts(struct lightningd *ld)
16101630
opt_set_uintval,
16111631
opt_show_uintval, &ld->config.ip_discovery_port,
16121632
"Sets the public TCP port to use for announcing discovered IPs.");
1633+
16131634
clnopt_witharg("--alt-addr", OPT_MULTI, opt_add_alt_addr, NULL,
16141635
ld,
1615-
"Set an alternative IP address (v4 or v6) to use selectively for private reconnections with established peers.");
1636+
"Set an alternative IP address (v4 or v6) to use by default for private reconnections with established peers.");
1637+
clnopt_witharg("--alt-bind-addr", OPT_MULTI, opt_add_alt_bind_addr, NULL,
1638+
ld,
1639+
"Bind an alternative IP address (v4 or v6) for listening, but do not announce or use automatically.");
1640+
clnopt_witharg("--alt-announce-addr", OPT_MULTI, opt_add_alt_announce_addr, NULL,
1641+
ld,
1642+
"Provide a reserved IP address (bound by --alt-bind-addr) to established channel peers.");
1643+
16161644
opt_register_noarg("--offline", opt_set_offline, ld,
16171645
"Start in offline-mode (do not automatically reconnect and do not accept incoming connections)");
16181646
clnopt_witharg("--autolisten", OPT_SHOWBOOL,
@@ -2209,6 +2237,8 @@ bool is_known_opt_cb_arg(char *(*cb_arg)(const char *, void *))
22092237
|| cb_arg == (void *)opt_add_bind_addr
22102238
|| cb_arg == (void *)opt_add_announce_addr
22112239
|| cb_arg == (void *)opt_add_alt_addr
2240+
|| cb_arg == (void *)opt_add_alt_bind_addr
2241+
|| cb_arg == (void *)opt_add_alt_announce_addr
22122242
|| cb_arg == (void *)opt_subdaemon
22132243
|| cb_arg == (void *)opt_set_db_upgrade
22142244
|| cb_arg == (void *)arg_log_to_file

tests/test_connection.py

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,87 @@ def test_connect_with_alt_addr(node_factory, bitcoind):
131131
raise
132132

133133

134+
def test_connect_with_alt_addr_rpc(node_factory, bitcoind):
135+
logging.basicConfig(level=logging.INFO)
136+
137+
# Set up nodes
138+
logging.info("Setting up two nodes with the capability to reconnect")
139+
l1 = node_factory.get_node(may_reconnect=True)
140+
l2 = node_factory.get_node(may_reconnect=True)
141+
142+
# Initial connection
143+
logging.info(f"Initial connection from l1 to l2 using localhost and port {l2.port}")
144+
l1.rpc.connect(l2.info['id'], 'localhost', l2.port)
145+
146+
# Checking initial connection state
147+
logging.info("Waiting for both nodes to report they are connected...")
148+
wait_for(lambda: only_one(l1.rpc.listpeers(l2.info['id'])['peers'])['connected'])
149+
wait_for(lambda: only_one(l2.rpc.listpeers(l1.info['id'])['peers'])['connected'])
150+
151+
# Fund channel and log the event
152+
logging.info(f"Funding channel between l1 and l2 with 10**6 satoshis")
153+
l1.fundchannel(l2, 10**6)
154+
155+
# Send the alt-addr from l2 to l1
156+
alt_addr = '127.21.21.21'
157+
addr_without_bind = '127.22.22.22'
158+
l2.rpc.alt_addr(l1.info['id'], f'{alt_addr}:{l2.port}')
159+
160+
# Modifying node configuration to use an alternative address
161+
logging.info(f"Stopping l2 to change its address to {alt_addr}:{l2.port}")
162+
l2.stop()
163+
l2.daemon.opts['alt-bind-addr'] = f'{alt_addr}:{l2.port}'
164+
l2.start()
165+
logging.info("Restarted l2 with bind-addr")
166+
167+
# Verification of the alternative address setting
168+
logging.info("Verifying bind address setting on l2")
169+
try:
170+
binding = l2.rpc.getinfo()['binding']
171+
assert len(binding) > 0, "No binding found for l2"
172+
assert any(bind['address'] == alt_addr for bind in binding), f"Expected bind-addr {alt_addr}, found {binding}"
173+
174+
except Exception as e:
175+
logging.error(f"Bind address not set correctly: {e}")
176+
raise
177+
178+
# Reconnection using the alternative address
179+
logging.info("Attempting to reconnect using the new alternative address")
180+
try:
181+
if any(peer['connected'] for peer in l1.rpc.listpeers()['peers']):
182+
l1.rpc.disconnect(l2.info['id'], force=True)
183+
l1.rpc.connect(l2.info['id'], alt_addr, l2.port)
184+
except Exception as e:
185+
logging.error(f"Error reconnecting nodes using alternative address: {e}")
186+
raise
187+
188+
# Verify the connection using the new address
189+
logging.info("Verifying new connection details")
190+
try:
191+
connected_peer = l1.rpc.getpeer(l2.info['id'])
192+
assert connected_peer['connected'], "Peers not connected"
193+
assert connected_peer['netaddr'][0].startswith(alt_addr), f"Connection not using alt-addr: {connected_peer['netaddr'][0]}"
194+
except Exception as e:
195+
logging.error(f"Error verifying connection using alt-addr: {e}")
196+
raise
197+
198+
# Disconnect and attempt to connect using the addr_without_bind
199+
l2.rpc.alt_addr(l1.info['id'], f'{addr_without_bind}:{l2.port}')
200+
l2.stop()
201+
l2.start()
202+
try:
203+
l1.rpc.connect(l2.info['id'], addr_without_bind, l2.port)
204+
logging.error("Connection should not be successful using addr_without_bind")
205+
assert False, "Connection should fail using addr_without_bind"
206+
except Exception as e:
207+
logging.info(f"Expected failure connecting using addr_without_bind: {e}")
208+
209+
# Final verification
210+
logging.info("Verifying no connection using addr_without_bind")
211+
connected_peer = l1.rpc.listpeers(l2.info['id'])['peers']
212+
assert len(connected_peer) == 0 or not connected_peer[0]['connected'], "Peer should not be connected using addr_without_bind"
213+
214+
134215
def test_remote_addr(node_factory, bitcoind):
135216
"""Check address discovery (BOLT1 #917) init remote_addr works as designed:
136217

0 commit comments

Comments
 (0)