From 4b3a272c9a541e400c34c96d5af64a32311b7fa5 Mon Sep 17 00:00:00 2001 From: kouloumos Date: Sun, 2 Apr 2023 17:35:31 +0300 Subject: [PATCH 1/2] simplify notebook setup with configuration file allow for a single point of configuration by: - moving all notebooks to the root dir while switching to a ". " prefix to keep the structure. - adding a configuration file `config.ini` in which the user can define their Bitcoin Core directory - adding `setup.py` as a single import that takes care of all the configurations required for the initial setup of the notebook. --- ...nb => 0.1-elliptic-curve-math-review.ipynb | 108 ++--- ...unctions.ipynb => 0.2-hash-functions.ipynb | 86 +--- ...n-script.ipynb => 0.3-bitcoin-script.ipynb | 8 +- .../addresses.ipynb => 0.4-addresses.ipynb | 149 ++----- ...rst-btc-tx.ipynb => 1.1-first-btc-tx.ipynb | 27 +- .../p2pkh.ipynb => 1.2-p2pkh.ipynb | 389 +++--------------- ...-multisig.ipynb => 1.3-p2sh-multisig.ipynb | 241 ++--------- .../p2wpkh.ipynb => 2.1-p2wpkh.ipynb | 269 ++---------- ...ipynb => 2.2-multiple-inputs-outputs.ipynb | 312 ++------------ ...g.ipynb => 2.3-p2wsh-2-of-2-multisig.ipynb | 257 ++---------- ...pynb => 3.1-schnorr-sig-and-taptweak.ipynb | 65 +-- ...taptree.ipynb => 3.2-taproot-taptree.ipynb | 52 +-- ...pynb => 3.3-p2tr-key-and-script-path.ipynb | 198 +++------ ...ution.ipynb => 4.1-sighash-evolution.ipynb | 87 ++-- ...ash-flags.ipynb => 4.2-sighash-flags.ipynb | 150 ++----- ...b => 5.1.transaction-level-timelocks.ipynb | 167 ++------ ....ipynb => 5.2-script-level-timelocks.ipynb | 200 ++------- README.md | 13 +- config.ini | 6 + functions/__init__.py | 1 + functions/setup_notebook.py | 22 + 21 files changed, 491 insertions(+), 2316 deletions(-) rename appendix/elliptic-curve-math-review.ipynb => 0.1-elliptic-curve-math-review.ipynb (78%) rename appendix/hash-functions.ipynb => 0.2-hash-functions.ipynb (86%) rename appendix/bitcoin-script.ipynb => 0.3-bitcoin-script.ipynb (98%) rename appendix/addresses.ipynb => 0.4-addresses.ipynb (86%) rename chapter1-legacy/first-btc-tx.ipynb => 1.1-first-btc-tx.ipynb (97%) rename chapter1-legacy/p2pkh.ipynb => 1.2-p2pkh.ipynb (68%) rename chapter1-legacy/p2sh-multisig.ipynb => 1.3-p2sh-multisig.ipynb (64%) rename chapter2-segwitv0/p2wpkh.ipynb => 2.1-p2wpkh.ipynb (66%) rename chapter2-segwitv0/multiple-inputs-outputs.ipynb => 2.2-multiple-inputs-outputs.ipynb (59%) rename chapter2-segwitv0/p2wsh-2-of-2-multisig.ipynb => 2.3-p2wsh-2-of-2-multisig.ipynb (64%) rename chapter3-taproot/schnorr-sig-and-taptweak.ipynb => 3.1-schnorr-sig-and-taptweak.ipynb (89%) rename chapter3-taproot/taproot-taptree.ipynb => 3.2-taproot-taptree.ipynb (86%) rename chapter3-taproot/p2tr-key-and-script-path.ipynb => 3.3-p2tr-key-and-script-path.ipynb (82%) rename chapter4-sighash/sighash-evolution.ipynb => 4.1-sighash-evolution.ipynb (92%) rename chapter4-sighash/sighash-flags.ipynb => 4.2-sighash-flags.ipynb (79%) rename chapter5-timelocks/transaction-level-timelocks.ipynb => 5.1.transaction-level-timelocks.ipynb (80%) rename chapter5-timelocks/script-level-timelocks.ipynb => 5.2-script-level-timelocks.ipynb (74%) create mode 100644 config.ini create mode 100644 functions/setup_notebook.py diff --git a/appendix/elliptic-curve-math-review.ipynb b/0.1-elliptic-curve-math-review.ipynb similarity index 78% rename from appendix/elliptic-curve-math-review.ipynb rename to 0.1-elliptic-curve-math-review.ipynb index 1c70694..8b31334 100644 --- a/appendix/elliptic-curve-math-review.ipynb +++ b/0.1-elliptic-curve-math-review.ipynb @@ -1,40 +1,12 @@ { "cells": [ - { - "cell_type": "markdown", - "id": "3ca0e780", - "metadata": {}, - "source": [ - "## Setup \n", - "\n", - "### Requirements\n", - "For this exercise we'll need Bitcoin Core. This notebook has been tested with [v24.0.1](https://github.com/bitcoin/bitcoin/releases/tag/v24.0.1).\n", - "\n", - "Below, set the paths for:\n", - "1. The bitcoin core functional test framework directory.\n", - "2. The directory containing bitcoin-tx-tutorial.\n", - "\n", - "**You'll need to edit these next two lines for your local setup.**" - ] - }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "id": "752d005e", "metadata": {}, "outputs": [], "source": [ - "path_to_bitcoin_functional_test = \"/Users/dariuscognac/bitcoin/test/functional\"\n", - "path_to_bitcoin_tx_tutorial = \"/Users/dariuscognac/Documents/Github/bitcoin-tx-tutorial\"\n", - "\n", - "import sys\n", - "\n", - "# Add the functional test framework to our PATH\n", - "sys.path.insert(0, path_to_bitcoin_functional_test)\n", - "from test_framework.test_shell import TestShell\n", - "\n", - "# Add the bitcoin-tx-tutorial functions to our PATH\n", - "sys.path.insert(0, path_to_bitcoin_tx_tutorial)\n", "from functions import *\n", "from functions.bip_0340_reference import *" ] @@ -101,7 +73,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "id": "2f212482", "metadata": {}, "outputs": [], @@ -120,18 +92,10 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "id": "54b533fc", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "pubkey: (55066263022277343669578718895168534326250603453777594175500187360389116729240, 32670510020758816978083085130507043184471273380659243275938904335757337482424)\n" - ] - } - ], + "outputs": [], "source": [ "privkey_int = int_from_bytes(privkey)\n", "pubkey = point_mul(G, privkey_int)\n", @@ -180,19 +144,10 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "id": "468b6795", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Uncompressed pubkey: 0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8\n", - "Compressed pubkey: 0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798\n" - ] - } - ], + "outputs": [], "source": [ "# using the same privkey value from above\n", "pubkey = point_mul(G, privkey_int)\n", @@ -226,23 +181,10 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "id": "a56fe6dc", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "original_pubkey: (115780575977492633039504758427830329241728645270042306223540962614150928364886, 78735063515800386211891312544505775871260717697865196436804966483607426560663)\n", - "y coordinate is odd\n", - "\n", - "Negating the private key..\n", - "new_pubkey: (115780575977492633039504758427830329241728645270042306223540962614150928364886, 37057025721515809211679672464182131982009266967775367602652617524301408111000)\n", - "y coordinate is even\n" - ] - } - ], + "outputs": [], "source": [ "# This private key has been chosen as it'll produce a public key with an odd y-coordinate\n", "original_privkey = bytes.fromhex(\"0000000000000000000000000000000000000000000000000000000000000006\")\n", @@ -289,20 +231,10 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "id": "c7cd1861", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Pubkey generated from summing private keys: (112711660439710606056748659173929673102114977341539408544630613555209775888121, 25583027980570883691656905877401976406448868254816295069919888960541586679410)\n", - "Pubkey generated from summing public keys: (112711660439710606056748659173929673102114977341539408544630613555209775888121, 25583027980570883691656905877401976406448868254816295069919888960541586679410)\n", - "Success!\n" - ] - } - ], + "outputs": [], "source": [ "# Define private keys and convert to int\n", "privkey_a = bytes.fromhex(\"0000000000000000000000000000000000000000000000000000000000000001\")\n", @@ -323,11 +255,27 @@ "assert(pubkey_ab == pubkey2)\n", "print(\"Success!\")" ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "10adecc4", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fa1bf7c9", + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -341,7 +289,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.0" + "version": "3.8.16" } }, "nbformat": 4, diff --git a/appendix/hash-functions.ipynb b/0.2-hash-functions.ipynb similarity index 86% rename from appendix/hash-functions.ipynb rename to 0.2-hash-functions.ipynb index ccf02aa..c7e301a 100644 --- a/appendix/hash-functions.ipynb +++ b/0.2-hash-functions.ipynb @@ -21,18 +21,10 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "id": "1da041f0", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "5f78c33274e43fa9de5659265c1d917e25c03722dcb0b8d27db8d5feaa813953\n" - ] - } - ], + "outputs": [], "source": [ "import hashlib\n", "\n", @@ -52,18 +44,10 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "id": "51287990", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "226821c2f5423e11fe9af68bd285c249db2e4b5a\n" - ] - } - ], + "outputs": [], "source": [ "output = hashlib.new('ripemd160', data).digest()\n", "print(output.hex())" @@ -82,7 +66,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "id": "f30433e5", "metadata": {}, "outputs": [], @@ -106,18 +90,10 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "id": "f4e6ca67", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "00000000000000001e8d6829a8a21adc5d38d0a473b144b6765798e61f98bd1d\n" - ] - } - ], + "outputs": [], "source": [ "# The block header from block 125552\n", "header_hex = (\n", @@ -152,7 +128,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "id": "0288b375", "metadata": {}, "outputs": [], @@ -175,18 +151,10 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "id": "41c06d0b", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "ca61e52e881d41374e640f819cd118cc153b21a7\n" - ] - } - ], + "outputs": [], "source": [ "pubkey = bytes.fromhex(\"11\")\n", "pkh = hash160(pubkey)\n", @@ -229,21 +197,10 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "id": "a87080b9", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'596711e622bf8dc1d6b892863d56504003f39bb0ee482d6d1715e590e58b35bc'" - ] - }, - "execution_count": 7, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "tx_hex = \"0100000001399434f3943d776250cf4b4c2b3fa2cac259dd5551a822e1976d25a2d9e0231d010000006b483045022100a628f785b81d04e3b5d2f4a554c839acab64215935a0558dda1e33d0120dada30220616acf4b1c796cebe11f30dd53bbb4354899d924a4791c8fd7c0ae3da0c4782c0121034f355bdcb7cc0af728ef3cceb9615d90684bb5b2ca5f859ab0f0b704075871aaffffffff0280d1f008000000001976a9143bc28d6d92d9073fb5e3adf481795eaf446bceed88ac80f0fa02000000001976a914531260aa2a199e228c537dfa42c82bea2c7c1f4d88ac00000000\"\n", "tx = bytes.fromhex(tx_hex)\n", @@ -261,21 +218,10 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "id": "28392546", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'fc7250a211deddc70ee5a2738de5f07817351cef'" - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "pk = bytes.fromhex(\"034f355bdcb7cc0af728ef3cceb9615d90684bb5b2ca5f859ab0f0b704075871aa\")\n", "hash160(pk).hex()" @@ -292,7 +238,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -306,7 +252,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.0" + "version": "3.8.16" } }, "nbformat": 4, diff --git a/appendix/bitcoin-script.ipynb b/0.3-bitcoin-script.ipynb similarity index 98% rename from appendix/bitcoin-script.ipynb rename to 0.3-bitcoin-script.ipynb index f7260e9..8a7a60b 100644 --- a/appendix/bitcoin-script.ipynb +++ b/0.3-bitcoin-script.ipynb @@ -40,7 +40,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "id": "881e4514", "metadata": {}, "outputs": [], @@ -76,7 +76,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "id": "d8c9fd61", "metadata": {}, "outputs": [], @@ -204,7 +204,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -218,7 +218,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.0" + "version": "3.8.16" } }, "nbformat": 4, diff --git a/appendix/addresses.ipynb b/0.4-addresses.ipynb similarity index 86% rename from appendix/addresses.ipynb rename to 0.4-addresses.ipynb index f4ed5b2..6d2436d 100644 --- a/appendix/addresses.ipynb +++ b/0.4-addresses.ipynb @@ -1,42 +1,13 @@ { "cells": [ - { - "cell_type": "markdown", - "id": "9e29d9d6", - "metadata": {}, - "source": [ - "## Setup \n", - "\n", - "### Requirements\n", - "For this exercise we'll need Bitcoin Core. This notebook has been tested with [v24.0.1](https://github.com/bitcoin/bitcoin/releases/tag/v24.0.1).\n", - "\n", - "Below, set the paths for:\n", - "1. The bitcoin core functional test framework directory.\n", - "2. The directory containing bitcoin-tx-tutorial.\n", - "\n", - "**You'll need to edit these next two lines for your local setup.**" - ] - }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "id": "4230eff0", "metadata": {}, "outputs": [], "source": [ - "path_to_bitcoin_functional_test = \"/Users/dariuscognac/bitcoin/test/functional\"\n", - "path_to_bitcoin_tx_tutorial = \"/Users/dariuscognac/Documents/Github/bitcoin-tx-tutorial\"\n", - "\n", - "import sys\n", - "\n", - "# Add the functional test framework to our PATH\n", - "sys.path.insert(0, path_to_bitcoin_functional_test)\n", - "from test_framework.test_shell import TestShell\n", - "\n", - "# Add the bitcoin-tx-tutorial functions to our PATH\n", - "sys.path.insert(0, path_to_bitcoin_tx_tutorial)\n", "from functions import *\n", - "\n", "import json" ] }, @@ -114,7 +85,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "id": "16534779", "metadata": {}, "outputs": [], @@ -139,18 +110,10 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "id": "3f26d1a8", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Base58 P2PKH address: mo6CPsdW8EsnWdmSSCrQ6225VVDtpMBTug\n" - ] - } - ], + "outputs": [], "source": [ "pubkey = bytes.fromhex(\"02466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f27\")\n", "\n", @@ -182,7 +145,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "id": "f2b5fa2d", "metadata": {}, "outputs": [], @@ -215,7 +178,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "id": "e1e21810", "metadata": {}, "outputs": [], @@ -247,20 +210,12 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "id": "7c0f0bf5", "metadata": { "code_folding": [] }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Base58 P2SH address: 2MuXogRGTh7uADB2wKBqFcsPTprVKnChJe6\n" - ] - } - ], + "outputs": [], "source": [ "# Take the hash (hash160) of the redeemScript\n", "script_hash = hash160(redeemScript)\n", @@ -287,7 +242,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "id": "e4a880ac", "metadata": {}, "outputs": [], @@ -314,20 +269,10 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "id": "91cfe0fc", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Is checksum valid: True\n", - "prefix: 0x6f\n", - "pubkey hash: 531260aa2a199e228c537dfa42c82bea2c7c1f4d\n" - ] - } - ], + "outputs": [], "source": [ "address = 'mo6CPsdW8EsnWdmSSCrQ6225VVDtpMBTug'\n", "address_decoded = decode_base58(address)\n", @@ -366,18 +311,10 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": null, "id": "bcdd6a19", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "scriptPubkey: 76a914531260aa2a199e228c537dfa42c82bea2c7c1f4d88ac\n" - ] - } - ], + "outputs": [], "source": [ "scriptPubkey = bytes.fromhex(\"76a914\" + pk_hash.hex() + \"88ac\")\n", "print(\"scriptPubkey: \", scriptPubkey.hex())" @@ -395,7 +332,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": null, "id": "2278c905", "metadata": {}, "outputs": [], @@ -414,18 +351,10 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": null, "id": "17eb43bc", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Bech32 P2WPKH address: tb1q0n68nma39lfj2swn73hlq4435gc88nkpwvn976\n" - ] - } - ], + "outputs": [], "source": [ "pubkey = bytes.fromhex(\"02466d7fcae563e5cc09a0d1870bb580344804617879a14949cf22285f1bae3f27\")\n", "\n", @@ -455,18 +384,10 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": null, "id": "ac722f9b", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Bech32 P2WSH address: bc1qpy8yjjs2l5neewx722mxve9w6m77zqsu7rldukggseflhwralerqdt85qc\n" - ] - } - ], + "outputs": [], "source": [ "# Note that unlike P2SH which uses HASH160, for P2WSH we use SHA256\n", "script_hash = hashlib.sha256(redeemScript).digest()\n", @@ -498,18 +419,10 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": null, "id": "be624b13", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Bech32m P2TR address: bcrt1pzpvm7fnxpqzvakdr9p4pvjta0ecxjtg5mszwzgsv9kl0xenmwnmse95m37\n" - ] - } - ], + "outputs": [], "source": [ "# Note that unlike P2SH which uses HASH160, for P2WSH we use SHA256\n", "x_only_pubkey = bytes.fromhex(\"1059bf26660804ced9a3286a16497d7e70692d14dc04e1220c2dbef3667b74f7\")\n", @@ -536,20 +449,10 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": null, "id": "84cc50aa", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Segwit version: 1\n", - "Script data: a4af82136997976431f2c76a1179662f04c14f8fdfd24de49a0df51496e733d1\n", - "scriptPubKey: 0120a4af82136997976431f2c76a1179662f04c14f8fdfd24de49a0df51496e733d1\n" - ] - } - ], + "outputs": [], "source": [ "s = bech32.decode('bcrt', 'bcrt1p5jhcyymfj7tkgv0jca4pz7tx9uzvznu0mlfymey6ph63f9h8x0gs7683vc')\n", "\n", @@ -577,7 +480,7 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": null, "id": "170b511d", "metadata": {}, "outputs": [], @@ -624,7 +527,7 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": null, "id": "acb05aaa", "metadata": { "code_folding": [ @@ -676,7 +579,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -690,7 +593,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.0" + "version": "3.8.16" } }, "nbformat": 4, diff --git a/chapter1-legacy/first-btc-tx.ipynb b/1.1-first-btc-tx.ipynb similarity index 97% rename from chapter1-legacy/first-btc-tx.ipynb rename to 1.1-first-btc-tx.ipynb index d08a50a..916a7fb 100644 --- a/chapter1-legacy/first-btc-tx.ipynb +++ b/1.1-first-btc-tx.ipynb @@ -193,19 +193,10 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "id": "16f32926", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Two rounds of SHA256 on the raw tx gives us: 169e1e83e930853391bc6f35f605c6754cfead57cf8387639d3b4096c54f18f4\n", - "Reversing the bytes to little endian: f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16\n" - ] - } - ], + "outputs": [], "source": [ "# store the transaction as bytes \n", "raw_tx = bytes.fromhex('0100000001c997a5e56e104102fa209c6a852dd90660a20b2d9c352423edce25857fcd3704000000004847304402204e45e16932b8af514961a1d3a1a25fdf3f4f7732e9d624c6c61548ab5fb8cd410220181522ec8eca07de4860a4acdd12909d831cc56cbbac4622082221a8768d1d0901ffffffff0200ca9a3b00000000434104ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84cac00286bee0000000043410411db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5cb2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b412a3ac00000000')\n", @@ -242,20 +233,10 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "id": "365e6ceb", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "size: 275\n", - "weight: 1100\n", - "vsize: 275\n" - ] - } - ], + "outputs": [], "source": [ "size = len(raw_tx)\n", "print(\"size: \", size)\n", diff --git a/chapter1-legacy/p2pkh.ipynb b/1.2-p2pkh.ipynb similarity index 68% rename from chapter1-legacy/p2pkh.ipynb rename to 1.2-p2pkh.ipynb index e00b0a0..afea35d 100644 --- a/chapter1-legacy/p2pkh.ipynb +++ b/1.2-p2pkh.ipynb @@ -1,5 +1,15 @@ { "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from functions import *\n", + "import json" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -26,32 +36,6 @@ " - Bitcoin Script basics - '[Bitcoin Script chapter](https://github.com/DariusParvin/bitcoin-tx-tutorial/blob/main/appendix/Bitcoin%20Script.ipynb)'" ] }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Setup \n", - "\n", - "### Requirements\n", - "For this exercise we'll need Bitcoin Core. This notebook has been tested with [v24.0.1](https://github.com/bitcoin/bitcoin/releases/tag/v24.0.1).\n", - "\n", - "Below, set the paths for:\n", - "1. The bitcoin core functional test framework directory.\n", - "2. The directory containing bitcoin-tx-tutorial.\n", - "\n", - "**You'll need to edit these next two lines for your local setup.**" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "path_to_bitcoin_functional_test = \"/Users/dariuscognac/bitcoin/test/functional\"\n", - "path_to_bitcoin_tx_tutorial = \"/Users/dariuscognac/Documents/Github/bitcoin-tx-tutorial\"" - ] - }, { "cell_type": "markdown", "metadata": {}, @@ -62,38 +46,11 @@ }, { "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "import sys\n", - "\n", - "# Add the functional test framework to our PATH\n", - "sys.path.insert(0, path_to_bitcoin_functional_test)\n", - "from test_framework.test_shell import TestShell\n", - "\n", - "# Add the bitcoin-tx-tutorial functions to our PATH\n", - "sys.path.insert(0, path_to_bitcoin_tx_tutorial)\n", - "from functions import *\n", - "\n", - "import json" - ] - }, - { - "cell_type": "code", - "execution_count": 3, + "execution_count": null, "metadata": { "code_folding": [] }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2022-12-06T21:11:26.463000Z TestFramework (INFO): Initializing test directory /var/folders/r5/yk8yg2xs1gs8xzkn5l8vr72w0000gn/T/bitcoin_func_test_zlfn_arb\n" - ] - } - ], + "outputs": [], "source": [ "# Setup our regtest environment\n", "test = TestShell().setup(\n", @@ -113,7 +70,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -147,17 +104,9 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "sender's p2pkh address: n4XmX91N5FfccY678vaG1ELNtXh6skVES7\n" - ] - } - ], + "outputs": [], "source": [ "sender_privkey = bytes.fromhex(\"1111111111111111111111111111111111111111111111111111111111111111\")\n", "sender_pubkey = privkey_to_pubkey(sender_privkey)\n", @@ -174,17 +123,9 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "5eff481de26cfefcbb288e945fc9cf95a60dd837fda51e31fec4c5e2e20ee044\n" - ] - } - ], + "outputs": [], "source": [ "txid_to_spend = node.sendtoaddress(sender_p2pkh_addr, 2.001)\n", "print(txid_to_spend)" @@ -199,64 +140,9 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{\n", - " \"txid\": \"5eff481de26cfefcbb288e945fc9cf95a60dd837fda51e31fec4c5e2e20ee044\",\n", - " \"hash\": \"c9f2deb9de45c33dce1d047776cf3e66b8371415bafaa23cee97289fe8ee5271\",\n", - " \"version\": 2,\n", - " \"size\": 228,\n", - " \"vsize\": 147,\n", - " \"weight\": 585,\n", - " \"locktime\": 101,\n", - " \"vin\": [\n", - " {\n", - " \"txid\": \"0fac9344999273a988cf86b683489543789b910624b5fdc22752bbb0a98a6d24\",\n", - " \"vout\": 0,\n", - " \"scriptSig\": {\n", - " \"asm\": \"\",\n", - " \"hex\": \"\"\n", - " },\n", - " \"txinwitness\": [\n", - " \"304402201835791520077ef3552179ee3c68b44180ea9ce6d7fa7ed438e15db341233c0402205c3265d27f90a0ac9ca6a342ec6e52faa38408dccb862587fed99d23d2d48a6401\",\n", - " \"024a2083a1938578d91173e6c44e72bd599b5b8d69fe9ce34c3e6f23ffbe4a058a\"\n", - " ],\n", - " \"sequence\": 4294967293\n", - " }\n", - " ],\n", - " \"vout\": [\n", - " {\n", - " \"value\": \"47.99897060\",\n", - " \"n\": 0,\n", - " \"scriptPubKey\": {\n", - " \"asm\": \"OP_DUP OP_HASH160 76ce045c03f7254d14ba15a9b70a8103004e05e0 OP_EQUALVERIFY OP_CHECKSIG\",\n", - " \"desc\": \"addr(mrM8q1CAXCQT6MDGXq6WMypkPqFCa8xvBg)#jwhsgzw6\",\n", - " \"hex\": \"76a91476ce045c03f7254d14ba15a9b70a8103004e05e088ac\",\n", - " \"address\": \"mrM8q1CAXCQT6MDGXq6WMypkPqFCa8xvBg\",\n", - " \"type\": \"pubkeyhash\"\n", - " }\n", - " },\n", - " {\n", - " \"value\": \"2.00100000\",\n", - " \"n\": 1,\n", - " \"scriptPubKey\": {\n", - " \"asm\": \"OP_DUP OP_HASH160 fc7250a211deddc70ee5a2738de5f07817351cef OP_EQUALVERIFY OP_CHECKSIG\",\n", - " \"desc\": \"addr(n4XmX91N5FfccY678vaG1ELNtXh6skVES7)#n2xufj4n\",\n", - " \"hex\": \"76a914fc7250a211deddc70ee5a2738de5f07817351cef88ac\",\n", - " \"address\": \"n4XmX91N5FfccY678vaG1ELNtXh6skVES7\",\n", - " \"type\": \"pubkeyhash\"\n", - " }\n", - " }\n", - " ]\n", - "}\n" - ] - } - ], + "outputs": [], "source": [ "raw_tx = node.getrawtransaction(txid_to_spend)\n", "decoded = node.decoderawtransaction(raw_tx)\n", @@ -273,17 +159,9 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "index to spend from: 1\n" - ] - } - ], + "outputs": [], "source": [ "if decoded[\"vout\"][0][\"scriptPubKey\"][\"address\"] == sender_p2pkh_addr:\n", " index_to_spend = 0\n", @@ -303,7 +181,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -330,19 +208,9 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "0x6f\n", - "3bc28d6d92d9073fb5e3adf481795eaf446bceed\n", - "ee2161b7\n" - ] - } - ], + "outputs": [], "source": [ "receiver_address = 'mkxwE7XtVYJKepoD2hbHnDjftuMQ1k6deE'\n", "receiver_address_decoded = decode_base58(receiver_address)\n", @@ -367,7 +235,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -385,7 +253,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -414,17 +282,9 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "unsigned_tx: 020000000144e00ee2e2c5c4fe311ea5fd37d80da695cfc95f948e28bbfcfe6ce21d48ff5e0100000000ffffffff0280d1f008000000001976a9143bc28d6d92d9073fb5e3adf481795eaf446bceed88ac80f0fa02000000001976a914531260aa2a199e228c537dfa42c82bea2c7c1f4d88ac00000000\n" - ] - } - ], + "outputs": [], "source": [ "# VERSION\n", "# version '2' indicates that we may use relative timelocks (BIP68)\n", @@ -496,60 +356,9 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{\n", - " \"txid\": \"ca4164fded6ead1d3bfdbba0f9fa4e0b2e27615b97905fa46195fe8c83adbe47\",\n", - " \"hash\": \"ca4164fded6ead1d3bfdbba0f9fa4e0b2e27615b97905fa46195fe8c83adbe47\",\n", - " \"version\": 2,\n", - " \"size\": 119,\n", - " \"vsize\": 119,\n", - " \"weight\": 476,\n", - " \"locktime\": 0,\n", - " \"vin\": [\n", - " {\n", - " \"txid\": \"5eff481de26cfefcbb288e945fc9cf95a60dd837fda51e31fec4c5e2e20ee044\",\n", - " \"vout\": 1,\n", - " \"scriptSig\": {\n", - " \"asm\": \"\",\n", - " \"hex\": \"\"\n", - " },\n", - " \"sequence\": 4294967295\n", - " }\n", - " ],\n", - " \"vout\": [\n", - " {\n", - " \"value\": \"1.50000000\",\n", - " \"n\": 0,\n", - " \"scriptPubKey\": {\n", - " \"asm\": \"OP_DUP OP_HASH160 3bc28d6d92d9073fb5e3adf481795eaf446bceed OP_EQUALVERIFY OP_CHECKSIG\",\n", - " \"desc\": \"addr(mkxwE7XtVYJKepoD2hbHnDjftuMQ1k6deE)#xlnzfr97\",\n", - " \"hex\": \"76a9143bc28d6d92d9073fb5e3adf481795eaf446bceed88ac\",\n", - " \"address\": \"mkxwE7XtVYJKepoD2hbHnDjftuMQ1k6deE\",\n", - " \"type\": \"pubkeyhash\"\n", - " }\n", - " },\n", - " {\n", - " \"value\": \"0.50000000\",\n", - " \"n\": 1,\n", - " \"scriptPubKey\": {\n", - " \"asm\": \"OP_DUP OP_HASH160 531260aa2a199e228c537dfa42c82bea2c7c1f4d OP_EQUALVERIFY OP_CHECKSIG\",\n", - " \"desc\": \"addr(mo6CPsdW8EsnWdmSSCrQ6225VVDtpMBTug)#cvzzm9uf\",\n", - " \"hex\": \"76a914531260aa2a199e228c537dfa42c82bea2c7c1f4d88ac\",\n", - " \"address\": \"mo6CPsdW8EsnWdmSSCrQ6225VVDtpMBTug\",\n", - " \"type\": \"pubkeyhash\"\n", - " }\n", - " }\n", - " ]\n", - "}\n" - ] - } - ], + "outputs": [], "source": [ "decoded = node.decoderawtransaction(unsigned_tx.hex())\n", "print(json.dumps(decoded, indent=2, default=str))" @@ -566,7 +375,7 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -605,19 +414,11 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": null, "metadata": { "code_folding": [] }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "signed transaction: 020000000144e00ee2e2c5c4fe311ea5fd37d80da695cfc95f948e28bbfcfe6ce21d48ff5e010000006b483045022100fdeca825ddc6c52a2ed891613f02ebe748adebf80d6d9c5593107dbcb78de27d02202ba0d862bf64d8730d396270f99162e186420ddc2cdcc9bbbf3f1812f247708e0121034f355bdcb7cc0af728ef3cceb9615d90684bb5b2ca5f859ab0f0b704075871aaffffffff0280d1f008000000001976a9143bc28d6d92d9073fb5e3adf481795eaf446bceed88ac80f0fa02000000001976a914531260aa2a199e228c537dfa42c82bea2c7c1f4d88ac00000000\n" - ] - } - ], + "outputs": [], "source": [ "# Append the sighash flag to the transaction\n", "sighash_flag = bytes.fromhex(\"0100 0000\") # SIGHASH_ALL\n", @@ -671,17 +472,9 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "61e8d3c2e9ced2a211c76a5d4c03f4fae8402964f8af0cf530dea9eed2468f7e\n" - ] - } - ], + "outputs": [], "source": [ "new_tx_txid = node.sendrawtransaction(signed_tx.hex())\n", "# new_tx_txid = node.testmempoolaccept(signed_tx.hex())\n", @@ -698,18 +491,9 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "receiver's p2pkh address: mkxwE7XtVYJKepoD2hbHnDjftuMQ1k6deE\n", - "sender's change p2pkh address: mo6CPsdW8EsnWdmSSCrQ6225VVDtpMBTug\n" - ] - } - ], + "outputs": [], "source": [ "print(\"receiver's p2pkh address: \" + receiver_address)\n", "change_p2pkh_addr = pk_to_p2pkh(change_pubkey, network = \"regtest\")\n", @@ -718,60 +502,9 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{\n", - " \"txid\": \"61e8d3c2e9ced2a211c76a5d4c03f4fae8402964f8af0cf530dea9eed2468f7e\",\n", - " \"hash\": \"61e8d3c2e9ced2a211c76a5d4c03f4fae8402964f8af0cf530dea9eed2468f7e\",\n", - " \"version\": 2,\n", - " \"size\": 226,\n", - " \"vsize\": 226,\n", - " \"weight\": 904,\n", - " \"locktime\": 0,\n", - " \"vin\": [\n", - " {\n", - " \"txid\": \"5eff481de26cfefcbb288e945fc9cf95a60dd837fda51e31fec4c5e2e20ee044\",\n", - " \"vout\": 1,\n", - " \"scriptSig\": {\n", - " \"asm\": \"3045022100fdeca825ddc6c52a2ed891613f02ebe748adebf80d6d9c5593107dbcb78de27d02202ba0d862bf64d8730d396270f99162e186420ddc2cdcc9bbbf3f1812f247708e[ALL] 034f355bdcb7cc0af728ef3cceb9615d90684bb5b2ca5f859ab0f0b704075871aa\",\n", - " \"hex\": \"483045022100fdeca825ddc6c52a2ed891613f02ebe748adebf80d6d9c5593107dbcb78de27d02202ba0d862bf64d8730d396270f99162e186420ddc2cdcc9bbbf3f1812f247708e0121034f355bdcb7cc0af728ef3cceb9615d90684bb5b2ca5f859ab0f0b704075871aa\"\n", - " },\n", - " \"sequence\": 4294967295\n", - " }\n", - " ],\n", - " \"vout\": [\n", - " {\n", - " \"value\": \"1.50000000\",\n", - " \"n\": 0,\n", - " \"scriptPubKey\": {\n", - " \"asm\": \"OP_DUP OP_HASH160 3bc28d6d92d9073fb5e3adf481795eaf446bceed OP_EQUALVERIFY OP_CHECKSIG\",\n", - " \"desc\": \"addr(mkxwE7XtVYJKepoD2hbHnDjftuMQ1k6deE)#xlnzfr97\",\n", - " \"hex\": \"76a9143bc28d6d92d9073fb5e3adf481795eaf446bceed88ac\",\n", - " \"address\": \"mkxwE7XtVYJKepoD2hbHnDjftuMQ1k6deE\",\n", - " \"type\": \"pubkeyhash\"\n", - " }\n", - " },\n", - " {\n", - " \"value\": \"0.50000000\",\n", - " \"n\": 1,\n", - " \"scriptPubKey\": {\n", - " \"asm\": \"OP_DUP OP_HASH160 531260aa2a199e228c537dfa42c82bea2c7c1f4d OP_EQUALVERIFY OP_CHECKSIG\",\n", - " \"desc\": \"addr(mo6CPsdW8EsnWdmSSCrQ6225VVDtpMBTug)#cvzzm9uf\",\n", - " \"hex\": \"76a914531260aa2a199e228c537dfa42c82bea2c7c1f4d88ac\",\n", - " \"address\": \"mo6CPsdW8EsnWdmSSCrQ6225VVDtpMBTug\",\n", - " \"type\": \"pubkeyhash\"\n", - " }\n", - " }\n", - " ]\n", - "}\n" - ] - } - ], + "outputs": [], "source": [ "decoded = node.decoderawtransaction(signed_tx.hex())\n", "print(json.dumps(decoded, indent=2, default=str))" @@ -820,7 +553,7 @@ }, { "cell_type": "code", - "execution_count": 20, + "execution_count": null, "metadata": { "code_folding": [ 0 @@ -849,7 +582,7 @@ }, { "cell_type": "code", - "execution_count": 21, + "execution_count": null, "metadata": { "code_folding": [ 0 @@ -923,7 +656,7 @@ }, { "cell_type": "code", - "execution_count": 22, + "execution_count": null, "metadata": { "code_folding": [ 0 @@ -937,7 +670,7 @@ }, { "cell_type": "code", - "execution_count": 23, + "execution_count": null, "metadata": { "code_folding": [ 0 @@ -1008,20 +741,9 @@ }, { "cell_type": "code", - "execution_count": 24, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'c4ed94e06172f08e7508e419e2dfa1060b83232bdc47245d408981ea3723c96d'" - ] - }, - "execution_count": 24, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "# Try broadcasting the transaction to see if it works!\n", "node.sendrawtransaction(signed_tx.hex())" @@ -1029,23 +751,20 @@ }, { "cell_type": "code", - "execution_count": 25, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2022-12-06T21:11:28.582000Z TestFramework (INFO): Stopping nodes\n", - "2022-12-06T21:11:29.059000Z TestFramework (INFO): Cleaning up /var/folders/r5/yk8yg2xs1gs8xzkn5l8vr72w0000gn/T/bitcoin_func_test_zlfn_arb on exit\n", - "2022-12-06T21:11:29.059000Z TestFramework (INFO): Tests successful\n" - ] - } - ], + "outputs": [], "source": [ "# stop bitcoin core\n", "test.shutdown()" ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { diff --git a/chapter1-legacy/p2sh-multisig.ipynb b/1.3-p2sh-multisig.ipynb similarity index 64% rename from chapter1-legacy/p2sh-multisig.ipynb rename to 1.3-p2sh-multisig.ipynb index eb7f3d9..0c30272 100644 --- a/chapter1-legacy/p2sh-multisig.ipynb +++ b/1.3-p2sh-multisig.ipynb @@ -1,5 +1,15 @@ { "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from functions import *\n", + "import json" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -27,44 +37,6 @@ " - TestShell setup - '[P2PKH chapter](https://github.com/DariusParvin/bitcoin-tx-tutorial/blob/main/chapter1-legacy/p2pkh.ipynb)'" ] }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Setup \n", - "\n", - "### Requirements\n", - "For this exercise we'll need Bitcoin Core. This notebook has been tested with [v24.0.1](https://github.com/bitcoin/bitcoin/releases/tag/v24.0.1).\n", - "\n", - "Below, set the paths for:\n", - "1. The bitcoin core functional test framework directory.\n", - "2. The directory containing bitcoin-tx-tutorial.\n", - "\n", - "**You'll need to edit these next two lines for your local setup.**" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "path_to_bitcoin_functional_test = \"/Users/dariuscognac/bitcoin/test/functional\"\n", - "path_to_bitcoin_tx_tutorial = \"/Users/dariuscognac/Documents/Github/bitcoin-tx-tutorial\"\n", - "\n", - "import sys\n", - "\n", - "# Add the functional test framework to our PATH\n", - "sys.path.insert(0, path_to_bitcoin_functional_test)\n", - "from test_framework.test_shell import TestShell\n", - "\n", - "# Add the bitcoin-tx-tutorial functions to our PATH\n", - "sys.path.insert(0, path_to_bitcoin_tx_tutorial)\n", - "from functions import *\n", - "\n", - "import json" - ] - }, { "cell_type": "markdown", "metadata": {}, @@ -84,17 +56,9 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "5221034f355bdcb7cc0af728ef3cceb9615d90684bb5b2ca5f859ab0f0b704075871aa2102466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f2721023c72addb4fdf09af94f0c94d7fe92a386a7e70cf8a1d85916386bb2535c7b1b153ae\n" - ] - } - ], + "outputs": [], "source": [ "privkey1 = bytes.fromhex(\"1111111111111111111111111111111111111111111111111111111111111111\")\n", "pubkey1 = privkey_to_pubkey(privkey1)\n", @@ -131,17 +95,9 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2MuXogRGTh7uADB2wKBqFcsPTprVKnChJe6\n" - ] - } - ], + "outputs": [], "source": [ "address_to_spend = script_to_p2sh(redeemScript, \"regtest\")\n", "print(address_to_spend)" @@ -158,18 +114,9 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2022-12-28T02:11:18.699000Z TestFramework (INFO): Initializing test directory /var/folders/r5/yk8yg2xs1gs8xzkn5l8vr72w0000gn/T/bitcoin_func_test_f11saxl4\n", - "txid: 2a60c33fd18722a74e3555154803a0077e95f510a0def717c54f2cf592b9cf70, 0\n" - ] - } - ], + "outputs": [], "source": [ "node = setup_testshell()\n", "txid_to_spend, index_to_spend = fund_address(node, address_to_spend, 2.001)\n", @@ -189,7 +136,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -207,7 +154,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -236,17 +183,9 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "unsigned_tx: 020000000170cfb992f52c4fc517f7dea010f5957e07a003481555354ea72287d13fc3602a0000000000ffffffff0280d1f008000000001976a9143bc28d6d92d9073fb5e3adf481795eaf446bceed88ac80f0fa02000000001976a914cc1b07838e387deacd0e5232e1e8b49f4c29e48488ac00000000\n" - ] - } - ], + "outputs": [], "source": [ "# VERSION\n", "# version '2' indicates that we may use relative timelocks (BIP68)\n", @@ -316,60 +255,9 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{\n", - " \"txid\": \"568959f367762a7c72432d3a7fff2994b6167537a3e9819a36f1f2ca05a2c9e0\",\n", - " \"hash\": \"568959f367762a7c72432d3a7fff2994b6167537a3e9819a36f1f2ca05a2c9e0\",\n", - " \"version\": 2,\n", - " \"size\": 119,\n", - " \"vsize\": 119,\n", - " \"weight\": 476,\n", - " \"locktime\": 0,\n", - " \"vin\": [\n", - " {\n", - " \"txid\": \"2a60c33fd18722a74e3555154803a0077e95f510a0def717c54f2cf592b9cf70\",\n", - " \"vout\": 0,\n", - " \"scriptSig\": {\n", - " \"asm\": \"\",\n", - " \"hex\": \"\"\n", - " },\n", - " \"sequence\": 4294967295\n", - " }\n", - " ],\n", - " \"vout\": [\n", - " {\n", - " \"value\": \"1.50000000\",\n", - " \"n\": 0,\n", - " \"scriptPubKey\": {\n", - " \"asm\": \"OP_DUP OP_HASH160 3bc28d6d92d9073fb5e3adf481795eaf446bceed OP_EQUALVERIFY OP_CHECKSIG\",\n", - " \"desc\": \"addr(mkxwE7XtVYJKepoD2hbHnDjftuMQ1k6deE)#xlnzfr97\",\n", - " \"hex\": \"76a9143bc28d6d92d9073fb5e3adf481795eaf446bceed88ac\",\n", - " \"address\": \"mkxwE7XtVYJKepoD2hbHnDjftuMQ1k6deE\",\n", - " \"type\": \"pubkeyhash\"\n", - " }\n", - " },\n", - " {\n", - " \"value\": \"0.50000000\",\n", - " \"n\": 1,\n", - " \"scriptPubKey\": {\n", - " \"asm\": \"OP_DUP OP_HASH160 cc1b07838e387deacd0e5232e1e8b49f4c29e484 OP_EQUALVERIFY OP_CHECKSIG\",\n", - " \"desc\": \"addr(mz8AXDhDMhvLs7kxwfQxvcH5GoVH6AdARZ)#6f8xcf93\",\n", - " \"hex\": \"76a914cc1b07838e387deacd0e5232e1e8b49f4c29e48488ac\",\n", - " \"address\": \"mz8AXDhDMhvLs7kxwfQxvcH5GoVH6AdARZ\",\n", - " \"type\": \"pubkeyhash\"\n", - " }\n", - " }\n", - " ]\n", - "}\n" - ] - } - ], + "outputs": [], "source": [ "decoded = node.decoderawtransaction(unsigned_tx.hex())\n", "print(json.dumps(decoded, indent=2, default=str))" @@ -386,7 +274,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -423,19 +311,11 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": null, "metadata": { "code_folding": [] }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "signed transaction: 020000000170cfb992f52c4fc517f7dea010f5957e07a003481555354ea72287d13fc3602a00000000fdfd000047304402201ae3f85d9fa9a8fa4043a67a68ab979c8f07a80aa6a2486f065c01b314d42a0202201d4d4165ad628a9353f8e886b4850866ab7cd77f09eeb16884a3bf511a8b836c01483045022100ae12f028e091df87ff5718acac6f150a9f4516c90f90186b6e36fdb80a6a6ab6022003cf86a581d2d670ecb811dae2479f2398bdd93beea8adcfb5cc6381a6242b85014c695221034f355bdcb7cc0af728ef3cceb9615d90684bb5b2ca5f859ab0f0b704075871aa2102466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f2721023c72addb4fdf09af94f0c94d7fe92a386a7e70cf8a1d85916386bb2535c7b1b153aeffffffff0280d1f008000000001976a9143bc28d6d92d9073fb5e3adf481795eaf446bceed88ac80f0fa02000000001976a914cc1b07838e387deacd0e5232e1e8b49f4c29e48488ac00000000\n" - ] - } - ], + "outputs": [], "source": [ "# Append the sighash flag to the transaction\n", "sighash_flag = bytes.fromhex(\"0100 0000\") # SIGHASH_ALL\n", @@ -498,17 +378,9 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "02d2326ec9aea1cd165fec6ed48e477688a474594af084f02a2807bcc3971f20\n" - ] - } - ], + "outputs": [], "source": [ "new_tx_txid = node.sendrawtransaction(signed_tx.hex())\n", "print(new_tx_txid)" @@ -516,60 +388,9 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{\n", - " \"txid\": \"02d2326ec9aea1cd165fec6ed48e477688a474594af084f02a2807bcc3971f20\",\n", - " \"hash\": \"02d2326ec9aea1cd165fec6ed48e477688a474594af084f02a2807bcc3971f20\",\n", - " \"version\": 2,\n", - " \"size\": 374,\n", - " \"vsize\": 374,\n", - " \"weight\": 1496,\n", - " \"locktime\": 0,\n", - " \"vin\": [\n", - " {\n", - " \"txid\": \"2a60c33fd18722a74e3555154803a0077e95f510a0def717c54f2cf592b9cf70\",\n", - " \"vout\": 0,\n", - " \"scriptSig\": {\n", - " \"asm\": \"0 304402201ae3f85d9fa9a8fa4043a67a68ab979c8f07a80aa6a2486f065c01b314d42a0202201d4d4165ad628a9353f8e886b4850866ab7cd77f09eeb16884a3bf511a8b836c[ALL] 3045022100ae12f028e091df87ff5718acac6f150a9f4516c90f90186b6e36fdb80a6a6ab6022003cf86a581d2d670ecb811dae2479f2398bdd93beea8adcfb5cc6381a6242b85[ALL] 5221034f355bdcb7cc0af728ef3cceb9615d90684bb5b2ca5f859ab0f0b704075871aa2102466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f2721023c72addb4fdf09af94f0c94d7fe92a386a7e70cf8a1d85916386bb2535c7b1b153ae\",\n", - " \"hex\": \"0047304402201ae3f85d9fa9a8fa4043a67a68ab979c8f07a80aa6a2486f065c01b314d42a0202201d4d4165ad628a9353f8e886b4850866ab7cd77f09eeb16884a3bf511a8b836c01483045022100ae12f028e091df87ff5718acac6f150a9f4516c90f90186b6e36fdb80a6a6ab6022003cf86a581d2d670ecb811dae2479f2398bdd93beea8adcfb5cc6381a6242b85014c695221034f355bdcb7cc0af728ef3cceb9615d90684bb5b2ca5f859ab0f0b704075871aa2102466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f2721023c72addb4fdf09af94f0c94d7fe92a386a7e70cf8a1d85916386bb2535c7b1b153ae\"\n", - " },\n", - " \"sequence\": 4294967295\n", - " }\n", - " ],\n", - " \"vout\": [\n", - " {\n", - " \"value\": \"1.50000000\",\n", - " \"n\": 0,\n", - " \"scriptPubKey\": {\n", - " \"asm\": \"OP_DUP OP_HASH160 3bc28d6d92d9073fb5e3adf481795eaf446bceed OP_EQUALVERIFY OP_CHECKSIG\",\n", - " \"desc\": \"addr(mkxwE7XtVYJKepoD2hbHnDjftuMQ1k6deE)#xlnzfr97\",\n", - " \"hex\": \"76a9143bc28d6d92d9073fb5e3adf481795eaf446bceed88ac\",\n", - " \"address\": \"mkxwE7XtVYJKepoD2hbHnDjftuMQ1k6deE\",\n", - " \"type\": \"pubkeyhash\"\n", - " }\n", - " },\n", - " {\n", - " \"value\": \"0.50000000\",\n", - " \"n\": 1,\n", - " \"scriptPubKey\": {\n", - " \"asm\": \"OP_DUP OP_HASH160 cc1b07838e387deacd0e5232e1e8b49f4c29e484 OP_EQUALVERIFY OP_CHECKSIG\",\n", - " \"desc\": \"addr(mz8AXDhDMhvLs7kxwfQxvcH5GoVH6AdARZ)#6f8xcf93\",\n", - " \"hex\": \"76a914cc1b07838e387deacd0e5232e1e8b49f4c29e48488ac\",\n", - " \"address\": \"mz8AXDhDMhvLs7kxwfQxvcH5GoVH6AdARZ\",\n", - " \"type\": \"pubkeyhash\"\n", - " }\n", - " }\n", - " ]\n", - "}\n" - ] - } - ], + "outputs": [], "source": [ "decoded = node.decoderawtransaction(signed_tx.hex())\n", "print(json.dumps(decoded, indent=2, default=str))" @@ -609,7 +430,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -623,7 +444,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.0" + "version": "3.8.16" } }, "nbformat": 4, diff --git a/chapter2-segwitv0/p2wpkh.ipynb b/2.1-p2wpkh.ipynb similarity index 66% rename from chapter2-segwitv0/p2wpkh.ipynb rename to 2.1-p2wpkh.ipynb index e304191..ab96940 100644 --- a/chapter2-segwitv0/p2wpkh.ipynb +++ b/2.1-p2wpkh.ipynb @@ -1,5 +1,15 @@ { "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from functions import *\n", + "import json" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -27,44 +37,6 @@ " - TestShell setup - '[P2PKH chapter](https://github.com/DariusParvin/bitcoin-tx-tutorial/blob/main/chapter1-legacy/p2pkh.ipynb)'" ] }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Setup \n", - "\n", - "### Requirements\n", - "For this exercise we'll need Bitcoin Core. This notebook has been tested with [v24.0.1](https://github.com/bitcoin/bitcoin/releases/tag/v24.0.1).\n", - "\n", - "Below, set the paths for:\n", - "1. The bitcoin core functional test framework directory.\n", - "2. The directory containing bitcoin-tx-tutorial.\n", - "\n", - "**You'll need to edit these next two lines for your local setup.**" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "path_to_bitcoin_functional_test = \"/Users/dariuscognac/bitcoin/test/functional\"\n", - "path_to_bitcoin_tx_tutorial = \"/Users/dariuscognac/Documents/Github/bitcoin-tx-tutorial\"\n", - "\n", - "import sys\n", - "\n", - "# Add the functional test framework to our PATH\n", - "sys.path.insert(0, path_to_bitcoin_functional_test)\n", - "from test_framework.test_shell import TestShell\n", - "\n", - "# Add the bitcoin-tx-tutorial functions to our PATH\n", - "sys.path.insert(0, path_to_bitcoin_tx_tutorial)\n", - "from functions import *\n", - "\n", - "import json" - ] - }, { "cell_type": "markdown", "metadata": {}, @@ -84,17 +56,9 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "sender's p2wpkh address: bcrt1ql3e9pgs3mmwuwrh95fecme0s0qtn2880hlwwpw\n" - ] - } - ], + "outputs": [], "source": [ "sender_privkey = bytes.fromhex(\"1111111111111111111111111111111111111111111111111111111111111111\")\n", "sender_pubkey = privkey_to_pubkey(sender_privkey)\n", @@ -113,18 +77,9 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2022-12-08T10:18:24.398000Z TestFramework (INFO): Initializing test directory /var/folders/r5/yk8yg2xs1gs8xzkn5l8vr72w0000gn/T/bitcoin_func_test_5i0cu3j8\n", - "txid: d4ce50311efa12a97b6c910afba180686687edaec7de92ffcfba18777673991c, 0\n" - ] - } - ], + "outputs": [], "source": [ "node = setup_testshell()\n", "txid_to_spend, index_to_spend = fund_address(node, address_to_spend, 2.001)\n", @@ -151,18 +106,9 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "witness version: 0\n", - "pubkey/script hash: fc7250a211deddc70ee5a2738de5f07817351cef\n" - ] - } - ], + "outputs": [], "source": [ "receiver_address = 'bcrt1ql3e9pgs3mmwuwrh95fecme0s0qtn2880hlwwpw'\n", "\n", @@ -188,7 +134,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -206,7 +152,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -235,17 +181,9 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "unsigned_tx: 02000000011c9973767718bacfff92dec7aeed87666880a1fb0a916c7ba912fa1e3150ced40000000000ffffffff0280d1f00800000000160014fc7250a211deddc70ee5a2738de5f07817351cef80f0fa0200000000160014531260aa2a199e228c537dfa42c82bea2c7c1f4d00000000\n" - ] - } - ], + "outputs": [], "source": [ "# VERSION\n", "# version '2' indicates that we may use relative timelocks (BIP68)\n", @@ -323,60 +261,9 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{\n", - " \"txid\": \"72ed59fd70134b2d5bb45eb16cb77d418ff2407998a30e72796aa775e437b05e\",\n", - " \"hash\": \"72ed59fd70134b2d5bb45eb16cb77d418ff2407998a30e72796aa775e437b05e\",\n", - " \"version\": 2,\n", - " \"size\": 113,\n", - " \"vsize\": 113,\n", - " \"weight\": 452,\n", - " \"locktime\": 0,\n", - " \"vin\": [\n", - " {\n", - " \"txid\": \"d4ce50311efa12a97b6c910afba180686687edaec7de92ffcfba18777673991c\",\n", - " \"vout\": 0,\n", - " \"scriptSig\": {\n", - " \"asm\": \"\",\n", - " \"hex\": \"\"\n", - " },\n", - " \"sequence\": 4294967295\n", - " }\n", - " ],\n", - " \"vout\": [\n", - " {\n", - " \"value\": \"1.50000000\",\n", - " \"n\": 0,\n", - " \"scriptPubKey\": {\n", - " \"asm\": \"0 fc7250a211deddc70ee5a2738de5f07817351cef\",\n", - " \"desc\": \"addr(bcrt1ql3e9pgs3mmwuwrh95fecme0s0qtn2880hlwwpw)#luvpmd0q\",\n", - " \"hex\": \"0014fc7250a211deddc70ee5a2738de5f07817351cef\",\n", - " \"address\": \"bcrt1ql3e9pgs3mmwuwrh95fecme0s0qtn2880hlwwpw\",\n", - " \"type\": \"witness_v0_keyhash\"\n", - " }\n", - " },\n", - " {\n", - " \"value\": \"0.50000000\",\n", - " \"n\": 1,\n", - " \"scriptPubKey\": {\n", - " \"asm\": \"0 531260aa2a199e228c537dfa42c82bea2c7c1f4d\",\n", - " \"desc\": \"addr(bcrt1q2vfxp232rx0z9rzn0hay9jptagk8c86ddphpjv)#f3wckqp8\",\n", - " \"hex\": \"0014531260aa2a199e228c537dfa42c82bea2c7c1f4d\",\n", - " \"address\": \"bcrt1q2vfxp232rx0z9rzn0hay9jptagk8c86ddphpjv\",\n", - " \"type\": \"witness_v0_keyhash\"\n", - " }\n", - " }\n", - " ]\n", - "}\n" - ] - } - ], + "outputs": [], "source": [ "decoded = node.decoderawtransaction(unsigned_tx.hex())\n", "print(json.dumps(decoded, indent=2, default=str))" @@ -391,17 +278,9 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "02000000ee7612c66f9ae792957ced87f2635ee395f6a7af6da67f71ae6572a6c0b6611b3bb13029ce7b1f559ef5e747fcac439f1455a2ec7c5f09b72290795e706650441c9973767718bacfff92dec7aeed87666880a1fb0a916c7ba912fa1e3150ced4000000001976a914fc7250a211deddc70ee5a2738de5f07817351cef88aca048ed0b00000000fffffffff91a6606c3037951dc241bb6edf31f9a61112940431aee9593c16c3bb3e1d2600000000001000000\n" - ] - } - ], + "outputs": [], "source": [ "pk_hash = hash160(sender_pubkey)\n", "scriptcode = bytes.fromhex(\"76a914\" + pk_hash.hex() + \"88ac\")\n", @@ -444,19 +323,11 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": null, "metadata": { "code_folding": [] }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "signed transaction: 020000000001011c9973767718bacfff92dec7aeed87666880a1fb0a916c7ba912fa1e3150ced40000000000ffffffff0280d1f00800000000160014fc7250a211deddc70ee5a2738de5f07817351cef80f0fa0200000000160014531260aa2a199e228c537dfa42c82bea2c7c1f4d02483045022100c4be2b40dd0de4d8394c90dd48cf10f7b7ebb966a00ed174c2ee987994f6a2aa022018fb4447db30f5c572c189996c522b81ee337613a8012167718f91d11c8cdb0e0121034f355bdcb7cc0af728ef3cceb9615d90684bb5b2ca5f859ab0f0b704075871aa00000000\n" - ] - } - ], + "outputs": [], "source": [ "# Create sigHash to be signed\n", "sighash = hash256(tx_digest_preimage)\n", @@ -512,17 +383,9 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "72ed59fd70134b2d5bb45eb16cb77d418ff2407998a30e72796aa775e437b05e\n" - ] - } - ], + "outputs": [], "source": [ "new_tx_txid = node.sendrawtransaction(signed_tx.hex())\n", "# result = node.testmempoolaccept(rawtxs=[signed_tx.hex()])\n", @@ -538,18 +401,9 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "receiver's p2pkh address: bcrt1ql3e9pgs3mmwuwrh95fecme0s0qtn2880hlwwpw\n", - "sender's change p2pkh address: mo6CPsdW8EsnWdmSSCrQ6225VVDtpMBTug\n" - ] - } - ], + "outputs": [], "source": [ "print(\"receiver's p2pkh address: \" + receiver_address)\n", "change_p2pkh_addr = pk_to_p2pkh(change_pubkey, network = \"regtest\")\n", @@ -558,64 +412,9 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{\n", - " \"txid\": \"72ed59fd70134b2d5bb45eb16cb77d418ff2407998a30e72796aa775e437b05e\",\n", - " \"hash\": \"a5559bc4d2b421b0b6e0e96792d7548935ec2be929f66dc2af323408507125c5\",\n", - " \"version\": 2,\n", - " \"size\": 223,\n", - " \"vsize\": 141,\n", - " \"weight\": 562,\n", - " \"locktime\": 0,\n", - " \"vin\": [\n", - " {\n", - " \"txid\": \"d4ce50311efa12a97b6c910afba180686687edaec7de92ffcfba18777673991c\",\n", - " \"vout\": 0,\n", - " \"scriptSig\": {\n", - " \"asm\": \"\",\n", - " \"hex\": \"\"\n", - " },\n", - " \"txinwitness\": [\n", - " \"3045022100c4be2b40dd0de4d8394c90dd48cf10f7b7ebb966a00ed174c2ee987994f6a2aa022018fb4447db30f5c572c189996c522b81ee337613a8012167718f91d11c8cdb0e01\",\n", - " \"034f355bdcb7cc0af728ef3cceb9615d90684bb5b2ca5f859ab0f0b704075871aa\"\n", - " ],\n", - " \"sequence\": 4294967295\n", - " }\n", - " ],\n", - " \"vout\": [\n", - " {\n", - " \"value\": \"1.50000000\",\n", - " \"n\": 0,\n", - " \"scriptPubKey\": {\n", - " \"asm\": \"0 fc7250a211deddc70ee5a2738de5f07817351cef\",\n", - " \"desc\": \"addr(bcrt1ql3e9pgs3mmwuwrh95fecme0s0qtn2880hlwwpw)#luvpmd0q\",\n", - " \"hex\": \"0014fc7250a211deddc70ee5a2738de5f07817351cef\",\n", - " \"address\": \"bcrt1ql3e9pgs3mmwuwrh95fecme0s0qtn2880hlwwpw\",\n", - " \"type\": \"witness_v0_keyhash\"\n", - " }\n", - " },\n", - " {\n", - " \"value\": \"0.50000000\",\n", - " \"n\": 1,\n", - " \"scriptPubKey\": {\n", - " \"asm\": \"0 531260aa2a199e228c537dfa42c82bea2c7c1f4d\",\n", - " \"desc\": \"addr(bcrt1q2vfxp232rx0z9rzn0hay9jptagk8c86ddphpjv)#f3wckqp8\",\n", - " \"hex\": \"0014531260aa2a199e228c537dfa42c82bea2c7c1f4d\",\n", - " \"address\": \"bcrt1q2vfxp232rx0z9rzn0hay9jptagk8c86ddphpjv\",\n", - " \"type\": \"witness_v0_keyhash\"\n", - " }\n", - " }\n", - " ]\n", - "}\n" - ] - } - ], + "outputs": [], "source": [ "decoded = node.decoderawtransaction(signed_tx.hex())\n", "print(json.dumps(decoded, indent=2, default=str))" @@ -655,7 +454,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -669,7 +468,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.0" + "version": "3.8.16" } }, "nbformat": 4, diff --git a/chapter2-segwitv0/multiple-inputs-outputs.ipynb b/2.2-multiple-inputs-outputs.ipynb similarity index 59% rename from chapter2-segwitv0/multiple-inputs-outputs.ipynb rename to 2.2-multiple-inputs-outputs.ipynb index 3545ae3..81416ce 100644 --- a/chapter2-segwitv0/multiple-inputs-outputs.ipynb +++ b/2.2-multiple-inputs-outputs.ipynb @@ -1,5 +1,15 @@ { "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from functions import *\n", + "import json" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -29,45 +39,6 @@ " - TestShell setup - '[P2PKH chapter](https://github.com/DariusParvin/bitcoin-tx-tutorial/blob/main/chapter1-legacy/p2pkh.ipynb)'\n" ] }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Setup \n", - "\n", - "### Requirements\n", - "For this exercise we'll need Bitcoin Core. This notebook has been tested with [v24.0.1](https://github.com/bitcoin/bitcoin/releases/tag/v24.0.1).\n", - "\n", - "Below, set the paths for:\n", - "1. The bitcoin core functional test framework directory.\n", - "2. The directory containing bitcoin-tx-tutorial.\n", - "\n", - "**You'll need to edit these next two lines for your local setup.**" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "\n", - "path_to_bitcoin_functional_test = \"/Users/dariuscognac/bitcoin/test/functional\"\n", - "path_to_bitcoin_tx_tutorial = \"/Users/dariuscognac/Documents/Github/bitcoin-tx-tutorial\"\n", - "\n", - "import sys\n", - "\n", - "# Add the functional test framework to our PATH\n", - "sys.path.insert(0, path_to_bitcoin_functional_test)\n", - "from test_framework.test_shell import TestShell\n", - "\n", - "# Add the bitcoin-tx-tutorial functions to our PATH\n", - "sys.path.insert(0, path_to_bitcoin_tx_tutorial)\n", - "from functions import *\n", - "\n", - "import json" - ] - }, { "cell_type": "markdown", "metadata": {}, @@ -89,19 +60,9 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2022-12-08T10:29:45.807000Z TestFramework (INFO): Initializing test directory /var/folders/r5/yk8yg2xs1gs8xzkn5l8vr72w0000gn/T/bitcoin_func_test_ezrqykdy\n", - "Andreas's UTXO: 5b9c4d176b42349dc2a8cca26d52a3b87c9f8773dd9cacc87003eb4a96cf7044, 0\n", - "Lisa's UTXO: 050746ee1a49d3273e9819cce6bfa3b8599e46b96b0225c07ceba0ef0e92afd2, 0\n" - ] - } - ], + "outputs": [], "source": [ "# Create two private keys and P2WPKH addresses\n", "privkey_a = bytes.fromhex(\"1111111111111111111111111111111111111111111111111111111111111111\")\n", @@ -134,7 +95,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -164,17 +125,9 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "unsigned_tx: 02000000024470cf964aeb0370c8ac9cdd73879f7cb8a3526da2cca8c29d34426b174d9c5b0000000000ffffffffd2af920eefa0eb7cc025026bb9469e59b8a3bfe6cc19983e27d3491aee4607050000000000ffffffff04002d310100000000160014fc7250a211deddc70ee5a2738de5f07817351cef002d310100000000160014d6fe05ad07a2b3a8f3b7223eeff694372032002f002d310100000000160014c94957ccbc70af1aec527a9d1318a2b5d16ce9c6809698000000000016001403731c543b60c656c43d6459abfc212fe30de86600000000\n" - ] - } - ], + "outputs": [], "source": [ "# VERSION\n", "# version '2' indicates that we may use relative timelocks (BIP68)\n", @@ -267,91 +220,9 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{\n", - " \"txid\": \"40c6bbde2a1f2f3ea4a3cc8986751fd452b91edb12684b92d853b4a8efa97bb0\",\n", - " \"hash\": \"40c6bbde2a1f2f3ea4a3cc8986751fd452b91edb12684b92d853b4a8efa97bb0\",\n", - " \"version\": 2,\n", - " \"size\": 216,\n", - " \"vsize\": 216,\n", - " \"weight\": 864,\n", - " \"locktime\": 0,\n", - " \"vin\": [\n", - " {\n", - " \"txid\": \"5b9c4d176b42349dc2a8cca26d52a3b87c9f8773dd9cacc87003eb4a96cf7044\",\n", - " \"vout\": 0,\n", - " \"scriptSig\": {\n", - " \"asm\": \"\",\n", - " \"hex\": \"\"\n", - " },\n", - " \"sequence\": 4294967295\n", - " },\n", - " {\n", - " \"txid\": \"050746ee1a49d3273e9819cce6bfa3b8599e46b96b0225c07ceba0ef0e92afd2\",\n", - " \"vout\": 0,\n", - " \"scriptSig\": {\n", - " \"asm\": \"\",\n", - " \"hex\": \"\"\n", - " },\n", - " \"sequence\": 4294967295\n", - " }\n", - " ],\n", - " \"vout\": [\n", - " {\n", - " \"value\": \"0.20000000\",\n", - " \"n\": 0,\n", - " \"scriptPubKey\": {\n", - " \"asm\": \"0 fc7250a211deddc70ee5a2738de5f07817351cef\",\n", - " \"desc\": \"addr(bcrt1ql3e9pgs3mmwuwrh95fecme0s0qtn2880hlwwpw)#luvpmd0q\",\n", - " \"hex\": \"0014fc7250a211deddc70ee5a2738de5f07817351cef\",\n", - " \"address\": \"bcrt1ql3e9pgs3mmwuwrh95fecme0s0qtn2880hlwwpw\",\n", - " \"type\": \"witness_v0_keyhash\"\n", - " }\n", - " },\n", - " {\n", - " \"value\": \"0.20000000\",\n", - " \"n\": 1,\n", - " \"scriptPubKey\": {\n", - " \"asm\": \"0 d6fe05ad07a2b3a8f3b7223eeff694372032002f\",\n", - " \"desc\": \"addr(bcrt1q6mlqttg852e63uahyglwla55xusryqp08vx9w2)#c2cp77px\",\n", - " \"hex\": \"0014d6fe05ad07a2b3a8f3b7223eeff694372032002f\",\n", - " \"address\": \"bcrt1q6mlqttg852e63uahyglwla55xusryqp08vx9w2\",\n", - " \"type\": \"witness_v0_keyhash\"\n", - " }\n", - " },\n", - " {\n", - " \"value\": \"0.20000000\",\n", - " \"n\": 2,\n", - " \"scriptPubKey\": {\n", - " \"asm\": \"0 c94957ccbc70af1aec527a9d1318a2b5d16ce9c6\",\n", - " \"desc\": \"addr(bcrt1qe9y40n9uwzh34mzj02w3xx9zkhgke6wxcql4lk)#t4m8q2ue\",\n", - " \"hex\": \"0014c94957ccbc70af1aec527a9d1318a2b5d16ce9c6\",\n", - " \"address\": \"bcrt1qe9y40n9uwzh34mzj02w3xx9zkhgke6wxcql4lk\",\n", - " \"type\": \"witness_v0_keyhash\"\n", - " }\n", - " },\n", - " {\n", - " \"value\": \"0.10000000\",\n", - " \"n\": 3,\n", - " \"scriptPubKey\": {\n", - " \"asm\": \"0 03731c543b60c656c43d6459abfc212fe30de866\",\n", - " \"desc\": \"addr(bcrt1qqde3c4pmvrr9d3pav3v6hlpp9l3sm6rxnj8dcm)#y7l0a0g8\",\n", - " \"hex\": \"001403731c543b60c656c43d6459abfc212fe30de866\",\n", - " \"address\": \"bcrt1qqde3c4pmvrr9d3pav3v6hlpp9l3sm6rxnj8dcm\",\n", - " \"type\": \"witness_v0_keyhash\"\n", - " }\n", - " }\n", - " ]\n", - "}\n" - ] - } - ], + "outputs": [], "source": [ "decoded = node.decoderawtransaction(unsigned_tx.hex())\n", "print(json.dumps(decoded, indent=2, default=str))" @@ -366,17 +237,9 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Andreas's signature: 30450221009bc6239ba94cda692c0e0903af911ff2e51056f9a42f323b835c10c5488ed0390220570a587a79b9824d378a7c7a916ac973db1efe4db5e1204084e0db616ba818b701\n" - ] - } - ], + "outputs": [], "source": [ "pk_hash_a = hash160(pubkey_a)\n", "scriptcode_a = bytes.fromhex(\"76a914\" + pk_hash_a.hex() + \"88ac\")\n", @@ -433,17 +296,9 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Lisa's signature: 3045022100968fefff098f7752c4ad1af641d41ab72afb8f1be4f1ce016dc1bdbbc65d86c702202a152e8d57bc9afdb0ca9f87e8376096a260d6448097f06610060227de08133601\n" - ] - } - ], + "outputs": [], "source": [ "pk_hash_l = hash160(pubkey_l)\n", "scriptcode_l = bytes.fromhex(\"76a914\" + pk_hash_l.hex() + \"88ac\")\n", @@ -486,19 +341,11 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "metadata": { "code_folding": [] }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "signed transaction: 020000000001024470cf964aeb0370c8ac9cdd73879f7cb8a3526da2cca8c29d34426b174d9c5b0000000000ffffffffd2af920eefa0eb7cc025026bb9469e59b8a3bfe6cc19983e27d3491aee4607050000000000ffffffff04002d310100000000160014fc7250a211deddc70ee5a2738de5f07817351cef002d310100000000160014d6fe05ad07a2b3a8f3b7223eeff694372032002f002d310100000000160014c94957ccbc70af1aec527a9d1318a2b5d16ce9c6809698000000000016001403731c543b60c656c43d6459abfc212fe30de866024830450221009bc6239ba94cda692c0e0903af911ff2e51056f9a42f323b835c10c5488ed0390220570a587a79b9824d378a7c7a916ac973db1efe4db5e1204084e0db616ba818b70121034f355bdcb7cc0af728ef3cceb9615d90684bb5b2ca5f859ab0f0b704075871aa02483045022100968fefff098f7752c4ad1af641d41ab72afb8f1be4f1ce016dc1bdbbc65d86c702202a152e8d57bc9afdb0ca9f87e8376096a260d6448097f06610060227de081336012102466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f2700000000\n" - ] - } - ], + "outputs": [], "source": [ "# Witness field\n", "witness = (\n", @@ -538,21 +385,12 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "40c6bbde2a1f2f3ea4a3cc8986751fd452b91edb12684b92d853b4a8efa97bb0\n" - ] - } - ], + "outputs": [], "source": [ "new_tx_txid = node.sendrawtransaction(signed_tx.hex())\n", - "# result = node.testmempoolaccept(rawtxs=[signed_tx.hex()])", - "print(new_tx_txid)" + "# result = node.testmempoolaccept(rawtxs=[signed_tx.hex()])print(new_tx_txid)" ] }, { @@ -566,99 +404,9 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{\n", - " \"txid\": \"40c6bbde2a1f2f3ea4a3cc8986751fd452b91edb12684b92d853b4a8efa97bb0\",\n", - " \"hash\": \"d98f73bab0e1e5adee78c61d95ddc12f249116b73bb9005a3bbb3c3717ef56a2\",\n", - " \"version\": 2,\n", - " \"size\": 434,\n", - " \"vsize\": 271,\n", - " \"weight\": 1082,\n", - " \"locktime\": 0,\n", - " \"vin\": [\n", - " {\n", - " \"txid\": \"5b9c4d176b42349dc2a8cca26d52a3b87c9f8773dd9cacc87003eb4a96cf7044\",\n", - " \"vout\": 0,\n", - " \"scriptSig\": {\n", - " \"asm\": \"\",\n", - " \"hex\": \"\"\n", - " },\n", - " \"txinwitness\": [\n", - " \"30450221009bc6239ba94cda692c0e0903af911ff2e51056f9a42f323b835c10c5488ed0390220570a587a79b9824d378a7c7a916ac973db1efe4db5e1204084e0db616ba818b701\",\n", - " \"034f355bdcb7cc0af728ef3cceb9615d90684bb5b2ca5f859ab0f0b704075871aa\"\n", - " ],\n", - " \"sequence\": 4294967295\n", - " },\n", - " {\n", - " \"txid\": \"050746ee1a49d3273e9819cce6bfa3b8599e46b96b0225c07ceba0ef0e92afd2\",\n", - " \"vout\": 0,\n", - " \"scriptSig\": {\n", - " \"asm\": \"\",\n", - " \"hex\": \"\"\n", - " },\n", - " \"txinwitness\": [\n", - " \"3045022100968fefff098f7752c4ad1af641d41ab72afb8f1be4f1ce016dc1bdbbc65d86c702202a152e8d57bc9afdb0ca9f87e8376096a260d6448097f06610060227de08133601\",\n", - " \"02466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f27\"\n", - " ],\n", - " \"sequence\": 4294967295\n", - " }\n", - " ],\n", - " \"vout\": [\n", - " {\n", - " \"value\": \"0.20000000\",\n", - " \"n\": 0,\n", - " \"scriptPubKey\": {\n", - " \"asm\": \"0 fc7250a211deddc70ee5a2738de5f07817351cef\",\n", - " \"desc\": \"addr(bcrt1ql3e9pgs3mmwuwrh95fecme0s0qtn2880hlwwpw)#luvpmd0q\",\n", - " \"hex\": \"0014fc7250a211deddc70ee5a2738de5f07817351cef\",\n", - " \"address\": \"bcrt1ql3e9pgs3mmwuwrh95fecme0s0qtn2880hlwwpw\",\n", - " \"type\": \"witness_v0_keyhash\"\n", - " }\n", - " },\n", - " {\n", - " \"value\": \"0.20000000\",\n", - " \"n\": 1,\n", - " \"scriptPubKey\": {\n", - " \"asm\": \"0 d6fe05ad07a2b3a8f3b7223eeff694372032002f\",\n", - " \"desc\": \"addr(bcrt1q6mlqttg852e63uahyglwla55xusryqp08vx9w2)#c2cp77px\",\n", - " \"hex\": \"0014d6fe05ad07a2b3a8f3b7223eeff694372032002f\",\n", - " \"address\": \"bcrt1q6mlqttg852e63uahyglwla55xusryqp08vx9w2\",\n", - " \"type\": \"witness_v0_keyhash\"\n", - " }\n", - " },\n", - " {\n", - " \"value\": \"0.20000000\",\n", - " \"n\": 2,\n", - " \"scriptPubKey\": {\n", - " \"asm\": \"0 c94957ccbc70af1aec527a9d1318a2b5d16ce9c6\",\n", - " \"desc\": \"addr(bcrt1qe9y40n9uwzh34mzj02w3xx9zkhgke6wxcql4lk)#t4m8q2ue\",\n", - " \"hex\": \"0014c94957ccbc70af1aec527a9d1318a2b5d16ce9c6\",\n", - " \"address\": \"bcrt1qe9y40n9uwzh34mzj02w3xx9zkhgke6wxcql4lk\",\n", - " \"type\": \"witness_v0_keyhash\"\n", - " }\n", - " },\n", - " {\n", - " \"value\": \"0.10000000\",\n", - " \"n\": 3,\n", - " \"scriptPubKey\": {\n", - " \"asm\": \"0 03731c543b60c656c43d6459abfc212fe30de866\",\n", - " \"desc\": \"addr(bcrt1qqde3c4pmvrr9d3pav3v6hlpp9l3sm6rxnj8dcm)#y7l0a0g8\",\n", - " \"hex\": \"001403731c543b60c656c43d6459abfc212fe30de866\",\n", - " \"address\": \"bcrt1qqde3c4pmvrr9d3pav3v6hlpp9l3sm6rxnj8dcm\",\n", - " \"type\": \"witness_v0_keyhash\"\n", - " }\n", - " }\n", - " ]\n", - "}\n" - ] - } - ], + "outputs": [], "source": [ "decoded = node.decoderawtransaction(signed_tx.hex())\n", "print(json.dumps(decoded, indent=2, default=str))" @@ -698,7 +446,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -712,7 +460,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.0" + "version": "3.8.16" } }, "nbformat": 4, diff --git a/chapter2-segwitv0/p2wsh-2-of-2-multisig.ipynb b/2.3-p2wsh-2-of-2-multisig.ipynb similarity index 64% rename from chapter2-segwitv0/p2wsh-2-of-2-multisig.ipynb rename to 2.3-p2wsh-2-of-2-multisig.ipynb index b49fd33..5aad53b 100644 --- a/chapter2-segwitv0/p2wsh-2-of-2-multisig.ipynb +++ b/2.3-p2wsh-2-of-2-multisig.ipynb @@ -1,5 +1,15 @@ { "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from functions import *\n", + "import json" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -27,44 +37,6 @@ " - TestShell setup - '[P2PKH chapter](https://github.com/DariusParvin/bitcoin-tx-tutorial/blob/main/chapter1-legacy/p2pkh.ipynb)'" ] }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Setup \n", - "\n", - "### Requirements\n", - "For this exercise we'll need Bitcoin Core. This notebook has been tested with [v24.0.1](https://github.com/bitcoin/bitcoin/releases/tag/v24.0.1).\n", - "\n", - "Below, set the paths for:\n", - "1. The bitcoin core functional test framework directory.\n", - "2. The directory containing bitcoin-tx-tutorial.\n", - "\n", - "**You'll need to edit these next two lines for your local setup.**" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "path_to_bitcoin_functional_test = \"/Users/dariuscognac/bitcoin/test/functional\"\n", - "path_to_bitcoin_tx_tutorial = \"/Users/dariuscognac/Documents/Github/bitcoin-tx-tutorial\"\n", - "\n", - "import sys\n", - "\n", - "# Add the functional test framework to our PATH\n", - "sys.path.insert(0, path_to_bitcoin_functional_test)\n", - "from test_framework.test_shell import TestShell\n", - "\n", - "# Add the bitcoin-tx-tutorial functions to our PATH\n", - "sys.path.insert(0, path_to_bitcoin_tx_tutorial)\n", - "from functions import *\n", - "\n", - "import json" - ] - }, { "cell_type": "markdown", "metadata": {}, @@ -86,17 +58,9 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "5221034f355bdcb7cc0af728ef3cceb9615d90684bb5b2ca5f859ab0f0b704075871aa2102466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f2752ae\n" - ] - } - ], + "outputs": [], "source": [ "privkey1 = bytes.fromhex(\"1111111111111111111111111111111111111111111111111111111111111111\")\n", "pubkey1 = privkey_to_pubkey(privkey1)\n", @@ -128,17 +92,9 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "bcrt1qpqn5k3h89nfv6cnrkvk3rt3g0zfhqfz23cxkgapsenj29ety5ckqyrn25s\n" - ] - } - ], + "outputs": [], "source": [ "address_to_spend = script_to_p2wsh(redeemScript, \"regtest\")\n", "print(address_to_spend)" @@ -155,18 +111,9 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2022-12-29T01:40:28.907000Z TestFramework (INFO): Initializing test directory /var/folders/r5/yk8yg2xs1gs8xzkn5l8vr72w0000gn/T/bitcoin_func_test_amyyxq7f\n", - "txid: 1362ff4ca1cfefb688f3c8b2e965cfed68d8c1549d161162684920dd218b5498, 0\n" - ] - } - ], + "outputs": [], "source": [ "node = setup_testshell()\n", "txid_to_spend, index_to_spend = fund_address(node, address_to_spend, 2.001)\n", @@ -186,7 +133,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -204,7 +151,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -233,17 +180,9 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "unsigned_tx: 020000000198548b21dd2049686211169d54c1d868edcf65e9b2c8f388b6efcfa14cff62130000000000ffffffff0280d1f008000000001976a9143bc28d6d92d9073fb5e3adf481795eaf446bceed88ac80f0fa02000000001976a914cc1b07838e387deacd0e5232e1e8b49f4c29e48488ac00000000\n" - ] - } - ], + "outputs": [], "source": [ "# VERSION\n", "# version '2' indicates that we may use relative timelocks (BIP68)\n", @@ -319,60 +258,9 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{\n", - " \"txid\": \"c243d2ca9343f1bbe24b8a92e93ad37758f65428cce9a8f9b8ffb1913ac691f4\",\n", - " \"hash\": \"c243d2ca9343f1bbe24b8a92e93ad37758f65428cce9a8f9b8ffb1913ac691f4\",\n", - " \"version\": 2,\n", - " \"size\": 119,\n", - " \"vsize\": 119,\n", - " \"weight\": 476,\n", - " \"locktime\": 0,\n", - " \"vin\": [\n", - " {\n", - " \"txid\": \"1362ff4ca1cfefb688f3c8b2e965cfed68d8c1549d161162684920dd218b5498\",\n", - " \"vout\": 0,\n", - " \"scriptSig\": {\n", - " \"asm\": \"\",\n", - " \"hex\": \"\"\n", - " },\n", - " \"sequence\": 4294967295\n", - " }\n", - " ],\n", - " \"vout\": [\n", - " {\n", - " \"value\": \"1.50000000\",\n", - " \"n\": 0,\n", - " \"scriptPubKey\": {\n", - " \"asm\": \"OP_DUP OP_HASH160 3bc28d6d92d9073fb5e3adf481795eaf446bceed OP_EQUALVERIFY OP_CHECKSIG\",\n", - " \"desc\": \"addr(mkxwE7XtVYJKepoD2hbHnDjftuMQ1k6deE)#xlnzfr97\",\n", - " \"hex\": \"76a9143bc28d6d92d9073fb5e3adf481795eaf446bceed88ac\",\n", - " \"address\": \"mkxwE7XtVYJKepoD2hbHnDjftuMQ1k6deE\",\n", - " \"type\": \"pubkeyhash\"\n", - " }\n", - " },\n", - " {\n", - " \"value\": \"0.50000000\",\n", - " \"n\": 1,\n", - " \"scriptPubKey\": {\n", - " \"asm\": \"OP_DUP OP_HASH160 cc1b07838e387deacd0e5232e1e8b49f4c29e484 OP_EQUALVERIFY OP_CHECKSIG\",\n", - " \"desc\": \"addr(mz8AXDhDMhvLs7kxwfQxvcH5GoVH6AdARZ)#6f8xcf93\",\n", - " \"hex\": \"76a914cc1b07838e387deacd0e5232e1e8b49f4c29e48488ac\",\n", - " \"address\": \"mz8AXDhDMhvLs7kxwfQxvcH5GoVH6AdARZ\",\n", - " \"type\": \"pubkeyhash\"\n", - " }\n", - " }\n", - " ]\n", - "}\n" - ] - } - ], + "outputs": [], "source": [ "decoded = node.decoderawtransaction(unsigned_tx.hex())\n", "print(json.dumps(decoded, indent=2, default=str))" @@ -387,17 +275,9 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "02000000bfb56f6bdd6a0a677fe1f6e58a3e8ce287e6618d2bf487adf7b2b5fb3f6049113bb13029ce7b1f559ef5e747fcac439f1455a2ec7c5f09b72290795e7066504498548b21dd2049686211169d54c1d868edcf65e9b2c8f388b6efcfa14cff621300000000475221034f355bdcb7cc0af728ef3cceb9615d90684bb5b2ca5f859ab0f0b704075871aa2102466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f2752aea048ed0b00000000ffffffff7c27b92041484c01942ac85d0fe5ff31e92d1a54e1618e190ef3f316c4799ecf0000000001000000\n" - ] - } - ], + "outputs": [], "source": [ "scriptcode = redeemScript\n", "\n", @@ -439,19 +319,11 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": null, "metadata": { "code_folding": [] }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "signed transaction: 0200000000010198548b21dd2049686211169d54c1d868edcf65e9b2c8f388b6efcfa14cff62130000000000ffffffff0280d1f008000000001976a9143bc28d6d92d9073fb5e3adf481795eaf446bceed88ac80f0fa02000000001976a914cc1b07838e387deacd0e5232e1e8b49f4c29e48488ac040047304402207894d3ba08df43e2a35e6eadbad445ad62a595a82b746a30185c9b46d0ec4b370220312601e8d6fad65735b2e0b625aa6bfbebbe15e6884021222f7c46429cf2519a0147304402207183b76dab31b3173c9822fd62f7efb1faf1c45c3d8237e13690eba04cfea3f502204657fb32d9ff731afad2c9b55a99bbc54fa49c6de1676f41122cb7b5131e9d0301475221034f355bdcb7cc0af728ef3cceb9615d90684bb5b2ca5f859ab0f0b704075871aa2102466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f2752ae00000000\n" - ] - } - ], + "outputs": [], "source": [ "# Create sigHash to be signed\n", "sighash = hash256(tx_digest_preimage)\n", @@ -506,17 +378,9 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "c243d2ca9343f1bbe24b8a92e93ad37758f65428cce9a8f9b8ffb1913ac691f4\n" - ] - } - ], + "outputs": [], "source": [ "new_tx_txid = node.sendrawtransaction(signed_tx.hex())\n", "# result = node.testmempoolaccept(rawtxs=[signed_tx.hex()])\n", @@ -525,66 +389,9 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{\n", - " \"txid\": \"c243d2ca9343f1bbe24b8a92e93ad37758f65428cce9a8f9b8ffb1913ac691f4\",\n", - " \"hash\": \"eb53fe0f9c4b5edec8f81d5b05da2b49af2d4306f81328746d4c53d16762aaec\",\n", - " \"version\": 2,\n", - " \"size\": 339,\n", - " \"vsize\": 174,\n", - " \"weight\": 696,\n", - " \"locktime\": 0,\n", - " \"vin\": [\n", - " {\n", - " \"txid\": \"1362ff4ca1cfefb688f3c8b2e965cfed68d8c1549d161162684920dd218b5498\",\n", - " \"vout\": 0,\n", - " \"scriptSig\": {\n", - " \"asm\": \"\",\n", - " \"hex\": \"\"\n", - " },\n", - " \"txinwitness\": [\n", - " \"\",\n", - " \"304402207894d3ba08df43e2a35e6eadbad445ad62a595a82b746a30185c9b46d0ec4b370220312601e8d6fad65735b2e0b625aa6bfbebbe15e6884021222f7c46429cf2519a01\",\n", - " \"304402207183b76dab31b3173c9822fd62f7efb1faf1c45c3d8237e13690eba04cfea3f502204657fb32d9ff731afad2c9b55a99bbc54fa49c6de1676f41122cb7b5131e9d0301\",\n", - " \"5221034f355bdcb7cc0af728ef3cceb9615d90684bb5b2ca5f859ab0f0b704075871aa2102466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f2752ae\"\n", - " ],\n", - " \"sequence\": 4294967295\n", - " }\n", - " ],\n", - " \"vout\": [\n", - " {\n", - " \"value\": \"1.50000000\",\n", - " \"n\": 0,\n", - " \"scriptPubKey\": {\n", - " \"asm\": \"OP_DUP OP_HASH160 3bc28d6d92d9073fb5e3adf481795eaf446bceed OP_EQUALVERIFY OP_CHECKSIG\",\n", - " \"desc\": \"addr(mkxwE7XtVYJKepoD2hbHnDjftuMQ1k6deE)#xlnzfr97\",\n", - " \"hex\": \"76a9143bc28d6d92d9073fb5e3adf481795eaf446bceed88ac\",\n", - " \"address\": \"mkxwE7XtVYJKepoD2hbHnDjftuMQ1k6deE\",\n", - " \"type\": \"pubkeyhash\"\n", - " }\n", - " },\n", - " {\n", - " \"value\": \"0.50000000\",\n", - " \"n\": 1,\n", - " \"scriptPubKey\": {\n", - " \"asm\": \"OP_DUP OP_HASH160 cc1b07838e387deacd0e5232e1e8b49f4c29e484 OP_EQUALVERIFY OP_CHECKSIG\",\n", - " \"desc\": \"addr(mz8AXDhDMhvLs7kxwfQxvcH5GoVH6AdARZ)#6f8xcf93\",\n", - " \"hex\": \"76a914cc1b07838e387deacd0e5232e1e8b49f4c29e48488ac\",\n", - " \"address\": \"mz8AXDhDMhvLs7kxwfQxvcH5GoVH6AdARZ\",\n", - " \"type\": \"pubkeyhash\"\n", - " }\n", - " }\n", - " ]\n", - "}\n" - ] - } - ], + "outputs": [], "source": [ "decoded = node.decoderawtransaction(signed_tx.hex())\n", "print(json.dumps(decoded, indent=2, default=str))" @@ -638,7 +445,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -652,7 +459,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.0" + "version": "3.8.16" } }, "nbformat": 4, diff --git a/chapter3-taproot/schnorr-sig-and-taptweak.ipynb b/3.1-schnorr-sig-and-taptweak.ipynb similarity index 89% rename from chapter3-taproot/schnorr-sig-and-taptweak.ipynb rename to 3.1-schnorr-sig-and-taptweak.ipynb index 36df480..4cec634 100644 --- a/chapter3-taproot/schnorr-sig-and-taptweak.ipynb +++ b/3.1-schnorr-sig-and-taptweak.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "id": "d758f205", "metadata": {}, "outputs": [], @@ -60,7 +60,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "id": "3e6b7f7d", "metadata": {}, "outputs": [], @@ -86,23 +86,10 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "id": "531055c8", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Private key: 0000000000000000000000000000000000000000000000000000000000000001\n", - "Public key: 79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798\n", - "\n", - "Signature: 4791b03f4381ddd5f22847d1c736e64d1d8d02f90af83a1373bb6392aae8d132660cc589d47e13a40c6bce2a408887d56f7ecac3895b9a9e5d75fe78b6f2478e\n", - "\n", - "Success!\n" - ] - } - ], + "outputs": [], "source": [ "# Generate a key pair\n", "privkey = bytes.fromhex(\"0000000000000000000000000000000000000000000000000000000000000001\")\n", @@ -170,22 +157,10 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "id": "5953a2c1", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "We can generate the tweaked pubkey using two methods\n", - "Tweaked pubkey generated using tweaked private key: 9cb4c69dbe5678869d52e5c875681cf2f02ea689bc6152ce9e1fb624189349b0\n", - "Tweaked pubkey generated without private key: 9cb4c69dbe5678869d52e5c875681cf2f02ea689bc6152ce9e1fb624189349b0\n", - "\n", - "The signature produced with the tweaked private key was valid against the tweaked public key!\n" - ] - } - ], + "outputs": [], "source": [ "# Generate a key pair\n", "privkey = bytes.fromhex(\"0000000000000000000000000000000000000000000000000000000000000004\")\n", @@ -252,28 +227,10 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "id": "47cadb23", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Original private key: 0000000000000000000000000000000000000000000000000000000000000004\n", - "Contract being committed to: Alice agrees to pay 10 BTC to Bob\n", - "Tweaked pubkey : 9cb4c69dbe5678869d52e5c875681cf2f02ea689bc6152ce9e1fb624189349b0\n", - "\n", - "Modify the contract to: Alice agrees to pay 0.1 BTC to Bob\n", - "\n", - "Calculate a new private key by subtracting the modified contract from the previous tweaked private key\n", - "New private key: 5ddf2900cc4058ccb0e60378da37ffbfcd276c24ea39e4925824f5c4fce2110c\n", - "\n", - "Resulting in the same tweaked pubkey as with the previous commitment!\n", - "Tweaked pubkey : 9cb4c69dbe5678869d52e5c875681cf2f02ea689bc6152ce9e1fb624189349b0\n" - ] - } - ], + "outputs": [], "source": [ "# The original values for reference\n", "print(\"Original private key: \", privkey.hex())\n", @@ -339,7 +296,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "id": "c0a78ea7", "metadata": {}, "outputs": [], @@ -388,7 +345,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -402,7 +359,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.0" + "version": "3.8.16" } }, "nbformat": 4, diff --git a/chapter3-taproot/taproot-taptree.ipynb b/3.2-taproot-taptree.ipynb similarity index 86% rename from chapter3-taproot/taproot-taptree.ipynb rename to 3.2-taproot-taptree.ipynb index 38166cb..ca94620 100644 --- a/chapter3-taproot/taproot-taptree.ipynb +++ b/3.2-taproot-taptree.ipynb @@ -1,41 +1,22 @@ { "cells": [ { - "cell_type": "markdown", + "cell_type": "code", + "execution_count": null, "metadata": {}, + "outputs": [], "source": [ - "# Taproot TapTree\n", - "\n", - "- The following material adapted from the Bitcoin Optech [Schnorr Taproot workshop](https://bitcoinops.org/en/schorr-taproot-workshop/)." + "from functions import *\n", + "from functions.bip_0340_reference import *" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Setup \n", - "**You'll need to edit these next two lines for your local setup.**" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "path_to_bitcoin_functional_test = \"/Users/dariuscognac/bitcoin/test/functional\"\n", - "path_to_bitcoin_tx_tutorial = \"/Users/dariuscognac/Documents/Github/bitcoin-tx-tutorial\"\n", - "\n", - "import sys\n", - "\n", - "# Add the functional test framework to our PATH\n", - "sys.path.insert(0, path_to_bitcoin_functional_test)\n", - "from test_framework.test_shell import TestShell\n", + "# Taproot TapTree\n", "\n", - "# Add the bitcoin-tx-tutorial functions to our PATH\n", - "sys.path.insert(0, path_to_bitcoin_tx_tutorial)\n", - "from functions import *\n", - "from functions.bip_0340_reference import *" + "- The following material adapted from the Bitcoin Optech [Schnorr Taproot workshop](https://bitcoinops.org/en/schorr-taproot-workshop/)." ] }, { @@ -74,7 +55,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -108,18 +89,9 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "TapTweak: 8e53fc0da2e9e8e27404703010ae519e85576ef6c73dde1b2bffac7f17b114a9\n", - "Bech32m address: bcrt1p5jhcyymfj7tkgv0jca4pz7tx9uzvznu0mlfymey6ph63f9h8x0gs7683vc\n" - ] - } - ], + "outputs": [], "source": [ "TAPSCRIPT_VER = bytes([0xc0]) # This is currently the only tapscript version. In future there may be others.\n", "internal_privkey = bytes.fromhex(\"83a5f1039118fbb4276cac2db41d236c1c1790d97d955c228fa3bde439fbec2a\")\n", @@ -193,7 +165,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -207,7 +179,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.0" + "version": "3.8.16" } }, "nbformat": 4, diff --git a/chapter3-taproot/p2tr-key-and-script-path.ipynb b/3.3-p2tr-key-and-script-path.ipynb similarity index 82% rename from chapter3-taproot/p2tr-key-and-script-path.ipynb rename to 3.3-p2tr-key-and-script-path.ipynb index a6ba56e..7d9b764 100644 --- a/chapter3-taproot/p2tr-key-and-script-path.ipynb +++ b/3.3-p2tr-key-and-script-path.ipynb @@ -1,5 +1,16 @@ { "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from functions import *\n", + "from functions.bip_0340_reference import *\n", + "import json" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -29,45 +40,6 @@ " - [Signature hash evolution](https://github.com/DariusParvin/bitcoin-tx-tutorial/blob/main/appendix/sighash_evolution.ipynb)" ] }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Setup \n", - "\n", - "### Requirements\n", - "For this exercise we'll need Bitcoin Core. This notebook has been tested with [v24.0.1](https://github.com/bitcoin/bitcoin/releases/tag/v24.0.1).\n", - "\n", - "Below, set the paths for:\n", - "1. The bitcoin core functional test framework directory.\n", - "2. The directory containing bitcoin-tx-tutorial.\n", - "\n", - "**You'll need to edit these next two lines for your local setup.**" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "path_to_bitcoin_functional_test = \"/Users/dariuscognac/bitcoin/test/functional\"\n", - "path_to_bitcoin_tx_tutorial = \"/Users/dariuscognac/Documents/Github/bitcoin-tx-tutorial\"\n", - "\n", - "import sys\n", - "\n", - "# Add the functional test framework to our PATH\n", - "sys.path.insert(0, path_to_bitcoin_functional_test)\n", - "from test_framework.test_shell import TestShell\n", - "\n", - "# Add the bitcoin-tx-tutorial functions to our PATH\n", - "sys.path.insert(0, path_to_bitcoin_tx_tutorial)\n", - "from functions import *\n", - "from functions.bip_0340_reference import *\n", - "\n", - "import json" - ] - }, { "cell_type": "markdown", "metadata": {}, @@ -99,18 +71,9 @@ }, { "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "TapTweak: 8e53fc0da2e9e8e27404703010ae519e85576ef6c73dde1b2bffac7f17b114a9\n", - "Bech32m address: bcrt1p5jhcyymfj7tkgv0jca4pz7tx9uzvznu0mlfymey6ph63f9h8x0gs7683vc\n" - ] - } - ], + "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ "TAPSCRIPT_VER = bytes([0xc0])\n", "internal_privkey = bytes.fromhex(\"83a5f1039118fbb4276cac2db41d236c1c1790d97d955c228fa3bde439fbec2a\")\n", @@ -169,18 +132,9 @@ }, { "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2023-01-01T09:42:22.576000Z TestFramework (INFO): Initializing test directory /var/folders/r5/yk8yg2xs1gs8xzkn5l8vr72w0000gn/T/bitcoin_func_test_a30mhq8s\n", - "txid: 5e61d25df2ca61d6be58b98a434e3ddd7d70dabd5a0c38bff8c97df40c02420f, 1\n" - ] - } - ], + "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ "node = setup_testshell()\n", "txid_to_spend, index_to_spend = fund_address(node, bech32m_address, 2.001)\n", @@ -201,7 +155,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -217,20 +171,9 @@ }, { "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'0014531260aa2a199e228c537dfa42c82bea2c7c1f4d'" - ] - }, - "execution_count": 5, - "metadata": {}, - "output_type": "execute_result" - } - ], + "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ "# Set the output scriptPubkeys and amounts\n", "output1_value_sat = int(float(\"1.5\") * 100000000)\n", @@ -242,17 +185,9 @@ }, { "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "unsigned_tx: 02000000010f42020cf47dc9f8bf380c5abdda707ddd3d4e438ab958bed661caf25dd2615e0100000000ffffffff0280d1f00800000000160014fc7250a211deddc70ee5a2738de5f07817351cef80f0fa0200000000160014531260aa2a199e228c537dfa42c82bea2c7c1f4d00000000\n" - ] - } - ], + "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ "# VERSION\n", "# version '2' indicates that we may use relative timelocks (BIP68)\n", @@ -330,7 +265,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -386,7 +321,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -405,18 +340,9 @@ }, { "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "0140ae7803efebf0bd7bfdf5a3d7cdd18a77190d08288a72f6bc28261be426cfd7b65055f6f324e0cc7b3e62c03ad4eaf301cc7851bde78031f759e1abaec9921764\n", - "signed transaction: 020000000001010f42020cf47dc9f8bf380c5abdda707ddd3d4e438ab958bed661caf25dd2615e0100000000ffffffff0280d1f00800000000160014fc7250a211deddc70ee5a2738de5f07817351cef80f0fa0200000000160014531260aa2a199e228c537dfa42c82bea2c7c1f4d0140ae7803efebf0bd7bfdf5a3d7cdd18a77190d08288a72f6bc28261be426cfd7b65055f6f324e0cc7b3e62c03ad4eaf301cc7851bde78031f759e1abaec992176400000000\n" - ] - } - ], + "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ "witness = (\n", " bytes.fromhex(\"01\") # one stack item in the witness\n", @@ -442,17 +368,9 @@ }, { "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[{'txid': '92a4387f65646140ccb75a611874d58defb94a3a7bb46b0ba4d59ef87e29aec9', 'wtxid': 'bdeeda66b862d30a3dffecc9fad27c46490bc677b96e550c265ff7e1101830ef', 'allowed': True, 'vsize': 130, 'fees': {'base': Decimal('0.00100000')}}]\n" - ] - } - ], + "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ "result = node.testmempoolaccept(rawtxs=[signed_tx.hex()])\n", "print(result)" @@ -479,7 +397,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -495,17 +413,9 @@ }, { "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "e9877ad0b9a7a935c5c8e9cb819afa130f26036e5623388c895cb45b55c3e7f6\n" - ] - } - ], + "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ "sighash_epoch = bytes.fromhex(\"00\")\n", "index_of_this_input = bytes.fromhex(\"0000 0000\")\n", @@ -563,7 +473,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -604,7 +514,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -627,17 +537,9 @@ }, { "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "signed transaction: 020000000001010f42020cf47dc9f8bf380c5abdda707ddd3d4e438ab958bed661caf25dd2615e0100000000ffffffff0280d1f00800000000160014fc7250a211deddc70ee5a2738de5f07817351cef80f0fa0200000000160014531260aa2a199e228c537dfa42c82bea2c7c1f4d03408624784388d931c6155db7f44ef7a503a10e36cea2c2354cdbdbf8b8d6ade9d3ef2e5f173299768e56d66bdb1ccc2d32eebf1cabfb435a1001343425219fb42c2220731bbf2e7163d87b12d66d3795655790691e59802fd1c578c2e06287555e3c28ac61c1031845925dcca99bc5689ce422b9204ff9721de8416b984b8a6b930e30352225a1494f24cfdfc93532412675eece318c63414dd02b8750947177b141e082076e2b71b71e05a8cd9771485b9248025e46871caa6585164a1fdf9e634d61023fd800000000\n" - ] - } - ], + "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ "witness = (\n", " bytes.fromhex(\"03\") \n", @@ -667,17 +569,9 @@ }, { "cell_type": "code", - "execution_count": 16, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[{'txid': '92a4387f65646140ccb75a611874d58defb94a3a7bb46b0ba4d59ef87e29aec9', 'wtxid': 'bdeeda66b862d30a3dffecc9fad27c46490bc677b96e550c265ff7e1101830ef', 'allowed': True, 'vsize': 130, 'fees': {'base': Decimal('0.00100000')}}]\n" - ] - } - ], + "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ "result = node.testmempoolaccept(rawtxs=[signed_tx.hex()])\n", "print(result)" @@ -717,7 +611,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -731,7 +625,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.0" + "version": "3.8.16" } }, "nbformat": 4, diff --git a/chapter4-sighash/sighash-evolution.ipynb b/4.1-sighash-evolution.ipynb similarity index 92% rename from chapter4-sighash/sighash-evolution.ipynb rename to 4.1-sighash-evolution.ipynb index 18604b6..b23dbcb 100644 --- a/chapter4-sighash/sighash-evolution.ipynb +++ b/4.1-sighash-evolution.ipynb @@ -1,5 +1,14 @@ { "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from functions import *" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -12,31 +21,7 @@ " - A conceptual understanding of [hash functions](https://www.thesslstore.com/blog/what-is-a-hash-function-in-cryptography-a-beginners-guide).\n", " - [Hexadecimal notation](https://inst.eecs.berkeley.edu/~cs61bl/r//cur/bits/decimal-binary-hex.html?topic=lab28.topic&step=2&course=) and [endianness](https://www.freecodecamp.org/news/what-is-endianness-big-endian-vs-little-endian/).\n", "- Specific to this notebook:\n", - " - SHA256, HASH256, HASH160 - '[Hash Functions chapter](https://github.com/DariusParvin/bitcoin-tx-tutorial/blob/main/appendix/hash-functions.ipynb)'\n", - "\n", - "\n", - "## Setup \n", - "**You'll need to edit these next two lines for your local setup.**" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "path_to_bitcoin_functional_test = \"/Users/dariuscognac/bitcoin/test/functional\"\n", - "path_to_bitcoin_tx_tutorial = \"/Users/dariuscognac/Documents/Github/bitcoin-tx-tutorial\"\n", - "\n", - "import sys\n", - "\n", - "# Add the functional test framework to our PATH\n", - "sys.path.insert(0, path_to_bitcoin_functional_test)\n", - "from test_framework.test_shell import TestShell\n", - "\n", - "# Add the bitcoin-tx-tutorial functions to our PATH\n", - "sys.path.insert(0, path_to_bitcoin_tx_tutorial)\n", - "from functions import *" + " - SHA256, HASH256, HASH160 - '[Hash Functions chapter](./0.2-hash-functions.ipynb)'\n" ] }, { @@ -64,7 +49,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -83,7 +68,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -125,7 +110,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -167,7 +152,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -181,17 +166,9 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Legacy sighash digest: 7afc74798a481b78b0d2dacb11f043e3b0b21311cfe6864a7e4acef56791e3b7\n" - ] - } - ], + "outputs": [], "source": [ "# STEP 1: replace the empty scriptSig with the input scriptPubkey\n", "tx_digest_preimage = (\n", @@ -246,7 +223,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -260,17 +237,9 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Segwit v0 sighash digest: da5f24608b19b11542beee4c3787b218f58d7f3686fce49c8c30911badfb2aed\n" - ] - } - ], + "outputs": [], "source": [ "# weakness 2 - The value of the input amount is now included in the sighash. Therefore a cold wallet cannot \n", "# be 'tricked' into signing off on an input with a different amount than anticipated (which would normally \n", @@ -340,7 +309,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -371,17 +340,9 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Taproot sighash digest: eba91a23cb1f908e27f2e9a44c28ea127a9ce724c25b97786a0e53fd24a186e6\n" - ] - } - ], + "outputs": [], "source": [ "# Future versions may use a different sighash epoc for different sighash algorithms\n", "sighash_epoch = bytes.fromhex(\"00\") \n", @@ -468,7 +429,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -482,7 +443,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.0" + "version": "3.8.16" } }, "nbformat": 4, diff --git a/chapter4-sighash/sighash-flags.ipynb b/4.2-sighash-flags.ipynb similarity index 79% rename from chapter4-sighash/sighash-flags.ipynb rename to 4.2-sighash-flags.ipynb index 67bfbb2..ec3e9b9 100644 --- a/chapter4-sighash/sighash-flags.ipynb +++ b/4.2-sighash-flags.ipynb @@ -1,5 +1,16 @@ { "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from functions import *\n", + "from functions.bip_0340_reference import *\n", + "import json" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -24,45 +35,10 @@ "\n", "\n", "- Specific to this notebook:\n", - " - SHA256, HASH256, HASH160 - '[Hash Functions chapter](https://github.com/DariusParvin/bitcoin-tx-tutorial/blob/main/appendix/hash-functions.ipynb)'\n", - " - Base58 addresses - '[Addresses chapter](https://github.com/DariusParvin/bitcoin-tx-tutorial/blob/main/appendix/Addresses.ipynb)'\n", - " - Bitcoin Script basics - '[Bitcoin Script chapter](https://github.com/DariusParvin/bitcoin-tx-tutorial/blob/main/appendix/Bitcoin%20Script.ipynb)'\n", - " - TestShell setup - '[P2PKH chapter](https://github.com/DariusParvin/bitcoin-tx-tutorial/blob/main/chapter1-legacy/p2pkh.ipynb)'\n", - "\n", - "\n", - "## Setup \n", - "\n", - "### Requirements\n", - "For this exercise we'll need Bitcoin Core. This notebook has been tested with [v24.0.1](https://github.com/bitcoin/bitcoin/releases/tag/v24.0.1).\n", - "\n", - "Below, set the paths for:\n", - "1. The bitcoin core functional test framework directory.\n", - "2. The directory containing bitcoin-tx-tutorial.\n", - "\n", - "**You'll need to edit these next two lines for your local setup.**" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "path_to_bitcoin_functional_test = \"/Users/dariuscognac/bitcoin/test/functional\"\n", - "path_to_bitcoin_tx_tutorial = \"/Users/dariuscognac/Documents/Github/bitcoin-tx-tutorial\"\n", - "\n", - "import sys\n", - "\n", - "# Add the functional test framework to our PATH\n", - "sys.path.insert(0, path_to_bitcoin_functional_test)\n", - "from test_framework.test_shell import TestShell\n", - "\n", - "# Add the bitcoin-tx-tutorial functions to our PATH\n", - "sys.path.insert(0, path_to_bitcoin_tx_tutorial)\n", - "from functions import *\n", - "from functions.bip_0340_reference import *\n", - "\n", - "import json" + " - SHA256, HASH256, HASH160 - '[Hash Functions chapter](./0.2-hash-functions.ipynb)'\n", + " - Base58 addresses - '[Addresses chapter](./0.4-addresses.ipynb)'\n", + " - Bitcoin Script basics - '[Bitcoin Script chapter](./0.3-bitcoin-script.ipynb)'\n", + " - TestShell setup - '[P2PKH chapter](./1.2-p2pkh.ipynb)'\n" ] }, { @@ -97,7 +73,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -122,19 +98,9 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2022-12-08T11:02:52.304000Z TestFramework (INFO): Initializing test directory /var/folders/r5/yk8yg2xs1gs8xzkn5l8vr72w0000gn/T/bitcoin_func_test_iwmc14gg\n", - "Cold wallet UTXO: 6697e6a4cb3d06f4c8342583d8158a51513aedfa404514f4af740a222371431d, 0\n", - "Hot wallet UTXO: 57bc2605d0218b4709f3eed074e998b51dd6998723a1024002f51df40c3f5044, 1\n" - ] - } - ], + "outputs": [], "source": [ "# Setup bitcoind and fund the addresses\n", "node = setup_testshell()\n", @@ -155,7 +121,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -209,17 +175,9 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "18b9b42c3ce105eccf440ae37be7794003358a659b0c9b57b4d1cb6581ac2a61\n" - ] - } - ], + "outputs": [], "source": [ "sighash_epoch = bytes.fromhex(\"00\")\n", "\n", @@ -277,17 +235,9 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Signature for the cold wallet UTXO: 493b33b734db4e9a779b92c1f224590db29c2c960ba08ff67fcadfbe9073b1f39c995c7cf604e3ac9a6cd12bf26297a9573d2083c54db5a36a85f34221d9ea6a02\n" - ] - } - ], + "outputs": [], "source": [ "# Sign the partial transaction\n", "aux_rand = bytes.fromhex(\"0000000000000000000000000000000000000000000000000000000000000000\")\n", @@ -317,7 +267,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -341,17 +291,9 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "unsigned_tx: 02000000021d437123220a74aff4144540faed3a51518a15d8832534c8f4063dcba4e697660000000000ffffffff44503f0cf41df5024002a1238799d61db598e974d0eef309478b21d00526bc570100000000ffffffff020068890900000000160014fc7250a211deddc70ee5a2738de5f07817351cef80f0fa0200000000160014531260aa2a199e228c537dfa42c82bea2c7c1f4d00000000\n" - ] - } - ], + "outputs": [], "source": [ "# OUTPUTS\n", "# 0x02 for two outputs\n", @@ -388,17 +330,9 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Signature for the hot wallet UTXO: cfb72ddd898c4ead3f932655c5e8da293ff9405e78653cb9bbd33482cf9ce01689e2f31522549a5cc7e028553adc00572bc8be22f41533a8484b7127ae50a3cb\n" - ] - } - ], + "outputs": [], "source": [ "# Create Signature for Hot Wallet UTXO\n", "sighash_epoch = bytes.fromhex(\"00\")\n", @@ -447,17 +381,9 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "signed transaction: 020000000001021d437123220a74aff4144540faed3a51518a15d8832534c8f4063dcba4e697660000000000ffffffff44503f0cf41df5024002a1238799d61db598e974d0eef309478b21d00526bc570100000000ffffffff020068890900000000160014fc7250a211deddc70ee5a2738de5f07817351cef80f0fa0200000000160014531260aa2a199e228c537dfa42c82bea2c7c1f4d0141493b33b734db4e9a779b92c1f224590db29c2c960ba08ff67fcadfbe9073b1f39c995c7cf604e3ac9a6cd12bf26297a9573d2083c54db5a36a85f34221d9ea6a020140cfb72ddd898c4ead3f932655c5e8da293ff9405e78653cb9bbd33482cf9ce01689e2f31522549a5cc7e028553adc00572bc8be22f41533a8484b7127ae50a3cb00000000\n" - ] - } - ], + "outputs": [], "source": [ "witness = (\n", " bytes.fromhex(\"01\") # one stack item in the witness for input 1\n", @@ -491,17 +417,9 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[{'txid': '51eb1f909586cad13a8778301cfe444145cbff4407789bdc17b6035e0f0c24a6', 'wtxid': '5e9b4f4e82eff99b4276661c1d00986b69b26788a41a62bf0f06b389df7a72d5', 'allowed': True, 'vsize': 188, 'fees': {'base': Decimal('0.00200000')}}]\n" - ] - } - ], + "outputs": [], "source": [ "result = node.testmempoolaccept(rawtxs=[signed_tx.hex()])\n", "print(result)" @@ -541,7 +459,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -555,7 +473,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.0" + "version": "3.8.16" } }, "nbformat": 4, diff --git a/chapter5-timelocks/transaction-level-timelocks.ipynb b/5.1.transaction-level-timelocks.ipynb similarity index 80% rename from chapter5-timelocks/transaction-level-timelocks.ipynb rename to 5.1.transaction-level-timelocks.ipynb index 01dfb43..4fe519b 100644 --- a/chapter5-timelocks/transaction-level-timelocks.ipynb +++ b/5.1.transaction-level-timelocks.ipynb @@ -1,5 +1,15 @@ { "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from functions import *\n", + "import json" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -32,44 +42,6 @@ "- https://medium.com/summa-technology/bitcoins-time-locks-27e0c362d7a1" ] }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Setup \n", - "\n", - "### Requirements\n", - "For this exercise we'll need Bitcoin Core. This notebook has been tested with [v24.0.1](https://github.com/bitcoin/bitcoin/releases/tag/v24.0.1).\n", - "\n", - "Below, set the paths for:\n", - "1. The bitcoin core functional test framework directory.\n", - "2. The directory containing bitcoin-tx-tutorial.\n", - "\n", - "**You'll need to edit these next two lines for your local setup.**" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "path_to_bitcoin_functional_test = \"/Users/dariuscognac/bitcoin/test/functional\"\n", - "path_to_bitcoin_tx_tutorial = \"/Users/dariuscognac/Documents/Github/bitcoin-tx-tutorial\"\n", - "\n", - "import sys\n", - "\n", - "# Add the functional test framework to our PATH\n", - "sys.path.insert(0, path_to_bitcoin_functional_test)\n", - "from test_framework.test_shell import TestShell\n", - "\n", - "# Add the bitcoin-tx-tutorial functions to our PATH\n", - "sys.path.insert(0, path_to_bitcoin_tx_tutorial)\n", - "from functions import *\n", - "\n", - "import json" - ] - }, { "cell_type": "markdown", "metadata": {}, @@ -91,17 +63,9 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "sender's p2wpkh address: bcrt1ql3e9pgs3mmwuwrh95fecme0s0qtn2880hlwwpw\n" - ] - } - ], + "outputs": [], "source": [ "sender_privkey = bytes.fromhex(\"1111111111111111111111111111111111111111111111111111111111111111\")\n", "sender_pubkey = privkey_to_pubkey(sender_privkey)\n", @@ -120,18 +84,9 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2022-12-08T11:20:14.091000Z TestFramework (INFO): Initializing test directory /var/folders/r5/yk8yg2xs1gs8xzkn5l8vr72w0000gn/T/bitcoin_func_test_6cipa0pr\n", - "txid: f8830ec636a360ca9dc0f267ab7f29d2675a7066a9b405c1ae9e22664ffba557, 1\n" - ] - } - ], + "outputs": [], "source": [ "node = setup_testshell()\n", "txid_to_spend, index_to_spend = fund_address(node, address_to_spend, 0.101)\n", @@ -149,7 +104,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -168,17 +123,9 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "nLocktime: f4010000\n" - ] - } - ], + "outputs": [], "source": [ "# let's suppose Peter's 18th birthday is estimated to happen at block 500\n", "locktime_int = 500\n", @@ -195,17 +142,9 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "sequence: fffffffe\n" - ] - } - ], + "outputs": [], "source": [ "sequence = bytes.fromhex(\"ffff fffe\")\n", "print(\"sequence: \", sequence.hex())" @@ -227,17 +166,9 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "unsigned_tx: 020000000157a5fb4f66229eaec105b4a966705a67d2297fab67f2c09dca60a336c60e83f80100000000fffffffe018096980000000000160014fc7250a211deddc70ee5a2738de5f07817351ceff4010000\n" - ] - } - ], + "outputs": [], "source": [ "# VERSION\n", "# version '2' indicates that we may use relative timelocks (BIP68)\n", @@ -310,17 +241,9 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "020000006e1879543ea79c0888efd4bae2fdd50e17092fe09f62280152b5e2eb69ce37c9bbdebfac1cd12080fb29f8919f7f8be7bdb21a89c8d09e8a59fc7bb1d2a7379657a5fb4f66229eaec105b4a966705a67d2297fab67f2c09dca60a336c60e83f8010000001976a914fc7250a211deddc70ee5a2738de5f07817351cef88ac201d9a0000000000fffffffe62580c97423350cc6d13c95a8203b8dd1962f9f34ecaa00a7542aa14f6e2b1a3f401000001000000\n" - ] - } - ], + "outputs": [], "source": [ "pk_hash = hash160(sender_pubkey)\n", "scriptcode = bytes.fromhex(\"76a914\" + pk_hash.hex() + \"88ac\")\n", @@ -359,19 +282,11 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": null, "metadata": { "code_folding": [] }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "signed transaction: 0200000000010157a5fb4f66229eaec105b4a966705a67d2297fab67f2c09dca60a336c60e83f80100000000fffffffe018096980000000000160014fc7250a211deddc70ee5a2738de5f07817351cef024730440220233a739ab1642554ee0f57b6ff17082b5e7f955936ae20ba4be8587991de0f82022005b2c09aa396cd20ad0de873091e855cdec82d56253f45c08da1b886e28242eb0121034f355bdcb7cc0af728ef3cceb9615d90684bb5b2ca5f859ab0f0b704075871aaf4010000\n" - ] - } - ], + "outputs": [], "source": [ "# Create sigHash to be signed\n", "sighash = hash256(tx_digest_preimage)\n", @@ -429,18 +344,9 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Blockchain height: 102\n", - "[{'txid': '7e4c8a4f7cc87d6ce28c180257eb4a13d558629d5cb97a37ec98c39bb123d83c', 'wtxid': '93266ce4276f2aa549adeb4f293a5eb02c40e435d479608d400ff11f0ed1529a', 'allowed': False, 'reject-reason': 'non-final'}]\n" - ] - } - ], + "outputs": [], "source": [ "height = node.getblockcount()\n", "print(\"Blockchain height: \", height)\n", @@ -458,18 +364,9 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Blockchain height: 500\n", - "[{'txid': '7e4c8a4f7cc87d6ce28c180257eb4a13d558629d5cb97a37ec98c39bb123d83c', 'wtxid': '93266ce4276f2aa549adeb4f293a5eb02c40e435d479608d400ff11f0ed1529a', 'allowed': True, 'vsize': 110, 'fees': {'base': Decimal('0.00100000')}}]\n" - ] - } - ], + "outputs": [], "source": [ "node.generate(398, invalid_call=False)\n", "height = node.getblockcount()\n", @@ -490,7 +387,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -570,7 +467,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -584,7 +481,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.0" + "version": "3.8.16" } }, "nbformat": 4, diff --git a/chapter5-timelocks/script-level-timelocks.ipynb b/5.2-script-level-timelocks.ipynb similarity index 74% rename from chapter5-timelocks/script-level-timelocks.ipynb rename to 5.2-script-level-timelocks.ipynb index 4d68bed..e0ad7a6 100644 --- a/chapter5-timelocks/script-level-timelocks.ipynb +++ b/5.2-script-level-timelocks.ipynb @@ -1,5 +1,15 @@ { "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from functions import *\n", + "import json" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -29,41 +39,7 @@ "\n", "\n", "### Further Reading\n", - "- https://medium.com/summa-technology/bitcoins-time-locks-27e0c362d7a1\n", - "\n", - "\n", - "## Setup \n", - "\n", - "### Requirements\n", - "For this exercise we'll need Bitcoin Core. This notebook has been tested with [v24.0.1](https://github.com/bitcoin/bitcoin/releases/tag/v24.0.1).\n", - "\n", - "Below, set the paths for:\n", - "1. The bitcoin core functional test framework directory.\n", - "2. The directory containing bitcoin-tx-tutorial.\n", - "\n", - "**You'll need to edit these next two lines for your local setup.**" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "path_to_bitcoin_functional_test = \"/Users/dariuscognac/bitcoin/test/functional\"\n", - "path_to_bitcoin_tx_tutorial = \"/Users/dariuscognac/Documents/Github/bitcoin-tx-tutorial\"\n", - "\n", - "import sys\n", - "\n", - "# Add the functional test framework to our PATH\n", - "sys.path.insert(0, path_to_bitcoin_functional_test)\n", - "from test_framework.test_shell import TestShell\n", - "\n", - "# Add the bitcoin-tx-tutorial functions to our PATH\n", - "sys.path.insert(0, path_to_bitcoin_tx_tutorial)\n", - "from functions import *\n", - "\n", - "import json" + "- https://medium.com/summa-technology/bitcoins-time-locks-27e0c362d7a1\n" ] }, { @@ -97,18 +73,9 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "sequence: fffffffe\n", - "02f401b1752102466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f27ac\n" - ] - } - ], + "outputs": [], "source": [ "# Set a public key for the receiver (Peter)\n", "receiver_privkey = bytes.fromhex(\"2222222222222222222222222222222222222222222222222222222222222222\")\n", @@ -144,17 +111,9 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "bcrt1qd75w96efgck0afp7zxarmhmzp2zjmzq0khkdf0fpaasrzl09m6aszmc5kn\n" - ] - } - ], + "outputs": [], "source": [ "address_to_spend = script_to_p2wsh(redeemScript, \"regtest\")\n", "print(address_to_spend)" @@ -170,18 +129,9 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2022-12-08T11:15:24.191000Z TestFramework (INFO): Initializing test directory /var/folders/r5/yk8yg2xs1gs8xzkn5l8vr72w0000gn/T/bitcoin_func_test_1tq57_mj\n", - "txid: e248baa92bf049bef96d7d0317dc60cda5bd8f0e63745ddf11c579a1eb365ab9, 1\n" - ] - } - ], + "outputs": [], "source": [ "node = setup_testshell()\n", "txid_to_spend, index_to_spend = fund_address(node, address_to_spend, 0.1)\n", @@ -201,7 +151,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -225,17 +175,9 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "unsigned_tx: 0200000001b95a36eba179c511df5d74630e8fbda5cd60dc17037d6df9be49f02ba9ba48e20100000000fffffffe01e00f9700000000001976a9143bc28d6d92d9073fb5e3adf481795eaf446bceed88acf4010000\n" - ] - } - ], + "outputs": [], "source": [ "# VERSION\n", "# version '2' indicates that we may use relative timelocks (BIP68)\n", @@ -307,17 +249,9 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "020000004718bd17ac0f84a7bfd6da7f8759e2ddacf763ce22c17cc425ff257ad3cdf240bbdebfac1cd12080fb29f8919f7f8be7bdb21a89c8d09e8a59fc7bb1d2a73796b95a36eba179c511df5d74630e8fbda5cd60dc17037d6df9be49f02ba9ba48e2010000002802f401b1752102466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f27ac8096980000000000fffffffe5d18c7a03d8b14317752ff0d8801c9fe97f8e11c3abfc3d0543fa2fedcceb020f401000001000000\n" - ] - } - ], + "outputs": [], "source": [ "input_amount_sat = int(0.1 * 100_000_000)\n", "value = input_amount_sat.to_bytes(8, byteorder=\"little\", signed=False)\n", @@ -353,19 +287,11 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "metadata": { "code_folding": [] }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "signed transaction: 02000000000101b95a36eba179c511df5d74630e8fbda5cd60dc17037d6df9be49f02ba9ba48e20100000000fffffffe01e00f9700000000001976a9143bc28d6d92d9073fb5e3adf481795eaf446bceed88ac024830450221008bf4cb4162e95e1b5f1744675f7b948da6f32d0ccbc77584a04370480d71f72802201f50567fcf3d792d891225b09323ee4dd9aeb842d2f593621d560600ee28ab54012802f401b1752102466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f27acf4010000\n" - ] - } - ], + "outputs": [], "source": [ "# Create sigHash to be signed\n", "sighash = hash256(tx_digest_preimage)\n", @@ -422,18 +348,9 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Blockchain height: 102\n", - "[{'txid': '5434444cb806c1df051a25f45c17b70b6cdefc5dcc4c6c3073de3ddef6256dff', 'wtxid': '08e13f1ba8516fc682ba72c51627c45081267a460e2b615666fe5f965744f1e8', 'allowed': False, 'reject-reason': 'non-final'}]\n" - ] - } - ], + "outputs": [], "source": [ "height = node.getblockcount()\n", "print(\"Blockchain height: \", height)\n", @@ -451,18 +368,9 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Blockchain height: 500\n", - "[{'txid': '5434444cb806c1df051a25f45c17b70b6cdefc5dcc4c6c3073de3ddef6256dff', 'wtxid': '08e13f1ba8516fc682ba72c51627c45081267a460e2b615666fe5f965744f1e8', 'allowed': True, 'vsize': 115, 'fees': {'base': Decimal('0.00100000')}}]\n" - ] - } - ], + "outputs": [], "source": [ "node.generate(398, invalid_call=False)\n", "height = node.getblockcount()\n", @@ -483,53 +391,9 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{\n", - " \"txid\": \"5434444cb806c1df051a25f45c17b70b6cdefc5dcc4c6c3073de3ddef6256dff\",\n", - " \"hash\": \"08e13f1ba8516fc682ba72c51627c45081267a460e2b615666fe5f965744f1e8\",\n", - " \"version\": 2,\n", - " \"size\": 202,\n", - " \"vsize\": 115,\n", - " \"weight\": 457,\n", - " \"locktime\": 500,\n", - " \"vin\": [\n", - " {\n", - " \"txid\": \"e248baa92bf049bef96d7d0317dc60cda5bd8f0e63745ddf11c579a1eb365ab9\",\n", - " \"vout\": 1,\n", - " \"scriptSig\": {\n", - " \"asm\": \"\",\n", - " \"hex\": \"\"\n", - " },\n", - " \"txinwitness\": [\n", - " \"30450221008bf4cb4162e95e1b5f1744675f7b948da6f32d0ccbc77584a04370480d71f72802201f50567fcf3d792d891225b09323ee4dd9aeb842d2f593621d560600ee28ab5401\",\n", - " \"02f401b1752102466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f27ac\"\n", - " ],\n", - " \"sequence\": 4278190079\n", - " }\n", - " ],\n", - " \"vout\": [\n", - " {\n", - " \"value\": \"0.09900000\",\n", - " \"n\": 0,\n", - " \"scriptPubKey\": {\n", - " \"asm\": \"OP_DUP OP_HASH160 3bc28d6d92d9073fb5e3adf481795eaf446bceed OP_EQUALVERIFY OP_CHECKSIG\",\n", - " \"desc\": \"addr(mkxwE7XtVYJKepoD2hbHnDjftuMQ1k6deE)#xlnzfr97\",\n", - " \"hex\": \"76a9143bc28d6d92d9073fb5e3adf481795eaf446bceed88ac\",\n", - " \"address\": \"mkxwE7XtVYJKepoD2hbHnDjftuMQ1k6deE\",\n", - " \"type\": \"pubkeyhash\"\n", - " }\n", - " }\n", - " ]\n", - "}\n" - ] - } - ], + "outputs": [], "source": [ "decoded = node.decoderawtransaction(signed_tx.hex())\n", "print(json.dumps(decoded, indent=2, default=str))" @@ -597,7 +461,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -611,7 +475,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.0" + "version": "3.8.16" } }, "nbformat": 4, diff --git a/README.md b/README.md index e5482de..bd3480d 100644 --- a/README.md +++ b/README.md @@ -64,7 +64,18 @@ Finally, to launch the interactive notebook: jupyter notebook ``` ### Bitcoin core -The notebooks in this repo use bitcoin core's `TestShell` from its test framework. The `TestShell` is used to create a local test instance of a bitcoin node (and blockchain) against which we can test our manually created transactions. The notebooks in this repo have been tested with [bitcoin core v24.0.1](https://github.com/bitcoin/bitcoin/releases/tag/v24.0.1). + +The notebooks in this repo require `bitcoind` and have been tested with [bitcoin core v24.0.1](https://github.com/bitcoin/bitcoin/releases/tag/v24.0.1). + +We use [`TestShell`](https://github.com/bitcoin/bitcoin/blob/master/test/functional/test-shell.md), a wrapper of the `BitcoinTestFramework` that extends its functionality in external interactive environments, such as jupyter notebooks. +The `TestShell` is used to create a local test instance of a bitcoin node (and blockchain) against which we can test our manually created transactions. + +In order for this to work, you need to add the path of your Bitcoin Core directory to the `config.ini` file. +For example, set: + +``` +SOURCE_DIRECTORY=/Users/username/bitcoin +``` ## Acknowledgements diff --git a/config.ini b/config.ini new file mode 100644 index 0000000..89e7390 --- /dev/null +++ b/config.ini @@ -0,0 +1,6 @@ +# Config file for the bitcoin-tx-tutorial + +[path] +# Set this to the source directory of Bitcoin Core +# eg SOURCE_DIRECTORY=/Users/username/bitcoin +SOURCE_DIRECTORY= diff --git a/functions/__init__.py b/functions/__init__.py index a666691..cb772c5 100644 --- a/functions/__init__.py +++ b/functions/__init__.py @@ -1,3 +1,4 @@ +import functions.setup_notebook from functions.addresses import * # from functions.create_regtest_utxo import * from functions.setup_testshell import * diff --git a/functions/setup_notebook.py b/functions/setup_notebook.py new file mode 100644 index 0000000..0dafb96 --- /dev/null +++ b/functions/setup_notebook.py @@ -0,0 +1,22 @@ +import configparser +import sys + +# Read configuration from config.ini +config = configparser.ConfigParser() +configfile = "config.ini" +config.read_file(open(configfile, encoding="utf8")) + +SOURCE_DIRECTORY = config["path"]["SOURCE_DIRECTORY"] + +assert not SOURCE_DIRECTORY == '', 'SOURCE_DIRECTORY not configured! Edit config.ini to configure SOURCE_DIRECTORY.' + +# Make functional framework scripts available +sys.path.insert(0, f"{SOURCE_DIRECTORY}/test/functional") + +try: + from test_framework.test_shell import TestShell + + print(f"Source directory configured as {SOURCE_DIRECTORY}") +except ModuleNotFoundError: + print(f"Error: {SOURCE_DIRECTORY} is not a Bitcoin Core source directory.") + print(f"Edit config.ini to configure SOURCE_DIRECTORY.") From ac358e7873751aa450fada6b62232c17c33843c8 Mon Sep 17 00:00:00 2001 From: kouloumos Date: Sun, 2 Apr 2023 17:43:14 +0300 Subject: [PATCH 2/2] change notebooks' references to use relative paths changing from absolute to relative references makes references more future-proof and allows for cross-notebook navigation when reading outside of github (e.g locally). side effect: fix broken links from previous notebooks' renames --- 0.4-addresses.ipynb | 6 ++--- 1.1-first-btc-tx.ipynb | 4 ++-- 1.2-p2pkh.ipynb | 14 ++++++------ 1.3-p2sh-multisig.ipynb | 10 ++++----- 2.1-p2wpkh.ipynb | 8 +++---- 2.2-multiple-inputs-outputs.ipynb | 8 +++---- 2.3-p2wsh-2-of-2-multisig.ipynb | 10 ++++----- 3.1-schnorr-sig-and-taptweak.ipynb | 2 +- 3.3-p2tr-key-and-script-path.ipynb | 26 +++++++++++----------- 5.1.transaction-level-timelocks.ipynb | 10 ++++----- 5.2-script-level-timelocks.ipynb | 10 ++++----- README.md | 32 +++++++++++++-------------- 12 files changed, 70 insertions(+), 70 deletions(-) diff --git a/0.4-addresses.ipynb b/0.4-addresses.ipynb index 6d2436d..7eab024 100644 --- a/0.4-addresses.ipynb +++ b/0.4-addresses.ipynb @@ -21,8 +21,8 @@ "Here we will cover the different scriptPubKey formats as well as how they can be encoded and decoded.\n", "\n", "The following functions have more explanation in the corresponding notebooks:\n", - "- [Hash Functions](https://github.com/DariusParvin/bitcoin-tx-tutorial/blob/main/appendix/hash-functions.ipynb) `HASH245`, `HASH160`.\n", - "- [Bitcoin Script](https://github.com/DariusParvin/bitcoin-tx-tutorial/blob/main/appendix/bitcoin-script.ipynb) `pushbytes`" + "- [Hash Functions](./0.2-hash-functions.ipynb) `HASH245`, `HASH160`.\n", + "- [Bitcoin Script](./0.3-hash-functions.ipynb) `pushbytes`" ] }, { @@ -412,7 +412,7 @@ "### Creating a bech32m P2TR address from a x-only public key\n", "Bech32m uses an almost identical encoding scheme as bech32, but with an additional constant. The imported `bech32` library is able to encode either address format and does so based on the `version` number. A version number of 0 indicates that the output is Segwit v0 and uses bech32, and a version number 1 indicates that the output is Segwit v1 (aka taproot) and uses bech32m.\n", "\n", - "Note that taproot introduces a new format of public key called _x-only_ public keys. For more on this see the note on public keys in '[Elliptic Curve Math Review](https://github.com/DariusParvin/bitcoin-tx-tutorial/blob/main/appendix/elliptic_curve_math_review.ipynb)'.\n", + "Note that taproot introduces a new format of public key called _x-only_ public keys. For more on this see the note on public keys in '[Elliptic Curve Math Review](./0.1-elliptic_curve_math_review.ipynb)'.\n", "\n", "In this example we'll create a P2TR address for the following x-only pubkey `a4af82136997976431f2c76a1179662f04c14f8fdfd24de49a0df51496e733d1`." ] diff --git a/1.1-first-btc-tx.ipynb b/1.1-first-btc-tx.ipynb index 916a7fb..e8566d0 100644 --- a/1.1-first-btc-tx.ipynb +++ b/1.1-first-btc-tx.ipynb @@ -339,7 +339,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -353,7 +353,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.0" + "version": "3.8.16" } }, "nbformat": 4, diff --git a/1.2-p2pkh.ipynb b/1.2-p2pkh.ipynb index afea35d..e66d625 100644 --- a/1.2-p2pkh.ipynb +++ b/1.2-p2pkh.ipynb @@ -31,9 +31,9 @@ "\n", "\n", "- Specific to this notebook:\n", - " - SHA256, HASH256, HASH160 - '[Hash Functions chapter](https://github.com/DariusParvin/bitcoin-tx-tutorial/blob/main/appendix/hash-functions.ipynb)'\n", - " - Base58 addresses - '[Addresses chapter](https://github.com/DariusParvin/bitcoin-tx-tutorial/blob/main/appendix/Addresses.ipynb)'\n", - " - Bitcoin Script basics - '[Bitcoin Script chapter](https://github.com/DariusParvin/bitcoin-tx-tutorial/blob/main/appendix/Bitcoin%20Script.ipynb)'" + " - SHA256, HASH256, HASH160 - '[Hash Functions chapter](./0.2-hash-functions.ipynb)'\n", + " - Base58 addresses - '[Addresses chapter](./0.4-addresses.ipynb)'\n", + " - Bitcoin Script basics - '[Bitcoin Script chapter](./0.3-bitcoin-script.ipynb)'" ] }, { @@ -203,7 +203,7 @@ "2 - make sure we are sending btc on the correct network (testnet/mainnet) \n", "3 - know what to put in the scriptPubkey\n", "\n", - "For more on addresses, refer back to the '[Addresses](https://github.com/DariusParvin/bitcoin-tx-tutorial/blob/main/appendix/addresses.ipynb)' chapter." + "For more on addresses, refer back to the '[Addresses](./0.4-addresses.ipynb)' chapter." ] }, { @@ -526,7 +526,7 @@ "metadata": {}, "source": [ " ## Answers\n", - "1. It is the double SHA256 (HASH256) of the raw transaction. Note that the output is displayed in little endian. See '[The First Bitcoin Transaction (Pay to Pubkey)](https://github.com/DariusParvin/bitcoin-tx-tutorial/blob/main/chapter1-legacy/first-btc-tx.ipynb)' for an example.\n", + "1. It is the double SHA256 (HASH256) of the raw transaction. Note that the output is displayed in little endian. See '[The First Bitcoin Transaction (Pay to Pubkey)](./1.1-first-btc-tx.ipynb)' for an example.\n", "2. The scriptSig in the input field contains the signature(s).\n", "3. A third party could observe the transaction in the mempool, change the signature, then broadcast the transaction with the altered signature and transaction ID.\n", "4. Two issues (non exhaustive):\n", @@ -769,7 +769,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -783,7 +783,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.0" + "version": "3.8.16" } }, "nbformat": 4, diff --git a/1.3-p2sh-multisig.ipynb b/1.3-p2sh-multisig.ipynb index 0c30272..9966845 100644 --- a/1.3-p2sh-multisig.ipynb +++ b/1.3-p2sh-multisig.ipynb @@ -31,10 +31,10 @@ "\n", "\n", "- Specific to this notebook:\n", - " - SHA256, HASH256, HASH160 - '[Hash Functions chapter](https://github.com/DariusParvin/bitcoin-tx-tutorial/blob/main/appendix/hash-functions.ipynb)'\n", - " - Base58 addresses - '[Addresses chapter](https://github.com/DariusParvin/bitcoin-tx-tutorial/blob/main/appendix/Addresses.ipynb)'\n", - " - Bitcoin Script basics - '[Bitcoin Script chapter](https://github.com/DariusParvin/bitcoin-tx-tutorial/blob/main/appendix/Bitcoin%20Script.ipynb)'\n", - " - TestShell setup - '[P2PKH chapter](https://github.com/DariusParvin/bitcoin-tx-tutorial/blob/main/chapter1-legacy/p2pkh.ipynb)'" + " - SHA256, HASH256, HASH160 - '[Hash Functions chapter](./0.2-hash-functions.ipynb)'\n", + " - Base58 addresses - '[Addresses chapter](./0.4-addresses.ipynb)'\n", + " - Bitcoin Script basics - '[Bitcoin Script chapter](./0.3-bitcoin-script.ipynb)'\n", + " - TestShell setup - '[P2PKH chapter](./1.2-p2pkh.ipynb)'" ] }, { @@ -109,7 +109,7 @@ "source": [ "#### Fund the 'sender' with 2.001 btc (0.001 btc is for the next tx fee)\n", "\n", - "Now that we have the address, we'll fund it using the `TestShell` commands. For more on these steps you can view the [function definitions](https://github.com/DariusParvin/bitcoin-tx-tutorial/blob/main/functions/setup_testshell.py) or look at the first [P2PKH notebook](https://github.com/DariusParvin/bitcoin-tx-tutorial/blob/main/chapter1-legacy/p2pkh.ipynb) example." + "Now that we have the address, we'll fund it using the `TestShell` commands. For more on these steps you can view the [function definitions](./functions/setup_testshell.py) or look at the first [P2PKH notebook](./1.2-p2pkh.ipynb) example." ] }, { diff --git a/2.1-p2wpkh.ipynb b/2.1-p2wpkh.ipynb index ab96940..3417c1c 100644 --- a/2.1-p2wpkh.ipynb +++ b/2.1-p2wpkh.ipynb @@ -31,10 +31,10 @@ "\n", "\n", "- Specific to this notebook:\n", - " - SHA256, HASH256, HASH160 - '[Hash Functions chapter](https://github.com/DariusParvin/bitcoin-tx-tutorial/blob/main/appendix/hash-functions.ipynb)'\n", - " - Base58 addresses - '[Addresses chapter](https://github.com/DariusParvin/bitcoin-tx-tutorial/blob/main/appendix/Addresses.ipynb)'\n", - " - Bitcoin Script basics - '[Bitcoin Script chapter](https://github.com/DariusParvin/bitcoin-tx-tutorial/blob/main/appendix/Bitcoin%20Script.ipynb)'\n", - " - TestShell setup - '[P2PKH chapter](https://github.com/DariusParvin/bitcoin-tx-tutorial/blob/main/chapter1-legacy/p2pkh.ipynb)'" + " - SHA256, HASH256, HASH160 - '[Hash Functions chapter](./0.2-hash-functions.ipynb)'\n", + " - Base58 addresses - '[Addresses chapter](./0.4-addresses.ipynb)'\n", + " - Bitcoin Script basics - '[Bitcoin Script chapter](./0.3-bitcoin-script.ipynb)'\n", + " - TestShell setup - '[P2PKH chapter](./1.2-p2pkh.ipynb)'" ] }, { diff --git a/2.2-multiple-inputs-outputs.ipynb b/2.2-multiple-inputs-outputs.ipynb index 81416ce..62d02d2 100644 --- a/2.2-multiple-inputs-outputs.ipynb +++ b/2.2-multiple-inputs-outputs.ipynb @@ -33,10 +33,10 @@ "\n", "\n", "- Specific to this notebook:\n", - " - SHA256, HASH256, HASH160 - '[Hash Functions chapter](https://github.com/DariusParvin/bitcoin-tx-tutorial/blob/main/appendix/hash-functions.ipynb)'\n", - " - Base58 addresses - '[Addresses chapter](https://github.com/DariusParvin/bitcoin-tx-tutorial/blob/main/appendix/Addresses.ipynb)'\n", - " - Bitcoin Script basics - '[Bitcoin Script chapter](https://github.com/DariusParvin/bitcoin-tx-tutorial/blob/main/appendix/Bitcoin%20Script.ipynb)'\n", - " - TestShell setup - '[P2PKH chapter](https://github.com/DariusParvin/bitcoin-tx-tutorial/blob/main/chapter1-legacy/p2pkh.ipynb)'\n" + " - SHA256, HASH256, HASH160 - '[Hash Functions chapter](./0.2-hash-functions.ipynb)'\n", + " - Base58 addresses - '[Addresses chapter](./0.4-addresses.ipynb)'\n", + " - Bitcoin Script basics - '[Bitcoin Script chapter](./0.3-bitcoin-script.ipynb)'\n", + " - TestShell setup - '[P2PKH chapter](./1.2-p2pkh.ipynb)'\n" ] }, { diff --git a/2.3-p2wsh-2-of-2-multisig.ipynb b/2.3-p2wsh-2-of-2-multisig.ipynb index 5aad53b..1774ad2 100644 --- a/2.3-p2wsh-2-of-2-multisig.ipynb +++ b/2.3-p2wsh-2-of-2-multisig.ipynb @@ -31,10 +31,10 @@ "\n", "\n", "- Specific to this notebook:\n", - " - SHA256, HASH256, HASH160 - '[Hash Functions chapter](https://github.com/DariusParvin/bitcoin-tx-tutorial/blob/main/appendix/hash-functions.ipynb)'\n", - " - Base58 addresses - '[Addresses chapter](https://github.com/DariusParvin/bitcoin-tx-tutorial/blob/main/appendix/Addresses.ipynb)'\n", - " - Bitcoin Script basics - '[Bitcoin Script chapter](https://github.com/DariusParvin/bitcoin-tx-tutorial/blob/main/appendix/Bitcoin%20Script.ipynb)'\n", - " - TestShell setup - '[P2PKH chapter](https://github.com/DariusParvin/bitcoin-tx-tutorial/blob/main/chapter1-legacy/p2pkh.ipynb)'" + " - SHA256, HASH256, HASH160 - '[Hash Functions chapter](./0.2-hash-functions.ipynb)'\n", + " - Base58 addresses - '[Addresses chapter](./0.4-addresses.ipynb)'\n", + " - Bitcoin Script basics - '[Bitcoin Script chapter](./0.3-bitcoin-script.ipynb)'\n", + " - TestShell setup - '[P2PKH chapter](./1.2-p2pkh.ipynb)'" ] }, { @@ -106,7 +106,7 @@ "source": [ "#### Fund the 'sender' with 2.001 btc (0.001 btc is for the next tx fee)\n", "\n", - "Now that we have the address, we'll fund it using the `TestShell` commands. For more on these steps you can view the [function definitions](https://github.com/DariusParvin/bitcoin-tx-tutorial/blob/main/functions/setup_testshell.py) or look at the first [P2PKH notebook](https://github.com/DariusParvin/bitcoin-tx-tutorial/blob/main/chapter1-legacy/p2pkh.ipynb) example." + "Now that we have the address, we'll fund it using the `TestShell` commands. For more on these steps you can view the [function definitions](./functions/setup_testshell.py) or look at the first [P2PKH notebook](./1.2-p2pkh.ipynb) example." ] }, { diff --git a/3.1-schnorr-sig-and-taptweak.ipynb b/3.1-schnorr-sig-and-taptweak.ipynb index 4cec634..b3ad362 100644 --- a/3.1-schnorr-sig-and-taptweak.ipynb +++ b/3.1-schnorr-sig-and-taptweak.ipynb @@ -40,7 +40,7 @@ "\n", "One of the ways ECDSA was designed to bypass the Schnorr patent was to break the useful linearity of Schnorr signatures. For this reason the math behind Schnorr signatures is also perhaps more intuitive than ECDSA. \n", "\n", - "Elliptic curve private keys have a linear property, such that the sum of private keys will produce a sum of public keys equal to the sum of the individiual public keys. For a review of this principle, refer to the section '[Elliptic Curve Math Review](https://github.com/DariusParvin/bitcoin-tx-tutorial/blob/main/elliptic_curve_math_review.ipynb)'. With Schnorr signatures, this linearity extends to the signatures themselves. \n", + "Elliptic curve private keys have a linear property, such that the sum of private keys will produce a sum of public keys equal to the sum of the individiual public keys. For a review of this principle, refer to the section '[Elliptic Curve Math Review](./0.1-elliptic_curve_math_review.ipynb)'. With Schnorr signatures, this linearity extends to the signatures themselves. \n", "\n", "## Schnorr Signatures\n", "\n", diff --git a/3.3-p2tr-key-and-script-path.ipynb b/3.3-p2tr-key-and-script-path.ipynb index 7d9b764..e32f923 100644 --- a/3.3-p2tr-key-and-script-path.ipynb +++ b/3.3-p2tr-key-and-script-path.ipynb @@ -29,15 +29,15 @@ "\n", "\n", "- Specific to this notebook:\n", - " - SHA256, HASH256, HASH160 - '[Hash Functions chapter](https://github.com/DariusParvin/bitcoin-tx-tutorial/blob/main/appendix/hash-functions.ipynb)'\n", - " - Base58 addresses - '[Addresses chapter](https://github.com/DariusParvin/bitcoin-tx-tutorial/blob/main/appendix/addresses.ipynb)'\n", - " - Bitcoin Script basics - '[Bitcoin Script chapter](https://github.com/DariusParvin/bitcoin-tx-tutorial/blob/main/appendix/bitcoin-script.ipynb)'\n", - " - TestShell setup - '[P2PKH chapter](https://github.com/DariusParvin/bitcoin-tx-tutorial/blob/main/chapter1-legacy/p2pkh.ipynb)'\n", + " - SHA256, HASH256, HASH160 - '[Hash Functions chapter](./0.2-hash-functions.ipynb)'\n", + " - Base58 addresses - '[Addresses chapter](./0.4-addresses.ipynb)'\n", + " - Bitcoin Script basics - '[Bitcoin Script chapter](./0.3-hash-functions.ipynb)'\n", + " - TestShell setup - '[P2PKH chapter](./1.2-p2pkh.ipynb)'\n", "- Specific for taproot:\n", - " - [Elliptic Curve Math Review](https://github.com/DariusParvin/bitcoin-tx-tutorial/blob/main/appendix/elliptic_curve_math_review.ipynb)\n", - " - [Schnorr signatures and TapTweaks](https://github.com/DariusParvin/bitcoin-tx-tutorial/blob/main/chapter3-taproot/schnorr-sig-and-taptweak.ipynb)\n", - " - [TapTrees](https://github.com/DariusParvin/bitcoin-tx-tutorial/blob/main/chapter3-taproot/taproot-taptree.ipynb)\n", - " - [Signature hash evolution](https://github.com/DariusParvin/bitcoin-tx-tutorial/blob/main/appendix/sighash_evolution.ipynb)" + " - [Elliptic Curve Math Review](./0.1-elliptic_curve_math_review.ipynb)\n", + " - [Schnorr signatures and TapTweaks](./3.1-schnorr-sig-and-taptweak.ipynb)\n", + " - [TapTrees](./3.2-taproot-taptree.ipynb)\n", + " - [Signature hash evolution](./4.1-sighash_evolution.ipynb)" ] }, { @@ -62,7 +62,7 @@ "## Part 1: Constructing a P2TR output that commits to a taptree\n", "\n", "In order to create this output, we'll need to perform the following steps. For more on taptrees see the chapter on\n", - "[TapTrees](https://github.com/DariusParvin/bitcoin-tx-tutorial/blob/main/taproot_taptree.ipynb):\n", + "[TapTrees](./3.2-taproot-taptree.ipynb):\n", "1. Compute TapLeaves A, B and C (for Adam, Ben, Carla).\n", "2. Compute Internal TapBranch AB.\n", "3. Compute TapTweak\n", @@ -127,7 +127,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Now we are ready to set up the bitcoin `TestShell` and fund this address. For more on these steps you can view the [function definitions](https://github.com/DariusParvin/bitcoin-tx-tutorial/blob/main/functions/setup_testshell.py) or look at the first [P2PKH notebook](https://github.com/DariusParvin/bitcoin-tx-tutorial/blob/main/chapter1-legacy/p2pkh.ipynb) example." + "Now we are ready to set up the bitcoin `TestShell` and fund this address. For more on these steps you can view the [function definitions](./functions/setup_testshell.py) or look at the first [P2PKH notebook](./1.2-p2pkh.ipynb) example." ] }, { @@ -150,7 +150,7 @@ "### Scenario\n", "Patricia comes back from her backpacking trip and thankfully none of her children needed to use the emergency funds she allocated for them. She decides to move majority of the funds (1.5 btc) into her cold wallet, and the rest (0.5 btc) to her hot wallet using the internal public key via a key path spend.\n", "\n", - "The first step she'll need to do is derive the tweaked internal private key. For more on this, review the section on [Schnorr signatures and TapTweaks](https://github.com/DariusParvin/bitcoin-tx-tutorial/blob/main/schnorr_sig_and_taptweak.ipynb)." + "The first step she'll need to do is derive the tweaked internal private key. For more on this, review the section on [Schnorr signatures and TapTweaks](./3.1-schnorr-sig-and-taptweak.ipynb)." ] }, { @@ -260,7 +260,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Now she's ready to compute the sighash and sign it with a schnorr signature using her tweaked internal key. For more on this section see [Signature hash evolution](https://github.com/DariusParvin/bitcoin-tx-tutorial/blob/main/sighash_evolution.ipynb)." + "Now she's ready to compute the sighash and sign it with a schnorr signature using her tweaked internal key. For more on this section see [Signature hash evolution](./4.1-sighash_evolution.ipynb)." ] }, { @@ -316,7 +316,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Now with the sighash she can sign it with her tweaked internal key. For more on schnorr signatures see [Schnorr signatures and TapTweaks](https://github.com/DariusParvin/bitcoin-tx-tutorial/blob/main/schnorr_sig_and_taptweak.ipynb)." + "Now with the sighash she can sign it with her tweaked internal key. For more on schnorr signatures see [Schnorr signatures and TapTweaks](./3.1-schnorr-sig-and-taptweak.ipynb)." ] }, { diff --git a/5.1.transaction-level-timelocks.ipynb b/5.1.transaction-level-timelocks.ipynb index 4fe519b..4e29dc7 100644 --- a/5.1.transaction-level-timelocks.ipynb +++ b/5.1.transaction-level-timelocks.ipynb @@ -33,10 +33,10 @@ "\n", "\n", "- Specific to this notebook:\n", - " - SHA256, HASH256, HASH160 - '[Hash Functions chapter](https://github.com/DariusParvin/bitcoin-tx-tutorial/blob/main/appendix/hash-functions.ipynb)'\n", - " - Base58 addresses - '[Addresses chapter](https://github.com/DariusParvin/bitcoin-tx-tutorial/blob/main/appendix/Addresses.ipynb)'\n", - " - Bitcoin Script basics - '[Bitcoin Script chapter](https://github.com/DariusParvin/bitcoin-tx-tutorial/blob/main/appendix/Bitcoin%20Script.ipynb)'\n", - " - TestShell setup - '[P2PKH chapter](https://github.com/DariusParvin/bitcoin-tx-tutorial/blob/main/chapter1-legacy/p2pkh.ipynb)'\n", + " - SHA256, HASH256, HASH160 - '[Hash Functions chapter](./0.2-hash-functions.ipynb)'\n", + " - Base58 addresses - '[Addresses chapter](./0.4-addresses.ipynb)'\n", + " - Bitcoin Script basics - '[Bitcoin Script chapter](./0.3-bitcoin-script.ipynb)'\n", + " - TestShell setup - '[P2PKH chapter](./1.2-p2pkh.ipynb)'\n", "\n", "### Further Reading\n", "- https://medium.com/summa-technology/bitcoins-time-locks-27e0c362d7a1" @@ -79,7 +79,7 @@ "source": [ "#### Create Kim's utxo with 0.101 btc (0.001 btc is for the next tx fee)\n", "\n", - "Now that we have the address, we'll fund it using the `TestShell` commands. For more on these steps you can view the [function definitions](https://github.com/DariusParvin/bitcoin-tx-tutorial/blob/main/functions/setup_testshell.py) or look at the first [P2PKH notebook](https://github.com/DariusParvin/bitcoin-tx-tutorial/blob/main/chapter1-legacy/p2pkh.ipynb) example." + "Now that we have the address, we'll fund it using the `TestShell` commands. For more on these steps you can view the [function definitions](./functions/setup_testshell.py) or look at the first [P2PKH notebook](./1.2-p2pkh.ipynb) example." ] }, { diff --git a/5.2-script-level-timelocks.ipynb b/5.2-script-level-timelocks.ipynb index e0ad7a6..0d24ddc 100644 --- a/5.2-script-level-timelocks.ipynb +++ b/5.2-script-level-timelocks.ipynb @@ -32,10 +32,10 @@ " - [Hexadecimal notation](https://inst.eecs.berkeley.edu/~cs61bl/r//cur/bits/decimal-binary-hex.html?topic=lab28.topic&step=2&course=) and [endianness](https://www.freecodecamp.org/news/what-is-endianness-big-endian-vs-little-endian/).\n", "\n", "- Specific to this notebook:\n", - " - SHA256, HASH256, HASH160 - '[Hash Functions chapter](https://github.com/DariusParvin/bitcoin-tx-tutorial/blob/main/appendix/hash-functions.ipynb)'\n", - " - Base58 addresses - '[Addresses chapter](https://github.com/DariusParvin/bitcoin-tx-tutorial/blob/main/appendix/Addresses.ipynb)'\n", - " - Bitcoin Script basics - '[Bitcoin Script chapter](https://github.com/DariusParvin/bitcoin-tx-tutorial/blob/main/appendix/Bitcoin%20Script.ipynb)'\n", - " - TestShell setup - '[P2PKH chapter](https://github.com/DariusParvin/bitcoin-tx-tutorial/blob/main/chapter1-legacy/p2pkh.ipynb)'\n", + " - SHA256, HASH256, HASH160 - '[Hash Functions chapter](./0.2-hash-functions.ipynb)'\n", + " - Base58 addresses - '[Addresses chapter](./0.4-addresses.ipynb)'\n", + " - Bitcoin Script basics - '[Bitcoin Script chapter](./0.3-bitcoin-script.ipynb)'\n", + " - TestShell setup - '[P2PKH chapter](./1.2-p2pkh.ipynb)'\n", "\n", "\n", "### Further Reading\n", @@ -124,7 +124,7 @@ "metadata": {}, "source": [ "#### Create Peter's utxo with 0.1 btc\n", - "Now that we have the address, we'll fund it using the `TestShell` commands. For more on these steps you can view the [function definitions](https://github.com/DariusParvin/bitcoin-tx-tutorial/blob/main/functions/setup_testshell.py) or look at the first [P2PKH notebook](https://github.com/DariusParvin/bitcoin-tx-tutorial/blob/main/chapter1-legacy/p2pkh.ipynb) example." + "Now that we have the address, we'll fund it using the `TestShell` commands. For more on these steps you can view the [function definitions](./functions/setup_testshell.py) or look at the first [P2PKH notebook](./1.2-p2pkh.ipynb) example." ] }, { diff --git a/README.md b/README.md index bd3480d..3e3e66e 100644 --- a/README.md +++ b/README.md @@ -10,27 +10,27 @@ This repo contains a series of python jupyter-notebooks to explain how bitcoin t ## Chapters + Chapter 1: 'Legacy Transactions' - - '[The First Bitcoin Transaction (Pay to Pubkey)](https://github.com/DariusParvin/bitcoin-tx-tutorial/blob/main/chapter1-legacy/first-btc-tx.ipynb)' - - '[P2PKH - Pay to Pubkey Hash](https://github.com/DariusParvin/bitcoin-tx-tutorial/blob/main/chapter1-legacy/p2pkh.ipynb)' - - '[P2SH - Pay to Script Hash (2-of-3 Mulitisig)](https://github.com/DariusParvin/bitcoin-tx-tutorial/blob/main/chapter1-legacy/p2sh-multisig.ipynb)' + - '[The First Bitcoin Transaction (Pay to Pubkey)](./1.1-first-btc-tx.ipynb)' + - '[P2PKH - Pay to Pubkey Hash](./1.2-p2pkh.ipynb)' + - '[P2SH - Pay to Script Hash (2-of-3 Mulitisig)](./1.3-p2sh-multisig.ipynb)' + Chapter 2: 'Segwit v0' - - '[P2WPKH - Pay to Witness Pubkey Hash](https://github.com/DariusParvin/bitcoin-tx-tutorial/blob/main/chapter2-segwitv0/p2wpkh.ipynb)' - - '[P2WSH - Pay to Witness Script Hash (2-of-2 Multisig)](https://github.com/DariusParvin/bitcoin-tx-tutorial/blob/main/chapter2-segwitv0/p2wsh-2-of-2-multisig.ipynb)' + - '[P2WPKH - Pay to Witness Pubkey Hash](./2.1-p2wpkh.ipynb)' + - '[P2WSH - Pay to Witness Script Hash (2-of-2 Multisig)](./2.3-p2wsh-2-of-2-multisig.ipynb)' + Chapter 3: 'Taproot' - - '[Schnorr signatures and TapTweaks](https://github.com/DariusParvin/bitcoin-tx-tutorial/blob/main/chapter3-taproot/schnorr-sig-and-taptweak.ipynb)' - - '[TapTrees](https://github.com/DariusParvin/bitcoin-tx-tutorial/blob/main/chapter3-taproot/taproot-taptree.ipynb)' - - '[P2TR - Key path and Script path spends](https://github.com/DariusParvin/bitcoin-tx-tutorial/blob/main/chapter3-taproot/p2tr-key-and-script-path.ipynb)' + - '[Schnorr signatures and TapTweaks](./3.1-schnorr-sig-and-taptweak.ipynb)' + - '[TapTrees](./3.2-taproot-taptree.ipynb)' + - '[P2TR - Key path and Script path spends](./3.3-p2tr-key-and-script-path.ipynb)' + Chapter 4: 'Signature hashes' - - '[Signature hash evolution](https://github.com/DariusParvin/bitcoin-tx-tutorial/blob/main/chapter4-sighash/sighash-evolution.ipynb)' - - '[Signature hash flags](https://github.com/DariusParvin/bitcoin-tx-tutorial/blob/main/chapter4-sighash/sighash-flags.ipynb)' + - '[Signature hash evolution](./4.1-sighash-evolution.ipynb)' + - '[Signature hash flags](./4.2-sighash-flags.ipynb)' + Chapter 5: 'Timelocks' - - '[Transaction-level timelocks](https://github.com/DariusParvin/bitcoin-tx-tutorial/blob/main/chapter5-timelocks/transaction-level-timelocks.ipynb)' - - '[Script-level timelocks](https://github.com/DariusParvin/bitcoin-tx-tutorial/blob/main/chapter5-timelocks/script-level-timelocks.ipynb)' + - '[Transaction-level timelocks](./5.1.transaction-level-timelocks.ipynb)' + - '[Script-level timelocks](./5.2-script-level-timelocks.ipynb)' + Appendix: - - '[Elliptic Curve Math Review](https://github.com/DariusParvin/bitcoin-tx-tutorial/blob/main/appendix/elliptic_curve_math_review.ipynb)' - - '[Hash Functions](https://github.com/DariusParvin/bitcoin-tx-tutorial/blob/main/appendix/hash-functions.ipynb)' - - '[Bitcoin Script](https://github.com/DariusParvin/bitcoin-tx-tutorial/blob/main/appendix/bitcoin_script.ipynb)' - - '[Addresses](https://github.com/DariusParvin/bitcoin-tx-tutorial/blob/main/appendix/addresses.ipynb)' + - '[Elliptic Curve Math Review](./0.1-elliptic_curve_math_review.ipynb)' + - '[Hash Functions](./0.2-hash-functions.ipynb)' + - '[Bitcoin Script](./0.3-bitcoin-script.ipynb)' + - '[Addresses](./0.4-addresses.ipynb)' ## Setup ### Python3