Bitcoin Script: The simple stack-based language easy explained!

Follow and share now!

Bitcoin contains a script language for allow very flexible ways to give access to transferred money. The name of this language is just Bitcoin Script. Please read this article to learn all about:

Purpose of Script:

The two byte structures Txin and Txout, part of Transactions, contain both a field, containing the to bytes assembled script. When a Txin refer a Txout to send the money to another Txout, the script of the input and the output become executed in one rush, so it shares the same memory. The Txout ask usual for some arguments, the Txin pushes these. In a classical Bitcoin Transaction needs the Txin to push the public key of the Bitcoin P2PKH address of the recipient, what is just a hash by the algorithms SHA-256 and RIPEMD-160 and a signature to proof, you own the private key.

OP_ in instruction names:

The Bitcoin Script mnemonic are usual written with the prefix OP_, for example OP_VERIFY. This is a usual schema to sort constant names, but most the times just redundant. It doesn’t matters, so most systems support them with and without OP_. Humans understand both too for obvious reasons.

How Bitcoin Script instructions get executed:

Bitcoin Script instruction Bytes, the opcodes, are RISC-like just one Byte long but may have appended argument Bytes. Such arguments are called immediate. It is a load-store-architecture, so there are instructions that just load data into the internal memory and others that just modify them, while for example the x86 platform allow each kind of source and destination storage, as long at most one of them was a memory address. Load-storage-architectures generates more but faster executed instructions, since data are just modification in the fast internal storage. The Bitcoin Script uses as storage just two Stacks. One is called the main stack, the other one is the alt(ernative) stack. There are just two instruction to access the alt stack, OP_TOALTSTACK and OP_FROMALTSTACK, so if anybody talks about the Script stack, it always means the main stack.

Bitcoin Script weak typing:

Bitcoin Script uses weak typing, what means, a value can be convert to different types by different methods automatically, while a value in languages with strong typing keeps always the same, until it is explicitly converted by the program. The general three types in Script are Byte arrays, numbers and boolean values. These three types can be converted in this order from left to right, so a Byte array can converted into a number without lost, a number to a Byte array is only possible by guessing. User should keep this especially by working with negative numbers in the mind, the both Byte arrays 0b1111 1111 and 0b1111 1111 1111 1111 are differently, but representing both the numeric value -1 in two complement. So OP_EQUAL would return a FALSE since they doesn’t match bytewise, OP_NUMEQUAL would return TRUE. The language contains if/else statements, but no loops, so it expect a boolean values, what is either TRUE or FALSE. Basically are all FALSE pushed as the number zero and all TRUE pushed as one, but on read evaluates all except zero to TRUE. OP_0NOTEQUAL is the preferred way to convert the implicated boolean values to their default push values.

Bitcoin basic payment validation:

You can be very creative at creating output transactions to give others or maybe yourself access to the coins of your transaction, but it make sense to use a transaction as simple as possible. One of the advantages is, Bitcoin is bound to software and it is hard for software to figure out if you have access to the Transaction, when they don’t follow a known scheme.

Pay-to-pubkey-hash payment method:

Pay-to-pubkey-hash (P2PKH) is the default method to send money to an Bitcoin address. Such an address is just the hash of a public key. That is good for the usability, since an address has always the same short length, but the Txout needs two checks. The Txin must provide the public key of the address and a signature. The signature is a by the private key encrypted hash of the Txout, the Output Transaction tests the hash of the public key for being the address of the recipient and the signature to be the valid hash when try to decrypt by this public key.

Txin source code: <push signature> <push public key>
Txout source code: OP_DUP OP_HASH160 <push recipient public key> OP_EQUALVERIFY OP_CHECKSIG

Current InstructionRemaining InstructionsStack beforeStack afterNote
<push signature><push public key> OP_DUP OP_HASH160 <push recipient public key hash> OP_EQUALVERIFY OP_CHECKSIG<signature>
<push public key>OP_DUP OP_HASH160 <push recipient public key hash> OP_EQUALVERIFY OP_CHECKSIG<signature><signature>
<public key>
OP_DUPOP_HASH160 <push recipient public key hash> OP_EQUALVERIFY OP_CHECKSIG<signature>
<public key>
<signature>
<public key>
<public key>

Duplicate the next element on stack.

OP_HASH160<push recipient public key hash> OP_EQUALVERIFY OP_CHECKSIG<signature>
<public key>
<public key>
<signature>
<public key>
<hash of public key>

Hash the next element on stack by SHA-256, followed by RIPEMD-160.

<push recipient public key hash>OP_EQUALVERIFY OP_CHECKSIG<signature>
<public key>
<hash of public key>
<signature>
<public key>
<hash of public key>
<recipient public key hash>
OP_EQUALVERIFYOP_CHECKSIG<signature>
<public key>
<hash of public key>
<recipient public key hash>
<signature>
<public key>

Marks the transaction as invalid, if the next both elements on stack don't match.
So makes sure, the by the Txin pushed public key has the right hash.

OP_CHECKSIG<signature>
<public key>
TRUE/FALSE

The Transaction is only valid, if the stack contains true after execution.

Instructions:

Legend: Push immediate/implicit Control Arithmetic/Logical/Stack manipulation Branch Crypto No operation/Reserved Disabled/Removed

 x0x1x2x3x4x5x6x7
