Skip to content

Commit f3b044e

Browse files
committed
docs: add neutrino headers import documentation
Document the neutrino fast sync feature that allows importing block and filter headers from local files or HTTP URLs on startup. Cover configuration for mainnet (block-dn.org), testnet3, testnet4, signet, file format details, security considerations, and troubleshooting.
1 parent 9d1aae5 commit f3b044e

1 file changed

Lines changed: 164 additions & 0 deletions

File tree

docs/neutrino_headers_import.md

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
# Neutrino Fast Sync via Headers Import
2+
3+
When LND is configured to use the neutrino (light client) backend, the initial
4+
sync requires downloading all block headers and compact filter headers from the
5+
network. On mainnet, this can take a significant amount of time as each header
6+
must be fetched individually via P2P.
7+
8+
The headers import feature allows neutrino to bootstrap from a pre-built header
9+
file or HTTP endpoint, dramatically reducing initial sync time. After importing
10+
headers from the external source, neutrino falls back to normal P2P sync for any
11+
remaining headers not covered by the import.
12+
13+
## How It Works
14+
15+
1. On startup, if header import sources are configured, neutrino downloads (or
16+
reads from disk) the block headers and filter headers from the specified
17+
sources.
18+
19+
2. Each import file begins with a 10-byte metadata header:
20+
- **Network magic** (4 bytes, little-endian): Identifies the target network
21+
(mainnet, testnet, etc.).
22+
- **Version** (1 byte): Format version (currently `0`).
23+
- **Header type** (1 byte): `0` for block headers, `1` for filter headers.
24+
- **Start height** (4 bytes, little-endian): The block height of the first
25+
header in the file.
26+
27+
3. Following the metadata, the file contains consecutive raw headers:
28+
- **Block headers**: 80 bytes each (standard Bitcoin block header).
29+
- **Filter headers**: 32 bytes each (BIP 158 compact filter header hash).
30+
31+
4. During import, neutrino validates all block headers by checking
32+
proof-of-work against the target network's consensus rules. Headers that
33+
fail validation are rejected.
34+
35+
5. After the import completes, neutrino resumes normal P2P sync to fetch any
36+
headers beyond what the import file contained, ensuring the node is fully
37+
caught up to the chain tip.
38+
39+
## Configuration
40+
41+
Both `neutrino.blockheaderssource` and `neutrino.filterheaderssource` must be
42+
specified together. Setting only one will cause LND to fail at startup with a
43+
configuration error.
44+
45+
Sources are auto-detected as either HTTP URLs or local file paths based on
46+
whether the value starts with `http`.
47+
48+
### Using block-dn.org (Recommended for Production)
49+
50+
The [block-dn.org](https://github.com/guggero/block-dn) service provides
51+
pre-built header files for multiple Bitcoin networks via HTTP. This is the
52+
recommended approach for production deployments.
53+
54+
The `end_block` parameter in the URL must be divisible by 100,000 and should be
55+
the highest such value below the current chain tip. For example, if the chain
56+
tip is at block 878,432, use `800000` as the end block.
57+
58+
#### Mainnet
59+
60+
```ini
61+
[neutrino]
62+
neutrino.blockheaderssource=https://block-dn.org/headers/import/800000
63+
neutrino.filterheaderssource=https://block-dn.org/filter-headers/import/800000
64+
```
65+
66+
#### Testnet3
67+
68+
```ini
69+
[neutrino]
70+
neutrino.blockheaderssource=https://testnet3.block-dn.org/headers/import/2900000
71+
neutrino.filterheaderssource=https://testnet3.block-dn.org/filter-headers/import/2900000
72+
```
73+
74+
#### Testnet4
75+
76+
```ini
77+
[neutrino]
78+
neutrino.blockheaderssource=https://testnet4.block-dn.org/headers/import/200000
79+
neutrino.filterheaderssource=https://testnet4.block-dn.org/filter-headers/import/200000
80+
```
81+
82+
#### Signet
83+
84+
```ini
85+
[neutrino]
86+
neutrino.blockheaderssource=https://signet.block-dn.org/headers/import/200000
87+
neutrino.filterheaderssource=https://signet.block-dn.org/filter-headers/import/200000
88+
```
89+
90+
You can check the current status and available block heights for each network at
91+
the corresponding status page:
92+
- Mainnet: https://block-dn.org/status
93+
- Testnet3: https://testnet3.block-dn.org/status
94+
- Testnet4: https://testnet4.block-dn.org/status
95+
- Signet: https://signet.block-dn.org/status
96+
97+
### Using Local Files
98+
99+
If you have pre-built header files on disk (for example, copied from an existing
100+
neutrino data directory), you can point LND at them directly:
101+
102+
```ini
103+
[neutrino]
104+
neutrino.blockheaderssource=/path/to/block_headers.bin
105+
neutrino.filterheaderssource=/path/to/filter_headers.bin
106+
```
107+
108+
Local files must include the 10-byte import metadata prefix. Raw header files
109+
from neutrino's data directory (`block_headers.bin` and
110+
`reg_filter_headers.bin`) do not include this metadata by default. You can add
111+
it programmatically using neutrino's `chainimport.AddHeadersImportMetadata()`
112+
utility.
113+
114+
## Security Considerations
115+
116+
The headers import feature includes several safeguards:
117+
118+
- **Proof-of-work validation**: All imported block headers are validated against
119+
the target network's consensus rules. An attacker cannot provide invalid
120+
headers without solving the proof-of-work puzzle.
121+
122+
- **Network magic check**: The import file's network magic must match the
123+
configured Bitcoin network, preventing accidental cross-network imports.
124+
125+
- **Filter header consistency**: Filter headers are validated against the block
126+
headers to ensure consistency.
127+
128+
- **P2P fallback**: After import, neutrino continues syncing via P2P. The P2P
129+
network provides an independent check — if the imported headers diverge from
130+
the honest chain, the P2P sync will detect and correct this.
131+
132+
For additional assurance, you can combine header import with neutrino's existing
133+
`assertfilterheader` option to checkpoint a known-good filter header hash at a
134+
specific height:
135+
136+
```ini
137+
[neutrino]
138+
neutrino.assertfilterheader=800000:0123456789abcdef...
139+
```
140+
141+
## Troubleshooting
142+
143+
### "both neutrino.blockheaderssource and neutrino.filterheaderssource must be specified together"
144+
145+
Both options must be set together. If you only need block headers, you still
146+
must provide a filter headers source, and vice versa.
147+
148+
### HTTP download failures
149+
150+
If using HTTP sources, ensure the URL is reachable and the `end_block` value in
151+
the URL is divisible by 100,000. Check the service status page to confirm
152+
availability.
153+
154+
### "failed to deserialize import metadata"
155+
156+
The import file is missing or has a corrupt metadata prefix. Ensure the file
157+
includes the 10-byte metadata header. Files copied directly from neutrino's data
158+
directory need metadata added via `chainimport.AddHeadersImportMetadata()`.
159+
160+
### "network magic mismatch"
161+
162+
The header file was built for a different Bitcoin network than what LND is
163+
configured to use. Ensure the header file matches your `bitcoin.network`
164+
setting (mainnet, testnet, signet, etc.).

0 commit comments

Comments
 (0)