Skip to content

Enables Bitcoin Cash contract bytecode to be factored into reusable functions

Notifications You must be signed in to change notification settings

bitjson/bch-functions

Repository files navigation

CHIP-2025-05 Functions: Function Definition and Invocation Operations

    Title: Function Definition and Invocation Operations
    Type: Standards
    Layer: Consensus
    Maintainer: Jason Dreyzehner
    Initial Publication Date: 2024-12-12
    Latest Revision Date: 2025-09-05
    Version: 2.0.2 (26e22566)
    Status: Frozen for Lock-In

Summary

This proposal introduces the OP_DEFINE and OP_INVOKE opcodes, enabling Bitcoin Cash contract bytecode to be factored into reusable functions.

Motivation & Benefits

  • Reduced transaction sizes – By eliminating duplicated bytecode, contract lengths can be optimized for a wider variety of use cases: finite field arithmetic, pairing-based cryptography, zero-knowledge proof systems, homomorphic encryption, post-quantum cryptography, and other important applications for the future security and competitiveness of Bitcoin Cash.

  • Stronger privacy and operational security – By enabling contract designs which leak less information about security measures, current assets, and transaction history, this proposal strengthens privacy and operational security for a variety of use cases.

  • Improved auditability – Without reusable functions, contracts are forced to unnecessarily duplicate significant logic. This proposal enables contracts to be written using more succinct, auditable patterns.

Deployment

Deployment of this specification is proposed for the May 2026 upgrade.

  • Activation is proposed for 1763208000 MTP, (2025-11-15T12:00:00.000Z) on chipnet.
  • Activation is proposed for 1778846400 MTP, (2026-05-15T12:00:00.000Z) on the BCH network (mainnet), testnet3, testnet4, and scalenet.

Technical Specification

The virtual machine is modified to add a Function Table of immutable functions, the OP_DEFINE opcode is defined at codepoint 0x89 (137), and the OP_INVOKE opcode is defined at 0x8a (138).

Function Table

The virtual machine (VM) is modified to add a new data structure: the Function Table is a map that holds immutable byte vectors; it maps each defined function identifier to an immutable function body (the byte vector).

Due to VM limits, the function table does not exceed Maximum Memory Slots in defined function count, and the function table's held byte vectors do not exceed the Stack Element Length Limit.

Defined Function Count

A Defined Function Count counter is added to track the count of defined functions.

Function Identifier

A function identifier – the function's key in the function table – is a byte string of length 0 to 7 (inclusive).

Maximum Memory Slots (MAX_MEMORY_SLOTS)

The existing cumulative stack and altstack depth limit (A.K.A. MAX_STACK_SIZE; 1000 items) is modified to incorporate Defined Function Count: the sum of stack depth, alternate stack depth, and Defined Function Count must be less than Maximum Memory Slots, set to 1000.

Notice of Possible Future Expansion

While unusual, it is possible to design pre-signed transactions, contract systems, and protocols which rely on the rejection of otherwise-valid transactions made invalid only by specifically exceeding one or more current VM limits. This proposal interprets such failure-reliant constructions as intentional – the constructions are designed to fail unless/until a possible future network upgrade in which such limits are increased, e.g. upgrade-activation futures contracts. Contract authors are advised that future upgrades may raise VM limits by increasing Maximum Memory Slots, or otherwise. See Limits CHIP Rationale: Inclusion of "Notice of Possible Future Expansion".

Reset Before Each Bytecode Evaluation

Prior to each phase of evaluation (unlocking bytecode, locking bytecode, and redeem bytecode), the Function Table and Defined Function Count must be reset to an empty table and 0, respectively.

OP_DEFINE

<function_body> <function_identifier> OP_DEFINE

The OP_DEFINE opcode is defined at codepoint 0x89 (137) with the following behavior:

  1. Pop the top item from the stack to interpret as a function identifier (a binary string of length 0 to 7, inclusive).1
  2. Pop the next item from the stack to interpret as the function body2, and copy it to the function table at the key equal to the function identifier. If that function key is already defined, error.3
  3. Increment Defined Function Count by one.4

