Improving BitVMX with Bitcoin Soft-forks

BitVMX is a complex general-purpose proving system designed to overcome the limitations of Bitcoin script. To achieve its goal it pays a price: a dispute consumes 250K vbytes of transaction witness space, and each verifier can initiate a dispute simultaneously, multiplying this number.
Due to the limitations in Bitcoin script, many Bitcoin builders are pushing for different kinds of Bitcoin upgrades. An upgrade to Bitcoin may take several years, and competing proposals may delay the decision an eternity. Since the BitVMX FORCE team is committed to making BitVMX the foundation for smart contract applications on Bitcoin, we asked ourselves: how much more powerful could BitVMX become if Bitcoin adopts certain proposed features? The answer is clear — it becomes even more useful! Not only BitVMX would still be a leading tool to compute on Bitcoin, but actually BitVMX becomes more efficient, and more importantly, more decentralized, if some new opcodes are soft-forked into Bitcoin.
In this article we present different types of upgrades that Bitcoin could undergo, and how they positively impact BitVMX. For practical resource comparison, we assume we use a version of the BitVMX protocol with all the improvements we already published: interleaved search, jumplist, point-compression for SNARKs and an improved signature scheme. This is how our protocol will look by the end of the year. We call this protocol Start-Of-The-Art (SOTA) BitVMX.
We assume we will use SOTA BitVMX to verify a peg-out for a bridge contract, and this involves verifying a SNARK proof. The protocol will search over 256M execution steps, with 31 midstates per partition, 160 bits per hash, with a worst case consuming 244K vbytes per dispute in 5.5 rounds (11 transactions). We assume that there are 20 operators (provers/verifiers) that participate in the bridge. For each peg-in, each party must transfer 100 Kbytes offchain.
Native SNARK Verification
Some bitcoiners dream that one day Bitcoin will have an opcode to natively verify a SNARK. They call it OP_SNARK. While indeed it would enable a lot more functionality, it is dubious it will be ever soft-forked into Bitcoin. Including OP_SNARK requires adding thousands of complex lines of code to Bitcoin, and yet it would only enable verifying a single type of computation integrity proof (Groth16), and one that requires a trusted setup, which is not very aligned with Bitcoin ethos. In comparison, BitVMX can verify any proof, SNARKs, STARKs, bulletproofs and newer folding-based schemes.
While it is unrealistic to consider having OP_SNARK on Bitcoin, one day we might have a richer language integrated into Bitcoin, such as Simplicity or The Great Script Restoration. A richer language would allow coding the SNARK verifier in a relatively short richer Bitcoin script.
Covenants
The discussion around covenants on Bitcoin dates back to July 2013. I think I was the first to propose adding a whole bunch of opcodes to easily build covenants. Two months later, someone asked in bitcointalk how to create a reversible vault-like mechanism for Bitcoin. I created the Tick method to answer the question. It was based on emulated covenants.
A decade passed and neither full covenants nor the specific vault application of covenants (i.e. OP_VAULT) were soft-forked into Bitcoin. There are two types of covenants: recursive and non-recursive. A recursive covenant in Bitcoin is a restriction that does not just apply to the next transaction spending the coins—it also propagates its rules to every future transaction that spends those coins. In other words, the spending conditions are enforced recursively, affecting the entire downstream chain of ownership. In contrast, a non-recursive covenant limits its constraints to just the immediate next transaction. Once that transaction is completed, the restriction no longer applies, and the coins can be spent freely thereafter. There has been a long debate about whether it is good or bad to add covenants to Bitcoin, with arguments against it focusing on the potential of recursive covenants to allow coin control regimes (e.g., whitelisted wallets, KYC-enforced tokens) that could alter Bitcoin’s fungibility and censorship resistance. The covenant functionality can arise from the addition of an opcode as simple as OP_CAT with some cryptographic tricks, but OP_CAT alone does not enable the recursive kind, so it is safe regarding fungibility. However, creating covenants with OP_CAT is much more complex than doing so with other proposed opcodes such as OP_TXHASH, OP_CHECKOUTPUTVERIFY or OP_CHECKTEMPLATEVERIFY (CTV).
Covenants have two positive impacts on BitVMX:
- No need for pre-signing a transaction DAG. A sole deposit address can contain all the required structure needed to enforce the dispute channels for a related computation. Removing the pre-signing reduces the offchain bandwidth consumption, but only by 18 Kilobytes.
- No need for using the funds advance/reimburse mechanism. When BitVMX is used for bridges, the peg-out addresses must be chosen at peg-in time, preventing the bridge from pegging-out to a different user. Instead, an operator must advance the funds to the real owner of the bitcoins, and then the protocol reimburses the operator. This represents a financial cost, a point of regulatory exposure, and an unnecessary complexity which could lead to a protocol vulnerability. A covenant can constrain that a spending transaction output be associated with a different address, one that is proven by an SPV or SNARK proof to be the one owned by the user who pegged-out.
What covenants cannot do to verify a computation without the fraud-proving mechanism that is inherent to all BitVM-like protocols.
Recursive covenants can simplify certain BitVMX applications but are not essential, because SNARKs can be verified with a finite number of transactions, and the SNARK can be used to bootstrap the continuation of the covenant.
String Operations
Satoshi Nakamoto disabled the OP_CAT opcode in Bitcoin's script language due to concerns about its potential for creating resource-intensive and malicious scripts, particularly denial-of-service attacks. OP_CAT was designed to concatenate two stack items, and it could be used to build complex scripts, which, when combined with other opcodes like OP_DUP, could create very large and computationally expensive transactions. However, the risk could have been mitigated by simply establishing a maximum stack element size. The opcode OP_SUBSTR was removed together with OP_CAT.
These string operations are useful for BitVMX, setting aside that both also enable covenants. Bitcoin script has two “worlds” of data-types that can hardly communicate: Small Script and Big Script. In Small Script, all arguments are 31-bit signed integers, and there are some arithmetic operations available (add, subtract, branch depending on values). In Big Script, we can verify signatures, hash values, but we cannot operate with big values. Small values cannot be converted to big values nor the opposite. The only means of communication is by querying the size of a Big Script data type with OP_SIZE, which returns a Small Script data type. However, as soon as Big Script operations are applied, the output data types are always fixed in size, so communication breaks.
The separation between these two script worlds means we cannot use OP_HASH in connecting with small values. BitVMX uses hash chains, and if the operator lies about the correctness of a link in the hash chain this needs to be verified by a full implementation of BLAKE3 or SHA-256 in Small script. SHA-256 requires 212 Kbytes of script to do what Big script does with a single opcode OP_SHA256. A 160-bit hash can be performed with a single OP_HASH. The string opcodes allow small values to be converted into big values and vice-versa, so we get the full power of OP_SHA256. Note that OP_CAT is enough to do the conversion: scripts can use witness data to show how a list of smaller values can be concatenated to produce a bigger one, although OP_SUBSTR may be more efficient. With OP_CAT we can replace hundreds of bytes of script with a single opcode.
Additionally OP_CAT allows the creation of authenticated Merkle trees in Bitcoin script, which means that virtual CPUs can use memory Merkelization quite simply. We can prove to the script that a certain memory location was changed with a Merkle Path that performs O(log(N)) OP_HASH operations for a memory of byte size 32*N. While BitVMX does not use Memory Merkelization (for the simple reason it is very expensive without OP_HASH), it could be easily adapted to use it, if Bitcoin were to perform a soft-fork and add any of the string manipulation opcodes.
Finally OP_CAT is useful to verify STARKs on Bitcoin more efficiently. This is orthogonal to BitVMX, which, together with the ESSPI extension, can already verify STARKs directly. The ColliderVM paper authors claim the STARK verification script requires 3.5M vbytes (others claim 3.1M), and SOTA BitVMX requires 0.25M vbytes, so BitVMX is still much more efficient. It would be interesting to see a more detailed comparison between both approaches.
Arithmetic Operations
Bitcoin script lacks integer multiplication (OP_MUL) and integer division (OP_DIV) since they were disabled together with OP_CAT. However, they pose absolutely no risk to Bitcoin.
If OP_MUL ever comes back, it would greatly reduce the number of script bytes required to execute the RISC-V 32-bit multiplication opcode. However, this script is only 5 Kbytes. It is already small compared with the overall protocol overhead (500 Kbytes). Therefore, the impact on BitVMX is quite low.
Other protocols that represent the full SNARK computation in a single Bitcoin script such as BitVM2 will benefit much more from having OP_MUL included again. These protocols could see a 10X reduction in their script sizes, which implies a 10X reduction in midstates, which directly implies a 10X reduction in onchain cost. Therefore, if OP_MUL returns, BitVM2 could become competitive to BitVMX in terms of onchain cost, even if it cannot match BitVMX in terms of flexibility and lack of additional security assumptions.
The following is the code required to multiply two 32-bits numbers. It takes up 2958 script bytes. A single OP_MUL opcode could do it.
OP_PUSHNUM_15 OP_PUSHNUM_15 OP_PUSHNUM_15 OP_PUSHNUM_15 OP_PUSHNUM_15 OP_PUSHNUM_15 OP_PUSHNUM_15 OP_PUSHNUM_15 OP_PUSHNUM_15 OP_PUSHNUM_15 OP_PUSHNUM_15 OP_PUSHNUM_15 OP_PUSHNUM_15 OP_PUSHNUM_15 OP_PUSHNUM_15 OP_PUSHNUM_15 OP_PUSHNUM_1 OP_PUSHNUM_2 OP_PUSHNUM_4 OP_PUSHNUM_3 OP_PUSHNUM_6 OP_PUSHNUM_9 OP_PUSHNUM_4 OP_PUSHNUM_8 OP_PUSHNUM_12 OP_0 OP_PUSHNUM_5 OP_PUSHNUM_10 OP_PUSHNUM_15 OP_PUSHNUM_4 OP_PUSHNUM_9 OP_PUSHNUM_6 OP_PUSHNUM_12 OP_PUSHNUM_2 OP_PUSHNUM_8 OP_PUSHNUM_14 OP_PUSHNUM_4 OP_PUSHNUM_7 OP_PUSHNUM_14 OP_PUSHNUM_5 OP_PUSHNUM_12 OP_PUSHNUM_3 OP_PUSHNUM_10 OP_PUSHNUM_1 OP_PUSHNUM_8 OP_0 OP_PUSHNUM_8 OP_0 OP_PUSHNUM_8 OP_0 OP_PUSHNUM_8 OP_0 OP_PUSHNUM_9 OP_PUSHNUM_2 OP_PUSHNUM_11 OP_PUSHNUM_4 OP_PUSHNUM_13 OP_PUSHNUM_6 OP_PUSHNUM_15 OP_PUSHNUM_8 OP_PUSHNUM_1 OP_PUSHNUM_10 OP_PUSHNUM_4 OP_PUSHNUM_14 OP_PUSHNUM_8 OP_PUSHNUM_2 OP_PUSHNUM_12 OP_PUSHNUM_6 OP_0 OP_PUSHNUM_10 OP_PUSHNUM_4 OP_PUSHNUM_11 OP_PUSHNUM_6 OP_PUSHNUM_1 OP_PUSHNUM_12 OP_PUSHNUM_7 OP_PUSHNUM_2 OP_PUSHNUM_13 OP_PUSHNUM_8 OP_PUSHNUM_3 OP_PUSHNUM_14 OP_PUSHNUM_9 OP_PUSHNUM_12 OP_PUSHNUM_8 OP_PUSHNUM_4 OP_0 OP_PUSHNUM_12 OP_PUSHNUM_8 OP_PUSHNUM_4 OP_0 OP_PUSHNUM_12 OP_PUSHNUM_8 OP_PUSHNUM_4 OP_0 OP_PUSHNUM_13 OP_PUSHNUM_10 OP_PUSHNUM_7 OP_PUSHNUM_4 OP_PUSHNUM_1 OP_PUSHNUM_14 OP_PUSHNUM_11 OP_PUSHNUM_8 OP_PUSHNUM_5 OP_PUSHNUM_2 OP_PUSHNUM_15 OP_PUSHNUM_12 OP_PUSHNUM_9 OP_PUSHNUM_14 OP_PUSHNUM_12 OP_PUSHNUM_10 OP_PUSHNUM_8 OP_PUSHNUM_6 OP_PUSHNUM_4 OP_PUSHNUM_2 OP_0 OP_PUSHNUM_14 OP_PUSHNUM_12 OP_PUSHNUM_10 OP_PUSHNUM_8 OP_PUSHNUM_6 OP_PUSHNUM_4 OP_PUSHNUM_15 OP_PUSHNUM_14 OP_PUSHNUM_13 OP_PUSHNUM_12 OP_PUSHNUM_11 OP_PUSHNUM_10 OP_PUSHNUM_9 OP_PUSHNUM_8 OP_PUSHNUM_7 OP_PUSHNUM_6 OP_PUSHNUM_5 OP_PUSHNUM_4 OP_PUSHNUM_3 OP_PUSHNUM_2 OP_PUSHNUM_1 OP_0 OP_0 OP_0 OP_0 OP_0 OP_0 OP_0 OP_0 OP_0 OP_0 OP_0 OP_0 OP_0 OP_0 OP_0 OP_0 OP_PUSHNUM_14 OP_PUSHNUM_13 OP_PUSHNUM_12 OP_PUSHNUM_12 OP_PUSHNUM_11 OP_PUSHNUM_10 OP_PUSHNUM_11 OP_PUSHNUM_10 OP_PUSHNUM_9 OP_PUSHNUM_9 OP_PUSHNUM_10 OP_PUSHNUM_9 OP_PUSHNUM_8 OP_PUSHNUM_8 OP_PUSHNUM_7 OP_PUSHNUM_9 OP_PUSHNUM_8 OP_PUSHNUM_8 OP_PUSHNUM_7 OP_PUSHNUM_6 OP_PUSHNUM_6 OP_PUSHNUM_8 OP_PUSHNUM_7 OP_PUSHNUM_7 OP_PUSHNUM_6 OP_PUSHNUM_6 OP_PUSHNUM_5 OP_PUSHNUM_5 OP_PUSHNUM_7 OP_PUSHNUM_7 OP_PUSHNUM_6 OP_PUSHNUM_6 OP_PUSHNUM_5 OP_PUSHNUM_5 OP_PUSHNUM_4 OP_PUSHNUM_4 OP_PUSHNUM_6 OP_PUSHNUM_6 OP_PUSHNUM_5 OP_PUSHNUM_5 OP_PUSHNUM_4 OP_PUSHNUM_4 OP_PUSHNUM_3 OP_PUSHNUM_3 OP_PUSHNUM_3 OP_PUSHNUM_5 OP_PUSHNUM_5 OP_PUSHNUM_4 OP_PUSHNUM_4 OP_PUSHNUM_4 OP_PUSHNUM_3 OP_PUSHNUM_3 OP_PUSHNUM_3 OP_PUSHNUM_2 OP_PUSHNUM_2 OP_PUSHNUM_4 OP_PUSHNUM_4 OP_PUSHNUM_4 OP_PUSHNUM_3 OP_PUSHNUM_3 OP_PUSHNUM_3 OP_PUSHNUM_2 OP_PUSHNUM_2 OP_PUSHNUM_2 OP_PUSHNUM_1 OP_PUSHNUM_1 OP_PUSHNUM_3 OP_PUSHNUM_3 OP_PUSHNUM_3 OP_PUSHNUM_3 OP_PUSHNUM_2 OP_PUSHNUM_2 OP_PUSHNUM_2 OP_PUSHNUM_2 OP_PUSHNUM_1 OP_PUSHNUM_1 OP_PUSHNUM_1 OP_PUSHNUM_1 OP_PUSHNUM_2 OP_PUSHNUM_2 OP_PUSHNUM_2 OP_PUSHNUM_2 OP_PUSHNUM_2 OP_PUSHNUM_1 OP_PUSHNUM_1 OP_PUSHNUM_1 OP_PUSHNUM_1 OP_PUSHNUM_1 OP_0 OP_0 OP_0 OP_PUSHNUM_1 OP_PUSHNUM_1 OP_PUSHNUM_1 OP_PUSHNUM_1 OP_PUSHNUM_1 OP_PUSHNUM_1 OP_PUSHNUM_1 OP_PUSHNUM_1 OP_0 OP_0 OP_0 OP_0 OP_0 OP_0 OP_0 OP_0 OP_0 OP_0 OP_0 OP_0 OP_0 OP_0 OP_0 OP_0 OP_0 OP_0 OP_0 OP_0 OP_0 OP_0 OP_0 OP_0 OP_0 OP_0 OP_0 OP_0 OP_0 OP_0 OP_0 OP_0 OP_0 OP_0 OP_0 OP_0 OP_0 OP_PUSHBYTES_1 78 OP_PUSHBYTES_1 77 OP_PUSHBYTES_1 75 OP_PUSHBYTES_1 72 OP_PUSHBYTES_1 6e OP_PUSHBYTES_1 69 OP_PUSHBYTES_1 63 OP_PUSHBYTES_1 5c OP_PUSHBYTES_1 54 OP_PUSHBYTES_1 4b OP_PUSHBYTES_1 41 OP_PUSHBYTES_1 36 OP_PUSHBYTES_1 2a OP_PUSHBYTES_1 1d OP_PUSHNUM_15 OP_0 OP_PUSHBYTES_2 2701 OP_ROLL OP_PUSHBYTES_2 2701 OP_ROLL OP_PUSHBYTES_2 2701 OP_ROLL OP_PUSHBYTES_2 2701 OP_ROLL OP_PUSHBYTES_2 2701 OP_ROLL OP_PUSHBYTES_2 2701 OP_ROLL OP_PUSHBYTES_2 2701 OP_ROLL OP_PUSHBYTES_2 2701 OP_ROLL OP_PUSHBYTES_2 2f01 OP_ROLL OP_PUSHBYTES_2 2f01 OP_ROLL OP_PUSHBYTES_2 2f01 OP_ROLL OP_PUSHBYTES_2 2f01 OP_ROLL OP_PUSHBYTES_2 2f01 OP_ROLL OP_PUSHBYTES_2 2f01 OP_ROLL OP_PUSHBYTES_2 2f01 OP_ROLL OP_PUSHBYTES_2 2f01 OP_ROLL OP_0 OP_PICK OP_PUSHNUM_9 OP_PICK OP_2DUP OP_MIN OP_TOALTSTACK OP_MAX OP_FROMALTSTACK OP_PUSHBYTES_1 11 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 a900 OP_ADD OP_PICK OP_TOALTSTACK OP_PUSHBYTES_1 20 OP_ADD OP_PICK OP_PUSHNUM_2 OP_PICK OP_PUSHNUM_10 OP_PICK OP_2DUP OP_MIN OP_TOALTSTACK OP_MAX OP_FROMALTSTACK OP_PUSHBYTES_1 12 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 aa00 OP_ADD OP_PICK OP_ROT OP_ADD OP_TOALTSTACK OP_PUSHBYTES_1 20 OP_ADD OP_PICK OP_PUSHNUM_1 OP_PICK OP_PUSHNUM_11 OP_PICK OP_2DUP OP_MIN OP_TOALTSTACK OP_MAX OP_FROMALTSTACK OP_PUSHBYTES_1 12 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 aa00 OP_ADD OP_PICK OP_FROMALTSTACK OP_ADD OP_TOALTSTACK OP_PUSHBYTES_1 21 OP_ADD OP_PICK OP_ADD OP_PUSHNUM_3 OP_PICK OP_PUSHNUM_10 OP_PICK OP_2DUP OP_MIN OP_TOALTSTACK OP_MAX OP_FROMALTSTACK OP_PUSHBYTES_1 12 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 aa00 OP_ADD OP_PICK OP_ROT OP_ADD OP_TOALTSTACK OP_PUSHBYTES_1 20 OP_ADD OP_PICK OP_PUSHNUM_2 OP_PICK OP_PUSHNUM_11 OP_PICK OP_2DUP OP_MIN OP_TOALTSTACK OP_MAX OP_FROMALTSTACK OP_PUSHBYTES_1 12 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 aa00 OP_ADD OP_PICK OP_FROMALTSTACK OP_ADD OP_TOALTSTACK OP_PUSHBYTES_1 21 OP_ADD OP_PICK OP_ADD OP_PUSHNUM_1 OP_PICK OP_PUSHNUM_12 OP_PICK OP_2DUP OP_MIN OP_TOALTSTACK OP_MAX OP_FROMALTSTACK OP_PUSHBYTES_1 12 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 aa00 OP_ADD OP_PICK OP_FROMALTSTACK OP_ADD OP_TOALTSTACK OP_PUSHBYTES_1 21 OP_ADD OP_PICK OP_ADD OP_PUSHNUM_4 OP_PICK OP_PUSHNUM_10 OP_PICK OP_2DUP OP_MIN OP_TOALTSTACK OP_MAX OP_FROMALTSTACK OP_PUSHBYTES_1 12 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 aa00 OP_ADD OP_PICK OP_ROT OP_ADD OP_TOALTSTACK OP_PUSHBYTES_1 20 OP_ADD OP_PICK OP_PUSHNUM_3 OP_PICK OP_PUSHNUM_11 OP_PICK OP_2DUP OP_MIN OP_TOALTSTACK OP_MAX OP_FROMALTSTACK OP_PUSHBYTES_1 12 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 aa00 OP_ADD OP_PICK OP_FROMALTSTACK OP_ADD OP_TOALTSTACK OP_PUSHBYTES_1 21 OP_ADD OP_PICK OP_ADD OP_PUSHNUM_2 OP_PICK OP_PUSHNUM_12 OP_PICK OP_2DUP OP_MIN OP_TOALTSTACK OP_MAX OP_FROMALTSTACK OP_PUSHBYTES_1 12 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 aa00 OP_ADD OP_PICK OP_FROMALTSTACK OP_ADD OP_TOALTSTACK OP_PUSHBYTES_1 21 OP_ADD OP_PICK OP_ADD OP_PUSHNUM_1 OP_PICK OP_PUSHNUM_13 OP_PICK OP_2DUP OP_MIN OP_TOALTSTACK OP_MAX OP_FROMALTSTACK OP_PUSHBYTES_1 12 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 aa00 OP_ADD OP_PICK OP_FROMALTSTACK OP_ADD OP_TOALTSTACK OP_PUSHBYTES_1 21 OP_ADD OP_PICK OP_ADD OP_PUSHNUM_5 OP_PICK OP_PUSHNUM_10 OP_PICK OP_2DUP OP_MIN OP_TOALTSTACK OP_MAX OP_FROMALTSTACK OP_PUSHBYTES_1 12 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 aa00 OP_ADD OP_PICK OP_ROT OP_ADD OP_TOALTSTACK OP_PUSHBYTES_1 20 OP_ADD OP_PICK OP_PUSHNUM_4 OP_PICK OP_PUSHNUM_11 OP_PICK OP_2DUP OP_MIN OP_TOALTSTACK OP_MAX OP_FROMALTSTACK OP_PUSHBYTES_1 12 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 aa00 OP_ADD OP_PICK OP_FROMALTSTACK OP_ADD OP_TOALTSTACK OP_PUSHBYTES_1 21 OP_ADD OP_PICK OP_ADD OP_PUSHNUM_3 OP_PICK OP_PUSHNUM_12 OP_PICK OP_2DUP OP_MIN OP_TOALTSTACK OP_MAX OP_FROMALTSTACK OP_PUSHBYTES_1 12 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 aa00 OP_ADD OP_PICK OP_FROMALTSTACK OP_ADD OP_TOALTSTACK OP_PUSHBYTES_1 21 OP_ADD OP_PICK OP_ADD OP_PUSHNUM_2 OP_PICK OP_PUSHNUM_13 OP_PICK OP_2DUP OP_MIN OP_TOALTSTACK OP_MAX OP_FROMALTSTACK OP_PUSHBYTES_1 12 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 aa00 OP_ADD OP_PICK OP_FROMALTSTACK OP_ADD OP_TOALTSTACK OP_PUSHBYTES_1 21 OP_ADD OP_PICK OP_ADD OP_PUSHNUM_1 OP_PICK OP_PUSHNUM_14 OP_PICK OP_2DUP OP_MIN OP_TOALTSTACK OP_MAX OP_FROMALTSTACK OP_PUSHBYTES_1 12 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 aa00 OP_ADD OP_PICK OP_FROMALTSTACK OP_ADD OP_TOALTSTACK OP_PUSHBYTES_1 21 OP_ADD OP_PICK OP_ADD OP_PUSHNUM_6 OP_PICK OP_PUSHNUM_10 OP_PICK OP_2DUP OP_MIN OP_TOALTSTACK OP_MAX OP_FROMALTSTACK OP_PUSHBYTES_1 12 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 aa00 OP_ADD OP_PICK OP_ROT OP_ADD OP_TOALTSTACK OP_PUSHBYTES_1 20 OP_ADD OP_PICK OP_PUSHNUM_5 OP_PICK OP_PUSHNUM_11 OP_PICK OP_2DUP OP_MIN OP_TOALTSTACK OP_MAX OP_FROMALTSTACK OP_PUSHBYTES_1 12 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 aa00 OP_ADD OP_PICK OP_FROMALTSTACK OP_ADD OP_TOALTSTACK OP_PUSHBYTES_1 21 OP_ADD OP_PICK OP_ADD OP_PUSHNUM_4 OP_PICK OP_PUSHNUM_12 OP_PICK OP_2DUP OP_MIN OP_TOALTSTACK OP_MAX OP_FROMALTSTACK OP_PUSHBYTES_1 12 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 aa00 OP_ADD OP_PICK OP_FROMALTSTACK OP_ADD OP_TOALTSTACK OP_PUSHBYTES_1 21 OP_ADD OP_PICK OP_ADD OP_PUSHNUM_3 OP_PICK OP_PUSHNUM_13 OP_PICK OP_2DUP OP_MIN OP_TOALTSTACK OP_MAX OP_FROMALTSTACK OP_PUSHBYTES_1 12 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 aa00 OP_ADD OP_PICK OP_FROMALTSTACK OP_ADD OP_TOALTSTACK OP_PUSHBYTES_1 21 OP_ADD OP_PICK OP_ADD OP_PUSHNUM_2 OP_PICK OP_PUSHNUM_14 OP_PICK OP_2DUP OP_MIN OP_TOALTSTACK OP_MAX OP_FROMALTSTACK OP_PUSHBYTES_1 12 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 aa00 OP_ADD OP_PICK OP_FROMALTSTACK OP_ADD OP_TOALTSTACK OP_PUSHBYTES_1 21 OP_ADD OP_PICK OP_ADD OP_PUSHNUM_1 OP_PICK OP_PUSHNUM_15 OP_PICK OP_2DUP OP_MIN OP_TOALTSTACK OP_MAX OP_FROMALTSTACK OP_PUSHBYTES_1 12 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 aa00 OP_ADD OP_PICK OP_FROMALTSTACK OP_ADD OP_TOALTSTACK OP_PUSHBYTES_1 21 OP_ADD OP_PICK OP_ADD OP_PUSHNUM_7 OP_PICK OP_PUSHNUM_10 OP_PICK OP_2DUP OP_MIN OP_TOALTSTACK OP_MAX OP_FROMALTSTACK OP_PUSHBYTES_1 12 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 aa00 OP_ADD OP_PICK OP_ROT OP_ADD OP_TOALTSTACK OP_PUSHBYTES_1 20 OP_ADD OP_PICK OP_PUSHNUM_6 OP_PICK OP_PUSHNUM_11 OP_PICK OP_2DUP OP_MIN OP_TOALTSTACK OP_MAX OP_FROMALTSTACK OP_PUSHBYTES_1 12 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 aa00 OP_ADD OP_PICK OP_FROMALTSTACK OP_ADD OP_TOALTSTACK OP_PUSHBYTES_1 21 OP_ADD OP_PICK OP_ADD OP_PUSHNUM_5 OP_PICK OP_PUSHNUM_12 OP_PICK OP_2DUP OP_MIN OP_TOALTSTACK OP_MAX OP_FROMALTSTACK OP_PUSHBYTES_1 12 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 aa00 OP_ADD OP_PICK OP_FROMALTSTACK OP_ADD OP_TOALTSTACK OP_PUSHBYTES_1 21 OP_ADD OP_PICK OP_ADD OP_PUSHNUM_4 OP_PICK OP_PUSHNUM_13 OP_PICK OP_2DUP OP_MIN OP_TOALTSTACK OP_MAX OP_FROMALTSTACK OP_PUSHBYTES_1 12 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 aa00 OP_ADD OP_PICK OP_FROMALTSTACK OP_ADD OP_TOALTSTACK OP_PUSHBYTES_1 21 OP_ADD OP_PICK OP_ADD OP_PUSHNUM_3 OP_PICK OP_PUSHNUM_14 OP_PICK OP_2DUP OP_MIN OP_TOALTSTACK OP_MAX OP_FROMALTSTACK OP_PUSHBYTES_1 12 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 aa00 OP_ADD OP_PICK OP_FROMALTSTACK OP_ADD OP_TOALTSTACK OP_PUSHBYTES_1 21 OP_ADD OP_PICK OP_ADD OP_PUSHNUM_2 OP_PICK OP_PUSHNUM_15 OP_PICK OP_2DUP OP_MIN OP_TOALTSTACK OP_MAX OP_FROMALTSTACK OP_PUSHBYTES_1 12 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 aa00 OP_ADD OP_PICK OP_FROMALTSTACK OP_ADD OP_TOALTSTACK OP_PUSHBYTES_1 21 OP_ADD OP_PICK OP_ADD OP_PUSHNUM_1 OP_PICK OP_PUSHNUM_16 OP_PICK OP_2DUP OP_MIN OP_TOALTSTACK OP_MAX OP_FROMALTSTACK OP_PUSHBYTES_1 12 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 aa00 OP_ADD OP_PICK OP_FROMALTSTACK OP_ADD OP_TOALTSTACK OP_PUSHBYTES_1 21 OP_ADD OP_PICK OP_ADD OP_PUSHNUM_8 OP_PICK OP_PUSHNUM_10 OP_PICK OP_2DUP OP_MIN OP_TOALTSTACK OP_MAX OP_FROMALTSTACK OP_PUSHBYTES_1 12 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 aa00 OP_ADD OP_PICK OP_ROT OP_ADD OP_TOALTSTACK OP_PUSHBYTES_1 20 OP_ADD OP_PICK OP_PUSHNUM_7 OP_PICK OP_PUSHNUM_11 OP_PICK OP_2DUP OP_MIN OP_TOALTSTACK OP_MAX OP_FROMALTSTACK OP_PUSHBYTES_1 12 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 aa00 OP_ADD OP_PICK OP_FROMALTSTACK OP_ADD OP_TOALTSTACK OP_PUSHBYTES_1 21 OP_ADD OP_PICK OP_ADD OP_PUSHNUM_6 OP_PICK OP_PUSHNUM_12 OP_PICK OP_2DUP OP_MIN OP_TOALTSTACK OP_MAX OP_FROMALTSTACK OP_PUSHBYTES_1 12 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 aa00 OP_ADD OP_PICK OP_FROMALTSTACK OP_ADD OP_TOALTSTACK OP_PUSHBYTES_1 21 OP_ADD OP_PICK OP_ADD OP_PUSHNUM_5 OP_PICK OP_PUSHNUM_13 OP_PICK OP_2DUP OP_MIN OP_TOALTSTACK OP_MAX OP_FROMALTSTACK OP_PUSHBYTES_1 12 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 aa00 OP_ADD OP_PICK OP_FROMALTSTACK OP_ADD OP_TOALTSTACK OP_PUSHBYTES_1 21 OP_ADD OP_PICK OP_ADD OP_PUSHNUM_4 OP_PICK OP_PUSHNUM_14 OP_PICK OP_2DUP OP_MIN OP_TOALTSTACK OP_MAX OP_FROMALTSTACK OP_PUSHBYTES_1 12 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 aa00 OP_ADD OP_PICK OP_FROMALTSTACK OP_ADD OP_TOALTSTACK OP_PUSHBYTES_1 21 OP_ADD OP_PICK OP_ADD OP_PUSHNUM_3 OP_PICK OP_PUSHNUM_15 OP_PICK OP_2DUP OP_MIN OP_TOALTSTACK OP_MAX OP_FROMALTSTACK OP_PUSHBYTES_1 12 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 aa00 OP_ADD OP_PICK OP_FROMALTSTACK OP_ADD OP_TOALTSTACK OP_PUSHBYTES_1 21 OP_ADD OP_PICK OP_ADD OP_PUSHNUM_2 OP_PICK OP_PUSHNUM_16 OP_PICK OP_2DUP OP_MIN OP_TOALTSTACK OP_MAX OP_FROMALTSTACK OP_PUSHBYTES_1 12 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 aa00 OP_ADD OP_PICK OP_FROMALTSTACK OP_ADD OP_TOALTSTACK OP_PUSHBYTES_1 21 OP_ADD OP_PICK OP_ADD OP_PUSHNUM_1 OP_PICK OP_PUSHBYTES_1 11 OP_PICK OP_2DUP OP_MIN OP_TOALTSTACK OP_MAX OP_FROMALTSTACK OP_PUSHBYTES_1 12 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 aa00 OP_ADD OP_PICK OP_FROMALTSTACK OP_ADD OP_TOALTSTACK OP_PUSHBYTES_1 21 OP_ADD OP_PICK OP_ADD OP_PUSHNUM_8 OP_PICK OP_PUSHNUM_11 OP_PICK OP_2DUP OP_MIN OP_TOALTSTACK OP_MAX OP_FROMALTSTACK OP_PUSHBYTES_1 12 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 aa00 OP_ADD OP_PICK OP_ROT OP_ADD OP_TOALTSTACK OP_PUSHBYTES_1 20 OP_ADD OP_PICK OP_PUSHNUM_7 OP_PICK OP_PUSHNUM_12 OP_PICK OP_2DUP OP_MIN OP_TOALTSTACK OP_MAX OP_FROMALTSTACK OP_PUSHBYTES_1 12 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 aa00 OP_ADD OP_PICK OP_FROMALTSTACK OP_ADD OP_TOALTSTACK OP_PUSHBYTES_1 21 OP_ADD OP_PICK OP_ADD OP_PUSHNUM_6 OP_PICK OP_PUSHNUM_13 OP_PICK OP_2DUP OP_MIN OP_TOALTSTACK OP_MAX OP_FROMALTSTACK OP_PUSHBYTES_1 12 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 aa00 OP_ADD OP_PICK OP_FROMALTSTACK OP_ADD OP_TOALTSTACK OP_PUSHBYTES_1 21 OP_ADD OP_PICK OP_ADD OP_PUSHNUM_5 OP_PICK OP_PUSHNUM_14 OP_PICK OP_2DUP OP_MIN OP_TOALTSTACK OP_MAX OP_FROMALTSTACK OP_PUSHBYTES_1 12 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 aa00 OP_ADD OP_PICK OP_FROMALTSTACK OP_ADD OP_TOALTSTACK OP_PUSHBYTES_1 21 OP_ADD OP_PICK OP_ADD OP_PUSHNUM_4 OP_PICK OP_PUSHNUM_15 OP_PICK OP_2DUP OP_MIN OP_TOALTSTACK OP_MAX OP_FROMALTSTACK OP_PUSHBYTES_1 12 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 aa00 OP_ADD OP_PICK OP_FROMALTSTACK OP_ADD OP_TOALTSTACK OP_PUSHBYTES_1 21 OP_ADD OP_PICK OP_ADD OP_PUSHNUM_3 OP_PICK OP_PUSHNUM_16 OP_PICK OP_2DUP OP_MIN OP_TOALTSTACK OP_MAX OP_FROMALTSTACK OP_PUSHBYTES_1 12 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 aa00 OP_ADD OP_PICK OP_FROMALTSTACK OP_ADD OP_TOALTSTACK OP_PUSHBYTES_1 21 OP_ADD OP_PICK OP_ADD OP_PUSHNUM_2 OP_PICK OP_PUSHBYTES_1 11 OP_PICK OP_2DUP OP_MIN OP_TOALTSTACK OP_MAX OP_FROMALTSTACK OP_PUSHBYTES_1 12 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 aa00 OP_ADD OP_PICK OP_FROMALTSTACK OP_ADD OP_TOALTSTACK OP_PUSHBYTES_1 21 OP_ADD OP_PICK OP_ADD OP_PUSHNUM_8 OP_PICK OP_PUSHNUM_12 OP_PICK OP_2DUP OP_MIN OP_TOALTSTACK OP_MAX OP_FROMALTSTACK OP_PUSHBYTES_1 12 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 aa00 OP_ADD OP_PICK OP_ROT OP_ADD OP_TOALTSTACK OP_PUSHBYTES_1 20 OP_ADD OP_PICK OP_PUSHNUM_7 OP_PICK OP_PUSHNUM_13 OP_PICK OP_2DUP OP_MIN OP_TOALTSTACK OP_MAX OP_FROMALTSTACK OP_PUSHBYTES_1 12 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 aa00 OP_ADD OP_PICK OP_FROMALTSTACK OP_ADD OP_TOALTSTACK OP_PUSHBYTES_1 21 OP_ADD OP_PICK OP_ADD OP_PUSHNUM_6 OP_PICK OP_PUSHNUM_14 OP_PICK OP_2DUP OP_MIN OP_TOALTSTACK OP_MAX OP_FROMALTSTACK OP_PUSHBYTES_1 12 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 aa00 OP_ADD OP_PICK OP_FROMALTSTACK OP_ADD OP_TOALTSTACK OP_PUSHBYTES_1 21 OP_ADD OP_PICK OP_ADD OP_PUSHNUM_5 OP_PICK OP_PUSHNUM_15 OP_PICK OP_2DUP OP_MIN OP_TOALTSTACK OP_MAX OP_FROMALTSTACK OP_PUSHBYTES_1 12 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 aa00 OP_ADD OP_PICK OP_FROMALTSTACK OP_ADD OP_TOALTSTACK OP_PUSHBYTES_1 21 OP_ADD OP_PICK OP_ADD OP_PUSHNUM_4 OP_PICK OP_PUSHNUM_16 OP_PICK OP_2DUP OP_MIN OP_TOALTSTACK OP_MAX OP_FROMALTSTACK OP_PUSHBYTES_1 12 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 aa00 OP_ADD OP_PICK OP_FROMALTSTACK OP_ADD OP_TOALTSTACK OP_PUSHBYTES_1 21 OP_ADD OP_PICK OP_ADD OP_PUSHNUM_3 OP_PICK OP_PUSHBYTES_1 11 OP_PICK OP_2DUP OP_MIN OP_TOALTSTACK OP_MAX OP_FROMALTSTACK OP_PUSHBYTES_1 12 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 aa00 OP_ADD OP_PICK OP_FROMALTSTACK OP_ADD OP_TOALTSTACK OP_PUSHBYTES_1 21 OP_ADD OP_PICK OP_ADD OP_PUSHNUM_8 OP_PICK OP_PUSHNUM_13 OP_PICK OP_2DUP OP_MIN OP_TOALTSTACK OP_MAX OP_FROMALTSTACK OP_PUSHBYTES_1 12 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 aa00 OP_ADD OP_PICK OP_ROT OP_ADD OP_TOALTSTACK OP_PUSHBYTES_1 20 OP_ADD OP_PICK OP_PUSHNUM_7 OP_PICK OP_PUSHNUM_14 OP_PICK OP_2DUP OP_MIN OP_TOALTSTACK OP_MAX OP_FROMALTSTACK OP_PUSHBYTES_1 12 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 aa00 OP_ADD OP_PICK OP_FROMALTSTACK OP_ADD OP_TOALTSTACK OP_PUSHBYTES_1 21 OP_ADD OP_PICK OP_ADD OP_PUSHNUM_6 OP_PICK OP_PUSHNUM_15 OP_PICK OP_2DUP OP_MIN OP_TOALTSTACK OP_MAX OP_FROMALTSTACK OP_PUSHBYTES_1 12 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 aa00 OP_ADD OP_PICK OP_FROMALTSTACK OP_ADD OP_TOALTSTACK OP_PUSHBYTES_1 21 OP_ADD OP_PICK OP_ADD OP_PUSHNUM_5 OP_PICK OP_PUSHNUM_16 OP_PICK OP_2DUP OP_MIN OP_TOALTSTACK OP_MAX OP_FROMALTSTACK OP_PUSHBYTES_1 12 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 aa00 OP_ADD OP_PICK OP_FROMALTSTACK OP_ADD OP_TOALTSTACK OP_PUSHBYTES_1 21 OP_ADD OP_PICK OP_ADD OP_PUSHNUM_4 OP_PICK OP_PUSHBYTES_1 11 OP_PICK OP_2DUP OP_MIN OP_TOALTSTACK OP_MAX OP_FROMALTSTACK OP_PUSHBYTES_1 12 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 aa00 OP_ADD OP_PICK OP_FROMALTSTACK OP_ADD OP_TOALTSTACK OP_PUSHBYTES_1 21 OP_ADD OP_PICK OP_ADD OP_PUSHNUM_8 OP_PICK OP_PUSHNUM_14 OP_PICK OP_2DUP OP_MIN OP_TOALTSTACK OP_MAX OP_FROMALTSTACK OP_PUSHBYTES_1 12 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 aa00 OP_ADD OP_PICK OP_ROT OP_ADD OP_TOALTSTACK OP_PUSHBYTES_1 20 OP_ADD OP_PICK OP_PUSHNUM_7 OP_PICK OP_PUSHNUM_15 OP_PICK OP_2DUP OP_MIN OP_TOALTSTACK OP_MAX OP_FROMALTSTACK OP_PUSHBYTES_1 12 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 aa00 OP_ADD OP_PICK OP_FROMALTSTACK OP_ADD OP_TOALTSTACK OP_PUSHBYTES_1 21 OP_ADD OP_PICK OP_ADD OP_PUSHNUM_6 OP_PICK OP_PUSHNUM_16 OP_PICK OP_2DUP OP_MIN OP_TOALTSTACK OP_MAX OP_FROMALTSTACK OP_PUSHBYTES_1 12 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 aa00 OP_ADD OP_PICK OP_FROMALTSTACK OP_ADD OP_TOALTSTACK OP_PUSHBYTES_1 21 OP_ADD OP_PICK OP_ADD OP_PUSHNUM_5 OP_PICK OP_PUSHBYTES_1 11 OP_PICK OP_2DUP OP_MIN OP_TOALTSTACK OP_MAX OP_FROMALTSTACK OP_PUSHBYTES_1 12 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 aa00 OP_ADD OP_PICK OP_FROMALTSTACK OP_ADD OP_TOALTSTACK OP_PUSHBYTES_1 21 OP_ADD OP_PICK OP_ADD OP_PUSHNUM_8 OP_PICK OP_PUSHNUM_15 OP_PICK OP_2DUP OP_MIN OP_TOALTSTACK OP_MAX OP_FROMALTSTACK OP_PUSHBYTES_1 12 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 aa00 OP_ADD OP_PICK OP_ROT OP_ADD OP_TOALTSTACK OP_PUSHBYTES_1 20 OP_ADD OP_PICK OP_PUSHNUM_7 OP_PICK OP_PUSHNUM_16 OP_PICK OP_2DUP OP_MIN OP_TOALTSTACK OP_MAX OP_FROMALTSTACK OP_PUSHBYTES_1 12 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 aa00 OP_ADD OP_PICK OP_FROMALTSTACK OP_ADD OP_TOALTSTACK OP_PUSHBYTES_1 21 OP_ADD OP_PICK OP_ADD OP_PUSHNUM_6 OP_PICK OP_PUSHBYTES_1 11 OP_PICK OP_2DUP OP_MIN OP_TOALTSTACK OP_MAX OP_FROMALTSTACK OP_PUSHBYTES_1 12 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 aa00 OP_ADD OP_PICK OP_FROMALTSTACK OP_ADD OP_TOALTSTACK OP_PUSHBYTES_1 21 OP_ADD OP_PICK OP_ADD OP_PUSHNUM_8 OP_PICK OP_PUSHNUM_16 OP_PICK OP_2DUP OP_MIN OP_TOALTSTACK OP_MAX OP_FROMALTSTACK OP_PUSHBYTES_1 12 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 aa00 OP_ADD OP_PICK OP_ROT OP_ADD OP_TOALTSTACK OP_PUSHBYTES_1 20 OP_ADD OP_PICK OP_PUSHNUM_7 OP_PICK OP_PUSHBYTES_1 11 OP_PICK OP_2DUP OP_MIN OP_TOALTSTACK OP_MAX OP_FROMALTSTACK OP_PUSHBYTES_1 12 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 aa00 OP_ADD OP_PICK OP_FROMALTSTACK OP_ADD OP_TOALTSTACK OP_PUSHBYTES_1 21 OP_ADD OP_PICK OP_ADD OP_PUSHNUM_8 OP_PICK OP_PUSHBYTES_1 11 OP_PICK OP_2DUP OP_MIN OP_TOALTSTACK OP_MAX OP_FROMALTSTACK OP_PUSHBYTES_1 12 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 aa00 OP_ADD OP_PICK OP_ROT OP_ADD OP_TOALTSTACK OP_PUSHBYTES_1 20 OP_ADD OP_PICK OP_TOALTSTACK OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_PUSHNUM_15 OP_PUSHNUM_14 OP_PUSHNUM_13 OP_PUSHNUM_12 OP_PUSHNUM_11 OP_PUSHNUM_10 OP_PUSHNUM_9 OP_PUSHNUM_8 OP_PUSHNUM_7 OP_PUSHNUM_6 OP_PUSHNUM_5 OP_PUSHNUM_4 OP_PUSHNUM_3 OP_PUSHNUM_2 OP_PUSHNUM_1 OP_0 OP_PUSHNUM_15 OP_PUSHNUM_14 OP_PUSHNUM_13 OP_PUSHNUM_12 OP_PUSHNUM_11 OP_PUSHNUM_10 OP_PUSHNUM_9 OP_PUSHNUM_8 OP_PUSHNUM_7 OP_PUSHNUM_6 OP_PUSHNUM_5 OP_PUSHNUM_4 OP_PUSHNUM_3 OP_PUSHNUM_2 OP_PUSHNUM_1 OP_0 OP_PUSHNUM_15 OP_PUSHNUM_14 OP_PUSHNUM_13 OP_PUSHNUM_12 OP_PUSHNUM_11 OP_PUSHNUM_10 OP_PUSHNUM_9 OP_PUSHNUM_8 OP_PUSHNUM_7 OP_PUSHNUM_6 OP_PUSHNUM_5 OP_PUSHNUM_4 OP_PUSHNUM_3 OP_PUSHNUM_2 OP_PUSHNUM_1 OP_0 OP_PUSHNUM_15 OP_PUSHNUM_14 OP_PUSHNUM_13 OP_PUSHNUM_12 OP_PUSHNUM_11 OP_PUSHNUM_10 OP_PUSHNUM_9 OP_PUSHNUM_8 OP_PUSHNUM_7 OP_PUSHNUM_6 OP_PUSHNUM_5 OP_PUSHNUM_4 OP_PUSHNUM_3 OP_PUSHNUM_2 OP_PUSHNUM_1 OP_0 OP_PUSHNUM_15 OP_PUSHNUM_14 OP_PUSHNUM_13 OP_PUSHNUM_12 OP_PUSHNUM_11 OP_PUSHNUM_10 OP_PUSHNUM_9 OP_PUSHNUM_8 OP_PUSHNUM_7 OP_PUSHNUM_6 OP_PUSHNUM_5 OP_PUSHNUM_4 OP_PUSHNUM_3 OP_PUSHNUM_2 OP_PUSHNUM_1 OP_0 OP_PUSHNUM_15 OP_PUSHNUM_14 OP_PUSHNUM_13 OP_PUSHNUM_12 OP_PUSHNUM_11 OP_PUSHNUM_10 OP_PUSHNUM_9 OP_PUSHNUM_8 OP_PUSHNUM_7 OP_PUSHNUM_6 OP_PUSHNUM_5 OP_PUSHNUM_4 OP_PUSHNUM_3 OP_PUSHNUM_2 OP_PUSHNUM_1 OP_0 OP_PUSHNUM_15 OP_PUSHNUM_14 OP_PUSHNUM_13 OP_PUSHNUM_12 OP_PUSHNUM_11 OP_PUSHNUM_10 OP_PUSHNUM_9 OP_PUSHNUM_8 OP_PUSHNUM_7 OP_PUSHNUM_6 OP_PUSHNUM_5 OP_PUSHNUM_4 OP_PUSHNUM_3 OP_PUSHNUM_2 OP_PUSHNUM_1 OP_0 OP_PUSHNUM_15 OP_PUSHNUM_14 OP_PUSHNUM_13 OP_PUSHNUM_12 OP_PUSHNUM_11 OP_PUSHNUM_10 OP_PUSHNUM_9 OP_PUSHNUM_8 OP_PUSHNUM_7 OP_PUSHNUM_6 OP_PUSHNUM_5 OP_PUSHNUM_4 OP_PUSHNUM_3 OP_PUSHNUM_2 OP_PUSHNUM_1 OP_0 OP_PUSHNUM_7 OP_PUSHNUM_7 OP_PUSHNUM_7 OP_PUSHNUM_7 OP_PUSHNUM_7 OP_PUSHNUM_7 OP_PUSHNUM_7 OP_PUSHNUM_7 OP_PUSHNUM_7 OP_PUSHNUM_7 OP_PUSHNUM_7 OP_PUSHNUM_7 OP_PUSHNUM_7 OP_PUSHNUM_7 OP_PUSHNUM_7 OP_PUSHNUM_7 OP_PUSHNUM_6 OP_PUSHNUM_6 OP_PUSHNUM_6 OP_PUSHNUM_6 OP_PUSHNUM_6 OP_PUSHNUM_6 OP_PUSHNUM_6 OP_PUSHNUM_6 OP_PUSHNUM_6 OP_PUSHNUM_6 OP_PUSHNUM_6 OP_PUSHNUM_6 OP_PUSHNUM_6 OP_PUSHNUM_6 OP_PUSHNUM_6 OP_PUSHNUM_6 OP_PUSHNUM_5 OP_PUSHNUM_5 OP_PUSHNUM_5 OP_PUSHNUM_5 OP_PUSHNUM_5 OP_PUSHNUM_5 OP_PUSHNUM_5 OP_PUSHNUM_5 OP_PUSHNUM_5 OP_PUSHNUM_5 OP_PUSHNUM_5 OP_PUSHNUM_5 OP_PUSHNUM_5 OP_PUSHNUM_5 OP_PUSHNUM_5 OP_PUSHNUM_5 OP_PUSHNUM_4 OP_PUSHNUM_4 OP_PUSHNUM_4 OP_PUSHNUM_4 OP_PUSHNUM_4 OP_PUSHNUM_4 OP_PUSHNUM_4 OP_PUSHNUM_4 OP_PUSHNUM_4 OP_PUSHNUM_4 OP_PUSHNUM_4 OP_PUSHNUM_4 OP_PUSHNUM_4 OP_PUSHNUM_4 OP_PUSHNUM_4 OP_PUSHNUM_4 OP_PUSHNUM_3 OP_PUSHNUM_3 OP_PUSHNUM_3 OP_PUSHNUM_3 OP_PUSHNUM_3 OP_PUSHNUM_3 OP_PUSHNUM_3 OP_PUSHNUM_3 OP_PUSHNUM_3 OP_PUSHNUM_3 OP_PUSHNUM_3 OP_PUSHNUM_3 OP_PUSHNUM_3 OP_PUSHNUM_3 OP_PUSHNUM_3 OP_PUSHNUM_3 OP_PUSHNUM_2 OP_PUSHNUM_2 OP_PUSHNUM_2 OP_PUSHNUM_2 OP_PUSHNUM_2 OP_PUSHNUM_2 OP_PUSHNUM_2 OP_PUSHNUM_2 OP_PUSHNUM_2 OP_PUSHNUM_2 OP_PUSHNUM_2 OP_PUSHNUM_2 OP_PUSHNUM_2 OP_PUSHNUM_2 OP_PUSHNUM_2 OP_PUSHNUM_2 OP_PUSHNUM_1 OP_PUSHNUM_1 OP_PUSHNUM_1 OP_PUSHNUM_1 OP_PUSHNUM_1 OP_PUSHNUM_1 OP_PUSHNUM_1 OP_PUSHNUM_1 OP_PUSHNUM_1 OP_PUSHNUM_1 OP_PUSHNUM_1 OP_PUSHNUM_1 OP_PUSHNUM_1 OP_PUSHNUM_1 OP_PUSHNUM_1 OP_PUSHNUM_1 OP_0 OP_0 OP_0 OP_0 OP_0 OP_0 OP_0 OP_0 OP_0 OP_0 OP_0 OP_0 OP_0 OP_0 OP_0 OP_0 OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_DUP OP_PUSHBYTES_2 8f00 OP_ADD OP_PICK OP_TOALTSTACK OP_PUSHNUM_14 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 8e00 OP_ADD OP_PICK OP_TOALTSTACK OP_PUSHNUM_13 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 8d00 OP_ADD OP_PICK OP_TOALTSTACK OP_PUSHNUM_12 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 8c00 OP_ADD OP_PICK OP_TOALTSTACK OP_PUSHNUM_11 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 8b00 OP_ADD OP_PICK OP_TOALTSTACK OP_PUSHNUM_10 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 8a00 OP_ADD OP_PICK OP_TOALTSTACK OP_PUSHNUM_9 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 8900 OP_ADD OP_PICK OP_TOALTSTACK OP_PUSHNUM_8 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 8800 OP_ADD OP_PICK OP_TOALTSTACK OP_PUSHNUM_7 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 8700 OP_ADD OP_PICK OP_TOALTSTACK OP_PUSHNUM_6 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 8600 OP_ADD OP_PICK OP_TOALTSTACK OP_PUSHNUM_5 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 8500 OP_ADD OP_PICK OP_TOALTSTACK OP_PUSHNUM_4 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 8400 OP_ADD OP_PICK OP_TOALTSTACK OP_PUSHNUM_3 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 8300 OP_ADD OP_PICK OP_TOALTSTACK OP_PUSHNUM_2 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 8200 OP_ADD OP_PICK OP_TOALTSTACK OP_PUSHNUM_1 OP_ADD OP_PICK OP_ADD OP_PUSHBYTES_2 8000 OP_ADD OP_PICK OP_TOALTSTACK OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_0 OP_0 OP_0 OP_0 OP_0 OP_0 OP_0 OP_PUSHNUM_1 OP_PUSHNUM_8 OP_ROLL OP_EQUALVERIFY OP_PUSHNUM_7 OP_ROLL OP_EQUALVERIFY OP_PUSHNUM_6 OP_ROLL OP_EQUALVERIFY OP_PUSHNUM_5 OP_ROLL OP_EQUALVERIFY OP_PUSHNUM_4 OP_ROLL OP_EQUALVERIFY OP_PUSHNUM_3 OP_ROLL OP_EQUALVERIFY OP_PUSHNUM_2 OP_ROLL OP_EQUALVERIFY OP_PUSHNUM_1 OP_ROLL OP_EQUALVERIFY OP_PUSHNUM_15 OP_PUSHNUM_15 OP_PUSHNUM_15 OP_PUSHNUM_15 OP_PUSHNUM_15 OP_PUSHNUM_15 OP_PUSHNUM_15 OP_PUSHNUM_14 OP_PUSHNUM_8 OP_ROLL OP_EQUALVERIFY OP_PUSHNUM_7 OP_ROLL OP_EQUALVERIFY OP_PUSHNUM_6 OP_ROLL OP_EQUALVERIFY OP_PUSHNUM_5 OP_ROLL OP_EQUALVERIFY OP_PUSHNUM_4 OP_ROLL OP_EQUALVERIFY OP_PUSHNUM_3 OP_ROLL OP_EQUALVERIFY OP_PUSHNUM_2 OP_ROLL OP_EQUALVERIFY OP_PUSHNUM_1 OP_ROLL OP_EQUALVERIFY OP_PUSHNUM_1
Bitwise Operations
The Bitwise operations were also removed with OP_CAT. Even if Big Script never communicates with Small Script, having back all the removed bitwise operations such as (OP_AND / OP_OR / OP_XOR / OP_RSHIFT / OP_LSHIFT) would reduce approximately 32X the size of the SHA-256 or BLAKE2 computation scripts. Currently, the best implementation of SHA-256/BLAKE3 (done by Fairgate) operates in nibbles, and consumes several opcodes per nibble for simple logic operation such as AND. The bitwise opcodes coming back would allow a single instruction to operate over 32-bit numbers. This would result in a reduction of about 40 Kbytes in the protocol’s worst case onchain data cost (assuming BLAKE2 is used).
The following code performs an AND operation between two 32-bit operands. It takes up 422 script bytes. The same could be accomplished in a single OP_AND instruction.
OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_DUP OP_PUSHBYTES_2 8f00 OP_ADD OP_PICK OP_TOALTSTACK OP_PUSHNUM_14 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 8e00 OP_ADD OP_PICK OP_TOALTSTACK OP_PUSHNUM_13 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 8d00 OP_ADD OP_PICK OP_TOALTSTACK OP_PUSHNUM_12 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 8c00 OP_ADD OP_PICK OP_TOALTSTACK OP_PUSHNUM_11 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 8b00 OP_ADD OP_PICK OP_TOALTSTACK OP_PUSHNUM_10 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 8a00 OP_ADD OP_PICK OP_TOALTSTACK OP_PUSHNUM_9 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 8900 OP_ADD OP_PICK OP_TOALTSTACK OP_PUSHNUM_8 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 8800 OP_ADD OP_PICK OP_TOALTSTACK OP_PUSHNUM_7 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 8700 OP_ADD OP_PICK OP_TOALTSTACK OP_PUSHNUM_6 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 8600 OP_ADD OP_PICK OP_TOALTSTACK OP_PUSHNUM_5 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 8500 OP_ADD OP_PICK OP_TOALTSTACK OP_PUSHNUM_4 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 8400 OP_ADD OP_PICK OP_TOALTSTACK OP_PUSHNUM_3 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 8300 OP_ADD OP_PICK OP_TOALTSTACK OP_PUSHNUM_2 OP_ADD OP_PICK OP_ADD OP_DUP OP_PUSHBYTES_2 8200 OP_ADD OP_PICK OP_TOALTSTACK OP_PUSHNUM_1 OP_ADD OP_PICK OP_ADD OP_PUSHBYTES_2 8000 OP_ADD OP_PICK OP_TOALTSTACK OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_0 OP_0 OP_0 OP_0 OP_0 OP_0 OP_0 OP_PUSHNUM_1 OP_PUSHNUM_8 OP_ROLL OP_EQUALVERIFY OP_PUSHNUM_7 OP_ROLL OP_EQUALVERIFY OP_PUSHNUM_6 OP_ROLL OP_EQUALVERIFY OP_PUSHNUM_5 OP_ROLL OP_EQUALVERIFY OP_PUSHNUM_4 OP_ROLL OP_EQUALVERIFY OP_PUSHNUM_3 OP_ROLL OP_EQUALVERIFY OP_PUSHNUM_2 OP_ROLL OP_EQUALVERIFY OP_PUSHNUM_1 OP_ROLL OP_EQUALVERIFY OP_PUSHNUM_15 OP_PUSHNUM_15 OP_PUSHNUM_15 OP_PUSHNUM_15 OP_PUSHNUM_15 OP_PUSHNUM_15 OP_PUSHNUM_15 OP_PUSHNUM_14 OP_PUSHNUM_8 OP_ROLL OP_EQUALVERIFY OP_PUSHNUM_7 OP_ROLL OP_EQUALVERIFY OP_PUSHNUM_6 OP_ROLL OP_EQUALVERIFY OP_PUSHNUM_5 OP_ROLL OP_EQUALVERIFY OP_PUSHNUM_4 OP_ROLL OP_EQUALVERIFY OP_PUSHNUM_3 OP_ROLL OP_EQUALVERIFY OP_PUSHNUM_2 OP_ROLL OP_EQUALVERIFY OP_PUSHNUM_1 OP_ROLL OP_EQUALVERIFY OP_PUSHNUM_1
Checking Arbitrary Signatures
The versatility of verifying Schnorr signatures for arbitrary messages that OP_CHECKSIGFROMSTACK (CSFS) provides can have numerous benefits for all BitVM-like protocols.
First, CSFS allows the parties to sign their inputs to the protocol without involving expensive Winternitz signatures, nor those inputs require co-signing or equivocation-proving. Since publishing Winternitz signed data is the main onchain cost of BitVMX, using CSFS would represent a drop of the worst case protocol cost to about 28% of the SOTA protocol cost, and still removing one protocol round. This efficiency gain can be combined with those provided by the removal of the SHA-256 code in Small Script if we had OP_CAT, reducing the overall cost to 2% of the current cost! This implies that a worst case dispute could require each party to post onchain no more than 4 Kbytes, the space used by only 16 average transactions.
Additionally, if we eliminate one-time signatures from the protocol, then there is a lot less precomputation and data exchange. In the SOTA protocol, for every peg-in, all potential operators must send each other about 35 Kbytes
of Winternitz public keys. If there are 20 operators, each party must send half a megabyte of data. With CSFS, the amount of data exchanged is negligible.
The following code verifies the signature of a 4-bit value. It takes up 376 script bytes. The same could be accomplished by pushing the data, public key and signature into the stack and executing a single OP_CHECKSIGFROMSTACK opcode, and the public key could be re-used for other signatures.
OP_PUSHBYTES_32 c6047f9441ed7d6d3045406e95c07cd85a6a6d4c90d35b8c6a568f07cfd511fd OP_CHECKSIGVERIFY OP_FROMALTSTACK OP_DUP OP_NEGATE OP_FROMALTSTACK OP_TUCK OP_SUB OP_FROMALTSTACK OP_TUCK OP_SUB OP_FROMALTSTACK OP_TUCK OP_SUB OP_FROMALTSTACK OP_TUCK OP_SUB OP_FROMALTSTACK OP_TUCK OP_SUB OP_FROMALTSTACK OP_TUCK OP_SUB OP_FROMALTSTACK OP_TUCK OP_SUB OP_FROMALTSTACK OP_TUCK OP_SUB OP_FROMALTSTACK OP_TUCK OP_SUB OP_PUSHBYTES_2 9600 OP_ADD OP_FROMALTSTACK OP_DUP OP_ADD OP_DUP OP_ADD OP_DUP OP_ADD OP_DUP OP_ADD OP_FROMALTSTACK OP_ADD OP_EQUALVERIFY OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_PUSHNUM_1
Checking Arbitrary Signatures + String Operations
Combining OP_CHECKSIGFROMSTACK and string operations it is possible to compress the midstates. Instead of signing each midstate separately (using 65 bytes to sign a 20-byte hash) a party can sign all midstates together as a single message. With OP_CAT, at any later time the script can verify that any single midstate belongs to the message by concatenating a given prefix, the midstate and a given postfix, and then checking against the signature. In the SOTA BitVMX presented, we pack 31 midstates in each transaction, consuming 2.6K vbytes in each transaction. Using OP_CAT+CSFS each transaction would only consume 685 bytes.
Currently, this combination is the most cost effective: 11 Kbytes of onchain data per dispute for a 5.5 round protocol, and 36 Kbytes for a 4.5 round protocol.
Signatures Excluding UTXO Hash
Several new sighash flags have been proposed to allow signing an input of a transaction T without signing which output it should connect to. Instead, the input of T can be connected to any transaction output whose scriptSig can
be satisfied by the input witness. Two of these opcodes are SIGHASH_ANYPREVOUT (APO) and SIGHASH_NOINPUT.
One of the characteristics of bridges involving a committee of operators is that if any of them misbehaves, his security bond is forfeit and he must be disallowed from participating in any other future protocol dispute. The Union bridge solves this problem by forcing operators to consume one unique enablement output each time they wish to participate.
If an operator participates in a thousand peg-ins, then each one has its own enablement output. All enablement outputs are part of a master enablement transaction. If an operator misbehaves in one peg-out, then all enablement
outputs must be burned at once. This is done by all operators pre-signing a long list of disablement transactions, one for each enablement output. A single master disablement transaction (or directory) connects to all disablement
transactions, so it can trigger all disablement with the publication of a single transaction. However, for every peg-in there is a new need for a master disablement transaction, and all the dependent disablement txs. for each of
the operators. Abstractly, we have two sets of large DAGS of transactions, and we need to connect each one of the first set with each of the second set. The following diagram depicts only 2 master disablement transactions. The
number of transactions that needs to be created for each operator is 2N, where N is the number of peg-in slots.