0xOP_0/OP_FALSE<P. 1 B.><P. 2 B.><P. 3 B.><P. 4 B.><P. 5 B.><P. 6 B.><P. 7 B.>
1x<P. 16 B.><P. 17 B.><P. 18 B.><P. 19 B.><P. 20 B.><P. 21 B.><P. 22 B.><P. 23 B.>
2x<P. 32 B.><P. 33 B.><P. 34 B.><P. 35 B.><P. 36 B.><P. 37 B.><P. 38 B.><P. 39 B.>
3x<P. 48 B.><P. 49 B.><P. 50 B.><P. 51 B.><P. 52 B.><P. 53 B.><P. 54 B.><P. 55 B.>
4x<P. 64 B.><P. 65 B.><P. 66 B.><P. 67 B.><P. 68 B.><P. 69 B.><P. 70 B.><P. 71 B.>
5xOP_RESERVEDOP_1/OP_TRUEOP_2OP_3OP_4OP_5OP_6OP_7
6xOP_16OP_NOPOP_VEROP_IFOP_NOTIFOP_VERIFOP_VERNOTIFOP_ELSE
7xOP_2OVEROP_2ROTOP_2SWAPOP_IFDUPOP_DEPTHOP_DROPOP_DUPOP_NIP
8xOP_LEFTOP_RIGHTOP_SIZEOP_INVERTOP_ANDOP_OROP_XOROP_EQUAL
9xOP_ABSOP_NOTOP_0NOTEQUALOP_ADDOP_SUBOP_MULOP_DIVOP_MOD
AxOP_GREATERTHANOP_LESSTHANOREQUALOP_GREATERTHANOREQUALOP_MINOP_MAXOP_WITHINOP_RIPEMD160OP_SHA1
BxOP_CHECKLOCKTIMEVERIFYOP_CHECKSEQUENCEVERIFY
Cx
Dx
Ex
Fx
 x8x9xAxBxCxDxExF
0x<P. 8 B.><P. 9 B.><P. 10 B.><P. 11 B.><P. 12 B.><P. 13 B.><P. 14 B.><P. 15 B.>
1x<P. 24 B.><P. 25 B.><P. 26 B.><P. 27 B.><P. 28 B.><P. 29 B.><P. 30 B.><P. 31 B.>
2x<P. 40 B.><P. 41 B.><P. 42 B.><P. 43 B.><P. 44 B.><P. 45 B.><P. 46 B.><P. 47 B.>
3x<P. 56 B.><P. 57 B.><P. 58 B.><P. 59 B.><P. 60 B.><P. 61 B.><P. 62 B.><P. 63 B.>
4x<P. 72 B.><P. 73 B.><P. 74 B.><P. 75 B.>OP_PUSHDATA1OP_PUSHDATA2OP_PUSHDATA4OP_1NEGATE
5xOP_8OP_9OP_10OP_11OP_12OP_13OP_14OP_15
6xOP_ENDIFOP_VERIFYOP_RETURNOP_TOALTSTACKOP_FROMALTSTACKOP_2DROPOP_2DUPOP_3DUP
7xOP_OVEROP_PICKOP_ROLLOP_ROTOP_SWAPOP_TUCKOP_CATOP_SUBSTR
8xOP_EQUALVERIFYOP_RESERVED1OP_RESERVED2OP_1ADDOP_1SUBOP_2MULOP_2DIVOP_NEGATE
9xOP_LSHIFTOP_RSHIFTOP_BOOLANDOP_BOOLOROP_NUMEQUALOP_NUMEQUALVERIFYOP_NUMNOTEQUALOP_LESSTHAN
AxOP_SHA256OP_HASH160OP_HASH256OP_CODESEPARATOROP_CHECKSIGOP_CHECKSIGVERIFYOP_CHECKMULTISIGOP_CHECKMULTISIGVERIFY
Bx
Cx
Dx
Ex
FxOP_PUBKEYHASHOP_PUBKEYOP_INVALIDOPCODE

Please click on the anchor links in the table above and the instruction description to navigate through the instructions.

OP_0/OP_FALSE:

OPCode: 0x00

Stack before:

...
<Pointer>

Stack after:

...
0x00
<Pointer>

Description:

The instruction 0x00 with the both mnemonics OP_0 and OP_FALSE pushes the number 0 onto stack, which is the same as the boolean value FALSE.

Push # Bytes:

OPCode: 0x01 – 0x4b

Stack before:

...
<Pointer>

Stack after:

...
The next # Bytes.
<Pointer>

Description:

The instructions 0x01 – 0x4b (decimal 1 to 75) push so many immediately following Bytes as one value onto stack, as the number of the instruction is. So 0x01 pushes the next Byte, 0x02 pushes the next two Bytes and so on. The immediate Bytes are Big Endian sorted, as shown in the example at the end of this paragraph. These instructions have no typical mnemonics, because the source codes usual doesn’t contain push instructions for values up to 75 Bytes, just the values to push. The assembler transfers them in the right instruction. There are some instructions, pushing a constant. Since they push an implicated value, they use just a single Byte what saves space and time:

The following instructions are for pushing a value of more than 75 Byte, it is virtually possible to push values up to four Gigabyte:

Example:

Source code: 0x123456

Binary:

   ┌───────────────── Instruction to push three Byte (0x03)
   │
   │         ┌─────── 3 Byte long argument (0x123456)
   │         │
|  ^ |       ^      |
|0x03|0x12 0x34 0x56|

Result:

The stack contains after execution 0x123456 as Big Endian, which evaluates to numeric decimal 1.193.046.

OP_PUSHDATA1:

OPCode: 0x4c

Stack before:

...
<Pointer>

Stack after:

...
The argument with the size in the next Byte.
<Pointer>

Description:

OP_PUSHDATA1 reads the next Byte in the program code, containing, how many Byte after this one the argument to push long is and push these Byte on stack, so it is possible to push values with up to 255 Bytes. The Byte to push are sorted Big Endian. When a value is less or equals than 75 Bytes, the general push instructions are strong recommend to use. The instructions OP_PUSHDATA2 and OP_PUSHDATA4 are for pushing even bigger values.

Example:

Source code: –

Binary:

  ┌─────────────────────── OP_PUSHDATA1 opcode (0x4c)
  │
  │     ┌───────────────── Len of the argument (0x03)
  │     │
  │     │         ┌─────── Argument to push in Big Endian (0x000004)
  │     │         │
| ^ |   ^ |       ^      |
|0x4c|0x03|0x00 0x00 0x04|

Result:

The stack contains after execution 0x000004 as Big Endian, which evaluates to numeric 4.

OP_PUSHDATA2:

OPCode: 0x4d

Stack before:

