/bch-bitwise

Re-enables bitwise operations, enabling Bitcoin Cash contracts to more efficiently implement a variety of financial and cryptographic applications

CHIP-2025-05 Bitwise: Re-Enable Bitwise Operations

    Title: Re-Enable Bitwise Operations
    Type: Standards
    Layer: Consensus
    Maintainer: Jason Dreyzehner
    Initial Publication Date: 2025-05-31
    Latest Revision Date: 2025-09-05
    Version: 1.1.1 (a432a19b)
    Status: Frozen for Lock-In

Summary

This proposal re-enables bitwise operations, enabling Bitcoin Cash contracts to more efficiently implement a variety of financial and cryptographic applications.

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 enable five bitwise opcodes: OP_INVERT, OP_LSHIFTNUM, OP_RSHIFTNUM, OP_LSHIFTBIN, and OP_RSHIFTBIN.

Bit Inversion

OP_INVERT

<binary_data> OP_INVERT

The OP_INVERT opcode is defined at codepoint 0x83 (131) with the following behavior:

  1. Pop the top item from the stack.1
  2. Invert (bitwise "NOT") each byte of the item, then push the result to the stack.2

OP_INVERT Clarifications

  1. If the stack is empty (no binary_data), error. Note that implementations may choose to operate on the top stack item in-place, but operation cost must be incremented as if the result were pushed again.
  2. The Operation Cost of OP_INVERT is the Base Instruction Cost plus the length of the pushed result (see Rationale: Calculation of Operation Costs). Note that the length of the result is always equal to the length of the input.

Arithmetic Shifts

OP_LSHIFTNUM

<valid_number> <bit_count> OP_LSHIFTNUM

The OP_LSHIFTNUM opcode is defined at codepoint 0x8d (141) with the following behavior:

  1. Pop the top item from the stack as a bit count (VM number).1
  2. Pop the next item from the stack as the value (VM number) to shift.2
  3. Perform an arithmetic left shift of the value by the bit count (result = value * (2 ^ bit_count)), then push the result to the stack.3

OP_LSHIFTNUM Clarifications

  1. If the stack is empty (no bit_count), error. If the popped item is not a VM Number, error. If the bit count is negative, error. See Rationale: Disallowance of Negative Shifts and Rationale: Predictable Handling of Excessive Shift Operations. Note that Maximum Stack Item Length may be increased by future upgrades. See Notice of Possible Future Expansion.
  2. If the stack is empty (no valid_number), error. If the popped item is not a valid VM Number, error.
  3. If the byte length of the result would exceed the Maximum Stack Item Length, error (implementations may optionally fast-fail such shifts). The Operation Cost of OP_LSHIFTNUM is the Base Instruction Cost plus the length of the pushed result (see Rationale: Calculation of Operation Costs). Note that the length of the output VM number may differ from the length of the input VM number.

OP_RSHIFTNUM

<valid_number> <bit_count> OP_RSHIFTNUM

The OP_RSHIFTNUM opcode is defined at codepoint 0x8e (142) with the following behavior:

  1. Pop the top item from the stack as a bit count (VM number).1
  2. Pop the next item from the stack as the value (VM number) to shift.2
  3. Perform an arithmetic right shift of the value by the bit count (result = value / (2 ^ bit_count)) rounding towards negative infinity3, then push the resulting VM number to the stack.4

OP_RSHIFTNUM Clarifications

  1. If the stack is empty (no bit_count), error. If the popped item is not a VM Number, error. If the bit count is negative, error. See Rationale: Disallowance of Negative Shifts and Rationale: Predictable Handling of Excessive Shift Operations. Note that Maximum Stack Item Length may be increased by future upgrades. See Notice of Possible Future Expansion.
  2. If the stack is empty (no valid_number), error. If the popped item is not a valid VM Number, error.
  3. The common behavior in Two's Complement right shifts (and the behavior standardized in C++20). See Rationale: Behavior of Arithmetic Right Shifts on Negative Values. Implementations may optionally include a faster return path for excessive shifts (0 for excessive shifts on positive values or -1 for excessive shifts on negative values).
  4. The Operation Cost of OP_RSHIFTNUM is the Base Instruction Cost plus the length of the pushed result (see Rationale: Calculation of Operation Costs). Note that the length of the output VM number may differ from the length of the input VM number.

