state

package
v1.4.2 Latest Latest
Warning

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

Go to latest
Published: Jun 25, 2026 License: BSD-3-Clause Imports: 8 Imported by: 0

Documentation

Overview

Package state manages persistent state for the S-Chain — the Lux storage VM.

M0 persists exactly two things over the chain's database namespace:

  1. MANIFESTS — the (bucket, object) -> {fileIds, size, etag} mapping that records which content blobs make up an object.
  2. LAST-BLOCK pointer — the last-accepted block id + height, the recovery anchor.

Every accessor reads/writes through the supplied database.Database, which the VM hands in as a *versiondb.Database (the per-block in-memory version layer). A Put therefore stages into the version layer during block processing and becomes durable ONLY when the VM commits the batch at Accept — the exact commit discipline dexvm/state/state.go follows. This package never imports the zapdb engine directly; it speaks only the luxfi/database interface, so the VM is free to swap the backing store.

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrStateCorrupted is returned when a stored value cannot be decoded into
	// its expected shape — a corrupt record must never be silently reinterpreted.
	ErrStateCorrupted = errors.New("state corrupted")
)

Functions

This section is empty.

Types

type Manifest

type Manifest struct {
	FileIDs []string `json:"fileIds"`
	Size    int64    `json:"size"`
	ETag    string   `json:"etag"`
}

Manifest is the committed content manifest for one object: the file blobs that compose it plus the object-level metadata an S3 HEAD returns. It is encoded as a deterministic JSON body (no maps, declaration-order fields), the same self-describing, protobuf-free style dexvm uses for its structured values.

type State

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

State manages the S-Chain's persistent state over the version layer `db`.

func New

func New(db database.Database) *State

New creates a state manager over db — the per-block version layer the VM commits atomically at Accept. Mirrors dexstate.New (dexvm/state/state.go:96), minus the durable receipt side-channel the storage VM does not need in M0.

func (*State) GetAlloc

func (s *State) GetAlloc(rng string) (uint64, error)

GetAlloc returns the current allocator counter for range — the next id that will be handed out. An absent range reads as 0 (its first allocation starts at id 0). Reads through the version layer, so it observes a counter staged in this block before commit and the durable value after commit.

func (*State) GetLastBlock

func (s *State) GetLastBlock() (ids.ID, uint64)

GetLastBlock returns the last accepted block id and height.

func (*State) GetManifest

func (s *State) GetManifest(bucket, object string) (m Manifest, found bool, err error)

GetManifest returns the manifest for (bucket, object). found is false when no manifest exists. Reads through the version layer, so it observes a manifest staged in this block before commit (the in-flight view) and the durable store after commit — identical to dexvm's versiondb-backed reads.

func (*State) Initialize

func (s *State) Initialize() error

Initialize loads the last-accepted block pointer from the database.

func (*State) PutManifest

func (s *State) PutManifest(bucket, object string, m Manifest) error

PutManifest stages a manifest into the version layer. It becomes durable only when the VM commits the block's batch at Accept — before that, a GetManifest on a freshly-constructed reader over the base DB does not see it. This is the versiondb/CommitBatch discipline the M0 proof asserts.

func (*State) Root

func (s *State) Root() (ids.ID, error)

Root returns a deterministic SHA-256 commitment over the COMMITTED object keyspaces: every manifest/<bucket>/<object> -> {fileIds,size,etag} entry AND every alloc/<range> -> counter entry the chain holds after this block's writes are staged. It is the value the block header binds, so two validators whose committed state actually diverges — a different object set, a changed etag/size/fileIds for an object, OR a different allocator counter for a range — ALWAYS produce different roots. Divergence can never hide behind a matching block hash. This is the manifest-VM analog of dexvm's State.StateHash (dexvm/state/state.go:395), covering the storage VM's two committed keyspaces.

The walk iterates each rootPrefix in turn via the zapdb prefix iterator NewIteratorWithStartAndPrefix(nil, prefix), so it reads through the versiondb (this block's staged in-memory writes merged over the durable base, deleted keys dropped). Only the manifest + alloc keyspaces are folded — the last-block pointer is consensus binding folded separately into the header via blockHash/height, NOT object state, so it is excluded here exactly as dexvm excludes its proposer-local receipt prefix.

The prefix order (rootPrefixes) is fixed and the keys within each prefix come out in lexicographic order, so the digest is independent of write history. Each field (domain, key, value) is framed with SP 800-185 left_encode of its BIT length before it is absorbed, so no two distinct (key,value) splits can collide by concatenation — the same canonicalization the validator NodeID scheme uses (ids/node_id_scheme.go). And because every key is absorbed WITH its full prefix, a manifest key and an alloc key can never alias even if their suffixes coincide. The hash is SHAKE256 (SHA-3): not length-extendable (unlike SHA-256), domain-separated by stateRootDomain, and PQ-strength (256-bit output → 128-bit collision/preimage even under Grover).

func (*State) SetAlloc

func (s *State) SetAlloc(rng string, n uint64) error

SetAlloc stages the allocator counter for range into the version layer. It becomes durable only when the VM commits the block's batch at Accept — the same versiondb/CommitBatch discipline as PutManifest. The value is a fixed 8-byte big-endian uint64 so the stored bytes are canonical (GetAlloc rejects any other width as corruption).

func (*State) SetLastBlock

func (s *State) SetLastBlock(blockID ids.ID, height uint64) error

SetLastBlock records the last accepted block id + height (32+8 bytes).

Jump to

Keyboard shortcuts

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