...
<Pointer>

Stack after:

...
The argument with the size in the next two Bytes.
<Pointer>

Description:

OP_PUSHDATA2 reads the next two Bytes from program code, containing, how many Bytes the argument long is, and push these Bytes, starting after these two bytes, as one value onto stack, so it is possible to push values with up to 65535 Bytes. The Bytes to push are sorted Big Endian, but the Byte of the count are sorted Little Endian! When the value to push is shorter than 256 Bytes, OP_PUSHDATA1 is a better choice, when the value is less or equals than 75 Bytes, the general push instructions are still better. The instruction OP_PUSHDATA4 can push even bigger data.

Example:

Source code: –

Binary:

   ┌─────────────────────────── OP_PUSHDATA2 opcode (0x4d)
   │
   │      ┌──────────────────── Len of the argument in Little Endian (0x0003)
   │      │
   │      │            ┌─────── Argument to push in Big Endian (0x000004)
|  ^      ^    |       ^      |
|0x4d|0x03 0x00|0x00 0x00 0x04|

Result:

The stack contains after execution 0x000004 as Big Endian, which evaluates to numeric 4.

OP_PUSHDATA4:

OPCode: 0x4e

Stack before:

...
<Pointer>

Stack after:

...
The argument with the size in the next four Bytes
<Pointer>

Description:

OP_PUSHDATA4 reads the next four Byte of the program code, containing, how many Byte after these the argument long is and push these Byte on stack, so it is virtually possible to push values with up to 4.294.967.295 Bytes, hence 4 GiB minus one Byte. The Byte to push are sorted Big Endian, but the Byte of the count are sorted Little Endian! When the value to push is shorter than 76 Byte, the general push instructions are strong recommended, if the value is shorter than 256 Byte, OP_PUSHDATA1 and if it is shorter than 65536 Byte OP_PUSHDATA2.

Example:

Source code: –

Binary:

  ┌────────────────────────────────────── OP_PUSHDATA4 opcode. (0x4e)
  │
  │            ┌───────────────────────── Len of the argument in Little Endian. (0x00000003)
  │            │
  │            │                 ┌─────── Argument to push in Big Endian (0x000004) 
  │            │                 │
| ^  |         ^         |       ^      |
|0x4e|0x03 0x00 0x00 0x00|0x00 0x00 0x04|

Result:

The stack contains after execution 0x000004 as Big Endian, which evaluates to numeric 4.

OP_1NEGATE:

OPCode: 0x4f

Stack before:

...
<Pointer>

Stack after:

...
-1
<Pointer>

Description:

OP_1NEGATE pushes a numerical minus one onto stack.

Example:

Source code: 0x00 0x01 OP_1NEGATE OP_ADD OP_NUMEQUAL

Binary: 0x00 0x51 0x4f 0x93 0x9c

OP_RESERVED:

OPCode: 0x50

Stack before:

...
<Pointer>

Stack after:

...
<Pointer>

Description:

A reserved Byte, marks Transaction as invalid if executed.

OP_#:

OPCodes:

0x51 - OP_1/OP_TRUE
0x52 - OP_2
0x53 - OP_3
0x54 - OP_4
0x55 - OP_5
0x56 - OP_6
0x57 - OP_7
0x58 - OP_8
0x59 - OP_9
0x5a - OP_10
0x5b - OP_11
0x5c - OP_12
0x5d - OP_13
0x5e - OP_14
0x5f - OP_15
0x60 - OP_16

Stack before:

...
<Pointer>

Stack after:

...
Instruction Byte - 0x50
<Pointer>

Description:

These 16 following instructions push the number in the name onto stack. That is always the opcode minus 0x50. It is strong recommended to use these instructions for pushing a constant from inclusive 1 to 16. Since they writes implicit values, the code becomes smaller and faster to execute. The instruction OP_0 pushes a numeric zero. OP_1 has the nickname OP_TRUE, but basically evaluate all except zero to TRUE. The instruction OP_0NOTEQUAL converting the implicated boolean values to these two numbers.

OP_NOP:

OPCode: 0x61

Stack before:

...
<Pointer>

Stack after:

...
<Pointer>

Description:

NOP is a usual processor instruction. It means no operation and does nothing.

OP_VER:

OPCode: 0x62

Stack before:

...
<Pointer>

Stack after:

...
<Pointer>

Description:

OP_VER is just a reserved Byte, the Transaction become marked as invalid, when executed.

OP_IF:

OPCode: 0x63

Stack before:

...
Condition
<Pointer>

Stack after:

...
<Pointer>

Description:

OP_IF defines the start of a block of code. This block gets may interrupted by the instruction OP_ELSE, which starts a second block. In both cases is the last block terminated by the instruction OP_ENDIF, else the Transaction become invalid. The instruction pops a value and continues executing only the if block, if the value is TRUE, else it executes the else block, if exists. In each case continues the execution after the ENDIF, if no error occurred. The instruction OP_NOTIF works similar, but execute the if block on a FALSE value, otherwise the else block, if exists.

OP_NOTIF:

OPCode: 0x64

Stack before:

...
Negated condition
<Pointer>

Stack after:

...
<Pointer>

Description:

This instruction acts like calling OP_NOT and OP_IF. It defines the start of a block, which become may interrupted by the instruction OP_ELSE. Both blocks must end with OP_ENDIF, else the Transaction become marked invalid. The instruction pops a value from stack and executes the if block, if this value is FALSE, else the else block, if exists. In each case continues the execution after the ENDIF, if no error occurred.

OP_VERIF:

OPCode: 0x65

Stack before:

...
<Pointer>

Stack after:

...
<Pointer>

Description:

A reserved Byte. The Transaction become marked as invalid, even when the interpreter read this, while skipping a code block (OP_IF/OP_NOTIF/OP_ELSE).

OP_VERNOTIF:

OPCode: 0x66

Stack before:

...
<Pointer>

Stack after:

...
<Pointer>

Description:

