From 019b31c522d729c45931a904e827dab954eaaeaa Mon Sep 17 00:00:00 2001 From: Michael Schmoock Date: Sat, 1 Jan 2022 14:05:58 +0100 Subject: [PATCH] options: only allow one DNS announcement --- lightningd/options.c | 25 +++++++++++++++++++++++++ tests/test_gossip.py | 23 ++++++++++++++--------- 2 files changed, 39 insertions(+), 9 deletions(-) diff --git a/lightningd/options.c b/lightningd/options.c index a1f263a0e..e851bc67f 100644 --- a/lightningd/options.c +++ b/lightningd/options.c @@ -196,6 +196,23 @@ static char *opt_set_accept_extra_tlv_types(const char *arg, } #endif +#if EXPERIMENTAL_FEATURES /* BOLT7 DNS RFC #911 */ +/* Returns the number of wireaddr types already announced */ +static size_t num_announced_types(enum wire_addr_type type, struct lightningd *ld) +{ + size_t num = 0; + for (size_t i = 0; i < tal_count(ld->proposed_wireaddr); i++) { + if (ld->proposed_wireaddr[i].itype != ADDR_INTERNAL_WIREADDR) + continue; + if (ld->proposed_wireaddr[i].u.wireaddr.type != type) + continue; + if (ld->proposed_listen_announce[i] & ADDR_ANNOUNCE) + num++; + } + return num; +} +#endif + static char *opt_add_addr_withtype(const char *arg, struct lightningd *ld, enum addr_listen_announce ala, @@ -242,6 +259,14 @@ static char *opt_add_addr_withtype(const char *arg, #if EXPERIMENTAL_FEATURES /* BOLT7 DNS RFC #911 */ /* Add ADDR_TYPE_DNS to announce DNS hostnames */ if (is_dnsaddr(address) && ala & ADDR_ANNOUNCE) { + /* BOLT-hostnames #7: + * The origin node: + * ... + * - MUST NOT announce more than one `type 5` DNS hostname. + */ + if (num_announced_types(ADDR_TYPE_DNS, ld) > 0) { + return tal_fmt(NULL, "Only one DNS can be announced"); + } memset(&wi, 0, sizeof(wi)); wi.itype = ADDR_INTERNAL_WIREADDR; wi.u.wireaddr.type = ADDR_TYPE_DNS; diff --git a/tests/test_gossip.py b/tests/test_gossip.py index 7696b2642..52ba9e120 100644 --- a/tests/test_gossip.py +++ b/tests/test_gossip.py @@ -114,7 +114,6 @@ def test_announce_address(node_factory, bitcoind): opts = {'disable-dns': None, 'announce-addr': ['4acth47i6kxnvkewtm6q7ib2s3ufpo5sqbsnzjpbi7utijcltosqemad.onion', '1.2.3.4:1234', - 'localhost:1235', 'example.com:1236', '::'], 'log-level': 'io', @@ -151,24 +150,21 @@ def test_announce_address(node_factory, bitcoind): # Also expect the address descriptor types to be sorted! # BOLT #7: # - MUST place address descriptors in ascending order. - l1.daemon.wait_for_log(r"\[OUT\] 0101.*0063" + l1.daemon.wait_for_log(r"\[OUT\] 0101.*0056" "010102030404d2" # IPv4 01 1.2.3.4:1234 "017f000001...." # IPv4 01 127.0.0.1:wxyz "0200000000000000000000000000000000...." # IPv6 02 ::: "04e00533f3e8f2aedaa8969b3d0fa03a96e857bbb28064dca5e147e934244b9ba5023003...." # TORv3 04 - "05096c6f63616c686f737404d3" # DNS 05 len localhost:1235 "050b6578616d706c652e636f6d04d4") # DNS 05 len example.com:1236 # Check other node can parse these (make sure it has digested msg) wait_for(lambda: 'addresses' in l2.rpc.listnodes(l1.info['id'])['nodes'][0]) addresses = l2.rpc.listnodes(l1.info['id'])['nodes'][0]['addresses'] addresses_dns = [address for address in addresses if address['type'] == 'dns'] - assert len(addresses) == 6 - assert len(addresses_dns) == 2 - assert addresses_dns[0]['address'] == 'localhost' - assert addresses_dns[0]['port'] == 1235 - assert addresses_dns[1]['address'] == 'example.com' - assert addresses_dns[1]['port'] == 1236 + assert len(addresses) == 5 + assert len(addresses_dns) == 1 + assert addresses_dns[0]['address'] == 'example.com' + assert addresses_dns[0]['port'] == 1236 @unittest.skipIf(not EXPERIMENTAL_FEATURES, "BOLT7 DNS RFC #911") @@ -236,6 +232,15 @@ def test_announce_and_connect_via_dns(node_factory, bitcoind): l4.rpc.connect(l1.info['id']) +@unittest.skipIf(not EXPERIMENTAL_FEATURES, "BOLT7 DNS RFC #911") +@pytest.mark.developer("gossip without DEVELOPER=1 is slow") +def test_only_announce_one_dns(node_factory, bitcoind): + # and test that we can't announce more than one DNS address + l1 = node_factory.get_node(may_fail=True, expect_fail=True, + options={'announce-addr': ['localhost.localdomain:12345', 'example.com:12345']}) + assert l1.daemon.is_in_stderr("Only one DNS can be announced") + + @pytest.mark.developer("needs DEVELOPER=1") def test_gossip_timestamp_filter(node_factory, bitcoind, chainparams): # Updates get backdated 5 seconds with --dev-fast-gossip.