Several copies of the Master disablement transaction and its dependencies must exist in the BitVMX transaction DAG, one for each disablement endpoint.
By using SIGHASH_ANYPREVOUT it is possible to connect a single master disablement transaction with all the disablement endpoints, saving setup time and protocol complexity from N^2 down to N. The following diagram depicts how a single master disablement transaction can be triggered by different disablement endpoints.

Reusing the Master Disablement part of the BitVMX Transaction DAG. The same master transaction can be connected to several endpoints.
Also, the Union bridge protocol uses N^2 dispute channels for N operators. These channels are connected on dispute to the disputed peg-in slot. This dynamic connection is complex. By using APO, it is possible to directly connect a dispute channel with the desired peg-in slot dynamically just by matching a signature with a public key.
OPCODE / ADDITION | Main Advantages | Red |
OP_TXHASH / OP_CAT´ | No need to emulate covenants. Reduced setup complexity and bandwidth usage. Any user can create a peg-in address. | – |
OP_CAT / OP_SUBSTR | No need to implement a hash function in script. Reduced signature verification script size. | 45 | OP_MUL | Reduced the size of RISC-V opcode verification. | 5 |
OP_AND / OP_OR / OP_XOR / OP_RSHIFT / OP_LSHIFT | Reduce the size of SHA-256 computation in script. | 40 |
OP_CSFS | No need to use Winternitz signatures. Use Schnorr instead. | 157 |
OP_CAT + OP_CSFS | No need to sign individual midstates: compound signing. No need to implement hash function in script. | 238 |
SIGHASH_ANYPREVOUT | Reduced setup time and bandwidth consumption. | — |
“Red.” refers to Cost Reduction expressed in onchain virtual kilobytes. All values are estimates.
Summary
BitVMX is a platform to optimistically verify smart-contracts on Bitcoin. It performs a partition search on the execution trace to identify the disputed step and only checks this step onchain. The searching and checking processes consume several hundred kilobytes of witness data. Several Bitcoin upgrades are being discussed nowadays, to add covenants, arbitrary message signature checking, string concatenation, bitwise operations, arithmetic operations, and more flexible input/output connections. All of these additions make BitVMX more efficient and more valuable. Since upgrading Bitcoin is a process that may take several years, we’ll have plenty of time to upgrade BitVMX to support the new Bitcoin features. Meanwhile, we at BitVMX FORCE keep building BitVMX with the assumption that Bitcoin has ossified, and with the peace of mind that the current functionality is good enough for BitVMX to be relatively efficient and cost effective.