From b6a91ed4b3078a5bec29a82a4b79e79f948e36b1 Mon Sep 17 00:00:00 2001 From: Peter Surda Date: Sat, 20 Jun 2015 09:54:15 +0200 Subject: [PATCH] Minor changes in cli, PoW, and a couple of new api calls. --- src/api.py | 70 +++++++++++++++++++++++++++++++++++++++++- src/bitmessagecli.py | 68 ++++++++++++++++++++++++++++++++++++++++ src/class_sqlThread.py | 2 +- src/openclpow.py | 14 ++++++--- src/proofofwork.py | 9 ++++-- 5 files changed, 154 insertions(+), 9 deletions(-) diff --git a/src/api.py b/src/api.py index 9e498f46..69e883b3 100644 --- a/src/api.py +++ b/src/api.py @@ -26,7 +26,7 @@ from pyelliptic.openssl import OpenSSL from struct import pack # Classes -from helper_sql import sqlQuery,sqlExecute,SqlBulkExecute +from helper_sql import sqlQuery,sqlExecute,SqlBulkExecute,sqlStoredProcedure from debug import logger # Helper Functions @@ -181,6 +181,12 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler): return data elif method == 'listAddressBookEntries' or method == 'listAddressbook': # the listAddressbook alias should be removed eventually. queryreturn = sqlQuery('''SELECT label, address from addressbook''') + if len(params) == 1: + label, = params + label = self._decode(label, "base64") + queryreturn = sqlQuery('''SELECT label, address from addressbook WHERE label = ?''', label) + elif len(params) > 1: + raise APIError(0, "Too many paremeters, max 1") data = '{"addresses":[' for row in queryreturn: label, address = row @@ -190,6 +196,22 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler): data += json.dumps({'label':label.encode('base64'), 'address': address}, indent=4, separators=(',', ': ')) data += ']}' return data + elif method == 'getAddressBookEntry': # search by label + if len(params) != 1: + raise APIError(0, "I need a label") + label, = params + label = self._decode(label, "base64") + queryreturn = sqlQuery('''SELECT label, address from addressbook WHERE label = ?''', label) + data = '{"address":[' + for row in queryreturn: + label, address = row + label = shared.fixPotentiallyInvalidUTF8Data(label) + if len(data) > 20: + data += ',' + data += json.dumps({'label':label.encode('base64'), 'address': address}, indent=4, separators=(',', ': ')) + data += ']}' + return data + elif method == 'addAddressBookEntry' or method == 'addAddressbook': # the addAddressbook alias should be deleted eventually. if len(params) != 2: raise APIError(0, "I need label and address") @@ -951,6 +973,52 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler): return json.dumps({'status':status, 'addressVersion':addressVersion, 'streamNumber':streamNumber, 'ripe':ripe.encode('base64')}, indent=4, separators=(',', ': ')) + elif method == 'getInboxCount': + #queryreturn = sqlQuery('''SELECT read, received < 'now' - 60 AS old, COUNT (*) AS cnt FROM inbox WHERE folder = 'inbox' GROUP BY read, old''') + ret = {} + queryreturn = sqlQuery('''SELECT COUNT (*) AS cnt FROM inbox WHERE folder = 'inbox' AND read = 0 AND received < 'now' - 60''') + for row in queryreturn: + count, = row + ret['oldread'] = count + queryreturn = sqlQuery('''SELECT COUNT (*) AS cnt FROM inbox WHERE folder = 'inbox' AND read = 1 AND received < 'now' - 60''') + for row in queryreturn: + count, = row + ret['oldunread'] = count + queryreturn = sqlQuery('''SELECT COUNT (*) AS cnt FROM inbox WHERE folder = 'inbox' AND read = 0 AND received >= 'now' - 60''') + for row in queryreturn: + count, = row + ret['newread'] = count + queryreturn = sqlQuery('''SELECT COUNT (*) AS cnt FROM inbox WHERE folder = 'inbox' AND read = 1 AND received >= 'now' - 60''') + for row in queryreturn: + count, = row + ret['newunread'] = count + data = '{"inboxCount":{' + for key in ret: + val = ret[key] + if len(data) > 16: + data += ',' + data += json.dumps({key:val}, indent=4, separators=(',', ': ')) + data += '}}' + elif method == 'getSentCount': + ret = {} + queryreturn = sqlQuery('''SELECT COUNT (*) AS cnt FROM sent WHERE folder = 'sent' AND status = 'msgqueued' ''') + for row in queryreturn: + count, = row + ret['queued'] = count + queryreturn = sqlQuery('''SELECT COUNT (*) AS cnt FROM sent WHERE folder = 'sent' AND status = 'msgsent' ''') + for row in queryreturn: + count, = row + ret['awaitingack'] = count + data = '{"sentCount":{' + for key in ret: + val = ret[key] + if len(data) > 15: + data += ',' + data += json.dumps({key:val}, indent=4, separators=(',', ': ')) + data += '}}' + elif method == 'deleteAndVacuum': + sqlStoredProcedure('deleteandvacuume') + return 'done' else: raise APIError(20, 'Invalid method: %s' % method) diff --git a/src/bitmessagecli.py b/src/bitmessagecli.py index cfe892b6..87d71f05 100644 --- a/src/bitmessagecli.py +++ b/src/bitmessagecli.py @@ -575,6 +575,46 @@ def genAdd(lbl,deterministic, passphrase, numOfAdd, addVNum, streamNum, ripe): # else: return 'Entry Error' +def delMilAddr(): #Generate address + global usrPrompt + try: + response = api.listAddresses2() + # if api is too old just return then fail + if "API Error 0020" in response: return + addresses = json.loads(response) + for entry in addresses['addresses']: + if entry['label'].decode('base64')[:6] == "random": + api.deleteAddress(entry['address']) + except: + print '\n Connection Error\n' + usrPrompt = 0 + main() + +def genMilAddr(): #Generate address + global usrPrompt + maxn = 0 + try: + response = api.listAddresses2() + if "API Error 0020" in response: return + addresses = json.loads(response) + for entry in addresses['addresses']: + if entry['label'].decode('base64')[:6] == "random": + newn = int(entry['label'].decode('base64')[6:]) + if maxn < newn: + maxn = newn + except: + print "\n Some error\n" + print "\n Starting at " + str(maxn) + "\n" + for i in range(maxn, 10000): + lbl = "random" + str(i) + addressLabel = lbl.encode('base64') + try: + generatedAddress = api.createRandomAddress(addressLabel) + except: + print '\n Connection Error\n' + usrPrompt = 0 + main() + def saveFile(fileName, fileData): #Allows attachments and messages/broadcats to be saved #This section finds all invalid characters and replaces them with ~ @@ -1249,6 +1289,19 @@ def markAllMessagesUnread(): if message['read']: markMessageUnread(message['msgid']) +def clientStatus(): + try: + clientStatus = json.loads(api.clientStatus()) + except: + print '\n Connection Error\n' + usrPrompt = 0 + main() + print "\nnetworkStatus: " + clientStatus['networkStatus'] + "\n" + print "\nnetworkConnections: " + str(clientStatus['networkConnections']) + "\n" + print "\nnumberOfPubkeysProcessed: " + str(clientStatus['numberOfPubkeysProcessed']) + "\n" + print "\nnumberOfMessagesProcessed: " + str(clientStatus['numberOfMessagesProcessed']) + "\n" + print "\nnumberOfBroadcastsProcessed: " + str(clientStatus['numberOfBroadcastsProcessed']) + "\n" + def UI(usrInput): #Main user menu global usrPrompt @@ -1665,6 +1718,21 @@ def UI(usrInput): #Main user menu markAllMessagesUnread() usrPrompt = 1 main() + + elif usrInput == "status": + clientStatus() + usrPrompt = 1 + main() + + elif usrInput == "million+": + genMilAddr() + usrPrompt = 1 + main() + + elif usrInput == "million-": + delMilAddr() + usrPrompt = 1 + main() else: print '\n "',usrInput,'" is not a command.\n' diff --git a/src/class_sqlThread.py b/src/class_sqlThread.py index 4eadc6f0..cbceed8f 100644 --- a/src/class_sqlThread.py +++ b/src/class_sqlThread.py @@ -400,7 +400,7 @@ class sqlThread(threading.Thread): queryreturn = self.cur.fetchall() for row in queryreturn: value, = row - if int(value) < int(time.time()) - 2592000: + if int(value) < int(time.time()) - 86400: logger.info('It has been a long time since the messages.dat file has been vacuumed. Vacuuming now...') try: self.cur.execute( ''' VACUUM ''') diff --git a/src/openclpow.py b/src/openclpow.py index 0876aa79..bd9dad3b 100644 --- a/src/openclpow.py +++ b/src/openclpow.py @@ -2,6 +2,7 @@ import numpy from struct import pack, unpack import time import hashlib +import random import pyopencl as cl hash_dt = numpy.dtype([('target', numpy.uint64), ('v', numpy.str_, 73)]) @@ -14,7 +15,7 @@ try: ctx = cl.create_some_context() queue = cl.CommandQueue(ctx) - f = open('kernel.cl', 'r') + f = open('/usr/src/PyBitmessage/src/kernel.cl', 'r') fstr = ''.join(f.readlines()) program = cl.Program(ctx, fstr).build() except: @@ -42,7 +43,10 @@ def do_opencl_pow(hash, target): kernel.set_arg(1, dest_buf) start = time.time() + #startpos = random.getrandbits(32) << 32 | random.getrandbits(32) + #startpos = random.getrandbits(32) startpos = 0 + progress = 0 globamt = worksize*2000 while output[0][0] == 0: @@ -50,17 +54,19 @@ def do_opencl_pow(hash, target): cl.enqueue_nd_range_kernel(queue, kernel, (globamt,), (worksize,)) cl.enqueue_read_buffer(queue, dest_buf, output) queue.finish() + #startpos == (globamt + startpos) & 0xFFFFFFFFFFFFFFFF startpos += globamt + progress += globamt sofar = time.time() - start - print sofar, startpos / sofar, "hashes/sec" + print sofar, progress / sofar, "hashes/sec" taken = time.time() - start - print startpos, taken + print progress, taken return output[0][0] if __name__ == "__main__": target = 54227212183L initialHash = "3758f55b5a8d902fd3597e4ce6a2d3f23daff735f65d9698c270987f4e67ad590b93f3ffeba0ef2fd08a8dc2f87b68ae5a0dc819ab57f22ad2c4c9c8618a43b3".decode("hex") - nonce = do_pow(initialHash.encode("hex"), target) + nonce = do_opencl_pow(initialHash.encode("hex"), target) trialValue, = unpack('>Q',hashlib.sha512(hashlib.sha512(pack('>Q',nonce) + initialHash).digest()).digest()[0:8]) print "{} - value {} < {}".format(nonce, trialValue, target) diff --git a/src/proofofwork.py b/src/proofofwork.py index f05e7eea..fec70287 100644 --- a/src/proofofwork.py +++ b/src/proofofwork.py @@ -6,7 +6,7 @@ from struct import unpack, pack import sys from shared import config, frozen import shared -from openclpow import do_opencl_pow +import openclpow #import os def _set_idle(): @@ -33,6 +33,7 @@ def _pool_worker(nonce, initialHash, target, pool_size): return [trialValue, nonce] def _doSafePoW(target, initialHash): + print "Safe POW\n" nonce = 0 trialValue = float('inf') while trialValue > target: @@ -41,6 +42,7 @@ def _doSafePoW(target, initialHash): return [trialValue, nonce] def _doFastPoW(target, initialHash): + print "Fast POW\n" import time from multiprocessing import Pool, cpu_count try: @@ -72,13 +74,14 @@ def _doFastPoW(target, initialHash): time.sleep(0.2) def _doGPUPow(target, initialHash): - nonce = do_opencl_pow(initialHash.encode("hex"), target) + print "GPU POW\n" + nonce = openclpow.do_opencl_pow(initialHash.encode("hex"), target) trialValue, = unpack('>Q',hashlib.sha512(hashlib.sha512(pack('>Q',nonce) + initialHash).digest()).digest()[0:8]) #print "{} - value {} < {}".format(nonce, trialValue, target) return [trialValue, nonce] def run(target, initialHash): - if has_opencl: + if openclpow.has_opencl(): return _doGPUPow(target, initialHash) elif frozen == "macosx_app" or not frozen: return _doFastPoW(target, initialHash)