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
This proposal re-enables bitwise operations, enabling Bitcoin Cash contracts to more efficiently implement a variety of financial and cryptographic applications.
Deployment of this specification is proposed for the May 2026 upgrade.
- Activation is proposed for
1763208000MTP, (2025-11-15T12:00:00.000Z) onchipnet. - Activation is proposed for
1778846400MTP, (2026-05-15T12:00:00.000Z) on the BCH network (mainnet),testnet3,testnet4, andscalenet.
The virtual machine is modified to enable five bitwise opcodes: OP_INVERT, OP_LSHIFTNUM, OP_RSHIFTNUM, OP_LSHIFTBIN, and OP_RSHIFTBIN.
<binary_data> OP_INVERT
The OP_INVERT opcode is defined at codepoint 0x83 (131) with the following behavior:
- Pop the top item from the stack.1
- Invert (bitwise "NOT") each byte of the item, then push the result to the stack.2
- 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. - The Operation Cost of
OP_INVERTis 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.
<valid_number> <bit_count> OP_LSHIFTNUM
The OP_LSHIFTNUM opcode is defined at codepoint 0x8d (141) with the following behavior:
- Pop the top item from the stack as a bit count (VM number).1
- Pop the next item from the stack as the value (VM number) to shift.2
- 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
- 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. - If the stack is empty (no
valid_number), error. If the popped item is not a valid VM Number, error. - 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_LSHIFTNUMis 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.
<valid_number> <bit_count> OP_RSHIFTNUM
The OP_RSHIFTNUM opcode is defined at codepoint 0x8e (142) with the following behavior:
- Pop the top item from the stack as a bit count (VM number).1
- Pop the next item from the stack as the value (VM number) to shift.2
- 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
- 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. - If the stack is empty (no
valid_number), error. If the popped item is not a valid VM Number, error. - 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 (
0for excessive shifts on positive values or-1for excessive shifts on negative values). - The Operation Cost of
OP_RSHIFTNUMis 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_data> <bit_count> OP_LSHIFTBIN
The OP_LSHIFTBIN opcode is defined at codepoint 0x98 (152) with the following behavior:
- Pop the top item from the stack as a bit count (VM number).1
- Pop the next item from the stack as the binary data to shift.2
- Perform a fixed-length, logical left shift of the data by the bit count, shifting-in
0bits from the right and dropping shifted-out bits on the left3, then push the result to the stack.4
- 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. - 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. - Implementations may optionally include a faster return path for excessive shifts (returning an appropriately-sized, zero-filled stack item).
- The Operation Cost of
OP_LSHIFTBINis 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.
<binary_data> <bit_count> OP_RSHIFTBIN
The OP_RSHIFTBIN opcode is defined at codepoint 0x99 (153) with the following behavior:
- Pop the top item from the stack as a bit count (VM number).1
- Pop the next item from the stack as the binary data to shift.2
- Perform a fixed-length, logical right shift of the data by the bit count, shifting-in
0bits from the left and dropping shifted-out bits on the right3, then push the result to the stack.4
- 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. - 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. - Implementations may optionally include a faster return path for excessive shifts (returning an appropriately-sized, zero-filled stack item).
- The Operation Cost of
OP_RSHIFTBINis 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.
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".
This proposal includes a suite of functional tests and benchmarks to verify the performance of all operations within virtual machine implementations.
Please see the following implementations for examples and additional test vectors:
- C++:
- Bitcoin Cash Node (BCHN) – A professional, miner-friendly node that solves practical problems for Bitcoin Cash. Merge Request !1962.
- JavaScript/TypeScript:
- Libauth – An ultra-lightweight, zero-dependency JavaScript library for Bitcoin Cash. Branch
next. - Bitauth IDE – An online IDE for bitcoin (cash) contracts. Branch
next.
- Libauth – An ultra-lightweight, zero-dependency JavaScript library for Bitcoin Cash. Branch
Thank you to the following contributors for reviewing and contributing improvements to this proposal, providing feedback, and promoting consensus among stakeholders: Calin Culianu
This section summarizes the evolution of this proposal.
- v1.1.1 – 2025-09-05 (
a432a19b– diff 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
This document is placed in the public domain.