LEZ Program Registry
On LEZ, a program is known by its id: a long string that says nothing about what the program does. The registry turns that id into a name, a version, an author and a description, with the program’s interface file and a pointer to source code you can rebuild and compare.
It is built so that, before you sign, a wallet can show which program you are about to call and whether its code matches its published source.
Writing a program or an app? Register it.
Built and tested. Not released: LEZ testnet 0.4 hasn’t launched.
Without the registryCall program <program id>
- Deployer entry: written with the program’s own key
- Fresh: the program runs the code the entry describes
- Verified: this machine rebuilt it from its recorded source
What an entry holds
Each entry records the program’s name, version, author, description and tags, a pointer to its interface file (its IDL), and a pointer to its source: the repository, the commit and the exact build configuration.
- Deployer entry
- Can only be written with the authorization needed to deploy or upgrade the program, so it comes from whoever controls the program. A client recognises it from its address alone.
- Community entries
- Anyone can publish an entry about someone else’s program. It is kept separately and can never take the deployer entry’s place.
- Proven author
- An account that signed the registration. Only that author can update the entry; handing it over needs both the old and the new author’s signatures. A frozen entry can’t change at all.
- Fresh or stale
- One read returns the entry and the live program together. If the program was upgraded since, the entry shows as stale: it describes other code.
A name in the registry is not unique and is not a guarantee. Anyone can register an entry with any name, even for an account with no program on it; lezreg marks those NO-PROGRAM and ranks them last. Only a deployer entry was written by the program’s own key.
From an id to something you can check
Look up the id
One read of the program’s account returns the deployer entry and the live program. No indexer and no server in between: reads go to the LEZ sequencer you choose.
Compare with the running code
Fresh means the program runs the code the entry claims. Stale means it was upgraded since, and its IDL may no longer match.
Fetch the interface
The IDL comes from Logos Storage and is checked against the hash recorded on chain before it is read. If it can’t be fetched, the entry still shows, marked “IDL unavailable”.
Rebuild the source
lezreg verifyrebuilds the recorded source in Docker, with the network off for the compile, and compares the result with what the entry claims and what is live:Match,MatchStale,MismatchorNotReproducible. A match can mark the program verified on your machine.
“Verified” therefore means your own machine rebuilt the running program from its recorded source. It shows where the code came from, not that the code is safe or good.
What it does not cover: every read trusts the sequencer you point it at, since there are no light-client proofs for LEZ state yet. And the registry program itself can be upgraded by whoever holds its key; like any program, an upgrade shows as a stale entry, here the registry’s own entry in itself.
Apps, checked by LNS name
Basecamp apps are found and checked by the LNS name of their publisher, such as alice. An app counts as verified only when three things agree: the record on the name alice vouches for the package’s root hash, the package’s manifest names lns:alice as its author, and the copy you installed has that same root hash. Only the holder of alice can change its records, so a copy can claim to come from alice but can’t make that name vouch for it.
The records sit in the name’s sealed profile, so only someone who knows the name can find its apps, and a privately held name lets a publisher stay anonymous. Each record can list the programs the app calls, and each of those shows its registry status.
- verified
- The name vouches for this exact package.
- mismatch
- The name publishes this app but doesn’t vouch for this package: a copy, or a release it hasn’t published yet.
- not published
- The name says nothing about this app.
- no such name
- The package claims an LNS name that isn’t registered.
- unclaimed
- The package doesn’t name an LNS publisher.
Where it stands
- Built
- The on-chain program, a Rust and a JavaScript SDK, the
lezregcommand line, theprogram_registryBasecamp module and a GitHub Action. - Tested
- On LEZ 0.4 release candidates. CI builds the program on two runners and gets byte-identical output. An end-to-end job starts its own local sequencer and Logos Storage nodes, deploys the registry, fetches its IDL through another node, and rebuilds the program to a
Match. These jobs passed on the latest main-branch commit when this page was written: see the runs. - Deployed
- Not yet. LEZ testnet 0.4 hasn’t launched, so there is no registry program id. In
lezreg, thetestnetnetwork is a placeholder with no address, and it says so.
Built as an entry for λPrize LP-0023. Open source under MIT or Apache-2.0.
Try it on a local chain
For now these commands run against a LEZ 0.4 sequencer you start on your own machine. The README explains how, under A local sequencer and the registry ELF. There are no release binaries: build lezreg from source, which needs Rust and the RISC Zero toolchain (Install).
git clone https://github.com/jefdiesel/lez-program-registry
cd lez-program-registry
cargo build --release -p lezreg
Point it at your chain
lezreg network set local --registry <REGISTRY_ID> # chain/deploy.sh does this for you
lezreg --network local list # local = http://127.0.0.1:3062
Look things up
lezreg show <PROGRAM_ID> # deployer entry (fresh/stale) + community entries
lezreg list --limit 20 # newest first, with fresh/stale/NO-PROGRAM; prints the --after cursor
lezreg search name token # exact name first, then names containing "token"
lezreg verify <program> [--mark] # rebuild in Docker, compile offline: Match / MatchStale / Mismatch
Check an app
Pass the LNS program id with --lns (or set LEZREG_LNS).
lezreg app show alice # its apps, and their programs' registry status
lezreg app verify alice_ui-1.2.0.lgx # verified / mismatch / not published / unclaimed
From a Basecamp app
Install the program_registry module from the catalog at https://raw.githubusercontent.com/jefdiesel/logos-modules/main/logos-repo.json, point it at the network once, then call it. Every method answers {success, value, error}.
logos.callModule("program_registry", "config_set", [JSON.stringify({
sequencer: "http://127.0.0.1:3062", registry: "<registry id>" })])
// A wallet prompt's one line:
var label = JSON.parse(logos.callModule("program_registry", "program_label", ["<program id>"]))
// label.value: { text: "token 1.2.0 ✓ verified", kind: "deployer", verified, stale, upgradeable, ... }
// Everything, and the IDL:
var resolved = JSON.parse(logos.callModule("program_registry", "resolve_program", ["<program id>"]))
var idl = JSON.parse(logos.callModule("program_registry", "get_idl", ["<program id>"]))
For apps, the same module has verify_app(module_name) for an installed app, verify_package(manifest) before installing, and publisher_apps(name) to list a name’s apps.
For program and app authors
Register a program or app
You register with your own key, from lezreg: one command deploys and registers a program, or registers one you deployed earlier. App publishers add a record to their LNS name. Nothing goes through this website.
Showing a program in your app
Resolving an id to a label and its IDL takes a few lines with the JavaScript SDK (sdk/js/lezreg.js: no dependencies, browsers and Node 19+):
import { Registry, fetchIdl } from "./lezreg.js";
const reg = new Registry({ rpc: "http://127.0.0.1:3062", registry: "<registry id>" });
const { deployer, freshness } = await reg.resolve("<program id>");
if (deployer) {
console.log(deployer.name, deployer.version, freshness); // "fresh", "stale" or "no-program"
const { status, idl } = await fetchIdl(deployer, { storageApi: "http://127.0.0.1:8080/api/storage/v1" });
console.log(status === "ok" ? idl.instructions.length : `IDL unavailable: ${status}`);
}
// One line for a prompt:
const label = await reg.programLabel("<program id>"); // { text, kind, stale, ... }
Show a stale entry as stale. The same path in Rust is a runnable example that CI runs on every push; both are in docs/sdk.md.