Browse Source

gossipd: dev-set-max-scids-encode-size to artificially force "full" replies.

We cap each reply at a single one, which forces the code into our
recursion logic.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
ppa-0.6.1
Rusty Russell 7 years ago
parent
commit
9e51e196c1
  1. 24
      gossipd/gossip.c
  2. 4
      gossipd/gossip_wire.csv
  3. 34
      lightningd/gossip_control.c
  4. 15
      tests/test_lightningd.py

24
gossipd/gossip.c

@ -101,6 +101,10 @@ HTABLE_DEFINE_TYPE(struct important_peerid,
important_peerid_eq, important_peerid_eq,
important_peerid_map); important_peerid_map);
#if DEVELOPER
static u32 max_scids_encode_bytes = -1U;
#endif
struct daemon { struct daemon {
/* Who am I? */ /* Who am I? */
struct pubkey id; struct pubkey id;
@ -439,6 +443,10 @@ static void encode_add_short_channel_id(u8 **encoded,
static bool encode_short_channel_ids_end(u8 **encoded, size_t max_bytes) static bool encode_short_channel_ids_end(u8 **encoded, size_t max_bytes)
{ {
#if DEVELOPER
if (tal_len(*encoded) > max_scids_encode_bytes)
return false;
#endif
return tal_len(*encoded) <= max_bytes; return tal_len(*encoded) <= max_bytes;
} }
@ -2291,6 +2299,17 @@ fail:
NULL))); NULL)));
goto out; goto out;
} }
static struct io_plan *dev_set_max_scids_encode_size(struct io_conn *conn,
struct daemon *daemon,
const u8 *msg)
{
if (!fromwire_gossip_dev_set_max_scids_encode_size(msg,
&max_scids_encode_bytes))
master_badmsg(WIRE_GOSSIP_DEV_SET_MAX_SCIDS_ENCODE_SIZE, msg);
return daemon_conn_read_next(conn, &daemon->master);
}
#endif /* DEVELOPER */ #endif /* DEVELOPER */
static int make_listen_fd(int domain, void *addr, socklen_t len, bool mayfail) static int make_listen_fd(int domain, void *addr, socklen_t len, bool mayfail)
@ -3518,11 +3537,15 @@ static struct io_plan *recv_req(struct io_conn *conn, struct daemon_conn *master
case WIRE_GOSSIP_QUERY_CHANNEL_RANGE: case WIRE_GOSSIP_QUERY_CHANNEL_RANGE:
return query_channel_range(conn, daemon, daemon->master.msg_in); return query_channel_range(conn, daemon, daemon->master.msg_in);
case WIRE_GOSSIP_DEV_SET_MAX_SCIDS_ENCODE_SIZE:
return dev_set_max_scids_encode_size(conn, daemon,
daemon->master.msg_in);
#else #else
case WIRE_GOSSIP_PING: case WIRE_GOSSIP_PING:
case WIRE_GOSSIP_QUERY_SCIDS: case WIRE_GOSSIP_QUERY_SCIDS:
case WIRE_GOSSIP_SEND_TIMESTAMP_FILTER: case WIRE_GOSSIP_SEND_TIMESTAMP_FILTER:
case WIRE_GOSSIP_QUERY_CHANNEL_RANGE: case WIRE_GOSSIP_QUERY_CHANNEL_RANGE:
case WIRE_GOSSIP_DEV_SET_MAX_SCIDS_ENCODE_SIZE:
break; break;
#endif /* !DEVELOPER */ #endif /* !DEVELOPER */
@ -3581,7 +3604,6 @@ int main(int argc, char *argv[])
timers_init(&daemon->timers, time_mono()); timers_init(&daemon->timers, time_mono());
daemon->broadcast_interval = 30000; daemon->broadcast_interval = 30000;
daemon->last_announce_timestamp = 0; daemon->last_announce_timestamp = 0;
/* stdin == control */ /* stdin == control */
daemon_conn_init(daemon, &daemon->master, STDIN_FILENO, recv_req, daemon_conn_init(daemon, &daemon->master, STDIN_FILENO, recv_req,
master_gone); master_gone);

4
gossipd/gossip_wire.csv

@ -186,6 +186,10 @@ gossip_query_channel_range_reply,,final_complete,bool
gossip_query_channel_range_reply,,num,u16 gossip_query_channel_range_reply,,num,u16
gossip_query_channel_range_reply,,scids,num*struct short_channel_id gossip_query_channel_range_reply,,scids,num*struct short_channel_id
# Set artificial maximum reply_channel_range size. Master->gossipd
gossip_dev_set_max_scids_encode_size,3030
gossip_dev_set_max_scids_encode_size,,max,u32
# Given a short_channel_id, return the endpoints # Given a short_channel_id, return the endpoints
gossip_resolve_channel_request,3009 gossip_resolve_channel_request,3009
gossip_resolve_channel_request,,channel_id,struct short_channel_id gossip_resolve_channel_request,,channel_id,struct short_channel_id

Can't render this file because it has a wrong number of fields in line 6.

34
lightningd/gossip_control.c

@ -139,6 +139,7 @@ static unsigned gossip_msg(struct subd *gossip, const u8 *msg, const int *fds)
case WIRE_GOSSIP_QUERY_SCIDS: case WIRE_GOSSIP_QUERY_SCIDS:
case WIRE_GOSSIP_QUERY_CHANNEL_RANGE: case WIRE_GOSSIP_QUERY_CHANNEL_RANGE:
case WIRE_GOSSIP_SEND_TIMESTAMP_FILTER: case WIRE_GOSSIP_SEND_TIMESTAMP_FILTER:
case WIRE_GOSSIP_DEV_SET_MAX_SCIDS_ENCODE_SIZE:
case WIRE_GOSSIPCTL_PEER_DISCONNECT: case WIRE_GOSSIPCTL_PEER_DISCONNECT:
case WIRE_GOSSIPCTL_PEER_IMPORTANT: case WIRE_GOSSIPCTL_PEER_IMPORTANT:
case WIRE_GOSSIPCTL_PEER_DISCONNECTED: case WIRE_GOSSIPCTL_PEER_DISCONNECTED:
@ -761,4 +762,37 @@ static const struct json_command dev_query_channel_range_command = {
"Query {peerid} for short_channel_ids for {first} block + {num} blocks" "Query {peerid} for short_channel_ids for {first} block + {num} blocks"
}; };
AUTODATA(json_command, &dev_query_channel_range_command); AUTODATA(json_command, &dev_query_channel_range_command);
static void json_dev_set_max_scids_encode_size(struct command *cmd,
const char *buffer,
const jsmntok_t *params)
{
u8 *msg;
jsmntok_t *maxtok;
u32 max;
if (!json_get_params(cmd, buffer, params,
"max", &maxtok,
NULL)) {
return;
}
if (!json_tok_number(buffer, maxtok, &max)) {
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"max must be a number");
return;
}
msg = towire_gossip_dev_set_max_scids_encode_size(NULL, max);
subd_send_msg(cmd->ld->gossip, take(msg));
command_success(cmd, null_response(cmd));
}
static const struct json_command dev_set_max_scids_encode_size = {
"dev-set-max-scids-encode-size",
json_dev_set_max_scids_encode_size,
"Set {max} bytes of short_channel_ids per reply_channel_range"
};
AUTODATA(json_command, &dev_set_max_scids_encode_size);
#endif /* DEVELOPER */ #endif /* DEVELOPER */

15
tests/test_lightningd.py

@ -2714,6 +2714,21 @@ class LightningDTests(BaseLightningDTests):
assert ret['final_complete'] assert ret['final_complete']
assert len(ret['short_channel_ids']) == 0 assert len(ret['short_channel_ids']) == 0
# Make l2 split reply into two.
l2.rpc.dev_set_max_scids_encode_size(max=9)
ret = l1.rpc.dev_query_channel_range(id=l2.info['id'],
first=0,
num=1000000)
# It should definitely have split
assert ret['final_first_block'] != 0 or ret['final_num_blocks'] != 1000000
assert ret['final_complete']
assert len(ret['short_channel_ids']) == 2
assert ret['short_channel_ids'][0] == scid12
assert ret['short_channel_ids'][1] == scid23
l2.daemon.wait_for_log('queue_channel_ranges full: splitting')
@unittest.skipIf(not DEVELOPER, "needs DEVELOPER=1") @unittest.skipIf(not DEVELOPER, "needs DEVELOPER=1")
def test_query_short_channel_id(self): def test_query_short_channel_id(self):
l1 = self.node_factory.get_node(options={'log-level': 'io'}) l1 = self.node_factory.get_node(options={'log-level': 'io'})

Loading…
Cancel
Save