You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
BlockDB is a specialized storage system designed for blockchain blocks. It provides O(1) write performance with support for parallel operations. Unlike general-purpose key-value stores like LevelDB that require periodic compaction, BlockDB's append-only design ensures consistently fast writes without the overhead of background maintenance operations.
3
+
BlockDB is a specialized database optimized for blockchain blocks.
4
4
5
5
## Key Functionalities
6
6
@@ -9,51 +9,47 @@ BlockDB is a specialized storage system designed for blockchain blocks. It provi
9
9
-**Flexible Write Ordering**: Supports out-of-order block writes for bootstrapping
-**Automatic Recovery**: Detects and recovers unindexed blocks after unclean shutdowns
12
-
-**Data Integrity**: Checksums verify block data on reads
13
12
14
-
## Architecture
13
+
## Design
15
14
16
-
BlockDB uses two file types: index files and data files. The index file maps block heights to locations in data files, while data files store the actual block content. Data storage can be split across multiple files based on size limits.
15
+
BlockDB uses two file types: index files and data files. The index file maps block heights to locations in data files, while data files store the actual block content. Data storage can be split across multiple files based on the maximum data file size.
17
16
18
17
```
19
18
┌─────────────────┐ ┌─────────────────┐
20
19
│ Index File │ │ Data File 1 │
21
20
│ (.idx) │ │ (.dat) │
22
21
├─────────────────┤ ├─────────────────┤
23
-
│ Header │ │ Block 1 │
22
+
│ Header │ │ Block 0 │
24
23
│ - Version │ ┌─────>│ - Header │
25
24
│ - Min Height │ │ │ - Data │
26
-
│ - MCH │ │ ├─────────────────┤
27
-
│ - Data Size │ │ │ Block 2 │
28
-
│ - ... │ │ │ │
29
-
├─────────────────┤ │ ┌──>│ - Header │
30
-
│ Entry[0] │ │ │ │ - Data │
31
-
│ - Offset ───────┼──┘ │ ├─────────────────┤
32
-
│ - Size │ │ │ ... │
33
-
├─────────────────┤ │ └─────────────────┘
34
-
│ Entry[1] │ │
35
-
│ - Offset ───────┼─────┘ ┌─────────────────┐
36
-
│ - Size │ │ Data File 2 │
37
-
├─────────────────┤ │ (.dat) │
38
-
│ ... │ ├─────────────────┤
39
-
└─────────────────┘ │ Block N │
40
-
│ - Header │
41
-
│ - Data │
42
-
├─────────────────┤
25
+
│ - Max Height │ │ ├─────────────────┤
26
+
│ - Data Size │ │ │ Block 1 │
27
+
│ - ... │ │ │ - Header │
28
+
├─────────────────┤ │ ┌──>│ - Data │
29
+
│ Entry[0] │ │ │ ├─────────────────┤
30
+
│ - Offset ───────┼──┘ │ │ ... │
31
+
│ - Size │ │ └─────────────────┘
32
+
│ - Header Size │ │
33
+
├─────────────────┤ │ ┌─────────────────┐
34
+
│ Entry[1] │ │ │ Data File 2 │
35
+
│ - Offset ───────┼─────┘ │ (.dat) │
36
+
│ - Size │ ├─────────────────┤
37
+
│ - Header Size │ │ Block N │
38
+
├─────────────────┤ │ - Header │
39
+
│ ... │ │ - Data │
40
+
└─────────────────┘ ├─────────────────┤
43
41
│ ... │
44
42
└─────────────────┘
45
43
```
46
44
47
-
## Implementation Details
48
-
49
45
### File Formats
50
46
51
47
#### Index File Structure
52
48
53
49
The index file consists of a fixed-size header followed by fixed-size entries:
54
50
55
51
```
56
-
Index File Header (48 bytes):
52
+
Index File Header (72 bytes):
57
53
┌────────────────────────────────┬─────────┐
58
54
│ Field │ Size │
59
55
├────────────────────────────────┼─────────┤
@@ -63,14 +59,16 @@ Index File Header (48 bytes):
63
59
│ Min Block Height │ 8 bytes │
64
60
│ Max Contiguous Height │ 8 bytes │
65
61
│ Data File Size │ 8 bytes │
62
+
│ Reserved │ 24 bytes│
66
63
└────────────────────────────────┴─────────┘
67
64
68
-
Index Entry (16 bytes):
65
+
Index Entry (18 bytes):
69
66
┌────────────────────────────────┬─────────┐
70
67
│ Field │ Size │
71
68
├────────────────────────────────┼─────────┤
72
69
│ Data File Offset │ 8 bytes │
73
70
│ Block Data Size │ 8 bytes │
71
+
│ Header Size │ 2 bytes │
74
72
└────────────────────────────────┴─────────┘
75
73
```
76
74
@@ -79,88 +77,45 @@ Index Entry (16 bytes):
79
77
Each block in the data file is stored with a header followed by the raw block data:
80
78
81
79
```
82
-
Block Header (24 bytes):
80
+
Block Header (26 bytes):
83
81
┌────────────────────────────────┬─────────┐
84
82
│ Field │ Size │
85
83
├────────────────────────────────┼─────────┤
86
84
│ Height │ 8 bytes │
87
85
│ Size │ 8 bytes │
86
+
│ Header Size │ 2 bytes │
88
87
│ Checksum │ 8 bytes │
89
88
└────────────────────────────────┴─────────┘
90
89
```
91
90
92
-
### Design Decisions
93
-
94
-
#### Append-Only Architecture
95
-
96
-
BlockDB is strictly append-only with no support for deletions. This aligns with blockchain's immutable nature and provides:
97
-
98
-
- Simplified concurrency model
99
-
- Predictable write performance
100
-
- Straightforward recovery logic
101
-
- No compaction overhead
102
-
103
-
**Trade-off**: Overwriting a block leaves the old data as unreferenced "dead" space. However, since blocks are immutable and rarely overwritten (only during reorgs), this trade-off has minimal impact in practice.
104
-
105
-
#### Fixed-Size Index Entries
106
-
107
-
Each index entry is exactly 16 bytes, containing the offset and size. This fixed size enables direct calculation of where each block's index entry is located, providing O(1) lookups. For blockchains with high block heights, the index remains efficient - even at height 1 billion, the index file would only be ~16GB.
108
-
109
-
#### Two File Type Separation
110
-
111
-
Separating index and data provides several benefits:
91
+
### Block Overwrites
112
92
113
-
- Index files remain relatively small and can benefit from SSD storage
114
-
- Data files can use cheaper storage and be backed up independently
115
-
- Sequential append-only writes to data files minimize fragmentation
116
-
- Index can be rebuilt by scanning data files if needed
93
+
BlockDB allows overwriting blocks at existing heights. When a block is overwritten, the new block is appended to the data file and the index entry is updated to point to the new location, leaving the old block data as unreferenced "dead" space. However, since blocks are immutable and rarely overwritten (e.g., during reorgs), this trade-off should have minimal impact in practice.
117
94
118
-
#### Out-of-Order Block Writing
95
+
###Fixed-Size Index Entries
119
96
120
-
Blocks can be written at any height regardless of arrival order. This is essential for blockchain nodes that may receive blocks out of sequence during syncing operations.
97
+
Each index entry is exactly 18 bytes on disk, containing the offset, size, and header size. This fixed size enables direct calculation of where each block's index entry is located, providing O(1) lookups. For blockchains with high block heights, the index remains efficient, even at height 1 billion, the index file would only be ~18GB.
121
98
122
-
####Durability and Fsync Behavior
99
+
### Durability and Fsync Behavior
123
100
124
101
BlockDB provides configurable durability through the `syncToDisk` parameter:
125
102
126
103
- When enabled, the data file is fsync'd after every block write, guaranteeing immediate durability
127
104
- The index file is fsync'd periodically (every `CheckpointInterval` blocks) to balance performance and recovery time
128
105
- When disabled, writes rely on OS buffering, trading durability for significantly better performance
129
106
130
-
### Key Operations
131
-
132
-
#### Write Performance
133
-
134
-
-**Time Complexity**: O(1) to write a block
135
-
-**I/O Pattern**: Sequential append to data file + single index entry write
136
-
-**Block Size Impact**: While index operations are O(1), total write time depends on block size. With a maximum block size enforced, write time remains bounded, maintaining effectively O(1) performance.
137
-
138
-
#### Read Performance
139
-
140
-
-**Time Complexity**: O(1) to read a block
141
-
-**I/O Pattern**: One index read + one data read
142
-
-**Concurrency**: Multiple blocks can be read in parallel
143
-
144
-
#### Recovery Mechanism
107
+
### Recovery Mechanism
145
108
146
109
On startup, BlockDB checks for signs of an unclean shutdown. If detected, it performs recovery:
147
110
148
-
1. Compares the data file size with the indexed data size (stored in index header)
149
-
2. If data file is larger, starts scanning from where the index left off
111
+
1. Compares the data file size with the indexed data size (stored in the index header)
112
+
2. If the data file is larger, it starts scanning from where the index left off
150
113
3. For each unindexed block found:
151
-
- Validates block header and checksum
114
+
- Validates the block header and checksum
152
115
- Writes the corresponding index entry
153
-
4. Updates maximum contiguous height
116
+
4. Updates the max contiguous height and max block height
154
117
5. Persists the updated index header
155
118
156
-
### Concurrency Model
157
-
158
-
BlockDB uses a reader-writer lock for overall thread safety, with atomic operations for write coordination:
159
-
160
-
- Multiple threads can read different blocks simultaneously without blocking
161
-
- Multiple threads can write concurrently - they use atomic operations to allocate unique space in the data file
162
-
- The reader-writer lock ensures consistency between reads and writes
163
-
164
119
## Usage
165
120
166
121
### Creating a Database
@@ -169,8 +124,6 @@ BlockDB uses a reader-writer lock for overall thread safety, with atomic operati
0 commit comments