1

The locking script I have is

OP_PUSH1(0x03) OP_ADD OP_PUSH1(0x05) OP_NUMEQUALVERIFY

I don't understand how the OP_PUSH works - where does it push from and does it push it onto the top of the stack? I thought script operations read from the top of the stack so I'd read the top item and push it back onto the stack which does nothing?

What would I have to put as an unlocking script on the left to get OP_NUMEQUALVERIFY to return valid here?

2 Answers 2

1
  1. For pushing numbers between 1-16, you should be using OP_1-OP_16.

  2. For pushing numbers larger than 16, you should be using OP_PUSH(OP_N/A).

E.g:

<5> push compiles to OP_5: 0x55

<17> push compiles to OP_PUSH1(0x11): 0x0111

<666> push compiles to OP_PUSH2(0x9a02): 0x029a02

  1. OP_ADD pops two inputs and adds them together. So your ordering is wrong because OP_ADD must come after 3 and 5.

  2. Stack must end with “1” so you should be using OP_NUMEQUAL instead of OP_NUMEQUALVERIFY, which leaves the stack with 1 instead of empty.

Your final script should be:

OP_3 OP_5 OP_ADD OP_EQUAL

And your unlocking script should be: OP_8

You can test it online at: https://ide.scriptwiz.app/

3
  • Why note just OP_2 then? That's the unlocking script that adds to 3 to equal 5
    – Jimbo
    Sep 10, 2021 at 17:13
  • OP_ADD pops the two previous items which are 3 and 5. Then adds them together, resulting 8 and therefore leaving the stack with 8 8 OP_EQUAL. Finally OP_EQUAL pops the two previous items which are 8 and 8, then compares them.
    – Burak
    Sep 12, 2021 at 21:33
  • The script in the question looks like "3 ADD 5 NUMEQUALVERIFY" which would be solved by a witness of "1 2" -- so "ADD" sees "1 2 3" on the stack and replaces the top two leaving "1 5", NUMEQUALVERIFY sees "1 5 5" and removes the top two and doesn't abort since they're equal, and finally just "1" is on the stack which is success. Aug 10, 2022 at 2:50
0

I don't understand how the OP_PUSH works - where does it push from and does it push it onto the top of the stack? I thought script operations read from the top of the stack so I'd read the top item and push it back onto the stack which does nothing?

As I understand it, the script is separate from the stack. The script is read left to right and it's instructions operate on the stack.

So you start with your program pointer at far left of script and with an empty stack.

Then script instructions 0100 (OP_PUSH1 0x00) would push the value 0x00 from the script onto the top of the stack. The stack would then contain 0x00 and the program pointer would point to the right of the 0x00 in the script.


As Buruk pointed out, your script is incorrect and wouldn't function as you intend.

I believe you need a locking script

010301059387

which is

OP_PUSH1 0x03 OP_PUSH1 0x05 OP_ADD OP_EQUAL

with an unlocking script of

0108

which is

OP-PUSH1 0x08

or implicitly

 0108 ...  010301059387


 OP-PUSH1 0x08   ...  OP_PUSH1 0x03 OP_PUSH1 0x05 OP_ADD OP_EQUAL

which we can work through step by step thus:

script interpretation of highlighted opcode stack after opcode executed
0108010301059387 OP_PUSH1 0x08 08
0108010301059387 OP_PUSH1 0x03 03 08
0108010301059387 OP_PUSH1 0x05 05 03 08
0108010301059387 OP_ADD 08 08
0108010301059387 OP_EQUAL TRUE

where

It doesn't matter whether you consider opcodes as acting on the top of a stack, bottom of a stack, left of a stack, right of a stack, front of a stack or back of a stack -- so long as all opcodes are consistent in which end they act on. A stack is simply any one-dimensional ordering of items with an arbitrarily chosen direction. Some languages/libraries might have opcodes/methods/instructions that act on the non-normal end -- you just have to know whether an opcode acts on the normal end or the other end, you could describe those ends as "near" and "far" or any other way you like.

It's just easier to imagine operating on a stack of sheets of paper, on a supporting surface in a gravitational field, where it is physically more convenient to add or remove items from the top than to extract or slide-in items at the bottom. These physical considerations have no meaning in computer operations but we should use words that are consistent with the analogy that is implicit in borrowing the word "stack" from everyday English.


Note that

  • OP_EQUAL is a bitwise operator that removes two one-byte operands from the stack
  • OP_NUMEQUAL is an arithmetic operator that removes two bigint operands from the stack. Bigints are longer than one byte. I believe each Bigint is 32 bytes (256 bits) on the stack.
  • OP_NUMEQUALVERIFY is OP_NUMEQUAL, OP_VERIFY
  • OP_ADD is listed as an arithmetic operator (not a bitwise operator) which implies it needs two bigint operands on the stack, not two byte values. However it seems to work with byte operands.

See https://siminchen.github.io/bitcoinIDE/build/editor.html

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.