Skip to content

Programming Bitcoin Script Transaction (Crypto) Contracts Step-by-Step - Let's start with building your own bitcoin stack machine from zero / scratch and let's run your own bitcoin ops (operations)...

License

Notifications You must be signed in to change notification settings

openblockchains/programming-bitcoin-script

Repository files navigation

Programming Bitcoin Script Transaction (Crypto) Contracts Step-by-Step

Let's start with building your own bitcoin stack machine from zero / scratch and let's run your own bitcoin ops (operations)...

Did you know? Every (yes, every) bitcoin transaction (payment) runs a contract script (one half coming from the "output" or "lock" transaction and the other half coming from the "input" or "unlock" transaction). The programming language is called simply (bitcoin) script.

Bitcoin uses a scripting system for transactions. Forth-like, Script is simple, stack-based, and processed from left to right. It is intentionally not Turing-complete, with no loops.

(Source: Script @ Bitcoin Wiki)

First impression. Adding 2+2 in Bitcoin Script starting from zero / scratch:

## A simple stack machine def op_add( stack ) left = stack.pop right = stack.pop stack.push( left + right ) end def op_2( stack ) stack.push( 2 ) end ## Let's run! stack = [] op_2( stack ) #=> stack = [2] op_2( stack ) #=> stack = [2,2] op_add( stack ) #=> stack = [4]

(Source: stackmachine_add.rb)

Yes, that's all the magic! You have built your own stack machine with two operations / ops, that is, op_add and op_2.

The op_2 operation pushes the number 2 onto the stack. The op_add operation pops the top two numbers from the stack and pushes the result onto the stack.

Aside - What's a Stack? Push 'n' Pop

A stack is a last-in first-out (LIFO) data structure. Use push to add an element to the top of the stack and use pop to remove the top element from the stack. Example:

stack = [] #=> [] stack.empty? #=> true stack.push( 1 ) #=> [1] stack.empty? #=> false stack.push( 2 ) #=> [1, 2] stack.push( 3 ) #=> [1, 2, 3] stack.push( "<signature>" ) #=> [1, 2, 3, "<signature>"] stack.push( "<pubkey>") #=> [1, 2, 3, "<signature>", "<pubkey>"] stack.pop #=> "<pubkey>" stack #=> [1, 2, 3, "<signature>"] stack.pop #=> "<signature>" stack #=> [1, 2, 3] stack.push( 4 ) #=> [1, 2, 3, 4] stack.push( 5 ) #=> [1, 2, 3, 4, 5] stack.pop #=> 5 stack #=> [1, 2, 3, 4] stack.pop #=> 4 stack #=> [1, 2, 3] stack.pop #=> 3 stack #=> [1, 2] stack.pop #=> 2 stack #=> [1] stack.empty? #=> false stack.pop #=> 1 stack #=> [] stack.empty? #=> true stack.pop #=> nil

(Source: stack.rb)

Unlock+Lock / Input+Output / ScriptSig+ScriptPubKey

In "real world" bitcoin the script has two parts / halves in two transactions that get combined. The "lock" or "output" or "ScriptPubKey" script that locks the "unspent transaction output (UTXO)" and the "unlock" or "input" or "ScriptSig" script that unlocks the bitcoins.

Anyone Can Spend (Unlock) the Outputs (Bitcoins)

The bitcoins are yours if the bitcoins haven't been spent yet - see blockchain and how it solves the double-spending problem :-) - AND if the script returns with true, that is, 1 is on top of the stack.

## A simple stack machine def op_true( stack ) stack.push( 1 ) end ## Let's run! stack = [] ## I) ScriptSig (input/unlock) part op_true( stack ) #=> stack = [1] ## II) ScriptPubKey (output/lock) part ## <Empty>

(Source: stackmachine_anyone.rb)

Bingo! Yes, that's all the magic! The op_true operation pushes the number 1, that is, true onto the stack.

The "official" bitcoin script notation reads:

ScriptSig (input): OP_TRUE ScriptPubKey: (empty) 

Now let's split the adding 2+2 script into a two part puzzle, that is, ?+2=4 or into ScriptSig and ScriptPubKey. If you know the answer you can "unlock" the bounty, that is, the bitcoin are yours! Here's the challenge:

