Describe new v2 format
[headersdns] / headersdns.sh
1 #!/bin/bash
2
3 # We need access to a bitcoin-cli instance to get some basic block information and a
4 # Bitcoin Core REST instance to get batches of filter headers and headers in hex.
5 # Requires https://github.com/bitcoin/bitcoin/pull/17631 for REST filter headers.
6 # After creating the zones, we scp them to SCP_TARGET, which is expected to add a
7 # relevant SOA record, NS record(s) and possibly DNSSec-sign the zones before loading
8 # them into a nameserver (knot is generally recommended as it uses much less memory to
9 # store such large zones, though you may need to set `zonefile-load: whole`,
10 # `journal-content: none` and `semantic-checks: off` to get reasonable performance out
11 # of it.
12
13 # The SOA record used on bitcoinheaders.net zones is:
14 # @     TTL_REPLACE     IN      SOA     ns.as397444.net. dnsadmin.as397444.net. (
15 #                                       SERIAL_REPLACE  ; Serial
16 #                                       TTL_REPLACE     ; Refresh
17 #                                       600             ; Retry
18 #                                       2419200         ; Expire
19 #                                       60 )            ; Negative Cache TTL
20 # with TTL_REPLACE replaced with max(min(head -n2 headers-$I.zone | tail -n1 | awk '{ print $2 }', 2592000), 86400) / 24.
21
22 # It is important that your secondary nameserver(s) support NOTIFYs to ensure you can
23 # update them as new blocks come in.
24
25 SCP_TARGET="user@hostname"
26 BITCOIN_CLI="~/bitcoin-cli"
27 BITCOIND_REST="http://127.0.0.1/rest"
28
29 mkdir -p header_zones
30 cc -Wall -O2 ./split.c -o split
31
32 while [ true ]; do
33         if [ "$LATEST_HASH" != "$($BITCOIN_CLI getbestblockhash)" ]; then
34                 LATEST_HASH=$($BITCOIN_CLI getbestblockhash)
35                 echo "Updating for new hash $LATEST_HASH..."
36
37                 COUNT=$($BITCOIN_CLI getblockcount)
38
39                 # Break header chunks into zones of 10k headers each
40                 for I in `seq 0 10000 $COUNT`; do
41                         TARGET=$(($COUNT > $(($I + 9999)) ? $(($I + 9999)) : $COUNT))
42                         HEADERS=""
43                         FILTERS=""
44                         # ...but bitcoind only provides 2000 at a time, so load them in batches
45                         for J in `seq $I 2000 $TARGET`; do
46                                 HASH=$($BITCOIN_CLI getblockhash $J)
47                                 HEADERS="$HEADERS$(wget -q -O - $BITCOIND_REST/headers/2000/$HASH.hex)"
48                                 FILTERS="$FILTERS$(wget -q -O - $BITCOIND_REST/blockfilterheaders/basic/2000/$HASH.hex)"
49                         done
50
51                         # split returns non-0 on error or if the zone on disk ends with the same header
52                         # as what we just provided, so only scp it to our nameserver if we get 0
53                         if echo "$HEADERS" | ./split $I $COUNT 80 headers-$(($I / 10000)).zone; then
54                                 echo -e "put headers-$(($I / 10000)).zone dest/\nquit\n" | sftp $SCP_TARGET
55                         fi
56                         if echo "$FILTERS" | ./split $I $COUNT 32 filterheaders-$(($I / 10000)).zone; then
57                                 echo -e "put filterheaders-$(($I / 10000)).zone dest/\nquit\n" | sftp $SCP_TARGET
58                         fi
59                 done
60         fi
61         sleep 10
62 done