Overview
This document specifies the I2P blockfile file format and the tables in the hostsdb.blockfile used by the Blockfile Naming Service.
For background, see I2P Naming and Address Book.
The blockfile enables fast destination lookups in a compact binary format.
Compared to the legacy hosts.txt system:
- Destinations are stored in binary, not Base64.
- Arbitrary metadata (e.g., added date, source, comments) can be attached.
- Lookup times are roughly 10× faster.
- Disk use increases modestly.
A blockfile is an on-disk collection of sorted maps (key-value pairs) implemented as skiplists.
It was derived from the Metanotion Blockfile Database.
This specification first defines the file structure, then describes how it is used by the BlockfileNamingService.
The Blockfile Naming Service replaced the old
hosts.txtimplementation in I2P 0.8.8.
On initialization, it imports entries fromprivatehosts.txt,userhosts.txt, andhosts.txt.
Blockfile Format
The format is composed of 1024-byte pages, each prefixed with a magic number for integrity.
Pages are numbered starting at 1:
| Page | Description |
|---|---|
| 1 | Superblock (starts at byte 0) |
| 2 | Metaindex skiplist (starts at byte 1024) |
All integers use network byte order (big-endian).
2-byte values are unsigned; 4-byte values (page numbers) are signed and must be positive.
Threading: The database is designed for single-threaded access;
BlockfileNamingServiceprovides synchronization.
Superblock Format
| Byte | Contents |
|---|---|
| 0-5 | Magic number 0x3141de493250 ("1A" 0xde "I2P") |
| 6 | Major version 0x01 |
| 7 | Minor version 0x02 |
| 8-15 | File length (in bytes) |
| 16-19 | First free list page |
| 20-21 | Mounted flag (0x01 = yes) |
| 22-23 | Span size (max key/value pairs per span, 16 for hostsdb) |
| 24-27 | Page size (as of v1.2; 1024 before that) |
| 28-1023 | Unused |
Skip List Block Page Format
| Byte | Contents |
|---|---|
| 0-7 | Magic 0x536b69704c697374 ("SkipList") |
| 8-11 | First span page |
| 12-15 | First level page |
| 16-19 | Size (total keys, valid at startup) |
| 20-23 | Spans (total spans, valid at startup) |
| 24-27 | Levels (total levels, valid at startup) |
| 28-29 | Span size (as of v1.2; used for new spans) |
| 30-1023 | Unused |
Skip Level Block Page Format
Every level has a span, but not all spans have levels.
| Byte | Contents |
|---|---|
| 0-7 | Magic 0x42534c6576656c73 ("BSLevels") |
| 8-9 | Max height |
| 10-11 | Current height |
| 12-15 | Span page |
| 16-… | Next level pages (current height × 4 bytes, lowest first) |
| — | Remaining bytes unused |
Skip Span Block Page Format
Key/value pairs are sorted by key across spans.
Non-first spans must not be empty.
| Byte | Contents |
|---|---|
| 0-3 | Magic 0x5370616e ("Span") |
| 4-7 | First continuation page or 0 |
| 8-11 | Previous span page or 0 |
| 12-15 | Next span page or 0 |
| 16-17 | Max keys (16 for hostsdb) |
| 18-19 | Size (current keys) |
| 20-1023 | Key/value structures |
Span Continuation Block Page Format
| Byte | Contents |
|---|---|
| 0-3 | Magic 0x434f4e54 ("CONT") |
| 4-7 | Next continuation page or 0 |
| 8-1023 | Key/value structures |
Key/Value Structure Format
Key and value length fields cannot span pages (all 4 bytes must fit).
If insufficient space remains, pad up to 3 bytes and continue at offset 8 of the next page.
| Byte | Contents |
|---|---|
| 0-1 | Key length (bytes) |
| 2-3 | Value length (bytes) |
| 4-… | Key data → Value data |
| — | Max length = 65535 bytes each |
Free List Block Page Format
| Byte | Contents |
|---|---|
| 0-7 | Magic 0x2366724c69737423 ("#frList#") |
| 8-11 | Next free list block or 0 |
| 12-15 | Number of valid free pages (0 – 252) |
| 16-1023 | Free page numbers (4 bytes each) |
Free Page Block Format
| Byte | Contents |
|---|---|
| 0-7 | Magic 0x7e2146524545217e ("~!FREE!~") |
| 8-1023 | Unused |
Metaindex
Located at page 2.
Maps US-ASCII strings → 4-byte integers.
The key is the skiplist name; the value is the page index.
Blockfile Naming Service Tables
The service defines several skiplists.
Each span supports up to 16 entries.
Properties Skiplist
%%__INFO__%% contains one entry:
| Key | Value |
|---|---|
info | A Properties object (UTF-8 String / String map) serialized as a Mapping |
Typical fields:
| Property | Description |
|---|---|
version | "4" |
created | Java long (ms since epoch) |
upgraded | Java long (ms since epoch, since DB v2) |
lists | Comma-separated host DBs (e.g. privatehosts.txt,userhosts.txt,hosts.txt) |
listversion_* | Version of each DB (used to detect partial upgrades, since v4) |
Reverse Lookup Skiplist
%%__REVERSE__%% contains Integer → Properties entries (since DB v2).
- Key: First 4 bytes of the SHA-256 hash of the Destination.
- Value: Properties object (serialized Mapping).
- Multiple entries handle collisions and multi-hostname Destinations.
- Each property key = hostname; value = empty string.
Host Database Skiplists
Each of hosts.txt, userhosts.txt, and privatehosts.txt maps hostnames → Destinations.
Version 4 supports multiple Destinations per hostname (introduced in I2P 0.9.26).
Version 3 databases are migrated automatically.
Key
UTF-8 string (hostname, lowercase, ending in .i2p)
Value
- Version 4:
- 1 byte count of Property/Destination pairs
- For each pair: Properties → Destination (binary)
- Version 3:
- Properties → Destination (binary)
DestEntry Properties
| Key | Meaning |
|---|---|
a | Time added (Java long ms) |
m | Last modified (Java long ms) |
notes | User comments |
s | Source (file or subscription URL) |
v | Signature verified (true/false) |
Implementation Notes
The BlockfileNamingService Java class implements this specification.
- Outside router context, the database opens read-only unless
i2p.naming.blockfile.writeInAppContext=true. - Not intended for multi-instance or multi-JVM access.
- Maintains three primary maps (
privatehosts,userhosts,hosts) and a reverse map for fast lookups.