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.
| Auth type | Byte | Key check | Typical use |
|---|---|---|---|
| Script-only | 0x00 | None. The witness script alone decides | Pure covenants, vaults, DEX orders |
| Post-quantum | 0x01 | ML-DSA-44 signature from the committed key | Quantum-resistant addresses |
| Classical | 0x02 | ECDSA secp256k1 signature from the committed compressed key | Classical 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.
| Family | Output | Address | Key | Witness |
|---|---|---|---|---|
| Strict PQ | OP_2 <commitment> | pq1z… / tpq1z… | ML-DSA-44 | 0x01 <sig> <pubkey> OP_TRUE |
| Strict ECDSA | OP_3 <commitment> | nq1r… / tnq1r… | Compressed secp256k1 | 0x02 <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.
| Bit | Field |
|---|---|
| 0 | Version |
| 1 | Locktime |
| 2 | SHA256d of all input outpoints |
| 3 | SHA256d of all input sequences |
| 4 | SHA256d of all serialized outputs |
| 5 | Current input outpoint |
| 6 | Current input sequence |
| 7 | Current input index |
| 8 | SHA256d 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
| Opcode | Byte | Replaces | Description |
|---|---|---|---|
OP_CHECKTEMPLATEVERIFY | 0xb3 | OP_NOP4 | Commit to a template of the spending transaction |
OP_CHECKSIGFROMSTACK | 0xb4 | OP_NOP5 | Verify a signature over a stack message, ECDSA or ML-DSA-44 |
OP_OUTPUTAUTHCOMMITMENT | 0xd5 | new | Push the 32-byte AuthScript commitment of a selected witness v1 output (NIP-023) |
OP_OUTPUTAUTHDEST | 0xc2 | new | Push the 33-byte AuthScript destination of an output, version ‖ program, for v1, strict PQ v2 and strict ECDSA v3 (NIP-041) |
Transaction introspection
| Opcode | Byte | Replaces | Description |
|---|---|---|---|
OP_TXHASH | 0xb5 | OP_NOP6 | Hash of selected transaction fields |
OP_TXFIELD | 0xb6 | OP_NOP7 | Fields of the spent output: value, AuthScript commitment, scriptPubKey, strict destination |
OP_INPUTFIELD | 0xc4 | new | Field of any spent input by index: value, AuthScript commitment, full script or strict destination (NIP-043) |
OP_TXLOCKTIME | 0xc5 | new | The transaction locktime as 4 little-endian bytes |
OP_OUTPUTVALUE | 0xcc | new | Value of a selected output |
OP_OUTPUTSCRIPT | 0xcd | new | scriptPubKey of a selected output |
OP_INPUTCOUNT | 0xd0 | new | Number of inputs |
OP_OUTPUTCOUNT | 0xd1 | new | Number of outputs |
OP_INPUTVALUE | 0xd6 | new | Value of a selected input's prevout (NIP-024) |
OP_CHAINCONTEXT | 0xd7 | new | Chain height, median time past or chain id (NIP-026) |
Asset introspection
| Opcode | Byte | Description |
|---|---|---|
OP_OUTPUTASSETFIELD | 0xce | Field of the asset payload attached to an output |
OP_INPUTASSETFIELD | 0xcf | Field of the asset payload of an input's prevout |
Reference inputs
| Opcode | Byte | Description |
|---|---|---|
OP_REFINPUTCOUNT | 0xd4 | Number of reference inputs |
OP_REFINPUTFIELD | 0xd2 | Field of a reference input, without spending it |
OP_REFINPUTASSETFIELD | 0xd3 | Asset field of a reference input |
These require transaction v3. See Transactions and consensus.
Bytes and arithmetic
| Opcode | Byte | Description |
|---|---|---|
OP_CAT | 0x7e | Concatenate two byte strings (re-enabled, BIP 347) |
OP_SPLIT | 0xb7 | Split a byte string at a position |
OP_REVERSEBYTES | 0xbc | Reverse the top stack item |
OP_MUL, OP_DIV, OP_MOD | 0x95, 0x96, 0x97 | Re-enabled with 64-bit signed, overflow-checked arithmetic. OP_ADD and OP_SUB are upgraded to 64 bits as well |
Hashes and signatures
| Opcode | Byte | NIP | Description |
|---|---|---|---|
OP_KECCAK256 | 0xba | 030 | Keccak-256, for Ethereum-compatible commitments |
OP_BLAKE2B | 0xbb | 030 | BLAKE2b |
OP_CHECKMERKLEINCLUSION | 0xc1 | 031 | Native Merkle proof verification with a tree-scheme selector. Scheme 05 verifies Poseidon trees (NIP-043) |
OP_BLAKE3 | 0xc8 | 034 | BLAKE3 |
OP_POSEIDON | 0xc9 | 036 | SNARK-friendly hash over the BN254 scalar field |
OP_SHA3_256 | 0xca | 034 | SHA3-256 |
OP_SHA512 | 0xcb | 034 | SHA-512 |
OP_CHECKSIG_ED25519 | 0xdd | 035 | Strict RFC 8032 Ed25519 verification |
OP_CHECKSIGADD | 0xde | 039 | Signature accumulator for threshold scripts, classical and PQ keys |
Zero-knowledge
| Opcode | Byte | Description |
|---|---|---|
OP_ZKVERIFY | 0xc3 | Groth16 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
NOPbehaves as thatNOP, 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_CHAINCONTEXTco-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-txtool, 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.