Expand description
DID owner spends that leave the DID itself unchanged (SPEC §3, unit U3).
The DID’s inner puzzle is spent, the DID recreates itself byte-identically, and any conditions the caller supplies ride along in that same spend. This is how a caller binds another operation to an authenticated act of the DID it controls, in one atomic bundle.
§What this composes with, and what it does not
Composition is by ANNOUNCEMENT: the DID emits an announcement another spend in the same bundle asserts, or asserts an announcement that other spend emits. Both directions are on the allowlist, and both are atomic — neither spend confirms without the other. That covers a dig-merkle store launch, an attestation, and any operation whose own spend can be authorized by “the DID spent in this bundle said so”.
Composition by MAGIC CONDITION does not work here. The data-store root updater
(UpdateDataStoreMerkleRoot, opcode −13) and the NFT owner assignment (TransferNft, opcode
−10) are both refused by the allowlist today. A DID-authorized NFT assignment is a real
operation and needs its own deliberate unit — widening a custody allowlist to make a sentence in
a doc comment true is exactly the change this guard exists to prevent.
§What the allowlist does and does not promise
It bounds the KIND of authority a spend may create, not the VALUE it may move. A permitted
even-amount CREATE_COIN may pay any amount of the caller’s bundled funds to any puzzle hash,
and a permitted CREATE_PUZZLE_ANNOUNCEMENT is emitted by the DID coin verbatim — which is
precisely how a DID grants authority to another spend. Nor does it confine every permitted shape
to this bundle: an AGG_SIG_PARENT signature is bound to the DID coin’s PARENT id, so it stays
satisfiable by any future spend of any coin sharing that parent — the outputs of the DID’s
PREVIOUS spend, not anything this spend creates. That set was fixed before this spend was built
and may include a coin an earlier caller paid to a third party. What the guard does hold: such a
signature can never reach a later generation of this DID, and can never become an off-domain
assertion. A caller who does not trust the source of these conditions must review the bundle —
and, where an AGG_SIG_PARENT is present, also what the DID’s PREVIOUS spend created, which this
bundle does not show. The guard does not make hostile conditions safe, and no allowlist over a
conditions passthrough could. See [permit_only_conditions_a_did_may_carry].
The DID’s own spend requires exactly one AGG_SIG_ME under the owner’s key. The caller’s
conditions may add signature requirements of their own on top of that, but only the kinds bound
to a coin id or parent id: the caller’s conditions are judged by an ALLOWLIST over their
re-parsed CLVM form, so AGG_SIG_UNSAFE and every other unbound or lifetime-constant signature
kind is refused. See [permit_only_conditions_a_did_may_carry] for why only an allowlist can
fail closed here.
§One odd-amount output
A singleton’s inner puzzle may emit exactly ONE odd-amount CREATE_COIN, and the DID’s own
recreation occupies it. A singleton launcher is an odd-amount coin, so a foreign singleton CANNOT
be parented to the DID coin. spend_did_with_conditions therefore refuses a caller’s
odd-amount CREATE_COIN outright: left to run, the bundle would assemble and report a child DID,
then be dropped at mempool admission — never entering a block, so costing no fee, but telling the
caller nothing about why. A DID-rooted launch parents its launcher to an ordinary coin and binds
it to the DID by other means (an announcement this spend asserts, or the launched singleton’s
owner puzzle hash). See
a_foreign_singleton_launcher_cannot_be_parented_to_the_did_coin in this module’s tests.
Functions§
- spend_
did_ with_ conditions - Spends
did, emittingconditionsin addition to the recreation condition that preserves the DID unchanged. Returns the recreated child DID.