A reserved Byte. The Transaction become marked as invalid, even when the interpreter read this, while skipping a code block (OP_IF/OP_NOTIF/OP_ELSE).

OP_ELSE:

OPCode: 0x67

Stack before:

...
<Pointer>

Stack after:

...
<Pointer>

Description:

This instruction must occur between an OP_IF or OP_NOTIF and OP_ENDIF zero or once. If the value, the IF tested, has the expected value, the block between the IF and the ELSE is executed, else the instructions between the ELSE and the matching ENDIF. The execution continues in both cases after the ENDIF, if no error occurred.

OP_ENDIF:

OPCode: 0x68

Stack before:

...
<Pointer>

Stack after:

...
<Pointer>

Description:

OP_ENDIF terminates OP_IF/OP_NOTIF or OP_ELSE. Transactions become marked as invalid, if an ELSE is not followed by an ENDIF or an IF/NOTIF instruction is not followed by an ENDIF or an ELSE.

OP_VERIFY:

OPCode: 0x69

Stack before:

...
<Value 0>
<Pointer>

Stack after:

...
<Pointer>

Description:

OP_VERIFY pops a value from stack and marks the Transaction as invalid, if it is FALSE. That is the usual way to verify data in Txouts, there are a lot instructions to call OP_VERIFY as last step. If it is the last test in a Transaction, the call of OP_VERIFY is not need, since a Transaction is only valid, if the next element from Stack evalidate to TRUE.

OP_RETURN:

OPCode: 0x6a

Stack before:

...
<Pointer>

Stack after:

...
<Pointer>

Description:

OP_RETURN marks the Transaction as invalid. That is the usual way to append data to a Transaction. For this, a Txout with a value of zero Satoshi and a Script that fails with the OP_RETURN instruction, followed by the data, will get created.

OP_TOALTSTACK:

OPCode: 0x6b

Stack before:

...
Value to transfer
<Pointer>

Stack after:

...
<Pointer>

Description:

OP_TOALTSTACK pops an element from main stack and push them onto the altstack. The only other instruction, accessing the alternative stack is OP_FROMALTSTACK, which works in reverse way.

OP_FROMALTSTACK:

OPCode: 0x6c

Stack before:

...
<Pointer>

Stack after:

...
Transferred value
<Pointer>

Description:

OP_FROMALTSTACK pops an element from altstack and push them onto the main stack. The only other instruction, accessing the alternative stack is OP_TOALTSTACK, which works in reverse way.

OP_2DROP:

OPCode: 0x6d

Stack before:

...
<Value 2>
<Value 1>
<Value 0>
<Pointer>

Stack after:

...
<Value 2>
<Pointer>

Description:

OP_2DROP pops two elements from stack and discard them.

OP_2DUP:

OPCode: 0x6e

Stack before:

...
<Value 2>
<Value 1>
<Value 0>
<Pointer>

Stack after:

...
<Value 2>
<Value 1>
<Value 0>
<Value 1>
<Value 0>
<Pointer>

Description:

OP_2DUP duplicates a group of the next two element on stack, so the stack become appended the next two elements on the stack in the same order.

OP_3DUP:

OPCode: 0x6f

Stack before:

...
<Value 3>
<Value 2>
<Value 1>
<Value 0>
<Pointer>

Stack after:

...
<Value 3>
<Value 2>
<Value 1>
<Value 0>
<Value 2>
<Value 1>
<Value 0>
<Pointer>

Description:

OP_3DUP duplicates a group of the next three elements on stack, so the stack become appended the next three elements on the stack in the same order.

OP_2OVER:

OPCode: 0x70

Stack before:

...
<Value 4>
<Value 3> +--┐
<Value 2> +-┐|
<Value 1>   ||
<Value 0> /_|┘
<Pointer> \

Stack after:

...
<Value 4>
<Value 3>
<Value 2>
<Value 1>
<Value 0>
<Value 3>
<Value 2>
<Pointer>

Description:

OP_2OVER copies a group of the third and the fourth element on stack at it ends.

OP_2ROT:

OPCode: 0x71

Stack before:

...
<Value 6>
<Value 5> +--┐
<Value 4> +-┐|
<Value 3>   ||
<Value 2>   ||
<Value 1>   ||
<Value 0> /_|┘
<Pointer> \

Stack after:

...
<Value 6>
<Value 3>
<Value 2>
<Value 1>
<Value 0>
<Value 5>
<Value 4>
<Pointer>

Description:

OP_2ROT rotates the first six elements on stack away from pointer by two. So it moves basicaly the fifth and sixth element to the end.

OP_2SWAP:

OPCode: 0x72

Stack before:

...
<Value 4>  _________
<Value 3> |  Group 1
<Value 2> |_________ 
<Value 1> |
<Value 0> |  Group 0
<Pointer>

Stack after:

...
<Value 4>  _________
<Value 1> |  Group 0
<Value 0> |_________
<Value 3> |
<Value 2> |  Group 1
<Pointer>

Description:

OP_2SWAP swaps the position of a group of the first and the second and another one of the third and the fourth elements. The position of the elements in these two groups are preserved.

OP_IFDUP:

OPCode: 0x73

Stack before:

...
<Value 0>
<Pointer>

Stack after:

Either

...
<Value 0>
<Value 0>
<Pointer>

or

...
<Value 0>
<Pointer>

Description:

OP_IFDUP duplicates the next element on stack, if it evaluates to TRUE. That means, all except zero become duplicated.

OP_DEPTH:

OPCode: 0x74

Stack before:

...
<Pointer>

Stack after:

...
<The count of elements before this one>
<Pointer>

Description:

OP_DEPTH pushes the numeric count of elements on the stack on the stack. The number doesn’t include the new pushed value, so the stack will be after execution an element longer than the pushed value.

OP_DROP:

OPCode: 0x75

Stack before:

...
<Value 1>
<Value 0> >---->
<Pointer>

Stack after:

...
<Value 1>
<Pointer>

Description:

OP_DROP pops the next element from stack and throw it away.

OP_DUP:

OPCode: 0x76

