Skip to content

Use bytes() on keys to be hashable in Python3 #2243

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: v0.6
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 21 additions & 15 deletions src/class_objectProcessor.py
Original file line number Diff line number Diff line change
@@ -140,9 +140,10 @@ def checkackdata(data):
# bypass nonce and time, retain object type/version/stream + body
readPosition = 16

if data[readPosition:] in state.ackdataForWhichImWatching:
data_bytes = bytes(data[readPosition:])
if data_bytes in state.ackdataForWhichImWatching:
logger.info('This object is an acknowledgement bound for me.')
del state.ackdataForWhichImWatching[data[readPosition:]]
del state.ackdataForWhichImWatching[data_bytes]
sqlExecute(
"UPDATE sent SET status='ackreceived', lastactiontime=?"
" WHERE ackdata=?", int(time.time()), data[readPosition:])
@@ -215,9 +216,10 @@ def processgetpubkey(data):
logger.info(
'the hash requested in this getpubkey request is: %s',
hexlify(requestedHash))
requestedHash_bytes = bytes(requestedHash)
# if this address hash is one of mine
if requestedHash in shared.myAddressesByHash:
myAddress = shared.myAddressesByHash[requestedHash]
if requestedHash_bytes in shared.myAddressesByHash:
myAddress = shared.myAddressesByHash[requestedHash_bytes]
elif requestedAddressVersionNumber >= 4:
requestedTag = data[readPosition:readPosition + 32]
if len(requestedTag) != 32:
@@ -227,8 +229,9 @@ def processgetpubkey(data):
logger.debug(
'the tag requested in this getpubkey request is: %s',
hexlify(requestedTag))
if requestedTag in shared.myAddressesByTag:
myAddress = shared.myAddressesByTag[requestedTag]
requestedTag_bytes = bytes(requestedTag)
if requestedTag_bytes in shared.myAddressesByTag:
myAddress = shared.myAddressesByTag[requestedTag_bytes]

if myAddress == '':
logger.info('This getpubkey request is not for any of my keys.')
@@ -413,12 +416,13 @@ def processpubkey(self, data):
' Sanity check failed.')

tag = data[readPosition:readPosition + 32]
if tag not in state.neededPubkeys:
tag_bytes = bytes(tag)
if tag_bytes not in state.neededPubkeys:
return logger.info(
'We don\'t need this v4 pubkey. We didn\'t ask for it.')

# Let us try to decrypt the pubkey
toAddress = state.neededPubkeys[tag][0]
toAddress = state.neededPubkeys[tag_bytes][0]
if protocol.decryptAndCheckPubkeyPayload(data, toAddress) == \
'successful':
# At this point we know that we have been waiting on this
@@ -483,7 +487,7 @@ def processmsg(self, data):

# This is a message bound for me.
# Look up my address based on the RIPE hash.
toAddress = shared.myAddressesByHash[toRipe]
toAddress = shared.myAddressesByHash[bytes(toRipe)]
readPosition = 0
sendersAddressVersionNumber, sendersAddressVersionNumberLength = \
decodeVarint(decryptedData[readPosition:readPosition + 10])
@@ -558,7 +562,7 @@ def processmsg(self, data):
readPosition += signatureLengthLength
signature = decryptedData[
readPosition:readPosition + signatureLength]
signedData = data[8:20] + encodeVarint(1) + encodeVarint(
signedData = bytes(data[8:20]) + encodeVarint(1) + encodeVarint(
streamNumberAsClaimedByMsg
) + decryptedData[:positionOfBottomOfAckData]

@@ -808,13 +812,14 @@ def processbroadcast(self, data):
elif broadcastVersion == 5:
embeddedTag = data[readPosition:readPosition + 32]
readPosition += 32
if embeddedTag not in shared.MyECSubscriptionCryptorObjects:
embeddedTag_bytes = bytes(embeddedTag)
if embeddedTag_bytes not in shared.MyECSubscriptionCryptorObjects:
logger.debug('We\'re not interested in this broadcast.')
return
# We are interested in this broadcast because of its tag.
# We're going to add some more data which is signed further down.
signedData = data[8:readPosition]
cryptorObject = shared.MyECSubscriptionCryptorObjects[embeddedTag]
signedData = bytes(data[8:readPosition])
cryptorObject = shared.MyECSubscriptionCryptorObjects[embeddedTag_bytes]
try:
decryptedData = cryptorObject.decrypt(data[readPosition:])
logger.debug('EC decryption successful')
@@ -997,8 +1002,9 @@ def possibleNewPubkey(self, address):
encodeVarint(addressVersion) + encodeVarint(streamNumber)
+ ripe
)[32:]
if tag in state.neededPubkeys:
del state.neededPubkeys[tag]
tag_bytes = bytes(tag)
if tag_bytes in state.neededPubkeys:
del state.neededPubkeys[tag_bytes]
self.sendMessages(address)

