Crate chain_storage

source ·
Expand description

Block storage crate.

Data model

This storage is designed to be independent from a particular block strucure. At the same time, since it is designed specifically for block chains, it handles the minimum amount of data required to maintain consistency. Such data includes:

  • Block ID
  • ID of the parent block
  • Chain length

This data is provided alongside a block in the BlockInfo structure.

Volatile + permanent storage model

Since blockchain can be branching extensively, this library provides the mechanism to have multiple blockchain branches. However, doing so for all block screates a lot of overhead for maintaining volatile storage. At the same time, branches usually die out pretty fast.

Given that, the storage is separated into two parts:

  • Volatile storage should be used for the part of a blockchain where a developer may need access to different branches.
  • Permanent storage for the part of the blockchain that is guaranteed not to change anymore.

Moving blocks to the permanent store.

if you have this block structure and call store.flush_to_permanent_store(block 2 id), then block 1 and block 2 will be moved to the permanent storage. if you call store.flush_to_permanent_store(block 3 id), block 3 will also be moved to the permanent store, but block 3' will still exist in the volatile store. note that if you call store.get_blocks_by_chain_length(3) only block 3 (which is in the permanent store) will be returned; and you cannot call store.flush_to_permanent_store(block 3' id) now.

fig.1 - note that root does not actually exist, this is an id referredby the first block in the chain

+---------+       +---------+
|         |       |         |
| block 4 |       | block 4'|
|         |       |         |
+---------+       +---------+
     |                 |
     |                 |
     v                 v
+---------+       +---------+
|         |       |         |
| block 3 |       | block 3'|
|         |       |         |
+---------+       +---------+
     |                 |
     |                 |
     v                 |
+---------+            |
|         |            |
| block 2 +<-----------+
|         |
+---------+
     |
     |
     v
+---------+
|         |
| block 1 |
|         |
+---------+
     |
     |
     v
+---------+
|         |
|  (root) |
|         |
+---------+

Removing stale branches

If you want to clean up branches, do the following:

  • Call store.get_tips_ids(), in our example it will return [Block 4 id, Block 4' id];
  • Determine which branches do you want to remove.
  • Call, for example, store.prune_branch(Block 4' id).

Performance benefits of permanent storage

Since blocks in the permanent storage are stored just one after another (the structure is block_length.to_le_bytes() ++ block_bytes and a file with references to blocks in the order they were added to the storage), it allows for the following scenarios:

  • Very fast block iteration
  • Transferring a portion of the data file over the network without locking it.
  • O(1) access by chain length.

fig. 2 - permanent storage structure

store                  block no. index

+--------------+       +-------------+
|              |       |             |
| block1       |       | block1 pos  |
|              |       |             |
+--------------+       +-------------+
|              |       |             |
| block2       |       | block2 pos  |
|              |       |             |
+--------------+       +-------------+
|              |       |             |
| ...          |       | ...         |
|              |       |             |
+--------------+       +-------------+
|              |       |             |
| blockn       |       | blockn pos  |
|              |       |             |
+--------------+       +-------------+

Storage directory layout

store
├── permanent       - permanent storage directory
│   └── flatfile    - storage file that can be transferred over the network
└── volatile        - volatile storage

Modules

Structs

  • A structure that holds the information about a blocks, that is needed to maintain consistency of the storage. This include the ID of the blocks, the ID of its parent and the length of the block chain for the given block.
  • Iterator over blocks. Starts from n-th ancestor of the given block.
  • Wrapper for data held by the database. This wrapper holds structs returned by both volatile and permanent storage to ensure we don’t have needless copying on return. Data should be accessed through the AsRef trait.

Enums