Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Anatomy of a manifest

Before writing any recipes, let's look at the skeleton every manifest shares. A manifest is a single JSON document. At the top level it has an envelope of metadata fields followed by the data sections.

{
  "manifest_version": "0.2.0",
  "protocol": "p2pk-simplicity",
  "description": "Pay-to-public-key using a Simplicity checksig program on Liquid.",
  "chain": "liquid",

  "utxo_types":         { ... },
  "contract_templates": { ... },
  "actions":            { ... }
}

The envelope

FieldRequiredPurpose
manifest_versionyesVersion of the tx-manifest format itself. Current: "0.2.0".
protocolyesKebab-case protocol identifier, e.g. "simplicity-lending".
descriptionnoFree-text summary of the whole protocol.
chainno"bitcoin", "liquid"/"elements", or "cross-chain". Defaults to "elements".
simplicity_hlnoSimplicityHL toolchain settings. See below.

Two authoring keys may appear on any object at any depth and carry no protocol meaning: $comment, for prose a tool must ignore, and $schema, an editor hint pointing at the JSON Schema. Both are stripped before a manifest is interpreted.

simplicity_hl — how the covenants are compiled

The whole block is optional, and so is every field in it. Written out with its defaults, it says exactly what omitting it says:

"simplicity_hl": {
  "debug_symbols": false,
  "unstable_features": []
}
FieldTypeDefaultEffect
debug_symbolsbooleanfalseCompile the .simf programs with debug symbols. Changes every covenant address.
unstable_featuresarray of strings[]Allow gated SimplicityHL syntax. Never changes an address.

debug_symbols

Compiles contracts with debug_symbols enabled. Note that this will change the CMR and addresses generated. In general this should not be used (or set to false), but is present to interact with contracts that are already deployed with this set to true.

unstable_features

The manifest form of simc -Z <name>. If you are using a contract that requires unstable features, you can enable them here.

The data sections

Three sections describe the protocol itself. Most files carry two of them, and none is required — a manifest with an empty actions map is still a manifest. Each gets a chapter of its own; this table is the map.

SectionHoldsCovered in
utxo_typesThe covenant addresses this protocol locks value to — one named entry per on-chain state, each pointing at a .simf programCovenant UTXO types
actionsOne transaction recipe each: which UTXOs to consume, what to create, what witnesses satisfy themHello World, Outputs & destinations, Witnesses
contract_templatesA typed contract: named fields plus the actions that operate on them, with one instance per deploymentInstance, state & constructors

Two shapes, and when the second one arrives

A protocol with a single contract type can put its actions straight under top-level actions, and give each one the params it needs. That is the whole file — no templates, no instance. Every recipe up to Witnesses is written this way.

contract_templates earns its place the moment a value has to outlive a single transaction. A loan's collateral amount is chosen once, baked into a covenant address, and then read back by four later actions; it cannot be a param, because a param is gone when the transaction is built. Declaring it as a template field stores it in the instance, where later actions reach it as instance.NAME. That is the whole distinction, and Parameters draws it out properly.

The two are not alternatives to choose between up front. A file may carry top-level actions and contract_templates at once — the lending example does, using standalone actions for setup work that belongs to no instance.

Read a real one. The fastest way to see how these fit together is examples/p2pk/txmanifest.json in the wallet repository — the smallest complete manifest — and then examples/lending_v3, which uses every section at once.

For the exhaustive list of fields each section accepts, with types and defaults, see the manifest field reference.

What runs it

A manifest is declarative: it says what a transaction must look like, never how to build one. Turning it into a signed transaction is a wallet's job — tx-manifest-wallet resolves the params, finds the inputs, compiles the covenants, builds and signs a PSET, dry-runs the Simplicity programs, and broadcasts. Each recipe introduces the parts it needs, so there is nothing to learn here up front; the wallet implementation guide has the full sequence for when you want it.

With the skeleton in hand, let's write our first contract.