@staticmethod
21 changes: 12 additions & 9 deletions src/class_singleWorker.py
Original file line number Diff line number Diff line change
@@ -87,7 +87,7 @@ def run(self):
tag = doubleHashOfAddressData[32:]
# We'll need this for when we receive a pubkey reply:
# it will be encrypted and we'll need to decrypt it.
state.neededPubkeys[tag] = (
state.neededPubkeys[bytes(tag)] = (
toAddress,
highlevelcrypto.makeCryptor(
hexlify(privEncryptionKey))
@@ -99,14 +99,14 @@ def run(self):
for row in queryreturn:
ackdata, = row
self.logger.info('Watching for ackdata %s', hexlify(ackdata))
state.ackdataForWhichImWatching[ackdata] = 0
state.ackdataForWhichImWatching[bytes(ackdata)] = 0

# Fix legacy (headerless) watched ackdata to include header
for oldack in state.ackdataForWhichImWatching:
if len(oldack) == 32:
# attach legacy header, always constant (msg/1/1)
newack = '\x00\x00\x00\x02\x01\x01' + oldack
state.ackdataForWhichImWatching[newack] = 0
state.ackdataForWhichImWatching[bytes(newack)] = 0
sqlExecute(
'''UPDATE sent SET ackdata=? WHERE ackdata=? AND folder = 'sent' ''',
newack, oldack
@@ -794,8 +794,9 @@ def sendMsg(self):
encodeVarint(toAddressVersionNumber)
+ encodeVarint(toStreamNumber) + toRipe
)[32:]
toTag_bytes = bytes(toTag)
if toaddress in state.neededPubkeys or \
toTag in state.neededPubkeys:
toTag_bytes in state.neededPubkeys:
# We already sent a request for the pubkey
sqlExecute(
'''UPDATE sent SET status='awaitingpubkey', '''
@@ -836,7 +837,8 @@ def sendMsg(self):
privEncryptionKey = doubleHashOfToAddressData[:32]
# The second half of the sha512 hash.
tag = doubleHashOfToAddressData[32:]
state.neededPubkeys[tag] = (
tag_bytes = bytes(tag)
state.neededPubkeys[tag_bytes] = (
toaddress,
highlevelcrypto.makeCryptor(
hexlify(privEncryptionKey))
@@ -859,7 +861,7 @@ def sendMsg(self):
''' status='doingpubkeypow') AND '''
''' folder='sent' ''',
toaddress)
del state.neededPubkeys[tag]
del state.neededPubkeys[tag_bytes]
break
# else:
# There was something wrong with this
@@ -901,7 +903,7 @@ def sendMsg(self):

# if we aren't sending this to ourselves or a chan
if not config.has_section(toaddress):
state.ackdataForWhichImWatching[ackdata] = 0
state.ackdataForWhichImWatching[bytes(ackdata)] = 0
queues.UISignalQueue.put((
'updateSentItemStatusByAckdata', (
ackdata,
@@ -1412,10 +1414,11 @@ def requestPubKey(self, toAddress):
privEncryptionKey = doubleHashOfAddressData[:32]
# Note that this is the second half of the sha512 hash.
tag = doubleHashOfAddressData[32:]
if tag not in state.neededPubkeys:
tag_bytes = bytes(tag)
if tag_bytes not in state.neededPubkeys:
# We'll need this for when we receive a pubkey reply:
# it will be encrypted and we'll need to decrypt it.
state.neededPubkeys[tag] = (
state.neededPubkeys[tag_bytes] = (
toAddress,
highlevelcrypto.makeCryptor(hexlify(privEncryptionKey))
)
4 changes: 2 additions & 2 deletions src/network/bmproto.py
Original file line number Diff line number Diff line change
@@ -415,7 +415,7 @@ def bm_command_object(self):
BMProto.stopDownloadingObject(self.object.inventoryHash, True)
else:
try:
del missingObjects[self.object.inventoryHash]
del missingObjects[bytes(self.object.inventoryHash)]
except KeyError:
pass

@@ -653,7 +653,7 @@ def stopDownloadingObject(hashId, forwardAnyway=False):
except KeyError:
pass
try:
del missingObjects[hashId]
del missingObjects[bytes(hashId)]
except KeyError:
pass

15 changes: 8 additions & 7 deletions src/network/dandelion.py
Original file line number Diff line number Diff line change
@@ -52,7 +52,7 @@ def addHash(self, hashId, source=None, stream=1):
if not state.dandelion_enabled:
return
with self.lock:
self.hashMap[hashId] = Stem(
self.hashMap[bytes(hashId)] = Stem(
self.getNodeStem(source),
stream,
self.poissonTimeout())
@@ -63,9 +63,10 @@ def setHashStream(self, hashId, stream=1):
include streams, we only learn this after receiving the object)
"""
with self.lock:
if hashId in self.hashMap:
self.hashMap[hashId] = Stem(
self.hashMap[hashId].child,
hashId_bytes = bytes(hashId)
if hashId_bytes in self.hashMap:
self.hashMap[hashId_bytes] = Stem(
self.hashMap[hashId_bytes].child,
stream,
self.poissonTimeout())

@@ -77,17 +78,17 @@ def removeHash(self, hashId, reason="no reason specified"):
''.join('%02x' % ord(i) for i in hashId), reason)
with self.lock:
try:
del self.hashMap[hashId]
del self.hashMap[bytes(hashId)]
except KeyError:
pass

def hasHash(self, hashId):
"""Is inventory vector in stem mode?"""
return hashId in self.hashMap
return bytes(hashId) in self.hashMap

def objectChildStem(self, hashId):
"""Child (i.e. next) node for an inventory vector during stem mode"""
return self.hashMap[hashId].child
return self.hashMap[bytes(hashId)].child

def maybeAddStem(self, connection):
"""
2 changes: 1 addition & 1 deletion src/network/downloadthread.py
Original file line number Diff line number Diff line change
@@ -67,7 +67,7 @@ def run(self):
continue
payload.extend(chunk)
chunkCount += 1
missingObjects[chunk] = now
missingObjects[bytes(chunk)] = now
if not chunkCount:
continue
payload[0:0] = addresses.encodeVarint(chunkCount)
21 changes: 12 additions & 9 deletions src/network/objectracker.py
Original file line number Diff line number Diff line change
@@ -81,25 +81,28 @@ def clean(self):

def hasObj(self, hashid):
"""Do we already have object?"""
hashid_bytes = bytes(hashid)
if haveBloom:
return hashid in self.invBloom
return hashid in self.objectsNewToMe
return hashid_bytes in self.invBloom
return hashid_bytes in self.objectsNewToMe

def handleReceivedInventory(self, hashId):
"""Handling received inventory"""
hashId_bytes = bytes(hashId)
if haveBloom:
self.invBloom.add(hashId)
self.invBloom.add(hashId_bytes)
try:
with self.objectsNewToThemLock:
del self.objectsNewToThem[hashId]
del self.objectsNewToThem[hashId_bytes]
except KeyError:
pass
if hashId not in missingObjects:
missingObjects[hashId] = time.time()
if hashId_bytes not in missingObjects:
missingObjects[hashId_bytes] = time.time()
self.objectsNewToMe[hashId] = True

def handleReceivedObject(self, streamNumber, hashid):
"""Handling received object"""
hashid_bytes = bytes(hashid)
for i in connectionpool.pool.connections():
if not i.fullyEstablished:
continue
@@ -110,7 +113,7 @@ def handleReceivedObject(self, streamNumber, hashid):
not state.Dandelion.hasHash(hashid)
or state.Dandelion.objectChildStem(hashid) == i):
with i.objectsNewToThemLock:
i.objectsNewToThem[hashid] = time.time()
i.objectsNewToThem[hashid_bytes] = time.time()
# update stream number,
# which we didn't have when we just received the dinv
# also resets expiration of the stem mode
@@ -119,7 +122,7 @@ def handleReceivedObject(self, streamNumber, hashid):
if i == self:
try:
with i.objectsNewToThemLock:
del i.objectsNewToThem[hashid]
del i.objectsNewToThem[hashid_bytes]
except KeyError:
pass
self.objectsNewToMe.setLastObject()
@@ -133,4 +136,4 @@ def hasAddr(self, addr):
def addAddr(self, hashid):
"""WIP, should be moved to addrthread.py or removed"""
if haveBloom:
self.addrBloom.add(hashid)
self.addrBloom.add(bytes(hashid))
8 changes: 4 additions & 4 deletions src/protocol.py
Original file line number Diff line number Diff line change
@@ -293,7 +293,7 @@ def isProofOfWorkSufficient(
if TTL < 300:
TTL = 300
POW, = unpack('>Q', highlevelcrypto.double_sha512(
data[:8] + hashlib.sha512(data[8:]).digest())[0:8])
bytes(data[:8]) + hashlib.sha512(data[8:]).digest())[0:8])
return POW <= 2 ** 64 / (
nonceTrialsPerByte * (
len(data) + payloadLengthExtraBytes
@@ -465,7 +465,7 @@ def decryptAndCheckPubkeyPayload(data, address):
readPosition += varintLength
# We'll store the address version and stream number
# (and some more) in the pubkeys table.
storedData = data[20:readPosition]
storedData = bytes(data[20:readPosition])

if addressVersion != embeddedAddressVersion:
logger.info(
@@ -482,11 +482,11 @@ def decryptAndCheckPubkeyPayload(data, address):
readPosition += 32
# the time through the tag. More data is appended onto
# signedData below after the decryption.
signedData = data[8:readPosition]
signedData = bytes(data[8:readPosition])
encryptedData = data[readPosition:]

# Let us try to decrypt the pubkey
toAddress, cryptorObject = state.neededPubkeys[tag]
toAddress, cryptorObject = state.neededPubkeys[bytes(tag)]
if toAddress != address:
logger.critical(
'decryptAndCheckPubkeyPayload failed due to toAddress'
4 changes: 2 additions & 2 deletions src/pyelliptic/cipher.py
Original file line number Diff line number Diff line change
@@ -30,7 +30,7 @@ def __init__(self, key, iv, do, ciphername='aes-256-cbc'):
self.ctx = OpenSSL.EVP_CIPHER_CTX_new()
if do == 1 or do == 0:
k = OpenSSL.malloc(key, len(key))
IV = OpenSSL.malloc(iv, len(iv))
IV = OpenSSL.malloc(bytes(iv), len(iv))
OpenSSL.EVP_CipherInit_ex(
self.ctx, self.cipher.get_pointer(), 0, k, IV, do)
else:
@@ -59,7 +59,7 @@ def update(self, input):
"""Update result with more data"""
i = OpenSSL.c_int(0)
buffer = OpenSSL.malloc(b"", len(input) + self.cipher.get_blocksize())
inp = OpenSSL.malloc(input, len(input))
inp = OpenSSL.malloc(bytes(input), len(input))
if OpenSSL.EVP_CipherUpdate(self.ctx, OpenSSL.byref(buffer),
OpenSSL.byref(i), inp, len(input)) == 0:
raise Exception("[OpenSSL] EVP_CipherUpdate FAIL ...")
5 changes: 3 additions & 2 deletions src/pyelliptic/ecc.py
Original file line number Diff line number Diff line change
@@ -7,6 +7,7 @@

from hashlib import sha512
from struct import pack, unpack
from ctypes import c_char_p

from .cipher import Cipher
from .hash import equals, hmac_sha256
@@ -218,8 +219,8 @@ def raw_get_ecdh_key(self, pubkey_x, pubkey_y):
if other_key == 0:
raise Exception("[OpenSSL] EC_KEY_new_by_curve_name FAIL ...")

other_pub_key_x = OpenSSL.BN_bin2bn(pubkey_x, len(pubkey_x), None)
other_pub_key_y = OpenSSL.BN_bin2bn(pubkey_y, len(pubkey_y), None)
other_pub_key_x = OpenSSL.BN_bin2bn(c_char_p(bytes(pubkey_x)), len(pubkey_x), None)
other_pub_key_y = OpenSSL.BN_bin2bn(c_char_p(bytes(pubkey_y)), len(pubkey_y), None)

other_group = OpenSSL.EC_KEY_get0_group(other_key)
other_pub_key = OpenSSL.EC_POINT_new(other_group)
2 changes: 1 addition & 1 deletion src/pyelliptic/hash.py
Original file line number Diff line number Diff line change
@@ -38,7 +38,7 @@ def hmac_sha256(k, m):
Compute the key and the message with HMAC SHA5256
"""
key = OpenSSL.malloc(k, len(k))
d = OpenSSL.malloc(m, len(m))
d = OpenSSL.malloc(bytes(m), len(m))
md = OpenSSL.malloc(0, 32)
i = OpenSSL.pointer(OpenSSL.c_int(0))
OpenSSL.HMAC(OpenSSL.EVP_sha256(), key, len(k), d, len(m), md, i)
22 changes: 12 additions & 10 deletions src/randomtrackingdict.py
Original file line number Diff line number Diff line change
@@ -38,37 +38,39 @@ def __len__(self):
return self.len

def __contains__(self, key):
return key in self.dictionary
return bytes(key) in self.dictionary

def __getitem__(self, key):
return self.dictionary[key][1]
return self.dictionary[bytes(key)][1]

def _swap(self, i1, i2):
with self.lock:
key1 = self.indexDict[i1]
key2 = self.indexDict[i2]
self.indexDict[i1] = key2
self.indexDict[i2] = key1
self.dictionary[key1][0] = i2
self.dictionary[key2][0] = i1
self.dictionary[bytes(key1)][0] = i2
self.dictionary[bytes(key2)][0] = i1
# for quick reassignment
return i2

def __setitem__(self, key, value):
with self.lock:
if key in self.dictionary:
self.dictionary[key][1] = value
key_bytes = bytes(key)
if key_bytes in self.dictionary:
self.dictionary[key_bytes][1] = value
else:
self.indexDict.append(key)
self.dictionary[key] = [self.len, value]
self.dictionary[key_bytes] = [self.len, value]
self._swap(self.len, self.len - self.pendingLen)
self.len += 1

def __delitem__(self, key):
if key not in self.dictionary:
key_bytes = bytes(key)
if key_bytes not in self.dictionary:
raise KeyError
with self.lock:
index = self.dictionary[key][0]
index = self.dictionary[key_bytes][0]
# not pending
if index < self.len - self.pendingLen:
# left of pending part
@@ -82,7 +84,7 @@ def __delitem__(self, key):
# operation can improve 4x, but it's already very fast so we'll
# ignore it for the time being
del self.indexDict[-1]
del self.dictionary[key]
del self.dictionary[key_bytes]
self.len -= 1

def setMaxPending(self, maxPending):
8 changes: 4 additions & 4 deletions src/shared.py
Original file line number Diff line number Diff line change
@@ -114,11 +114,11 @@ def reloadMyAddressHashes():
if len(privEncryptionKey) == 64:
myECCryptorObjects[hashobj] = \
highlevelcrypto.makeCryptor(privEncryptionKey)
myAddressesByHash[hashobj] = addressInKeysFile
myAddressesByHash[bytes(hashobj)] = addressInKeysFile
tag = highlevelcrypto.double_sha512(
encodeVarint(addressVersionNumber)
+ encodeVarint(streamNumber) + hashobj)[32:]
myAddressesByTag[tag] = addressInKeysFile
myAddressesByTag[bytes(tag)] = addressInKeysFile

if not keyfileSecure:
fixSensitiveFilePermissions(os.path.join(
@@ -149,7 +149,7 @@ def reloadBroadcastSendersForWhichImWatching():
encodeVarint(addressVersionNumber)
+ encodeVarint(streamNumber) + hashobj
).digest()[:32]
MyECSubscriptionCryptorObjects[hashobj] = \
MyECSubscriptionCryptorObjects[bytes(hashobj)] = \
highlevelcrypto.makeCryptor(hexlify(privEncryptionKey))
else:
doubleHashOfAddressData = highlevelcrypto.double_sha512(
@@ -158,7 +158,7 @@ def reloadBroadcastSendersForWhichImWatching():
)
tag = doubleHashOfAddressData[32:]
privEncryptionKey = doubleHashOfAddressData[:32]
MyECSubscriptionCryptorObjects[tag] = \
MyECSubscriptionCryptorObjects[bytes(tag)] = \
highlevelcrypto.makeCryptor(hexlify(privEncryptionKey))


17 changes: 10 additions & 7 deletions src/storage/sqlite.py
Original file line number Diff line number Diff line change
@@ -29,20 +29,22 @@ def __init__(self):

def __contains__(self, hash_):
with self.lock:
if hash_ in self._objects:
hash_bytes = bytes(hash_)
if hash_bytes in self._objects:
return True
rows = sqlQuery(
'SELECT streamnumber FROM inventory WHERE hash=?',
sqlite3.Binary(hash_))
if not rows:
return False
self._objects[hash_] = rows[0][0]
self._objects[hash_bytes] = rows[0][0]
return True

def __getitem__(self, hash_):
with self.lock:
if hash_ in self._inventory:
return self._inventory[hash_]
hash_bytes = bytes(hash_)
if hash_bytes in self._inventory:
return self._inventory[hash_bytes]
rows = sqlQuery(
'SELECT objecttype, streamnumber, payload, expirestime, tag'
' FROM inventory WHERE hash=?', sqlite3.Binary(hash_))
@@ -53,15 +55,16 @@ def __getitem__(self, hash_):
def __setitem__(self, hash_, value):
with self.lock:
value = InventoryItem(*value)
self._inventory[hash_] = value
self._objects[hash_] = value.stream
hash_bytes = bytes(hash_)
self._inventory[hash_bytes] = value
self._objects[hash_bytes] = value.stream

def __delitem__(self, hash_):
raise NotImplementedError

def __iter__(self):
with self.lock:
hashes = self._inventory.keys()[:]
hashes = [] + self._inventory.keys()[:]
hashes += (x for x, in sqlQuery('SELECT hash FROM inventory'))
return hashes.__iter__()

8 changes: 4 additions & 4 deletions src/tests/test_randomtrackingdict.py
Original file line number Diff line number Diff line change
@@ -15,10 +15,10 @@ class TestRandomTrackingDict(unittest.TestCase):
@staticmethod
def randString():
"""helper function for tests, generates a random string"""
retval = ''
for _ in range(32):
retval += chr(random.randint(0, 255))
return retval
retval = bytearray(32)
for i in range(32):
retval[i] = random.randint(0, 255)
return bytes(retval)

def test_check_randomtrackingdict(self):
"""Check the logic of RandomTrackingDict class"""