Skip to main content

Storage

Overview

The dogechain currently utilizes LevelDB for data storage, as well as an in-memory data store.

Throughout the dogechain, when modules need to interact with the underlying data store, they don't need to know which DB engine or service they're speaking to.

The DB layer is abstracted away between a module called Storage, which exports interfaces that modules query.

Each DB layer, for now only LevelDB, implements these methods separately, making sure they fit in with their implementation.

blockchain/storage/storage.go
// Storage is a generic blockchain storage
type Storage interface {
ReadCanonicalHash(n uint64) (types.Hash, bool)
WriteCanonicalHash(n uint64, hash types.Hash) error

ReadHeadHash() (types.Hash, bool)
ReadHeadNumber() (uint64, bool)
WriteHeadHash(h types.Hash) error
WriteHeadNumber(uint64) error

WriteForks(forks []types.Hash) error
ReadForks() ([]types.Hash, error)

WriteDiff(hash types.Hash, diff *big.Int) error
ReadDiff(hash types.Hash) (*big.Int, bool)

WriteHeader(h *types.Header) error
ReadHeader(hash types.Hash) (*types.Header, error)

WriteCanonicalHeader(h *types.Header, diff *big.Int) error

WriteBody(hash types.Hash, body *types.Body) error
ReadBody(hash types.Hash) (*types.Body, error)

WriteSnapshot(hash types.Hash, blob []byte) error
ReadSnapshot(hash types.Hash) ([]byte, bool)

WriteReceipts(hash types.Hash, receipts []*types.Receipt) error
ReadReceipts(hash types.Hash) ([]*types.Receipt, error)

WriteTxLookup(hash types.Hash, blockHash types.Hash) error
ReadTxLookup(hash types.Hash) (types.Hash, bool)

Close() error
}

LevelDB

Prefixes

In order to make querying the LevelDB storage deterministic, and to avoid key storage clashing, the dogechain leverages prefixes and sub-prefixes when storing data

blockchain/storage/keyvalue.go
// Prefixes for the key-value store
var (
// DIFFICULTY is the difficulty prefix
DIFFICULTY = []byte("d")

// HEADER is the header prefix
HEADER = []byte("h")

// HEAD is the chain head prefix
HEAD = []byte("o")

// FORK is the entry to store forks
FORK = []byte("f")

// CANONICAL is the prefix for the canonical chain numbers
CANONICAL = []byte("c")

// BODY is the prefix for bodies
BODY = []byte("b")

// RECEIPTS is the prefix for receipts
RECEIPTS = []byte("r")

// SNAPSHOTS is the prefix for snapshots
SNAPSHOTS = []byte("s")

// TX_LOOKUP_PREFIX is the prefix for transaction lookups
TX_LOOKUP_PREFIX = []byte("l")
)

// Sub-prefixes
var (
HASH = []byte("hash")
NUMBER = []byte("number")
EMPTY = []byte("empty")
)

Future Plans

The plans for the near future include adding some of the most popular DB solutions, such as:

  • PostgreSQL
  • MySQL

📜 Resources