├── .gitignore ├── README.md ├── Session_1.ipynb ├── Session_2.ipynb ├── Session_3.ipynb ├── Session_4.ipynb ├── Session_5.ipynb ├── Session_6.ipynb ├── Session_7.ipynb └── donate.png /.gitignore: -------------------------------------------------------------------------------- 1 | .ipynb_checkpoints -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #### Description 2 | 3 | The notebooks are based on the examples and exercises that were taught at Jimmy Song seminar *Programming Blockchain*. 4 | 5 | Check out [Jimmy's blog!](https://medium.com/@jimmysong/) 6 | 7 | [Update] Jimmy created his own exercise notebooks: https://github.com/jimmysong/pb-exercises 8 | 9 | #### How to start 10 | 11 | Run the following commands: 12 | 13 | ``` 14 | sudo pip install pycoin 15 | sudo pip install jupyter 16 | git clone https://github.com/sahabi/programming-blockchain.git 17 | cd programming-blockchain 18 | jupyter notebook 19 | ``` 20 | 21 | On your browser you can select the notebook. 22 | 23 | Notebooks were tested only on Python 2.7 and Ubuntu 14.04. 24 | 25 | 26 | #### TODO 27 | 28 | - [ ] Python 3 compatibility 29 | - [ ] Include the answers to the excercises. Maybe in a seperate notebook? 30 | - [ ] Fix the encryption example in Session 2 31 | 32 | #### Issues 33 | 34 | Please open a new issue if you want something fixed. Or contribute! 35 | 36 | 37 | #### Contributions 38 | 39 | All contributions are welcome. 40 | -------------------------------------------------------------------------------- /Session_1.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "### Session 1" 8 | ] 9 | }, 10 | { 11 | "cell_type": "code", 12 | "execution_count": null, 13 | "metadata": { 14 | "collapsed": false 15 | }, 16 | "outputs": [], 17 | "source": [ 18 | "# Addition and Substraction\n", 19 | "# Same as module P arithmetic (F_19)\n", 20 | "\n", 21 | "print( (11 + 6) % 19)\n", 22 | "print( (17 - 6) % 19)\n", 23 | "print( (8 + 14) % 19)\n", 24 | "print( (4 - 12) % 19)" 25 | ] 26 | }, 27 | { 28 | "cell_type": "markdown", 29 | "metadata": {}, 30 | "source": [ 31 | "#### Exercise 1\n", 32 | "\n", 33 | "Solve these equations in $F_{31}$\n", 34 | "\n", 35 | "$2 + 15 = ?$\n", 36 | "\n", 37 | "$29 - 4 = ?$\n", 38 | "\n", 39 | "$17 + 21 = ?$\n", 40 | "\n", 41 | "$15 - 30 = ?$\n" 42 | ] 43 | }, 44 | { 45 | "cell_type": "code", 46 | "execution_count": null, 47 | "metadata": { 48 | "collapsed": true 49 | }, 50 | "outputs": [], 51 | "source": [] 52 | }, 53 | { 54 | "cell_type": "code", 55 | "execution_count": null, 56 | "metadata": { 57 | "collapsed": true 58 | }, 59 | "outputs": [], 60 | "source": [] 61 | }, 62 | { 63 | "cell_type": "code", 64 | "execution_count": null, 65 | "metadata": { 66 | "collapsed": false 67 | }, 68 | "outputs": [], 69 | "source": [ 70 | "# Multiplication\n", 71 | "# Same as modulo P arithmetic (F_19)\n", 72 | "\n", 73 | "print ( (2 * 4) % 19)\n", 74 | "print ( (7 * 3) % 19)\n", 75 | "print ( (15 * 4) % 19)\n", 76 | "print ( (11**2) % 19)" 77 | ] 78 | }, 79 | { 80 | "cell_type": "markdown", 81 | "metadata": {}, 82 | "source": [ 83 | "#### Exercise 2\n", 84 | "1- Solve these equations in $F_{31}$\n", 85 | "\n", 86 | "$24 \\times 19 = ?$ \n", 87 | "\n", 88 | "$17^{3} = ?$\n", 89 | "\n", 90 | "$5^{5} \\times 18 = ? $\n", 91 | "\n", 92 | "2- Write a program to calculate 1*k, 2*k, 3*k, …\n", 93 | "30*k for some k in $F_{31}$. Notice anything about\n", 94 | "these sets?\n", 95 | "\n", 96 | "3- Write a program to calculate $k^{30}$ for all k in $F_{31}$.\n", 97 | "Notice anything?" 98 | ] 99 | }, 100 | { 101 | "cell_type": "code", 102 | "execution_count": null, 103 | "metadata": { 104 | "collapsed": true 105 | }, 106 | "outputs": [], 107 | "source": [] 108 | }, 109 | { 110 | "cell_type": "code", 111 | "execution_count": null, 112 | "metadata": { 113 | "collapsed": true 114 | }, 115 | "outputs": [], 116 | "source": [] 117 | }, 118 | { 119 | "cell_type": "code", 120 | "execution_count": null, 121 | "metadata": { 122 | "collapsed": false 123 | }, 124 | "outputs": [], 125 | "source": [ 126 | "# Division\n", 127 | "# Inverse of Multiplication\n", 128 | "\n", 129 | "print ( ((8 * pow(4, 19-2, 19) ) % 19))\n", 130 | "print ( ((2 * pow(3, 19-2, 19) ) % 19))\n", 131 | "print ( ((3 * pow(4, 19-2, 19) ) % 19))\n", 132 | "print ( ((7 * pow(11, 19-2, 19) ) % 19))" 133 | ] 134 | }, 135 | { 136 | "cell_type": "markdown", 137 | "metadata": {}, 138 | "source": [ 139 | "#### Exercise 3\n", 140 | "1- Solve these equations in $F_{31}$\n", 141 | "\n", 142 | "$3 \\div 24 = ?$\n", 143 | "\n", 144 | "$17^{-3} = ?$ \n", 145 | "\n", 146 | "$4^{-4} \\times 11 = ?$\n", 147 | "\n", 148 | "\n", 149 | "2- Write a program to calculate k/1, k/2, k/3, …\n", 150 | "k/30 for some k in $F_{31}$. Notice anything about\n", 151 | "these sets?" 152 | ] 153 | }, 154 | { 155 | "cell_type": "code", 156 | "execution_count": null, 157 | "metadata": { 158 | "collapsed": true 159 | }, 160 | "outputs": [], 161 | "source": [] 162 | }, 163 | { 164 | "cell_type": "code", 165 | "execution_count": null, 166 | "metadata": { 167 | "collapsed": true 168 | }, 169 | "outputs": [], 170 | "source": [] 171 | }, 172 | { 173 | "cell_type": "code", 174 | "execution_count": null, 175 | "metadata": { 176 | "collapsed": false 177 | }, 178 | "outputs": [], 179 | "source": [ 180 | "# Curve: y^2 = x^3 + 5x + 7\n", 181 | "# What is (2,5) + (3,7)\n", 182 | "\n", 183 | "s = (7. - 5)/(3-2)\n", 184 | "x3 = s**2 - 2 - 3\n", 185 | "y3 = s*(2 - x3) - 5\n", 186 | "\n", 187 | "print (\"({},{})\".format(x3,y3))" 188 | ] 189 | }, 190 | { 191 | "cell_type": "markdown", 192 | "metadata": {}, 193 | "source": [ 194 | "#### Exercise 4\n", 195 | "For the curve $y^{2} = x^{3} + 5x + 7$:\n", 196 | "\n", 197 | "1- What is $(3,7) + (18,77)$?\n", 198 | "\n", 199 | "2- Verify this point is on the curve" 200 | ] 201 | }, 202 | { 203 | "cell_type": "code", 204 | "execution_count": null, 205 | "metadata": { 206 | "collapsed": true 207 | }, 208 | "outputs": [], 209 | "source": [] 210 | }, 211 | { 212 | "cell_type": "code", 213 | "execution_count": null, 214 | "metadata": { 215 | "collapsed": true 216 | }, 217 | "outputs": [], 218 | "source": [] 219 | }, 220 | { 221 | "cell_type": "code", 222 | "execution_count": null, 223 | "metadata": { 224 | "collapsed": false 225 | }, 226 | "outputs": [], 227 | "source": [ 228 | "# Curve: y^2 = x^3 + 5x + 7\n", 229 | "# What is (2,5) + (2,5)\n", 230 | "\n", 231 | "s = (3*2**2+5)/(2*5.)\n", 232 | "x3 = s**2 - 2*2\n", 233 | "y3 = s*(2 - x3) - 5\n", 234 | "\n", 235 | "print (\"({},{})\".format(x3,y3))" 236 | ] 237 | }, 238 | { 239 | "cell_type": "markdown", 240 | "metadata": {}, 241 | "source": [ 242 | "#### Exercise 5\n", 243 | "For the curve $y^{2} = x^{3} + 5x + 7$:\n", 244 | "\n", 245 | "1- What is $(3,7) + (3,7)$?\n", 246 | "\n", 247 | "2- Verify this point is on the curve\n" 248 | ] 249 | }, 250 | { 251 | "cell_type": "code", 252 | "execution_count": null, 253 | "metadata": { 254 | "collapsed": true 255 | }, 256 | "outputs": [], 257 | "source": [] 258 | }, 259 | { 260 | "cell_type": "code", 261 | "execution_count": null, 262 | "metadata": { 263 | "collapsed": true 264 | }, 265 | "outputs": [], 266 | "source": [] 267 | } 268 | ], 269 | "metadata": { 270 | "kernelspec": { 271 | "display_name": "Python 2", 272 | "language": "python", 273 | "name": "python2" 274 | }, 275 | "language_info": { 276 | "codemirror_mode": { 277 | "name": "ipython", 278 | "version": 2 279 | }, 280 | "file_extension": ".py", 281 | "mimetype": "text/x-python", 282 | "name": "python", 283 | "nbconvert_exporter": "python", 284 | "pygments_lexer": "ipython2", 285 | "version": "2.7.6" 286 | } 287 | }, 288 | "nbformat": 4, 289 | "nbformat_minor": 1 290 | } 291 | -------------------------------------------------------------------------------- /Session_2.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "### Session 2" 8 | ] 9 | }, 10 | { 11 | "cell_type": "code", 12 | "execution_count": null, 13 | "metadata": { 14 | "collapsed": false 15 | }, 16 | "outputs": [], 17 | "source": [ 18 | "# Verify (73,128) is on the curve y^2 = x^3 + 7 over F_137\n", 19 | "\n", 20 | "LHS = 128**2 % 137\n", 21 | "RHS = (73**3+7) % 137\n", 22 | "print(RHS == LHS)\n" 23 | ] 24 | }, 25 | { 26 | "cell_type": "markdown", 27 | "metadata": {}, 28 | "source": [ 29 | "#### Exercise 1\n", 30 | "\n", 31 | "Which of these points are on the $y^{2}=x^{3}+7$ curve over $F_{223}$?\n", 32 | "\n", 33 | "a) $(192,105)$\n", 34 | "\n", 35 | "b) $(17,56)$\n", 36 | "\n", 37 | "c) $(200,119)$\n", 38 | "\n", 39 | "d) $(1,193)$\n", 40 | "\n", 41 | "e) $(42,99)$" 42 | ] 43 | }, 44 | { 45 | "cell_type": "code", 46 | "execution_count": null, 47 | "metadata": { 48 | "collapsed": true 49 | }, 50 | "outputs": [], 51 | "source": [] 52 | }, 53 | { 54 | "cell_type": "code", 55 | "execution_count": null, 56 | "metadata": { 57 | "collapsed": false 58 | }, 59 | "outputs": [], 60 | "source": [] 61 | }, 62 | { 63 | "cell_type": "code", 64 | "execution_count": null, 65 | "metadata": { 66 | "collapsed": false 67 | }, 68 | "outputs": [], 69 | "source": [ 70 | "# Curve: y^2 = x^3 + 5x + 7 over F_137\n", 71 | "# What is (73,128) + (46,22)\n", 72 | "\n", 73 | "s = ((128 - 22) * pow(73 - 46, 137 - 2, 137)) % 137\n", 74 | "x3 = (s**2 - 73 - 46) % 137\n", 75 | "y3 = (s*(73 - x3) - 128) % 137\n", 76 | "\n", 77 | "print (\"({},{})\".format(x3,y3))\n", 78 | "\n", 79 | "#or\n", 80 | "\n", 81 | "def add_points(point,_point, field):\n", 82 | " s = ((_point[1] - point[1]) * pow(_point[0] - point[0], field - 2, field)) % 137\n", 83 | " x3 = (s**2 - point[0] - _point[0]) % field\n", 84 | " y3 = (s*(point[0] - x3) - point[1]) % field \n", 85 | " return (x3, y3) \n", 86 | "\n", 87 | "print add((46,22),(73,128), 137)\n" 88 | ] 89 | }, 90 | { 91 | "cell_type": "markdown", 92 | "metadata": {}, 93 | "source": [ 94 | "#### Exercise 2\n", 95 | "\n", 96 | "For the curve $y^{2}=x^{3}+7$ over $F_{223}$, find:\n", 97 | "\n", 98 | "1- $(192,105) + (17,56) = ?$\n", 99 | "\n", 100 | "2- $(47,71) + (117,141) = ?$\n", 101 | "\n", 102 | "3- $(143,98) + (76,66) = ?$" 103 | ] 104 | }, 105 | { 106 | "cell_type": "code", 107 | "execution_count": null, 108 | "metadata": { 109 | "collapsed": true 110 | }, 111 | "outputs": [], 112 | "source": [] 113 | }, 114 | { 115 | "cell_type": "code", 116 | "execution_count": null, 117 | "metadata": { 118 | "collapsed": true 119 | }, 120 | "outputs": [], 121 | "source": [] 122 | }, 123 | { 124 | "cell_type": "code", 125 | "execution_count": null, 126 | "metadata": { 127 | "collapsed": false 128 | }, 129 | "outputs": [], 130 | "source": [ 131 | "# Curve: y^2 = x^3 + 5x + 7 over F_137\n", 132 | "# What is 2*(73,128)\n", 133 | "\n", 134 | "def double_point(point, field):\n", 135 | " s = (3*(point[0]**2)) * pow(2*point[1], field - 2, field) % field\n", 136 | " x3 = (s**2 - 2*point[0]) % field\n", 137 | " y3 = (s*(point[0] - x3) - point[1]) % field\n", 138 | " return (x3, y3)\n", 139 | "\n", 140 | "print double_point((73,128),137)\n" 141 | ] 142 | }, 143 | { 144 | "cell_type": "markdown", 145 | "metadata": {}, 146 | "source": [ 147 | "#### Exercise 3\n", 148 | "For the curve $y^{2}=x^{3}+7$ over $F_{223}$, find:\n", 149 | "\n", 150 | "$2\\times(192,105) = ?$\n", 151 | "\n", 152 | "$2\\times(143,98) = ?$\n", 153 | "\n", 154 | "$2\\times(47,71) = ?$\n", 155 | "\n", 156 | "$4\\times(47,71) = ?$\n", 157 | "\n", 158 | "$8\\times(47,71) = ?$\n", 159 | "\n", 160 | "$21\\times(47,71) = ?$" 161 | ] 162 | }, 163 | { 164 | "cell_type": "code", 165 | "execution_count": null, 166 | "metadata": { 167 | "collapsed": false 168 | }, 169 | "outputs": [], 170 | "source": [] 171 | }, 172 | { 173 | "cell_type": "code", 174 | "execution_count": null, 175 | "metadata": { 176 | "collapsed": false 177 | }, 178 | "outputs": [], 179 | "source": [] 180 | }, 181 | { 182 | "cell_type": "code", 183 | "execution_count": null, 184 | "metadata": { 185 | "collapsed": false 186 | }, 187 | "outputs": [], 188 | "source": [ 189 | "# y^2 = x^3 + 7 over F_223, G=(47,71)\n", 190 | "# How many elements does this group have?\n", 191 | "# {G, 2G, 3G, ..., nG} where nG=inf\n", 192 | "\n", 193 | "def multiply_point(point, n, field):\n", 194 | " _point = 0\n", 195 | " def add_point():\n", 196 | " if _point == 0:\n", 197 | " return point\n", 198 | " elif _point == point:\n", 199 | " return double_point()\n", 200 | " else:\n", 201 | " s = ((_point[1] - point[1]) * pow(_point[0] - point[0], field - 2, field)) % field\n", 202 | " x3 = (s**2 - point[0] - _point[0]) % field\n", 203 | " y3 = (s*(point[0] - x3) - point[1]) % field \n", 204 | " return (x3, y3) \n", 205 | " def double_point():\n", 206 | " s = (3*(_point[0]**2)) * pow(2*_point[1], field - 2, field) % field\n", 207 | " x3 = (s**2 - 2*_point[0]) % field\n", 208 | " y3 = (s*(_point[0] - x3) - _point[1]) % field\n", 209 | " return (x3, y3)\n", 210 | " for i in range(n):\n", 211 | " _point = add_point()\n", 212 | " \n", 213 | " return _point\n", 214 | "\n", 215 | "print multiply_point((47,71),21,223)\n" 216 | ] 217 | }, 218 | { 219 | "cell_type": "markdown", 220 | "metadata": {}, 221 | "source": [ 222 | "#### Exercise 4\n", 223 | "For the curve $y^{2}=x^{3}+7$ over $F_{223}$, and $G=(15,86)$:\n", 224 | "\n", 225 | "\n", 226 | "How many elements does this group have?\n", 227 | "\n", 228 | "$\\{G, 2G, 3G, ... nG\\}$ where $nG=∞$" 229 | ] 230 | }, 231 | { 232 | "cell_type": "code", 233 | "execution_count": null, 234 | "metadata": { 235 | "collapsed": true 236 | }, 237 | "outputs": [], 238 | "source": [] 239 | }, 240 | { 241 | "cell_type": "code", 242 | "execution_count": null, 243 | "metadata": { 244 | "collapsed": false 245 | }, 246 | "outputs": [], 247 | "source": [ 248 | "# Confirming G is on the curve\n", 249 | "# G = (79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798,\n", 250 | "# 483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8)\n", 251 | "\n", 252 | "x = 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798\n", 253 | "y = 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8\n", 254 | "p = 2**256 - 2**32 - 977\n", 255 | "print y**2 % p == (x**3 + 7) % p" 256 | ] 257 | }, 258 | { 259 | "cell_type": "code", 260 | "execution_count": null, 261 | "metadata": { 262 | "collapsed": false 263 | }, 264 | "outputs": [], 265 | "source": [ 266 | "# Confirming the order of G is n\n", 267 | "\n", 268 | "# G = (79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798,\n", 269 | "# 483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8)\n", 270 | "\n", 271 | "n = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141\n", 272 | "x = 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798\n", 273 | "y = 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8\n", 274 | "n = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141\n", 275 | "from pycoin.ecdsa import generator_secp256k1 as g\n", 276 | "print (n*g).pair()" 277 | ] 278 | }, 279 | { 280 | "cell_type": "code", 281 | "execution_count": null, 282 | "metadata": { 283 | "collapsed": false 284 | }, 285 | "outputs": [], 286 | "source": [ 287 | "# Getting a public key from private\n", 288 | "\n", 289 | "from pycoin.ecdsa import generator_secp256k1 as g\n", 290 | "secret = 999\n", 291 | "x, y = (secret*g).pair()\n", 292 | "print(hex(x), hex(y))" 293 | ] 294 | }, 295 | { 296 | "cell_type": "markdown", 297 | "metadata": {}, 298 | "source": [ 299 | "#### Exercise 5\n", 300 | "\n", 301 | "1- Get the public point where\n", 302 | "\n", 303 | "$s=7$\n", 304 | "\n", 305 | "$s=1485$\n", 306 | "\n", 307 | "$s=2128$\n", 308 | "\n", 309 | "$s=2240+231$\n", 310 | "\n", 311 | "2- Confirm the resulting points lie on the\n", 312 | "secp256k1 curve $y^{2}=x^{3}+7$" 313 | ] 314 | }, 315 | { 316 | "cell_type": "code", 317 | "execution_count": null, 318 | "metadata": { 319 | "collapsed": true 320 | }, 321 | "outputs": [], 322 | "source": [] 323 | }, 324 | { 325 | "cell_type": "code", 326 | "execution_count": null, 327 | "metadata": { 328 | "collapsed": true 329 | }, 330 | "outputs": [], 331 | "source": [] 332 | }, 333 | { 334 | "cell_type": "code", 335 | "execution_count": null, 336 | "metadata": { 337 | "collapsed": true 338 | }, 339 | "outputs": [], 340 | "source": [] 341 | }, 342 | { 343 | "cell_type": "code", 344 | "execution_count": null, 345 | "metadata": { 346 | "collapsed": false 347 | }, 348 | "outputs": [], 349 | "source": [] 350 | }, 351 | { 352 | "cell_type": "code", 353 | "execution_count": null, 354 | "metadata": { 355 | "collapsed": false 356 | }, 357 | "outputs": [], 358 | "source": [ 359 | "\n" 360 | ] 361 | }, 362 | { 363 | "cell_type": "markdown", 364 | "metadata": {}, 365 | "source": [ 366 | "#### Exercise 6\n", 367 | "\n", 368 | "Find the compressed and uncompressed SEC\n", 369 | "format for public keys where the private key is:\n", 370 | "\n", 371 | "1- $999^{3}$\n", 372 | "\n", 373 | "2- 123\n", 374 | "\n", 375 | "3- 42424242" 376 | ] 377 | }, 378 | { 379 | "cell_type": "code", 380 | "execution_count": null, 381 | "metadata": { 382 | "collapsed": true 383 | }, 384 | "outputs": [], 385 | "source": [] 386 | }, 387 | { 388 | "cell_type": "code", 389 | "execution_count": null, 390 | "metadata": { 391 | "collapsed": true 392 | }, 393 | "outputs": [], 394 | "source": [] 395 | }, 396 | { 397 | "cell_type": "code", 398 | "execution_count": null, 399 | "metadata": { 400 | "collapsed": false 401 | }, 402 | "outputs": [], 403 | "source": [ 404 | "# Addresses, SEC format\n", 405 | "\n", 406 | "from pycoin.encoding import b2a_base58, hash160\n", 407 | "from hashlib import sha256\n", 408 | "from binascii import unhexlify\n", 409 | "sec = unhexlify(\"025CBDF0646E5DB4EAA398F365F2EA7A0E3D419B7E0330E39CE92BDDEDCAC4F9BC\")\n", 410 | "h160 = hash160(sec)\n", 411 | "raw = chr(0) + h160\n", 412 | "raw = raw + sha256(raw).digest()[:4]\n", 413 | "print b2a_base58(raw)\n" 414 | ] 415 | }, 416 | { 417 | "cell_type": "markdown", 418 | "metadata": {}, 419 | "source": [ 420 | "#### Exercise 7\n", 421 | "\n", 422 | "Find the mainnet and testnet address corresponding to these private keys:\n", 423 | "\n", 424 | "1- Compressed, $888^{3}$\n", 425 | "\n", 426 | "2- Uncompressed, $321$\n", 427 | "\n", 428 | "3- Uncompressed, $4242424242$" 429 | ] 430 | }, 431 | { 432 | "cell_type": "code", 433 | "execution_count": null, 434 | "metadata": { 435 | "collapsed": true 436 | }, 437 | "outputs": [], 438 | "source": [] 439 | }, 440 | { 441 | "cell_type": "code", 442 | "execution_count": null, 443 | "metadata": { 444 | "collapsed": true 445 | }, 446 | "outputs": [], 447 | "source": [] 448 | }, 449 | { 450 | "cell_type": "markdown", 451 | "metadata": {}, 452 | "source": [ 453 | "#### Exercise 8\n", 454 | "\n", 455 | "Create a testnet address using your own secret key. Send the secret key and address to me.\n", 456 | "\n", 457 | "Record this key and address! You will need it\n", 458 | "tomorrow." 459 | ] 460 | }, 461 | { 462 | "cell_type": "code", 463 | "execution_count": null, 464 | "metadata": { 465 | "collapsed": true 466 | }, 467 | "outputs": [], 468 | "source": [] 469 | }, 470 | { 471 | "cell_type": "code", 472 | "execution_count": null, 473 | "metadata": { 474 | "collapsed": true 475 | }, 476 | "outputs": [], 477 | "source": [] 478 | }, 479 | { 480 | "cell_type": "code", 481 | "execution_count": null, 482 | "metadata": { 483 | "collapsed": false 484 | }, 485 | "outputs": [], 486 | "source": [ 487 | "# Signing Example\n", 488 | "\n", 489 | "from pycoin.ecdsa import generator_secp256k1 as g\n", 490 | "from random import randint\n", 491 | "n = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141\n", 492 | "e = 4\n", 493 | "z = randint(0, 2**256)\n", 494 | "k = randint(0, 2**256)\n", 495 | "r = (k*g).pair()[0]\n", 496 | "s = (z+r*e) * pow(k, n-2, n) % n\n", 497 | "print (hex(z), hex(r), hex(s))" 498 | ] 499 | }, 500 | { 501 | "cell_type": "code", 502 | "execution_count": null, 503 | "metadata": { 504 | "collapsed": false 505 | }, 506 | "outputs": [], 507 | "source": [ 508 | "# Verification Example\n", 509 | "\n", 510 | "from pycoin.ecdsa import generator_secp256k1 as g\n", 511 | "n = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141\n", 512 | "z = 0x524c14a77b666d906fbe56973becf3b3b9eac65442774473c68407e89c5659de\n", 513 | "r = 0xc0824a3ccdf3482f1435ef1917fad4a1d5573a15f0fa18a9b81dc76a941c4a3c\n", 514 | "s = 0x84ada30118411ef3f1777690d3dc182c289e04486375e91ba73bc48c51c59da7\n", 515 | "pub = g.__class__(g.curve(),\n", 516 | "0xe493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13,\n", 517 | "0x51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922)\n", 518 | "u = z * pow(s, n-2, n) % n\n", 519 | "v = r * pow(s, n-2, n) % n\n", 520 | "(u*g + v*pub).pair()[0] == r" 521 | ] 522 | }, 523 | { 524 | "cell_type": "markdown", 525 | "metadata": {}, 526 | "source": [ 527 | "#### Exercise 9\n", 528 | "\n", 529 | "Are these sigs valid?\n", 530 | "\n", 531 | "P = (887387e452b8eacc4acfde10d9aaf7f6d9a0f975aabb10d006e4da568744d06c,\n", 532 | "61de6d95231cd89026e286df3b6ae4a894a3378e393e93a0f45b666329a0ae34)\n", 533 | "\n", 534 | "1- z, r, s =\n", 535 | "ec208baa0fc1c19f708a9ca96fdeff3ac3f230bb4a7ba4aede4942ad003c0f60,\n", 536 | "ac8d1c87e51d0d441be8b3dd5b05c8795b48875dffe00b7ffcfac23010d3a395,\n", 537 | "68342ceff8935ededd102dd876ffd6ba72d6a427a3edb13d26eb0781cb423c4\n", 538 | "\n", 539 | "2- z, r, s =\n", 540 | "7c076ff316692a3d7eb3c3bb0f8b1488cf72e1afcd929e29307032997a838a3d,\n", 541 | "eff69ef2b1bd93a66ed5219add4fb51e11a840f404876325a1e8ffe0529a2c,\n", 542 | "c7207fee197d27c618aea621406f6bf5ef6fca38681d82b2f06fddbdce6feab6" 543 | ] 544 | }, 545 | { 546 | "cell_type": "code", 547 | "execution_count": null, 548 | "metadata": { 549 | "collapsed": true 550 | }, 551 | "outputs": [], 552 | "source": [] 553 | }, 554 | { 555 | "cell_type": "code", 556 | "execution_count": null, 557 | "metadata": { 558 | "collapsed": true 559 | }, 560 | "outputs": [], 561 | "source": [] 562 | }, 563 | { 564 | "cell_type": "code", 565 | "execution_count": null, 566 | "metadata": { 567 | "collapsed": false 568 | }, 569 | "outputs": [], 570 | "source": [ 571 | "# Encryption Example (error)\n", 572 | "\n", 573 | "from pycoin.ecdsa import generator_secp256k1 as g\n", 574 | "from binascii import hexlify\n", 575 | "from random import randint\n", 576 | "p = g.__class__(g.curve(),\n", 577 | "0x935581e52c354cd2f484fe8ed83af7a3097005b2f9c60bff71d35bd795f54b67,\n", 578 | "0x3296fb8e372dec2f72836d46f17abd994218feefccefd89b6a3dc2b2da9a6375)\n", 579 | "k = randint(0, 2**256)\n", 580 | "shared_secret = (k*p).pair()\n", 581 | "message = \"My name is Inrigo Montoya, you killed my father, prepare to die!\"\n", 582 | "m_hex = int(hexlify(message), 16)\n", 583 | "pad = shared_secret[0] * 2**256 + shared_secret[1]\n", 584 | "print hexlify(m_hex ^ pad)" 585 | ] 586 | }, 587 | { 588 | "cell_type": "code", 589 | "execution_count": null, 590 | "metadata": { 591 | "collapsed": false 592 | }, 593 | "outputs": [], 594 | "source": [ 595 | "# Decryption Example\n", 596 | "\n", 597 | "# Your secret exponent = 8675309\n", 598 | "# Q = (d13e1fe6729be5add3e283fadda877064eebc4f34fec97f72f369b2a859508e4,\n", 599 | "# bb4dbb92e9dec51e92f7ab6976900e68143f2be4b9c9397f55820a6b2a35b322)\n", 600 | "# Message =\n", 601 | "# ba207cb26fd74cccd55018427c89bffdc7c6e977bcd72145e2323966de072698e4411b6cf330323c120a138bde2\n", 602 | "# 6909d97a954c64bb5c37797c10339fac581e8\n", 603 | "\n", 604 | "from pycoin.ecdsa import generator_secp256k1 as g\n", 605 | "from binascii import unhexlify\n", 606 | "q = g.__class__(g.curve(),\n", 607 | "0xd13e1fe6729be5add3e283fadda877064eebc4f34fec97f72f369b2a859508e4,\n", 608 | "0xbb4dbb92e9dec51e92f7ab6976900e68143f2be4b9c9397f55820a6b2a35b322)\n", 609 | "message = 0xba207cb26fd74cccd55018427c89bffdc7c6e977bcd72145e2323966de072698e4411b6cf330323c120a138bde26909d97a954c64bb5c37797c10339fac581e8\n", 610 | "shared_secret = (8675309*q).pair()\n", 611 | "pad = shared_secret[0] * 2**256 + shared_secret[1]\n", 612 | "unhexlify(hex(pad ^ message)[2:-1])" 613 | ] 614 | }, 615 | { 616 | "cell_type": "code", 617 | "execution_count": null, 618 | "metadata": { 619 | "collapsed": true 620 | }, 621 | "outputs": [], 622 | "source": [] 623 | } 624 | ], 625 | "metadata": { 626 | "kernelspec": { 627 | "display_name": "Python 2", 628 | "language": "python", 629 | "name": "python2" 630 | }, 631 | "language_info": { 632 | "codemirror_mode": { 633 | "name": "ipython", 634 | "version": 2 635 | }, 636 | "file_extension": ".py", 637 | "mimetype": "text/x-python", 638 | "name": "python", 639 | "nbconvert_exporter": "python", 640 | "pygments_lexer": "ipython2", 641 | "version": "2.7.6" 642 | } 643 | }, 644 | "nbformat": 4, 645 | "nbformat_minor": 1 646 | } 647 | -------------------------------------------------------------------------------- /Session_3.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "### Session 3" 8 | ] 9 | }, 10 | { 11 | "cell_type": "code", 12 | "execution_count": null, 13 | "metadata": { 14 | "collapsed": false 15 | }, 16 | "outputs": [], 17 | "source": [ 18 | "# Encode 2^256-2^200 in WIF mainnet/testnet compressed/uncompressed\n", 19 | "\n", 20 | "from pycoin.encoding import b2a_hashed_base58\n", 21 | "from binascii import unhexlify\n", 22 | "s = unhexlify(hex(2**256-2**200)[2:-1])\n", 23 | "print (b2a_hashed_base58(chr(0x80)+s))\n", 24 | "print (b2a_hashed_base58(chr(0x80)+s+chr(1)))\n", 25 | "print (b2a_hashed_base58(chr(0xef)+s))\n", 26 | "print (b2a_hashed_base58(chr(0xef)+s+chr(1)))" 27 | ] 28 | }, 29 | { 30 | "cell_type": "markdown", 31 | "metadata": {}, 32 | "source": [ 33 | "#### Exercise 1\n", 34 | "Find the WIF format of the following\n", 35 | "\n", 36 | "1- $2^{256}-2^{199}$, mainnet, compressed\n", 37 | "\n", 38 | "2- $2^{256}-2^{201}$, testnet, uncompressed\n", 39 | "\n", 40 | "3- 0dba685b4511dbd3d368e5c4358a1277de9486447af7b3604a69b8d9d8b7889d, mainnet, uncompressed\n", 41 | "\n", 42 | "4- 1cca23de92fd1862fb5b76e5f4f50eb082165e5191e116c18ed1a6b24be6a53f, testnet, compressed" 43 | ] 44 | }, 45 | { 46 | "cell_type": "code", 47 | "execution_count": null, 48 | "metadata": { 49 | "collapsed": false 50 | }, 51 | "outputs": [], 52 | "source": [ 53 | "# Encode 1234567890 in both Big Endian and Little Endian\n", 54 | "h = hex(1234567890)\n", 55 | "print(h)\n", 56 | "from binascii import hexlify, unhexlify\n", 57 | "print (hexlify(unhexlify(h[2:])[::-1]))\n" 58 | ] 59 | }, 60 | { 61 | "cell_type": "code", 62 | "execution_count": null, 63 | "metadata": { 64 | "collapsed": false 65 | }, 66 | "outputs": [], 67 | "source": [ 68 | "# Decode Little Endian number: 0x17e8fa\n", 69 | "h = hex(1234567890)\n", 70 | "print(h)\n", 71 | "from binascii import hexlify, unhexlify\n", 72 | "print (hexlify(unhexlify(h[2:])[::-1]))" 73 | ] 74 | }, 75 | { 76 | "cell_type": "markdown", 77 | "metadata": {}, 78 | "source": [ 79 | "#### Exercise 2\n", 80 | "\n", 81 | "1- Convert the following hex from Big Endian to Little Endian\n", 82 | "\n", 83 | "03ee4f7a4e68f802303bc659f8f817964b4b74fe046facc3ae1be4679d622c45\n", 84 | "\n", 85 | "813f79011acb80925dfe69b3def355fe914bd1d96a3f5f71bf8303c6a989c7d1\n", 86 | "\n", 87 | "2- Convert the following numbers from Little Endian to\n", 88 | "Decimal\n", 89 | "\n", 90 | "99c3980000000000\n", 91 | "\n", 92 | "a135ef0100000000" 93 | ] 94 | }, 95 | { 96 | "cell_type": "code", 97 | "execution_count": null, 98 | "metadata": { 99 | "collapsed": true 100 | }, 101 | "outputs": [], 102 | "source": [] 103 | }, 104 | { 105 | "cell_type": "code", 106 | "execution_count": null, 107 | "metadata": { 108 | "collapsed": false 109 | }, 110 | "outputs": [], 111 | "source": [ 112 | "# Convert Little Endian to Big\n", 113 | "\n", 114 | "from binascii import hexlify, unhexlify\n", 115 | "x = \"03ee4f7a4e68f802303bc659f8f817964b4b74fe046facc3ae1be4679d622c45\"\n", 116 | "b = unhexlify(x)\n", 117 | "print(hexlify(b[::-1]))" 118 | ] 119 | }, 120 | { 121 | "cell_type": "markdown", 122 | "metadata": {}, 123 | "source": [ 124 | "#### Exercise 3\n", 125 | "\n", 126 | "Look up this transaction on blockchain.info:\n", 127 | "\n", 128 | "d1c789a9c60383bf715f3f6ad9d14b91fe55f3deb369fe5d9280cb1a01793f81\n", 129 | "\n", 130 | "Get the hex representation of this transaction." 131 | ] 132 | }, 133 | { 134 | "cell_type": "code", 135 | "execution_count": null, 136 | "metadata": { 137 | "collapsed": true 138 | }, 139 | "outputs": [], 140 | "source": [] 141 | }, 142 | { 143 | "cell_type": "code", 144 | "execution_count": null, 145 | "metadata": { 146 | "collapsed": true 147 | }, 148 | "outputs": [], 149 | "source": [] 150 | }, 151 | { 152 | "cell_type": "markdown", 153 | "metadata": {}, 154 | "source": [ 155 | "#### Exercise 4\n", 156 | "\n", 157 | "010000000456919960ac691763688d3d3bcea9ad6ecaf875df5339e148a1fc61c6ed7a069e010000006a47304402204585bcdef85e6b1\n", 158 | "c6af5c2669d4830ff86e42dd205c0e089bc2a821657e951c002201024a10366077f87d6bce1f7100ad8cfa8a064b39d4e8fe4ea13a7b7\n", 159 | "1aa8180f012102f0da57e85eec2934a82a585ea337ce2f4998b50ae699dd79f5880e253dafafb7feffffffeb8f51f4038dc17e6313cf8\n", 160 | "31d4f02281c2a468bde0fafd37f1bf882729e7fd3000000006a47304402207899531a52d59a6de200179928ca900254a36b8dff8bb75f\n", 161 | "5f5d71b1cdc26125022008b422690b8461cb52c3cc30330b23d574351872b7c361e9aae3649071c1a7160121035d5c93d9ac96881f19b\n", 162 | "a1f686f15f009ded7c62efe85a872e6a19b43c15a2937feffffff567bf40595119d1bb8a3037c356efd56170b64cbcc160fb028fa1070\n", 163 | "4b45d775000000006a47304402204c7c7818424c7f7911da6cddc59655a70af1cb5eaf17c69dadbfc74ffa0b662f02207599e08bc8023\n", 164 | "693ad4e9527dc42c34210f7a7d1d1ddfc8492b654a11e7620a0012102158b46fbdff65d0172b7989aec8850aa0dae49abfb84c81ae6e5\n", 165 | "b251a58ace5cfeffffffd63a5e6c16e620f86f375925b21cabaf736c779f88fd04dcad51d26690f7f345010000006a47304402200633e\n", 166 | "a0d3314bea0d95b3cd8dadb2ef79ea8331ffe1e61f762c0f6daea0fabde022029f23b3e9c30f080446150b23852028751635dcee2be66\n", 167 | "9c2a1686a4b5edf304012103ffd6f4a67e94aba353a00882e563ff2722eb4cff0ad6006e86ee20dfe7520d55feffffff0251430f00000\n", 168 | "000001976a914ab0c0b2e98b1ab6dbf67d4750b0a56244948a87988ac005a6202000000001976a9143c82d7df364eb6c75be8c80df2b3\n", 169 | "eda8db57397088ac46430600\n", 170 | "\n", 171 | "1- What is the scriptSig from the second input in this tx?\n", 172 | "\n", 173 | "2- What is the scriptPubKey of the second input in this tx?\n", 174 | "\n", 175 | "3- What is the amount for that input?" 176 | ] 177 | }, 178 | { 179 | "cell_type": "code", 180 | "execution_count": null, 181 | "metadata": { 182 | "collapsed": true 183 | }, 184 | "outputs": [], 185 | "source": [] 186 | } 187 | ], 188 | "metadata": { 189 | "kernelspec": { 190 | "display_name": "Python 2", 191 | "language": "python", 192 | "name": "python2" 193 | }, 194 | "language_info": { 195 | "codemirror_mode": { 196 | "name": "ipython", 197 | "version": 2 198 | }, 199 | "file_extension": ".py", 200 | "mimetype": "text/x-python", 201 | "name": "python", 202 | "nbconvert_exporter": "python", 203 | "pygments_lexer": "ipython2", 204 | "version": "2.7.6" 205 | } 206 | }, 207 | "nbformat": 4, 208 | "nbformat_minor": 1 209 | } 210 | -------------------------------------------------------------------------------- /Session_4.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "### Session 4\n", 8 | "\n", 9 | "#### Exercise 1\n", 10 | "\n", 11 | "How much is the transaction fee of this transaction?\n", 12 | "\n", 13 | "010000000456919960ac691763688d3d3bcea9ad6ecaf875df5339e148a1fc61c6ed7a069e010000006a47304402204585bcdef85e6b1\n", 14 | "c6af5c2669d4830ff86e42dd205c0e089bc2a821657e951c002201024a10366077f87d6bce1f7100ad8cfa8a064b39d4e8fe4ea13a7b7\n", 15 | "1aa8180f012102f0da57e85eec2934a82a585ea337ce2f4998b50ae699dd79f5880e253dafafb7feffffffeb8f51f4038dc17e6313cf8\n", 16 | "31d4f02281c2a468bde0fafd37f1bf882729e7fd3000000006a47304402207899531a52d59a6de200179928ca900254a36b8dff8bb75f\n", 17 | "5f5d71b1cdc26125022008b422690b8461cb52c3cc30330b23d574351872b7c361e9aae3649071c1a7160121035d5c93d9ac96881f19b\n", 18 | "a1f686f15f009ded7c62efe85a872e6a19b43c15a2937feffffff567bf40595119d1bb8a3037c356efd56170b64cbcc160fb028fa1070\n", 19 | "4b45d775000000006a47304402204c7c7818424c7f7911da6cddc59655a70af1cb5eaf17c69dadbfc74ffa0b662f02207599e08bc8023\n", 20 | "693ad4e9527dc42c34210f7a7d1d1ddfc8492b654a11e7620a0012102158b46fbdff65d0172b7989aec8850aa0dae49abfb84c81ae6e5\n", 21 | "b251a58ace5cfeffffffd63a5e6c16e620f86f375925b21cabaf736c779f88fd04dcad51d26690f7f345010000006a47304402200633e\n", 22 | "a0d3314bea0d95b3cd8dadb2ef79ea8331ffe1e61f762c0f6daea0fabde022029f23b3e9c30f080446150b23852028751635dcee2be66\n", 23 | "9c2a1686a4b5edf304012103ffd6f4a67e94aba353a00882e563ff2722eb4cff0ad6006e86ee20dfe7520d55feffffff0251430f00000\n", 24 | "000001976a914ab0c0b2e98b1ab6dbf67d4750b0a56244948a87988ac005a6202000000001976a9143c82d7df364eb6c75be8c80df2b3\n", 25 | "eda8db57397088ac46430600\n" 26 | ] 27 | }, 28 | { 29 | "cell_type": "code", 30 | "execution_count": null, 31 | "metadata": { 32 | "collapsed": true 33 | }, 34 | "outputs": [], 35 | "source": [] 36 | }, 37 | { 38 | "cell_type": "code", 39 | "execution_count": null, 40 | "metadata": { 41 | "collapsed": true 42 | }, 43 | "outputs": [], 44 | "source": [] 45 | }, 46 | { 47 | "cell_type": "code", 48 | "execution_count": null, 49 | "metadata": { 50 | "collapsed": false 51 | }, 52 | "outputs": [], 53 | "source": [ 54 | "# Double-sha256 this to get the hash that’s being signed (z)\n", 55 | "\n", 56 | "from hashlib import sha256\n", 57 | "from binascii import hexlify, unhexlify\n", 58 | "\n", 59 | "modified_tx = \"0100000001813f79011acb80925dfe69b3def355fe914bd1d96a3f5f71bf8303c6a989c7d1000000001976a914a802fc56c704ce87c42d7c92eb75e7896bdc41ae88acfeffffff02a135ef01000000001976a914bc3b654dca7e56b04dca18f2566cdaf02e8d9ada88ac99c39800000000001976a9141c4bc762dd5423e332166702cb75f40df79fea1288ac1943060001000000\"\n", 60 | "h = sha256(sha256(unhexlify(modified_tx)).digest()).hexdigest()\n", 61 | "print h\n", 62 | "z = int(h, 16)\n", 63 | "print z" 64 | ] 65 | }, 66 | { 67 | "cell_type": "code", 68 | "execution_count": null, 69 | "metadata": { 70 | "collapsed": false 71 | }, 72 | "outputs": [], 73 | "source": [ 74 | "# From the scriptsig we can get the x coordinate of the public key\n", 75 | "# We know y is odd (pubkey starts with 03). Here we get y \n", 76 | "# and the public point\n", 77 | "\n", 78 | "x = 0x49fc4e631e3624a545de3f89f5d8684c7b8138bd94bdd531d2e213bf016b278a\n", 79 | "from pycoin.ecdsa import generator_secp256k1 as g\n", 80 | "from pycoin.ecdsa import public_pair_for_x\n", 81 | "y = public_pair_for_x(g, x, is_even=False)[1]\n", 82 | "pub = g.__class__(g.curve(), x, y)\n", 83 | "print pub" 84 | ] 85 | }, 86 | { 87 | "cell_type": "markdown", 88 | "metadata": {}, 89 | "source": [ 90 | "#### Exercise 2\n", 91 | "\n", 92 | "Validate this signature:\n", 93 | "\n", 94 | "P = (sec compressed format)\n", 95 | "0349fc4e631e3624a545de3f89f5d8684c7b8138bd94bdd531d2e213bf016b278a\n", 96 | "\n", 97 | "z = 27e0c5994dec7824e56dec6b2fcb342eb7cdb0d0957c2fce9882f715e85d81a6\n", 98 | "\n", 99 | "r = ed81ff192e75a3fd2304004dcadb746fa5e24c5031ccfcf21320b0277457c98f\n", 100 | "\n", 101 | "s = 7a986d955c6e0cb35d446a89d3f56100f4d7f67801c31967743a9c8e10615bed" 102 | ] 103 | }, 104 | { 105 | "cell_type": "code", 106 | "execution_count": null, 107 | "metadata": { 108 | "collapsed": true 109 | }, 110 | "outputs": [], 111 | "source": [] 112 | }, 113 | { 114 | "cell_type": "code", 115 | "execution_count": null, 116 | "metadata": { 117 | "collapsed": true 118 | }, 119 | "outputs": [], 120 | "source": [] 121 | }, 122 | { 123 | "cell_type": "markdown", 124 | "metadata": {}, 125 | "source": [ 126 | "#### Exercise 3\n", 127 | "\n", 128 | "Validate the signature for the first input in this transaction:\n", 129 | "\n", 130 | "01000000012f5ab4d2666744a44864a63162060c2ae36ab0a2375b1c2b6b\n", 131 | "43077ed5dcbed6000000006a473044022034177d53fcb8e8cba62432c5f6\n", 132 | "cc3d11c16df1db0bce20b874cfc61128b529e1022040c2681a2845f5eb0c\n", 133 | "46adb89585604f7bf8397b82db3517afb63f8e3d609c990121035e8b10b6\n", 134 | "75477614809f3dde7fd0e33fb898af6d86f51a65a54c838fddd417a5feff\n", 135 | "ffff02c5872e00000000001976a91441b835c78fb1406305727d8925ff31\n", 136 | "5d90f9bbc588acae2e1700000000001976a914c300e84d277c6c7bcf1719\n", 137 | "0ebc4e7744609f8b0c88ac31470600" 138 | ] 139 | }, 140 | { 141 | "cell_type": "code", 142 | "execution_count": null, 143 | "metadata": { 144 | "collapsed": true 145 | }, 146 | "outputs": [], 147 | "source": [] 148 | }, 149 | { 150 | "cell_type": "code", 151 | "execution_count": null, 152 | "metadata": { 153 | "collapsed": true 154 | }, 155 | "outputs": [], 156 | "source": [] 157 | }, 158 | { 159 | "cell_type": "markdown", 160 | "metadata": {}, 161 | "source": [ 162 | "#### Exercise 4\n", 163 | "\n", 164 | "Determine a ScriptSig that will satisfy this:\n", 165 | "\n", 166 | "ScriptPubKey = OP_DUP OP_DUP OP_MUL\n", 167 | "OP_ADD OP_6 OP_EQUAL\n", 168 | "\n", 169 | "$X$ =>(op_dup, op_dup) $x,x,x$=> (op_mul)\n", 170 | "\n", 171 | "$x^{2},x$=>(op_add) $x^{2}+x$=>(op_6)6, $x^{2}+x$\n", 172 | "\n", 173 | "$x^{2}+x=6$ => $x=2,-3$\n" 174 | ] 175 | }, 176 | { 177 | "cell_type": "code", 178 | "execution_count": null, 179 | "metadata": { 180 | "collapsed": true 181 | }, 182 | "outputs": [], 183 | "source": [] 184 | }, 185 | { 186 | "cell_type": "code", 187 | "execution_count": null, 188 | "metadata": { 189 | "collapsed": true 190 | }, 191 | "outputs": [], 192 | "source": [] 193 | }, 194 | { 195 | "cell_type": "code", 196 | "execution_count": null, 197 | "metadata": { 198 | "collapsed": false 199 | }, 200 | "outputs": [], 201 | "source": [ 202 | "# ScriptPubKey\n", 203 | "# We want to send this to mnrVtF8DWjMu839VW3rBfgYaAfKk8983Xf\n", 204 | "# Figure out the actual hash160 from the address\n", 205 | "\n", 206 | "from pycoin.encoding import a2b_hashed_base58\n", 207 | "from binascii import hexlify\n", 208 | "\n", 209 | "print (hexlify(a2b_hashed_base58('mnrVtF8DWjMu839VW3rBfgYaAfKk8983Xf')[1:]))\n" 210 | ] 211 | }, 212 | { 213 | "cell_type": "markdown", 214 | "metadata": {}, 215 | "source": [ 216 | "#### Exercise 5\n", 217 | "\n", 218 | "Get the p2pkh ScriptPubKey of the address:\n", 219 | "\n", 220 | "mzx5YhAH9kNHtcN481u6WkjeHjYtVeKVh2" 221 | ] 222 | }, 223 | { 224 | "cell_type": "code", 225 | "execution_count": null, 226 | "metadata": { 227 | "collapsed": true 228 | }, 229 | "outputs": [], 230 | "source": [] 231 | }, 232 | { 233 | "cell_type": "code", 234 | "execution_count": null, 235 | "metadata": { 236 | "collapsed": true 237 | }, 238 | "outputs": [], 239 | "source": [] 240 | }, 241 | { 242 | "cell_type": "code", 243 | "execution_count": null, 244 | "metadata": { 245 | "collapsed": false 246 | }, 247 | "outputs": [], 248 | "source": [ 249 | "# Signing the transaction\n", 250 | "# Sign this hash\n", 251 | "\n", 252 | "secret = xxxx\n", 253 | "z = 0x026f3b5e37b44308ecc3984275e009f35de44652a7fb22f1761ed0d91caba688\n", 254 | "from pycoin.ecdsa import generator_secp256k1 as g\n", 255 | "from random import randint\n", 256 | "from binascii import hexlify\n", 257 | "n = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141\n", 258 | "k = randint(0, 2**256)\n", 259 | "r = (k*g).pair()[0]\n", 260 | "s = (z + r*secret) * pow(k, n-2, n) % n\n", 261 | "if s > n/2: s = n - s\n", 262 | "from pycoin.tx.script.der import sigencode_der\n", 263 | "print hexlify(sigencode_der(r,s))" 264 | ] 265 | }, 266 | { 267 | "cell_type": "code", 268 | "execution_count": null, 269 | "metadata": { 270 | "collapsed": true 271 | }, 272 | "outputs": [], 273 | "source": [] 274 | } 275 | ], 276 | "metadata": { 277 | "kernelspec": { 278 | "display_name": "Python 2", 279 | "language": "python", 280 | "name": "python2" 281 | }, 282 | "language_info": { 283 | "codemirror_mode": { 284 | "name": "ipython", 285 | "version": 2 286 | }, 287 | "file_extension": ".py", 288 | "mimetype": "text/x-python", 289 | "name": "python", 290 | "nbconvert_exporter": "python", 291 | "pygments_lexer": "ipython2", 292 | "version": "2.7.6" 293 | } 294 | }, 295 | "nbformat": 4, 296 | "nbformat_minor": 1 297 | } 298 | -------------------------------------------------------------------------------- /Session_5.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "### Session 5\n", 8 | "\n", 9 | "#### Exercise 1\n", 10 | "\n", 11 | "You have been sent 0.1 TBTC\n", 12 | "\n", 13 | "1- Send 0.05 TBTC to this address:\n", 14 | "mnrVtF8DWjMu839VW3rBfgYaAfKk8983Xf\n", 15 | "\n", 16 | "2- Send your transaction on:\n", 17 | "https://testnet.blockexplorer.com/tx/send" 18 | ] 19 | }, 20 | { 21 | "cell_type": "code", 22 | "execution_count": null, 23 | "metadata": { 24 | "collapsed": true 25 | }, 26 | "outputs": [], 27 | "source": [] 28 | }, 29 | { 30 | "cell_type": "code", 31 | "execution_count": null, 32 | "metadata": { 33 | "collapsed": true 34 | }, 35 | "outputs": [], 36 | "source": [] 37 | }, 38 | { 39 | "cell_type": "markdown", 40 | "metadata": {}, 41 | "source": [ 42 | "#### Exercise 2\n", 43 | "\n", 44 | "0100000001868278ed6ddfb6c1ed3ad5f8181eb0c7a385aa0836f01d5e4789e6bd304d87221a00000\n", 45 | "0db00483045022100dc92655fe37036f47756db8102e0d7d5e28b3beb83a8fef4f5dc0559bddfb94e\n", 46 | "02205a36d4e4e6c7fcd16658c50783e00c341609977aed3ad00937bf4ee942a899370148304502210\n", 47 | "0da6bee3c93766232079a01639d07fa869598749729ae323eab8eef53577d611b02207bef15429dca\n", 48 | "dce2121ea07f233115c6f09034c0be68db99980b9a6c5e75402201475221022626e955ea6ea6d9885\n", 49 | "0c994f9107b036b1334f18ca8830bfff1295d21cfdb702103b287eaf122eea69030a0e9feed096bed\n", 50 | "8045c8b98bec453e1ffac7fbdbd4bb7152aeffffffff04d3b11400000000001976a914904a49878c0\n", 51 | "adfc3aa05de7afad2cc15f483a56a88ac7f400900000000001976a914418327e3f3dda4cf5b908932\n", 52 | "5a4b95abdfa0334088ac722c0c00000000001976a914ba35042cfe9fc66fd35ac2224eebdafd1028a\n", 53 | "d2788acdc4ace020000000017a91474d691da1574e6b3c192ecfb52cc8984ee7b6c568700000000\n", 54 | "\n", 55 | "What is the amount and address of the second output shown\n", 56 | "here?" 57 | ] 58 | }, 59 | { 60 | "cell_type": "code", 61 | "execution_count": null, 62 | "metadata": { 63 | "collapsed": true 64 | }, 65 | "outputs": [], 66 | "source": [] 67 | }, 68 | { 69 | "cell_type": "code", 70 | "execution_count": null, 71 | "metadata": { 72 | "collapsed": true 73 | }, 74 | "outputs": [], 75 | "source": [] 76 | }, 77 | { 78 | "cell_type": "code", 79 | "execution_count": null, 80 | "metadata": { 81 | "collapsed": false 82 | }, 83 | "outputs": [], 84 | "source": [ 85 | "# Creating a p2sh address\n", 86 | "# 17a91474d691da1574e6b3c192ecfb52cc8984ee7b6c5687\n", 87 | "# = 74d691da1574e6b3c192ecfb52cc8984ee7b6c56\n", 88 | "#BIP0013 defines how to turn this into an address\n", 89 | "#For mainnet prepend byte 5, for testnet byte 192\n", 90 | "\n", 91 | "from pycoin.encoding import b2a_hashed_base58\n", 92 | "from binascii import unhexlify\n", 93 | "print (b2a_hashed_base58(chr(5)+unhexlify('74d691da1574e6b3c192ecfb52cc8984ee7b6c56')))\n" 94 | ] 95 | }, 96 | { 97 | "cell_type": "markdown", 98 | "metadata": {}, 99 | "source": [ 100 | "#### Exercise 3\n", 101 | "\n", 102 | "Find the hash160 of the RedeemScript:\n", 103 | "5221022626e955ea6ea6d98850c994f9107b036b1334f18\n", 104 | "ca8830bfff1295d21cfdb702103b287eaf122eea69030a0\n", 105 | "e9feed096bed8045c8b98bec453e1ffac7fbdbd4bb7152a\n", 106 | "e" 107 | ] 108 | }, 109 | { 110 | "cell_type": "code", 111 | "execution_count": null, 112 | "metadata": { 113 | "collapsed": true 114 | }, 115 | "outputs": [], 116 | "source": [] 117 | }, 118 | { 119 | "cell_type": "code", 120 | "execution_count": null, 121 | "metadata": { 122 | "collapsed": true 123 | }, 124 | "outputs": [], 125 | "source": [] 126 | }, 127 | { 128 | "cell_type": "code", 129 | "execution_count": null, 130 | "metadata": { 131 | "collapsed": false 132 | }, 133 | "outputs": [], 134 | "source": [ 135 | "# Verifying p2sh Transaction\n", 136 | "\n", 137 | "#Sig1 = 483045022100dc92655fe37036f47756db8102e0d7d5e28b3beb83a8fef4f5dc0559bddfb94e02205\n", 138 | "#a36d4e4e6c7fcd16658c50783e00c341609977aed3ad00937bf4ee942a8993701\n", 139 | "#Sig2 = 483045022100da6bee3c93766232079a01639d07fa869598749729ae323eab8eef53577d611b02207\n", 140 | "#bef15429dcadce2121ea07f233115c6f09034c0be68db99980b9a6c5e75402201\n", 141 | "\n", 142 | "#What did this sign and how do we verify?\n", 143 | "\n", 144 | "#We replace the scriptSig with the redeemScript and append the\n", 145 | "#sighash (SIGHASH_ALL)\n", 146 | "#We get the double-sha256 of this:\n", 147 | "# e71bfa115715d6fd33796948126f40a8cdd39f187e4afb03896795189fe1423c\n", 148 | "\n", 149 | "#We derive the r and s from the first signature\n", 150 | "#483045022100dc92655fe37036f47756db8102e0d7d5e28b3beb83a8fef4f5dc0559bddfb94e02205\n", 151 | "#a36d4e4e6c7fcd16658c50783e00c341609977aed3ad00937bf4ee942a8993701\n", 152 | "\n", 153 | "z = int('e71bfa115715d6fd33796948126f40a8cdd39f187e4afb03896795189fe1423c', 16)\n", 154 | "r = int('00dc92655fe37036f47756db8102e0d7d5e28b3beb83a8fef4f5dc0559bddfb94e', 16)\n", 155 | "s = int('5a36d4e4e6c7fcd16658c50783e00c341609977aed3ad00937bf4ee942a89937', 16)\n", 156 | "\n", 157 | "#We derive the pubkey from the first pubkey\n", 158 | "#022626e955ea6ea6d98850c994f9107b036b1334f18ca8830bfff1295d21cfdb70\n", 159 | "\n", 160 | "from pycoin.ecdsa import generator_secp256k1 as g\n", 161 | "from pycoin.ecdsa import public_pair_for_x, verify\n", 162 | "\n", 163 | "x = 0x2626e955ea6ea6d98850c994f9107b036b1334f18ca8830bfff1295d21cfdb70\n", 164 | "_, y = public_pair_for_x(g, x, is_even=True)\n", 165 | "pub = g.__class__(g.curve(), x, y)\n", 166 | "verify(g, (x,y), z, (r,s))\n" 167 | ] 168 | }, 169 | { 170 | "cell_type": "markdown", 171 | "metadata": {}, 172 | "source": [ 173 | "#### Exercise 4\n", 174 | "Validate the second signature with the second key" 175 | ] 176 | }, 177 | { 178 | "cell_type": "code", 179 | "execution_count": null, 180 | "metadata": { 181 | "collapsed": true 182 | }, 183 | "outputs": [], 184 | "source": [] 185 | }, 186 | { 187 | "cell_type": "code", 188 | "execution_count": null, 189 | "metadata": { 190 | "collapsed": true 191 | }, 192 | "outputs": [], 193 | "source": [] 194 | }, 195 | { 196 | "cell_type": "markdown", 197 | "metadata": {}, 198 | "source": [ 199 | "#### Exercise 5\n", 200 | "\n", 201 | "01000000010000000000000000000000000000000000000000000000000000000000000000fffffff\n", 202 | "f5e03d71b07254d696e656420627920416e74506f6f6c20626a31312f4542312f4144362f43205914\n", 203 | "293101fabe6d6d678e2c8c34afc36896e7d9402824ed38e856676ee94bfdb0c6c4bcd8b2e5666a040\n", 204 | "0000000000000c7270000a5e00e00ffffffff01faf20b58000000001976a914338c84849423992471\n", 205 | "bffb1a54a8d9b1d69dc28a88ac00000000\n", 206 | "\n", 207 | "Find the Output Address corresponding to this ScriptPubKey" 208 | ] 209 | }, 210 | { 211 | "cell_type": "code", 212 | "execution_count": null, 213 | "metadata": { 214 | "collapsed": true 215 | }, 216 | "outputs": [], 217 | "source": [] 218 | }, 219 | { 220 | "cell_type": "code", 221 | "execution_count": null, 222 | "metadata": { 223 | "collapsed": true 224 | }, 225 | "outputs": [], 226 | "source": [] 227 | } 228 | ], 229 | "metadata": { 230 | "kernelspec": { 231 | "display_name": "Python 2", 232 | "language": "python", 233 | "name": "python2" 234 | }, 235 | "language_info": { 236 | "codemirror_mode": { 237 | "name": "ipython", 238 | "version": 2 239 | }, 240 | "file_extension": ".py", 241 | "mimetype": "text/x-python", 242 | "name": "python", 243 | "nbconvert_exporter": "python", 244 | "pygments_lexer": "ipython2", 245 | "version": "2.7.6" 246 | } 247 | }, 248 | "nbformat": 4, 249 | "nbformat_minor": 1 250 | } 251 | -------------------------------------------------------------------------------- /Session_6.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "### Session 6\n", 8 | "\n", 9 | "#### Exercise 1\n", 10 | "\n", 11 | "020000208ec39428b17323fa0ddec8e887b4a7c53b8c0a0\n", 12 | "a220cfd0000000000000000005b0750fce0a889502d4050\n", 13 | "8d39576821155e9c9e3f5c3157f961db38fd8b25be1e77a\n", 14 | "759e93c0118a4ffd71d\n", 15 | "\n", 16 | "What is the double-sha256 hash of this block? Notice anything?" 17 | ] 18 | }, 19 | { 20 | "cell_type": "code", 21 | "execution_count": null, 22 | "metadata": { 23 | "collapsed": true 24 | }, 25 | "outputs": [], 26 | "source": [] 27 | }, 28 | { 29 | "cell_type": "code", 30 | "execution_count": null, 31 | "metadata": { 32 | "collapsed": true 33 | }, 34 | "outputs": [], 35 | "source": [] 36 | }, 37 | { 38 | "cell_type": "markdown", 39 | "metadata": {}, 40 | "source": [ 41 | "#### Exercise 2\n", 42 | "\n", 43 | "Parse this block:\n", 44 | "\n", 45 | "000000203c437224480966081c2b14afac79e58207d99\n", 46 | "6c8ac9d32000000000000000000847a4c2c77c8ecf041\n", 47 | "6ca07c2dc038414f14135017e18525f85cacdeedb5424\n", 48 | "4e0d6b958df620218c626368a" 49 | ] 50 | }, 51 | { 52 | "cell_type": "code", 53 | "execution_count": null, 54 | "metadata": { 55 | "collapsed": true 56 | }, 57 | "outputs": [], 58 | "source": [] 59 | }, 60 | { 61 | "cell_type": "code", 62 | "execution_count": null, 63 | "metadata": { 64 | "collapsed": true 65 | }, 66 | "outputs": [], 67 | "source": [] 68 | }, 69 | { 70 | "cell_type": "markdown", 71 | "metadata": {}, 72 | "source": [ 73 | "#### Exercise 3\n", 74 | "\n", 75 | "Calculate the target and difficulty for\n", 76 | "these bits:\n", 77 | " \n", 78 | "0xf2881718" 79 | ] 80 | }, 81 | { 82 | "cell_type": "code", 83 | "execution_count": null, 84 | "metadata": { 85 | "collapsed": true 86 | }, 87 | "outputs": [], 88 | "source": [] 89 | }, 90 | { 91 | "cell_type": "code", 92 | "execution_count": null, 93 | "metadata": { 94 | "collapsed": true 95 | }, 96 | "outputs": [], 97 | "source": [] 98 | }, 99 | { 100 | "cell_type": "markdown", 101 | "metadata": {}, 102 | "source": [ 103 | "#### Exercise 4\n", 104 | "\n", 105 | "Validate the proof-of-work for this block:\n", 106 | " \n", 107 | "04000000fbedbbf0cfdaf278c094f187f2eb\n", 108 | "987c86a199da22bbb2040000000000000000\n", 109 | "7b7697b29129648fa08b4bcd13c9d5e60abb\n", 110 | "973a1efac9c8d573c71c807c56c3d6213557\n", 111 | "faa80518c3737ec1" 112 | ] 113 | }, 114 | { 115 | "cell_type": "code", 116 | "execution_count": null, 117 | "metadata": { 118 | "collapsed": true 119 | }, 120 | "outputs": [], 121 | "source": [] 122 | }, 123 | { 124 | "cell_type": "code", 125 | "execution_count": null, 126 | "metadata": { 127 | "collapsed": true 128 | }, 129 | "outputs": [], 130 | "source": [] 131 | }, 132 | { 133 | "cell_type": "code", 134 | "execution_count": null, 135 | "metadata": { 136 | "collapsed": false 137 | }, 138 | "outputs": [], 139 | "source": [ 140 | "# Merkle Root Calculation Example\n", 141 | "from hashlib import sha256\n", 142 | "from binascii import hexlify, unhexlify\n", 143 | "\n", 144 | "def s2(x):\n", 145 | " return hashlib.sha256(hashlib.sha256(x).digest()).digest()\n", 146 | "\n", 147 | "hashes = # look up the hashes on block 1180730 on testnet\n", 148 | "leafs = [unhexlify(x)[::-1] for x in hashes]\n", 149 | "level3 = [s2(leafs[i] + leafs[i+1]) for i in range(0, len(leafs), 2)]\n", 150 | "level2 = [s2(level3[i] + level3[i+1]) for i in range(0, len(level3), 2)]\n", 151 | "level2.append(level2[-1])\n", 152 | "level1 = [s2(level2[i] + level2[i+1]) for i in range(0, len(level2), 2)]\n", 153 | "level0 = [s2(level1[i] + level1[i+1]) for i in range(0, len(level1), 2)]\n", 154 | "print(hexlify(level0[0][::-1]))" 155 | ] 156 | }, 157 | { 158 | "cell_type": "code", 159 | "execution_count": null, 160 | "metadata": { 161 | "collapsed": false 162 | }, 163 | "outputs": [], 164 | "source": [ 165 | "# Example Proof\n", 166 | "# We’ll construct a proof for the 11th item in the list\n", 167 | "\n", 168 | "item_num = 10\n", 169 | "c = leafs[item_num]\n", 170 | "c = s2(c + leafs[11])\n", 171 | "c = s2(level3[4] + c)\n", 172 | "c = s2(c + level2[3])\n", 173 | "c = s2(level1[0] + c)\n", 174 | "print(c == level0[0])\n", 175 | "proof = (10, leafs[11], level3[4], level2[3], level1[0])" 176 | ] 177 | }, 178 | { 179 | "cell_type": "markdown", 180 | "metadata": {}, 181 | "source": [ 182 | "#### Exercise 5\n", 183 | "\n", 184 | "1- Validate the merkle root for this block\n", 185 | "on Testnet:\n", 186 | "0000000000000451fa80fcdb243b84c35eaae215a85a8faa880559e8239e6f20\n", 187 | "\n", 188 | "2- Construct a merkle proof for this\n", 189 | "transaction (same block):\n", 190 | "e8270fb475763bc8d855cfe45ed98060988c1bdcad2ffc8364f783c98999a208" 191 | ] 192 | }, 193 | { 194 | "cell_type": "code", 195 | "execution_count": null, 196 | "metadata": { 197 | "collapsed": true 198 | }, 199 | "outputs": [], 200 | "source": [] 201 | }, 202 | { 203 | "cell_type": "code", 204 | "execution_count": null, 205 | "metadata": { 206 | "collapsed": true 207 | }, 208 | "outputs": [], 209 | "source": [] 210 | }, 211 | { 212 | "cell_type": "markdown", 213 | "metadata": {}, 214 | "source": [ 215 | "#### Exercise 6\n", 216 | "\n", 217 | "1- Write a program to get the merkle root given a\n", 218 | "list of hashes.\n", 219 | "\n", 220 | "2- Write a program that returns you the merkle\n", 221 | "proof (index, list of hashes) given a transaction\n", 222 | "hash from a list.\n", 223 | "\n", 224 | "3- Write a test for this program using random\n", 225 | "hashes (generated new every time!)." 226 | ] 227 | }, 228 | { 229 | "cell_type": "code", 230 | "execution_count": null, 231 | "metadata": { 232 | "collapsed": true 233 | }, 234 | "outputs": [], 235 | "source": [] 236 | }, 237 | { 238 | "cell_type": "code", 239 | "execution_count": null, 240 | "metadata": { 241 | "collapsed": true 242 | }, 243 | "outputs": [], 244 | "source": [] 245 | } 246 | ], 247 | "metadata": { 248 | "kernelspec": { 249 | "display_name": "Python 2", 250 | "language": "python", 251 | "name": "python2" 252 | }, 253 | "language_info": { 254 | "codemirror_mode": { 255 | "name": "ipython", 256 | "version": 2 257 | }, 258 | "file_extension": ".py", 259 | "mimetype": "text/x-python", 260 | "name": "python", 261 | "nbconvert_exporter": "python", 262 | "pygments_lexer": "ipython2", 263 | "version": "2.7.6" 264 | } 265 | }, 266 | "nbformat": 4, 267 | "nbformat_minor": 1 268 | } 269 | -------------------------------------------------------------------------------- /Session_7.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "### Session 7\n", 8 | "\n", 9 | "#### Version\n", 10 | "f9beb4d976657273696f6e0000000000650000005f1a69d2721101000100000000000000bc8f5e540\n", 11 | "0000000010000000000000000000000000000000000ffffc61b6409208d0100000000000000000000\n", 12 | "00000000000000ffffcb0071c0208d128035cbc97953f80f2f5361746f7368693a302e392e332fcf0\n", 13 | "5050001\n", 14 | "\n", 15 | "This is the network magic. This is always the same and is an\n", 16 | "easy way to determine the next message if the connection is\n", 17 | "interrupted. Testnet has a different Network Magic. Altcoins\n", 18 | "have a different Network Magic." 19 | ] 20 | }, 21 | { 22 | "cell_type": "markdown", 23 | "metadata": {}, 24 | "source": [ 25 | "f9beb4d976657273696f6e0000000000650000005f1a69d2721101000100000000000000bc8f5e540\n", 26 | "0000000010000000000000000000000000000000000ffffc61b6409208d0100000000000000000000\n", 27 | "00000000000000ffffcb0071c0208d128035cbc97953f80f2f5361746f7368693a302e392e332fcf05050001\n", 28 | "\n", 29 | "This is the payload checksum. This field is always 4 bytes. The\n", 30 | "rest of the message is the actual version message\n" 31 | ] 32 | }, 33 | { 34 | "cell_type": "code", 35 | "execution_count": null, 36 | "metadata": { 37 | "collapsed": false 38 | }, 39 | "outputs": [], 40 | "source": [ 41 | "# This is the command. The ascii here is literally “version” with 5\n", 42 | "# bytes that pad since this field is always 12 bytes.\n", 43 | "\n", 44 | "from binascii import hexlify, unhexlify\n", 45 | "print(unhexlify(\"76657273696f6e0000000000\"))" 46 | ] 47 | }, 48 | { 49 | "cell_type": "markdown", 50 | "metadata": {}, 51 | "source": [ 52 | "f9beb4d976657273696f6e0000000000650000005f1a69d2721101000100000000000000bc8f5e540\n", 53 | "0000000010000000000000000000000000000000000ffffc61b6409208d0100000000000000000000\n", 54 | "00000000000000ffffcb0071c0208d128035cbc97953f80f2f5361746f7368693a302e392e332fcf0\n", 55 | "5050001\n", 56 | "\n", 57 | "This is the payload length. This field is always 4 bytes. Again\n", 58 | "little-endian so the number of bytes in the payload is 0x65 = 101" 59 | ] 60 | }, 61 | { 62 | "cell_type": "markdown", 63 | "metadata": {}, 64 | "source": [ 65 | "f9beb4d976657273696f6e0000000000650000005f1a69d2721101000100000000000000bc8f5e540\n", 66 | "0000000010000000000000000000000000000000000ffffc61b6409208d0100000000000000000000\n", 67 | "00000000000000ffffcb0071c0208d128035cbc97953f80f2f5361746f7368693a302e392e332fcf0\n", 68 | "5050001\n", 69 | "\n", 70 | "This is the payload checksum. This field is always 4 bytes. The\n", 71 | "rest of the message is the actual version message" 72 | ] 73 | }, 74 | { 75 | "cell_type": "code", 76 | "execution_count": null, 77 | "metadata": { 78 | "collapsed": false 79 | }, 80 | "outputs": [], 81 | "source": [ 82 | "# here we double-hash the version message\n", 83 | "from hashlib import sha256\n", 84 | "from binascii import unhexlify\n", 85 | "\n", 86 | "msg ='721101000100000000000000bc8f5e5400000000010000000000000000000000000000000000ffffc61b6409208d010000000000000000000000000000000000ffffcb0071c0208d128035cbc97953f80f2f5361746f7368693a302e392e332fcf05050001'\n", 87 | "print(sha256(sha256(unhexlify(msg)).digest()).hexdigest())" 88 | ] 89 | }, 90 | { 91 | "cell_type": "markdown", 92 | "metadata": {}, 93 | "source": [ 94 | "#### Exercise 1\n", 95 | "\n", 96 | "f9beb4d976657273696f6e0000000000650000005f1a69d2721101000100000000000000bc8f5e540\n", 97 | "0000000010000000000000000000000000000000000ffffc61b6409208d0100000000000000000000\n", 98 | "00000000000000ffffcb0071c0208d128035cbc97953f80f2f5361746f7368693a302e392e332fcf0\n", 99 | "5050001\n", 100 | "\n", 101 | "What is the actual time of this message?" 102 | ] 103 | }, 104 | { 105 | "cell_type": "code", 106 | "execution_count": null, 107 | "metadata": { 108 | "collapsed": true 109 | }, 110 | "outputs": [], 111 | "source": [] 112 | }, 113 | { 114 | "cell_type": "code", 115 | "execution_count": null, 116 | "metadata": { 117 | "collapsed": true 118 | }, 119 | "outputs": [], 120 | "source": [] 121 | }, 122 | { 123 | "cell_type": "markdown", 124 | "metadata": {}, 125 | "source": [ 126 | "#### Exercise 2\n", 127 | "\n", 128 | "Parse this message:\n", 129 | "\n", 130 | "f9beb4d976657261636b00000000000\n", 131 | "0000000005df6e0e2" 132 | ] 133 | }, 134 | { 135 | "cell_type": "code", 136 | "execution_count": null, 137 | "metadata": { 138 | "collapsed": true 139 | }, 140 | "outputs": [], 141 | "source": [] 142 | }, 143 | { 144 | "cell_type": "code", 145 | "execution_count": null, 146 | "metadata": { 147 | "collapsed": true 148 | }, 149 | "outputs": [], 150 | "source": [] 151 | }, 152 | { 153 | "cell_type": "markdown", 154 | "metadata": {}, 155 | "source": [ 156 | "#### Exercise 3\n", 157 | "Parse this message and check the checksum:\n", 158 | "\n", 159 | "F9BEB4D974780000000000000000000002010000E293CDBE01000000016DBDDB085B1D8AF75184F0B\n", 160 | "C01FAD58D1266E9B63B50881990E4B40D6AEE3629000000008B483045022100F3581E1972AE8AC7C7\n", 161 | "367A7A253BC1135223ADB9A468BB3A59233F45BC578380022059AF01CA17D00E41837A1D58E97AA31\n", 162 | "BAE584EDEC28D35BD96923690913BAE9A0141049C02BFC97EF236CE6D8FE5D94013C721E915982ACD\n", 163 | "2B12B65D9B7D59E20A842005F8FC4E02532E873D37B96F09D6D4511ADA8F14042F46614A4C70C0F14\n", 164 | "BEFF5FFFFFFFF02404B4C00000000001976A9141AA0CD1CBEA6E7458A7ABAD512A9D9EA1AFB225E88\n", 165 | "AC80FAE9C7000000001976A9140EAB5BEA436A0484CFAB12485EFDA0B78B4ECC5288AC00000000" 166 | ] 167 | }, 168 | { 169 | "cell_type": "code", 170 | "execution_count": null, 171 | "metadata": { 172 | "collapsed": true 173 | }, 174 | "outputs": [], 175 | "source": [] 176 | }, 177 | { 178 | "cell_type": "code", 179 | "execution_count": null, 180 | "metadata": { 181 | "collapsed": true 182 | }, 183 | "outputs": [], 184 | "source": [] 185 | }, 186 | { 187 | "cell_type": "code", 188 | "execution_count": null, 189 | "metadata": { 190 | "collapsed": false 191 | }, 192 | "outputs": [], 193 | "source": [ 194 | "# Connecting to a Node Manually\n", 195 | "\n", 196 | "import socket\n", 197 | "from binascii import unhexlify, hexlify\n", 198 | "\n", 199 | "node_IP = # (string) Find nodes to connect to here: https://bitnodes.21.co/nodes/\n", 200 | "port = 8883\n", 201 | "s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n", 202 | "msg = unhexlify('f9beb4d976657273696f6e0000000000650000005f1a69d27211\\\n", 203 | "01000100000000000000bc8f5e5400000000010000000000000000000000000\\\n", 204 | "000000000ffffc61b6409208d010000000000000000000000000000000000ff\\\n", 205 | "ffcb0071c0208d128035cbc97953f80f2f5361746f7368693a302e392e332fc\\\n", 206 | "f05050001')\n", 207 | "s.connect((node_IP, port))\n", 208 | "s.sendall(msg)\n", 209 | "data = s.recv(200)\n", 210 | "print(hexlify(data))" 211 | ] 212 | }, 213 | { 214 | "cell_type": "markdown", 215 | "metadata": {}, 216 | "source": [ 217 | "#### Exercise 4\n", 218 | "\n", 219 | "Connect to a node and parse some messages\n" 220 | ] 221 | }, 222 | { 223 | "cell_type": "code", 224 | "execution_count": null, 225 | "metadata": { 226 | "collapsed": true 227 | }, 228 | "outputs": [], 229 | "source": [ 230 | "import socket\n", 231 | "from binascii import unhexlify, hexlify\n", 232 | "\n", 233 | "\n", 234 | "node_IP = # (string) Find nodes to connect to here: https://bitnodes.21.co/nodes/\n", 235 | "port = 8883\n", 236 | "s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n", 237 | "msg = unhexlify('f9beb4d976657273696f6e0000000000650000005f1a69d27211\\\n", 238 | "01000100000000000000bc8f5e5400000000010000000000000000000000000\\\n", 239 | "000000000ffffc61b6409208d010000000000000000000000000000000000ff\\\n", 240 | "ffcb0071c0208d128035cbc97953f80f2f5361746f7368693a302e392e332fc\\\n", 241 | "f05050001')\n", 242 | "s.connect((node_IP, port))\n", 243 | "s.sendall(msg)\n", 244 | "data = s.recv(200)\n", 245 | "print(hexlify(data))" 246 | ] 247 | } 248 | ], 249 | "metadata": { 250 | "kernelspec": { 251 | "display_name": "Python 2", 252 | "language": "python", 253 | "name": "python2" 254 | }, 255 | "language_info": { 256 | "codemirror_mode": { 257 | "name": "ipython", 258 | "version": 2 259 | }, 260 | "file_extension": ".py", 261 | "mimetype": "text/x-python", 262 | "name": "python", 263 | "nbconvert_exporter": "python", 264 | "pygments_lexer": "ipython2", 265 | "version": "2.7.6" 266 | } 267 | }, 268 | "nbformat": 4, 269 | "nbformat_minor": 1 270 | } 271 | -------------------------------------------------------------------------------- /donate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sahabi/programming-blockchain/ccf011431fa5cf9966811abd96ff7ecc3dc40ccd/donate.png --------------------------------------------------------------------------------