Documentation
¶
Index ¶
- Constants
- Variables
- func AnyCheckpointFileExists(dir string, fileName string) (bool, error)
- func Checkpoints(dir string) ([]int, error)
- func ConvertCheckpointV6ToV7(inputDir string, inputFileName string, outputDir string, outputFileName string, ...) error
- func ConvertCheckpointV7ToV6(v7Dir string, v7File string, execDir string, prevCheckpointNum int, ...) error
- func CopyCheckpointFile(filename string, from string, to string) ([]string, error)
- func CreateCheckpointWriterForFile(dir, filename string, logger zerolog.Logger) (io.WriteCloser, error)
- func DeleteCheckpointFiles(dir string, fileName string) error
- func EncodeDelete(rootHash ledger.RootHash) []byte
- func EncodeUpdate(update *ledger.TrieUpdate) []byte
- func FromV6LeafNode(v6 *node.Node) (*payloadless.Node, error)
- func FromV6Trie(v6 *trie.MTrie) (*payloadless.MTrie, error)
- func FromV6Tries(v6Tries []*trie.MTrie) ([]*payloadless.MTrie, error)
- func HasRootCheckpoint(dir string) (bool, error)
- func HasRootCheckpointV7(dir string) (bool, error)
- func IterateCheckpointNodes(logger zerolog.Logger, dir string, fileName string, fn IterateNodeFunc) error
- func ListCheckpoints(dir string) ([]int, int, error)
- func ListCheckpointsWithInfo(dir string) ([]CheckpointInfo, *CheckpointInfo, error)
- func ListV6Checkpoints(dir string) ([]int, int, error)
- func ListV7Checkpoints(dir string) ([]int, int, error)
- func LoadCheckpoint(filepath string, logger zerolog.Logger) (tries []*trie.MTrie, errToReturn error)
- func NumberToFilename(n int) string
- func NumberToFilenamePart(n int) string
- func NumberToFilenameV7(n int) string
- func OpenAndReadCheckpointV6(dir string, fileName string, logger zerolog.Logger) (triesToReturn []*trie.MTrie, errToReturn error)
- func OpenAndReadCheckpointV7(dir string, fileName string, logger zerolog.Logger) (triesToReturn []*payloadless.MTrie, errToReturn error)
- func OpenAndReadLeafNodesFromCheckpointV6(allLeafNodesCh chan<- *LeafNode, dir string, fileName string, ...) (errToReturn error)
- func ReadCheckpointFileSize(dir string, fileName string) (uint64, error)
- func ReadCheckpointTriesRootHash(logger zerolog.Logger, dir, fileName string) ([]ledger.RootHash, error)
- func ReadTriesRootHash(logger zerolog.Logger, dir string, fileName string) ([]ledger.RootHash, error)
- func ReadTriesRootHashV7(logger zerolog.Logger, dir string, fileName string) ([]ledger.RootHash, error)
- func RootCheckpointFilenameV7() string
- func SoftlinkCheckpointFile(filename string, from string, to string) ([]string, error)
- func StoreCheckpointV5(dir string, fileName string, logger zerolog.Logger, tries ...*trie.MTrie) (errToReturn error)
- func StoreCheckpointV6(tries []*trie.MTrie, outputDir string, outputFile string, ...) error
- func StoreCheckpointV6Concurrently(tries []*trie.MTrie, outputDir string, outputFile string, ...) error
- func StoreCheckpointV6SingleThread(tries []*trie.MTrie, outputDir string, outputFile string, ...) error
- func StoreCheckpointV7(tries []*payloadless.MTrie, outputDir string, outputFile string, ...) error
- func StoreCheckpointV7Concurrently(tries []*payloadless.MTrie, outputDir string, outputFile string, ...) error
- func StoreCheckpointV7SingleThread(tries []*payloadless.MTrie, outputDir string, outputFile string, ...) error
- func VerifyCheckpointHashes(logger zerolog.Logger, dir string, fileName string, nWorker uint) error
- type CheckpointInfo
- type CheckpointNode
- type Checkpointer
- func (c *Checkpointer) Checkpoint(to int) (err error)
- func (c *Checkpointer) CheckpointWriter(to int) (io.WriteCloser, error)
- func (c *Checkpointer) Checkpoints() ([]int, error)
- func (c *Checkpointer) CheckpointsV6() ([]int, error)
- func (c *Checkpointer) CheckpointsV7() ([]int, error)
- func (c *Checkpointer) Dir() string
- func (c *Checkpointer) HasRootCheckpoint() (bool, error)
- func (c *Checkpointer) HasRootCheckpointV7() (bool, error)
- func (c *Checkpointer) LatestCheckpointV6() (int, error)
- func (c *Checkpointer) LoadCheckpoint(checkpoint int) ([]*trie.MTrie, error)
- func (c *Checkpointer) LoadCheckpointV6(checkpoint int) ([]*trie.MTrie, error)
- func (c *Checkpointer) LoadLatestCheckpointV7() (tries []*payloadless.MTrie, loadedCheckpoint int, err error)
- func (c *Checkpointer) LoadRootCheckpoint() ([]*trie.MTrie, error)
- func (c *Checkpointer) LoadRootCheckpointV7() ([]*payloadless.MTrie, error)
- func (c *Checkpointer) NotCheckpointedSegments() (from, to int, err error)
- func (c *Checkpointer) RemoveCheckpoint(checkpoint int) errordeprecated
- func (c *Checkpointer) RemoveCheckpointV6(checkpoint int) error
- func (c *Checkpointer) RemoveCheckpointV7(checkpoint int) error
- type Crc32Reader
- type Crc32Writer
- type DiskWAL
- func (w *DiskWAL) Done() <-chan struct{}
- func (w *DiskWAL) NewCheckpointer() (*Checkpointer, error)
- func (w *DiskWAL) PauseRecord()
- func (w *DiskWAL) Ready() <-chan struct{}
- func (w *DiskWAL) RecordDelete(rootHash ledger.RootHash) error
- func (w *DiskWAL) RecordUpdate(update *ledger.TrieUpdate) (segmentNum int, skipped bool, err error)
- func (w *DiskWAL) Replay(checkpointFn func(tries []*trie.MTrie) error, ...) error
- func (w *DiskWAL) ReplayLogsOnly(checkpointFn func(tries []*trie.MTrie) error, ...) error
- func (w *DiskWAL) ReplayOnForest(forest *mtrie.Forest) error
- func (w *DiskWAL) ReplayOnPayloadlessForest(forest *payloadless.Forest) error
- func (w *DiskWAL) ReplayOnPayloadlessForestUntil(forest *payloadless.Forest, targetRootHash ledger.RootHash) (found bool, sourceNumber int, err error)
- func (w *DiskWAL) Segments() (first, last int, err error)
- func (w *DiskWAL) UnpauseRecord()
- type IterateNodeFunc
- type LeafNode
- type LedgerWAL
- type PayloadlessTrieQueue
- type SyncOnCloseRenameFile
- type TrieQueue
- type WALOperation
- type WriterSeekerCloser
Constants ¶
const ( MagicBytesCheckpointHeader uint16 = 0x2137 MagicBytesCheckpointSubtrie uint16 = 0x2136 MagicBytesCheckpointToptrie uint16 = 0x2135 MagicBytesPayloadHeader uint16 = 0x2138 )
const MaxVersion = VersionV7
MaxVersion is the latest checkpoint version we support. Need to update MaxVersion when creating a newer version.
const SegmentSize = 32 * 1024 * 1024 // 32 MB
const V7FileSuffix = ".v7"
V7FileSuffix is appended to V7 (payloadless) checkpoint filenames so they are visibly distinct from V6 files and can coexist with them in the same directory. Example: V6 = "checkpoint.00000100", V7 = "checkpoint.00000100.v7"
const VersionV1 uint16 = 0x01
const VersionV3 uint16 = 0x03
Versions was reset while changing trie format, so now bump it to 3 to avoid conflicts Version 3 contains a file checksum for detecting corrupted checkpoint files.
const VersionV4 uint16 = 0x04
Version 4 contains a footer with node count and trie count (previously in the header). Version 4 also reduces checkpoint data size. See EncodeNode() and EncodeTrie() for more details.
const VersionV5 uint16 = 0x05
Version 5 includes these changes: - remove regCount and maxDepth from serialized nodes - add allocated register count and size to serialized tries - reduce number of bytes used to encode payload value size from 8 bytes to 4 bytes. See EncodeNode() and EncodeTrie() for more details.
const VersionV6 uint16 = 0x06
Version 6 includes these changes:
- trie nodes are stored in additional 17 checkpoint files, with .0, .1, .2, ... .16 as file name extension
const VersionV7 uint16 = 0x07
Version 7 includes these changes:
- payloadless mode: leaf nodes store payload hashes (32 bytes) instead of full payloads
- used by payloadless execution nodes, which read register values from the storehouse
Variables ¶
var CheckpointHasRootHash = checkpointHasRootHash
var CheckpointHasSingleRootHash = checkpointHasSingleRootHash
var ErrCheckpointHashMismatch = errors.New("checkpoint hash verification failed")
ErrCheckpointHashMismatch indicates that a node's stored (cached) hash does not match the hash recomputed from its content (leaf node) or its children (interim node). It signals a corrupt checkpoint.
var ErrCheckpointIntegrity = errors.New("checkpoint integrity violation")
ErrCheckpointIntegrity indicates that a checkpoint's trie structure is corrupt: an interim node references a child that has not been seen yet (a forward or out-of-range reference, violating the descendants-first ordering), a node is not referenced by any parent interim node or trie root (an orphan node), or a node declares a height outside the valid range.
var ErrEOFNotReached = errors.New("expect to reach EOF, but actually didn't")
ErrEOFNotReached for indicating end of file not reached error
Functions ¶
func AnyCheckpointFileExists ¶
AnyCheckpointFileExists reports whether any file belonging to a checkpoint with the given fileName exists under dir: the checkpoint header, any of its part files, or any stray file sharing the same prefix (for example a leftover from an interrupted write). It is intended for callers that must refuse to overwrite the checkpoint output, since writing a checkpoint recreates all of these files.
No error returns are expected during normal operation.
func Checkpoints ¶ added in v0.28.1
Checkpoints returns all the checkpoint numbers in asc order
func ConvertCheckpointV6ToV7 ¶
func ConvertCheckpointV6ToV7( inputDir string, inputFileName string, outputDir string, outputFileName string, logger zerolog.Logger, nWorker uint, stream bool, ) error
ConvertCheckpointV6ToV7 reads a V6 checkpoint at (inputDir, inputFileName), converts it to a V7 (payloadless) checkpoint, and writes it to (outputDir, outputFileName).
Behavior:
- The input V6 part files (header + 17 part files) must all be present.
- The output filename must use the V7 suffix (e.g. "checkpoint.00000100.v7"); a missing or wrong suffix is rejected.
- No output file (including any part file) with the same name may already exist; otherwise the call is rejected and the existing output is left untouched.
- The conversion preserves trie root hashes: a V7 checkpoint round-tripped through this function matches the V6 root hashes exactly.
- On any failure after the checks above, the partially written output is removed.
`stream` selects the conversion strategy:
- false: read the entire V6 forest into memory, convert it, and write the V7 checkpoint. Peak memory is approximately the sum of the V6 trie set and the V7 trie set, so mainnet-scale checkpoints need a host with memory headroom.
- true: stream each part file node-by-node (see [convertCheckpointV6ToV7Stream]). Peak memory is independent of checkpoint size, at the cost of not re-deriving the trie root hashes from the converted nodes.
nWorker controls how many of the 16 subtrie part files are processed in parallel; valid range is [1, 16]. In the non-streaming mode, the V6 read step also reads the 16 subtrie part files concurrently using its own internal worker pool (this function does not gate that), so the total parallelism while running may exceed nWorker briefly during the read→write hand-off.
Expected error returns during normal operation:
- none — all error returns indicate a malformed input, a clobbering output, or a write failure, which are treated as exceptions.
func ConvertCheckpointV7ToV6 ¶
func ConvertCheckpointV7ToV6( v7Dir string, v7File string, execDir string, prevCheckpointNum int, walFrom int, walTo int, outputDir string, outputFile string, logger zerolog.Logger, nWorker uint, ) error
ConvertCheckpointV7ToV6 reconstructs a full V6 checkpoint from a V7 (payloadless) checkpoint by re-sourcing every leaf's payload from a previous full V6 checkpoint plus the WAL segments written between that previous checkpoint and the V7 checkpoint.
Rationale: a V7 checkpoint stores only a leaf hash per register, not the payload, so it cannot be turned back into a V6 checkpoint on its own. However, every payload referenced by the V7 checkpoint must exist either in the previous full checkpoint (if the register was not updated since) or in one of the WAL segments written since (if it was). By computing HashLeaf(path, value) for each candidate payload from those two sources and matching it against the leaf hash stored in the V7 checkpoint, the original payload is recovered.
Inputs:
- (v7Dir, v7File): the V7 checkpoint header file to convert, e.g. "checkpoint.00000100.v7". Its number N is parsed from the filename.
- execDir: the standard ledger WAL directory holding both the previous V6 checkpoint part files and the numbered WAL segment files.
- prevCheckpointNum: the previous full V6 checkpoint number M to source unchanged payloads from. If negative, it is auto-discovered as the latest V6 checkpoint in execDir with number strictly less than N. If no such numbered checkpoint exists, it falls back to the V6 root checkpoint, in which case the full WAL range [0, N] is replayed.
- walFrom, walTo: the inclusive WAL segment range to source updated payloads from. If negative, they default to (M+1, N] — i.e. all updates applied after the previous checkpoint up to and including the V7 checkpoint state.
- (outputDir, outputFile): where to write the reconstructed V6 checkpoint.
Memory: the checkpoint is processed one subtrie partition (first path nibble) at a time. For partition i, only that partition's payloads are held in memory while its V6 subtrie part file is written, then released before the next partition. nWorker partitions are processed concurrently (valid range [1, subtrieCount]), trading peak memory for speed.
Limitation: the per-trie regSize (AllocatedRegSize) field is metrics-only and is dropped by the V7 format; it is NOT reconstructed and is written as 0 in every trie root record. A warning is logged. This does not affect trie root hashes or any consensus-critical state; it only affects the LatestTrieRegSize metric until the node rebuilds tries.
The output filename must NOT carry the V7 suffix and no output part file may already exist; otherwise the call is rejected. On any failure, partially written output files are removed.
No error returns are expected during normal operation; all error returns indicate malformed input, missing source data, an unmatched leaf hash, a clobbering output, or an IO failure.
func CopyCheckpointFile ¶ added in v0.28.2
Copy the checkpoint file including the part files from the given `from` to the `to` directory it returns the path of all the copied files any error returned are exceptions
func CreateCheckpointWriterForFile ¶
func CreateCheckpointWriterForFile(dir, filename string, logger zerolog.Logger) (io.WriteCloser, error)
CreateCheckpointWriterForFile returns a file writer that will write to a temporary file and then move it to the checkpoint folder by renaming it.
func DeleteCheckpointFiles ¶
DeleteCheckpointFiles removes the header file and all part files of the checkpoint with the given file name in `dir`. It is version-agnostic: `fileName` selects the checkpoint, so pass the V6 name ("checkpoint.00000100", "root.checkpoint") or the V7 name (same, suffixed with V7FileSuffix).
Deleting a checkpoint that isn't there is not an error. This makes the function suitable for clearing a partially-written checkpoint left behind by a process that died mid-write: a checkpoint is only complete once its header file exists, so an incomplete one can always be discarded and rewritten from its source.
No error returns are expected during normal operation.
func EncodeDelete ¶
func EncodeUpdate ¶
func EncodeUpdate(update *ledger.TrieUpdate) []byte
func FromV6LeafNode ¶
func FromV6LeafNode(v6 *node.Node) (*payloadless.Node, error)
FromV6LeafNode converts a V6 leaf node.Node into the equivalent V7 (payloadless) payloadless.Node. The conversion preserves the node's path, height, and computed hash; the payload value is replaced by the height-0 leaf hash HashLeaf(path, value).
For an unallocated leaf (empty or nil payload), the result is a payloadless leaf with leafHash == nil and the same default-for-height node hash.
Expected error returns during normal operation:
- none — the only failure mode is passing an interim node, which is treated as a programmer error rather than a benign error.
func FromV6Trie ¶
func FromV6Trie(v6 *trie.MTrie) (*payloadless.MTrie, error)
FromV6Trie converts a V6 trie.MTrie into the equivalent V7 (payloadless) payloadless.MTrie. Every node is converted via FromV6LeafNode (leaves) or fromV6InterimNode (interim), preserving the node hashes; consequently the resulting V7 trie has the same root hash as the input V6 trie.
Shared sub-tries in the input (e.g. across a forest of related tries) are converted only once thanks to the visited-node memoization.
No error returns are expected during normal operation.
func FromV6Tries ¶
func FromV6Tries(v6Tries []*trie.MTrie) ([]*payloadless.MTrie, error)
FromV6Tries converts a slice of V6 tries to V7 tries, preserving root hashes. Sub-tries shared across multiple input tries are converted once.
No error returns are expected during normal operation.
func HasRootCheckpoint ¶ added in v0.28.1
func HasRootCheckpointV7 ¶
HasRootCheckpointV7 checks if a V7 (payloadless) root checkpoint exists.
func IterateCheckpointNodes ¶
func IterateCheckpointNodes(logger zerolog.Logger, dir string, fileName string, fn IterateNodeFunc) error
IterateCheckpointNodes streams every node of a checkpoint (V6 or V7), invoking fn once per node in descendants-first (post-order DFS) order, the same order in which nodes are written to disk. The whole checkpoint is never loaded into memory: each node is decoded from the raw byte stream and handed to fn without retaining child pointers or payloads.
The version is detected from the checkpoint header file's version bytes; each part file's magic+version bytes are additionally validated while reading. Per-part-file CRC32 checksums are verified, matching the regular checkpoint readers.
Counts produced by fn are over the unique nodes of the whole checkpoint forest (nodes shared between tries are stored, and therefore delivered, exactly once).
While streaming, the trie structure is verified:
- every interim node must reference only already-seen, in-range children (descendants-first ordering); and
- every node must be referenced by some parent interim node or trie root.
To perform these checks without retaining nodes, the iterator keeps two bits per node (a "default node" bit and a "referenced" bit), i.e. O(nodeCount) bits of memory — far smaller than the nodes themselves, but not constant.
Expected error returns during normal operation:
- ErrCheckpointIntegrity: when an interim node references an unknown/forward child, when a node is not referenced by any parent or trie root, or when a node declares an out-of-range height.
- os.ErrNotExist (wrapped): when a checkpoint part file is missing.
func ListCheckpoints ¶ added in v0.28.1
ListCheckpoints returns all the numbers of the checkpoint files (both V6 and V7), and the number of the last checkpoint. Note: it doesn't include the root checkpoint file. For version-specific listing, use ListV6Checkpoints or ListV7Checkpoints.
func ListCheckpointsWithInfo ¶
func ListCheckpointsWithInfo(dir string) ([]CheckpointInfo, *CheckpointInfo, error)
ListCheckpointsWithInfo returns all checkpoint infos and the latest checkpoint info. It detects both V6 and V7 checkpoints based on their filenames. Note: it doesn't include the root checkpoint file.
func ListV6Checkpoints ¶
ListV6Checkpoints returns all V6 checkpoint numbers (unsorted) and the latest V6 checkpoint number. Returns -1 as the latest if no V6 checkpoints exist.
func ListV7Checkpoints ¶
ListV7Checkpoints returns all V7 checkpoint numbers (unsorted) and the latest V7 checkpoint number. Returns -1 as the latest if no V7 checkpoints exist.
func LoadCheckpoint ¶
func NumberToFilename ¶
func NumberToFilenamePart ¶
func NumberToFilenameV7 ¶
NumberToFilenameV7 returns the V7 (payloadless) checkpoint filename for a given number. Example: 100 -> "checkpoint.00000100.v7"
func OpenAndReadCheckpointV6 ¶ added in v0.28.1
func OpenAndReadCheckpointV6(dir string, fileName string, logger zerolog.Logger) ( triesToReturn []*trie.MTrie, errToReturn error, )
OpenAndReadCheckpointV6 open the checkpoint file and read it with readCheckpointV6
func OpenAndReadCheckpointV7 ¶
func OpenAndReadCheckpointV7(dir string, fileName string, logger zerolog.Logger) ( triesToReturn []*payloadless.MTrie, errToReturn error, )
OpenAndReadCheckpointV7 opens a V7 (payloadless) checkpoint and returns the tries as []*payloadless.MTrie. The file must be a V7 checkpoint — V6 (and any other version) is rejected, both because the V7 reader explicitly validates the V7 magic+version at every part-file header and because V7 files use a different filename suffix (V7FileSuffix) so they're trivially distinguishable on disk.
func OpenAndReadLeafNodesFromCheckpointV6 ¶ added in v0.30.0
func OpenAndReadLeafNodesFromCheckpointV6( allLeafNodesCh chan<- *LeafNode, dir string, fileName string, expectedRootHash ledger.RootHash, logger zerolog.Logger) ( errToReturn error)
OpenAndReadLeafNodesFromCheckpointV6 takes a channel for pushing the leaf nodes that are read from the given checkpoint file specified by dir and fileName. It returns when finish reading the checkpoint file and the input channel can be closed. It requires the checkpoint file only has one trie.
func ReadCheckpointFileSize ¶ added in v0.33.10
ReadCheckpointFileSize returns the total size of the checkpoint file
func ReadCheckpointTriesRootHash ¶
func ReadCheckpointTriesRootHash(logger zerolog.Logger, dir, fileName string) ([]ledger.RootHash, error)
ReadCheckpointTriesRootHash reads the trie root hashes from either a V6 or V7 (payloadless) checkpoint, dispatching by the V7FileSuffix on `fileName`.
Both checkpoint versions may coexist in the same directory, so callers that only have a directory and filename (and not the version) should use this function rather than dispatching on the suffix themselves. Callers that already know which version they want should call ReadTriesRootHash or ReadTriesRootHashV7 directly.
No error returns are expected during normal operation.
func ReadTriesRootHash ¶ added in v0.32.2
func ReadTriesRootHashV7 ¶
func ReadTriesRootHashV7(logger zerolog.Logger, dir string, fileName string) ( []ledger.RootHash, error, )
ReadTriesRootHashV7 returns the trie root hashes recorded in a V7 (payloadless) checkpoint without decoding any node payloads. It first validates the part-file checksums and then reads only the per-trie metadata records at the tail of the top-trie file.
fileName is the V7 header filename (typically ending in V7FileSuffix).
func RootCheckpointFilenameV7 ¶
func RootCheckpointFilenameV7() string
RootCheckpointFilenameV7 returns the on-disk filename of the V7 (payloadless) root checkpoint. The V7 file lives alongside the V6 root (bootstrap.FilenameWALRootCheckpoint), with the V7 suffix appended, so the two can coexist while a node is being migrated between modes.
func SoftlinkCheckpointFile ¶ added in v0.33.37
SoftlinkCheckpointFile creates soft links of the checkpoint file including the part files from the given `from` to the `to` directory
func StoreCheckpointV5 ¶ added in v0.28.1
func StoreCheckpointV5(dir string, fileName string, logger zerolog.Logger, tries ...*trie.MTrie) ( errToReturn error, )
StoreCheckpointV5 writes the given tries to checkpoint file, and also appends a CRC32 file checksum for integrity check. Checkpoint file consists of a flattened forest. Specifically, it consists of:
- a list of encoded nodes, where references to other nodes are by list index.
- a list of encoded tries, each referencing their respective root node by index.
Referencing to other nodes by index 0 is a special case, meaning nil.
As an important property, the nodes are listed in an order which satisfies Descendents-First-Relationship. The Descendents-First-Relationship has the following important property: When rebuilding the trie from the sequence of nodes, build the trie on the fly, as for each node, the children have been previously encountered. TODO: evaluate alternatives to CRC32 since checkpoint file is many GB in size. TODO: add concurrency if the performance gains are enough to offset complexity.
func StoreCheckpointV6 ¶ added in v0.28.1
func StoreCheckpointV6( tries []*trie.MTrie, outputDir string, outputFile string, logger zerolog.Logger, nWorker uint) error
StoreCheckpointV6 stores checkpoint file into a main file and 17 file parts. the main file stores:
- version
- checksum of each part file (17 in total)
- checksum of the main file itself the first 16 files parts contain the trie nodes below the subtrieLevel the last part file contains the top level trie nodes above the subtrieLevel and all the trie root nodes.
nWorker specifies how many workers to encode subtrie concurrently, valid range [1,16]
func StoreCheckpointV6Concurrently ¶ added in v0.28.1
func StoreCheckpointV6Concurrently(tries []*trie.MTrie, outputDir string, outputFile string, logger zerolog.Logger) error
StoreCheckpointV6Concurrently stores checkpoint file in v6 in max workers, useful during state extraction
func StoreCheckpointV6SingleThread ¶ added in v0.28.1
func StoreCheckpointV6SingleThread(tries []*trie.MTrie, outputDir string, outputFile string, logger zerolog.Logger) error
StoreCheckpointV6SingleThread stores checkpoint file in v6 in a single threaded manner, useful when EN is executing block.
func StoreCheckpointV7 ¶
func StoreCheckpointV7( tries []*payloadless.MTrie, outputDir string, outputFile string, logger zerolog.Logger, nWorker uint, ) error
StoreCheckpointV7 stores a payloadless checkpoint into a header file and 17 part files. The on-disk layout (header + 16 subtrie parts + top-trie part) mirrors V6, but each node and trie record is encoded by the payloadless flattener (payloadless.EncodeNode, payloadless.EncodeTrie) — leaves carry a 32-byte leaf hash, not a full payload.
nWorker specifies how many subtries to encode concurrently; valid range is [1,16].
func StoreCheckpointV7Concurrently ¶
func StoreCheckpointV7Concurrently(tries []*payloadless.MTrie, outputDir string, outputFile string, logger zerolog.Logger) error
StoreCheckpointV7Concurrently stores a V7 (payloadless) checkpoint using up to 16 worker goroutines to encode subtries in parallel.
func StoreCheckpointV7SingleThread ¶
func StoreCheckpointV7SingleThread(tries []*payloadless.MTrie, outputDir string, outputFile string, logger zerolog.Logger) error
StoreCheckpointV7SingleThread stores a V7 (payloadless) checkpoint in a single-threaded manner.
func VerifyCheckpointHashes ¶
VerifyCheckpointHashes verifies the cryptographic integrity of every node in a checkpoint (V6 or V7) by recomputing each node's hash and comparing it against the hash stored alongside the node on disk:
- For a leaf node, the hash is recomputed from its content: the payload value (V6) or the stored leaf hash (V7). This is the streaming equivalent of the per-leaf check performed by trie.MTrie.IsAValidTrie / node.Node.VerifyCachedHash.
- For an interim node, the hash is recomputed as HashInterNode of its two children's hashes (using the height-appropriate default hash for an empty child).
Nodes are streamed in descendants-first (post-order DFS) order, so every child's hash is verified and recorded before its parent is checked. A correct subtrie root hash therefore transitively attests the whole subtrie. The full forest is never materialized: only one 32-byte hash per node is retained (no node objects, no payloads), which is the improvement over loading the checkpoint and calling trie.MTrie.IsAValidTrie.
The 16 subtrie part files are verified concurrently using up to nWorker goroutines; nWorker must be in [1, 16]. The (small) top-trie part file is then verified single-threaded using the subtrie node hashes. Per-part-file CRC32 checksums and magic/version bytes are validated while reading, matching the regular checkpoint readers.
Expected error returns during normal operation:
- ErrCheckpointHashMismatch: when a node's stored hash does not match its recomputed hash.
- ErrCheckpointIntegrity: when an interim node references an out-of-range or forward child index.
- os.ErrNotExist (wrapped): when a checkpoint part file is missing.
Types ¶
type CheckpointInfo ¶
type CheckpointInfo struct {
Number int // Checkpoint number (e.g., 100 for "checkpoint.00000100")
Version uint16 // Checkpoint version (VersionV6 or VersionV7)
}
CheckpointInfo contains metadata about a checkpoint file parsed from its filename.
type CheckpointNode ¶
type CheckpointNode struct {
// Index is the 1-based global index of this node in the checkpoint's
// descendants-first node sequence. It matches the index scheme used to
// reference children: index 0 is reserved for the nil (empty) child.
Index uint64
// Height is the node's height in the trie.
Height uint16
// Hash is the node's hash.
Hash hash.Hash
// IsLeaf is true for leaf nodes and false for interim nodes.
IsLeaf bool
// IsDefault is true iff this node's hash equals the default hash for its
// height, i.e. the sub-trie rooted at this node is completely unallocated.
IsDefault bool
// Path is the register storage path. Only meaningful for leaf nodes.
Path ledger.Path
// PayloadSize is the encoded payload size (in bytes) recorded in a V6 leaf
// node's on-disk length prefix. It is 0 for interim nodes and for V7
// (payloadless) leaf nodes, which do not store payloads.
PayloadSize int
// LeftChildIndex and RightChildIndex are the global indices of an interim
// node's children; 0 means a nil (empty) child. Both are 0 for leaf nodes.
LeftChildIndex uint64
RightChildIndex uint64
}
CheckpointNode carries the decoded, per-node information passed to an IterateNodeFunc during a streaming iteration of a checkpoint. It is a lightweight view: no child pointers and no payload bytes are retained, so the caller can process arbitrarily large checkpoints without materializing the trie forest in memory.
type Checkpointer ¶
type Checkpointer struct {
// contains filtered or unexported fields
}
func NewCheckpointer ¶
func NewCheckpointer(wal *DiskWAL, keyByteSize int, forestCapacity int) *Checkpointer
func (*Checkpointer) Checkpoint ¶
func (c *Checkpointer) Checkpoint(to int) (err error)
Checkpoint creates new checkpoint stopping at given segment
func (*Checkpointer) CheckpointWriter ¶
func (c *Checkpointer) CheckpointWriter(to int) (io.WriteCloser, error)
func (*Checkpointer) Checkpoints ¶ added in v0.14.0
func (c *Checkpointer) Checkpoints() ([]int, error)
Checkpoints returns all the numbers of the checkpoint files in asc order. note, it doesn't include the root checkpoint file
func (*Checkpointer) CheckpointsV6 ¶
func (c *Checkpointer) CheckpointsV6() ([]int, error)
CheckpointsV6 returns all V6 checkpoint numbers in asc order. Use this when loading checkpoints in non-payloadless mode.
func (*Checkpointer) CheckpointsV7 ¶
func (c *Checkpointer) CheckpointsV7() ([]int, error)
CheckpointsV7 returns all V7 checkpoint numbers in asc order. Use this when loading checkpoints in payloadless mode.
func (*Checkpointer) Dir ¶ added in v0.28.1
func (c *Checkpointer) Dir() string
func (*Checkpointer) HasRootCheckpoint ¶
func (c *Checkpointer) HasRootCheckpoint() (bool, error)
func (*Checkpointer) HasRootCheckpointV7 ¶
func (c *Checkpointer) HasRootCheckpointV7() (bool, error)
HasRootCheckpointV7 checks if a V7 (payloadless) root checkpoint exists.
func (*Checkpointer) LatestCheckpointV6 ¶
func (c *Checkpointer) LatestCheckpointV6() (int, error)
LatestCheckpointV6 returns the number of the latest V6 checkpoint, or -1 if there are no V6 checkpoints. V7 (payloadless) files in the same directory are ignored — see [Checkpointer.listV6Checkpoints] for rationale.
func (*Checkpointer) LoadCheckpoint ¶
func (c *Checkpointer) LoadCheckpoint(checkpoint int) ([]*trie.MTrie, error)
LoadCheckpoint loads a full-mtrie (V6 and earlier) checkpoint by number. V7 (payloadless) checkpoints have a different in-memory type and are loaded via OpenAndReadCheckpointV7 instead. Deprecated: use LoadCheckpointV6 for explicit loading of V6 checkpoints. This function will be removed in the future when V6 checkpoints are no longer supported.
func (*Checkpointer) LoadCheckpointV6 ¶
func (c *Checkpointer) LoadCheckpointV6(checkpoint int) ([]*trie.MTrie, error)
LoadCheckpointV6 loads a V6 checkpoint by number. Returns an error if not found.
func (*Checkpointer) LoadLatestCheckpointV7 ¶
func (c *Checkpointer) LoadLatestCheckpointV7() (tries []*payloadless.MTrie, loadedCheckpoint int, err error)
LoadLatestCheckpointV7 loads the most recent usable V7 (payloadless) checkpoint from the WAL directory and returns its tries together with the number of the loaded checkpoint.
It tries the newest numbered V7 checkpoint first, falling back to older ones if a checkpoint file fails to load. This mirrors the V6 checkpoint selection in [DiskWAL.replay]. The returned `loadedCheckpoint` is the number of the numbered checkpoint that was loaded, used by callers to determine the first WAL segment to replay.
When no numbered V7 checkpoint is usable, it falls back to the V7 root checkpoint (converted from the V6 root.checkpoint during bootstrap), if present. In that case, and when no V7 checkpoint of either kind exists, `loadedCheckpoint` is -1, signalling that all segments must be replayed on top of the returned tries (which is the empty slice when no checkpoint exists at all).
No error returns are expected during normal operation.
func (*Checkpointer) LoadRootCheckpoint ¶
func (c *Checkpointer) LoadRootCheckpoint() ([]*trie.MTrie, error)
func (*Checkpointer) LoadRootCheckpointV7 ¶
func (c *Checkpointer) LoadRootCheckpointV7() ([]*payloadless.MTrie, error)
LoadRootCheckpointV7 loads the V7 (payloadless) root checkpoint as a set of payloadless tries. It is the payloadless analog of Checkpointer.LoadRootCheckpoint.
No error returns are expected during normal operation.
func (*Checkpointer) NotCheckpointedSegments ¶
func (c *Checkpointer) NotCheckpointedSegments() (from, to int, err error)
NotCheckpointedSegments - returns numbers of segments which are not checkpointed yet, or -1, -1 if there are no segments
func (*Checkpointer) RemoveCheckpoint
deprecated
added in
v0.14.0
func (c *Checkpointer) RemoveCheckpoint(checkpoint int) error
RemoveCheckpoint deletes both the V6 and the V7 part files for the given checkpoint number. Deleting a version that isn't present is not an error, so this reports a failure whenever either deletion fails.
Deprecated: both compactors own their retention independently and use Checkpointer.RemoveCheckpointV6 / Checkpointer.RemoveCheckpointV7, so that a writer never deletes files owned by the other version. Prefer those.
No error returns are expected during normal operation.
func (*Checkpointer) RemoveCheckpointV6 ¶
func (c *Checkpointer) RemoveCheckpointV6(checkpoint int) error
RemoveCheckpointV6 deletes only the V6 (full-mtrie) part files for the given checkpoint number, leaving any same-numbered V7 file in place. This is used by the V6 compactor's retention logic so V7 checkpoints owned by a separate writer aren't collaterally damaged.
func (*Checkpointer) RemoveCheckpointV7 ¶
func (c *Checkpointer) RemoveCheckpointV7(checkpoint int) error
RemoveCheckpointV7 deletes only the V7 (payloadless) part files for the given checkpoint number, leaving any same-numbered V6 file in place. This is used by the payloadless compactor's retention logic so V6 checkpoints owned by a separate writer aren't collaterally damaged.
type Crc32Reader ¶ added in v0.14.0
type Crc32Reader struct {
// contains filtered or unexported fields
}
func NewCRC32Reader ¶ added in v0.14.0
func NewCRC32Reader(reader io.Reader) *Crc32Reader
func (*Crc32Reader) Crc32 ¶ added in v0.14.0
func (c *Crc32Reader) Crc32() uint32
type Crc32Writer ¶ added in v0.14.0
func NewCRC32Writer ¶ added in v0.14.0
func NewCRC32Writer(writer io.Writer) *Crc32Writer
func (*Crc32Writer) Crc32 ¶ added in v0.14.0
func (c *Crc32Writer) Crc32() uint32
type DiskWAL ¶ added in v0.15.4
type DiskWAL struct {
// contains filtered or unexported fields
}
func NewDiskWAL ¶ added in v0.15.4
func NewDiskWAL(logger zerolog.Logger, reg prometheus.Registerer, metrics module.WALMetrics, dir string, forestCapacity int, pathByteSize int, segmentSize int) (*DiskWAL, error)
TODO use real logger and metrics, but that would require passing them to Trie storage
func (*DiskWAL) Done ¶ added in v0.15.4
func (w *DiskWAL) Done() <-chan struct{}
Done implements interface module.ReadyDoneAware it closes all the open write-ahead log files and releases the file lock.
func (*DiskWAL) NewCheckpointer ¶ added in v0.15.4
func (w *DiskWAL) NewCheckpointer() (*Checkpointer, error)
NewCheckpointer returns a Checkpointer for this WAL
func (*DiskWAL) PauseRecord ¶ added in v0.15.4
func (w *DiskWAL) PauseRecord()
func (*DiskWAL) RecordDelete ¶ added in v0.15.4
func (*DiskWAL) RecordUpdate ¶ added in v0.15.4
RecordUpdate writes the trie update to the write ahead log on disk. if write ahead logging is not paused, it returns the file num (write ahead log) that the trie update was written to. if write ahead logging is enabled, the second returned value is false, otherwise it's true, meaning WAL is disabled.
func (*DiskWAL) ReplayLogsOnly ¶ added in v0.15.4
func (*DiskWAL) ReplayOnForest ¶ added in v0.15.4
func (*DiskWAL) ReplayOnPayloadlessForest ¶
func (w *DiskWAL) ReplayOnPayloadlessForest(forest *payloadless.Forest) error
ReplayOnPayloadlessForest reconstructs in-memory payloadless state by loading the latest V7 (payloadless) checkpoint from the WAL directory onto `forest`, then replaying every WAL segment newer than that checkpoint.
This is the payloadless analog of DiskWAL.ReplayOnForest: it hides checkpoint selection, checkpoint loading, and segment replay behind a single call so the ledger constructor stays uniform across V6 and V7. Like the V6 path, it tries the newest V7 checkpoint first and falls back to older ones if a checkpoint file fails to load. When no V7 checkpoint exists, it replays all segments onto the (presumably empty) `forest`.
When no numbered V7 checkpoint is available it falls back to a V7 root checkpoint (converted from the V6 root.checkpoint during bootstrap), mirroring the V6 root-checkpoint fallback in [DiskWAL.replay].
A V7 checkpoint of one kind or the other is required: a payloadless forest retains only leaf-hash commitments, which cannot be reconstructed by WAL replay alone (the WAL records full payload updates, but replaying every update from genesis to rebuild the commitment is not feasible at runtime). When neither a numbered V7 checkpoint nor a V7 root checkpoint is present, this refuses to seed rather than silently booting an empty, uncommitted forest.
Expected error returns during normal operation:
- error containing "no V7 checkpoint found": when the WAL directory contains no V7 checkpoint of either kind, so the forest cannot be seeded.
func (*DiskWAL) ReplayOnPayloadlessForestUntil ¶
func (w *DiskWAL) ReplayOnPayloadlessForestUntil( forest *payloadless.Forest, targetRootHash ledger.RootHash, ) (found bool, sourceNumber int, err error)
ReplayOnPayloadlessForestUntil reconstructs payloadless state like DiskWAL.ReplayOnPayloadlessForest, but stops replaying WAL segments as soon as an update produces a trie whose root hash equals `targetRootHash` (or the target is already one of the loaded V7 checkpoint tries).
Stopping early bounds both time and memory to the segments up to the target. This also avoids a correctness pitfall of replaying to the end: the forest is LRU-bounded, so a target more than `capacity` tries before the WAL tip would be evicted before it could be read.
It returns true when the target trie is present after loading the V7 checkpoint or during segment replay, and false when all segments were replayed without producing it. The caller reads the trie back via payloadless.Forest.GetTrie.
When the target is found, `sourceNumber` identifies where it came from: the number of the loaded V7 checkpoint when the target was already one of the checkpoint tries, or the number of the WAL segment whose replay produced it. Segments are replayed one at a time precisely so this number is observable. `sourceNumber` is -1 when the target was found in the unnumbered V7 root checkpoint, and when the target was not found at all.
Expected error returns during normal operation:
- error containing "no V7 checkpoint found": when the WAL directory contains no V7 checkpoint of either kind, so the forest cannot be seeded.
func (*DiskWAL) UnpauseRecord ¶ added in v0.15.4
func (w *DiskWAL) UnpauseRecord()
type IterateNodeFunc ¶
type IterateNodeFunc func(*CheckpointNode) error
IterateNodeFunc processes a single node during a checkpoint iteration. Nodes are delivered in descendants-first (post-order DFS) order, so every child of a node is delivered before the node itself.
Returning an error aborts the iteration and the error is propagated out of IterateCheckpointNodes.
type LedgerWAL ¶
type LedgerWAL interface {
module.ReadyDoneAware
NewCheckpointer() (*Checkpointer, error)
PauseRecord()
UnpauseRecord()
RecordUpdate(update *ledger.TrieUpdate) (int, bool, error)
RecordDelete(rootHash ledger.RootHash) error
ReplayOnForest(forest *mtrie.Forest) error
ReplayOnPayloadlessForest(forest *payloadless.Forest) error
Segments() (first, last int, err error)
Replay(
checkpointFn func(tries []*trie.MTrie) error,
updateFn func(update *ledger.TrieUpdate) error,
deleteFn func(ledger.RootHash) error,
) error
ReplayLogsOnly(
checkpointFn func(tries []*trie.MTrie) error,
updateFn func(update *ledger.TrieUpdate) error,
deleteFn func(rootHash ledger.RootHash) error,
) error
}
type PayloadlessTrieQueue ¶
type PayloadlessTrieQueue struct {
// contains filtered or unexported fields
}
PayloadlessTrieQueue is a fix-sized FIFO queue of payloadless.MTrie.
It is the payloadless counterpart of TrieQueue and is intended for the same purpose: bookkeeping the rolling set of recent tries that a Compactor considers when emitting a checkpoint. Like TrieQueue, it is intentionally not goroutine-safe — its sole expected caller is the single Compactor goroutine.
func NewPayloadlessTrieQueue ¶
func NewPayloadlessTrieQueue(capacity uint) *PayloadlessTrieQueue
NewPayloadlessTrieQueue returns a new empty queue with the given capacity.
func NewPayloadlessTrieQueueWithValues ¶
func NewPayloadlessTrieQueueWithValues(capacity uint, tries []*payloadless.MTrie) *PayloadlessTrieQueue
NewPayloadlessTrieQueueWithValues returns a new queue pre-populated with the given tries. If more than `capacity` tries are provided, only the `capacity` most recent ones are retained.
func (*PayloadlessTrieQueue) Count ¶
func (q *PayloadlessTrieQueue) Count() int
Count returns the current element count.
func (*PayloadlessTrieQueue) Push ¶
func (q *PayloadlessTrieQueue) Push(t *payloadless.MTrie)
Push appends a trie to the queue. When the queue is full, the oldest entry is overwritten in FIFO order.
func (*PayloadlessTrieQueue) Tries ¶
func (q *PayloadlessTrieQueue) Tries() []*payloadless.MTrie
Tries returns the queued tries in FIFO order (oldest first). The returned slice is a fresh copy and is safe for the caller to retain.
type SyncOnCloseRenameFile ¶ added in v0.14.0
SyncOnCloseRenameFile is a composite of buffered writer over a given file which flushes/sync on closing and renames to `targetName` as a last step. Typical usecase is to write data to a temporary file and only rename it to target one as the last step. This help avoid situation when writing is interrupted and unusable file but with target name exists.
func (*SyncOnCloseRenameFile) Close ¶ added in v0.14.0
func (s *SyncOnCloseRenameFile) Close() error
func (*SyncOnCloseRenameFile) Sync ¶ added in v0.14.0
func (s *SyncOnCloseRenameFile) Sync() error
type TrieQueue ¶ added in v0.27.0
type TrieQueue struct {
// contains filtered or unexported fields
}
TrieQueue is a fix-sized FIFO queue of MTrie. It is only used by Compactor for checkpointing, and it is intentionally not threadsafe given its limited use case. It is not a general purpose queue to avoid incurring overhead for features not needed for its limited use case.
func NewTrieQueue ¶ added in v0.27.0
NewTrieQueue returns a new TrieQueue with given capacity.
func NewTrieQueueWithValues ¶ added in v0.27.0
NewTrieQueueWithValues returns a new TrieQueue with given capacity and initial values.
type WALOperation ¶
type WALOperation uint8
const WALDelete WALOperation = 2
const WALUpdate WALOperation = 1
func Decode ¶
func Decode(data []byte) (operation WALOperation, rootHash ledger.RootHash, update *ledger.TrieUpdate, err error)
Decode decodes the given data into a WAL operation, root hash and trie update. It returns (WALDelete, rootHash, nil, nil) if the operation is WALDelete. It returns (WALUpdate, hash.DummyHash, update, nil) if the operation is WALUpdate. To read the root hash of the trie update, use update.RootHash.
Source Files
¶
- checkpoint_node_iterator.go
- checkpoint_v6_convert.go
- checkpoint_v6_convert_stream.go
- checkpoint_v6_leaf_reader.go
- checkpoint_v6_reader.go
- checkpoint_v6_writer.go
- checkpoint_v7_convert.go
- checkpoint_v7_convert_stream.go
- checkpoint_v7_reader.go
- checkpoint_v7_writer.go
- checkpoint_verifier.go
- checkpointer.go
- checksum.go
- encoding.go
- fadvise_linux.go
- syncrename.go
- triequeue.go
- triequeue_payloadless.go
- wal.go