OP_DEFINE Clarifications

  1. If the stack is empty (no function_identifier), error. If the length of the popped item is outside of the range 0 to 7 (inclusive), error. See Rationale: Use of Stack-Based Parameters and Rationale: Format of Function Identifiers.
  2. if the stack is empty (no function_body), error. Note that any stack item is a valid function body (including empty stack items); implementations must not attempt to parse the function body until invoked by OP_INVOKE. See Rationale: Deferred Parsing of Function Bodies.
  3. See Rationale: Immutability of Function Bodies. Note also that function identifiers/table keys may be defined in any order. See Rationale: Support for Skipping Function Identifiers.
  4. Note that the Operation Cost of OP_DEFINE is equal to the Base Instruction Cost plus the Stack-Pushed Bytes cost for the function body.

OP_INVOKE

<function_identifier> OP_INVOKE

The OP_INVOKE opcode is defined at codepoint 0x8a (138) with the following behavior:

  1. Pop the top item from the stack to interpret as a function identifier.1
  2. Preserve the active bytecode (A.K.A. script), instruction pointer (A.K.A. program counter or pc), and index of the last executed code separator (A.K.A. pbegincodehash) by pushing them to the top of the control stack.2 (Note that this subjects function invocations to the existing control stack depth limit of 100.)
  3. Reset the instruction pointer and last executed code separator, then execute the function body as if it were the active bytecode.3 If the bytecode is malformed (i.e. a push operation requires more bytes than are available in the remaining segment of bytecode to be parsed), error.
  4. When the evaluation is complete4, restore the original bytecode, instruction pointer, and last executed code separator, then continue evaluation after the OP_INVOKE instruction.5

OP_INVOKE Clarifications

  1. If the stack is empty (no function_identifier), error. If the popped item is not a VM Number representing a previously-defined function in the function table, error. If the referenced function body has a length of zero: error if the control stack depth limit of 100 would be exceeded by a non-empty evaluation; otherwise, continue after the OP_INVOKE instruction.
  2. Note that this requires the control stack to be capable of holding a new stack frame data type to preserve the state of the parent evaluation.
  3. OP_INVOKEed bytecode otherwise shares the context of the parent evaluation:
    1. Invoked functions may modify the stack, alternate stack, and function table. Note that invoked functions are subject to the following limits:
      • Control stack usage (e.g. OP_IF/OP_END_IF and/or further OP_INVOKEs) within the evaluation remains restricted by the 100-item depth limit (cumulatively applied to all nested function calls).
      • Stack depth + alternate stack depth + Defined Function Count must be no larger than Maximum Memory Slots (formerly: MAX_STACK_SIZE), which is currently 1000.
    2. Executed OP_CODESEPARATOR operations record the index of the current instruction pointer (A.K.A. pc) within the OP_INVOKEed bytecode as the last executed code separator (A.K.A. pbegincodehash).
    3. The OP_ACTIVEBYTECODE operation produces the serialization of the active bytecode beginning from the last executed code separator.
    4. In signature operations, the covered bytecode includes only the active bytecode beginning from the last executed code separator (or if none have been executed in the current evaluation, the full active bytecode).
  4. For an OP_INVOKE evaluation to complete successfully, the top element remaining on the control stack must be a stack frame to resume after the evaluation. (E.g. Validation fails if an OP_IF within the evaluation is not resolved by a matching OP_ENDIF within the same evaluation.)
  5. After an active bytecode has been fully evaluated, the next stack frame is resumed (restoring its bytecode, instruction pointer, and last executed code separator values) until all stack frames are complete (the control stack is empty) or the evaluation has produced some error. Note that two or more OP_INVOKE operations may be resolved within the same virtual machine step (e.g. if a child OP_INVOKE is the final instruction of a parent OP_INVOKE evaluation). Note that the Operation Cost of OP_INVOKE is equal to the Base Instruction Cost.

Rationale

Evaluations of Alternatives

Risk Assessment

Test Vectors

This proposal includes a suite of functional tests and benchmarks to verify the performance of all operations within virtual machine implementations.

Implementations

Please see the following implementations for examples and additional test vectors:

Feedback & Reviews

Changelog

This section summarizes the evolution of this proposal.

Copyright

This document is placed in the public domain.

About

Enables Bitcoin Cash contract bytecode to be factored into reusable functions

Topics

Resources

Stars

Watchers

Forks

Contributors