Reputation: 61
I have researched this question thoroughly here:
and I have tried various layouts to try and get it to work.
print(merkle(txtHashes))
ha = merkle(txtHashes)
print(ha)
the code comes from here a Python 2.7 script see below:
import hashlib
# 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')
txtHashes = [
"00baf6626abc2df808da36a518c69f09b0d2ed0a79421ccfde4f559d2e42128b",
"91c5e9f288437262f218c60f986e8bc10fb35ab3b9f6de477ff0eb554da89dea",
"46685c94b82b84fa05b6a0f36de6ff46475520113d5cb8c6fb060e043a0dbc5c"]
print merkle(txtHashes)
This works on Python 2.7, I can't get it to work on Python 3 even when I change the bottom line to
print(merkle(txtHashes))
Error given:
Traceback (most recent call last):
File "C:/Python30/MerkleRootTrial.py", line 126, in <module>
print(merkle(txtHashes))
File "C:/Python30/MerkleRootTrial.py", line 10, in merkle
newHashList.append(hash2(hashList[i], hashList[i+1]))
File "C:/Python30/MerkleRootTrial.py", line 18, in hash2
a1 = a.decode('hex')[::-1]
AttributeError: 'str' object has no attribute 'decode'
Upvotes: 0
Views: 215
Reputation: 31
To add to benediktwerner's answer, you can also decode the hex string to bytes using the following two methods in python 3.x:
import codecs
a1 = codecs.decode(a, 'hex_codec')[::-1]
Or, if you prefer not to import:
a1 = bytes.fromhex(a)[::-1]
From these two examples, the returned values for a1 are equal.
Upvotes: 1
Reputation: 88
In Python 3 str
and bytes
are different types while they were the same in Python 2. In Python 3 only bytes
-objects have a decode()
function and only str
-objects have encode()
, so you can't do a.decode('hex')
because a
is a str
.
Also, some (I think all?) pseudo-encodings like "hex"
(and a few others like "zip"
and "rot13"
) were removed, so you can't convert strings
and bytes
from/to hex anymore using en/decode()
. Instead, you can use binascii
:
import binascii
binascii.hexlify(a) # instead of a.encode("hex")
binascii.unhexlify(a) # instead of a.decode("hex")
Note, that hexlify()
only takes bytes
-objects (which only makes sense) and both of those methods also return bytes
-objects, but you can convert str
to bytes
and the other way around using en/decode()
:
b"abc".decode() -> "abc"
"abc".encode() -> b"abc"
In your case you need to import binascii
change hash2
to this:
def hash2(a, b):
# Reverse inputs before and after hashing
# due to big-endian / little-endian nonsense
a1 = binascii.unhexlify(a)[::-1]
b1 = binascii.unhexlify(b)[::-1]
h = hashlib.sha256(hashlib.sha256(a1+b1).digest()).digest()
return binascii.hexlify(h[::-1]) # add .decode() here if you want str instead of bytes
Upvotes: 2