Update 11_1_Writing_Puzzle_Scripts.md

This commit is contained in:
Shannon Appelcline 2017-06-02 13:30:27 -07:00 committed by GitHub
parent 5fd47a187a
commit 0e7954c065

View File

@ -1,2 +1,190 @@
https://medium.com/@alcio/non-standard-p2sh-scripts-508fa6292df5 # 10.1: Writing Puzzle Scripts
* Bounties: https://bitcointalk.org/index.php?topic=293382.0
> **NOTE:** This is a draft in progress, so that I can get some feedback from early reviewers. It is not yet ready for learning.
Bitcoin Scripts _don't_ actually have to depend on the knowledge of a secret key. They can instead be puzzles of any sort.
## Write Simple Algebra Scripts
Our first real Script, from [§7.2: Running a Bitcoin Script](7_2_Running_a_Bitcoin_Script.md) was an alegbraic script. That Bitcoin Script, `OP_ADD 99 OP_EQUAL`, could have been alternatively described as `x + y = 99`.
This sort of Script doesn't have a lot of applicability in the real world, as it's too easy to claim the funds. But, a puzzle-solving contest giving out Bitcoin dust might offer it as a fun entertainment.
More notably, creating alegebraic puzzles gives you a nice understanding of how the arithmetic functions in Bitcoin Script work.
### Write a Multiplier Script
Bitcoin Script has a number of opcodes that were disabled to maintain the security of the system. One of the is `OP_MUL`, which would have allowed multiplication ... but is instead disabled.
So, how would you write an algebraic function like `3x + 7 = 13`?
The most obvious answer is to `OP_DUP` the number input from the locking script twice. Then you can push the `7` and keep adding until you get your total. The full locking script would look like this: `OP_DUP OP_DUP 7 OP_ADD OP_ADD OP_ADD 13 OP_EQUAL`.
Here's how it would run if executed with the correct unlocking script of `2`:
```
Script: 2 OP_DUP OP_DUP 7 OP_ADD OP_ADD OP_ADD 13 OP_EQUAL
Stack: [ ]
Script: OP_DUP OP_DUP 7 OP_ADD OP_ADD OP_ADD 13 OP_EQUAL
Stack: [ 25 ]
Script: OP_DUP 7 OP_ADD OP_ADD OP_ADD 13 OP_EQUAL
Running: 2 OP_DUP
Stack: [ 2 2 ]
Script: 7 OP_ADD OP_ADD OP_ADD 13 OP_EQUAL
Running: 2 OP_DUP
Stack: [ 2 2 2 ]
Script: OP_ADD OP_ADD OP_ADD 13 OP_EQUAL
Stack: [ 2 2 2 7 ]
Script: OP_ADD OP_ADD 13 OP_EQUAL
Running: 2 7 OP_ADD
Stack: [ 2 2 9 ]
Script: OP_ADD 13 OP_EQUAL
Running: 2 9 OP_ADD
Stack: [ 2 11 ]
Script: 13 OP_EQUAL
Running: 2 11 OP_ADD
Stack: [ 13 ]
Script: OP_EQUAL
Stack: [ 13 13 ]
Script:
Running: 13 13 OP_EQUAL
Stack: [ True ]
```
See also the [WebBC Debug Execution](https://webbtc.com/script/2/OP_DUP%20OP_DUP%207%20OP_ADD%20OP_ADD%20OP_ADD%2013%20OP_EQUAL/) of this script.
### Write an Equation System
What if you wanted to instead write an equation system, such as `x + y = 3`, `y + z = 5`, and `x + z = 4`? A bit of algebra tells you that the answers come out to `x = 1`, `y = 2`, and `z = 3`. But, how do you script it?
Most obviously, after the redeemer inputs the three numbers, we're going to need two copies of each numbers, since each goes into two equations. `OP_3DUP` takes care of that and results in `x y z x y z` being on the stack. Popping off two items at a time will give us `y z`, `z x`, and `x y`. Voila! That's our three equations, so we just need to do some addition! Here's the full script: `OP_3DUP OP_ADD 5 OP_EQUALVERIFY OP_ADD 4 OP_EQUALVERIFY OP_ADD 3 OP_EQUAL`.
Here's how it runs with the correct unlocking script of `1 2 3`:
```
Script: 1 2 3 OP_3DUP OP_ADD 5 OP_EQUALVERIFY OP_ADD 4 OP_EQUALVERIFY OP_ADD 3 OP_EQUAL
Stack: [ ]
Script: OP_3DUP OP_ADD 5 OP_EQUALVERIFY OP_ADD 4 OP_EQUALVERIFY OP_ADD 3 OP_EQUAL
Stack: [ 1 2 3 ]
Script: OP_ADD 5 OP_EQUALVERIFY OP_ADD 4 OP_EQUALVERIFY OP_ADD 3 OP_EQUAL
Running: 1 2 3 OP_3DUP
Stack: [ 1 2 3 1 2 3 ]
Script: 5 OP_EQUALVERIFY OP_ADD 4 OP_EQUALVERIFY OP_ADD 3 OP_EQUAL
Running: 2 3 OP_ADD
Stack: [ 1 2 3 1 5 ]
Script: OP_EQUALVERIFY OP_ADD 4 OP_EQUALVERIFY OP_ADD 3 OP_EQUAL
Stack: [ 1 2 3 1 5 5 ]
Script: OP_ADD 4 OP_EQUALVERIFY OP_ADD 3 OP_EQUAL
Running: 5 5 OP_EQUALVERIFY
Stack: [ 1 2 3 1 ] — Does Not Exit
Script: 4 OP_EQUALVERIFY OP_ADD 3 OP_EQUAL
Running: 3 1 OP_ADD
Stack: [ 1 2 4 ]
Script: OP_EQUALVERIFY OP_ADD 3 OP_EQUAL
Stack: [ 1 2 4 4 ]
Script: OP_ADD 3 OP_EQUAL
Running: 4 4 OP_EQUALVERIFY
Stack: [ 1 2 ] — Does Not Exit
Script: 3 OP_EQUAL
Running: 1 2 OP_ADD
Stack: [ 3 ]
Script: OP_EQUAL
Stack: [ 3 3 ]
Script:
Running: 3 3 OP_EQUAL
Stack: [ True ]
```
See also the [WebBC Debug Execution](https://webbtc.com/script/1%202%203/OP_3DUP%20OP_ADD%205%20OP_EQUALVERIFY%20OP_ADD%204%20OP_EQUALVERIFY%20OP_ADD%203%20OP_EQUAL/) of this script.
## Write Simple Computational Scripts
Though puzzle scripts are trivial, they can actually have real-world usefulness if you want to crowdsource a computation. You simply create a script that requires the answer to the computation and you put Bitcoin into the P2SH address. It'll then stay there until someone comes up with the answer.
For example, Peter Todd [offered rewards](https://bitcointalk.org/index.php?topic=293382.0) for solving equations that demonstrate collisions for standard cryptographic algorithms. Here was his script for confirming a SHA1 collision: `OP_2DUP OP_EQUAL OP_NOT OP_VERIFY OP_SHA1 OP_SWAP OP_SHA1 OP_EQUAL`. It requires two inputs, which will be the two numbers that collide.
Here's how it runs with correct answers.
First, we fill in our stack:
```
Script: <numA> <numB> OP_2DUP OP_EQUAL OP_NOT OP_VERIFY OP_SHA1 OP_SWAP OP_SHA1 OP_EQUAL
Stack: [ ]
Script: OP_2DUP OP_EQUAL OP_NOT OP_VERIFY OP_SHA1 OP_SWAP OP_SHA1 OP_EQUAL
Stack: [ <numA> <numB> ]
Script: OP_EQUAL OP_NOT OP_VERIFY OP_SHA1 OP_SWAP OP_SHA1 OP_EQUAL
Running: <numA> <numB> OP_2DUP
Stack: [ <numA> <numB> <numA> <numB> ]
```
Then, we make sure the two numbers aren't equal, exiting if they are:
```
Script: OP_NOT OP_VERIFY OP_SHA1 OP_SWAP OP_SHA1 OP_EQUAL
Running: <numA> <numB> OP_EQUAL
Stack: [ <numA> <numB> False ]
Script: OP_VERIFY OP_SHA1 OP_SWAP OP_SHA1 OP_EQUAL
Running: False OP_NOT
Stack: [ <numA> <numB> True ]
Script: OP_SHA1 OP_SWAP OP_SHA1 OP_EQUAL
Running: True OP_VERIFY
Stack: [ <numA> <numB> ] — Does Not Exit
```
We now create two SHAs:
```
Script: OP_SWAP OP_SHA1 OP_EQUAL
Running: <numB> OP_SHA1
Stack: [ <numA> <hashB> ]
Script: OP_SHA1 OP_EQUAL
Running: <numA> <hashB> OP_SWAP
Stack: [ <hashB> <numA> ]
Script: OP_EQUAL
Running: <numA> OP_SHA1
Stack: [ <hashB> <hashA> ]
Script:
Running: <hashB> <hashA> OP_EQUAL
Stack: [ True ]
```
This is a nice example because it shows careful use of logic (with the `OP_NOT` and the `OP_VERIFY`) and good use of stack functions (with the `OP_SWAP`). It's all around a great example of a real-world function. And it is very real-world. When [SHA-1 was broken](https://shattered.io/), 2.48 BTC were quickly liberated from the address, with a total value of almost $3,000.
See also the [WebBTC Debug Execution](https://webbtc.com/script/255044462d312e330a25e2e3cfd30a0a0a312030206f626a0a3c3c2f57696474682032203020522f4865696768742033203020522f547970652034203020522f537562747970652035203020522f46696c7465722036203020522f436f6c6f7253706163652037203020522f4c656e6774682038203020522f42697473506572436f6d706f6e656e7420383e3e0a73747265616d0affd8fffe00245348412d3120697320646561642121212121852fec092339759c39b1a1c63c4c97e1fffe017f46dc93a6b67e013b029aaa1db2560b45ca67d688c7f84b8c4c791fe02b3df614f86db1690901c56b45c1530afedfb76038e972722fe7ad728f0e4904e046c230570fe9d41398abe12ef5bc942be33542a4802d98b5d70f2a332ec37fac3514e74ddc0f2cc1a874cd0c78305a21566461309789606bd0bf3f98cda8044629a1%20255044462d312e330a25e2e3cfd30a0a0a312030206f626a0a3c3c2f57696474682032203020522f4865696768742033203020522f547970652034203020522f537562747970652035203020522f46696c7465722036203020522f436f6c6f7253706163652037203020522f4c656e6774682038203020522f42697473506572436f6d706f6e656e7420383e3e0a73747265616d0affd8fffe00245348412d3120697320646561642121212121852fec092339759c39b1a1c63c4c97e1fffe017346dc9166b67e118f029ab621b2560ff9ca67cca8c7f85ba84c79030c2b3de218f86db3a90901d5df45c14f26fedfb3dc38e96ac22fe7bd728f0e45bce046d23c570feb141398bb552ef5a0a82be331fea48037b8b5d71f0e332edf93ac3500eb4ddc0decc1a864790c782c76215660dd309791d06bd0af3f98cda4bc4629b1/OP_2DUP%20OP_EQUAL%20OP_NOT%20OP_VERIFY%20OP_SHA1%20OP_SWAP%20OP_SHA1%20OP_EQUAL/), with the correct answers.
The other [bounties](https://bitcointalk.org/index.php?topic=293382.0) remain unclaimed at the time of this writing. They're all written in the same manner as the SHA-1 example above.
## Understand the Danger of Puzzle Scripts
Though puzzle scripts are great to further examine Bitcoin Scripting, but you'll only see them in real-world use if they have very low values or if they are intended for redemption by very skilled users. There's a reason for this: they aren't secure. Yet, Peter Todd's cryptographic bounties prove that they do have some real-world application.
But, here's where the security falls down.
First, anyone can redeem them without knowing much of a secret. They do have to have the `redeemScript`, which offers some protection, but once they do, that's probably all the secret that's necessary. Unless your puzzle is _really_ tough, such as a computational puzzle.
Second, the actual redemption isn't secure. Normally, a Bitcoin transction is protected by the signature. Because the signature covers the transaction, no one on the network can take your transaction and change it to send to their address. The restulant signature would no longer be valid. That isn't true with a transactions whose inputs are just numbers. Anyone could grab your inputs and write a new transaction that sends to them. If they can get their transaction into a block before yours, they win, and you don't get the puzzle money. There are solutions for this, but they involve mining the block yourself of having a trusted pool mine it, and neither of those is rational for an average Bitcoin user.
## Summary: Writing Puzzle Scripts
Puzzles scripts are a great introduction to more realistic and complex real-world Bitcoin Scripts. They demonstrate the power of the mathematical and stack functions in Bitcoin Script and how they can be carefully combined to create questions that require very specific answers. However, their real-world usage is also limited by the security problems inherent in non-signed Bitcoin transactions.
_What is the power of puzzle script?_ Despite their limitations, puzzles scripts have been used in the real world as the prizes for computational bounties. Anyone who can figure out a complex puzzle, whose solution presmably has some real-world impact, can win the bounty.