<jupyter_start><jupyter_text>Exercise 1 1.1. Make [this test](/edit/session6/tx.py) pass```tx.py:TxTest:test_is_coinbase```<jupyter_code># Exercise 1.1

reload(tx)
run(tx.TxTest('test_is_coinbase'))<jupyter_output>.
----------------------------------------------------------------------
Ran 1 test in 0.001s

OK<jupyter_text>Exercise 2 2.1. Parse the Genesis Block Coinbase Transaction and print out the scriptSig's third item```01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4d04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73ffffffff0100f2052a01000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000``` 2.2. Make [this test](/edit/session6/tx.py) pass```tx.py:TxTest:test_coinbase_height```<jupyter_code># Exercise 2.1

hex_tx = '01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4d04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73ffffffff0100f2052a01000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000'

# create stream with BytesIO and bytes.fromhex
stream = BytesIO(bytes.fromhex(hex_tx))
# parse the coinbase transaction
coinbase = Tx.parse(stream)
# print the first input's script_sig's third instruction
print(coinbase.tx_ins[0].script_sig.instructions[2])
# Exercise 2.2

reload(tx)
run(tx.TxTest('test_coinbase_height'))<jupyter_output>.
----------------------------------------------------------------------
Ran 1 test in 0.001s

OK<jupyter_text>Exercise 3 3.1. Find the output address corresponding to this ScriptPubKey```<KEY>```Remember the structure of pay-to-pubkey-hash (p2pkh) which has `OP_DUP OP_HASH160  OP_EQUALVERIFY OP_CHECKSIG`.You need to grab the hash160 and turn that into an address.<jupyter_code># Exercise 3.1

hex_script_pubkey = '<KEY>'

# BytesIO(bytes.fromhex) to get the stream
stream = BytesIO(bytes.fromhex(hex_script_pubkey))
# parse with Script
script_pubkey = Script.parse(stream)
# get the address using address() on the script_pubkey
print(script_pubkey.address())<jupyter_output>15hZo812Lx266Dot6T52krxpnhrNiaqHya<jupyter_text>Exercise 4 4.1. What is the hash256 of this block? Notice anything?```020000208ec39428b17323fa0ddec8e887b4a7c53b8c0a0a220cfd0000000000000000005b0750fce0a889502d40508d39576821155e9c9e3f5c3157f961db38fd8b25be1e77a759e93c0118a4ffd71d``` 4.2. Make [these tests](/edit/session6/block.py) pass.```block.py:BlockTest:test_parseblock.py:BlockTest:test_serializeblock.py:BlockTest:test_hash```<jupyter_code># Exercise 4.1

hex_block = '020000208ec39428b17323fa0ddec8e887b4a7c53b8c0a0a220cfd0000000000000000005b0750fce0a889502d40508d39576821155e9c9e3f5c3157f961db38fd8b25be1e77a759e93c0118a4ffd71d'

# bytes.fromhex to get the binary
bin_block = bytes.fromhex(hex_block)
# hash256 the result
result = hash256(bin_block)
# hex() to see what it looks like
print(result.hex())
# Exercise 4.2

reload(block)
run(block.BlockTest('test_parse'))
run(block.BlockTest('test_serialize'))
run(block.BlockTest('test_hash'))
# Version Signaling Example

from block import Block

hex_block = '020000208ec39428b17323fa0ddec8e887b4a7c53b8c0a0a220cfd0000000000000000005b0750fce0a889502d40508d39576821155e9c9e3f5c3157f961db38fd8b25be1e77a759e93c0118a4ffd71d'

bin_block = bytes.fromhex(hex_block)
stream = BytesIO(bin_block)
b = Block.parse(stream)
version = b.version
print('BIP9: {}'.format(version >> 29 == 0b001))
print('BIP91: {}'.format(version >> 4 & 1 == 1))
print('BIP141: {}'.format(version >> 1 & 1 == 1))<jupyter_output>BIP9: True
BIP91: False
BIP141: True<jupyter_text>Exercise 5 5.1. Make [these tests](/edit/session6/block.py) pass.```block.py:BlockTest:test_bip9block.py:BlockTest:test_bip91block.py:BlockTest:test_bip141```<jupyter_code># Exercise 5.1