## A simple stack machine def op_add( stack ) left = stack.pop right = stack.pop stack.push( left + right ) end def op_2( stack ) stack.push( 2 ) end def op_4( stack ) stack.push( 4 ) end def op_equal( stack ) left = stack.pop right = stack.pop stack.push( left == right ? 1 : 0 ) end ## Let's run! stack = [] ## I) ScriptSig (input/unlock) part ## FIX!!! - add your "unlock" stack operation / operations here ## II) ScriptPubKey (output/lock) part op_2( stack ) #=> stack = [?, 2] op_add( stack ) #=> stack = [4] op_4( stack ) #=> stack = [4,4] op_equal( stack ) #=> stack = [1]

(Source: stackmachine_puzzle.rb)

The "official" bitcoin script notation reads:

ScriptSig (input): ? ScriptPubKey: OP_2 OP_ADD OP_4 OP_EQUAL 

If you check all Bitcoin script operations - the following ops should no longer be a mystery:

Constants

Word Opcode Hex Input Output Description
OP_0, OP_FALSE 0 0x00 Nothing. (empty value) An empty array of bytes is pushed onto the stack. (This is not a no-op: an item is added to the stack.)
OP_1, OP_TRUE 81 0x51 Nothing. 1 The number 1 is pushed onto the stack.
OP_2-OP_16 82-96 0x52-0x60 Nothing. 2-16 The number in the word name (2-16) is pushed onto the stack.

Bitwise logic

Word Opcode Hex Input Output Description
OP_EQUAL 135 0x87 x1 x2 True / false Returns 1 if the inputs are exactly equal, 0 otherwise.

Arithmetic

Word Opcode Hex Input Output Description
OP_ADD 147 0x93 a b out a is added to b.
OP_MUL 149 0x95 a b out a is multiplied by b. disabled.
OP_DIV 150 0x96 a b out a is divided by b. disabled.

Trivia Corner: Did you know? The OP_MUL for multiplications (e.g. 2*2) has been banned, that is, disabled! Why? Because of security concerns, that is, fear of stack overflows. What about OP_DIV for divisions (e.g. 4/2)? Don't ask! Ask who's protecting you from stack underflows? So what's left for programming - not much really other than checking signatures and timelocks :-).

To be continued ...

Standard Scripts

Short Name Long Name
p2pk Pay-to-pubkey
p2pkh Pay-to-pubkey-hash
p2sh Pay-to-script-hash

Standard Scripts with SegWit (Segregated Witness)

| p2wpkh | Pay-to-witness-pubkey-hash | | p2wsh | Pay-to-witness-script-hash |

Resources

Articles

Books / Series

  • Programming Bitcoin from Scratch by Jimmy Song
    • Chapter 6 - Script - How Script Works • Example Operations • Parsing the Script Fields • Combining the Script Fields • Standard Scripts • p2pk • Problems with p2pk • Solving the Problems with p2pkh • Scripts Can Be Arbitrarily Constructed • Conclusion
    • Chapter 8 - Pay-to-Script Hash - Bare Multisig • Coding OP_CHECKMULTISIG • Problems with Bare Multisig • Pay-to-Script-Hash (p2sh) • Coding p2sh • Conclusion
    • Chapter 13 - Segregated Witness - Pay-to-Witness-Pubkey-Hash (p2wpkh) • p2wpkh Transactions • p2sh-p2wpkh • Coding p2wpkh and p2sh-p2wpkh • Pay-to-Witness-Script-Hash (p2wsh) • p2sh-p2wsh • Coding p2wsh and p2sh-p2wsh • Other Improvements • Conclusion

Talk Notes

License

The Programming Bitcoin Script Step-by-Step book / guide is dedicated to the public domain. Use it as you please with no restrictions whatsoever.

About

Programming Bitcoin Script Transaction (Crypto) Contracts Step-by-Step - Let's start with building your own bitcoin stack machine from zero / scratch and let's run your own bitcoin ops (operations)...

Topics

Resources

License

Stars

Watchers

Forks

Languages