Skip to content

Commit 5e4f28c

Browse files
committed
added hints for chapters 6-10
1 parent 31fd43c commit 5e4f28c

47 files changed

Lines changed: 907 additions & 451 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

appa.asciidoc

Lines changed: 155 additions & 85 deletions
Large diffs are not rendered by default.

ch03.asciidoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -733,7 +733,7 @@ To whit, here are the steps:
733733
====
734734
The calculation of z requires two rounds of sha256. You may be wondering why there are two rounds when only 1 is necessary to get a 256-bit number. The reason is for security.
735735
736-
There is a well-known hash collision attack on SHA1 called a _birthday attack_ which basically makes finding collisions much easier. This is how Google found a SHA1 collision in 2017 (https://security.googleblog.com/2017/02/announcing-first-sha1-collision.html). Using SHA1 twice, or double-SHA1 is the way to defeat this attack.
736+
There is a well-known hash collision attack on sha1 called a _birthday attack_ which basically makes finding collisions much easier. This is how Google found a sha1 collision in 2017 (https://security.googleblog.com/2017/02/announcing-first-sha1-collision.html). Using sha1 twice, or double-sha1 is the way to defeat this attack.
737737
738738
There is no known sha256 weakness like a birthday attack, but is doing two rounds is a defense against possible potential weaknesses.
739739
====

ch06.asciidoc

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -223,11 +223,11 @@ class Script:
223223
<5> Any element longer than 520 bytes cannot be serialized.
224224
<6> We prepend with the length of the entire Script.
225225

226-
Note that both the parser and serializer were used in Chapter 5 for Transaction parsing/serializing. The Script object represents the instruction set that needs to be validated.
226+
Note that both the parser and serializer were used in Chapter 5 for Transaction parsing/serializing. The Script object represents the instruction set that requires validation.
227227

228228
=== Combining the Script fields
229229

230-
It's important to realize at this point that the lockbox (ScriptPubKey) and the unlocking (ScriptSig) are in *different* transactions. Specifically, the lockbox is where the bitcoins are received, the unlocking is where the bitcoins are spent. The input in the spending transaction *points to the receiving transaction*. Essentially, we have a situation like this:
230+
To evaluate Script, we need to combine the ScriptPubKey and ScriptSig fields. The lockbox (ScriptPubKey) and the unlocking (ScriptSig) are in _different_ transactions. Specifically, the lockbox is where the bitcoins are received, the unlocking is where the bitcoins are spent. The input in the spending transaction _points to the receiving transaction_. Essentially, we have a situation like this:
231231

232232
.ScriptPubKey and ScriptSig
233233
image::Script3.png[ScriptPubKey and ScriptSig]
@@ -247,7 +247,7 @@ class Script:
247247
----
248248
<1> We are combining the instruction set to create a new Script object.
249249

250-
We will utilize this for Script evaluation later in this chapter.
250+
We will use this ability to combine Scripts for evaluation later in this chapter.
251251

252252
=== Stardard Scripts
253253

@@ -339,7 +339,7 @@ True
339339
<2> We can do this because of the $$__add__$$ method we created above.
340340
<3> We want to go through the instructions and see if the result is `True` or not.
341341

342-
Here is the method that we'll use for the *combined* instruction set (combination of ScriptSig of the current transaction and the ScriptPubKey of the previous transaction).
342+
Here is the method that we'll use for the _combined_ instruction set (combination of the ScriptPubKey of the previous transaction and the ScriptSig of the current transaction).
343343

344344
[source,python]
345345
----
@@ -395,7 +395,7 @@ class Script:
395395
====
396396
The code shown here is a little bit of a cheat as the combined Script is not executed this way exactly. The ScriptSig is evaluated separately from the ScriptPubKey as to not allow operations from ScriptSig to affect the ScriptPubKey instructions.
397397
398-
Specifically, the stack after all the ScriptSig instructions are evaluated are stored and then the ScriptPubkey is evaluated on its own.
398+
Specifically, the stack after all the ScriptSig instructions are evaluated are stored and then the ScriptPubkey instructions are evaluated on their own.
399399
====
400400

401401

@@ -451,7 +451,7 @@ def op_0(stack):
451451
return True
452452
----
453453

454-
Numbers being pushed onto the stack are essentially encoded into bytes and decoded when the numerical value is need.
454+
Numbers being pushed onto the stack are encoded into bytes and decoded from bytes when the numerical value is needed.
455455

456456
==== Exercise {counter:exercise}
457457

@@ -636,9 +636,9 @@ Figure out what this Script is doing:
636636
.Exercise 4
637637
image::exercise2.png[Exercise 4]
638638

639-
==== SHA1 Piñata
639+
==== Sha1 Piñata
640640

641-
In 2013, Peter Todd created a Script very similar to the exercise above and put some Bitcoins into it to create an economic incentive for people to find hash collisions. The donations reached 2.49153717 BTC and when Google actually found a hash collision for SHA1 in February of 2017 (https://security.googleblog.com/2017/02/announcing-first-sha1-collision.html), this Script was promptly redeemed. The transaction output was 2.48 coins which was $2848.88 USD at the time.
641+
In 2013, Peter Todd created a Script very similar to the Script in Exercise 4 and put some Bitcoins into it to create an economic incentive for people to find hash collisions. The donations reached 2.49153717 BTC and when Google actually found a hash collision for sha1 in February of 2017 (https://security.googleblog.com/2017/02/announcing-first-sha1-collision.html), this Script was promptly redeemed. The transaction output was 2.48 coins which was $2848.88 USD at the time.
642642

643643
Peter created more piñatas for sha256, hash256 and hash160, which add economic incentives to find collisions for these hashing functions.
644644

ch07.asciidoc

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ A full node can check the spentness of an input pretty easily, a light client ha
3636

3737
The second part of the validation is making sure that the sum of the inputs is greater than or equal to the sum of the outputs. This ensures that the transaction does not create new coins. The one exception is a Coinbase transaction which we'll study more in Chapter 9. The inputs don't have an amount, so this must be looked up on the blockchain. Once again, full nodes will have access to the amounts associated with the unspent output, but light clients will have to depend on full nodes to supply this information.
3838

39-
We covered how to calculate fees in Chapter 5. This validation step is essentially the same as checking that the fee is not negative (that is, creating money). Recall the last exercise in Chapter 5. The answer should have looked something like this:
39+
We covered how to calculate fees in Chapter 5. This validation step is essentially the same as checking that the fee is not negative (that is, creating money). Recall the last exercise in Chapter 5. The method `fee` looks like this:
4040

4141
[source,python]
4242
----
@@ -66,16 +66,16 @@ True
6666
<1> As with many other code samples, the ... is not literal, it's there to represent data that's too long to put into this book.
6767
<2> This only works because we're using Python. See Note.
6868

69-
If the fee is negative, we know that the `output_sum` is greater than the `input_sum`, which is another way of saying that this transaction is trying to create money out of thin air.
69+
If the fee is negative, we know that the `output_sum` is greater than the `input_sum`, which is another way of saying that this transaction is trying to create Bitcoins out of the ether.
7070

7171
[NOTE]
7272
.Value Overflow Incident
7373
====
74-
Back in 2010, there was a transaction that created 184 Billion new bitcoins. This is due to the fact that in C++, the value field is actually an integer and not an unsigned integer. That is, the value could be negative!
74+
Back in 2010, there was a transaction that created 184 billion new Bitcoins. This is due to the fact that in C++, the value field is a _signed_ integer and not an _unsigned_ integer. That is, the value could be negative!
7575
76-
The clever transaction passed all the checks with regard to fees and not creating new bitcoins, but only because the amount overflowed past the maximum number. Note 2^64^ is roughly 1.84 * 10^19^ satoshis, which is 184 Billion Bitcoins. The fee was negative by enough that the C++ code was essentially tricked into believing that the fee was actually positive by 0.1 BTC!
76+
The clever transaction passed all the checks including the one for not creating new bitcoins, but only because the output amounts overflowed past the maximum number. Note 2^64^ is roughly 1.84 * 10^19^ satoshis, which is 184 billion Bitcoins. The fee was negative by enough that the C++ code was tricked into believing that the fee was actually positive by 0.1 BTC!
7777
78-
The vulnerability is detailed in CVE-2010-5139 and was patched via soft-fork in Bitcoin 0.3.11. The transaction and the extra bitcoins it created was invalidated retroactively by a block reorganization, which is another way of saying a new chain of blocks that's longer was mined to replace it.
78+
The vulnerability is detailed in CVE-2010-5139 and was patched via soft-fork in Bitcoin Core 0.3.11. The transaction and the extra Bitcoins it created was invalidated retroactively by a block reorganization, which is another way of saying a new chain of blocks that's longer was mined to replace it.
7979
====
8080

8181
=== Checking the Signature
@@ -94,12 +94,12 @@ Perhaps the trickiest part of validating a transaction is the process of checkin
9494
True
9595
----
9696

97-
SEC public keys and DER signatures are in the stack when an instruction like `OP_CHECKSIG` is executed make getting the public key `P` and signature `(r,s)` pretty straightforward. The hard part is getting the actual signature hash `z`. You would think that this would be easy since you can just hash the transaction. But you can't do that since the signature is part of the ScriptSig and a signature can't sign itself.
97+
SEC public keys and DER signatures are in the stack when an instruction like `OP_CHECKSIG` is executed make getting the public key `P` and signature `(r,s)` pretty straightforward. The hard part is getting the actual signature hash `z`. A naive way to get the signature hash would be to hash the entire transaction. Unfortunately, we can't do that since the signature is part of the ScriptSig and a signature can't sign itself.
9898

9999
.Validation Start
100100
image::validation1.png[Validation Start]
101101

102-
Instead, what you need to do is to modify the transaction before actually signing it. That is, we have to compute a different `z` _for each input_. The procedure is as follows.
102+
Instead, what you need to do is to modify the transaction before actually signing it. That is, we have to compute a different signature hash, or `z`, _for each input_. The procedure is as follows.
103103

104104
==== Step 1: Empty all the ScriptSigs
105105

@@ -156,14 +156,13 @@ We can now make this transaction validation process into a method for `Tx`. Than
156156
[NOTE]
157157
.Quadratic Hashing
158158
====
159-
One of the reasons why this method of creating the signature hash is inefficient is because of the Quadratic Hashing problem. The Quadratic Hashing problem is the fact that calculating the signature hashes, or `z`'s varies quadratically with the number of inputs in a transaction. Specifically, the number of `hash256` operations for calculating the `z` will increase on a per-input basis, but in addition, the length of the transaction will increase, slowing down each hash256 operation as the entire signature hash will need to be calculated anew for each input.
159+
One of the reasons why this method of creating the signature hash is inefficient is because of the Quadratic Hashing problem. The Quadratic Hashing problem is the fact that calculating the signature hashes, or `z`'s increases quadratically with the number of inputs in a transaction. Specifically, the number of hash256 operations for calculating the `z` will increase on a per-input basis, but in addition, the length of the transaction will increase, slowing down each hash256 operation as the entire signature hash will need to be calculated anew for each input.
160160
161-
This was particularly obvious with the biggest transaction ever mined: `bb41a757f405890fb0f5856228e23b715702d714d59bf2b1feb70d8b2b4e3e08`. This transaction had 5569 inputs and 1 output and took many miners over a minute to validate as the signature hashes were so expensive to calculate.
161+
This was particularly obvious with the biggest transaction ever mined: `bb41a757f405890fb0f5856228e23b715702d714d59bf2b1feb70d8b2b4e3e08`. This transaction had 5569 inputs and 1 output and took many miners over a minute to validate as the signature hashes for the transaction were so expensive to calculate.
162162
163163
Segwit (Chapter 13) fixes this with a different way of calculating the signature hash, which is specified in BIP0143.
164164
====
165165

166-
167166
==== Exercise {counter:exercise}
168167

169168
Write the `sig_hash` method for the `Tx` class.

ch08.asciidoc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ We now need to special case the particular sequence of redeem_script, `OP_HASH16
267267
return False
268268
return True
269269
----
270-
<1> 0xa9 is `OP_HASH160`, 0x87 is `OP_EQUAL`. We're checking here that the next 3 instructions are exactly the pattern we're looking for.
270+
<1> `0xa9` is `OP_HASH160`, `0x87` is `OP_EQUAL`. We're checking here that the next 3 instructions are exactly the pattern we're looking for.
271271
<2> We know that this is `OP_HASH160`, so we just pop it off. Similarly, we know the next one is the 20-byte hash value and the third item is `OP_EQUAL`, which is what we tested for in the if statement above it.
272272
<3> We run the `OP_HASH160`, 20-byte hash push on the stack and `OP_EQUAL` as normal.
273273
<4> There should be a 1 remaining, which is what op_verify checks for (`OP_VERIFY` consumes 1 element and does not put anything back).
@@ -278,7 +278,7 @@ We now need to special case the particular sequence of redeem_script, `OP_HASH16
278278

279279
The nice thing about p2sh is that the RedeemScript can be as long as the largest single element from `OP_PUSHDATA2`, which is 520 bytes. Multisig is just one possibility. You can have Scripts that define more complicated logic like "2 of 3 of these keys or 5 of 7 of these other keys". The main feature of p2sh is that it's very flexible and at the same time reduces the UTXO set size by pushing the burden of storing part of the Script back to the user.
280280

281-
As we'll see in Chapter 13, p2sh will be used for backwards compatibility with Segwit.
281+
As we'll see in Chapter 13, p2sh is used to make Segwit backwards compatible.
282282

283283
==== Addresses
284284

ch09.asciidoc

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -380,13 +380,17 @@ Calculate the new bits given the first and last blocks of this 2016 block diffic
380380
Block 471744:
381381

382382
```
383-
000000203471101bbda3fe307664b3283a9ef0e97d9a38a7eacd8800000000000000000010c8aba8479bbaa5e0848152fd3c2289ca50e1c3e58c9a4faaafbdf5803c5448ddb845597e8b0118e43a81d3
383+
000000203471101bbda3fe307664b3283a9ef0e97d9a38a7eacd88000000000000000000
384+
10c8aba8479bbaa5e0848152fd3c2289ca50e1c3e58c9a4faaafbdf5803c5448ddb84559
385+
7e8b0118e43a81d3
384386
```
385387

386388
Block 473759:
387389

388390
```
389-
02000020f1472d9db4b563c35f97c428ac903f23b7fc055d1cfc26000000000000000000b3f449fcbe1bc4cfbcb8283a0d2c037f961a3fdf2b8bedc144973735eea707e1264258597e8b0118e5f00474
391+
02000020f1472d9db4b563c35f97c428ac903f23b7fc055d1cfc26000000000000000000
392+
b3f449fcbe1bc4cfbcb8283a0d2c037f961a3fdf2b8bedc144973735eea707e126425859
393+
7e8b0118e5f00474
390394
```
391395

392396
==== Exercise {counter:exercise}

code-ch05/Chapter5.ipynb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,9 @@
157157
"\n",
158158
"hex_transaction = '010000000456919960ac691763688d3d3bcea9ad6ecaf875df5339e148a1fc61c6ed7a069e010000006a47304402204585bcdef85e6b1c6af5c2669d4830ff86e42dd205c0e089bc2a821657e951c002201024a10366077f87d6bce1f7100ad8cfa8a064b39d4e8fe4ea13a7b71aa8180f012102f0da57e85eec2934a82a585ea337ce2f4998b50ae699dd79f5880e253dafafb7feffffffeb8f51f4038dc17e6313cf831d4f02281c2a468bde0fafd37f1bf882729e7fd3000000006a47304402207899531a52d59a6de200179928ca900254a36b8dff8bb75f5f5d71b1cdc26125022008b422690b8461cb52c3cc30330b23d574351872b7c361e9aae3649071c1a7160121035d5c93d9ac96881f19ba1f686f15f009ded7c62efe85a872e6a19b43c15a2937feffffff567bf40595119d1bb8a3037c356efd56170b64cbcc160fb028fa10704b45d775000000006a47304402204c7c7818424c7f7911da6cddc59655a70af1cb5eaf17c69dadbfc74ffa0b662f02207599e08bc8023693ad4e9527dc42c34210f7a7d1d1ddfc8492b654a11e7620a0012102158b46fbdff65d0172b7989aec8850aa0dae49abfb84c81ae6e5b251a58ace5cfeffffffd63a5e6c16e620f86f375925b21cabaf736c779f88fd04dcad51d26690f7f345010000006a47304402200633ea0d3314bea0d95b3cd8dadb2ef79ea8331ffe1e61f762c0f6daea0fabde022029f23b3e9c30f080446150b23852028751635dcee2be669c2a1686a4b5edf304012103ffd6f4a67e94aba353a00882e563ff2722eb4cff0ad6006e86ee20dfe7520d55feffffff0251430f00000000001976a914ab0c0b2e98b1ab6dbf67d4750b0a56244948a87988ac005a6202000000001976a9143c82d7df364eb6c75be8c80df2b3eda8db57397088ac46430600'\n",
159159
"\n",
160+
"# convert the hex_transaction to binary\n",
161+
"# create a stream using BytesIO\n",
162+
"# use Tx.parse to get the transaction object.\n",
160163
"# ScriptSig from second input\n",
161164
"# ScriptPubKey from first output\n",
162165
"# Amount from second output"

code-ch06/6.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ def op_hash160(stack):
1717
stack.append(h160)
1818
return True
1919

20+
2021
def op_checksig(stack, z):
2122
if len(stack) < 2:
2223
return False
@@ -63,7 +64,8 @@ def test_exercise_3(self):
6364
def test_exercise_4(self):
6465
hex_script_pubkey = '086e879169a77ca787'
6566
script_pubkey = Script.parse(BytesIO(bytes.fromhex(hex_script_pubkey)))
66-
hex_script_sig = 'fd86024d4001255044462d312e330a25e2e3cfd30a0a0a312030206f626a0a3c3c2f57696474682032203020522f4865696768742033203020522f547970652034203020522f537562747970652035203020522f46696c7465722036203020522f436f6c6f7253706163652037203020522f4c656e6774682038203020522f42697473506572436f6d706f6e656e7420383e3e0a73747265616d0affd8fffe00245348412d3120697320646561642121212121852fec092339759c39b1a1c63c4c97e1fffe017f46dc93a6b67e013b029aaa1db2560b45ca67d688c7f84b8c4c791fe02b3df614f86db1690901c56b45c1530afedfb76038e972722fe7ad728f0e4904e046c230570fe9d41398abe12ef5bc942be33542a4802d98b5d70f2a332ec37fac3514e74ddc0f2cc1a874cd0c78305a21566461309789606bd0bf3f98cda8044629a14d4001255044462d312e330a25e2e3cfd30a0a0a312030206f626a0a3c3c2f57696474682032203020522f4865696768742033203020522f547970652034203020522f537562747970652035203020522f46696c7465722036203020522f436f6c6f7253706163652037203020522f4c656e6774682038203020522f42697473506572436f6d706f6e656e7420383e3e0a73747265616d0affd8fffe00245348412d3120697320646561642121212121852fec092339759c39b1a1c63c4c97e1fffe017346dc9166b67e118f029ab621b2560ff9ca67cca8c7f85ba84c79030c2b3de218f86db3a90901d5df45c14f26fedfb3dc38e96ac22fe7bd728f0e45bce046d23c570feb141398bb552ef5a0a82be331fea48037b8b5d71f0e332edf93ac3500eb4ddc0decc1a864790c782c76215660dd309791d06bd0af3f98cda4bc4629b1'
67-
script_sig = Script.parse(BytesIO(bytes.fromhex(hex_script_sig)))
67+
collision1 = bytes.fromhex('255044462d312e330a25e2e3cfd30a0a0a312030206f626a0a3c3c2f57696474682032203020522f4865696768742033203020522f547970652034203020522f537562747970652035203020522f46696c7465722036203020522f436f6c6f7253706163652037203020522f4c656e6774682038203020522f42697473506572436f6d706f6e656e7420383e3e0a73747265616d0affd8fffe00245348412d3120697320646561642121212121852fec092339759c39b1a1c63c4c97e1fffe017f46dc93a6b67e013b029aaa1db2560b45ca67d688c7f84b8c4c791fe02b3df614f86db1690901c56b45c1530afedfb76038e972722fe7ad728f0e4904e046c230570fe9d41398abe12ef5bc942be33542a4802d98b5d70f2a332ec37fac3514e74ddc0f2cc1a874cd0c78305a21566461309789606bd0bf3f98cda8044629a1')
68+
collision2 = bytes.fromhex('255044462d312e330a25e2e3cfd30a0a0a312030206f626a0a3c3c2f57696474682032203020522f4865696768742033203020522f547970652034203020522f537562747970652035203020522f46696c7465722036203020522f436f6c6f7253706163652037203020522f4c656e6774682038203020522f42697473506572436f6d706f6e656e7420383e3e0a73747265616d0affd8fffe00245348412d3120697320646561642121212121852fec092339759c39b1a1c63c4c97e1fffe017346dc9166b67e118f029ab621b2560ff9ca67cca8c7f85ba84c79030c2b3de218f86db3a90901d5df45c14f26fedfb3dc38e96ac22fe7bd728f0e45bce046d23c570feb141398bb552ef5a0a82be331fea48037b8b5d71f0e332edf93ac3500eb4ddc0decc1a864790c782c76215660dd309791d06bd0af3f98cda4bc4629b1')
69+
script_sig = Script([collision1, collision2])
6870
combined_script = script_sig + script_pubkey
6971
self.assertEqual(combined_script.evaluate(0), True)

0 commit comments

Comments
 (0)