reload(block)
run(block.BlockTest('test_bip9'))
run(block.BlockTest('test_bip91'))
run(block.BlockTest('test_bip141'))
# Calculating Target from Bits Example

bits = bytes.fromhex('e93c0118')
exponent = bits[-1]
coefficient = little_endian_to_int(bits[:-1])
target = coefficient*256**(exponent-3)
print('{:x}'.format(target).zfill(64))
# Calculating Difficulty from Target Example

from helper import little_endian_to_int

bits = bytes.fromhex('e93c0118')
exponent = bits[-1]
coefficient = little_endian_to_int(bits[:-1])
target = coefficient * 256**(exponent - 3)

min_target = 0xffff * 256**(0x1d - 3)
difficulty = min_target // target
print(difficulty)<jupyter_output>888171856257<jupyter_text>Exercise 6 6.1. Calculate the target and difficulty for these bits:```f2881718```Bits to target formula is \\(\texttt{coefficient}\cdot256^{(\texttt{exponent}-3)}\\) where coefficient is the first three bytes in little endian and exponent is the last byte.Target to Difficulty formula is \\(\texttt{difficulty} = \texttt{min} / \texttt{target}\\)where \\(\texttt{min} = \texttt{0xffff}\cdot256^{(\texttt{0x1d}-3)}\\) 6.2. Make [this test](/edit/session6/block.py) pass.```block.py:BlockTest:test_target```<jupyter_code># Exercise 6.1

hex_bits = 'f2881718'

# bytes.fromhex to get the bits
bits = bytes.fromhex(hex_bits)
# last byte is exponent
exponent = bits[-1]
# first three bytes are the coefficient in little endian
coefficient = little_endian_to_int(bits[:-1])
# plug into formula coefficient * 256^(exponent-3) to get the target
target = coefficient * 256**(exponent-3)
# print target using print('{:x}'.format(target).zfill(64))
print('{:x}'.format(target).zfill(64))

# difficulty formula is 0xffff * 256**(0x1d - 3) / target
difficulty = 0xffff * 256**(0x1d - 3) // target
# print the difficulty
print(difficulty)
# Exercise 6.2

reload(block)
run(block.BlockTest('test_target'))<jupyter_output>.
----------------------------------------------------------------------
Ran 1 test in 0.001s

OK<jupyter_text>Exercise 7 7.1.Validate the proof-of-work for this block```04000000fbedbbf0cfdaf278c094f187f2eb987c86a199da22bbb20400000000000000007b7697b29129648fa08b4bcd13c9d5e60abb973a1efac9c8d573c71c807c56c3d6213557faa80518c3737ec1```Check that the proof-of-work (hash256 interpreted as a little-endian number) is lower than the target. 7.2. Make [this test](/edit/session6/block.py) pass.```block.py:BlockTest:test_check_pow```<jupyter_code># Exercise 7.1

from block import Block

hex_block = '04000000fbedbbf0cfdaf278c094f187f2eb987c86a199da22bbb20400000000000000007b7697b29129648fa08b4bcd13c9d5e60abb973a1efac9c8d573c71c807c56c3d6213557faa80518c3737ec1'

# bytes.fromhex to get the binary block
bin_block = bytes.fromhex(hex_block)
# make a stream using BytesIO
stream = BytesIO(bin_block)
# parse the Block
b = Block.parse(stream)

# hash256 the serialization
h256 = hash256(b.serialize())
# interpret the result as a number in little endian
proof = little_endian_to_int(h256)
# get the target
target = b.target()
# check proof of work < target
print(proof < target)
# Exercise 7.2

reload(block)
run(block.BlockTest('test_check_pow'))<jupyter_output>.
----------------------------------------------------------------------
Ran 1 test in 0.001s

OK
{'fraction_non_alphanumeric': 0.13978201634877385, 'fraction_numerical': 0.19346049046321526, 'mean_word_length': 5.932011331444759, 'pattern_counts': {'":': 0, '<': 26, '<?xml version=': 0, '>': 30, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 15, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '7', 'dir': 'jupyter-structured-clean-dedup', 'id': '314446', 'license': 'BSD-2-Clause', 'n_tokens_mistral': 3644, 'n_tokens_neox': 2734, 'n_words': 473, 'path': 'session6/complete/session6.ipynb', 'repo_name': 'robbaltzer/pb-exercises', 'size': '7434'}