Skip to content Search Apps Documentation Source Content File Folder Download Copy Actions State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

Community realm. Read the code first. Community realm, deployed by its author. Read the code before you interact or send coins.

machine.gno

3.76 Kb · 100 lines
  1// Package vmkit is the host ABI shared by every guest virtual machine that
  2// runs inside a gno realm: a stepping contract with an explicit fuel budget,
  3// a capability-scoped [Host], and a snapshot format that lets a guest program
  4// outlive the transaction that started it.
  5//
  6// A guest VM implements [Machine]. Everything else in this package is the
  7// machinery a VM should not have to write twice: the [Meter], the [Codec] the
  8// snapshots are built from, an in-memory [TestHost], and the avl-backed
  9// [Store] a realm keeps its instances in.
 10//
 11// The three things the ABI exists to fix:
 12//
 13//   - Fuel is the interface, not the backstop. Running out of fuel yields
 14//     [OutOfFuel] plus a machine that can be snapshotted, never a panic. Gas
 15//     still bounds the transaction, but a guest that stops is a normal outcome.
 16//   - Continuations. Snapshot and Restore mean a program runs across blocks.
 17//     The realm stores the bytes, and the next caller pays for the next slice.
 18//     Gno realm code itself cannot pause; a guest can.
 19//   - Capabilities, not ambient authority. A guest gets exactly the [Host] it
 20//     was handed. No Send without a grant, no storage outside its own scope.
 21//
 22// Live demo: [r/moul/x/vm/bfdemo](/r/moul/x/vm/bfdemo/v0), running the
 23// [p/moul/x/vm/bf](/p/moul/x/vm/bf/v0) guest.
 24package vmkit
 25
 26// Status is the outcome of a call to [Machine.Step].
 27type Status int
 28
 29const (
 30	// Running means the machine stopped because it ran out of the fuel
 31	// handed to this slice, but the program has not finished. It is
 32	// resumable: snapshot it, and step it again later.
 33	Running Status = iota
 34
 35	// Halted means the program reached its end. Terminal.
 36	Halted
 37
 38	// Trapped means the guest did something the machine refuses to do:
 39	// an invalid instruction, an out-of-range access, a capability it was
 40	// not granted. Terminal.
 41	Trapped
 42
 43	// OutOfFuel means the instance exhausted its total budget, not just the
 44	// fuel for this slice. Terminal unless the owner raises the budget.
 45	OutOfFuel
 46)
 47
 48// String renders the status as the lowercase word used in realm output.
 49func (s Status) String() string {
 50	switch s {
 51	case Running:
 52		return "running"
 53	case Halted:
 54		return "halted"
 55	case Trapped:
 56		return "trapped"
 57	case OutOfFuel:
 58		return "out of fuel"
 59	}
 60	return "unknown"
 61}
 62
 63// Done reports whether the status is terminal, i.e. stepping again is
 64// pointless without operator intervention.
 65func (s Status) Done() bool { return s != Running }
 66
 67// Machine is one guest virtual machine, mid-execution.
 68//
 69// Step runs until the program halts, traps, or burns `fuel` units, whichever
 70// comes first, and reports how much fuel it actually used. A Machine must
 71// charge at least one unit per guest instruction so that a fuel budget is a
 72// real bound on work; beyond that the unit is the VM's own business, and
 73// [r/moul/x/vm/bfdemo](/r/moul/x/vm/bfdemo/v0) compares them by measurement
 74// rather than by trusting the number.
 75//
 76// Snapshot must round-trip through Restore: a machine stepped to exhaustion,
 77// snapshotted, restored and stepped again must produce exactly what the same
 78// machine stepped in one go would have. That property is what makes a guest
 79// program a contract instead of a function call.
 80type Machine interface {
 81	Step(h Host, fuel int64) (used int64, status Status)
 82	Snapshot() []byte
 83	Restore(b []byte) error
 84}
 85
 86// Trapper is an optional refinement of [Machine]: a machine that can explain
 87// why it trapped. Kept out of [Machine] so the core ABI stays three methods.
 88type Trapper interface {
 89	// Trap returns the reason for a [Trapped] status, or "" when the
 90	// machine has not trapped.
 91	Trap() string
 92}
 93
 94// TrapReason returns m's trap reason when m implements [Trapper], else "".
 95func TrapReason(m Machine) string {
 96	if t, ok := m.(Trapper); ok {
 97		return t.Trap()
 98	}
 99	return ""
100}