Stack before:

...
<Value 1>
<Value 0> +
<Pointer>

Stack after:

...
<Value 1>
<Value 0>
<Value 0>
<Pointer>

Description:

OP_DUP duplicates the next element on stack.

OP_NIP:

OPCode: 0x77

Stack before:

...
<Value 2>
<Value 1> >---->
<Value 0>
<Pointer>

Stack after:

...
<Value 2>
<Value 0>
<Pointer>

Description:

OP_NIP removes the element after the next one from stack, but leaves the next one untouched.

OP_OVER:

OPCode: 0x78

Stack before:

...
<Value 2>
<Value 1> +-┐
<Value 0> /_|
<Pointer> \

Stack after:

...
<Value 2>
<Value 1>
<Value 0>
<Value 1>
<Pointer>

Description:

OP_OVER pushes a copy of the element after the next one on the stack again.

OP_PICK:

OPCode: 0x79

Stack before:

...
<Value n>
...
<Value 1>
<Value 0>
n
<Pointer>

Stack after:

...
<Value n>
...
<Value 1>
<Value 0>
<Value n>
<Pointer>

Description:

OP_PICK pops an as number interpreted element from stack and pushes a copy of the element with this number on the stack, where zero is the next element after the initial pop, one is the element after the next and so on.

OP_ROLL:

OPCode: 0x7a

Stack before:

...
<Value n>
...
<Value 1>
<Value 0>
n
<Pointer>

Stack after:

...
<Value 1>
<Value 0>
<Value n>
<Pointer>

Description:

OP_ROLL pops an element from stack, interprets it as number and moves the value with this position in the stack to the pointer, where the element after the popped one is element zero, the next one element one and so one. Hence, the old copy in stack gets removed.

OP_ROT:

OPCode: 0x7b

Stack before:

...
<Value 3>
<Value 2> >-┐
<Value 1>   |
<Value 0> /_|
<Pointer> \

Stack after:

...
<Value 3>
<Value 1>
<Value 0>
<Value 2>
<Pointer>

Description:

OP_ROT rotate the first three elements as a group away from pointer by one, hence it moves the third element to the pointer of the stack.

OP_SWAP:

OPCode: 0x7c

Stack before:

...
<Value 2>
<Value 1> >-┐
<Value 0> /_|
<Pointer> \

Stack after:

...
<Value 2>
<Value 0>
<Value 1>
<Pointer>

Description:

OP_SWAP swaps the next two elements on stack, hence move the second element to the pointer end of the stack.

OP_TUCK:

OPCode: 0x7d

Stack before:

...
<Value 2> /_
<Value 1> \ |
<Value 0> +-┘
<Pointer>

Stack after:

...
<Value 2>
<Value 0>
<Value 1>
<Value 0>
<Pointer>

Description:

OP_TUCK copies the next element on stack between the to begin second and third element.

OP_SIZE:

OPCode: 0x82

Stack before:

...
<Value 1>
<Value 0>
<Pointer>

Stack after:

...
<Value 1>
<Value 0>
<Size of Value 0>
<Pointer>

Description:

OP_SIZE pushes the size of the next element on the stack without touching it.

OP_EQUAL:

OPCode: 0x87

Stack before:

...
<Value 2>
<Value 1>
<Value 0>
<Pointer>

Stack after:

...
<Value 2>
TRUE/FALSE
<Pointer>

Description:

OP_EQUAL pops two elements from stack and pushes TRUE, if both was exact bytewise equals, FALSE otherwise. For mark the Transaction as invalide in case of both values doesn’t match, OP_EQUALVERIFY is preferred. For comparing numeric values exists the instructions OP_NUMEQUAL and OP_NUMEQUALVERIFY.

OP_EQUALVERIFY:

OPCode: 0x88

Stack before:

...
<Value 2>
<Value 1>
<Value 0>
<Pointer>

Stack after:

...
<Value 2>
<Pointer>

Description:

OP_EQUALVERIFY acts like a call of OP_EQUAL and OP_VERIFY in one rush, hence pops two elements from stack and marks the Transaction as invalid, if both are not equals.

OP_RESERVED1:

OPCode: 0x89

Stack before:

...
<Pointer>

Stack after:

<Transaction is invalid>

Description:

OP_RESERVED1 is just a reserved Byte, the Transaction become marked as invalid, when executed.

OP_RESERVED2:

OPCode: 0x8a

Stack before:

...
<Pointer>

Stack after:

<Transaction is invalid>

Description:

OP_RESERVED2 is just a reserved Byte, the Transaction become marked as invalid, when executed.

OP_1ADD:

OPCode: 0x8b

Stack before:

...
<Value 1>
<Value 0>
<Pointer>

Stack after:

...
<Value 1>
<Value 0> + 1
<Pointer>

Description:

OP_1ADD pops an element, increment them by one and pushes the result. For this jobs, that is preferred over the usage of OP_ADD.

OP_1SUB:

OPCode: 0x8c

Stack before:

...
<Value 1>
<Value 0>
<Pointer>

Stack after:

...
<Value 1>
<Value 0> - 1
<Pointer>

Description:

OP_1SUB pops an element, decrement them by one and pushes the result back. For this jobs, that is preferred over the usage of OP_SUB.

 

OP_NEGATE:

OPCode: 0x8f

Stack before:

...
<Value 1>
<Value 0>
<Pointer>

Stack after:

...
<Value 1>
-<Value 0>
<Pointer>

Description:

OP_NEGATE pops an element, change the sign and push the result back. That is the same as 0 - <Value 0>.

OP_ABS:

OPCode: 0x90

Stack before:

...
<Value 1>
<Value 0>/-<Value 0>
<Pointer>

Stack after:

...
<Value 1>
<Value 0>
<Pointer>

Description:

OP_ABS pops an element from stack, change the sign to positive and push the result back. So when the next element on stack is negative, it becomes positive, if it is positive, it is leave unchanged.

OP_NOT:

OPCode: 0x91

Stack before:

