BoltDB is the persistent key-value store database utilised by the Prysm client. A piece of software that Prysm initially inherited from its origins as a Geth fork was its storage engine, LevelDB. As a simple embedded key-value store written in Go, LevelDB worked well; however, after observing a number of corruption-related issues, it was decided to survey some other options for the project.
There were two main requirements of the new storage engine; it needed to be an embedded environment, and written in Go. After a considerable amount of testing, three options in particular met this criteria as well as performance expectancy: BoltDB, Badger and the old option, LevelDB.
After testing and benchmarking all three options, Bolt was decided upon as the best option for Prysm. Although LevelDB and Badger performed better in write-heavy benchmarks (as expected for an LSM-tree), the difference was not substantial, while BoltDB performed much better on read-heavy benchmarks. Further, though Bolt also consumes more space on disk compared to the other two options, it provides the strongest guarantees against data loss, one of the most crucial goals of the project.
All database related logic is contained in the
db/ directory of the Prysm repository. Given that BoltDB is a key-value store backend, 'buckets' (akin to tables in relational databases) are required for data storage. Blocks, transactions, state, proposals and attestations are are all defined in these buckets, in what is known as 'bucket data'.
Example: bucket creation
A user wants to create a new bucket named
myNewStuffBucket to the database. To perform this action, the bucket data must be added to the template found in
db/schema.go, like so:
The newly created bucket is added to the
NewDB constructor in
db/db.go, like so: