Skip to content

Singular 0.10.0 — any wallet joins and folds a registry from its state token

Choose a tag to compare

@lambdasistemi-ci lambdasistemi-ci released this 11 Oct 19:04
· 420 commits to main since this release
d2e3c18

Singular is a permissionless registry of unique keys on Cardano: each active key is held as one token in an output of the application that uses the registry. In this release a registry has two permanent operations, registering a key and terminating it for good, and it is run by independent participants. Anyone holding a registry's state token, a wallet and a Koios endpoint (Koios is a public Cardano chain-data API) can inspect it, book a request and fold pending requests — a fold is the transaction that applies requests to the registry — with no shared directory and no node socket. The registry's state is rebuilt from its public chain history on every command. The command line is split in two: singular registry for the registry, open-datum for the example application that keeps a free payload under each key.

What changed

The registry contract

  • A registry admits exactly two operations for its whole life: registration (a key goes from absent to active) and permanent termination (active to terminal). The other five historical edge encodings still decode, for refusal tests, but can never reach a successful fold. The validators, transaction builders, simulator and documentation follow this single law (#523).
  • A request carries the datum its receiving output must hold, so a folder who did not book it can fold it from the public request alone; the private preimage store is removed (#421).

Commands

  • singular is the registry command line: registry create | fold | reject | reclaim | inspect. open-datum is a separate executable with create, insert, update, terminate, fold and inspect; insert and terminate accept --fold to book and fold in one command. The open-datum validators move to their own Aiken project, with every validator hash unchanged (#535).
  • Booking and folding are separate commands. insert and terminate book a request and print its fold deadline; fold settles it with whichever wallet runs it (#367).
  • registry reject clears requests that are past both their processing and retract windows, refunding each owner (#374). registry reclaim --request TXID#IX lets the owner take back a pending request inside its retract window (#380). Both judge the windows from the ledger tip, never the host clock (#397).
  • registry create takes --process-time MS and --retract-time MS; the defaults are 600 000 and 300 000 milliseconds, fixed for the life of the registry (#405).
  • insert builds the open-datum envelope itself from the key, the signing wallet, the deposit (default 2 000 000 lovelace) and a JSON payload; --envelope is removed. --key takes text and --key-hex takes hex on every command (#365, #369).
  • A booking that the key's current entry rules out (inserting a registered or retired key, updating or terminating an unregistered one) is refused before signing, with a reason labelled client policy, and leaves no pending request (#535).
  • fold judges each pending request on its own and settles the first that passes, in ledger order; every request left out is named in the receipt with its reason. --request names the request the fold is expected to settle (#556).

Joining a registry from public data

  • Every command names the registry by --state-token; create prints the token and writes no identity file. A participant joins from an empty directory with only the token, a wallet and a provider (#476).
  • Commands rebuild the registry's trie from the state token's public history, checking the root at every fold. Transactions that failed their scripts are left out, and a withheld or inconsistent history is refused by name (HistoryIncomplete, RootDoesNotChain). The saved trie mirror is removed (#391, #411).
  • Local state (journal, saved bodies, lock) is kept per network, state token and wallet under $XDG_STATE_HOME/singular; --state-dir (renamed from --registry) overrides the root. inspect --wallet-address reconciles a wallet's interrupted writes without a signing key (#524, #525).
  • A packaged two-actor journey (nix run .#registry-two-actors) runs Alice and Bob on one registry from separate homes, each folding the other's requests (#433).

Chain access through Koios

  • Registry commands read and submit through a Koios ledger provider with the caller's own wallet. Script budgets are evaluated locally and validity intervals are converted from pinned network time. The node adapter is removed: no ordinary command accepts a node socket or backend selector, and old socket and backend settings are refused by name (#402, #410, #460).
  • Confirmation is awaited on the calling thread and retries after 1, 2 and 4 seconds before settling at 5. A command keeps the identity of a transaction it submitted when confirmation times out, and never resubmits it (#512, #548).

Narration and refusals

  • Every command can narrate what it does: --trace off|what|how, --trace-to stderr|file:PATH (repeatable) and --trace-format text|json (JSON Lines). Standard output stays the command's receipt (#418). Setting SINGULAR_LOG=<file> writes a timestamped phase log (#366).
  • Every trie refusal names its registry, its transaction and its cause.

Evidence that the chain refuses

  • A new test executable, singular-negative, submits forbidden transactions with no client-side checks and judges the node's own answer. Each forbidden move (a stranger's update, a tampered update, a release outside a fold, a short fold, a taken or revived key) runs beside an accepting control on a development network built from the release archive (#533, #537, #550).
  • Mutant validators: for each refusing rule, one patch removes exactly that rule, and the matching pair must then fail (#558).
  • The conformance suite re-evaluates each refused transaction against traced validators and compares the reason with the one the Lean model (the formal specification) gives (#357). Its registry rows run as generic programs, and requirements carry plain-language names (#373, #378).

Release and test machinery

  • Demo 1, recovery and end-to-end checks run as parallel hosted jobs, each proved to have run before its result is trusted; development-shell steps run as Nix apps; Node 20 actions move to Node 24; refusal evidence uploads are compressed.

Use it

  1. Download singular-onchain-0.10.0.tar.gz and SHA256SUMS. The checksum file also covers singular-docs-0.10.0.tar.gz; download it too to check every listed file.
  2. Run sha256sum --check SHA256SUMS, extract the on-chain archive, then run bash verify-identities.sh inside it to check the compiled validators. To check the whole release from its downloaded bytes, including a run of the commands on a development network, run nix run github:lambdasistemi/singular/v0.10.0#verify-release -- v0.10.0 (https://github.com/lambdasistemi/singular/blob/v0.10.0/docs/verify-release.md).
  3. Follow DEMO1.md in the archive. It builds singular, open-datum and a private development node with Nix, then runs a registry end to end: create, insert, fold by another wallet, inspect, update, terminate, reject and reclaim.
  4. README.md in the archive describes the bounded registry journey (nix run .#journey from offchain/) and the identity and fixture checks.
  5. To run against a test network with your own Koios endpoint and wallet, follow https://github.com/lambdasistemi/singular/blob/v0.10.0/docs/consumer-onboarding.md. For what a preprod run checks, see https://github.com/lambdasistemi/singular/blob/v0.10.0/docs/demo1-preprod.md. The full command reference is https://github.com/lambdasistemi/singular/blob/v0.10.0/docs/singular-node.md.

Limits

  • This release abandons registries deployed with earlier contracts; there is no migration. The preprod record (docs/preprod.md) describes such an earlier deployment and its historical tools.
  • No public-network run of Demo 1 has happened for this release; the preprod page is a reviewer's map, not a record of a run.
  • A fold settles one request at a time: the journal binds one transition per fold.
  • A reject refund is accepted by the chain only as one output to the request's owner (issue #361).
  • The archive still carries the row runners of the earlier naming design (claim, recovery, retirement). They are not buildable or verified against this release's source and must not be relied on.

Full list of changes: v0.9.0...v0.10.0