...
<Value 1>
0/1/<Value 0>
<Pointer>

Stack after:

...
<Value 1>
TRUE/FALSE/FALSE
<Pointer>

Description:

OP_NOT pops an element from stack and pushes TRUE, if it is zero, FALSE otherwise.

OP_0NOTEQUAL:

OPCode: 0x92

Stack before:

...
0/1/<Value 0>
<Pointer>

Stack after:

...
FALSE/TRUE/TRUE
<Pointer>

Description:

OP_0NOTEQUAL pops an element from stack and pushes FALSE, if the element is numeric zero, otherwise it pushes TRUE. That convert the values from their implicated boolean values to their fix numeric values.

OP_ADD:

OPCode: 0x93

Stack before:

...
<Value 2>
<Value 1>
<Value 0>
<Pointer>

Stack after:

...
<Value 2>
<Value 0> + <Value 1>
<Pointer>

Description:

OP_ADD pops two elements from stack, adds them together and pushes the result back. For increment a value from stack by one, it’s strong recommend to use OP_1ADD.

OP_SUB:

OPCode: 0x94

Stack before:

...
<Value 2>
<Value 1>
<Value 0>
<Pointer>

Stack after:

...
<Value 2>
<Value 1> - <Value 0>
<Pointer>

Description:

OP_SUB pops two elements and subtracts the first from the second one. For decrement a value from stack by one, it’s strong recommend to use OP_1SUB.

OP_BOOLAND:

OPCode: 0x9a

Stack before:

...
<Value 2>
<Value 1>
<Value 0>
<Pointer>

Stack after:

...
<Value 2>
<Value 0> & <Value 1> != 0
<Pointer>

Description:

OP_BOOLAND pops two elements from stack and pushes TRUE, if <Value 0> AND <Value 1> is not zero, FALSE otherwise. In other words, pushes one, if any of the same Bits in both elements was set.

OP_BOOLOR:

OPCode: 0x9b

Stack before:

...
<Value 2>
<Value 1>
<Value 0>
<Pointer>

Stack after:

...
<Value 2>
<Value 0> | <Value 1> != 0
<Pointer>

Description:

OP_BOOLOR pops two elements from stack and pushes TRUE, if <Value 0> OR <Value 1> is not zero, FALSE otherwise. In other words, pushes FALSE, if any Bit in one of the elements is set.

OP_NUMEQUAL:

OPCode: 0x9c

Stack before:

...
<Value 2>
<Value 1>
<Value 0>
<Pointer>

Stack after:

...
<Value 2>
asNum(<Value 0>) != asNum(<Value 1>) ? 1 : 0
<Pointer>

Description:

OP_NUMEQUAL pops two elements from stack and pushes TRUE, if the elements are numeric equals, FALSE otherwise. To mark the Transaction as invalid in case of different numbers, calling OP_NUMEQUALVERIFY is strong recommend, as long it is not the last check, since a Transaction is only valid, if the stack contains after script execution one element that evaluates to boolean TRUE.

OP_NUMEQUALVERIFY:

OPCode: 0x9d

Stack before:

...
<Value 2>
<Value 1>
<Value 0>
<Pointer>

Stack after:

...
<Value 2>
<Pointer>

Description:

OP_NUMEQUALVERIFY acts like a call of OP_NUMEQUAL, followed by OP_VERIFY, so it pops two elements from stack and mark the Transaction as invalid, if both are not numeric equal. If this is the last test to possibly mark this Transaction as invalid, the call of OP_NUMEQUAL is the way to go, since a Transaction is only valid, if the stack contains after script execution one element that evaluates to boolean TRUE.

OP_NUMNOTEQUAL:

OPCode: 0x9e

Stack before:

...
<Value 1>
<Value 0>
<Pointer>

Stack after:

...
TRUE/FALSE
<Pointer>

Description:

OP_NUMNOTEQUAL pops two elements from stack and push TRUE, if they are not numeric equals, FALSE otherwise.

OP_LESSTHAN:

OPCode: 0x9f

Stack before:

...
<Value 1>
<Value 0>
<Pointer>

Stack after:

...
TRUE/FALSE 
<Pointer>

Description:

OP_LESSTHAN pops two numbers from stack and pushes TRUE, if the second one is smaller than the first one, FALSE otherwise.

OP_GREATERTHAN:

OPCode: 0xa0

Stack before:

...
<Value 2>
<Value 1>
<Value 0>
<Pointer>

Stack after:

...
<Value 2>
<Value 1> > <Value 0>
<Pointer>

Description:

OP_GREATERTHAN pops two numbers from stack and pushes TRUE, if the second one is greater than the first one, FALSE otherwise.

OP_LESSTHANOREQUAL:

OPCode: 0xa0

Stack before:

...
<Value 2>
<Value 1>
<Value 0>
<Pointer>

Stack after:

...
<Value 2>
<Value 1> <= <Value 0>
<Pointer>

Description:

OP_LESSTHANOREQUAL pops two numbers from stack and pushes TRUE, if the second one is less than or equals the first one, FALSE otherwise.

OP_GREATERTHANOREQUAL:

OPCode: 0xa1

Stack before:

...
<Value 2>
<Value 1>
<Value 0>
<Pointer>

Stack after:

...
<Value 2>
<Value 1> >= <Value 0>
<Pointer>

Description:

OP_GREATERTHANOREQUAL pops two numbers from stack and pushes TRUE, if the second one is greater than or equals the first one, FALSE otherwise.

OP_MIN:

OPCode: 0xa3

Stack before:

...
<Value 2>
<Value 1>
<Value 0>
<Pointer>

Stack after:

...
<Value 2>
<Value 1> > <Value 0> ? <Value 1> : <Value 0>
<Pointer>

Description:

OP_MIN pops two elements from stack and push the numeric smaller one of both.

OP_MAX:

OPCode: 0xa4

Stack before:

...
<Value 2>
<Value 1>
<Value 0>
<Pointer>

Stack after:

...
<Value 2>
<Value 1> > <Value 0> ? <Value 0> : <Value 1>
<Pointer>

