{ "cells": [ { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "# Generate bitcoin addresses for Irving & Holden's 2016 clinical trial word document\n", "\n", "### By [Daniel Himmelstein](http://dhimmel.com/) ([@dhimmel](https://twitter.com/dhimmel))\n", "\n", "This notebook computes the bitcoin addresses for the [word document](https://f1000researchdata.s3.amazonaws.com/datasets/8114/9c9f9a18-a852-40c6-953e-c75107abc714_Appendix_1_-_unformatted_text_file_.docx) from the following study:\n", "\n", "> **How blockchain-timestamped protocols could improve the trustworthiness of medical science** [[version 2; referees: 3 approved]](https://doi.org/b2pt)
\n", "Greg Irving, John Holden
\n", "_F1000Research_ (2016) DOI: [10.12688/f1000research.8114.2](https://doi.org/10.12688/f1000research.8114.2)\n", "\n", "It uses the method described by Benjamin Gregory Carlisle in a 2014 blog post titled [Proof of prespecified endpoints in medical research with the bitcoin blockchain](http://www.bgcarlisle.com/blog/2014/08/25/proof-of-prespecified-endpoints-in-medical-research-with-the-bitcoin-blockchain/).\n", "\n", "**Warning: the Carlisle method is not the recommended approach for _proof of existence_ using Bitcoin. This notebook is not an endorsement of the method, but rather a demostration that the address generation in the Irving & Holden study is flawed.**" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "## Dependencies\n", "\n", "This is a Python 3 notebook. It requires [Python Bitcoin Tools](https://github.com/vbuterin/pybitcointools), which can be installed with `pip install bitcoin`. This notebook was generated using `bitcoin==1.1.42` from [PyPI](https://pypi.python.org/pypi/bitcoin/1.1.42)." ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [], "source": [ "from urllib.request import urlopen\n", "import hashlib\n", "\n", "import bitcoin" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "## Generate the private key\n", "\n", "Get the sha256 hash for [Dataset 1. Unformatted text file.\n", "](https://doi.org/10.5256/f1000research.8114.d114596 \"Irving & Holden. F1000 Research. Dataset 1. Unformatted text file.\")" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/plain": [ "'8da3088936035521f9e9b57963679d89e306a06c6aebd1167b4d198e79562326'" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "url = 'https://f1000researchdata.s3.amazonaws.com/datasets/8114/9c9f9a18-a852-40c6-953e-c75107abc714_Appendix_1_-_unformatted_text_file_.docx'\n", "response = urlopen(url)\n", "data = response.read()\n", "checksum = hashlib.sha256(data)\n", "private_key = checksum.hexdigest()\n", "private_key" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/plain": [ "'hex'" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Get the private key's format\n", "bitcoin.get_privkey_format(private_key)" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "## Generate the corresponding public keys\n", "\n", "There are two common types of bitcoin public keys (compressed and uncompressed) that result in different bitcoin addresses. Neither Carlisle or Irving & Holden report which type of public they use, so we'll try both." ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/plain": [ "'04a1582612a51aa8cea8e8ced2078d01141ff941e6c5d985bbae2536ce33ef5396bc7946f188aeb99d6b575b935c218ae19780ef77a535107a5272e7390e1001e4'" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Uncompressed public key\n", "public_key = bitcoin.privkey_to_pubkey(private_key)\n", "public_key" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/plain": [ "'02a1582612a51aa8cea8e8ced2078d01141ff941e6c5d985bbae2536ce33ef5396'" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Compressed public key\n", "public_key_compressed = bitcoin.compress(public_key)\n", "public_key_compressed" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "## Generate the corresponding addresses\n", "\n", "Note that neither address matches the address reported by Irving & Holden, which was [`1AHjCz2oEUTH8js4S8vViC8NKph4zCACXH`](https://blockchain.info/address/1AHjCz2oEUTH8js4S8vViC8NKph4zCACXH)." ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/plain": [ "'1P6cxmuSsjDqUGCsyaEzgcj7iTEPsMAjhU'" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Uncompressed address\n", "address = bitcoin.pubkey_to_address(public_key)\n", "address" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/plain": [ "'17pJjJGJJTzVsJx9JSfbx6vp1sGkPNoDoA'" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Compressed address\n", "address_compressed = bitcoin.pubkey_to_address(public_key_compressed)\n", "address_compressed" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Irving & Holden have a big problem.\n" ] } ], "source": [ "# Check whether the Irving & Holden address is wrong\n", "address_irving = '1AHjCz2oEUTH8js4S8vViC8NKph4zCACXH'\n", "if not address_irving in {address, address_compressed}:\n", " print('Irving & Holden have a big problem.')" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "## Check whether either of the correct addresses has ever been used\n", "\n", "As of March 6, 2017, neither address has been used." ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "https://blockchain.info/address/1P6cxmuSsjDqUGCsyaEzgcj7iTEPsMAjhU\n", "https://blockchain.info/address/17pJjJGJJTzVsJx9JSfbx6vp1sGkPNoDoA\n" ] } ], "source": [ "# URLs for blockchain.info address details\n", "for address in address, address_compressed:\n", " url = 'https://blockchain.info/address/{}'.format(address)\n", " print(url)" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "## Alternative implementation\n", "\n", "For an altertative implementation, you can generate the sha256 checksum via the unix shell:\n", "\n", "```sh\n", "URL=https://f1000researchdata.s3.amazonaws.com/datasets/8114/9c9f9a18-a852-40c6-953e-c75107abc714_Appendix_1_-_unformatted_text_file_.docx\n", "curl --silent $URL | shasum --algorithm 256\n", "```\n", "\n", "Then you can use [bitaddress.org](https://www.bitaddress.org) to generate the bitcoin addresses. Just go to the \"Wallet Details\" page and paste the sha256 hash into the \"Enter Private Key\" field. This approach generates the same addresses as this notebook." ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "## Plain text hashes\n", "\n", "Since [Xorbin](http://www.xorbin.com/tools/sha256-hash-calculator) appears to only support hashing of pasted text rather than an uploaded file, it's likely Irving & Holden pasted the word document contents into Xorbin. It's difficult to recreate exactly how the formatted word document was converted to plain text. Below we convert addresses for one possible plain text representation." ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "collapsed": true, "deletable": true, "editable": true }, "outputs": [], "source": [ "# See carlisle.py for the source of the carlisle_method function\n", "# that implements the address generation logic above.\n", "from carlisle import carlisle_method" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "collapsed": true, "deletable": true, "editable": true }, "outputs": [], "source": [ "# This data was produced by selecting all from the work document, copying,\n", "# and pasting on macOS 10.12.3 using Microsoft Word for Mac 2011 Version 14.0.0\n", "# It's entirely possible the version below has already been corrupted due to automated\n", "# newline encoding conversions.\n", "data = b'''\\\n", "Study Type:\tInterventional \n", "Study Design:\tAllocation: Randomized\n", "Endpoint Classification: Safety/Efficacy Study\n", "Intervention Model: Parallel Assignment\n", "Masking: Open Label\n", "Primary Purpose: Prevention\n", "Official Title:\tCardiovascular and Metabolic Effects of Moderate Alcohol Consumption in Type 2 Diabetes\n", "\n", "Further study details as provided by Ben-Gurion University of the Negev:\n", "\n", "Primary Outcome Measures: \n", "Glycemic control [ Time Frame: 6 months ] [ Designated as safety issue: Yes ]\n", "\n", "Secondary Outcome Measures: \n", "CVD status [ Time Frame: 6 months ] [ Designated as safety issue: Yes ]\n", "\n", "'''" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/plain": [ "{'address': '1Evz8cSTcq4JtYfHHNk6tjXj9rUW88orUt',\n", " 'compressed': False,\n", " 'private_key': 'e32dbf3fb5525d006af1881809269cca7f749b0e6b82e505ecf690ab9c33ad60',\n", " 'public_key': '04616f8ead7203b881f36e4e3ac7dd98ee982611b468ddeee81f94ca8c0b3564100dcca6fc76920b938806b8a560361a1957f1c2a72b62758cc97c1c70228ed220',\n", " 'url ': 'https://blockchain.info/address/1Evz8cSTcq4JtYfHHNk6tjXj9rUW88orUt'}" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "carlisle_method(data, compress=False)" ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/plain": [ "{'address': '1JqGTvoGYPRHf3r8vC2nws5BApnFu7wa8V',\n", " 'compressed': True,\n", " 'private_key': 'e32dbf3fb5525d006af1881809269cca7f749b0e6b82e505ecf690ab9c33ad60',\n", " 'public_key': '02616f8ead7203b881f36e4e3ac7dd98ee982611b468ddeee81f94ca8c0b356410',\n", " 'url ': 'https://blockchain.info/address/1JqGTvoGYPRHf3r8vC2nws5BApnFu7wa8V'}" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "carlisle_method(data, compress=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Update for protocol for manuscript version 3\n", "\n", "On March 30, 2017, Irving & Holden posted [version 3](https://doi.org/10.12688/f1000research.8114.3) of their study to _F1000Research_. This version contains a new \"[Dataset 1.Unformatted text file](https://doi.org/10.5256/f1000research.8114.d156051)\", which is a text document rather than word document. Below we find the hash and addresses for this text." ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "b'The CArdiovasCulAr Diabetes & Ethanol (CASCADE) Trial (CASCADE)\\r\\n\\r\\n\\r\\nStudy Type:\\tInterventional \\r\\nStudy Design:\\tAllocation: Randomized\\r\\nEndpoint Classification: Safety/Efficacy Study\\r\\nIntervention Model: Parallel Assignment\\r\\nMasking: Open Label\\r\\nPrimary Purpose: Prevention\\r\\nOfficial Title:\\tCardiovascular and Metabolic Effects of Moderate Alcohol Consumption in Type 2 Diabetes\\r\\n\\r\\nFurther study details as provided by Ben-Gurion University of the Negev:\\r\\n\\r\\nPrimary Outcome Measures: \\r\\nGlycemic control [ Time Frame: 6 months ] [ Designated as safety issue: Yes ]\\r\\n\\r\\nSecondary Outcome Measures: \\r\\nCVD status [ Time Frame: 6 months ] [ Designated as safety issue: Yes ]\\r\\n\\r\\n\\r\\nEstimated Enrollment:\\t200\\r\\nStudy Start Date:\\tMay 2010\\r\\nEstimated Study Completion Date:\\tMay 2012\\r\\nEstimated Primary Completion Date:\\tMay 2012 (Final data collection date for primary outcome measure)\\r\\n'" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "url = 'https://f1000researchdata.s3.amazonaws.com/datasets/8114/da88d341-eeed-4630-b120-78e9ff8a9d38_CASCADE.txt'\n", "response = urlopen(url)\n", "data = response.read()\n", "data" ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "{'address': '1HZ5Cw2iXcXZpBKwWncmCQYyz4Zn5Mj4qk',\n", " 'compressed': False,\n", " 'private_key': '9072d05a5e95d783a6d28745c19ce8c47eac93cb1bedbde1cf43a192287288f3',\n", " 'public_key': '0441dd7bb4328026f417e41d9582214fd0ddba3e6e8649e3ad59a8db055a44746ee6357b0dacc503f75bd2a7cb25f4886e9975e468e98aceecfb3f15493b4aa2d6',\n", " 'url ': 'https://blockchain.info/address/1HZ5Cw2iXcXZpBKwWncmCQYyz4Zn5Mj4qk'}" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "carlisle_method(data, compress=False)" ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "{'address': '1HvdUMh6BFrBdxBehMkgTVJydHHaBL1Na6',\n", " 'compressed': True,\n", " 'private_key': '9072d05a5e95d783a6d28745c19ce8c47eac93cb1bedbde1cf43a192287288f3',\n", " 'public_key': '0241dd7bb4328026f417e41d9582214fd0ddba3e6e8649e3ad59a8db055a44746e',\n", " 'url ': 'https://blockchain.info/address/1HvdUMh6BFrBdxBehMkgTVJydHHaBL1Na6'}" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "carlisle_method(data, compress=True)" ] } ], "metadata": { "kernelspec": { "display_name": "Python [conda env:timestamps]", "language": "python", "name": "conda-env-timestamps-py" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.6.0" } }, "nbformat": 4, "nbformat_minor": 2 }