Skip to main content

Covenants and Opcodes

POSITRONIC turns Neurai Script into a covenant environment. A covenant is a script that constrains how funds or assets may be spent, not only who may spend them. Constraints are enforced at consensus level, with no virtual machine and no trusted party.

AuthScript: the execution environment​

Covenants run inside AuthScript, a family of SegWit witness programs whose 32-byte program is a tagged commitment to how the output may be spent. Generic AuthScript is witness version 1, encoded as nc1p… on mainnet and tnc1p… on testnet and regtest. It accepts any witness script and is the family for contracts and covenants.

Output · generic AuthScript, witness v1OP_1 <32-byte commitment>commitment = TaggedHash("NeuraiAuthScript", 01 ‖ authType ‖ [hash160(key)] ‖ SHA256(script))0x00script-onlypure covenant0x01post-quantumML-DSA-440x02classicalsecp256k1spend1. Revealwitness stack:authType [sig pubkey]args… witnessScript2. Recomputehash the revealed partsmust equal thecommitted 32 bytes3. Authenticate0x01: ML-DSA-44 signature0x02: ECDSA signature0x00: nothing to check4. Authorizerun witnessScriptCTV, CSFS, TXHASH,introspection, math…who may spend (authentication) is separated from how funds may be spent (authorization), so covenants are plain script logic
Auth typeByteKey checkTypical use
Script-only0x00None. The witness script alone decidesPure covenants, vaults, DEX orders
Post-quantum0x01ML-DSA-44 signature from the committed keyQuantum-resistant addresses
Classical0x02ECDSA secp256k1 signature from the committed compressed keyClassical keys with covenant logic
commitment = TaggedHash("NeuraiAuthScript", 0x01 || authType || [hash160(pubkey)] || SHA256(witnessScript))

The witness stack for spending is:

<authType> [<signature> <pubkey>] <arg1> <arg2> ... <witnessScript>

Strict families for wallet addresses​

Wallet addresses use two strict AuthScript families. Their witness script is fixed to OP_TRUE, so a strict output is a single-key address with no script logic.

FamilyOutputAddressKeyWitness
Strict PQOP_2 <commitment>pq1z… / tpq1z…ML-DSA-440x01 <sig> <pubkey> OP_TRUE
Strict ECDSAOP_3 <commitment>nq1r… / tnq1r…Compressed secp256k10x02 <sig> <pubkey> OP_TRUE

The commitment uses the witness version as its lead byte instead of 0x01, so the same 32 bytes under another version are a different destination. Consensus requires exactly these four witness items, and OP_TRUE is never evaluated. The former nq1p… / tnq1p… encoding of witness v1 is rejected, with no alias. Wallets hand out strict addresses and never generic v1 ones. See Post-quantum addresses.

Script element limits are raised so that an ML-DSA-44 public key (1312 bytes) and signature (about 2420 bytes) fit. See Post-quantum addresses.

Covenant primitives​

OP_CHECKTEMPLATEVERIFY​

Rigid templates, as in BIP 119. The spending transaction must match a pre-committed hash of its version, locktime, input count and sequences, all outputs and the input index. The hash does not commit to input prevouts, so the covenant works whichever UTXO funds it.

<template_hash> OP_CHECKTEMPLATEVERIFY

Use it for batched payouts, vaults and congestion control: once committed, no signer can change destinations or amounts.

OP_CHECKSIGFROMSTACK​

Verifies a signature over an arbitrary message from the stack instead of the transaction hash. Both ECDSA and ML-DSA-44 keys are accepted. This is the oracle primitive: a script can require an attestation signed by a known key before releasing funds.

<sig> <msg> <pubkey> OP_CHECKSIGFROMSTACK OP_VERIFY

OP_TXHASH​

A flexible commitment (NIP-042). The script pushes a two-byte, little-endian 16-bit mask that selects which transaction fields go into a tagged hash, so a script can commit to the outputs and leave the inputs free, or the reverse.

BitField
0Version
1Locktime
2SHA256d of all input outpoints
3SHA256d of all input sequences
4SHA256d of all serialized outputs
5Current input outpoint
6Current input sequence
7Current input index
8SHA256d of all reference input outpoints, in order
tag = SHA256("NeuraiTxHash")
digest = SHA256(tag || tag || mask_le16 || selected fields, in bit order)

The mask must be nonzero with bits 9 to 15 clear, which leaves 511 valid masks. Any other selector fails the script. Outputs are hashed with their full script, asset suffix included. No mask commits to scriptSigs or witness data, so a wallet can sign after a covenant or a proof has fixed the transaction. The tag does not name a network or an application: a protocol that signs the digest should add its own tag to the signed message.

<10 00> OP_TXHASH <expected_digest> OP_EQUAL // bit 4: the outputs only

Opcode catalogue​

All opcodes below are enabled on testnet and regtest and disabled on mainnet until activation.

Covenants​

OpcodeByteReplacesDescription
OP_CHECKTEMPLATEVERIFY0xb3OP_NOP4Commit to a template of the spending transaction
OP_CHECKSIGFROMSTACK0xb4OP_NOP5Verify a signature over a stack message, ECDSA or ML-DSA-44
OP_OUTPUTAUTHCOMMITMENT0xd5newPush the 32-byte AuthScript commitment of a selected witness v1 output (NIP-023)
OP_OUTPUTAUTHDEST0xc2newPush the 33-byte AuthScript destination of an output, version ‖ program, for v1, strict PQ v2 and strict ECDSA v3 (NIP-041)

Transaction introspection​

OpcodeByteReplacesDescription
OP_TXHASH0xb5OP_NOP6Hash of selected transaction fields
OP_TXFIELD0xb6OP_NOP7Fields of the spent output: value, AuthScript commitment, scriptPubKey, strict destination
OP_INPUTFIELD0xc4newField of any spent input by index: value, AuthScript commitment, full script or strict destination (NIP-043)
OP_TXLOCKTIME0xc5newThe transaction locktime as 4 little-endian bytes
OP_OUTPUTVALUE0xccnewValue of a selected output
OP_OUTPUTSCRIPT0xcdnewscriptPubKey of a selected output
OP_INPUTCOUNT0xd0newNumber of inputs
OP_OUTPUTCOUNT0xd1newNumber of outputs
OP_INPUTVALUE0xd6newValue of a selected input's prevout (NIP-024)
OP_CHAINCONTEXT0xd7newChain height, median time past or chain id (NIP-026)

Asset introspection​

OpcodeByteDescription
OP_OUTPUTASSETFIELD0xceField of the asset payload attached to an output
OP_INPUTASSETFIELD0xcfField of the asset payload of an input's prevout

Reference inputs​

OpcodeByteDescription
OP_REFINPUTCOUNT0xd4Number of reference inputs
OP_REFINPUTFIELD0xd2Field of a reference input, without spending it
OP_REFINPUTASSETFIELD0xd3Asset field of a reference input

These require transaction v3. See Transactions and consensus.

Bytes and arithmetic​

OpcodeByteDescription
OP_CAT0x7eConcatenate two byte strings (re-enabled, BIP 347)
OP_SPLIT0xb7Split a byte string at a position
OP_REVERSEBYTES0xbcReverse the top stack item
OP_MUL, OP_DIV, OP_MOD0x95, 0x96, 0x97Re-enabled with 64-bit signed, overflow-checked arithmetic. OP_ADD and OP_SUB are upgraded to 64 bits as well

Hashes and signatures​

OpcodeByteNIPDescription
OP_KECCAK2560xba030Keccak-256, for Ethereum-compatible commitments
OP_BLAKE2B0xbb030BLAKE2b
OP_CHECKMERKLEINCLUSION0xc1031Native Merkle proof verification with a tree-scheme selector. Scheme 05 verifies Poseidon trees (NIP-043)
OP_BLAKE30xc8034BLAKE3
OP_POSEIDON0xc9036SNARK-friendly hash over the BN254 scalar field
OP_SHA3_2560xca034SHA3-256
OP_SHA5120xcb034SHA-512
OP_CHECKSIG_ED255190xdd035Strict RFC 8032 Ed25519 verification
OP_CHECKSIGADD0xde039Signature accumulator for threshold scripts, classical and PQ keys

Zero-knowledge​

OpcodeByteDescription
OP_ZKVERIFY0xc3Groth16 proof verification over BN254, inside AuthScript only. Profile 01 checks the proof. Profile 02 also checks a public Merkle tree transition with Poseidon. Used by the privacy pool

Activation and safety​

  • Each opcode has its own consensus flag. When the flag is off, an opcode that replaces a NOP behaves as that NOP, a re-enabled opcode returns a disabled-opcode error, and an opcode on a new byte slot returns a bad-opcode error. The mainnet rules therefore stay byte-for-byte unchanged until activation.
  • OP_CHAINCONTEXT co-activates 64-bit integers, because median time past will not fit in 4 bytes after 2038.
  • Policy code that verifies scripts outside consensus, such as signing RPCs and the neurai-tx tool, reads its flags through one helper so signing matches block validation on the chain the node runs on (NIP-020).

Examples​

Output-only covenant. Commit to the outputs, accept any inputs:

<10 00> OP_TXHASH <expected_outputs_hash> OP_EQUAL

Oracle-gated release. Spend only with an attestation from a known oracle key:

<oracle_pubkey> OP_CHECKSIGFROMSTACK OP_VERIFY

Partial-fill sell order. Read the asset payload of the spent output, compute the remaining amount with 64-bit arithmetic, and require the change output to re-create the same covenant. The @neuraiproject/neurai-scripts package ships a builder for this pattern.

Reference​

The full opcode specification with stack diagrams, error conditions and examples is in the node repository under doc/covenants.md and doc/new-opcodes-depin-branch.md.