Description:

OP_MAX pops two elements from stack and pushes the numeric greater one of both.

OP_WITHIN:

OPCode: 0xa5

Stack before:

...
<Value 3>
<Value 2>
<Value 1>
<Value 0>
<Pointer>

Stack after:

...
<Value 3>
<Value 2> >= <Value 1> && <Value 2> < <Value 3>
<Pointer>

Description:

OP_WITHIN pops three elements from stack and pushes TRUE, if the third is between inclusive the second and exclusive the first one.

OP_RIPEMD160:

OPCode: 0xa6

Stack before:

...
<Value 1>
<Value 0>
<Pointer>

Stack after:

...
<Value 1>
ripemd160(<Value 0>)
<Pointer>

Description:

OP_RIPEMD160 pops an element from stack, hashes it by the algorithm RIPEMD-160 and pushes the result back.

OP_SHA1:

OPCode: 0xa7

Stack before:

...
<Value 1>
<Value 0>
<Pointer>

Stack after:

...
<Value 1>
sha1(<Value 0>)
<Pointer>

Description:

OP_SHA1 pops an element from stack, hashes it by the algorithm SHA-1 and pushes the result back.

OP_SHA256:

OPCode: 0xa8

Stack before:

...
<Value 1>
<Value 0>
<Pointer>

Stack after:

...
<Value 1>
sha256(<Value 0>)
<Pointer>

Description:

OP_SHA256 pops an element from stack, hashes it by the algorithm SHA-256 and pushes the result back.

OP_HASH160:

OPCode: 0xa9

Stack before:

...
<Value 1>
<Value 0>
<Pointer>

Stack after:

...
<Value 1>
ripemd160(sha256(<Value 0>))
<Pointer>

Description:

OP_HASH160 pops an element from stack, hashes it using the algorithm SHA-256, hashes the result by the algorithm RIPEMD-160 and pushes this result back. That is the usual way to generate a Bitcoin address from your public key.

OP_HASH256:

OPCode: 0xaa

Stack before:

...
<Value 1>
<Value 0>
<Pointer>

Stack after:

...
<Value 1>
sha256(sha256(<Value 0>))
<Pointer>

Description:

OP_HASH256 pops an element from stack, hashes it using the algorithm SHA-256, hashes the result by SHA-256 again and pushes this result back. That is the usual way to hash Block Headers and Transactions.

OP_CODESEPARATOR:

OPCode: 0xab

Stack before:

...
<Pointer>

Stack after:

...
<Pointer>

Description:

All the signature-checking instructions tests the signature for a hash between a variable pointer and the end of the script field. This looks at start at the begin of the script field, the instruction OP_CODESEPARATOR updates this pointer to the location of the command.

OP_CHECKSIG:

OPCode: 0xac

Stack before:

...
Signature
Public Key
<Pointer>

Stack after:

...
TRUE/FALSE
<Pointer>

Description:

OP_CHECKSIG pops two elements from stack and pushes TRUE if and only if the second element is a valid signature, decrypted by the private key of the first one, handled as public key.

OP_CHECKSIGVERIFY:

OPCode: 0xad

Stack before:

...
Signature
Public Key
<Pointer>

Stack after:

...
<Pointer>

Description:

OP_CHECKSIGVERIFY works like calling OP_CHECKSIG and OP_VERIFY in one step, so pops two elements and marks the Transaction as invalid, if the second one is not a valid signature, encrypted by the private key of the first element.

OP_CHECKMULTISIG:

Warning: Buggy! (Read description)

OPCode: 0xae

Stack before:

...
<Value 0>
Dummy
...
Signature 2
Signature 1
Signature 0
Signature count
...
Public Key 2
Public Key 1
Public Key 0
Public Key count
<Pointer>

Stack after:

...
<Value 0>
TRUE/FALSE
<Pointer>

Description:

OP_CHECKMULTISIG pops from stack a public key count, the public keys, a signature count, the signatures and because of a bug an unused value. It tests for each signature, if there is a matching public key and if it is a valid signature for this Transaction. A matched public key is for the following signatures not tested again, so the public key count must be greater or equal the signature count to find for each signature a public key. When no public key exists for a signature or any cannot be validated, this instruction pushes a FALSE, if all signatures was valid, it pushes TRUE.

OP_CHECKMULTISIGVERIFY:

Warning: Buggy! (Read description)

OPCode: 0xaf

Stack before:

...
Dummy
Signature 0
Signature 1
Signature 2
Signature count
Public Key 0
Public Key 1
Public Key 2
Public Key count
<Pointer>

Stack after:

...
<Pointer>

Description:

OP_CHECKMULTISIGVERIFY acts like calling OP_CHECKMULTISIG and OP_VERIFY in one step. So, it pops a public key count, the public keys, a signature count, the signatures and because of a bug an unused value. It tests for each signature, if there is a matching public key and if it is a valid signature for this Transaction. A matched public key is for the following signatures not tested again, so the public key count must be greater or equal the signature count to find for each signature a public key. When for a signature no public key exists or a signature is not valid, this instruction marks the Transaction as invalid.

OP_NOP#:

OPCodes:

0xb0 - OP_NOP1
0xb3 - OP_NOP4
0xb4 - OP_NOP5
0xb5 - OP_NOP6
0xb6 - OP_NOP7
0xb7 - OP_NOP8
0xb8 - OP_NOP9
0xb9 - OP_NOP10

Stack before:

...
<Pointer>

Stack after:

...
<Pointer>

Description:

The Byte 0xb0 and 0xb3 to 0xb9 have the mnemonics OP_NOP1 and OP_NOP4 to OP_NOP10. These are all ignored and are the recommended way to add own instructions to an encrypted currency. OP_NOP2 and OP_NOP3 was already redefined for OP_CHECKLOCKTIMEVERIFY and OP_CHECKSEQUENCEVERIFY.

OP_CHECKLOCKTIMEVERIFY:

OPCode: 0xb1

Stack before:

