diff --git a/src/bitmessagemain.py b/src/bitmessagemain.py index 3c920520..ba31f7a9 100755 --- a/src/bitmessagemain.py +++ b/src/bitmessagemain.py @@ -46,6 +46,7 @@ from SimpleXMLRPCServer import * import json from subprocess import call #used when the API must execute an outside program import singleton +import proofofwork #For each stream to which we connect, several outgoingSynSender threads will exist and will collectively create 8 connections with peers. class outgoingSynSender(threading.Thread): @@ -2709,16 +2710,11 @@ class singleWorker(threading.Thread): payload += pubEncryptionKey[1:] #Do the POW for this pubkey message - nonce = 0 - trialValue = 99999999999999999999 target = 2**64 / ((len(payload)+shared.networkDefaultPayloadLengthExtraBytes+8) * shared.networkDefaultProofOfWorkNonceTrialsPerByte) print '(For pubkey message) Doing proof of work...' initialHash = hashlib.sha512(payload).digest() - while trialValue > target: - nonce += 1 - trialValue, = unpack('>Q',hashlib.sha512(hashlib.sha512(pack('>Q',nonce) + initialHash).digest()).digest()[0:8]) + trialValue, nonce = proofofwork.run(target, initialHash) print '(For pubkey message) Found proof of work', trialValue, 'Nonce:', nonce - payload = pack('>Q',nonce) + payload """t = (hash,payload,embeddedTime,'no') shared.sqlLock.acquire() @@ -2775,14 +2771,10 @@ class singleWorker(threading.Thread): payload += signature #Do the POW for this pubkey message - nonce = 0 - trialValue = 99999999999999999999 target = 2**64 / ((len(payload)+shared.networkDefaultPayloadLengthExtraBytes+8) * shared.networkDefaultProofOfWorkNonceTrialsPerByte) print '(For pubkey message) Doing proof of work...' initialHash = hashlib.sha512(payload).digest() - while trialValue > target: - nonce += 1 - trialValue, = unpack('>Q',hashlib.sha512(hashlib.sha512(pack('>Q',nonce) + initialHash).digest()).digest()[0:8]) + trialValue, nonce = proofofwork.run(target, initialHash) print '(For pubkey message) Found proof of work', trialValue, 'Nonce:', nonce payload = pack('>Q',nonce) + payload @@ -2850,16 +2842,12 @@ class singleWorker(threading.Thread): payload += encodeVarint(len(signature)) payload += signature - nonce = 0 - trialValue = 99999999999999999999 target = 2**64 / ((len(payload)+shared.networkDefaultPayloadLengthExtraBytes+8) * shared.networkDefaultProofOfWorkNonceTrialsPerByte) print '(For broadcast message) Doing proof of work...' #self.emit(SIGNAL("updateSentItemStatusByAckdata(PyQt_PyObject,PyQt_PyObject)"),ackdata,'Doing work necessary to send broadcast...') shared.UISignalQueue.put(('updateSentItemStatusByAckdata',(ackdata,'Doing work necessary to send broadcast...'))) initialHash = hashlib.sha512(payload).digest() - while trialValue > target: - nonce += 1 - trialValue, = unpack('>Q',hashlib.sha512(hashlib.sha512(pack('>Q',nonce) + initialHash).digest()).digest()[0:8]) + trialValue, nonce = proofofwork.run(target, initialHash) print '(For broadcast message) Found proof of work', trialValue, 'Nonce:', nonce payload = pack('>Q',nonce) + payload @@ -2921,16 +2909,12 @@ class singleWorker(threading.Thread): pubEncryptionKey = pointMult(privEncryptionKey) payload += highlevelcrypto.encrypt(dataToEncrypt,pubEncryptionKey.encode('hex')) - nonce = 0 - trialValue = 99999999999999999999 target = 2**64 / ((len(payload)+shared.networkDefaultPayloadLengthExtraBytes+8) * shared.networkDefaultProofOfWorkNonceTrialsPerByte) print '(For broadcast message) Doing proof of work...' #self.emit(SIGNAL("updateSentItemStatusByAckdata(PyQt_PyObject,PyQt_PyObject)"),ackdata,'Doing work necessary to send broadcast...') shared.UISignalQueue.put(('updateSentItemStatusByAckdata',(ackdata,'Doing work necessary to send broadcast...'))) initialHash = hashlib.sha512(payload).digest() - while trialValue > target: - nonce += 1 - trialValue, = unpack('>Q',hashlib.sha512(hashlib.sha512(pack('>Q',nonce) + initialHash).digest()).digest()[0:8]) + trialValue, nonce = proofofwork.run(target, initialHash) print '(For broadcast message) Found proof of work', trialValue, 'Nonce:', nonce payload = pack('>Q',nonce) + payload @@ -3162,8 +3146,6 @@ class singleWorker(threading.Thread): requiredPayloadLengthExtraBytes = shared.networkDefaultPayloadLengthExtraBytes encrypted = highlevelcrypto.encrypt(payload,"04"+pubEncryptionKeyBase256.encode('hex')) - nonce = 0 - trialValue = 99999999999999999999 #We are now dropping the unencrypted data in payload since it has already been encrypted and replacing it with the encrypted payload that we will send out. payload = embeddedTime + encodeVarint(toStreamNumber) + encrypted target = 2**64 / ((len(payload)+requiredPayloadLengthExtraBytes+8) * requiredAverageProofOfWorkNonceTrialsPerByte) @@ -3172,9 +3154,7 @@ class singleWorker(threading.Thread): shared.printLock.release() powStartTime = time.time() initialHash = hashlib.sha512(payload).digest() - while trialValue > target: - nonce += 1 - trialValue, = unpack('>Q',hashlib.sha512(hashlib.sha512(pack('>Q',nonce) + initialHash).digest()).digest()[0:8]) + trialValue, nonce = proofofwork.run(target, initialHash) print '(For msg message) Found proof of work', trialValue, 'Nonce:', nonce try: print 'POW took', int(time.time()-powStartTime), 'seconds.', nonce/(time.time()-powStartTime), 'nonce trials per second.' @@ -3215,8 +3195,6 @@ class singleWorker(threading.Thread): shared.printLock.acquire() print 'making request for pubkey with ripe:', ripe.encode('hex') shared.printLock.release() - nonce = 0 - trialValue = 99999999999999999999 #print 'trial value', trialValue statusbar = 'Doing the computations necessary to request the recipient\'s public key.' shared.UISignalQueue.put(('updateStatusBar',statusbar)) @@ -3224,9 +3202,7 @@ class singleWorker(threading.Thread): print 'Doing proof-of-work necessary to send getpubkey message.' target = 2**64 / ((len(payload)+shared.networkDefaultPayloadLengthExtraBytes+8) * shared.networkDefaultProofOfWorkNonceTrialsPerByte) initialHash = hashlib.sha512(payload).digest() - while trialValue > target: - nonce += 1 - trialValue, = unpack('>Q',hashlib.sha512(hashlib.sha512(pack('>Q',nonce) + initialHash).digest()).digest()[0:8]) + trialValue, nonce = proofofwork.run(target, initialHash) shared.printLock.acquire() print 'Found proof of work', trialValue, 'Nonce:', nonce shared.printLock.release() @@ -3250,8 +3226,6 @@ class singleWorker(threading.Thread): shared.UISignalQueue.put(('updateSentItemStatusByHash',(ripe,'Sending public key request. Waiting for reply. Requested at ' + unicode(strftime(shared.config.get('bitmessagesettings', 'timeformat'),localtime(int(time.time()))),'utf-8')))) def generateFullAckMessage(self,ackdata,toStreamNumber,embeddedTime): - nonce = 0 - trialValue = 99999999999999999999 payload = embeddedTime + encodeVarint(toStreamNumber) + ackdata target = 2**64 / ((len(payload)+shared.networkDefaultPayloadLengthExtraBytes+8) * shared.networkDefaultProofOfWorkNonceTrialsPerByte) shared.printLock.acquire() @@ -3259,9 +3233,7 @@ class singleWorker(threading.Thread): shared.printLock.release() powStartTime = time.time() initialHash = hashlib.sha512(payload).digest() - while trialValue > target: - nonce += 1 - trialValue, = unpack('>Q',hashlib.sha512(hashlib.sha512(pack('>Q',nonce) + initialHash).digest()).digest()[0:8]) + trialValue, nonce = proofofwork.run(target, initialHash) shared.printLock.acquire() print '(For ack message) Found proof of work', trialValue, 'Nonce:', nonce try: diff --git a/src/proofofwork.py b/src/proofofwork.py new file mode 100644 index 00000000..03d7c22d --- /dev/null +++ b/src/proofofwork.py @@ -0,0 +1,28 @@ +def _pool_worker(nonce, initialHash, target, pool_size): + import hashlib + from struct import unpack, pack + trialValue = 99999999999999999999 + while trialValue > target: + nonce += pool_size + trialValue, = unpack('>Q',hashlib.sha512(hashlib.sha512(pack('>Q',nonce) + initialHash).digest()).digest()[0:8]) + return [trialValue, nonce] + +def run(target, initialHash): + from multiprocessing import Pool, cpu_count + import time + try: + pool_size = cpu_count() + except: + pool_size = 4 + pool = Pool(processes=pool_size) + result = [] + for i in range(pool_size): + result.append(pool.apply_async(_pool_worker, args = (i, initialHash, target, pool_size))) + while True: + for i in range(pool_size): + if result[i].ready(): + result = result[i].get() + pool.terminate() + return result[0], result[1] + time.sleep(1) +