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

v0 source realm

Package bfdemo is the playground for the guest-VM work: a realm that runs Brainfuck programs on chain, a slice at a t...

Readme View source

r/moul/x/vm/bfdemo

A realm that runs Brainfuck programs on chain, a slice at a time.

It is a demo of p/moul/x/vm/bf (the machine) and p/moul/x/vm/vmkit (the host ABI, the fuel meter, the instance store), and carries no logic of its own.

What it exists to show is the thing gno realm code cannot do for itself: a program that runs out of fuel does not fail, it pauses. The realm keeps the snapshot, and the next caller pays for the next slice. Upload a program, call Step a few times, and watch one computation finish across several transactions.

Calls

function what
Upload(src, input, budget) compile and store a program, returns its id. Compilation happens here, so a malformed program is rejected by the transaction that submitted it
Step(id, fuel) run one slice and keep the snapshot. Anyone may pay for a slice, not only the owner
Remove(id) delete an instance. Owner only

Render("/") lists the instances and offers three sample programs. Render("/<id>") shows one instance: its compiled program, status, fuel, and output.

Limits

Everything a caller can grow is bounded, because all of it is storage somebody pays a deposit on: 64 instances, 64 KiB of source, 1 KiB of input, 4 KiB of output, 5,000,000 fuel per slice, 30,000 tape cells. A guest that writes past the output cap is trapped rather than truncated, so the rendered output is never a lie.

Untrusted input

A program's source is caller-supplied, and everything outside the eight operators is a comment that may hold anything at all. The page never renders it: it shows the program the machine actually compiled, which cannot contain a backtick or a newline and so cannot break out of its code fence. Guest output is arbitrary bytes and is escaped the same way, backtick included.

No instance is funded, so Host.Send always returns ErrNotGranted. That is the capability rule doing its job, not a missing feature.


Part of moul/gno-contracts — moul's versioned gno.land contracts. See the repository for the full catalog, build/test tooling, and usage.

Dependency graph:

gno.land/r/moul/x/vm/bfdemo/v0 dependency graph

🧪 Highly experimental — potentially vibe-coded. Not audited; may break, change, or be removed at any time. Do not use with anything of value. Full disclaimer: DISCLAIMER.

Overview

Package bfdemo is the playground for the guest-VM work: a realm that runs Brainfuck programs on chain, a slice at a time.

It is a demo of two libraries and carries no logic of its own: p/moul/x/vm/bf(/p/moul/x/vm/bf/v0) is the machine, and p/moul/x/vm/vmkit(/p/moul/x/vm/vmkit/v0) is the host ABI, the fuel meter and the instance store.

What it exists to show is the thing gno realm code cannot do for itself: a program that runs out of fuel does not fail, it pauses. The realm keeps the snapshot, and the next caller pays for the next slice. Upload a program, call Step a few times, and watch one computation finish across several transactions.

Constants 1

const MaxInstances, MaxOutput, MaxInput, DefaultFuel, MaxSliceFuel

 1const (
 2	// MaxInstances is how many programs the realm keeps at once. Past it,
 3	// an upload has to wait for someone to remove one.
 4	MaxInstances = 64
 5	// MaxOutput caps the bytes one program may write. Past it the guest is
 6	// trapped rather than truncated, so rendered output is never a lie.
 7	MaxOutput = 4096
 8	// MaxInput caps the call input a program can be given.
 9	MaxInput = 1024
10	// DefaultFuel is the budget an upload gets when it asks for none, and
11	// the slice size Step uses when asked for none.
12	DefaultFuel = 100000
13	// MaxSliceFuel bounds one transaction's work regardless of what the
14	// caller asked for.
15	MaxSliceFuel = 5000000
16)
source

Caps. Everything a caller can grow is bounded, because all of it is storage somebody pays a deposit on.

Functions 4

func Remove

crossing Action
1func Remove(cur realm, id string)
source

Remove deletes an instance. Owner only.

func Render

1func Render(path string) string
source

Render is the realm's gnoweb view.

  • "/" the samples, the instance list, and how the thing works.
  • "/<id>" one instance: its program, status, fuel and output.

func Step

crossing Action
1func Step(cur realm, id string, fuel int64) string
source

Step runs one slice of the instance: up to `fuel` guest ops, then stop and keep the snapshot. Anyone may pay for a slice, not only the owner: a paused program that only its owner can advance is a worse demo and no safer, since the program and its budget were both fixed at upload.

func Upload

crossing Action
1func Upload(cur realm, src, input string, budget int64) string
source

Upload compiles src and stores it as a new instance, returning its id.

Compilation happens here rather than at the first Step, so an unbalanced program is rejected by the transaction that submitted it instead of costing somebody else the gas later.

Imports 11

Source Files 5