Documentation
¶
Overview ¶
Package schain implements the Lux S-Chain — the STORAGE VM.
The S-Chain records object STORAGE MANIFESTS through real Lux consensus: a PutManifest mutation enters the mempool, the proposer drains it into a block, every validator deterministically applies it to a per-block version layer during Verify, and the block COMMITS the version layer to the chain's database (zapdb via the luxfi/database interface) in exactly ONE atomic batch at Accept. A manifest is durable — and GetManifest returns it — only after Accept.
M0 is the smallest end-to-end proof of that contract: no blobs, no pinning, no networking beyond the VM↔engine contract. It forks dexvm's structure and COMMIT DISCIPLINE (chains/dexvm/vm.go), stripped of the DEX's cross-chain relay/settlement machinery, which a storage VM does not have:
- vm.db (versiondb) is the per-block state layer; vm.baseDB is the durable base it wraps (mirror of dexvm/vm.go:316-318).
- ProcessBlock applies txs to the version layer, NO I/O, deterministic (mirror of dexvm/vm.go:542).
- acceptBlock does ONE db.CommitBatch() + batch.Write() then db.Abort() (mirror of dexvm/vm.go:1194 — its no-shared-memory branch).
DESIGN: no background goroutines; every operation is block-driven and deterministic, so every node produces identical state from identical inputs.
Index ¶
- Variables
- type Block
- func (b *Block) Accept(ctx context.Context) error
- func (b *Block) Bytes() []byte
- func (b *Block) Height() uint64
- func (b *Block) ID() ids.ID
- func (b *Block) Parent() ids.ID
- func (b *Block) ParentID() ids.ID
- func (b *Block) Reject(ctx context.Context) error
- func (b *Block) Status() uint8
- func (b *Block) Timestamp() time.Time
- func (b *Block) Verify(ctx context.Context) error
- type BlockResult
- type ChainVM
- func (cvm *ChainVM) BuildBlock(ctx context.Context) (chain.Block, error)
- func (cvm *ChainVM) Connected(ctx context.Context, nodeID ids.NodeID, v *version.Application) error
- func (cvm *ChainVM) Disconnected(ctx context.Context, nodeID ids.NodeID) error
- func (cvm *ChainVM) GetBlock(ctx context.Context, blkID ids.ID) (chain.Block, error)
- func (cvm *ChainVM) GetBlockIDAtHeight(ctx context.Context, height uint64) (ids.ID, error)
- func (cvm *ChainVM) GetInnerVM() *VM
- func (cvm *ChainVM) HealthCheck(ctx context.Context) (chain.HealthResult, error)
- func (cvm *ChainVM) Initialize(ctx context.Context, vmInit vmcore.Init) error
- func (cvm *ChainVM) LastAccepted(ctx context.Context) (ids.ID, error)
- func (cvm *ChainVM) NewHTTPHandler(ctx context.Context) (http.Handler, error)
- func (cvm *ChainVM) ParseBlock(ctx context.Context, data []byte) (chain.Block, error)
- func (cvm *ChainVM) SetPreference(ctx context.Context, blkID ids.ID) error
- func (cvm *ChainVM) SetState(ctx context.Context, stateNum uint32) error
- func (cvm *ChainVM) Shutdown(ctx context.Context) error
- func (cvm *ChainVM) SubmitTx(tx []byte) error
- func (cvm *ChainVM) Version(ctx context.Context) (string, error)
- func (cvm *ChainVM) WaitForEvent(ctx context.Context) (vmcore.Message, error)
- type Factory
- type Status
- type VM
- func (vm *VM) CreateHandlers(ctx context.Context) (map[string]http.Handler, error)
- func (vm *VM) GetBlockHeight() uint64
- func (vm *VM) GetLastBlockTime() time.Time
- func (vm *VM) GetManifest(bucket, object string) (state.Manifest, bool, error)
- func (vm *VM) HealthCheck(ctx context.Context) (chain.HealthResult, error)
- func (vm *VM) Initialize(ctx context.Context, vmInit vmcore.Init) error
- func (vm *VM) ProcessBlock(ctx context.Context, blockHeight uint64, blockTime time.Time, ...) (*BlockResult, error)
- func (vm *VM) SetState(ctx context.Context, stateNum uint32) error
- func (vm *VM) Shutdown(ctx context.Context) error
- func (vm *VM) Version(ctx context.Context) (string, error)
Constants ¶
This section is empty.
Variables ¶
var ( // VMID is the unique identifier for the S-Chain storage VM. Derived from the // ASCII bytes of "schain", left-aligned and zero-padded to 32 bytes — the same // byte pattern dexvm uses (dexvm/factory.go:31, ids.ID{'d','e','x','v','m'}). VMID = ids.ID{'s', 'c', 'h', 'a', 'i', 'n'} )
Functions ¶
This section is empty.
Types ¶
type Block ¶
type Block struct {
// contains filtered or unexported fields
}
Block is an S-Chain block. It wraps the deterministic ProcessBlock result and implements chain.Block. It carries only the storage VM's needs: a header and the serialized PutManifest transactions — no cross-chain carried fills (the dexvm wire-format complication a storage VM does not have).
func (*Block) Accept ¶
Accept marks the block accepted and commits its state batch in ONE atomic write (the single commit point — dexvm/block.go:159). After this returns, the block's manifests are durable and GetManifest observes them.
func (*Block) Bytes ¶
Bytes serializes the block. Wire format:
height[8] | timestamp[8] | parentID[32] | stateRoot[32] | txCount[4] | txCount × ( txLen[4] | txBytes )
The txCount prefix makes the transactions self-delimiting. stateRoot is the proposer's claimed manifest state root, carried in the header so the block id (sha256 of these bytes) commits to it — a peer cannot swap the claimed root or a manifest while keeping the same id, and Verify rejects a claimed root that does not match the root recomputed from the applied txs.
func (*Block) Reject ¶
Reject discards the block's staged version-layer changes (dexvm/block.go:175).
func (*Block) Verify ¶
Verify processes the block deterministically against the version layer, then enforces the manifest STATE ROOT: it recomputes the root from the txs it just applied and rejects the block if that computed root does not match the root the proposer claimed in the header. This is the multi-validator safety gate — a proposer (or a corrupted replica) whose post-apply manifest state diverges from what an honest validator computes cannot get its block accepted, because the claimed root (committed by the block id) and the recomputed root disagree. Verify performs NO external I/O on any node (mirror of dexvm/block.go:141); the manifest writes land in the in-memory version layer and become durable only at Accept.
type BlockResult ¶
type BlockResult struct {
BlockHeight uint64
Timestamp time.Time
// StateRoot is the deterministic commitment over the manifest keyspace AFTER
// this block's writes are staged, folded with the block's consensus binding
// (blockHash + height). It travels in the block header and Block.Verify
// recomputes it on every validator and rejects a block whose claimed root
// does not match — the multi-validator safety gate M0 omitted.
StateRoot ids.ID
// contains filtered or unexported fields
}
BlockResult is the deterministic result of processing one block. For the storage VM the per-block output is simply the height/time/blockHash binding — the manifest mutations are staged directly into the version layer by ProcessBlock and committed at Accept. There is no cross-chain leg to carry.
type ChainVM ¶
type ChainVM struct {
// contains filtered or unexported fields
}
ChainVM wraps the functional storage VM to implement chain.ChainVM — the interface the chains manager drives. It owns the in-memory block index, mempool, and last-accepted pointers; the inner VM owns state + commit. This is the dexvm/chainvm.go boilerplate, stripped of the DEX fee gate and DAG hooks the storage VM does not need.
func NewChainVM ¶
NewChainVM constructs a ChainVM wrapping a fresh inner storage VM.
func (*ChainVM) BuildBlock ¶
BuildBlock drains the mempool into a new block on top of the preferred tip. The proposer chooses the block time (wall clock, clamped non-decreasing) and carries it in the bytes — the consensus-agreement point. The block id is the hash of the serialized bytes, so it commits to every drained transaction.
func (*ChainVM) Disconnected ¶
Disconnected is a no-op for M0.
func (*ChainVM) GetBlockIDAtHeight ¶
GetBlockIDAtHeight returns the accepted block id at a height.
func (*ChainVM) GetInnerVM ¶
GetInnerVM exposes the inner VM for direct reads (e.g. GetManifest).
func (*ChainVM) HealthCheck ¶
HealthCheck delegates to the inner VM.
func (*ChainVM) Initialize ¶
Initialize wires the inner VM and seeds the genesis block.
func (*ChainVM) LastAccepted ¶
LastAccepted returns the last accepted block id.
func (*ChainVM) NewHTTPHandler ¶
NewHTTPHandler assembles the inner VM's handlers behind one mux.
func (*ChainVM) ParseBlock ¶
ParseBlock parses a block from bytes, deduplicating against the index.
func (*ChainVM) SetPreference ¶
SetPreference sets the tip new blocks build on.
func (*ChainVM) SubmitTx ¶
SubmitTx admits a transaction to the mempool and notifies the engine to build a block. This is the canonical user-mempool entry. The bytes are validated (parse + Verify) before they touch the pending pool, so a malformed manifest never enters a block.
func (*ChainVM) WaitForEvent ¶
WaitForEvent blocks until an event should trigger block building. M0 triggers builds via SubmitTx -> PendingTxs on toEngine, so this simply parks until the context is cancelled (mirror of dexvm/chainvm.go:408).
type Factory ¶
type Factory struct{}
Factory creates new S-Chain VM instances for the chains manager.
type VM ¶
type VM struct {
// contains filtered or unexported fields
}
VM is the inner functional storage VM. It holds the dual-DB layering and the typed manifest state; the chain.ChainVM wrapper (ChainVM) drives it.
func (*VM) CreateHandlers ¶
CreateHandlers returns the VM's HTTP handlers. M0 exposes none (the VM contract + commit discipline is the deliverable; the S3 API surface is M1+).
func (*VM) GetBlockHeight ¶
GetBlockHeight returns the current block height.
func (*VM) GetLastBlockTime ¶
GetLastBlockTime returns the timestamp of the last processed block.
func (*VM) GetManifest ¶
GetManifest returns a committed manifest for (bucket, object). Reads go through the version layer, so this observes only state already committed by an accepted block (the in-memory staging from an unaccepted block is the proposer's transient view, not durable). The M0 proof asserts a manifest is visible here ONLY after Accept.
func (*VM) HealthCheck ¶
HealthCheck reports the VM healthy once initialized.
func (*VM) Initialize ¶
Initialize sets up the VM with the consensus runtime, database, and channels. It establishes the dual-DB layering (baseDB durable, db versiondb) the commit discipline depends on — the exact wiring of dexvm/vm.go:311-321.
func (*VM) ProcessBlock ¶
func (vm *VM) ProcessBlock(ctx context.Context, blockHeight uint64, blockTime time.Time, blockTxs [][]byte) (*BlockResult, error)
ProcessBlock deterministically applies a block's transactions to the version layer. It performs NO external I/O — the same inputs produce identical state on every node, so Verify is a pure function (mirror of dexvm/vm.go:542). The manifest writes land in vm.db's in-memory layer and become durable only when acceptBlock commits the batch.
Directories
¶
| Path | Synopsis |
|---|---|
|
Package object wires the S3 OBJECT path to the S-Chain storage VM, proving the on-chain-metadata / off-chain-blob split end to end:
|
Package object wires the S3 OBJECT path to the S-Chain storage VM, proving the on-chain-metadata / off-chain-blob split end to end: |
|
Package pinning is the deterministic single-writer assignment for the S-Chain storage VM.
|
Package pinning is the deterministic single-writer assignment for the S-Chain storage VM. |
|
Package state manages persistent state for the S-Chain — the Lux storage VM.
|
Package state manages persistent state for the S-Chain — the Lux storage VM. |
|
Package txs defines the transaction surface for the S-Chain — the Lux STORAGE VM.
|
Package txs defines the transaction surface for the S-Chain — the Lux STORAGE VM. |