immutable

package
v0.70.12 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 15, 2026 License: Apache-2.0 Imports: 17 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var ErrDigestMismatch = errors.New("immutable DB: file digest mismatch")

ErrDigestMismatch reports a file whose contents are not the contents that were certified for it: either the digest of what was opened differs from the certified one, or nothing certified that name at all.

The second is not a lesser case. A file the digest map does not cover is one nobody vouched for, and reading it because the map is silent would leave the map's coverage up to whoever added the file.

View Source
var ErrInvalidChunkOffset = errors.New("invalid chunk offset")

ErrInvalidChunkOffset reports a secondary-index block offset that cannot be trusted to seek or slice the chunk file it names: it overflows int64, lands beyond the file's size, or does not strictly follow the offset before it. Callers can match it with errors.Is to distinguish a corrupt or tampered index from an ordinary I/O failure.

View Source
var ErrPointBeyondLastChunk = errors.New(
	"immutable DB: point is beyond the last chunk",
)

Functions

func ChunkName added in v0.70.0

func ChunkName(num uint64) string

ChunkName returns the name an immutable file number is stored under, without an extension: five digits, zero padded.

Exported because callers that know a chunk by its number have to ask for it by name — the position of a name in a sorted listing is not its number whenever the range on disk does not start at zero, which is what a catch-up produces.

func ChunkNameAbove added in v0.70.0

func ChunkNameAbove(name, bound string) bool

ChunkNameAbove reports whether chunk name sorts after bound numerically.

Not a plain string comparison. ChunkName pads to five digits, so names are a fixed width only below 100000 — past that they grow, and "99999" > "100000" as strings while 99999 < 100000 as numbers. A bound compared lexically would then hide the chunk just below it and admit the one just above, which is both of the things a bound exists to prevent. Longer means larger first, and only equal widths compare as text.

Types

type Block

type Block struct {
	Hash  []byte
	Cbor  []byte
	Type  uint
	Slot  uint64
	IsEbb bool
}

type BlockIterator

type BlockIterator struct {
	// contains filtered or unexported fields
}

func (*BlockIterator) Close

func (b *BlockIterator) Close() error

func (*BlockIterator) Next

func (b *BlockIterator) Next() (*Block, error)

type ImmutableDb

type ImmutableDb struct {
	// contains filtered or unexported fields
}

func New

func New(dataDir string) (*ImmutableDb, error)

New returns a new ImmutableDb using the specified data directory or an error

func NewFromRoot added in v0.70.0

func NewFromRoot(root *os.Root) (*ImmutableDb, error)

NewFromRoot returns a new ImmutableDb that reads every file through root rather than by resolving the data directory's pathname again.

Use this when the directory was vetted and the caller needs the reads to be about that directory rather than about whatever its name refers to later. The handle refers to the directory itself, so a tree substituted behind the name afterwards is not what gets read; New cannot offer that, because it only ever holds a name.

The caller keeps ownership of root and must hold it open for as long as the returned ImmutableDb is used. Closing it early makes subsequent reads fail rather than silently fall back to the pathname.

func NewFromRootVerified added in v0.70.0

func NewFromRootVerified(
	root *os.Root,
	digests map[string]string,
	maxChunk string,
) (*ImmutableDb, error)

NewFromRootVerified is NewFromRoot for a tree whose files are individually certified: every file is read once, checked against digests, and parsed from the bytes that were checked.

NewFromRoot binds the reads to a directory. This binds them to the bytes. The two are not the same guarantee, and the difference is the whole point here: a Mithril bootstrap hashes each downloaded file when it lands, and whatever consumes it opens it again later. Between those, a writer who shares the download directory can rename a file of their own over the verified one without ever leaving the directory the handle refers to, and the second open reads what they wrote.

Holding the descriptor open across both would answer the rename and nothing else. A descriptor names an inode, so writes made through the file it still refers to are visible to a reader that has merely rewound it — the check and the parse would be two readings of one mutable thing, and only the first would be the one that was compared against the digest. So there is only one reading: the entry is read into memory, the digest is computed over that buffer, and the parser walks the same buffer. Nothing that happens to the file afterwards is reachable from it.

This holds one entry in memory at a time, bounded by the certified size of the largest file, which is what the guarantee costs. The file is read twice — once streaming, to learn that size without trusting it, and once into the buffer — so it is the parser's read that is removed, not one of the two.

digests maps a name directly beneath the data directory ("00000.chunk") to its lowercase hex SHA-256. An empty or nil map is refused: it would verify nothing while looking as though it did.

maxChunk, when non-empty, hides every chunk named above it (use ChunkName). The pipelined bootstrap copy reads a tree its download pool is still filling, and chunks arrive out of order — so a chunk above the contiguous prefix may be present and half written. The bound keeps the reader inside the prefix whose archives have been verified rather than failing on one that is merely unfinished. A name rather than a count, because a count would mean the same thing as a position, and a position is not a chunk number.

The caller keeps ownership of root on the same terms as NewFromRoot.

func (*ImmutableDb) BlocksFromPoint

func (i *ImmutableDb) BlocksFromPoint(
	point ocommon.Point,
) (*BlockIterator, error)

func (*ImmutableDb) GetBlock

func (i *ImmutableDb) GetBlock(point ocommon.Point) (*Block, error)

func (*ImmutableDb) GetTip

func (i *ImmutableDb) GetTip() (*ocommon.Point, error)

func (*ImmutableDb) LastSlotInChunk added in v0.60.1

func (i *ImmutableDb) LastSlotInChunk(
	num uint64,
) (uint64, bool, error)

LastSlotInChunk returns the slot of the last block in the immutable file numbered num. The second return value is false when no chunk of that number is present, with no error. This bounds an incremental copy to a contiguous chunk prefix while later chunks may still be downloading out of order.

By number, not by position in the sorted listing. The two coincide only when the range on disk starts at chunk 0, and a catch-up downloads only the archives above the import marker — so a position lookup would answer about a different chunk than the caller named, and bound the copy by the wrong slot.

func (*ImmutableDb) TruncateChunksFromPoint

func (i *ImmutableDb) TruncateChunksFromPoint(point ocommon.Point) error

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL