Block Rotation
Introduction
SKALE Chain Block rotation is set by the rotate_after_block parameter in static_schain_params.json. The current default value is 1,024,000 blocks and is tuned by performance of consensus, skaled, and node storage.
Each SKALE Chain maintains a minimum to maximum number of blocks, currently 4,096,000 to 5,119,999 blocks.
Rotation is performed across 4 databases. Each database contains:
-
blocks
-
transactions and their receipts
-
log blooms
-
"best" (lastBlockHash, best block of the canonical chain)
-
"chainStart" (firstBlockHash, used when full chain isn’t available, for example after snapshot import)
Specification
-
SKALED maintains not an exact amount of blocks set in the config, but at least this amount.
-
Config parameter rotate_after_block sets the number of blocks after which skaled rotates 1 out of 4 databases. As a result, skaled maintains a minimum of rotate_after_block * 4, and a maximum rotate_after_block * 5 – 1 blocks.
-
Database rotation happens just before a new block is inserted.
API Changes
Calls | Changes |
---|---|
eth_getBlockByNumber/eth_getBlockByHash |
may return null |
eth_getBlockTransactionCountByNumber/eth_getBlockTransactionCountByHash |
may return null |
eth_getUncleCountByBlockNumber/eth_getUncleCountByBlockHash |
may return null |
eth_getTransactionByBlockHashAndIndex/eth_getTransactionByBlockNumberAndIndex |
may return null |
eth_getUncleByBlockHashAndIndex/eth_getUncleByBlockNumberAndIndex |
may return null |
eth_getTransactionByHash |
may return null |
eth_getTransactionReceipt |
may return null |
eth_getFilterLogs/eth_getLogs |
will treat removed blocks as if they have 0 logs |
Mechanisms
Rotation is performed in the following DBs: blocks_and_extras
This database contains:
-
Blocks
-
Transactions and their receipts
-
Log blooms
-
“best” and “chainStart”
Directory with DB contains subdirectories:
-
0.db
-
1.db
-
2.db
-
3.db
-
4.db
These directories are created automatically.
On rotation, one directory is deleted and re-created. The order of rotation is 0→4→3→2→1→0
The “current” piece for writing is marked with the key:
const std::string current_piece_mark_key =
"ead48ec575aaa7127384dee432fc1c02d9f6a22950234e5ecf59f35ed9f6e78d"
with an empty value.
On rotation, this key is killed in old current piece and is created in new current piece.
On start, it’s searched in all pieces.
Insert/update operations go to current piece.
Read operations are performed in all pieces from most recent to least recent, until found.
Kill operations are performed in all pieces.