From https://en.wikipedia.org/wiki/Hash_function:
A hash function is any function that can be used to map data of arbitrary size to data of fixed size. The values returned by a hash function are called hash values, hash codes, hash sums, or simply hashes.
First, importing Python's hashing function library.
import hashlib
The first MD5
hash codes (cf. https://en.wikipedia.org/wiki/MD5).
md5_1 = hashlib.md5('yves').hexdigest()
md5_1
'afe3bd960b4c46a68580c4e564cca24e'
md5_2 = hashlib.md5('yves2').hexdigest()
md5_2
'664d839e06bada38ce04f7208896efdf'
hashlib.md5('Dr. Yves Johannes Hilpisch').hexdigest()
'642394f6d25fd9fe4b88e359c8aaf051'
We define first a character set of lower case letters only.
import string
charset = string.ascii_lowercase
charset
'abcdefghijklmnopqrstuvwxyz'
Hash codes for all single characters in charset
.
from itertools import permutations
pm = permutations(charset, 1)
for comb in pm:
comb = ''.join(comb)
md5 = hashlib.md5(comb)
print comb, md5.hexdigest()
a 0cc175b9c0f1b6a831c399e269772661 b 92eb5ffee6ae2fec3ad71c777531578f c 4a8a08f09d37b73795649038408b5f33 d 8277e0910d750195b448797616e091ad e e1671797c52e15f763380b45e841ec32 f 8fa14cdd754f91cc6554c9e71929cce7 g b2f5ff47436671b6e533d8dc3614845d h 2510c39011c5be704182423e3a695e91 i 865c0c0b4ab0e063e5caa3387c1a8741 j 363b122c528f54df4a0446b6bab05515 k 8ce4b16b22b58894aa86c421e8759df3 l 2db95e8e1a9267b7a1188556b2013b33 m 6f8f57715090da2632453988d9a1501b n 7b8b965ad4bca0e41ab51de7b31363a1 o d95679752134a2d9eb61dbd7b91c4bcc p 83878c91171338902e0fe0fb97a8c47a q 7694f4a66316e53c8cdd9d9954bd611d r 4b43b0aee35624cd95b910189b3dc231 s 03c7c0ace395d80182db07ae2c30f034 t e358efa489f58062f10dd7316b65649e u 7b774effe4a349c6dd82ad4f4f21d34c v 9e3669d19b675bd57058fd4664205d2a w f1290186a5d0b1ceab27f4e77c0c5d68 x 9dd4e461268c8034f5c8564e155c67a6 y 415290769594460e2e485922904f345d z fbade9e36a3f36d3d676c1b808451dd7
Now doing brute force hash code cracking — 'knowing' that the relevant word has a maximum of 4 characters.
%%time
for i in range(1, 5):
print '%d CHARATERS USED NOW' % i
pm = permutations(charset, i)
for comb in pm:
comb = ''.join(comb)
md5 = hashlib.md5(comb).hexdigest()
if md5 == md5_1:
print 'SUCCESS'
print comb, md5
break
1 CHARATERS USED NOW 2 CHARATERS USED NOW 3 CHARATERS USED NOW 4 CHARATERS USED NOW SUCCESS yves afe3bd960b4c46a68580c4e564cca24e CPU times: user 375 ms, sys: 40 ms, total: 415 ms Wall time: 359 ms
Let us enlarge the character set to include digits as well.
charset2 = string.lowercase + string.digits
charset2
'abcdefghijklmnopqrstuvwxyz0123456789'
Time to crack the second hash code increases due to greater word length and bigger character set.
%%time
for i in range(1, 6):
print '%d CHARATERS USED NOW' % i
pm = permutations(charset2, i)
for comb in pm:
comb = ''.join(comb)
md5 = hashlib.md5(comb).hexdigest()
if md5 == md5_2:
print 'SUCCESS'
print comb, md5
break
1 CHARATERS USED NOW 2 CHARATERS USED NOW 3 CHARATERS USED NOW 4 CHARATERS USED NOW 5 CHARATERS USED NOW SUCCESS yves2 664d839e06bada38ce04f7208896efdf CPU times: user 30 s, sys: 75 ms, total: 30.1 s Wall time: 29.9 s
Bitcoin mining is based on SHA256
hash codes (cf. https://en.wikipedia.org/wiki/SHA-2)
md5 = hashlib.sha256('yves')
md5.hexdigest()
'9195c7b9bb56d375948ba058cddea1982b49864e12c700de58d69c5c72dbd075'
The idea behind mining is to find a hash code that is 'small enough', i.e. lies below a certain target level (mainly defined by 'leading zeros' in the target hex value).
target = '%064x' % (1000000000 << 200)
target
'0000003b9aca0000000000000000000000000000000000000000000000000000'
target = target.decode('hex')
target
'\x00\x00\x00;\x9a\xca\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
The original hash code for 'yves' is not small enough.
md5.digest() < target
False
However, adding (a) certain number(s) to the string, yields a hash code small enough.
hashlib.sha256('%dyves' % 23240167).hexdigest()
'00000003b04fad4b30a527760fea6ee5beec8035ef636316c2bf2577b2789611'
The following code simulates a mining procedure.
%%time
i = 0
while True:
md5 = hashlib.sha256('%d' % i + 'yves')
if md5.digest() < target:
print 'SUCCESS'
print i, md5.hexdigest()
# break
if i % 2500000 == 0:
print i
i += 1
if i > 55000000:
break
0 2500000 5000000 7500000 10000000 12500000 15000000 17500000 20000000 22500000 SUCCESS 23240167 00000003b04fad4b30a527760fea6ee5beec8035ef636316c2bf2577b2789611 25000000 SUCCESS 27090678 00000007a53f0b5163e1cb7ade64881e4eb3e06f9c102ad72a19c942223ba82b 27500000 30000000 32500000 35000000 37500000 40000000 42500000 45000000 47500000 50000000 SUCCESS 50427211 000000099f6760417f3b2161a9ba9e989c62da1745d949267d5b648edaa21496 52500000 55000000 CPU times: user 1min 10s, sys: 153 ms, total: 1min 10s Wall time: 1min 10s
The time to find a suitable hash code depends on the input string.
%%time
i = 0
while True:
md5 = hashlib.sha256('%d' % i + 'yveshilpisch')
if md5.digest() < target:
print 'SUCCESS'
print i, md5.hexdigest()
# break
if i % 2500000 == 0:
print i
i += 1
if i > 55000000:
break
0 2500000 5000000 7500000 10000000 12500000 15000000 17500000 20000000 22500000 25000000 27500000 30000000 32500000 35000000 37500000 40000000 42500000 45000000 47500000 50000000 52500000 55000000 CPU times: user 1min 10s, sys: 157 ms, total: 1min 10s Wall time: 1min 10s
The following example is from http://www.righto.com/2014/02/bitcoin-mining-hard-way-algorithms.html and is about a 'real' bitcoin block and how to mine it wih Python.
import struct
The basic elements of a bitcoin block.
The elements translated into Python code.
ver = 2
prev_block = "000000000000000117c80378b8da0e33559b5997f2ad55e2f7d18ec1975b9717"
mrkl_root = "871714dcbae6c8193a2bb9b2a69fe1c0440399f38d94b3a0f1b447275a29978a"
time_ = 0x53058b35 # 2014-02-20 04:57:25
bits = 0x19015f53 # difficulty
bits
419520339
The derivation of the target value which is the upper limit for a successful hash code.
# https://en.bitcoin.it/wiki/Difficulty
exp = bits >> 24
exp
25
mant = bits & 0xffffff
mant
89939
hex(mant)
'0x15f53'
8 * (exp - 3)
176
The concrete values.
target_hexstr = '%064x' % (mant * (1 << (8 * (exp - 3))))
target_hexstr
'00000000000000015f5300000000000000000000000000000000000000000000'
target_str = target_hexstr.decode('hex')
target_str # C struct
'\x00\x00\x00\x00\x00\x00\x00\x01_S\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
The Python module struct
can be used to convert Python values to C structs represented as Python strings and vice versa.
pa = struct.pack('LLL', 1, 20, 300) # packing data
pa
'\x01\x00\x00\x00\x00\x00\x00\x00\x14\x00\x00\x00\x00\x00\x00\x00,\x01\x00\x00\x00\x00\x00\x00'
struct.unpack('LLL', pa) # unpacking data
(1, 20, 300)
The nonce
is the value which is to be added to the other block elements during the hash code generation. One looks for the nonce
that gives a hash code smaller than the target level.
nonce = 850000000
Finally, the Python code to do the mining activitiy. Basically, the nonce
values gets increased by 1 during the look, a new hash code is generated and compared to the target level.
%%time
while nonce < 0x100000000:
header = (struct.pack("<L", ver)
+ prev_block.decode('hex')[::-1]
+ mrkl_root.decode('hex')[::-1]
+ struct.pack("<LLL", time_, bits, nonce))
hash = hashlib.sha256(hashlib.sha256(header).digest()).digest()
if nonce % 100000 == 0:
print nonce, hash[::-1].encode('hex')
if hash[::-1] < target_str:
print nonce, hash[::-1].encode('hex')
print 'success'
break
nonce += 1
850000000 2d06d5717ef51ce987ec0f0e4823620f8d9d2d6556174103297a6099900a04c0 850100000 d426ab32784c7bf5b24b93e9e83d4f685abf21d1b8117c69dfcc644ed8b59f4d 850200000 879860b11769268f1e5ca7df9a763a7daf63911d2e25eb599db5bd295eba15ee 850300000 639bb2d2d53ad9923c1aea1da51d20d716754086a47605bf51a474e0f8751d2e 850400000 b00da7ec454b36fd7f7f96fd973361e56c8f19d252b95b4ada21d49dc6751001 850500000 124ceef6fa93474bfbaa91dc1428d2d5801a6b3e8e19c4edbb87c17995757030 850600000 ed546943a811deed9a2e37a74fda8a66b60d93f80db8f98d02fac8209c116862 850700000 53a8be9b39b0320a8d52eb02a53ca868fbdf550e90eacfafcc06b421afde2abd 850800000 275944cb52b35cc3993bd286e3861afbc246c7de7ed274da917cc22d05cd2bf5 850900000 3f39d1b4f2296ff6511f163484d121b12b2e4393026dddae7fd21940193c4959 851000000 2caff003e29dfc2ec7130a20d84118580a48d81627e0a766a6450a14404aa030 851100000 38532290165437742d889e1aca06d8547cf5e212ab6a201ce0aa18a7178bde93 851200000 5328e4e15f9143668ee761fcd6703b4bbb491962d18d0198acb036eaddec27d4 851300000 84b6093aabe15d54875d6507ff4101e9fab1f19281cf02d66b0535dc8ef3c540 851400000 961beb37d43cb3e9ec00b12ad6999e7599f2671dc9bd0529cbb4825e045ef6ad 851500000 b6d5c3b36ba77f5216eb8ce0cd0d7ee35ca24794d519d689637cb331a83cd531 851600000 58c3abc58a3fcccda18f205cc124bcfce61d244b46bb70161da040e346429b61 851700000 a96d86bf20b939b6013fd8e30fe6dba47a449d66bebf4010ae04d56a3706ba76 851800000 4e0bc5299ef60ee2e542b3db8c17a1fc37b423d7d04a90b8afdca7d637a58879 851900000 00676bec9bef56ada1a43471bf99d314d32c5722997e91026b517602eafc0768 852000000 47c01a53e024c253601f54332790483091888c463d8b8647c8d6f7e078eafb9b 852100000 c6a6127d8c781f9094c285487f3524395d14add01d1a78705d2e6c95525a588b 852200000 53c762141e8c9d615dc50b9f3dbc7923d770e8909b1e9a2d3a07e4bb5bc4cbe1 852300000 1367247fa37ba19a1f4f7611a660dd7d20ee3e0966fed015aba43c260c1a6ed6 852400000 1bd5babc0d87efd848b56e09cf7cc46c95923864cc2924aa2a1c5fc71835ec21 852500000 e49a890d18918861d8b3a70ee4db417884ff44940e0a05aa282bc5af5d2cf8df 852600000 1906382ef5f88e718a0a3f511300278828b9e066f0f17538bb0a004789ce03f1 852700000 e2019b137817605eabe86e477fb701a939704d0ea6a0edbde551add2398d9712 852800000 b9cd34c3e42796b3acfdbade72f80f58d6d25210dd69bd7e2e07a1b1f11dcb44 852900000 7b9ee4365e34663f53f6f2839782c6742874d1df9a26d9d5849b4f7ab44e1d22 853000000 4691fb160b2d339e2a54e95f81b891d46acd7f68754b0bd1f4b6942ca0c804ca 853100000 0f8f14bbce8a3130c77c9c1e16350b6e355dd1ed02e609e2c27317733c0b3961 853200000 61988103dd17e23ded0344340f3b0f264cb8d96132730cf48ebc34b06377a75b 853300000 5fe85a9f29709cb866065cf82c45c0d16b8c9f59cf548dad131a8b07805597b9 853400000 ee63a5132d8126c255f73d48e02eec5c7b3d3fb91c447a74aa13b9c982dbbbf6 853500000 d042c47176ab86bca4b9b2f85c2bd88ba755006e7edccfed7f0c701dc4d33fc9 853600000 6cac0791a530a9e3b8b53d72cbaa2fb46c14c5e65d843e08ab656444bea9a9ea 853700000 d79092388a07d7e9267e286bc947c01c54dffca661f8f80bf6800be46d742369 853800000 75ebeafea5b28c3121000dcf48e023aa829a2a2644afbe530d2b631ed8906bdf 853900000 dfbd31c5596f8face76616084d962d0ff2736a36b8171166d11de5fe2624fa33 854000000 b261dbf2a4d3178730c06c7d37b3d3f104b9b0c8266cc0bf8ddcffb88ee3e620 854100000 b8fa2bdc41f553695f1dbd368b924569b4fa4cb59b7bbb16a8d8e78efa6bb43e 854200000 4e7174dc8891c4cf1e6e97dc62166961a289f88206bdd383ba0c31a027610e4f 854300000 e80a0ac318574b7bebba1ec3aaec37ed173b4e143997eb66cf5118daf68e020b 854400000 0da8de618a00dd0aa71af0ff3350cd78435f10b160a06dee0578caf5bcab38b9 854500000 f0759c38ce0c7772ac8c4722937bed08140f8ce159725643dc2e96c335cc7c23 854600000 20e6560f3b64596d9632005d9464d83a3125eb2faef9e34349fd7409869fef51 854700000 c3c28a756b90252a0798a4fb318dece2f66671c142c79094ee04143284c00cfe 854800000 e1f78c86fb5afb69ade79f1ba6a0b2f059fd04c1826b74dc7dd99f1ce1148c39 854900000 7a4267e76008a80ffe34241f9fdcd829017fc41ec26af8446f7a2d1c736563a5 855000000 c56c40696263177bce80ee786c31f5d488d5bab570efb4abee25acb004088645 855100000 f365ea084e95a6a45ea48e957c188d3639db4aa7d8e91f246a5e69004033b79f 855200000 96519548a733cc53746e0b07b62f7c0ebb1389a6c4cb8d30309b1f24d78eff26 855300000 08a9120bb5b207c95ee9d9437c53224024fd7da2c38ef03988ba952eccb85910 855400000 18379a22c13f193c9cdb0d5e6eccc2745bc0c95402162ca9721c0dc286c8d61d 855500000 3c2d6d680516d5d430dbf787e9158799676277a6e419595dbbf4fe42f43120a9 855600000 0233a14315cf2b61fce61b534d530c6087e805731bf52fd8f273a24c0806024c 855700000 27a1c3fe9e19f964bcc172598705a1a9bf4e705cb6846765ea1cef856d009cd9 855800000 b0603f071da6f70c98dd66d59be05bc9da7e5a144a7cd4088eac3fccf85f2579 855900000 55046172647ff3a4a8b3928816f4f05bf24a08e1ddfde212ba4d83ece5749bb7 856000000 634192b589ea881333b5e566873ecbaaf8addc5d7ef4240f8e8c1325c29c4c7a 856100000 c2fbb25c7dcca8a41e5b305e9ba0c0c9fcb80b16877029349b65358a7d7b7ce0 856192328 0000000000000000e067a478024addfecdc93628978aa52d91fabd4292982a50 success CPU times: user 25.1 s, sys: 78 ms, total: 25.2 s Wall time: 25 s
The following are the hard-coded transaction hashes for the Bitcoin block under consideration (http://www.righto.com/2014/02/bitcoin-mining-hard-way-algorithms.html).
# https://blockexplorer.com/rawblock/0000000000000000e067a478024addfecdc93628978aa52d91fabd4292982a50
txHashes = [
"00baf6626abc2df808da36a518c69f09b0d2ed0a79421ccfde4f559d2e42128b",
"91c5e9f288437262f218c60f986e8bc10fb35ab3b9f6de477ff0eb554da89dea",
"46685c94b82b84fa05b6a0f36de6ff46475520113d5cb8c6fb060e043a0dbc5c",
"ba7ed2544c78ad793ef5bb0ebe0b1c62e8eb9404691165ffcb08662d1733d7a8",
"b8dc1b7b7ed847c3595e7b02dbd7372aa221756b718c5f2943c75654faf48589",
"25074ef168a061fcc8663b4554a31b617683abc33b72d2e2834f9329c93f8214",
"0fb8e311bffffadc6dc4928d7da9e142951d3ba726c8bde2cf1489b62fb9ebc5",
"c67c79204e681c8bb453195db8ca7d61d4692f0098514ca198ccfd1b59dbcee3",
"bd27570a6cbd8ad026bfdb8909fdae9321788f0643dea195f39cd84a60a1901b",
"41a06e53ffc5108358ddcec05b029763d714ae9f33c5403735e8dee78027fe74",
"cc2696b44cb07612c316f24c07092956f7d8b6e0d48f758572e0d611d1da6fb9",
"8fc508772c60ace7bfeb3f5f3a507659285ea6f351ac0474a0a9710c7673d4fd",
"62fed508c095446d971580099f976428fc069f32e966a40a991953b798b28684",
"928eadbc39196b95147416eedf6f635dcff818916da65419904df8fde977d5db",
"b137e685df7c1dffe031fb966a0923bb5d0e56f381e730bc01c6d5244cfe47c1",
"b92207cee1f9e0bfbd797b05a738fab9de9c799b74f54f6b922f20bd5ec23dd6",
"29d6f37ada0481375b6903c6480a81f8deaf2dcdba03411ed9e8d3e5684d02dd",
"48158deb116e4fd0429fbbbae61e8e68cb6d0e0c4465ff9a6a990037f88c489c",
"be64ea86960864cc0a0236bbb11f232faf5b19ae6e2c85518628f5fae37ec1ca",
"081363552e9fff7461f1fc6663e1abd0fb2dd1c54931e177479a18c4c26260e8",
"eb87c25dd2b2537b1ff3dbabc420e422e2a801f1bededa6fa49ef7980feaef70",
"339e16fcc11deb61ccb548239270af43f5ad34c321416bada4b8d66467b1c697",
"4ad6417a3a04179482ed2e4b7251c396e38841c6fba8d2ce9543337ab7c93c02",
"c28a45cded020bf424b400ffc9cb6f2f85601934f18c34a4f78283247192056a",
"882037cc9e3ee6ddc2d3eba86b7ca163533b5d3cbb16eaa38696bb0a2ea1137e",
"179bb936305b46bb0a9df330f8701984c725a60e063ad5892fa97461570b5c04",
"9517c585d1578cb327b7988f38e1a15c663955ea288a2292b40d27f232fbb980",
"2c7e07d0cf42e5520bcbfe2f5ef63761a9ab9d7ccb00ea346195eae030f3b86f",
"534f631fc42ae2d309670e01c7a0890e4bfb65bae798522ca14df09c81b09734",
"104643385619adb848593eb668a8066d1f32650edf35e74b0fc3306cb6719448",
"87ac990808239c768182a752f4f71cd98558397072883c7e137efb49d22b9231",
"9b3e2f1c47d59a444e9b6dc725f0ac6baf160d22f3a9d399434e5e65b14eccb0",
"fbe123066ae5add633a542f151663db4eb5a7053e388faadb40240671ae1b09b",
"1dd07e92e20b3cb9208af040031f7cfc4efd46cc31ec27be20a1047965a42849",
"2709bb9ed27353c1fd76b9240cab7576a44de68945e256ad44b2cb8d849a8060",
"d0174db2c712573432a7869c1508f371f3a1058aeedddc1b53a7e04d7c56c725",
"b4a16f724cddb8f77ddf3d2146a12c4be13d503885eaba3518a03da005009f62",
"2aa706d75decbe57745e01d46f9f5d30a08dedaf3288cee14cc4948e3684e1d4",
"ee49c5f6a5129ccaf2abebbc1d6d07a402a600af6221476b89aafaa683ca95b7",
"bea1011c77874845e9b4c876ed2ceebd530d428dd4a564ad003d9211d40bb091",
"f1e88ffc2b1de2aa4827002f06943ce5468735f7433f960bf01e75885b9f832b",
"19247d017e002fb9143d1a89eb921222a94f8a3d0faaf2e05b0f594989edc4c4",
"13f714ff62ee7d26b6d69ca980c141ebc54e9f71d2697083fe6c5efc1b02bd0f",
"0c78cbb8246572f015fbdc53dc9798fa54d1119ec77c1f07ac310bcbcc40dbf8",
"4bcde0ef92a6d24a2be7be50ac5e5299d776df2e6229ba5d475c2491da94f255",
"0cfd7d1058502730cf0b2ffa880c78ef534651e06832b5d87c0d7eb84eac5b0c",
"3a168f794d6e0c614429ad874317cc4cd67a8177214880ff6ea1704d29228c2f",
"f9a555d817334397b402518d6fd959dc73d981ee7f5fe67969b63974ebbef127",
"24b52691f66eaed4ce391a473902e309018257c98b9f02aaa33b399c9e6f3168",
"a37b5e623dc26a180d9e2c9510d06885b014e86e533adb63ec40511e10b55046",
"9dbaeb485e51d9e25a5621dc46e0bc0aaf51fb26be5acc4e370b96f62c469b80",
"a6431d3d39f6c38c5df48405090752cab03bfdf5c77cf881b18a946807fba74a",
"faa77e309f125373acf19855dd496fffe2f74962e545420844557a3adc7ebc11",
"3523f52543ecfea2f78486dc91550fad0e6467d46d9d9c82ca63b2e0230bfa71",
"a0583e358e42d77d18d1fd0533ff0a65615fc3b3112061ef92f168a00bf640c1",
"42ae900888d5e5dde59c8e3d06e13db9e84ef05d27726d4b67fd00c50cd9406a",
"154940777d3ff78f592ef02790131a59263c36b4958bbc836f9a767ea1a9f178",
"6a0337de6ac75eecf748306e8ebc5bfe5c811a1481ae50f6956a9e7f26a679f5",
"c99530c2148e09688d0b88795625943371183bf1f5d56c7446c6ed51ea133589",
"626421dbe8ad6a0fd0d622d5dd3308a1cdc00b98575a41a91fe01a439e6f40bd",
"b2f3a559f605a158cc395126c3cf394a7e92a53b7514c75157e1dc43a6c7f93e",
"dffe06d1bea81f2a01c76786404bb867258f9e68013bf25454097ce935090738",
"0860159ec7a2a51ce107c182a988c40b4bc2057a734354a1219b6c65e72640ed",
"a405ff1bb51846b1867acc0b0da17f6f9616e592a0a7ff5ef3297c1ecfd60911",
"a7d451924263284765f6343bca8a21b79b89ebfe611c7355dd88e0ec1c29e232",
"41c758d08a4d3fe4d90645711589b832a2cd54dd25bd5b66e463e5d389a53aff",
"a05c1a93a521fa5dbc1790cfbb808893453a428a65f2c6b2d51249fbb12db309",
"90997920aa9786e10f513cfdd14e294feee6739cee1ab61b3fb1e3f42e7a915d",
"99fcb9cb62c20a3135484a70bd3f73983f8f3b7b26266dad34f3993958a7642c",
"e05f9a668b37e5f78bd3b9d047f29f92b33a87f11dd48390410006f858188b7b",
"56dbc65895f7992da4a6985e7edba4d1c00879f1b28442c644c8a07658ceab27",
"5e9004fe262b829563d0804656ba68b1de1690401f08a1915273230d8c902fc0",
"1ea9ed3717523c5e304b7a7ac8058a87fb4f3fed8c6004769f226c9bb67e79c5",
"f0f1a4c009b3f1b2729e89898e2f5c0fcdc312edea5df884a9c897cb90e4c566",
"b5bb4ddf04863e6a60f33cb96c20dac8175d3bae55f335781503143c97a50e43",
"f14cc97a20c6f627b4b78301352ae35463bc359362589cd178a06c0fa90850b7",
"628801c8f614015c0fa0ccb2768cccc3e7b9d41ceed06071ce2534d31f7236d6",
"3be1013c8f8da150e2195408093153b55b08b037fd92db8bb5e803f4c2538aae",
"c9e1f8777685f54ba65c4e02915fd649ee1edcbf9c77ddf584b943d27efb86c3",
"4274e92ed3bd02eb101baa5fb8ff7b96236830762d08273749fbb5166db8ab0b",
"aa84c955bea04c7cee8f5bbbec97d25930fcaca363eed1b8cad37b931556d3e3",
"d6a29c948677fb1f71aaf16debc3d071a4dd349458eb9e056dce3a000ff853da",
"ba84bdb3d78367ca365016ac4bff9269576eb010f874c2967af73e0de5638de0",
"1546c79951e3b541bc64d1957b565b7a2850fc87192c7b374aee6cfc69b9805e",
"f119227d492ebe27fe9aae321980802454dfa64b2691efbe796c5075d5b07f62",
"b8cf13d64818b32f96bbb585998b1bc9505f6a94055488e5a71fee9479c6f2a9",
"1aaf459705b6afef2d7b83e3f181f1af55be0813daf55edce104cc59abc28ed7",
"61ac185c8f520b5e3134953dc52ff292a40e1e96b088dab259558a9d240ec02f",
"2da96e3154d7ec2329f787b73cb8a436b92d64cf3cc28e920d073279ea73b5f8",
"1c4d72ce733b971b9ec4e24f37d733355f6f2ea635cc67ffb3e22748484df446",
"2a6f89769f3272ac8c7a36a42a57627eca6b260ab2c76d8046a27d44d4034893",
"f8d11df51a2cc113698ebf39a958fe81179d7d973d2044322771c0fe63f4d7c9",
"f2287f17a4fa232dca5715c24a92f7112402a8101b9a7b276fb8c8f617376b90",
"bb5ee510a4fda29cae30c97e7eee80569d3ec3598465f2d7e0674c395e0256e9",
"647ab8c84365620d60f2523505d14bd230b5e650c96dee48be47770063ee7461",
"34b06018fcc33ba6ebb01198d785b0629fbdc5d1948f688059158f053093f08b",
"ff58b258dab0d7f36a2908e6c75229ce308d34806289c912a1a5f39a5aa71f9f",
"232fc124803668a9f23b1c3bcb1134274303f5c0e1b0e27c9b6c7db59f0e2a4d",
"27a0797cc5b042ba4c11e72a9555d13a67f00161550b32ede0511718b22dbc2c",
]
Function to generate the (pair-wise) Merkle hash.
# Hash pairs of items recursively until a single value is obtained
def merkle(hashList):
if len(hashList) == 1:
return hashList[0]
newHashList = []
# Process pairs. For odd length, the last is skipped
for i in range(0, len(hashList)-1, 2):
newHashList.append(hash2(hashList[i], hashList[i+1]))
if len(hashList) % 2 == 1: # odd, hash last item twice
newHashList.append(hash2(hashList[-1], hashList[-1]))
return merkle(newHashList)
def hash2(a, b):
# Reverse inputs before and after hashing
# due to big-endian / little-endian nonsense
a1 = a.decode('hex')[::-1]
b1 = b.decode('hex')[::-1]
h = hashlib.sha256(hashlib.sha256(a1+b1).digest()).digest()
return h[::-1].encode('hex')
Finally, the Merkle hash code for the above transaction hashes as found in the block header.
print merkle(txHashes)
871714dcbae6c8193a2bb9b2a69fe1c0440399f38d94b3a0f1b447275a29978a
http://tpq.io | @dyjh | team@tpq.io
Python Quant Platform | http://quant-platform.com
Python for Finance | Python for Finance @ O'Reilly
Derivatives Analytics with Python | Derivatives Analytics @ Wiley Finance
Listed Volatility and Variance Derivatives | Listed VV Derivatives @ Wiley Finance