From 1de569d38dc4116995670a952b0216c8e5055c36 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Wed, 19 Jun 2024 09:26:01 +0930 Subject: [PATCH] devtools/gossipwith: use timestamp filter message not obsolete INIT_ROUTING_SYNC. This means we do have to set the network correctly though, and also we can get query messages from lightningd which we have to filter. Signed-off-by: Rusty Russell --- contrib/pyln-testing/pyln/testing/utils.py | 3 +- devtools/gossipwith.c | 18 +++++++--- tests/test_gossip.py | 42 +++++++++++++--------- tools/bench-gossipd.sh | 2 +- 4 files changed, 41 insertions(+), 24 deletions(-) diff --git a/contrib/pyln-testing/pyln/testing/utils.py b/contrib/pyln-testing/pyln/testing/utils.py index 91f9d5294..1840916b1 100644 --- a/contrib/pyln-testing/pyln/testing/utils.py +++ b/contrib/pyln-testing/pyln/testing/utils.py @@ -1387,7 +1387,8 @@ class LightningNode(object): timeout=TIMEOUT, stdout=subprocess.PIPE).stdout.strip() out = subprocess.run(['devtools/gossipwith', - '--features=40', # OPT_GOSSIP_QUERIES + '--no-gossip', + '--network={}'.format(TEST_NETWORK), '--timeout-after={}'.format(int(math.sqrt(TIMEOUT) + 1)), '{}@localhost:{}'.format(self.info['id'], self.port), diff --git a/devtools/gossipwith.c b/devtools/gossipwith.c index 8785ed915..41132cf99 100644 --- a/devtools/gossipwith.c +++ b/devtools/gossipwith.c @@ -54,7 +54,7 @@ struct io_conn { }; static struct secret notsosecret; -static bool initial_sync = false; +static bool no_gossip = false, all_gossip = false; static unsigned long max_messages = -1UL; /* Empty stubs to make us compile */ @@ -175,9 +175,8 @@ static struct io_plan *handshake_success(struct io_conn *conn, int peer_fd = io_conn_fd(conn); struct pollfd pollfd[2]; - if (initial_sync) - set_feature_bit(&features, - OPTIONAL_FEATURE(OPT_INITIAL_ROUTING_SYNC)); + set_feature_bit(&features, + OPTIONAL_FEATURE(OPT_GOSSIP_QUERIES)); if (!no_init) { u8 *msg; @@ -193,6 +192,13 @@ static struct io_plan *handshake_success(struct io_conn *conn, /* Ignore their init message. */ tal_free(sync_crypto_read(NULL, peer_fd, cs)); tal_free(tlvs); + + msg = towire_gossip_timestamp_filter(NULL, + &chainparams->genesis_blockhash, + all_gossip ? 0 + : no_gossip ? 0xFFFFFFFF : time_now().ts.tv_sec, + 0xFFFFFFFF); + sync_crypto_write(peer_fd, cs, take(msg)); } if (stream_stdin) @@ -296,8 +302,10 @@ int main(int argc, char *argv[]) features = tal_arr(conn, u8, 0); chainparams = chainparams_for_network("bitcoin"); - opt_register_noarg("--initial-sync", opt_set_bool, &initial_sync, + opt_register_noarg("--all-gossip", opt_set_bool, &all_gossip, "Stream complete gossip history at start"); + opt_register_noarg("--no-gossip", opt_set_bool, &no_gossip, + "Suppress all gossip at start"); opt_register_arg("--max-messages", opt_set_ulongval, opt_show_ulongval, &max_messages, "Terminate after reading this many messages"); diff --git a/tests/test_gossip.py b/tests/test_gossip.py index 42924fd32..bbd36b96c 100644 --- a/tests/test_gossip.py +++ b/tests/test_gossip.py @@ -645,7 +645,8 @@ def test_gossip_no_empty_announcements(node_factory, bitcoind, chainparams): l1.daemon.wait_for_log(r'\[IN\] 0100') wait_for(lambda: l1.rpc.listchannels()['channels'] == []) - # l1 won't relay it (make sure it has time to digest though) + # l1 won't mention it in reply (make sure it has time to digest though) + # but it may actually relay it time.sleep(2) encoded = subprocess.run(['devtools/mkencoded', '--scids', '00'], check=True, @@ -654,14 +655,14 @@ def test_gossip_no_empty_announcements(node_factory, bitcoind, chainparams): assert l1.query_gossip('query_channel_range', chainparams['chain_hash'], 0, 1000000, - filters=['0109', '0107', '0012']) == ['0108' - # blockhash - + chainparams['chain_hash'] - # first_blocknum, number_of_blocks, complete - + format(0, '08x') + format(1000000, '08x') + '01' - # encoded_short_ids - + format(len(encoded) // 2, '04x') - + encoded] + filters=['0109', '0107', '0012', '0100']) == ['0108' + # blockhash + + chainparams['chain_hash'] + # first_blocknum, number_of_blocks, complete + + format(0, '08x') + format(1000000, '08x') + '01' + # encoded_short_ids + + format(len(encoded) // 2, '04x') + + encoded] # If we reconnect, gossip will now flow. l1.rpc.connect(l2.info['id'], 'localhost', l2.port) @@ -1344,7 +1345,8 @@ def test_gossipwith(node_factory): l1, l2 = node_factory.line_graph(2, wait_for_announce=True) out = subprocess.run(['devtools/gossipwith', - '--initial-sync', + '--all-gossip', + '--network={}'.format(TEST_NETWORK), '--timeout-after={}'.format(int(math.sqrt(TIMEOUT) + 1)), '{}@localhost:{}'.format(l1.info['id'], l1.port)], check=True, @@ -1356,8 +1358,8 @@ def test_gossipwith(node_factory): msg = out[2:2 + l] out = out[2 + l:] - # Ignore pings, timestamp_filter - if t == 265 or t == 18: + # Ignore pings, gossip_timestamp_filter, query_channel_range + if t in (18, 263, 265): continue # channel_announcement node_announcement or channel_update assert t == 256 or t == 257 or t == 258 @@ -1398,6 +1400,7 @@ def test_gossip_notices_close(node_factory, bitcoind): wait_for(lambda: l1.rpc.listnodes()['nodes'] == []) subprocess.run(['devtools/gossipwith', + '--network={}'.format(TEST_NETWORK), '--max-messages=0', '{}@localhost:{}'.format(l1.info['id'], l1.port), channel_announcement, @@ -1645,6 +1648,7 @@ def test_gossip_announce_invalid_block(node_factory, bitcoind): # Test gossip for an unknown block. subprocess.run(['devtools/gossipwith', + '--network={}'.format(TEST_NETWORK), '--max-messages=0', '{}@localhost:{}'.format(l1.info['id'], l1.port), # short_channel_id=103x1x1 @@ -1675,6 +1679,7 @@ def test_gossip_announce_unknown_block(node_factory, bitcoind): # Test gossip for unknown block. subprocess.run(['devtools/gossipwith', + '--network={}'.format(TEST_NETWORK), '--max-messages=0', '{}@localhost:{}'.format(l1.info['id'], l1.port), # short_channel_id=103x1x1 @@ -1931,7 +1936,8 @@ def test_gossip_not_dying(node_factory, bitcoind): def get_gossip(node): out = subprocess.run(['devtools/gossipwith', - '--initial-sync', + '--network={}'.format(TEST_NETWORK), + '--all-gossip', '--timeout-after=2', '{}@localhost:{}'.format(node.info['id'], node.port)], check=True, @@ -1943,8 +1949,8 @@ def test_gossip_not_dying(node_factory, bitcoind): msg = out[2:2 + l] out = out[2 + l:] - # Ignore pings, timestamp_filter - if t == 265 or t == 18: + # Ignore pings, gossip_timestamp_filter, query_channel_range + if t in (18, 263, 265): continue # channel_announcement node_announcement or channel_update assert t == 256 or t == 257 or t == 258 @@ -1976,7 +1982,9 @@ def test_dump_own_gossip(node_factory): # We should get channel_announcement, channel_update, node_announcement. # (Plus random pings, timestamp_filter) out = subprocess.run(['devtools/gossipwith', + '--no-gossip', '--timeout-after={}'.format(int(math.sqrt(TIMEOUT) + 1)), + '--network={}'.format(TEST_NETWORK), '{}@localhost:{}'.format(l1.info['id'], l1.port)], check=True, timeout=TIMEOUT, stdout=subprocess.PIPE).stdout @@ -1991,8 +1999,8 @@ def test_dump_own_gossip(node_factory): l, t = struct.unpack('>HH', out[0:4]) out = out[2 + l:] - # Ignore pings, timestamp_filter - if t == 265 or t == 18: + # Ignore pings, timestamp_filter, query_channel_range + if t in (18, 263, 265): continue assert t == expect[0] diff --git a/tools/bench-gossipd.sh b/tools/bench-gossipd.sh index 79540f1fc..9b4ff5269 100755 --- a/tools/bench-gossipd.sh +++ b/tools/bench-gossipd.sh @@ -139,7 +139,7 @@ fi if [ -z "${TARGETS##* peer_write_all_sec *}" ]; then ENTRIES=$(grep 'Read .* cannounce/cupdate/nannounce/cdelete' "$DIR"/log | cut -d\ -f5 | tr / + | bc) if [ "$ENTRIES" = 0 ]; then echo "Bad store?"; exit 1; fi - /usr/bin/time --quiet --append -f %e devtools/gossipwith --initial-sync --max-messages=$((ENTRIES - 5)) "$ID"@"$DIR"/peer 2>&1 > /dev/null | print_stat peer_write_all_sec + /usr/bin/time --quiet --append -f %e devtools/gossipwith --all-gossip --max-messages=$((ENTRIES - 5)) "$ID"@"$DIR"/peer 2>&1 > /dev/null | print_stat peer_write_all_sec fi if [ -z "${TARGETS##* peer_read_all_sec *}" ]; then