Documentation
¶
Index ¶
- Variables
- func ChunkName(num uint64) string
- func ChunkNameAbove(name, bound string) bool
- type Block
- type BlockIterator
- type ImmutableDb
- func (i *ImmutableDb) BlocksFromPoint(point ocommon.Point) (*BlockIterator, error)
- func (i *ImmutableDb) GetBlock(point ocommon.Point) (*Block, error)
- func (i *ImmutableDb) GetTip() (*ocommon.Point, error)
- func (i *ImmutableDb) LastSlotInChunk(num uint64) (uint64, bool, error)
- func (i *ImmutableDb) TruncateChunksFromPoint(point ocommon.Point) error
Constants ¶
This section is empty.
Variables ¶
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.
var ErrPointBeyondLastChunk = errors.New(
"immutable DB: point is beyond the last chunk",
)
Functions ¶
func ChunkName ¶ added in v0.70.0
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
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 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) 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