From 4c7558906af6f812f9f177a86d5b17e9468880a0 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Mon, 25 Jul 2022 04:23:53 +0000 Subject: [PATCH 1/4] Tweak script slightly --- headersdns.sh | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/headersdns.sh b/headersdns.sh index 4d8cabd..bc5a995 100644 --- a/headersdns.sh +++ b/headersdns.sh @@ -22,12 +22,15 @@ # It is important that your secondary nameserver(s) support NOTIFYs to ensure you can # update them as new blocks come in. +set -e + SCP_TARGET="user@hostname" BITCOIN_CLI="~/bitcoin-cli" BITCOIND_REST="http://127.0.0.1/rest" mkdir -p header_zones cc -Wall -O2 ./split.c -o split +cd header_zones while [ true ]; do if [ "$LATEST_HASH" != "$($BITCOIN_CLI getbestblockhash)" ]; then @@ -50,10 +53,10 @@ while [ true ]; do # split returns non-0 on error or if the zone on disk ends with the same header # as what we just provided, so only scp it to our nameserver if we get 0 - if echo "$HEADERS" | ./split $I $COUNT 80 headers-$(($I / 10000)).zone; then + if echo "$HEADERS" | ../split $I $COUNT 80 headers-$(($I / 10000)).zone; then echo -e "put headers-$(($I / 10000)).zone dest/\nquit\n" | sftp $SCP_TARGET fi - if echo "$FILTERS" | ./split $I $COUNT 32 filterheaders-$(($I / 10000)).zone; then + if echo "$FILTERS" | ../split $I $COUNT 32 filterheaders-$(($I / 10000)).zone; then echo -e "put filterheaders-$(($I / 10000)).zone dest/\nquit\n" | sftp $SCP_TARGET fi done -- 2.30.2 From 819aaf17281f220e5c5364fb1af14ac4c2ebde9f Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Mon, 20 Nov 2023 23:54:31 +0000 Subject: [PATCH 2/4] Update filter header example to point to block 10k --- index.html | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/index.html b/index.html index 8c4143e..dfebe82 100644 --- a/index.html +++ b/index.html @@ -64,14 +64,14 @@

0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a29ab5f49ffff001d1dac2b7c

-

and the first filter header encoded as:

+

and the 10,000th filter header encoded as:

-0.0.basic.filter.bitcoinheaders.net. 604800 IN AAAA 2001:9f3:c30f:c37:fb97:7cf3:e1a3:173c
-0.0.basic.filter.bitcoinheaders.net. 604800 IN AAAA 2001:2802:139c:2020::
-0.0.basic.filter.bitcoinheaders.net. 604800 IN AAAA 2001:1631:e8ff:119a:d308:8b6f:5b2b:ced0
+10000.1.basic.filter.bitcoinheaders.net. 604800 IN AAAA 2001:65e:9154:fba5:5883:1fa0:4738:3262 +10000.1.basic.filter.bitcoinheaders.net. 604800 IN AAAA 2001:1dee:3a70:76df:a4aa:5ee9:5285:5cdf +10000.1.basic.filter.bitcoinheaders.net. 604800 IN AAAA 2001:225c:f460:3730::

which decodes to

- 9f3c30f0c37fb977cf3e1a3173c631e8ff119ad3088b6f5b2bced0802139c202 + 65e9154fba558831fa047383262dee3a7076dfa4aa5ee952855cdf25cf460373

You can find the scripts used to generate the zones as well as this website via git. -- 2.30.2 From f048c6a2255cb7827f9f1d0bb1327e3fdcbe24d1 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Sat, 25 Nov 2023 17:45:16 +0000 Subject: [PATCH 3/4] Add new v2 encoding which should be simpler to parse --- split.c | 48 ++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 44 insertions(+), 4 deletions(-) diff --git a/split.c b/split.c index 8e484d0..1d70a2c 100644 --- a/split.c +++ b/split.c @@ -34,6 +34,9 @@ int main(int argc, char* argv[]) { size_t linelen = 0; getline(&hex, &linelen, stdin); size_t len = strlen(hex); + // len should include a \n but otherwise be a multiple of header_len + assert(len % 2 == 1); + assert((len-1)/2 % header_len == 0); if (start_height < total_height - 1) { int prev_chunk_count = (total_height - 1) / 10000; @@ -60,7 +63,48 @@ int main(int argc, char* argv[]) { assert(write(out_fd, hex + ((len / header_len / 2) - 1) * header_len * 2, header_len * 2) == header_len * 2); assert(write(out_fd, "\n", 1) == 1); + // We add one byte for the version and then divide (rounding up) by 14 bytes per IPv6. + int addr_count = (header_len + 1 + 13) / 14; for (int i = 0; i < len / header_len / 2; i++) { + int zttl = ttl - i; + if (zttl < 60) { zttl = 60; } + + for (int j = 0; j < addr_count; j++) { + char fmt[7*5]; + memset(fmt, 0, sizeof(fmt)); + for (int k = 0; k < 7; k++) { + char* target = fmt + k * 5; + int start = j*14*2 + k*4 - 2; + int count = header_len*2 - start; + if (start < 0) { + start = 0; + target[0] = '0'; + target[1] = '1'; + target += 2; + if (count > 2) count = 2; + } + if (count < 0) { + fmt[k*5] = '0'; + continue; + } + if (count > 4) count = 4; + assert(count % 2 == 0); + memcpy(target, &hex[i * header_len*2 + start], count); + if (count < 4 && start != 0) { + target[2] = '0'; + target[3] = '0'; + } + } + dprintf(out_fd, "v2.%d %d IN AAAA 260%d:%s:%s:%s:%s:%s:%s:%s\n", + start_height + i, zttl, j, + &fmt[0 * 5], + &fmt[1 * 5], + &fmt[2 * 5], + &fmt[3 * 5], + &fmt[4 * 5], + &fmt[5 * 5], + &fmt[6 * 5]); + } if (header_len == 80) { for (int j = 0; j < 6; j++) { char fmt[7*5]; @@ -82,8 +126,6 @@ int main(int argc, char* argv[]) { memcpy(fmt + 4*5, &hex[i * header_len*2 + 3*4 + offs], 4); memcpy(fmt + 5*5, &hex[i * header_len*2 + 4*4 + offs], 4); memcpy(fmt + 6*5, &hex[i * header_len*2 + 5*4 + offs], 4); - int zttl = ttl - i; - if (zttl < 60) { zttl = 60; } dprintf(out_fd, "%d %d IN AAAA 2001:%d%s:%s:%s:%s:%s:%s:%s\n", start_height + i, zttl, j, &fmt[0 * 5], @@ -116,8 +158,6 @@ int main(int argc, char* argv[]) { fmt[5*5] = '0'; fmt[6*5] = '0'; } - int zttl = ttl - i; - if (zttl < 60) { zttl = 60; } dprintf(out_fd, "%d %d IN AAAA 2001:%d%s:%s:%s:%s:%s:%s:%s\n", start_height + i, zttl, j, &fmt[0 * 5], -- 2.30.2 From ee273e606117b32cd1d6bc93ba11304f6049c01d Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Sat, 25 Nov 2023 19:02:47 +0000 Subject: [PATCH 4/4] Describe new v2 format --- index.html | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/index.html b/index.html index dfebe82..9e23822 100644 --- a/index.html +++ b/index.html @@ -45,30 +45,30 @@ bitcoinheaders.net currently supports fetching of either full Bitcoin headers or neutrino filter headers, both with a similar format. To ensure reliable access in the face of strict DNS filters, the data is encoded in IPv6 addresses in AAAA records and DNSSec signed to prevent some basic attacks.

- Headers names are broken into sub-zones of 10,000 records, so queries should take the form of height.(height / 10000).bitcoinheaders.net (or, for basic neutrino filter headers, height.(height / 10000).basic.filter.bitcoinheaders.net). + Headers names are broken into sub-zones of 10,000 records, so queries should take the form of v2.height.(height / 10000).bitcoinheaders.net (or, for basic neutrino filter headers, v2.height.(height / 10000).basic.filter.bitcoinheaders.net).

- All headers and filter headers are encoded with an arbitrary two byte prefix (currently "2001:"), followed by a 0-indexed order nibble (as nameservers often reorder responses). Bitcoin headers are then prefixed by a single version byte (currently version 0 - two 0 nibbles) and placed into the remaining 80 bytes of six IPv6 addresses. Filter headers are simply placed into three IPv6 addresses with a 17-nibble (8.5 byte) 0 suffix. + All headers and filter headers are encoded with an arbitrary one byte prefix (which you must ignore, as it may change in the future), followed by a 0-indexed order byte (as nameservers often reorder responses). Entries are then prefixed by a single version byte (currently version 1) and placed into the remaining bytes of the IPv6 addresses.

The genesis block header is, thus, encoded as (note that the responses are usually not sorted):

-0.0.bitcoinheaders.net.	604800	IN	AAAA	2001:0:1000::
-0.0.bitcoinheaders.net.	604800	IN	AAAA	2001:1000::
-0.0.bitcoinheaders.net.	604800	IN	AAAA	2001:2000::3ba:3edf
-0.0.bitcoinheaders.net.	604800	IN	AAAA	2001:3d7a:7b12:b27a:c72c:3e67:768f:617f
-0.0.bitcoinheaders.net.	604800	IN	AAAA	2001:4c81:bc38:88a5:1323:a9fb:8aa4:b1e5
-0.0.bitcoinheaders.net.	604800	IN	AAAA	2001:5e4a:29ab:5f49:ffff:1d:1dac:2b7c
+v2.0.0.bitcoinheaders.net. 604800 IN AAAA 2603:7b12:b27a:c72c:3e67:768f:617f:c81b +v2.0.0.bitcoinheaders.net. 604800 IN AAAA 2600:101:: +v2.0.0.bitcoinheaders.net. 604800 IN AAAA 2601:: +v2.0.0.bitcoinheaders.net. 604800 IN AAAA 2602::3b:a3ed:fd7a +v2.0.0.bitcoinheaders.net. 604800 IN AAAA 2605:ab5f:49ff:ff00:1d1d:ac2b:7c00:0 +v2.0.0.bitcoinheaders.net. 604800 IN AAAA 2604:c388:8a51:323a:9fb8:aa4b:1e5e:4a29

which decodes to

0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a29ab5f49ffff001d1dac2b7c

and the 10,000th filter header encoded as:

-10000.1.basic.filter.bitcoinheaders.net. 604800 IN AAAA 2001:65e:9154:fba5:5883:1fa0:4738:3262
-10000.1.basic.filter.bitcoinheaders.net. 604800 IN AAAA 2001:1dee:3a70:76df:a4aa:5ee9:5285:5cdf
-10000.1.basic.filter.bitcoinheaders.net. 604800 IN AAAA 2001:225c:f460:3730::
+v2.10000.1.basic.filter.bitcoinheaders.net. 604800 IN AAAA 2601:2dee:3a70:76df:a4aa:5ee9:5285:5cdf +v2.10000.1.basic.filter.bitcoinheaders.net. 604800 IN AAAA 2600:165:e915:4fba:5588:31fa:473:8326 +v2.10000.1.basic.filter.bitcoinheaders.net. 604800 IN AAAA 2602:25cf:4603:7300::

which decodes to

65e9154fba558831fa047383262dee3a7076dfa4aa5ee952855cdf25cf460373 -- 2.30.2