Binary (Logical) Shifts

OP_LSHIFTBIN

<binary_data> <bit_count> OP_LSHIFTBIN

The OP_LSHIFTBIN opcode is defined at codepoint 0x98 (152) with the following behavior:

  1. Pop the top item from the stack as a bit count (VM number).1
  2. Pop the next item from the stack as the binary data to shift.2
  3. Perform a fixed-length, logical left shift of the data by the bit count, shifting-in 0 bits from the right and dropping shifted-out bits on the left3, then push the result to the stack.4

OP_LSHIFTBIN Clarifications

  1. If the stack is empty (no bit_count), error. If the popped item is not a VM Number, error. If the bit count is negative, error. See Rationale: Disallowance of Negative Shifts and Rationale: Predictable Handling of Excessive Shift Operations. Note that Maximum Stack Item Length may be increased by future upgrades. See Notice of Possible Future Expansion.
  2. If the stack is empty (no binary_data), error. Note that any stack item is a valid input; zero-byte inputs produce a zero-byte output.
  3. Implementations may optionally include a faster return path for excessive shifts (returning an appropriately-sized, zero-filled stack item).
  4. The Operation Cost of OP_LSHIFTBIN is the Base Instruction Cost plus the length of the pushed result (see Rationale: Calculation of Operation Costs). Note that the length of the result is always equal to the length of the input. See Rationale: Fixed-Length Result of Binary Shifts.

OP_RSHIFTBIN

<binary_data> <bit_count> OP_RSHIFTBIN

The OP_RSHIFTBIN opcode is defined at codepoint 0x99 (153) with the following behavior:

  1. Pop the top item from the stack as a bit count (VM number).1
  2. Pop the next item from the stack as the binary data to shift.2
  3. Perform a fixed-length, logical right shift of the data by the bit count, shifting-in 0 bits from the left and dropping shifted-out bits on the right3, then push the result to the stack.4

OP_RSHIFTBIN Clarifications

  1. If the stack is empty (no bit_count), error. If the popped item is not a VM Number, error. If the bit count is negative, error. See Rationale: Disallowance of Negative Shifts and Rationale: Predictable Handling of Excessive Shift Operations. Note that Maximum Stack Item Length may be increased by future upgrades. See Notice of Possible Future Expansion.
  2. If the stack is empty (no binary_data), error. Note that any stack item is a valid input; zero-byte inputs produce a zero-byte output.
  3. Implementations may optionally include a faster return path for excessive shifts (returning an appropriately-sized, zero-filled stack item).
  4. The Operation Cost of OP_RSHIFTBIN is the Base Instruction Cost plus the length of the pushed result (see Rationale: Calculation of Operation Costs). Note that the length of the result is always equal to the length of the input. See Rationale: Fixed-Length Result of Binary Shifts.

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 Stack Item Length (A.K.A. MAX_SCRIPT_ELEMENT_SIZE), maximum bytecode length (A.K.A. MAX_SCRIPT_SIZE), or otherwise. See Limits CHIP Rationale: Inclusion of "Notice of Possible Future Expansion".

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

Acknowledgements

Thank you to the following contributors for reviewing and contributing improvements to this proposal, providing feedback, and promoting consensus among stakeholders: Calin Culianu

Changelog

This section summarizes the evolution of this proposal.

  • v1.1.1 – 2025-09-05 (a432a19bdiff vs. master)
    • Update VMB tests and benchmarks
  • v1.1.0 – 2025-06-09 (1c954588)
    • More predictable handling of excessive shifts (#2)
  • v1.0.0 – 2025-05-31 (4fab9dfe)
    • Initial publication

Copyright

This document is placed in the public domain.