Introduction
One of the main features of SKALE Network is node rotation, and this is performed through a BLS Snapshot process. Briefly, if node A leaves a SKALE Chain for any reason (e.g. random rotation, node exit, etc.), another node B will be chosen to replace it. Once node B is chosen, it needs all the information about previous blocks, transactions, etc. from the SKALE chain. SKALE Network solves this by periodically performing snapshots of the SKALE chain file system on each node so that nodes can share the latest snapshot with incoming node B. Additionally, a node can be restarted from a snapshot if the node was offline for a long period of time, if it cannot catch up with other nodes using SKALE Consensus’ catch-up algorithm. [Graphic placeholder: Snapshot timeline showing rotation and handoff to new node]Design
skaled uses the btrfs to create snapshots.btrfs (B-tree File System)Linux filesystem designed for high performance and reliability, featuring built-in support for snapshots, checksums, compression, and pooling of multiple storage devices.Instead of overwriting data in place, Btrfs writes new changes to a fresh location and updates pointers to them. This makes it possible to take instant, space-efficient snapshots, detect data corruption using checksums, and roll back safely without slowing the system down.
- First block on SKALE chain occurred at
- Node does snapshot every seconds (configurable number, stored in SKALE chain config, so it is similar for all nodes in SKALE chain)
- (k+1)-th snapshot will be done once another block’s B timestamp crosses boundary
- Node updates last_snapshotted_block_with_hash with k-th snapshot block number
- If it is time to do snapshot and node already has 3 snapshots stored, it deletes the latest of them
- Node creates a snapshot S_latest
- Node updates last_snapshot_creation_time with B’s timestamp
- Node calculates S_latest’s hash in separate thread (computes hash of every file in this snapshot including filestorage), assuming it will be successfully calculated before next snapshot is done. So (k+1)-th snapshot will be ready to be used only when (k+2)-th snapshot will be performing
- Node updates stateRoot field with k-th snapshot hash
- Node A chooses a random node from SKALE chain and requests the last snapshot block number
- Node A requests all nodes from the SKALE chain to send a snapshot hash signed with its corresponding BLS key
- Once node A receives all hashes and signatures, A tries to choose a hash H similar on at least 2/3 + 1 nodes, then A collects their BLS signatures into one and verifies it. (If steps 1–3 fail, a node will not start.)
- Node A chooses a random node from those 2/3 + 1 nodes and downloads a snapshot from it, computes its hash and confirms whether it is similar to H. If it is similar then a node starts from this snapshot, otherwise node A will attempt to download a snapshot from another node
stateRoot is needed to determine whether there are any node software issues. Each time a new block is passed from consensus, a node compares its own stateRoot with the stateRoot of the incoming block (so snapshot hashes of the last block from different nodes are compared). If the stateRoots fail to match, then a software issue is assumed and the node must restart from a snapshot.
JSON-RPC Snapshot Methods
skale_getSnapshot
Parameters- blockNumber: integer, a block number
- autoCreate: Boolean, create snapshot if it does not exist
- dataSize: integer, the size of snapshot in bytes
- maxAllowedChunkSize: integer, the maximum chunk size in bytes
skale_downloadSnapshotFragment
Returns a snapshot fragment. Parameters- blockNumber: a block number, or the string “latest”
- from: a block number
- size: integer, the size of fragment in bytes
- isBinary: Boolean
- size: integer, the size of chunk in bytes
- data: base64, btrfs data
skale_getSnapshotSignature
Returns signature of snapshot hash on given block number. Parameters- blockNumber: integer, a block number
- X: string, X coordinate of signature
- Y: string, Y coordinate of signature
- helper: integer, minimum number such that Y=(X+helper)^3 is a square in Fq
- hash: string, hash of a snapshot on given block number
- signerIndex: integer, receiver’s index in SKALE chain
skale_getLatestSnapshotBlockNumber
Returns the latest snapshotted block’s number. Parameters NULL Returns- blockNumber: integer, the latest snapshotted block’s number
