Universal Asset Protocol July 2026 Update.

A follow-up to Universal Asset Protocol announcement

Whippetcoin Do Not Use Blockchain version 1.2.0 is available. This is a mandatory upgrade.

The original UAP post promised that “with OP_MINT and OP_INSPECT, you actually can build token systems that enforce conservation and covenants at the consensus level.” I’ve since then spent more time analyzing the code and the intent and have made a new Whippetcoin release that makes this more true.

OP_MINT didn’t require a signature

I first implemented OP_MINT as a scriptPubKey opcode that validated its own conditions (entry fee, salt length, overflow) and then unconditionally succeeded without requiring any scriptSig requirement at all. In practice that meant any real WHIP value locked in a mint output could be spent by anyone who saw it, not just its intended owner.

Two of the five safety properties described in my original design doc were also unimplemented: “one-shot” (an input can’t already carry a UAP asset) and “strict script” (outputs must match an enforced template).

Why did this show up now? I spent some AI tokens to write better, more comprehensive end-to-end tests.

What changed

OP_MINT now requires the recipient’s signature. The script format gained a recipient pubkey (<pubkey> <multiplier> <salt> OP_MINT), and spending now requires a valid signature from that key, checked unconditionally. The core now enforces encoding strictness for that signature and pubkey (DER form, low-S, defined hashtype, pubkey format), rather than applying them only with the policy SCRIPT_VERIFY_STRICTENC-style flags in place. Those flags govern mempool-policy only, and they’re not required for consensus, so relying on them here would have let a miner include a malformed-encoding signature or pubkey directly in a block.

A new OP_MINT_TRANSFER opcode replaces the old, unenforced covenant convention. Previously, “covenant” outputs were just a suggested script pattern. Nothing forced a spending transaction to actually respect the convention. Now, spending a OP_MINT/OP_MINT_TRANSFER position requires the transaction to produce at least one continuing OP_MINT_TRANSFER output carrying the same multiplier, with total output value bounded by the input’s value. This strengthens the rule of token conservation.

One-shot enforcement is real, by checking that no sibling input in a mint transaction is itself an unspent UAP position. This was the second most invasive code change in this whole effort, extending the script-checker interface to see prevout scripts at all, plumbed through from the actual coins view at the validation call site.

Two independent mint lineages can’t be merged, and it costs nothing extra to prove it. This turned out to be a free consequence of how the conservation check works (it runs once per UAP input, each demanding the transaction’s total covenant-output value fit within that input’s own value) rather than something built and verified separately. Same-multiplier positions get scarce, traceable-to-a-single-mint identity without any token-ID bookkeeping.

Non-covenant outputs are now allowed alongside a covenant continuation. This is a relaxation of the rules needed to make an atomic token-for-WHIP swap possible in a single transaction (token input + buyer’s payment input → covenant to buyer + payment to seller + change). Verified this doesn’t reopen the merge-prevention property above.

Activation is height-gated. All of this used to be live from genesis with no activation mechanism at all. It now activates at block 80,000 on mainnet and testnet. Before that height, the opcodes fail closed, not silently continue under the old, unsigned behavior.

While I have no expectation that anyone will merge mine, I realized that the previous releases re-used Dogecoin’s merge mining chain ID, so I’ve corrected that at block 80,000 as well, bundling both changes into the same activation height.

Features Built on this Foundation

contrib/uap-js is a dependency-free JavaScript library for building and signing UAP transactions client-side, in a browser or Node, with no build step. It never talks to the network. Instead, you supply it UTXO details and it hands you signed transaction hex.

contrib/uap-indexer is a small Go service and tiny HTTP API that watches a node’s RPC and answers the question “which UTXOs are UAP positions”. It also hosts a genuinely non-custodial order relay: makers sign standing sell orders with SIGHASH_SINGLE|ANYONECANPAY (committing only to their own input and their own payment, not the token’s eventual destination), and any taker can fill one later with zero live coordination. The relay never holds funds or keys, and independently-run instances can mirror each other’s order books with no shared trust. Validation of mirrored orders operates exactly like locally-submitted orders.

Docker image and operator’s guide is documentation for anyone who wants to run their own indexer/relay instance. You need to know enough to use the commands docker build and docker run and provide credentials via environment variables.

How we know this actually works

I’ve tested every claim against a live whippetd on regtest, as well as via unit tests in isolation: mint, transfer, wrong-signer rejection, value-inflation rejection, an atomic swap, a maker/taker order filled by a party with no back-channel to the maker, and cross-relay mirroring between two independently-run indexer instances. This caught several real bugs.

If you’re running your own UAP tooling: this changes the mint script format, requires a recipient pubkey where there wasn’t one before, and changes what a valid spend of an existing OP_MINT output looks like. See doc/uap-minting-guide.md for the updated format and doc/uap-marketplace-design.md / doc/uap-marketplace-operators-guide.md for everything built on top.