...
<Pointer>

Stack after:

...
<Pointer>

Description:

Pops an element from stack and marks the Transaction as invalid, if any of the following cases matches:

  • The element is numeric bigger than the nLockTime field of the Transaction.
  • The element is numeric negative.
  • The field sequence_no of the Txin is 0xffffffff.
  • (element >= 500.000.000) ^ (nLockTime >= 500.000.000) is TRUE
  • A stack underflow, for obvious reasons.

OP_CHECKSEQUENCEVERIFY:

OPCode: 0xb2

Stack before:

...
<Pointer>

Stack after:

...
<Pointer>

Disabled instructions:

OP_CAT:

Warning: Disabled!

OPCode: 0x7e

Stack before:

...
<Value 1>
<Value 0>
<Pointer>

Stack after:

...
<Value 1><Value 0>
<Pointer>

Description:

OP_CAT popped two elements from stack and concatenated them.

OP_SUBSTR:

Warning: Disabled!

OPCode: 0x7f

Stack before:

...
<Value>
<Begin index>
<Size>
<Pointer>

Stack after:

...
<Substring>
<Pointer>

Description:

OP_SUBSTR popped a value, an index and a size value in reverse order and pushed a sub-sequence of them.

OP_LEFT:

Warning: Disabled!

OPCode: 0x80

Stack before:

...
<Value>
<Index>
<Pointer>

Stack after:

...
<Substring>
<Pointer>

Description:

OP_LEFT popped an index, a value and pushed a sub-sequence from the left end to the index.

OP_RIGHT:

Warning: Disabled!

OPCode: 0x81

Stack before:

...
<Value>
<Index>
<Pointer>

Stack after:

...
<Substring>
<Pointer>

Description:

OP_RIGHT popped an index, a value and pushed a sub-sequence from the right end to the index.

OP_INVERT:

Warning: Disabled!

OPCode: 0x83

Stack before:

...
<Value 0>
<Pointer>

Stack after:

...
NOT(<Value 0>)
<Pointer>

Description:

OP_INVERT popped a value from stack and push it with complemented Bits.

OP_AND:

Warning: Disabled!

OPCode: 0x84

Stack before:

...
<Value 1>
<Value 0>
<Pointer>

Stack after:

...
<Value 0 ^ 1)
<Pointer>

Description:

OP_AND popped two values from stack and pushed the result of a bitwise AND between them back.

OP_OR:

Warning: Disabled!

OPCode: 0x85

Stack before:

...
<Value 1>
<Value 0>
<Pointer>

Stack after:

...
<Value 0 V 1)
<Pointer>

Description:

OP_OR popped two values from stack and pushed the result of a bitwise OR between them back.

OP_XOR:

Warning: Disabled!

OPCode: 0x86

Stack before:

...
<Value 1>
<Value 0>
<Pointer>

Stack after:

...
<Value 0 XOR 1)
<Pointer>

Description:

OP_XOR popped two values from stack and pushed the result of a bitwise XOR between them back.

OP_2MUL:

Warning: Disabled!

OPCode: 0x8d

Stack before:

...
<Value 0>
<Pointer>

Stack after:

...
<Value 0> * 2
<Pointer>

Description:

OP_2MUL popped a value from stack, multiplied them by two and pushed them back onto stack. This was and is for a number representation of the base two a shift to the left, like ten in the decimal system.

OP_2DIV:

Warning: Disabled!

OPCode: 0x8e

Stack before:

...
<Value 0>
<Pointer>

Stack after:

...
<Value 0> / 2
<Pointer>

Description:

OP_2DIV popped a value from stack, divided them by two and pushed them back onto stack. This was and is for a number representation of the base two a shift to the right, like by ten in the decimal system. The bit shifted out is the rest of the division.

OP_MUL:

Warning: Disabled!

OPCode: 0x95

Stack before:

...
<Value 1>
<Value 0>
<Pointer>

Stack after:

...
<Value 0> * <Value 1>
<Pointer>

Description:

OP_MUL popped two elements from stack, multiplied both ones and pushed the result back.

OP_DIV:

Warning: Disabled!

OPCode: 0x96

Stack before:

...
<Value 1>
<Value 0>
<Pointer>

Stack after:

...
<Value 0> / <Value 1>
<Pointer>

Description:

OP_DIV popped two elements from stack, divided the first by the second one and pushed the result back.

OP_MOD:

Warning: Disabled!

OPCode: 0x97

Stack before:

...
<Value 1>
<Value 0>
<Pointer>

Stack after:

...
<Value 0> (mod) <Value 1>
<Pointer>

Description:

OP_MOD popped two elements from stack and pushed the rest of a division from the first by the second element.

OP_LSHIFT:

Warning: Disabled!

OPCode: 0x98

Stack before:

...
<Value 1>
<Value 0>
<Pointer>

Stack after:

...
<Value 1> << <Value 0>
<Pointer>

Description:

OP_LSHIFT popped two elements from stack, shifted the second one to left by the places, represented by the first one and pushed the result back.

OP_RSHIFT:

Warning: Disabled!

OPCode: 0x99

Stack before:

...
<Value 1>
<Value 0>
<Pointer>

Stack after:

...
<Value 1> >>> <Value 0>
<Pointer>

Description:

OP_RSHIFT popped two elements from stack, shifted the second one arithmetic to right by the places, represented by the first one and pushed the result back. That means, the sign will not change. On complement numbers system, that is setting the new MSB to the old ones value.

Post Your Comment Here

Your email address will not be published. Required fields are marked *

Free Demo!

Join the Calloway Crypto System now,
to get a free demo account:

Join the Calloway Crypto Soft now!

Read now the whole review!

If you have additional questions or stumble, please email immediate to earnmoneytodayblog@gmail.com or use the simple contact form.

 

earn-money.today successful challenge: 1041/2000 successful trader. Test now Calloway Crypto System or other verified trading systems for free and send us how successful you are and how much profit you made, and may what we can do for you.

52%

Last successful trader:
Antje B.
Be the next!