Documentation
¶
Index ¶
- Constants
- Variables
- type ExportNode
- type Exporter
- type Hash
- type ImmutableTree
- func (t *ImmutableTree) Close() error
- func (t *ImmutableTree) Export(ndb *nodeDB) (*Exporter, error)
- func (t *ImmutableTree) Get(key []byte) ([]byte, error)
- func (t *ImmutableTree) GetByIndex(index int64) ([]byte, []byte, error)
- func (t *ImmutableTree) GetMembershipProof(key []byte) (*ics23.CommitmentProof, error)
- func (t *ImmutableTree) GetNonMembershipProof(key []byte) (*ics23.CommitmentProof, error)
- func (t *ImmutableTree) GetWithIndex(key []byte) (int64, []byte, error)
- func (t *ImmutableTree) Has(key []byte) (bool, error)
- func (t *ImmutableTree) Hash() []byte
- func (t *ImmutableTree) Height() int8
- func (t *ImmutableTree) IsEmpty() bool
- func (t *ImmutableTree) Iterate(fn func(key []byte, value []byte) bool) (bool, error)
- func (t *ImmutableTree) IterateRange(start, end []byte, ascending bool, fn func(key, value []byte) bool) (stopped bool, err error)
- func (t *ImmutableTree) Iterator(start, end []byte, ascending bool) (*Iterator, error)
- func (t *ImmutableTree) SetValueResolver(resolver ValueResolver)
- func (t *ImmutableTree) Size() int64
- func (t *ImmutableTree) VerifyMembership(proof *ics23.CommitmentProof, key []byte) (bool, error)
- func (t *ImmutableTree) VerifyNonMembership(proof *ics23.CommitmentProof, key []byte) (bool, error)
- func (t *ImmutableTree) Version() int64
- type Importer
- type InnerNode
- type Iterator
- type LeafNode
- type Logger
- type MiniMerkle
- type MutableTree
- func (t *MutableTree) AvailableVersions() []int
- func (t *MutableTree) Close() error
- func (t *MutableTree) DeleteVersionsFrom(_ int64) error
- func (t *MutableTree) DeleteVersionsTo(toVersion int64) error
- func (t *MutableTree) Get(key []byte) ([]byte, error)
- func (t *MutableTree) GetByIndex(index int64) ([]byte, []byte, error)
- func (t *MutableTree) GetCommittedValueByKey(vk []byte) ([]byte, error)
- func (t *MutableTree) GetImmutable(version int64) (*ImmutableTree, error)
- func (t *MutableTree) GetImmutableUnregistered(version int64) (*ImmutableTree, error)
- func (t *MutableTree) GetMembershipProof(key []byte) (*ics23.CommitmentProof, error)
- func (t *MutableTree) GetNonMembershipProof(key []byte) (*ics23.CommitmentProof, error)
- func (t *MutableTree) GetValueByKey(vk []byte) ([]byte, error)
- func (t *MutableTree) GetVersioned(key []byte, version int64) ([]byte, error)
- func (t *MutableTree) GetWithIndex(key []byte) (int64, []byte, error)
- func (t *MutableTree) Has(key []byte) (bool, error)
- func (t *MutableTree) Hash() []byte
- func (t *MutableTree) Height() int8
- func (t *MutableTree) Import(version int64) (*Importer, error)
- func (t *MutableTree) IsEmpty() bool
- func (t *MutableTree) Iterate(fn func(key []byte, value []byte) bool) (bool, error)
- func (t *MutableTree) IterateRange(start, end []byte, ascending bool, fn func(key, value []byte) bool) (stopped bool, err error)
- func (t *MutableTree) Iterator(start, end []byte, ascending bool) (*Iterator, error)
- func (t *MutableTree) Load() (int64, error)
- func (t *MutableTree) LoadVersion(version int64) (int64, error)
- func (t *MutableTree) LoadVersionForOverwriting(_ int64) error
- func (t *MutableTree) PruneVersionsTo(toVersion int64) error
- func (t *MutableTree) Remove(key []byte) ([]byte, bool, error)
- func (t *MutableTree) Rollback()
- func (t *MutableTree) SaveVersion() (rootHash []byte, savedVersion int64, err error)
- func (t *MutableTree) Set(key, value []byte) (updated bool, err error)
- func (t *MutableTree) SetInitialVersion(version uint64)
- func (t *MutableTree) Size() int64
- func (t *MutableTree) Snapshot(version int64) *ImmutableTree
- func (t *MutableTree) Version() int64
- func (t *MutableTree) VersionExists(version int64) bool
- func (t *MutableTree) WorkingHash() []byte
- func (t *MutableTree) WorkingVersion() int64
- type Node
- type NodeKey
- type Option
- type Options
- type ValueResolver
Constants ¶
const ( // B is the branching factor. Inner nodes have up to B children // and B-1 separator keys. Leaf nodes have up to B key-value pairs. B = 32 // MinKeys is the minimum occupancy for non-root nodes (B/2). MinKeys = B / 2 // HashSize is the size of a SHA256 hash in bytes. HashSize = sha256.Size // 32 // NodeKeySize is the size of a serialized NodeKey (version:8 + nonce:4). NodeKeySize = 12 // Domain separator prefix bytes (RFC 6962). DomainLeaf byte = 0x00 DomainInner byte = 0x01 DomainEmpty byte = 0x02 // DB key prefixes. PrefixNode byte = 'B' PrefixVal byte = 'V' PrefixRoot byte = 'R' PrefixMeta byte = 'M' PrefixOrphan byte = 'O' // PrefixFast keys the optional latest-version fast index (user-key → // version‖value). It is an unauthenticated read accelerator outside the // Merkle commitment; see fast_index.go. PrefixMeta‖"fastidx" stamps the // version it is complete for. PrefixFast byte = 'F' // Node type bytes for serialization. TypeInner byte = 0x01 TypeLeaf byte = 0x02 )
const MaxKeyLen = 1 << 20 // 1 MiB
MaxKeyLen caps how long a single key can be. Must stay at or below maxReadBytesLen in node.go — if we ever accepted a key larger than the read cap, the node would serialize successfully but fail to deserialize, permanently wedging that version of the tree.
Variables ¶
var ( ErrVersionDoesNotExist = errors.New("version does not exist") ErrKeyDoesNotExist = errors.New("key does not exist") ErrExportDone = errors.New("export done") ErrNotInitializedTree = errors.New("tree not initialized") ErrNoImport = errors.New("no import in progress") ErrNodeMissingNodeKey = errors.New("node missing node key") ErrEmptyTree = errors.New("tree is empty") ErrActiveReaders = errors.New("version has active readers") ErrEmptyKey = errors.New("key must not be empty") ErrNoCommittedState = errors.New("no committed state: call SaveVersion before generating proofs") ErrKeyTooLong = errors.New("key exceeds maximum size") ErrUnsupported = errors.New("operation not supported") ErrUncommittedChanges = errors.New("uncommitted working-session changes") ErrChecksumMismatch = errors.New("record checksum mismatch") // ErrSessionPoisoned wraps (via %w on the sentinel, with the original // failure flattened into the message) the first error that left the // working session inconsistent. Set/Remove/SaveVersion refuse while it is // set; Rollback or a successful LoadVersion clears it. ErrSessionPoisoned = errors.New("session poisoned by an earlier failure: Rollback before continuing") )
var BptreeSpec = &ics23.ProofSpec{ LeafSpec: &ics23.LeafOp{ Prefix: []byte{DomainLeaf}, PrehashKey: ics23.HashOp_NO_HASH, PrehashValue: ics23.HashOp_SHA256, Hash: ics23.HashOp_SHA256, Length: ics23.LengthOp_VAR_PROTO, }, InnerSpec: &ics23.InnerSpec{ ChildOrder: []int32{0, 1}, MinPrefixLength: 1, MaxPrefixLength: 1, ChildSize: int32(HashSize), EmptyChild: sentinelHash[:], Hash: ics23.HashOp_SHA256, }, MinDepth: 5, MaxDepth: 60, }
BptreeSpec is the ICS23 ProofSpec for the B+ tree. The mini merkle collapses into a uniform chain of binary InnerOps.
Functions ¶
This section is empty.
Types ¶
type ExportNode ¶
type ExportNode struct {
Key []byte
Value []byte // actual value (inlined, not hash)
Height int8 // 0=leaf entry, -1=leaf boundary marker, >0=inner marker
NumKeys int16 // leaf boundary: keys in this leaf; inner: separator key count
SeparatorKeys [][]byte // inner marker only: all separator keys
}
ExportNode is the format for export/import streaming.
type Exporter ¶
type Exporter struct {
// contains filtered or unexported fields
}
Exporter streams tree nodes in depth-first post-order (children before parent).
Lifecycle: the caller MUST Close the Exporter when done — including on error or early return (use defer). Close stops the streaming goroutine and releases the version-reader reservation taken by Export. Abandoning an Exporter without Close leaks that goroutine (it blocks once the 32-entry channel buffer fills, i.e. for any tree with >32 nodes) AND permanently pins its version against pruning: PruneVersionsTo of that version returns ErrActiveReaders, and the store's auto-prune at Commit panics on it. Fully consuming the stream (Next until ErrExportDone) lets the goroutine exit but does NOT release the reservation — Close is still required. Close is idempotent.
func (*Exporter) Close ¶
func (e *Exporter) Close()
Close releases the exporter and decrements version readers. Safe to call multiple times. The goroutine exits promptly without needing to drain the channel.
func (*Exporter) Next ¶
func (e *Exporter) Next() (*ExportNode, error)
Next returns the next ExportNode, or ErrExportDone when finished.
type Hash ¶
Hash is a fixed-size SHA256 hash.
func HashInner ¶
HashInner computes an inner mini-merkle node hash:
SHA256(0x01 || left || right)
If both left and right are the sentinel, returns the sentinel (short-circuit rule for ICS23 EmptyChild compatibility).
func HashLeafSlot ¶
HashLeafSlot computes the hash for an occupied leaf slot:
SHA256(0x00 || varint(len(key)) || key || varint(32) || SHA256(value))
This matches ICS23 LeafOp with Prefix=0x00, PrehashValue=SHA256, Length=VAR_PROTO.
func HashLeafSlotFromValueHash ¶
HashLeafSlotFromValueHash computes the leaf slot hash from a pre-computed value hash.
SHA256(0x00 || varint(len(key)) || key || 0x20 || valueHash)
type ImmutableTree ¶
type ImmutableTree struct {
// contains filtered or unexported fields
}
ImmutableTree is a read-only snapshot of the tree at a specific version. It is safe for concurrent reads. Created by MutableTree.GetImmutable() or by snapshotting the root after SaveVersion.
When the snapshot is backed by a DB, ndb is non-nil. Iterators and exporters created from it register as version readers (via ndb.incrVersionReaders) so that PruneVersionsTo cannot delete nodes they still depend on.
func NewImmutableTree ¶
func NewImmutableTree(root Node, version int64) *ImmutableTree
NewImmutableTree creates an ImmutableTree from a root node and version.
func (*ImmutableTree) Close ¶
func (t *ImmutableTree) Close() error
Close releases this snapshot's version-reader reservation, if it holds one, allowing a prune of its version to proceed. It is idempotent (sync.Once) so double or concurrent Close cannot over-decrement. A snapshot from GetImmutable or proof generation is registered and MUST be Closed; unregistered snapshots (Snapshot, GetImmutableUnregistered) make Close a no-op.
func (*ImmutableTree) Export ¶
func (t *ImmutableTree) Export(ndb *nodeDB) (*Exporter, error)
Export creates an Exporter for the tree. The tree's version is protected from pruning via a version reader held for the Exporter's lifetime; the caller MUST Close the returned Exporter (use defer) to release it — see the Exporter docs.
func (*ImmutableTree) Get ¶
func (t *ImmutableTree) Get(key []byte) ([]byte, error)
Get returns the value for a key, or nil if not found.
func (*ImmutableTree) GetByIndex ¶
func (t *ImmutableTree) GetByIndex(index int64) ([]byte, []byte, error)
GetByIndex returns the key and value at the given index.
func (*ImmutableTree) GetMembershipProof ¶
func (t *ImmutableTree) GetMembershipProof(key []byte) (*ics23.CommitmentProof, error)
GetMembershipProof generates an ICS23 existence proof for a key. Proofs over empty-valued keys generate but can never verify: ics23's LeafOp rejects empty values (the value-side twin of the empty-key constraint; IAVL behaves identically). See TestProof_EmptyValueUnprovable.
func (*ImmutableTree) GetNonMembershipProof ¶
func (t *ImmutableTree) GetNonMembershipProof(key []byte) (*ics23.CommitmentProof, error)
GetNonMembershipProof generates an ICS23 non-existence proof for a key. The proof embeds the gap's neighbor existence proofs, so it cannot verify when an adjacent key holds an empty value (see GetMembershipProof).
func (*ImmutableTree) GetWithIndex ¶
func (t *ImmutableTree) GetWithIndex(key []byte) (int64, []byte, error)
GetWithIndex returns the index, value, and whether the key was found.
func (*ImmutableTree) Has ¶
func (t *ImmutableTree) Has(key []byte) (bool, error)
Has returns true if the key exists.
func (*ImmutableTree) Hash ¶
func (t *ImmutableTree) Hash() []byte
Hash returns the root hash. Returns SHA256("") for empty trees, matching IAVL.
func (*ImmutableTree) Height ¶
func (t *ImmutableTree) Height() int8
Height returns the tree height.
func (*ImmutableTree) IsEmpty ¶
func (t *ImmutableTree) IsEmpty() bool
IsEmpty returns true if the tree has no keys.
func (*ImmutableTree) Iterate ¶
Iterate calls fn for each key-value pair in sorted order. If a value resolver is set, values are resolved to actual bytes.
func (*ImmutableTree) IterateRange ¶
func (t *ImmutableTree) IterateRange(start, end []byte, ascending bool, fn func(key, value []byte) bool) (stopped bool, err error)
IterateRange iterates over [start, end) calling fn. Stops early if fn returns true. A value-resolution or node-load failure is returned as err — fn is never called with the failing row, and stopped is meaningless when err != nil.
func (*ImmutableTree) Iterator ¶
func (t *ImmutableTree) Iterator(start, end []byte, ascending bool) (*Iterator, error)
ImmutableTree.Iterator returns an iterator over [start, end).
When the immutable tree is DB-backed (t.ndb != nil), the iterator registers as a version reader so concurrent pruning cannot delete the nodes it walks. The reader is released on Close. For snapshot-only trees without an ndb, values are resolved via t.valueResolver (no version tracking needed).
func (*ImmutableTree) SetValueResolver ¶
func (t *ImmutableTree) SetValueResolver(resolver ValueResolver)
SetValueResolver sets the function used to resolve valueKeys to raw values.
func (*ImmutableTree) Size ¶
func (t *ImmutableTree) Size() int64
Size returns the total number of key-value pairs.
func (*ImmutableTree) VerifyMembership ¶
func (t *ImmutableTree) VerifyMembership(proof *ics23.CommitmentProof, key []byte) (bool, error)
VerifyMembership verifies an ICS23 existence proof against the tree's root hash. The value is taken from the proof itself (no tree lookup needed).
func (*ImmutableTree) VerifyNonMembership ¶
func (t *ImmutableTree) VerifyNonMembership(proof *ics23.CommitmentProof, key []byte) (bool, error)
VerifyNonMembership verifies an ICS23 non-existence proof.
func (*ImmutableTree) Version ¶
func (t *ImmutableTree) Version() int64
Version returns the version of this snapshot.
type Importer ¶
type Importer struct {
// contains filtered or unexported fields
}
Importer reconstructs a tree from a stream of ExportNodes, preserving the exact tree structure (and thus the root hash).
The stream is structurally validated as it arrives: leaf keys must be strictly ascending across the whole stream, every leaf marker must drain the entry buffer exactly, separators must sit in the window (max(left child) < sep <= min(right child)), and inner heights must equal derived child height + 1. Combined with the caller's final root-hash check against a trusted app hash (which covers keys, value hashes, and shape), a malicious stream cannot produce a tree that mis-routes reads. The one residual freedom — a separator moved WITHIN its window under an unchanged root hash — does not affect reads, iteration, or pruning; its first consequence is an app-hash mismatch at the first write that routes differently, which halts the node loudly.
func (*Importer) Add ¶
func (imp *Importer) Add(node *ExportNode) error
Add adds an ExportNode to the tree being imported. Nodes must arrive in depth-first post-order as produced by the Exporter. A validation failure leaves the importer's stack and buffer untouched, but values staged by earlier Adds remain staged until Close (which rolls the session back) — a rejected stream must be Closed, not Committed.
func (*Importer) Close ¶
Close releases the importer. If the import was not committed (abandoned, rejected stream, or failed Commit), the staged session state — value records Add wrote into the shared batch, and any root/version mutation a failed Commit left behind — is rolled back; otherwise those value records would ride into the NEXT commit as unreferenced, unreclaimable records in a future version's namespace. Idempotent; safe after Commit.
func (*Importer) Commit ¶
Commit finalizes the import by saving the version.
The caller wiring state-sync MUST compare the committed version's hash against the consensus-trusted app hash: the structural checks in Add cover what the hash cannot (separator windows, heights), and the hash covers what the checks cannot (keys, value hashes, shape). An empty stream commits an empty tree — accepted for tests, though no honest Exporter can produce it (Export fails on an empty tree), so a state-sync caller should treat it like any other hash mismatch.
type InnerNode ¶
type InnerNode struct {
// contains filtered or unexported fields
}
InnerNode stores separator keys and child references. It has numKeys separator keys and numKeys+1 children.
func (*InnerNode) Clone ¶
Clone creates a shallow copy of the node with nodeKey set to nil (marking it as unsaved/new for COW). Keys and childNodes are shared slice/pointer references (COW-safe: keys are never mutated in-place, only replaced by shifting). The ndb reference is preserved for lazy loading.
func (*InnerNode) GetNodeKey ¶
func (*InnerNode) NumChildren ¶
NumChildren returns the number of children (numKeys + 1).
func (*InnerNode) RebuildMiniMerkle ¶
func (n *InnerNode) RebuildMiniMerkle()
RebuildMiniMerkle recomputes the full mini merkle tree from the slot-level hashes. For InnerNode, slots are childHashes. For LeafNode, slots are HashLeafSlotFromValueHash(key, valueHash). Cost: B-1 = 31 SHA256 calls (sets leaf slots directly, then Build).
func (*InnerNode) SetNodeKey ¶
type Iterator ¶
type Iterator struct {
// contains filtered or unexported fields
}
Iterator traverses key-value pairs in a B+ tree within a [start, end) range. Implements the same contract as tm2/pkg/db.Iterator. Uses a stack of (innerNode, childIndex) pairs for traversal — no leaf sibling pointers needed.
func NewIteratorWithNDB ¶
func NewIteratorWithNDB(imm *ImmutableTree, start, end []byte, ascending bool, mtree *MutableTree) *Iterator
NewIteratorWithNDB creates an iterator over an immutable tree with value resolution via the mutable tree's nodeDB. Used by the store wrapper.
When the immutable tree carries a DB-backed ndb, the iterator registers as a version reader on imm.version so that concurrent PruneVersionsTo cannot delete nodes this iterator still walks. The reader is released on Close.
type LeafNode ¶
type LeafNode struct {
// contains filtered or unexported fields
}
LeafNode stores sorted key-value hash pairs.
func (*LeafNode) GetNodeKey ¶
func (*LeafNode) RebuildMiniMerkle ¶
func (n *LeafNode) RebuildMiniMerkle()
func (*LeafNode) SetNodeKey ¶
type Logger ¶
type Logger interface {
Info(msg string, keyVals ...any)
Warn(msg string, keyVals ...any)
Error(msg string, keyVals ...any)
Debug(msg string, keyVals ...any)
}
Logger is the interface for tree logging.
func NewNopLogger ¶
func NewNopLogger() Logger
NewNopLogger returns a Logger that discards all output.
type MiniMerkle ¶
type MiniMerkle struct {
// contains filtered or unexported fields
}
MiniMerkle is a binary merkle tree over B slots, stored as a heap-style array of size 2*B. Index 1 is the root. Indices B..2B-1 are the leaf-level slots. Index 0 is unused.
The tree uses the sentinel short-circuit rule: if both children are the sentinel, the parent is the sentinel (not SHA256(0x01 || sentinel || sentinel)). This ensures ICS23 EmptyChild compatibility at all depths.
func NewMiniMerkle ¶
func NewMiniMerkle() MiniMerkle
NewMiniMerkle creates a MiniMerkle with all slots set to the sentinel.
func (*MiniMerkle) Build ¶
func (m *MiniMerkle) Build()
Build recomputes the entire mini merkle tree from the leaf-level slots. Cost: B-1 = 31 SHA256 calls for B=32.
func (*MiniMerkle) GetSlot ¶
func (m *MiniMerkle) GetSlot(index int) Hash
GetSlot returns the hash at leaf-level slot index (0..B-1).
func (*MiniMerkle) Root ¶
func (m *MiniMerkle) Root() Hash
Root returns the mini merkle root hash (index 1).
func (*MiniMerkle) SetSlot ¶
func (m *MiniMerkle) SetSlot(index int, h Hash)
SetSlot sets the hash at leaf-level slot index (0..B-1) and recomputes the path from that slot to the root. Cost: log₂(B) = 5 SHA256 calls.
func (*MiniMerkle) SiblingPath ¶
func (m *MiniMerkle) SiblingPath(index int) (siblings []Hash, positions []int)
SiblingPath returns the log₂(B) sibling hashes needed to prove that slot[index] is part of the mini merkle root. The path goes from the leaf level toward the root. Each entry is the sibling's hash at that level. Also returns the position indices (0=left child, 1=right child) indicating which side the proven slot is on at each level.
type MutableTree ¶
type MutableTree struct {
// contains filtered or unexported fields
}
MutableTree is the working (writable) B+ tree: Set, Get, Has, Remove, SaveVersion, LoadVersion, Rollback, pruning, proofs, and iteration.
Concurrency ¶
A MutableTree is SINGLE-GOROUTINE. Its mutators (Set, Remove, SaveVersion, LoadVersion, Load, Rollback, DeleteVersionsTo, PruneVersionsTo, Import, SetInitialVersion) and its working-tree reads (Get, Has, Hash, WorkingHash, Version, WorkingVersion, Size, IsEmpty, Height, Iterate, Iterator, GetByIndex, GetWithIndex, GetValueByKey, GetMembershipProof, GetNonMembershipProof, Snapshot) read and write the working-tree fields (root, lastSaved, version, size, nextValueNonce, versionOrphans) WITHOUT locking, so none of them may be called concurrently with each other or with a mutator.
For concurrent reads at a COMMITTED version, call GetImmutable(version) — it is safe to call concurrently with the writer (it reads only the internally-synchronized nodeDB, never the working-tree fields) — and read the returned ImmutableTree, which is safe for concurrent reads against an active writer; Close it when done (it holds a version-reader reservation that blocks pruning of that version until released). GetVersioned, GetCommittedValueByKey, VersionExists, and AvailableVersions are likewise safe to call concurrently with the writer.
The gno ABCI path satisfies this contract by serializing all store access through the connection mutex.
func NewMutableTreeWithDB ¶
NewMutableTreeWithDB creates a DB-backed MutableTree.
func (*MutableTree) AvailableVersions ¶
func (t *MutableTree) AvailableVersions() []int
AvailableVersions returns all available version numbers.
func (*MutableTree) Close ¶
func (t *MutableTree) Close() error
Close closes the tree and its underlying DB resources.
func (*MutableTree) DeleteVersionsFrom ¶
func (t *MutableTree) DeleteVersionsFrom(_ int64) error
DeleteVersionsFrom is not supported — it would leak values and nodes. Not called by gno.land, the SDK, or the store layer.
func (*MutableTree) DeleteVersionsTo ¶
func (t *MutableTree) DeleteVersionsTo(toVersion int64) error
DeleteVersionsTo deletes versions from first to toVersion (inclusive), including orphaned nodes via dual-tree-walk pruning.
func (*MutableTree) Get ¶
func (t *MutableTree) Get(key []byte) ([]byte, error)
Get retrieves the value for a key.
func (*MutableTree) GetByIndex ¶
func (t *MutableTree) GetByIndex(index int64) ([]byte, []byte, error)
GetByIndex returns the key and value at the given zero-based index.
func (*MutableTree) GetCommittedValueByKey ¶
func (t *MutableTree) GetCommittedValueByKey(vk []byte) ([]byte, error)
GetCommittedValueByKey resolves a valueKey to the raw value bytes from the DB ONLY (never the uncommitted working-session buffer). It is the race-free read for cross-package committed-snapshot consumers (the store's GetImmutable / proof resolvers), which run concurrently with the writer.
func (*MutableTree) GetImmutable ¶
func (t *MutableTree) GetImmutable(version int64) (*ImmutableTree, error)
GetImmutable returns a committed read-only snapshot at version, REGISTERED as a version reader: a concurrent PruneVersionsTo(version) is blocked until the snapshot is Closed. Callers MUST Close it (else that version can never prune).
func (*MutableTree) GetImmutableUnregistered ¶
func (t *MutableTree) GetImmutableUnregistered(version int64) (*ImmutableTree, error)
GetImmutableUnregistered returns a committed read-only snapshot WITHOUT registering as a version reader. For long-lived snapshots that have no Close hook (e.g. the store's immutable LoadVersion view) — registering them would pin the version against pruning forever. Such a snapshot is not protected against a concurrent prune of its version (acceptable: prune and queries are serialized by the ABCI mutex today).
func (*MutableTree) GetMembershipProof ¶
func (t *MutableTree) GetMembershipProof(key []byte) (*ics23.CommitmentProof, error)
GetMembershipProof returns an ICS23 existence proof for key against the last committed version (verifiable against MutableTree.Hash()), not the working tree. Returns ErrNoCommittedState if no version has been committed yet, or ErrEmptyTree if the committed tree is empty.
Single-goroutine: it reads the working tree's lastSaved/version (see the MutableTree concurrency contract). For concurrent or historical proofs, use GetImmutable(version).GetMembershipProof instead.
func (*MutableTree) GetNonMembershipProof ¶
func (t *MutableTree) GetNonMembershipProof(key []byte) (*ics23.CommitmentProof, error)
GetNonMembershipProof returns an ICS23 non-existence proof for key against the last committed version (verifiable against MutableTree.Hash()), not the working tree. Returns ErrNoCommittedState if no version has been committed yet, or ErrEmptyTree if the committed tree is empty.
Single-goroutine: it reads the working tree's lastSaved/version (see the MutableTree concurrency contract). For concurrent or historical proofs, use GetImmutable(version).GetNonMembershipProof instead.
func (*MutableTree) GetValueByKey ¶
func (t *MutableTree) GetValueByKey(vk []byte) ([]byte, error)
GetValueByKey resolves a valueKey to the raw value bytes, consulting the uncommitted working-session buffer first (read-your-writes). Safe only on the single writer goroutine.
func (*MutableTree) GetVersioned ¶
func (t *MutableTree) GetVersioned(key []byte, version int64) ([]byte, error)
GetVersioned returns the value for a key at a specific version.
func (*MutableTree) GetWithIndex ¶
func (t *MutableTree) GetWithIndex(key []byte) (int64, []byte, error)
GetWithIndex returns the index, value, and whether the key was found.
func (*MutableTree) Has ¶
func (t *MutableTree) Has(key []byte) (bool, error)
Has returns true if the key exists in the tree.
func (*MutableTree) Hash ¶
func (t *MutableTree) Hash() []byte
Hash returns the root hash of the last saved version. Returns SHA256("") for empty trees, matching IAVL behavior.
func (*MutableTree) Import ¶
func (t *MutableTree) Import(version int64) (*Importer, error)
Import creates an Importer that will reconstruct a tree at the given version.
The target version must be beyond the latest committed version: importing into the live key namespace would overwrite node/value records shared with retained versions (silent corruption). Import then rolls back any uncommitted working-session state (pending batch, orphan list, value-nonce counter) so stale state from a prior un-committed session cannot leak into the import's SaveVersion. Import rebuilds the root from scratch, so reverting t.root to lastSaved here is harmless.
func (*MutableTree) IsEmpty ¶
func (t *MutableTree) IsEmpty() bool
IsEmpty returns true if the tree has no keys.
func (*MutableTree) Iterate ¶
Iterate calls fn for each key-value pair in sorted order. Values are resolved from the value store.
func (*MutableTree) IterateRange ¶
func (t *MutableTree) IterateRange(start, end []byte, ascending bool, fn func(key, value []byte) bool) (stopped bool, err error)
IterateRange on MutableTree. Same contract as ImmutableTree.IterateRange.
func (*MutableTree) Iterator ¶
func (t *MutableTree) Iterator(start, end []byte, ascending bool) (*Iterator, error)
Iterator returns an iterator over [start, end) in the given direction. MutableTree iterators walk the in-memory working tree and do not take a version reader: pruning rejects toVersion >= latest, and a working tree loaded at an older version is protected by the working-tree-reader guard (PruneVersionsTo rejects t.version <= toVersion with ErrActiveReaders).
func (*MutableTree) Load ¶
func (t *MutableTree) Load() (int64, error)
Load loads the latest version from the DB.
func (*MutableTree) LoadVersion ¶
func (t *MutableTree) LoadVersion(version int64) (int64, error)
LoadVersion loads a specific version from the DB.
All fallible reads happen BEFORE the working session is discarded: on any error the previous session survives fully intact (a failed load must not wipe staged values the working tree still references — committing that would persist dangling valueKeys).
func (*MutableTree) LoadVersionForOverwriting ¶
func (t *MutableTree) LoadVersionForOverwriting(_ int64) error
LoadVersionForOverwriting is not supported — it would leak values and nodes. Not called by gno.land, the SDK, or the store layer.
func (*MutableTree) PruneVersionsTo ¶
func (t *MutableTree) PruneVersionsTo(toVersion int64) error
PruneVersionsTo deletes all versions from firstVersion through toVersion (inclusive), removing orphaned nodes via the dual-tree-walk algorithm. Sharing with the successor is decided by NodeKey record identity (COW shares records by reference; content hashes can collide across distinct records).
func (*MutableTree) Remove ¶
func (t *MutableTree) Remove(key []byte) ([]byte, bool, error)
Remove removes a key from the tree. Returns the old value and whether the key was found.
func (*MutableTree) Rollback ¶
func (t *MutableTree) Rollback()
Rollback discards all mutations since the last save. Values staged this session live only in the uncommitted batch, so discarding it drops them — nothing was written to the DB to clean up.
func (*MutableTree) SaveVersion ¶
func (t *MutableTree) SaveVersion() (rootHash []byte, savedVersion int64, err error)
SaveVersion persists the current tree state as a new version. Returns (rootHash, version, error).
func (*MutableTree) Set ¶
func (t *MutableTree) Set(key, value []byte) (updated bool, err error)
Set inserts or updates a key-value pair. Returns true if the key already existed (update), false if it was a new insert.
func (*MutableTree) SetInitialVersion ¶
func (t *MutableTree) SetInitialVersion(version uint64)
SetInitialVersion sets the version number for the first SaveVersion.
func (*MutableTree) Size ¶
func (t *MutableTree) Size() int64
Size returns the total number of key-value pairs.
func (*MutableTree) Snapshot ¶
func (t *MutableTree) Snapshot(version int64) *ImmutableTree
Snapshot creates an ImmutableTree snapshot of the current working tree with a properly wired value resolver. For tests and lightweight snapshots.
The snapshot wraps the LIVE working tree, whose most recent Sets may live only in pendingVals (uncommitted), so it resolves with read-your-writes (committed=false). It is a single-writer-only convenience: unlike GetImmutable, it is NOT safe to read concurrently with the writer.
func (*MutableTree) Version ¶
func (t *MutableTree) Version() int64
Version returns the last saved version.
func (*MutableTree) VersionExists ¶
func (t *MutableTree) VersionExists(version int64) bool
VersionExists returns true if the given version exists.
func (*MutableTree) WorkingHash ¶
func (t *MutableTree) WorkingHash() []byte
WorkingHash computes the hash of the current unsaved working tree. Returns SHA256("") for empty trees, matching IAVL behavior.
func (*MutableTree) WorkingVersion ¶
func (t *MutableTree) WorkingVersion() int64
WorkingVersion returns the version that will be used by the next SaveVersion.
type Node ¶
type Node interface {
GetNodeKey() *NodeKey
SetNodeKey(nk *NodeKey)
Hash() Hash
// contains filtered or unexported methods
}
Node is the interface implemented by both InnerNode and LeafNode.
type NodeKey ¶
NodeKey identifies a node in the database: (version, nonce). Version is the tree version when the node was created. Nonce is a per-version counter distinguishing nodes within a version.
func GetNodeKey ¶
GetNodeKey deserializes a NodeKey from a 12-byte slice.
type Option ¶
type Option func(*Options)
Option is a functional option for tree construction.
func FastIndexOption ¶
FastIndexOption enables the optional latest-version fast index: a flat user-key → version‖value map that accelerates committed point Gets of present keys (1 read instead of a full tree descent + value read). It is an unauthenticated read accelerator — not part of the Merkle root — so it can be toggled per-node without affecting the app hash. Default off.
func FlushThresholdOption ¶
func InitialVersionOption ¶
func SyncOption ¶
type Options ¶
type Options struct {
Sync bool // fsync writes
InitialVersion uint64 // first version number
FlushThreshold int // batch flush size in bytes
FastIndex bool // maintain the latest-version fast index (read accelerator)
}
Options configures tree behavior.
func DefaultOptions ¶
func DefaultOptions() Options
type ValueResolver ¶
ValueResolver resolves a valueKey to the raw value bytes.