most daemon code done

This commit is contained in:
Jonathan Warren 2013-05-01 16:06:55 -04:00
parent 3811881868
commit 08dad3e33d
1 changed files with 666 additions and 489 deletions

View File

@ -18,15 +18,18 @@ useVeryEasyProofOfWorkForTesting = False #If you set this to True while on the n
encryptedBroadcastSwitchoverTime = 1369735200 encryptedBroadcastSwitchoverTime = 1369735200
import sys import sys
import ConfigParser
try: try:
from PyQt4.QtCore import * from PyQt4.QtCore import *
from PyQt4.QtGui import * from PyQt4.QtGui import *
except Exception, err: except Exception, err:
print 'PyBitmessage requires PyQt. You can download it from http://www.riverbankcomputing.com/software/pyqt/download or by searching Google for \'PyQt Download\' (without quotes).' print 'PyBitmessage requires PyQt. You can download it from http://www.riverbankcomputing.com/software/pyqt/download or by searching Google for \'PyQt Download\' (without quotes).'
print 'Error message:', err print 'Error message:', err
sys.exit() sys.exit()
import ConfigParser
from bitmessageui import * from bitmessageui import *
import ConfigParser
from newaddressdialog import * from newaddressdialog import *
from newsubscriptiondialog import * from newsubscriptiondialog import *
from regenerateaddresses import * from regenerateaddresses import *
@ -56,15 +59,25 @@ import highlevelcrypto
from pyelliptic.openssl import OpenSSL from pyelliptic.openssl import OpenSSL
import ctypes import ctypes
from pyelliptic import arithmetic from pyelliptic import arithmetic
import signal #Used to capture a Ctrl-C keypress so that Bitmessage can shutdown gracefully.
#The next 3 are used for the API #The next 3 are used for the API
from SimpleXMLRPCServer import * from SimpleXMLRPCServer import *
import json import json
from subprocess import call #used when the API must execute an outside program from subprocess import call #used when the API must execute an outside program
class iconGlossaryDialog(QtGui.QDialog):
def __init__(self,parent):
QtGui.QWidget.__init__(self, parent)
self.ui = Ui_iconGlossaryDialog()
self.ui.setupUi(self)
self.parent = parent
self.ui.labelPortNumber.setText('You are using TCP port ' + str(config.getint('bitmessagesettings', 'port')) + '. (This can be changed in the settings).')
QtGui.QWidget.resize(self,QtGui.QWidget.sizeHint(self))
#For each stream to which we connect, several outgoingSynSender threads will exist and will collectively create 8 connections with peers. #For each stream to which we connect, several outgoingSynSender threads will exist and will collectively create 8 connections with peers.
class outgoingSynSender(QThread): class outgoingSynSender(threading.Thread):
def __init__(self, parent = None): def __init__(self):
QThread.__init__(self, parent) threading.Thread.__init__(self)
def setup(self,streamNumber): def setup(self,streamNumber):
self.streamNumber = streamNumber self.streamNumber = streamNumber
@ -73,7 +86,7 @@ class outgoingSynSender(QThread):
time.sleep(1) time.sleep(1)
global alreadyAttemptedConnectionsListResetTime global alreadyAttemptedConnectionsListResetTime
while True: while True:
#time.sleep(999999)#I sometimes use this to prevent connections for testing. time.sleep(999999)#I sometimes use this to prevent connections for testing.
if len(selfInitiatedConnections[self.streamNumber]) < 8: #maximum number of outgoing connections = 8 if len(selfInitiatedConnections[self.streamNumber]) < 8: #maximum number of outgoing connections = 8
random.seed() random.seed()
HOST, = random.sample(knownNodes[self.streamNumber], 1) HOST, = random.sample(knownNodes[self.streamNumber], 1)
@ -135,7 +148,8 @@ class outgoingSynSender(QThread):
try: try:
sock.connect((HOST, PORT)) sock.connect((HOST, PORT))
rd = receiveDataThread() rd = receiveDataThread()
self.emit(SIGNAL("passObjectThrough(PyQt_PyObject)"),rd) rd.daemon = True # close the main program even if there are threads left
#self.emit(SIGNAL("passObjectThrough(PyQt_PyObject)"),rd)
objectsOfWhichThisRemoteNodeIsAlreadyAware = {} objectsOfWhichThisRemoteNodeIsAlreadyAware = {}
rd.setup(sock,HOST,PORT,self.streamNumber,objectsOfWhichThisRemoteNodeIsAlreadyAware) rd.setup(sock,HOST,PORT,self.streamNumber,objectsOfWhichThisRemoteNodeIsAlreadyAware)
rd.start() rd.start()
@ -160,7 +174,8 @@ class outgoingSynSender(QThread):
knownNodesLock.release() knownNodesLock.release()
print 'deleting ', HOST, 'from knownNodes because it is more than 48 hours old and we could not connect to it.' print 'deleting ', HOST, 'from knownNodes because it is more than 48 hours old and we could not connect to it.'
except socks.Socks5AuthError, err: except socks.Socks5AuthError, err:
self.emit(SIGNAL("updateStatusBar(PyQt_PyObject)"),"SOCKS5 Authentication problem: "+str(err)) #self.emit(SIGNAL("updateStatusBar(PyQt_PyObject)"),"SOCKS5 Authentication problem: "+str(err))
UISignalQueue.put(('updateStatusBar',"SOCKS5 Authentication problem: "+str(err)))
except socks.Socks5Error, err: except socks.Socks5Error, err:
pass pass
print 'SOCKS5 error. (It is possible that the server wants authentication).)' ,str(err) print 'SOCKS5 error. (It is possible that the server wants authentication).)' ,str(err)
@ -188,9 +203,9 @@ class outgoingSynSender(QThread):
time.sleep(0.1) time.sleep(0.1)
#Only one singleListener thread will ever exist. It creates the receiveDataThread and sendDataThread for each incoming connection. Note that it cannot set the stream number because it is not known yet- the other node will have to tell us its stream number in a version message. If we don't care about their stream, we will close the connection (within the recversion function of the recieveData thread) #Only one singleListener thread will ever exist. It creates the receiveDataThread and sendDataThread for each incoming connection. Note that it cannot set the stream number because it is not known yet- the other node will have to tell us its stream number in a version message. If we don't care about their stream, we will close the connection (within the recversion function of the recieveData thread)
class singleListener(QThread): class singleListener(threading.Thread):
def __init__(self, parent = None): def __init__(self):
QThread.__init__(self, parent) threading.Thread.__init__(self)
def run(self): def run(self):
@ -219,7 +234,8 @@ class singleListener(QThread):
a.close() a.close()
a,(HOST,PORT) = sock.accept()""" a,(HOST,PORT) = sock.accept()"""
rd = receiveDataThread() rd = receiveDataThread()
self.emit(SIGNAL("passObjectThrough(PyQt_PyObject)"),rd) rd.daemon = True # close the main program even if there are threads left
#self.emit(SIGNAL("passObjectThrough(PyQt_PyObject)"),rd)
objectsOfWhichThisRemoteNodeIsAlreadyAware = {} objectsOfWhichThisRemoteNodeIsAlreadyAware = {}
rd.setup(a,HOST,PORT,-1,objectsOfWhichThisRemoteNodeIsAlreadyAware) rd.setup(a,HOST,PORT,-1,objectsOfWhichThisRemoteNodeIsAlreadyAware)
printLock.acquire() printLock.acquire()
@ -233,9 +249,9 @@ class singleListener(QThread):
#This thread is created either by the synSenderThread(for outgoing connections) or the singleListenerThread(for incoming connectiosn). #This thread is created either by the synSenderThread(for outgoing connections) or the singleListenerThread(for incoming connectiosn).
class receiveDataThread(QThread): class receiveDataThread(threading.Thread):
def __init__(self, parent = None): def __init__(self):
QThread.__init__(self, parent) threading.Thread.__init__(self)
self.data = '' self.data = ''
self.verackSent = False self.verackSent = False
self.verackReceived = False self.verackReceived = False
@ -304,7 +320,8 @@ class receiveDataThread(QThread):
if self.connectionIsOrWasFullyEstablished: #We don't want to decrement the number of connections and show the result if we never incremented it in the first place (which we only do if the connection is fully established- meaning that both nodes accepted each other's version packets.) if self.connectionIsOrWasFullyEstablished: #We don't want to decrement the number of connections and show the result if we never incremented it in the first place (which we only do if the connection is fully established- meaning that both nodes accepted each other's version packets.)
connectionsCountLock.acquire() connectionsCountLock.acquire()
connectionsCount[self.streamNumber] -= 1 connectionsCount[self.streamNumber] -= 1
self.emit(SIGNAL("updateNetworkStatusTab(PyQt_PyObject,PyQt_PyObject)"),self.streamNumber,connectionsCount[self.streamNumber]) #self.emit(SIGNAL("updateNetworkStatusTab(PyQt_PyObject,PyQt_PyObject)"),self.streamNumber,connectionsCount[self.streamNumber])
UISignalQueue.put(('updateNetworkStatusTab',(self.streamNumber,connectionsCount[self.streamNumber])))
printLock.acquire() printLock.acquire()
print 'Updating network status tab with current connections count:', connectionsCount[self.streamNumber] print 'Updating network status tab with current connections count:', connectionsCount[self.streamNumber]
printLock.release() printLock.release()
@ -438,11 +455,13 @@ class receiveDataThread(QThread):
def connectionFullyEstablished(self): def connectionFullyEstablished(self):
self.connectionIsOrWasFullyEstablished = True self.connectionIsOrWasFullyEstablished = True
if not self.initiatedConnection: if not self.initiatedConnection:
self.emit(SIGNAL("setStatusIcon(PyQt_PyObject)"),'green') #self.emit(SIGNAL("setStatusIcon(PyQt_PyObject)"),'green')
UISignalQueue.put(('setStatusIcon','green'))
#Update the 'Network Status' tab #Update the 'Network Status' tab
connectionsCountLock.acquire() connectionsCountLock.acquire()
connectionsCount[self.streamNumber] += 1 connectionsCount[self.streamNumber] += 1
self.emit(SIGNAL("updateNetworkStatusTab(PyQt_PyObject,PyQt_PyObject)"),self.streamNumber,connectionsCount[self.streamNumber]) #self.emit(SIGNAL("updateNetworkStatusTab(PyQt_PyObject,PyQt_PyObject)"),self.streamNumber,connectionsCount[self.streamNumber])
UISignalQueue.put(('updateNetworkStatusTab',(self.streamNumber,connectionsCount[self.streamNumber])))
connectionsCountLock.release() connectionsCountLock.release()
remoteNodeIncomingPort, remoteNodeSeenTime = knownNodes[self.streamNumber][self.HOST] remoteNodeIncomingPort, remoteNodeSeenTime = knownNodes[self.streamNumber][self.HOST]
printLock.acquire() printLock.acquire()
@ -570,7 +589,8 @@ class receiveDataThread(QThread):
inventory[self.inventoryHash] = (objectType, self.streamNumber, data, embeddedTime) inventory[self.inventoryHash] = (objectType, self.streamNumber, data, embeddedTime)
inventoryLock.release() inventoryLock.release()
self.broadcastinv(self.inventoryHash) self.broadcastinv(self.inventoryHash)
self.emit(SIGNAL("incrementNumberOfBroadcastsProcessed()")) #self.emit(SIGNAL("incrementNumberOfBroadcastsProcessed()"))
UISignalQueue.put(('incrementNumberOfBroadcastsProcessed','no data'))
self.processbroadcast(readPosition,data)#When this function returns, we will have either successfully processed this broadcast because we are interested in it, ignored it because we aren't interested in it, or found problem with the broadcast that warranted ignoring it. self.processbroadcast(readPosition,data)#When this function returns, we will have either successfully processed this broadcast because we are interested in it, ignored it because we aren't interested in it, or found problem with the broadcast that warranted ignoring it.
@ -698,7 +718,8 @@ class receiveDataThread(QThread):
sqlReturnQueue.get() sqlReturnQueue.get()
sqlSubmitQueue.put('commit') sqlSubmitQueue.put('commit')
sqlLock.release() sqlLock.release()
self.emit(SIGNAL("displayNewInboxMessage(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"),self.inventoryHash,toAddress,fromAddress,subject,body) #self.emit(SIGNAL("displayNewInboxMessage(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"),self.inventoryHash,toAddress,fromAddress,subject,body)
UISignalQueue.put(('displayNewInboxMessage',(self.inventoryHash,toAddress,fromAddress,subject,body)))
#If we are behaving as an API then we might need to run an outside command to let some program know that a new message has arrived. #If we are behaving as an API then we might need to run an outside command to let some program know that a new message has arrived.
if safeConfigGetBoolean('bitmessagesettings','apienabled'): if safeConfigGetBoolean('bitmessagesettings','apienabled'):
@ -829,7 +850,8 @@ class receiveDataThread(QThread):
sqlReturnQueue.get() sqlReturnQueue.get()
sqlSubmitQueue.put('commit') sqlSubmitQueue.put('commit')
sqlLock.release() sqlLock.release()
self.emit(SIGNAL("displayNewInboxMessage(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"),self.inventoryHash,toAddress,fromAddress,subject,body) #self.emit(SIGNAL("displayNewInboxMessage(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"),self.inventoryHash,toAddress,fromAddress,subject,body)
UISignalQueue.put(('displayNewInboxMessage',(self.inventoryHash,toAddress,fromAddress,subject,body)))
#If we are behaving as an API then we might need to run an outside command to let some program know that a new message has arrived. #If we are behaving as an API then we might need to run an outside command to let some program know that a new message has arrived.
if safeConfigGetBoolean('bitmessagesettings','apienabled'): if safeConfigGetBoolean('bitmessagesettings','apienabled'):
@ -890,7 +912,9 @@ class receiveDataThread(QThread):
inventory[self.inventoryHash] = (objectType, self.streamNumber, data, embeddedTime) inventory[self.inventoryHash] = (objectType, self.streamNumber, data, embeddedTime)
inventoryLock.release() inventoryLock.release()
self.broadcastinv(self.inventoryHash) self.broadcastinv(self.inventoryHash)
self.emit(SIGNAL("incrementNumberOfMessagesProcessed()")) #self.emit(SIGNAL("incrementNumberOfMessagesProcessed()"))
UISignalQueue.put(('incrementNumberOfMessagesProcessed','no data'))
self.processmsg(readPosition,data) #When this function returns, we will have either successfully processed the message bound for us, ignored it because it isn't bound for us, or found problem with the message that warranted ignoring it. self.processmsg(readPosition,data) #When this function returns, we will have either successfully processed the message bound for us, ignored it because it isn't bound for us, or found problem with the message that warranted ignoring it.
@ -932,7 +956,8 @@ class receiveDataThread(QThread):
sqlReturnQueue.get() sqlReturnQueue.get()
sqlSubmitQueue.put('commit') sqlSubmitQueue.put('commit')
sqlLock.release() sqlLock.release()
self.emit(SIGNAL("updateSentItemStatusByAckdata(PyQt_PyObject,PyQt_PyObject)"),encryptedData[readPosition:],'Acknowledgement of the message received just now.') #self.emit(SIGNAL("updateSentItemStatusByAckdata(PyQt_PyObject,PyQt_PyObject)"),encryptedData[readPosition:],'Acknowledgement of the message received just now.')
UISignalQueue.put(('updateSentItemStatusByAckdata',(encryptedData[readPosition:],'Acknowledgement of the message received just now.')))
return return
else: else:
printLock.acquire() printLock.acquire()
@ -1106,7 +1131,8 @@ class receiveDataThread(QThread):
sqlReturnQueue.get() sqlReturnQueue.get()
sqlSubmitQueue.put('commit') sqlSubmitQueue.put('commit')
sqlLock.release() sqlLock.release()
self.emit(SIGNAL("displayNewInboxMessage(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"),self.inventoryHash,toAddress,fromAddress,subject,body) #self.emit(SIGNAL("displayNewInboxMessage(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"),self.inventoryHash,toAddress,fromAddress,subject,body)
UISignalQueue.put(('displayNewInboxMessage',(self.inventoryHash,toAddress,fromAddress,subject,body)))
#If we are behaving as an API then we might need to run an outside command to let some program know that a new message has arrived. #If we are behaving as an API then we might need to run an outside command to let some program know that a new message has arrived.
if safeConfigGetBoolean('bitmessagesettings','apienabled'): if safeConfigGetBoolean('bitmessagesettings','apienabled'):
@ -1139,7 +1165,8 @@ class receiveDataThread(QThread):
sqlSubmitQueue.put('commit') sqlSubmitQueue.put('commit')
sqlLock.release() sqlLock.release()
self.emit(SIGNAL("displayNewSentMessage(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"),toAddress,'[Broadcast subscribers]',fromAddress,subject,message,ackdata) #self.emit(SIGNAL("displayNewSentMessage(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"),toAddress,'[Broadcast subscribers]',fromAddress,subject,message,ackdata)
UISignalQueue.put(('displayNewSentMessage',(toAddress,'[Broadcast subscribers]',fromAddress,subject,message,ackdata)))
workerQueue.put(('sendbroadcast',(fromAddress,subject,message))) workerQueue.put(('sendbroadcast',(fromAddress,subject,message)))
if self.isAckDataValid(ackData): if self.isAckDataValid(ackData):
@ -1232,7 +1259,8 @@ class receiveDataThread(QThread):
inventory[inventoryHash] = (objectType, self.streamNumber, data, embeddedTime) inventory[inventoryHash] = (objectType, self.streamNumber, data, embeddedTime)
inventoryLock.release() inventoryLock.release()
self.broadcastinv(inventoryHash) self.broadcastinv(inventoryHash)
self.emit(SIGNAL("incrementNumberOfPubkeysProcessed()")) #self.emit(SIGNAL("incrementNumberOfPubkeysProcessed()"))
UISignalQueue.put(('incrementNumberOfPubkeysProcessed','no data'))
self.processpubkey(data) self.processpubkey(data)
@ -1985,9 +2013,9 @@ class receiveDataThread(QThread):
return False return False
#Every connection to a peer has a sendDataThread (and also a receiveDataThread). #Every connection to a peer has a sendDataThread (and also a receiveDataThread).
class sendDataThread(QThread): class sendDataThread(threading.Thread):
def __init__(self, parent = None): def __init__(self):
QThread.__init__(self, parent) threading.Thread.__init__(self)
self.mailbox = Queue.Queue() self.mailbox = Queue.Queue()
sendDataQueues.append(self.mailbox) sendDataQueues.append(self.mailbox)
printLock.acquire() printLock.acquire()
@ -2236,6 +2264,55 @@ def safeConfigGetBoolean(section,field):
except: except:
return False return False
def signal_handler(signal, frame):
if safeConfigGetBoolean('bitmessagesettings','daemon'):
doCleanShutdown()
sys.exit(0)
else:
print 'Unfortunately you cannot use Ctrl+C when running the UI because the UI captures the signal.'
def doCleanShutdown():
UISignalQueue.put(('updateStatusBar','Bitmessage is stuck waiting for the knownNodesLock.'))
knownNodesLock.acquire()
UISignalQueue.put(('updateStatusBar','Saving the knownNodes list of peers to disk...'))
output = open(appdata + 'knownnodes.dat', 'wb')
print 'finished opening knownnodes.dat. Now pickle.dump'
pickle.dump(knownNodes, output)
print 'Completed pickle.dump. Closing output...'
output.close()
knownNodesLock.release()
print 'Finished closing knownnodes.dat output file.'
UISignalQueue.put(('updateStatusBar','Done saving the knownNodes list of peers to disk.'))
broadcastToSendDataQueues((0, 'shutdown', 'all'))
printLock.acquire()
print 'Flushing inventory in memory out to disk...'
printLock.release()
UISignalQueue.put(('updateStatusBar','Flushing inventory in memory out to disk. This should normally only take a second...'))
flushInventory()
print 'Finished flushing inventory.'
sqlSubmitQueue.put('exit')
if safeConfigGetBoolean('bitmessagesettings','daemon'):
printLock.acquire()
print 'Done.'
printLock.release()
os._exit(0)
def connectToStream(streamNumber):
#self.listOfOutgoingSynSenderThreads = [] #if we don't maintain this list, the threads will get garbage-collected.
connectionsCount[streamNumber] = 0
selfInitiatedConnections[streamNumber] = {}
for i in range(32):
a = outgoingSynSender()
#self.listOfOutgoingSynSenderThreads.append(a)
#QtCore.QObject.connect(a, QtCore.SIGNAL("passObjectThrough(PyQt_PyObject)"), self.connectObjectToSignals)
#QtCore.QObject.connect(a, QtCore.SIGNAL("updateStatusBar(PyQt_PyObject)"), self.updateStatusBar)
a.setup(streamNumber)
a.start()
#Does an EC point multiplication; turns a private key into a public key. #Does an EC point multiplication; turns a private key into a public key.
def pointMult(secret): def pointMult(secret):
#ctx = OpenSSL.BN_CTX_new() #This value proved to cause Seg Faults on Linux. It turns out that it really didn't speed up EC_POINT_mul anyway. #ctx = OpenSSL.BN_CTX_new() #This value proved to cause Seg Faults on Linux. It turns out that it really didn't speed up EC_POINT_mul anyway.
@ -2338,9 +2415,9 @@ def assembleVersionMessage(remoteHost,remotePort,myStreamNumber):
return datatosend + payload return datatosend + payload
#This thread exists because SQLITE3 is so un-threadsafe that we must submit queries to it and it puts results back in a different queue. They won't let us just use locks. #This thread exists because SQLITE3 is so un-threadsafe that we must submit queries to it and it puts results back in a different queue. They won't let us just use locks.
class sqlThread(QThread): class sqlThread(threading.Thread):
def __init__(self, parent = None): def __init__(self):
QThread.__init__(self, parent) threading.Thread.__init__(self)
def run(self): def run(self):
self.conn = sqlite3.connect(appdata + 'messages.dat' ) self.conn = sqlite3.connect(appdata + 'messages.dat' )
@ -2474,6 +2551,8 @@ class sqlThread(QThread):
item = sqlSubmitQueue.get() item = sqlSubmitQueue.get()
if item == 'commit': if item == 'commit':
self.conn.commit() self.conn.commit()
elif item == 'exit':
return
else: else:
parameters = sqlSubmitQueue.get() parameters = sqlSubmitQueue.get()
#print 'item', item #print 'item', item
@ -2497,16 +2576,17 @@ It resends messages when there has been no response:
resends msg messages in 4 days (then 8 days, then 16 days, etc...) resends msg messages in 4 days (then 8 days, then 16 days, etc...)
''' '''
class singleCleaner(QThread): class singleCleaner(threading.Thread):
def __init__(self, parent = None): def __init__(self):
QThread.__init__(self, parent) threading.Thread.__init__(self)
def run(self): def run(self):
timeWeLastClearedInventoryAndPubkeysTables = 0 timeWeLastClearedInventoryAndPubkeysTables = 0
while True: while True:
sqlLock.acquire() sqlLock.acquire()
self.emit(SIGNAL("updateStatusBar(PyQt_PyObject)"),"Doing housekeeping (Flushing inventory in memory to disk...)") #self.emit(SIGNAL("updateStatusBar(PyQt_PyObject)"),"Doing housekeeping (Flushing inventory in memory to disk...)")
UISignalQueue.put(('updateStatusBar','Doing housekeeping (Flushing inventory in memory to disk...)'))
for hash, storedValue in inventory.items(): for hash, storedValue in inventory.items():
objectType, streamNumber, payload, receivedTime = storedValue objectType, streamNumber, payload, receivedTime = storedValue
if int(time.time())- 3600 > receivedTime: if int(time.time())- 3600 > receivedTime:
@ -2516,7 +2596,8 @@ class singleCleaner(QThread):
sqlReturnQueue.get() sqlReturnQueue.get()
del inventory[hash] del inventory[hash]
sqlSubmitQueue.put('commit') sqlSubmitQueue.put('commit')
self.emit(SIGNAL("updateStatusBar(PyQt_PyObject)"),"") #self.emit(SIGNAL("updateStatusBar(PyQt_PyObject)"),"")
UISignalQueue.put(('updateStatusBar',''))
sqlLock.release() sqlLock.release()
broadcastToSendDataQueues((0, 'pong', 'no data')) #commands the sendData threads to send out a pong message if they haven't sent anything else in the last five minutes. The socket timeout-time is 10 minutes. broadcastToSendDataQueues((0, 'pong', 'no data')) #commands the sendData threads to send out a pong message if they haven't sent anything else in the last five minutes. The socket timeout-time is 10 minutes.
if timeWeLastClearedInventoryAndPubkeysTables < int(time.time()) - 7380: if timeWeLastClearedInventoryAndPubkeysTables < int(time.time()) - 7380:
@ -2550,7 +2631,8 @@ class singleCleaner(QThread):
except: except:
pass pass
workerQueue.put(('sendmessage',toaddress)) workerQueue.put(('sendmessage',toaddress))
self.emit(SIGNAL("updateStatusBar(PyQt_PyObject)"),"Doing work necessary to again attempt to request a public key...") #self.emit(SIGNAL("updateStatusBar(PyQt_PyObject)"),"Doing work necessary to again attempt to request a public key...")
UISignalQueue.put(('updateStatusBar','Doing work necessary to again attempt to request a public key...'))
t = (int(time.time()),pubkeyretrynumber+1,toripe) t = (int(time.time()),pubkeyretrynumber+1,toripe)
sqlSubmitQueue.put('''UPDATE sent SET lastactiontime=?, pubkeyretrynumber=? WHERE toripe=?''') sqlSubmitQueue.put('''UPDATE sent SET lastactiontime=?, pubkeyretrynumber=? WHERE toripe=?''')
sqlSubmitQueue.put(t) sqlSubmitQueue.put(t)
@ -2563,15 +2645,17 @@ class singleCleaner(QThread):
sqlSubmitQueue.put(t) sqlSubmitQueue.put(t)
sqlReturnQueue.get() sqlReturnQueue.get()
workerQueue.put(('sendmessage',toaddress)) workerQueue.put(('sendmessage',toaddress))
self.emit(SIGNAL("updateStatusBar(PyQt_PyObject)"),"Doing work necessary to again attempt to deliver a message...") #self.emit(SIGNAL("updateStatusBar(PyQt_PyObject)"),"Doing work necessary to again attempt to deliver a message...")
UISignalQueue.put(('updateStatusBar','Doing work necessary to again attempt to deliver a message...'))
sqlSubmitQueue.put('commit') sqlSubmitQueue.put('commit')
sqlLock.release() sqlLock.release()
time.sleep(300) time.sleep(300)
#This thread, of which there is only one, does the heavy lifting: calculating POWs. #This thread, of which there is only one, does the heavy lifting: calculating POWs.
class singleWorker(QThread): class singleWorker(threading.Thread):
def __init__(self, parent = None): def __init__(self):
QThread.__init__(self, parent) #QThread.__init__(self, parent)
threading.Thread.__init__(self)
def run(self): def run(self):
sqlLock.acquire() sqlLock.acquire()
@ -2643,7 +2727,9 @@ class singleWorker(QThread):
self.requestPubKey(toAddressVersionNumber,toStreamNumber,toRipe) self.requestPubKey(toAddressVersionNumber,toStreamNumber,toRipe)
else: else:
print 'We have already requested this pubkey (the ripe hash is in neededPubkeys). We will re-request again soon.' print 'We have already requested this pubkey (the ripe hash is in neededPubkeys). We will re-request again soon.'
self.emit(SIGNAL("updateSentItemStatusByHash(PyQt_PyObject,PyQt_PyObject)"),toRipe,'Public key was requested earlier. Receiver must be offline. Will retry.') #self.emit(SIGNAL("updateSentItemStatusByHash(PyQt_PyObject,PyQt_PyObject)"),toRipe,'Public key was requested earlier. Receiver must be offline. Will retry.')
UISignalQueue.put(('updateSentItemStatusByHash',(toRipe,'Public key was requested earlier. Receiver must be offline. Will retry.')))
else: else:
print 'We already have the necessary public key.' print 'We already have the necessary public key.'
self.sendMsg(toRipe) #by calling this function, we are asserting that we already have the pubkey for toRipe self.sendMsg(toRipe) #by calling this function, we are asserting that we already have the pubkey for toRipe
@ -2734,7 +2820,8 @@ class singleWorker(QThread):
print 'broadcasting inv with hash:', inventoryHash.encode('hex') print 'broadcasting inv with hash:', inventoryHash.encode('hex')
printLock.release() printLock.release()
broadcastToSendDataQueues((streamNumber, 'sendinv', inventoryHash)) broadcastToSendDataQueues((streamNumber, 'sendinv', inventoryHash))
self.emit(SIGNAL("updateStatusBar(PyQt_PyObject)"),"") #self.emit(SIGNAL("updateStatusBar(PyQt_PyObject)"),"")
UISignalQueue.put(('updateStatusBar',''))
config.set(myAddress,'lastpubkeysendtime',str(int(time.time()))) config.set(myAddress,'lastpubkeysendtime',str(int(time.time())))
with open(appdata + 'keys.dat', 'wb') as configfile: with open(appdata + 'keys.dat', 'wb') as configfile:
config.write(configfile) config.write(configfile)
@ -2799,7 +2886,8 @@ class singleWorker(QThread):
print 'broadcasting inv with hash:', inventoryHash.encode('hex') print 'broadcasting inv with hash:', inventoryHash.encode('hex')
printLock.release() printLock.release()
broadcastToSendDataQueues((streamNumber, 'sendinv', inventoryHash)) broadcastToSendDataQueues((streamNumber, 'sendinv', inventoryHash))
self.emit(SIGNAL("updateStatusBar(PyQt_PyObject)"),"") #self.emit(SIGNAL("updateStatusBar(PyQt_PyObject)"),"")
UISignalQueue.put(('updateStatusBar',''))
config.set(myAddress,'lastpubkeysendtime',str(int(time.time()))) config.set(myAddress,'lastpubkeysendtime',str(int(time.time())))
with open(appdata + 'keys.dat', 'wb') as configfile: with open(appdata + 'keys.dat', 'wb') as configfile:
config.write(configfile) config.write(configfile)
@ -2820,7 +2908,8 @@ class singleWorker(QThread):
privSigningKeyBase58 = config.get(fromaddress, 'privsigningkey') privSigningKeyBase58 = config.get(fromaddress, 'privsigningkey')
privEncryptionKeyBase58 = config.get(fromaddress, 'privencryptionkey') privEncryptionKeyBase58 = config.get(fromaddress, 'privencryptionkey')
except: except:
self.emit(SIGNAL("updateSentItemStatusByAckdata(PyQt_PyObject,PyQt_PyObject)"),ackdata,'Error! Could not find sender address (your address) in the keys.dat file.') #self.emit(SIGNAL("updateSentItemStatusByAckdata(PyQt_PyObject,PyQt_PyObject)"),ackdata,'Error! Could not find sender address (your address) in the keys.dat file.')
UISignalQueue.put(('updateSentItemStatusByAckdata',(ackdata,'Error! Could not find sender address (your address) in the keys.dat file.')))
continue continue
privSigningKeyHex = decodeWalletImportFormat(privSigningKeyBase58).encode('hex') privSigningKeyHex = decodeWalletImportFormat(privSigningKeyBase58).encode('hex')
@ -2849,7 +2938,8 @@ class singleWorker(QThread):
trialValue = 99999999999999999999 trialValue = 99999999999999999999
target = 2**64 / ((len(payload)+networkDefaultPayloadLengthExtraBytes+8) * networkDefaultProofOfWorkNonceTrialsPerByte) target = 2**64 / ((len(payload)+networkDefaultPayloadLengthExtraBytes+8) * networkDefaultProofOfWorkNonceTrialsPerByte)
print '(For broadcast message) Doing proof of work...' print '(For broadcast message) Doing proof of work...'
self.emit(SIGNAL("updateSentItemStatusByAckdata(PyQt_PyObject,PyQt_PyObject)"),ackdata,'Doing work necessary to send broadcast...') #self.emit(SIGNAL("updateSentItemStatusByAckdata(PyQt_PyObject,PyQt_PyObject)"),ackdata,'Doing work necessary to send broadcast...')
UISignalQueue.put(('updateSentItemStatusByAckdata',(ackdata,'Doing work necessary to send broadcast...')))
initialHash = hashlib.sha512(payload).digest() initialHash = hashlib.sha512(payload).digest()
while trialValue > target: while trialValue > target:
nonce += 1 nonce += 1
@ -2864,7 +2954,8 @@ class singleWorker(QThread):
print 'sending inv (within sendBroadcast function)' print 'sending inv (within sendBroadcast function)'
broadcastToSendDataQueues((streamNumber, 'sendinv', inventoryHash)) broadcastToSendDataQueues((streamNumber, 'sendinv', inventoryHash))
self.emit(SIGNAL("updateSentItemStatusByAckdata(PyQt_PyObject,PyQt_PyObject)"),ackdata,'Broadcast sent on '+unicode(strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(time.time()))),'utf-8')) #self.emit(SIGNAL("updateSentItemStatusByAckdata(PyQt_PyObject,PyQt_PyObject)"),ackdata,'Broadcast sent on '+unicode(strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(time.time()))),'utf-8'))
UISignalQueue.put(('updateSentItemStatusByAckdata',(ackdata,'Broadcast sent on '+unicode(strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(time.time()))),'utf-8'))))
#Update the status of the message in the 'sent' table to have a 'broadcastsent' status #Update the status of the message in the 'sent' table to have a 'broadcastsent' status
sqlLock.acquire() sqlLock.acquire()
@ -2880,7 +2971,8 @@ class singleWorker(QThread):
privSigningKeyBase58 = config.get(fromaddress, 'privsigningkey') privSigningKeyBase58 = config.get(fromaddress, 'privsigningkey')
privEncryptionKeyBase58 = config.get(fromaddress, 'privencryptionkey') privEncryptionKeyBase58 = config.get(fromaddress, 'privencryptionkey')
except: except:
self.emit(SIGNAL("updateSentItemStatusByAckdata(PyQt_PyObject,PyQt_PyObject)"),ackdata,'Error! Could not find sender address (your address) in the keys.dat file.') #self.emit(SIGNAL("updateSentItemStatusByAckdata(PyQt_PyObject,PyQt_PyObject)"),ackdata,'Error! Could not find sender address (your address) in the keys.dat file.')
UISignalQueue.put(('updateSentItemStatusByAckdata',(ackdata,'Error! Could not find sender address (your address) in the keys.dat file.')))
continue continue
privSigningKeyHex = decodeWalletImportFormat(privSigningKeyBase58).encode('hex') privSigningKeyHex = decodeWalletImportFormat(privSigningKeyBase58).encode('hex')
@ -2917,7 +3009,8 @@ class singleWorker(QThread):
trialValue = 99999999999999999999 trialValue = 99999999999999999999
target = 2**64 / ((len(payload)+networkDefaultPayloadLengthExtraBytes+8) * networkDefaultProofOfWorkNonceTrialsPerByte) target = 2**64 / ((len(payload)+networkDefaultPayloadLengthExtraBytes+8) * networkDefaultProofOfWorkNonceTrialsPerByte)
print '(For broadcast message) Doing proof of work...' print '(For broadcast message) Doing proof of work...'
self.emit(SIGNAL("updateSentItemStatusByAckdata(PyQt_PyObject,PyQt_PyObject)"),ackdata,'Doing work necessary to send broadcast...') #self.emit(SIGNAL("updateSentItemStatusByAckdata(PyQt_PyObject,PyQt_PyObject)"),ackdata,'Doing work necessary to send broadcast...')
UISignalQueue.put(('updateSentItemStatusByAckdata',(ackdata,'Doing work necessary to send broadcast...')))
initialHash = hashlib.sha512(payload).digest() initialHash = hashlib.sha512(payload).digest()
while trialValue > target: while trialValue > target:
nonce += 1 nonce += 1
@ -2932,7 +3025,8 @@ class singleWorker(QThread):
print 'sending inv (within sendBroadcast function)' print 'sending inv (within sendBroadcast function)'
broadcastToSendDataQueues((streamNumber, 'sendinv', inventoryHash)) broadcastToSendDataQueues((streamNumber, 'sendinv', inventoryHash))
self.emit(SIGNAL("updateSentItemStatusByAckdata(PyQt_PyObject,PyQt_PyObject)"),ackdata,'Broadcast sent on '+unicode(strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(time.time()))),'utf-8')) #self.emit(SIGNAL("updateSentItemStatusByAckdata(PyQt_PyObject,PyQt_PyObject)"),ackdata,'Broadcast sent on '+unicode(strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(time.time()))),'utf-8'))
UISignalQueue.put(('updateSentItemStatusByAckdata',(ackdata,'Broadcast sent on '+unicode(strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(time.time()))),'utf-8'))))
#Update the status of the message in the 'sent' table to have a 'broadcastsent' status #Update the status of the message in the 'sent' table to have a 'broadcastsent' status
sqlLock.acquire() sqlLock.acquire()
@ -2965,7 +3059,8 @@ class singleWorker(QThread):
ackdataForWhichImWatching[ackdata] = 0 ackdataForWhichImWatching[ackdata] = 0
toStatus,toAddressVersionNumber,toStreamNumber,toHash = decodeAddress(toaddress) toStatus,toAddressVersionNumber,toStreamNumber,toHash = decodeAddress(toaddress)
fromStatus,fromAddressVersionNumber,fromStreamNumber,fromHash = decodeAddress(fromaddress) fromStatus,fromAddressVersionNumber,fromStreamNumber,fromHash = decodeAddress(fromaddress)
self.emit(SIGNAL("updateSentItemStatusByAckdata(PyQt_PyObject,PyQt_PyObject)"),ackdata,'Doing work necessary to send the message.') #self.emit(SIGNAL("updateSentItemStatusByAckdata(PyQt_PyObject,PyQt_PyObject)"),ackdata,'Doing work necessary to send the message.')
UISignalQueue.put(('updateSentItemStatusByAckdata',(ackdata,'Doing work necessary to send the message.')))
printLock.acquire() printLock.acquire()
print 'Found a message in our database that needs to be sent with this pubkey.' print 'Found a message in our database that needs to be sent with this pubkey.'
print 'First 150 characters of message:', message[:150] print 'First 150 characters of message:', message[:150]
@ -2982,7 +3077,8 @@ class singleWorker(QThread):
privSigningKeyBase58 = config.get(fromaddress, 'privsigningkey') privSigningKeyBase58 = config.get(fromaddress, 'privsigningkey')
privEncryptionKeyBase58 = config.get(fromaddress, 'privencryptionkey') privEncryptionKeyBase58 = config.get(fromaddress, 'privencryptionkey')
except: except:
self.emit(SIGNAL("updateSentItemStatusByAckdata(PyQt_PyObject,PyQt_PyObject)"),ackdata,'Error! Could not find sender address (your address) in the keys.dat file.') #self.emit(SIGNAL("updateSentItemStatusByAckdata(PyQt_PyObject,PyQt_PyObject)"),ackdata,'Error! Could not find sender address (your address) in the keys.dat file.')
UISignalQueue.put(('updateSentItemStatusByAckdata',(ackdata,'Error! Could not find sender address (your address) in the keys.dat file.')))
continue continue
privSigningKeyHex = decodeWalletImportFormat(privSigningKeyBase58).encode('hex') privSigningKeyHex = decodeWalletImportFormat(privSigningKeyBase58).encode('hex')
@ -3017,7 +3113,8 @@ class singleWorker(QThread):
privSigningKeyBase58 = config.get(fromaddress, 'privsigningkey') privSigningKeyBase58 = config.get(fromaddress, 'privsigningkey')
privEncryptionKeyBase58 = config.get(fromaddress, 'privencryptionkey') privEncryptionKeyBase58 = config.get(fromaddress, 'privencryptionkey')
except: except:
self.emit(SIGNAL("updateSentItemStatusByAckdata(PyQt_PyObject,PyQt_PyObject)"),ackdata,'Error! Could not find sender address (your address) in the keys.dat file.') #self.emit(SIGNAL("updateSentItemStatusByAckdata(PyQt_PyObject,PyQt_PyObject)"),ackdata,'Error! Could not find sender address (your address) in the keys.dat file.')
UISignalQueue.put(('updateSentItemStatusByAckdata',(ackdata,'Error! Could not find sender address (your address) in the keys.dat file.')))
continue continue
privSigningKeyHex = decodeWalletImportFormat(privSigningKeyBase58).encode('hex') privSigningKeyHex = decodeWalletImportFormat(privSigningKeyBase58).encode('hex')
@ -3114,7 +3211,8 @@ class singleWorker(QThread):
inventoryHash = calculateInventoryHash(payload) inventoryHash = calculateInventoryHash(payload)
objectType = 'msg' objectType = 'msg'
inventory[inventoryHash] = (objectType, toStreamNumber, payload, int(time.time())) inventory[inventoryHash] = (objectType, toStreamNumber, payload, int(time.time()))
self.emit(SIGNAL("updateSentItemStatusByAckdata(PyQt_PyObject,PyQt_PyObject)"),ackdata,'Message sent. Waiting on acknowledgement. Sent on ' + unicode(strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(time.time()))),'utf-8')) #self.emit(SIGNAL("updateSentItemStatusByAckdata(PyQt_PyObject,PyQt_PyObject)"),ackdata,'Message sent. Waiting on acknowledgement. Sent on ' + unicode(strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(time.time()))),'utf-8'))
UISignalQueue.put(('updateSentItemStatusByAckdata',(ackdata,'Message sent. Waiting on acknowledgement. Sent on ' + unicode(strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(time.time()))),'utf-8'))))
print 'sending inv (within sendmsg function)' print 'sending inv (within sendmsg function)'
broadcastToSendDataQueues((streamNumber, 'sendinv', inventoryHash)) broadcastToSendDataQueues((streamNumber, 'sendinv', inventoryHash))
@ -3145,8 +3243,10 @@ class singleWorker(QThread):
trialValue = 99999999999999999999 trialValue = 99999999999999999999
#print 'trial value', trialValue #print 'trial value', trialValue
statusbar = 'Doing the computations necessary to request the recipient\'s public key.' statusbar = 'Doing the computations necessary to request the recipient\'s public key.'
self.emit(SIGNAL("updateStatusBar(PyQt_PyObject)"),statusbar) #self.emit(SIGNAL("updateStatusBar(PyQt_PyObject)"),statusbar)
self.emit(SIGNAL("updateSentItemStatusByHash(PyQt_PyObject,PyQt_PyObject)"),ripe,'Doing work necessary to request public key.') UISignalQueue.put(('updateStatusBar',statusbar))
#self.emit(SIGNAL("updateSentItemStatusByHash(PyQt_PyObject,PyQt_PyObject)"),ripe,'Doing work necessary to request public key.')
UISignalQueue.put(('updateSentItemStatusByHash',(ripe,'Doing work necessary to request public key.')))
print 'Doing proof-of-work necessary to send getpubkey message.' print 'Doing proof-of-work necessary to send getpubkey message.'
target = 2**64 / ((len(payload)+networkDefaultPayloadLengthExtraBytes+8) * networkDefaultProofOfWorkNonceTrialsPerByte) target = 2**64 / ((len(payload)+networkDefaultPayloadLengthExtraBytes+8) * networkDefaultProofOfWorkNonceTrialsPerByte)
initialHash = hashlib.sha512(payload).digest() initialHash = hashlib.sha512(payload).digest()
@ -3164,8 +3264,10 @@ class singleWorker(QThread):
print 'sending inv (for the getpubkey message)' print 'sending inv (for the getpubkey message)'
broadcastToSendDataQueues((streamNumber, 'sendinv', inventoryHash)) broadcastToSendDataQueues((streamNumber, 'sendinv', inventoryHash))
self.emit(SIGNAL("updateStatusBar(PyQt_PyObject)"),'Broacasting the public key request. This program will auto-retry if they are offline.') #self.emit(SIGNAL("updateStatusBar(PyQt_PyObject)"),'Broacasting the public key request. This program will auto-retry if they are offline.')
self.emit(SIGNAL("updateSentItemStatusByHash(PyQt_PyObject,PyQt_PyObject)"),ripe,'Sending public key request. Waiting for reply. Requested at ' + unicode(strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(time.time()))),'utf-8')) UISignalQueue.put(('updateStatusBar','Broacasting the public key request. This program will auto-retry if they are offline.'))
#self.emit(SIGNAL("updateSentItemStatusByHash(PyQt_PyObject,PyQt_PyObject)"),ripe,'Sending public key request. Waiting for reply. Requested at ' + unicode(strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(time.time()))),'utf-8'))
UISignalQueue.put(('updateSentItemStatusByHash',(ripe,'Sending public key request. Waiting for reply. Requested at ' + unicode(strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(time.time()))),'utf-8'))))
def generateFullAckMessage(self,ackdata,toStreamNumber,embeddedTime): def generateFullAckMessage(self,ackdata,toStreamNumber,embeddedTime):
nonce = 0 nonce = 0
@ -3194,121 +3296,46 @@ class singleWorker(QThread):
headerData += hashlib.sha512(payload).digest()[:4] headerData += hashlib.sha512(payload).digest()[:4]
return headerData + payload return headerData + payload
class addressGenerator(QThread): class addressGenerator(threading.Thread):
def __init__(self, parent = None): def __init__(self):
QThread.__init__(self, parent) #QThread.__init__(self, parent)
threading.Thread.__init__(self)
def setup(self,addressVersionNumber,streamNumber,label="(no label)",numberOfAddressesToMake=1,deterministicPassphrase="",eighteenByteRipe=False):
self.addressVersionNumber = addressVersionNumber
self.streamNumber = streamNumber
self.label = label
self.numberOfAddressesToMake = numberOfAddressesToMake
self.deterministicPassphrase = deterministicPassphrase
self.eighteenByteRipe = eighteenByteRipe
def run(self): def run(self):
if self.addressVersionNumber == 3: while True:
if self.deterministicPassphrase == "": addressVersionNumber,streamNumber,label,numberOfAddressesToMake,deterministicPassphrase,eighteenByteRipe, = addressGeneratorQueue.get()
statusbar = 'Generating one new address' if addressVersionNumber == 3:
self.emit(SIGNAL("updateStatusBar(PyQt_PyObject)"),statusbar) if deterministicPassphrase == "":
#This next section is a little bit strange. We're going to generate keys over and over until we #statusbar = 'Generating one new address'
#find one that starts with either \x00 or \x00\x00. Then when we pack them into a Bitmessage address, #self.emit(SIGNAL("updateStatusBar(PyQt_PyObject)"),statusbar)
#we won't store the \x00 or \x00\x00 bytes thus making the address shorter. UISignalQueue.put(('updateStatusBar','Generating one new address'))
startTime = time.time()
numberOfAddressesWeHadToMakeBeforeWeFoundOneWithTheCorrectRipePrefix = 0
potentialPrivSigningKey = OpenSSL.rand(32)
potentialPubSigningKey = pointMult(potentialPrivSigningKey)
while True:
numberOfAddressesWeHadToMakeBeforeWeFoundOneWithTheCorrectRipePrefix += 1
potentialPrivEncryptionKey = OpenSSL.rand(32)
potentialPubEncryptionKey = pointMult(potentialPrivEncryptionKey)
#print 'potentialPubSigningKey', potentialPubSigningKey.encode('hex')
#print 'potentialPubEncryptionKey', potentialPubEncryptionKey.encode('hex')
ripe = hashlib.new('ripemd160')
sha = hashlib.new('sha512')
sha.update(potentialPubSigningKey+potentialPubEncryptionKey)
ripe.update(sha.digest())
#print 'potential ripe.digest', ripe.digest().encode('hex')
if self.eighteenByteRipe:
if ripe.digest()[:2] == '\x00\x00':
break
else:
if ripe.digest()[:1] == '\x00':
break
print 'Generated address with ripe digest:', ripe.digest().encode('hex')
print 'Address generator calculated', numberOfAddressesWeHadToMakeBeforeWeFoundOneWithTheCorrectRipePrefix, 'addresses at', numberOfAddressesWeHadToMakeBeforeWeFoundOneWithTheCorrectRipePrefix/(time.time()-startTime),'addresses per second before finding one with the correct ripe-prefix.'
address = encodeAddress(3,self.streamNumber,ripe.digest())
#self.emit(SIGNAL("updateStatusBar(PyQt_PyObject)"),'Finished generating address. Writing to keys.dat')
#An excellent way for us to store our keys is in Wallet Import Format. Let us convert now.
#https://en.bitcoin.it/wiki/Wallet_import_format
privSigningKey = '\x80'+potentialPrivSigningKey
checksum = hashlib.sha256(hashlib.sha256(privSigningKey).digest()).digest()[0:4]
privSigningKeyWIF = arithmetic.changebase(privSigningKey + checksum,256,58)
#print 'privSigningKeyWIF',privSigningKeyWIF
privEncryptionKey = '\x80'+potentialPrivEncryptionKey
checksum = hashlib.sha256(hashlib.sha256(privEncryptionKey).digest()).digest()[0:4]
privEncryptionKeyWIF = arithmetic.changebase(privEncryptionKey + checksum,256,58)
#print 'privEncryptionKeyWIF',privEncryptionKeyWIF
config.add_section(address)
config.set(address,'label',self.label)
config.set(address,'enabled','true')
config.set(address,'decoy','false')
config.set(address,'noncetrialsperbyte',config.get('bitmessagesettings','defaultnoncetrialsperbyte'))
config.set(address,'payloadlengthextrabytes',config.get('bitmessagesettings','defaultpayloadlengthextrabytes'))
config.set(address,'privSigningKey',privSigningKeyWIF)
config.set(address,'privEncryptionKey',privEncryptionKeyWIF)
with open(appdata + 'keys.dat', 'wb') as configfile:
config.write(configfile)
#It may be the case that this address is being generated as a result of a call to the API. Let us put the result in the necessary queue.
apiAddressGeneratorReturnQueue.put(address)
self.emit(SIGNAL("updateStatusBar(PyQt_PyObject)"),'Done generating address. Doing work necessary to broadcast it...')
self.emit(SIGNAL("writeNewAddressToTable(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"),self.label,address,str(self.streamNumber))
reloadMyAddressHashes()
workerQueue.put(('doPOWForMyV3Pubkey',ripe.digest()))
else: #There is something in the deterministicPassphrase variable thus we are going to do this deterministically.
statusbar = 'Generating '+str(self.numberOfAddressesToMake) + ' new addresses.'
self.emit(SIGNAL("updateStatusBar(PyQt_PyObject)"),statusbar)
signingKeyNonce = 0
encryptionKeyNonce = 1
listOfNewAddressesToSendOutThroughTheAPI = [] #We fill out this list no matter what although we only need it if we end up passing the info to the API.
for i in range(self.numberOfAddressesToMake):
#This next section is a little bit strange. We're going to generate keys over and over until we #This next section is a little bit strange. We're going to generate keys over and over until we
#find one that has a RIPEMD hash that starts with either \x00 or \x00\x00. Then when we pack them #find one that starts with either \x00 or \x00\x00. Then when we pack them into a Bitmessage address,
#into a Bitmessage address, we won't store the \x00 or \x00\x00 bytes thus making the address shorter. #we won't store the \x00 or \x00\x00 bytes thus making the address shorter.
startTime = time.time() startTime = time.time()
numberOfAddressesWeHadToMakeBeforeWeFoundOneWithTheCorrectRipePrefix = 0 numberOfAddressesWeHadToMakeBeforeWeFoundOneWithTheCorrectRipePrefix = 0
potentialPrivSigningKey = OpenSSL.rand(32)
potentialPubSigningKey = pointMult(potentialPrivSigningKey)
while True: while True:
numberOfAddressesWeHadToMakeBeforeWeFoundOneWithTheCorrectRipePrefix += 1 numberOfAddressesWeHadToMakeBeforeWeFoundOneWithTheCorrectRipePrefix += 1
potentialPrivSigningKey = hashlib.sha512(self.deterministicPassphrase + encodeVarint(signingKeyNonce)).digest()[:32] potentialPrivEncryptionKey = OpenSSL.rand(32)
potentialPrivEncryptionKey = hashlib.sha512(self.deterministicPassphrase + encodeVarint(encryptionKeyNonce)).digest()[:32]
potentialPubSigningKey = pointMult(potentialPrivSigningKey)
potentialPubEncryptionKey = pointMult(potentialPrivEncryptionKey) potentialPubEncryptionKey = pointMult(potentialPrivEncryptionKey)
#print 'potentialPubSigningKey', potentialPubSigningKey.encode('hex') #print 'potentialPubSigningKey', potentialPubSigningKey.encode('hex')
#print 'potentialPubEncryptionKey', potentialPubEncryptionKey.encode('hex') #print 'potentialPubEncryptionKey', potentialPubEncryptionKey.encode('hex')
signingKeyNonce += 2
encryptionKeyNonce += 2
ripe = hashlib.new('ripemd160') ripe = hashlib.new('ripemd160')
sha = hashlib.new('sha512') sha = hashlib.new('sha512')
sha.update(potentialPubSigningKey+potentialPubEncryptionKey) sha.update(potentialPubSigningKey+potentialPubEncryptionKey)
ripe.update(sha.digest()) ripe.update(sha.digest())
#print 'potential ripe.digest', ripe.digest().encode('hex') #print 'potential ripe.digest', ripe.digest().encode('hex')
if self.eighteenByteRipe: if eighteenByteRipe:
if ripe.digest()[:2] == '\x00\x00': if ripe.digest()[:2] == '\x00\x00':
break break
else: else:
if ripe.digest()[:1] == '\x00': if ripe.digest()[:1] == '\x00':
break break
print 'Generated address with ripe digest:', ripe.digest().encode('hex')
print 'ripe.digest', ripe.digest().encode('hex') print 'Address generator calculated', numberOfAddressesWeHadToMakeBeforeWeFoundOneWithTheCorrectRipePrefix, 'addresses at', numberOfAddressesWeHadToMakeBeforeWeFoundOneWithTheCorrectRipePrefix/(time.time()-startTime),'addresses per second before finding one with the correct ripe-prefix.'
print 'Address generator calculated', numberOfAddressesWeHadToMakeBeforeWeFoundOneWithTheCorrectRipePrefix, 'addresses at', numberOfAddressesWeHadToMakeBeforeWeFoundOneWithTheCorrectRipePrefix/(time.time()-startTime),'keys per second.' address = encodeAddress(3,streamNumber,ripe.digest())
address = encodeAddress(3,self.streamNumber,ripe.digest())
#self.emit(SIGNAL("updateStatusBar(PyQt_PyObject)"),'Finished generating address. Writing to keys.dat') #self.emit(SIGNAL("updateStatusBar(PyQt_PyObject)"),'Finished generating address. Writing to keys.dat')
#An excellent way for us to store our keys is in Wallet Import Format. Let us convert now. #An excellent way for us to store our keys is in Wallet Import Format. Let us convert now.
@ -3316,34 +3343,110 @@ class addressGenerator(QThread):
privSigningKey = '\x80'+potentialPrivSigningKey privSigningKey = '\x80'+potentialPrivSigningKey
checksum = hashlib.sha256(hashlib.sha256(privSigningKey).digest()).digest()[0:4] checksum = hashlib.sha256(hashlib.sha256(privSigningKey).digest()).digest()[0:4]
privSigningKeyWIF = arithmetic.changebase(privSigningKey + checksum,256,58) privSigningKeyWIF = arithmetic.changebase(privSigningKey + checksum,256,58)
#print 'privSigningKeyWIF',privSigningKeyWIF
privEncryptionKey = '\x80'+potentialPrivEncryptionKey privEncryptionKey = '\x80'+potentialPrivEncryptionKey
checksum = hashlib.sha256(hashlib.sha256(privEncryptionKey).digest()).digest()[0:4] checksum = hashlib.sha256(hashlib.sha256(privEncryptionKey).digest()).digest()[0:4]
privEncryptionKeyWIF = arithmetic.changebase(privEncryptionKey + checksum,256,58) privEncryptionKeyWIF = arithmetic.changebase(privEncryptionKey + checksum,256,58)
#print 'privEncryptionKeyWIF',privEncryptionKeyWIF
try: config.add_section(address)
config.add_section(address) config.set(address,'label',label)
print 'label:', self.label config.set(address,'enabled','true')
config.set(address,'label',self.label) config.set(address,'decoy','false')
config.set(address,'enabled','true') config.set(address,'noncetrialsperbyte',config.get('bitmessagesettings','defaultnoncetrialsperbyte'))
config.set(address,'decoy','false') config.set(address,'payloadlengthextrabytes',config.get('bitmessagesettings','defaultpayloadlengthextrabytes'))
config.set(address,'noncetrialsperbyte',config.get('bitmessagesettings','defaultnoncetrialsperbyte')) config.set(address,'privSigningKey',privSigningKeyWIF)
config.set(address,'payloadlengthextrabytes',config.get('bitmessagesettings','defaultpayloadlengthextrabytes')) config.set(address,'privEncryptionKey',privEncryptionKeyWIF)
config.set(address,'privSigningKey',privSigningKeyWIF) with open(appdata + 'keys.dat', 'wb') as configfile:
config.set(address,'privEncryptionKey',privEncryptionKeyWIF) config.write(configfile)
with open(appdata + 'keys.dat', 'wb') as configfile:
config.write(configfile)
self.emit(SIGNAL("writeNewAddressToTable(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"),self.label,address,str(self.streamNumber)) #It may be the case that this address is being generated as a result of a call to the API. Let us put the result in the necessary queue.
listOfNewAddressesToSendOutThroughTheAPI.append(address) apiAddressGeneratorReturnQueue.put(address)
if self.eighteenByteRipe:
reloadMyAddressHashes()#This is necessary here (rather than just at the end) because otherwise if the human generates a large number of new addresses and uses one before they are done generating, the program will receive a getpubkey message and will ignore it. #self.emit(SIGNAL("updateStatusBar(PyQt_PyObject)"),'Done generating address. Doing work necessary to broadcast it...')
except: UISignalQueue.put(('updateStatusBar','Done generating address. Doing work necessary to broadcast it...'))
print address,'already exists. Not adding it again.' #self.emit(SIGNAL("writeNewAddressToTable(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"),self.label,address,str(streamNumber))
#It may be the case that this address is being generated as a result of a call to the API. Let us put the result in the necessary queue. UISignalQueue.put(('writeNewAddressToTable',(label,address,streamNumber)))
apiAddressGeneratorReturnQueue.put(listOfNewAddressesToSendOutThroughTheAPI) reloadMyAddressHashes()
self.emit(SIGNAL("updateStatusBar(PyQt_PyObject)"),'Done generating address') workerQueue.put(('doPOWForMyV3Pubkey',ripe.digest()))
reloadMyAddressHashes()
else: #There is something in the deterministicPassphrase variable thus we are going to do this deterministically.
statusbar = 'Generating '+str(numberOfAddressesToMake) + ' new addresses.'
#self.emit(SIGNAL("updateStatusBar(PyQt_PyObject)"),statusbar)
UISignalQueue.put(('updateStatusBar',statusbar))
signingKeyNonce = 0
encryptionKeyNonce = 1
listOfNewAddressesToSendOutThroughTheAPI = [] #We fill out this list no matter what although we only need it if we end up passing the info to the API.
for i in range(numberOfAddressesToMake):
#This next section is a little bit strange. We're going to generate keys over and over until we
#find one that has a RIPEMD hash that starts with either \x00 or \x00\x00. Then when we pack them
#into a Bitmessage address, we won't store the \x00 or \x00\x00 bytes thus making the address shorter.
startTime = time.time()
numberOfAddressesWeHadToMakeBeforeWeFoundOneWithTheCorrectRipePrefix = 0
while True:
numberOfAddressesWeHadToMakeBeforeWeFoundOneWithTheCorrectRipePrefix += 1
potentialPrivSigningKey = hashlib.sha512(deterministicPassphrase + encodeVarint(signingKeyNonce)).digest()[:32]
potentialPrivEncryptionKey = hashlib.sha512(deterministicPassphrase + encodeVarint(encryptionKeyNonce)).digest()[:32]
potentialPubSigningKey = pointMult(potentialPrivSigningKey)
potentialPubEncryptionKey = pointMult(potentialPrivEncryptionKey)
#print 'potentialPubSigningKey', potentialPubSigningKey.encode('hex')
#print 'potentialPubEncryptionKey', potentialPubEncryptionKey.encode('hex')
signingKeyNonce += 2
encryptionKeyNonce += 2
ripe = hashlib.new('ripemd160')
sha = hashlib.new('sha512')
sha.update(potentialPubSigningKey+potentialPubEncryptionKey)
ripe.update(sha.digest())
#print 'potential ripe.digest', ripe.digest().encode('hex')
if eighteenByteRipe:
if ripe.digest()[:2] == '\x00\x00':
break
else:
if ripe.digest()[:1] == '\x00':
break
print 'ripe.digest', ripe.digest().encode('hex')
print 'Address generator calculated', numberOfAddressesWeHadToMakeBeforeWeFoundOneWithTheCorrectRipePrefix, 'addresses at', numberOfAddressesWeHadToMakeBeforeWeFoundOneWithTheCorrectRipePrefix/(time.time()-startTime),'keys per second.'
address = encodeAddress(3,streamNumber,ripe.digest())
#self.emit(SIGNAL("updateStatusBar(PyQt_PyObject)"),'Finished generating address. Writing to keys.dat')
#An excellent way for us to store our keys is in Wallet Import Format. Let us convert now.
#https://en.bitcoin.it/wiki/Wallet_import_format
privSigningKey = '\x80'+potentialPrivSigningKey
checksum = hashlib.sha256(hashlib.sha256(privSigningKey).digest()).digest()[0:4]
privSigningKeyWIF = arithmetic.changebase(privSigningKey + checksum,256,58)
privEncryptionKey = '\x80'+potentialPrivEncryptionKey
checksum = hashlib.sha256(hashlib.sha256(privEncryptionKey).digest()).digest()[0:4]
privEncryptionKeyWIF = arithmetic.changebase(privEncryptionKey + checksum,256,58)
try:
config.add_section(address)
print 'label:', label
config.set(address,'label',label)
config.set(address,'enabled','true')
config.set(address,'decoy','false')
config.set(address,'noncetrialsperbyte',config.get('bitmessagesettings','defaultnoncetrialsperbyte'))
config.set(address,'payloadlengthextrabytes',config.get('bitmessagesettings','defaultpayloadlengthextrabytes'))
config.set(address,'privSigningKey',privSigningKeyWIF)
config.set(address,'privEncryptionKey',privEncryptionKeyWIF)
with open(appdata + 'keys.dat', 'wb') as configfile:
config.write(configfile)
#self.emit(SIGNAL("writeNewAddressToTable(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"),self.label,address,str(self.streamNumber))
UISignalQueue.put(('writeNewAddressToTable',(label,address,str(streamNumber))))
listOfNewAddressesToSendOutThroughTheAPI.append(address)
if eighteenByteRipe:
reloadMyAddressHashes()#This is necessary here (rather than just at the end) because otherwise if the human generates a large number of new addresses and uses one before they are done generating, the program will receive a getpubkey message and will ignore it.
except:
print address,'already exists. Not adding it again.'
#It may be the case that this address is being generated as a result of a call to the API. Let us put the result in the necessary queue.
apiAddressGeneratorReturnQueue.put(listOfNewAddressesToSendOutThroughTheAPI)
#self.emit(SIGNAL("updateStatusBar(PyQt_PyObject)"),'Done generating address')
UISignalQueue.put(('updateStatusBar','Done generating address'))
reloadMyAddressHashes()
#This is one of several classes that constitute the API #This is one of several classes that constitute the API
@ -3441,7 +3544,8 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
return a+b return a+b
elif method == 'statusBar': elif method == 'statusBar':
message, = params message, = params
apiSignalQueue.put(('updateStatusBar',message)) #apiSignalQueue.put(('updateStatusBar',message))
UISignalQueue.put(('updateStatusBar',message))
elif method == 'listAddresses': elif method == 'listAddresses':
data = '{"addresses":[' data = '{"addresses":['
configSections = config.sections() configSections = config.sections()
@ -3464,7 +3568,9 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
label, eighteenByteRipe = params label, eighteenByteRipe = params
label = label.decode('base64') label = label.decode('base64')
apiAddressGeneratorReturnQueue.queue.clear() apiAddressGeneratorReturnQueue.queue.clear()
apiSignalQueue.put(('createRandomAddress',(label, eighteenByteRipe))) #params should be a twopul which equals (eighteenByteRipe, label) streamNumberForAddress = 1
#apiSignalQueue.put(('createRandomAddress',(label, eighteenByteRipe))) #params should be a twopul which equals (eighteenByteRipe, label)
addressGeneratorQueue.put((3,streamNumberForAddress,label,1,"",eighteenByteRipe))
return apiAddressGeneratorReturnQueue.get() return apiAddressGeneratorReturnQueue.get()
elif method == 'createDeterministicAddresses': elif method == 'createDeterministicAddresses':
if len(params) == 0: if len(params) == 0:
@ -3506,7 +3612,8 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
return 'API Error 0005: You have (accidentially?) specified too many addresses to make. Maximum 9999. This check only exists to prevent mischief; if you really want to create more addresses than this, contact the Bitmessage developers and we can modify the check or you can do it yourself by searching the source code for this message.' return 'API Error 0005: You have (accidentially?) specified too many addresses to make. Maximum 9999. This check only exists to prevent mischief; if you really want to create more addresses than this, contact the Bitmessage developers and we can modify the check or you can do it yourself by searching the source code for this message.'
apiAddressGeneratorReturnQueue.queue.clear() apiAddressGeneratorReturnQueue.queue.clear()
print 'about to send numberOfAddresses', numberOfAddresses print 'about to send numberOfAddresses', numberOfAddresses
apiSignalQueue.put(('createDeterministicAddresses',(passphrase, numberOfAddresses, addressVersionNumber, streamNumber, eighteenByteRipe))) #apiSignalQueue.put(('createDeterministicAddresses',(passphrase, numberOfAddresses, addressVersionNumber, streamNumber, eighteenByteRipe)))
addressGeneratorQueue.put((addressVersionNumber,streamNumber,'unused API address',numberOfAddresses,passphrase,eighteenByteRipe))
data = '{"addresses":[' data = '{"addresses":['
queueReturn = apiAddressGeneratorReturnQueue.get() queueReturn = apiAddressGeneratorReturnQueue.get()
for item in queueReturn: for item in queueReturn:
@ -3540,7 +3647,8 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
sqlReturnQueue.get() sqlReturnQueue.get()
sqlSubmitQueue.put('commit') sqlSubmitQueue.put('commit')
sqlLock.release() sqlLock.release()
apiSignalQueue.put(('updateStatusBar','Per API: Trashed message (assuming message existed). UI not updated.')) #apiSignalQueue.put(('updateStatusBar','Per API: Trashed message (assuming message existed). UI not updated.'))
UISignalQueue.put(('updateStatusBar','Per API: Trashed message (assuming message existed). UI not updated.'))
return 'Trashed message (assuming message existed). UI not updated. To double check, run getAllInboxMessages to see that the message disappeared, or restart Bitmessage and look in the normal Bitmessage GUI.' return 'Trashed message (assuming message existed). UI not updated. To double check, run getAllInboxMessages to see that the message disappeared, or restart Bitmessage and look in the normal Bitmessage GUI.'
elif method == 'sendMessage': elif method == 'sendMessage':
if len(params) == 0: if len(params) == 0:
@ -3664,8 +3772,9 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
sqlLock.release() sqlLock.release()
toLabel = '[Broadcast subscribers]' toLabel = '[Broadcast subscribers]'
apiSignalQueue.put(('displayNewSentMessage',(toAddress,toLabel,fromAddress,subject,message,ackdata))) #apiSignalQueue.put(('displayNewSentMessage',(toAddress,toLabel,fromAddress,subject,message,ackdata)))
#self.emit(SIGNAL("displayNewSentMessage(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"),toAddress,toLabel,fromAddress,subject,message,ackdata)
UISignalQueue.put(('displayNewSentMessage',(toAddress,toLabel,fromAddress,subject,message,ackdata)))
workerQueue.put(('sendbroadcast',(fromAddress,subject,message))) workerQueue.put(('sendbroadcast',(fromAddress,subject,message)))
return ackdata.encode('hex') return ackdata.encode('hex')
@ -3674,202 +3783,65 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
return 'Invalid Method: %s'%method return 'Invalid Method: %s'%method
#This thread, of which there is only one, runs the API. #This thread, of which there is only one, runs the API.
class singleAPI(QThread): class singleAPI(threading.Thread):
def __init__(self, parent = None): def __init__(self):
QThread.__init__(self, parent) threading.Thread.__init__(self)
def run(self): def run(self):
se = SimpleXMLRPCServer((config.get('bitmessagesettings', 'apiinterface'),config.getint('bitmessagesettings', 'apiport')), MySimpleXMLRPCRequestHandler, True, True) se = SimpleXMLRPCServer((config.get('bitmessagesettings', 'apiinterface'),config.getint('bitmessagesettings', 'apiport')), MySimpleXMLRPCRequestHandler, True, True)
se.register_introspection_functions() se.register_introspection_functions()
se.serve_forever() se.serve_forever()
#The MySimpleXMLRPCRequestHandler class cannot emit signals (or at least I don't know how) because it is not a QT thread. It therefore puts data in a queue which this thread monitors and emits the signals on its behalf.
class singleAPISignalHandler(QThread):
class UISignaler(QThread):
def __init__(self, parent = None): def __init__(self, parent = None):
QThread.__init__(self, parent) QThread.__init__(self, parent)
def run(self): def run(self):
while True: while True:
command, data = apiSignalQueue.get() command, data = UISignalQueue.get()
if command == 'updateStatusBar': if not safeConfigGetBoolean('bitmessagesettings','daemon'):
self.emit(SIGNAL("updateStatusBar(PyQt_PyObject)"),data) if command == 'writeNewAddressToTable':
elif command == 'createRandomAddress': label, address, streamNumber = data
label, eighteenByteRipe = data self.emit(SIGNAL("writeNewAddressToTable(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"),label,address,str(streamNumber))
streamNumberForAddress = 1 elif command == 'updateStatusBar':
self.addressGenerator = addressGenerator() self.emit(SIGNAL("updateStatusBar(PyQt_PyObject)"),data)
self.addressGenerator.setup(3,streamNumberForAddress,label,1,"",eighteenByteRipe) elif command == 'updateSentItemStatusByHash':
self.emit(SIGNAL("passAddressGeneratorObjectThrough(PyQt_PyObject)"),self.addressGenerator) hash, message = data
self.addressGenerator.start() self.emit(SIGNAL("updateSentItemStatusByHash(PyQt_PyObject,PyQt_PyObject)"),hash,message)
elif command == 'createDeterministicAddresses': elif command == 'updateSentItemStatusByAckdata':
passphrase, numberOfAddresses, addressVersionNumber, streamNumber, eighteenByteRipe = data ackData, message = data
self.addressGenerator = addressGenerator() self.emit(SIGNAL("updateSentItemStatusByAckdata(PyQt_PyObject,PyQt_PyObject)"),ackData,message)
self.addressGenerator.setup(addressVersionNumber,streamNumber,'unused API address',numberOfAddresses,passphrase,eighteenByteRipe) elif command == 'displayNewInboxMessage':
self.emit(SIGNAL("passAddressGeneratorObjectThrough(PyQt_PyObject)"),self.addressGenerator) inventoryHash,toAddress,fromAddress,subject,body = data
self.addressGenerator.start() self.emit(SIGNAL("displayNewInboxMessage(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"),inventoryHash,toAddress,fromAddress,subject,body)
elif command == 'displayNewSentMessage': elif command == 'displayNewSentMessage':
toAddress,toLabel,fromAddress,subject,message,ackdata = data toAddress,fromLabel,fromAddress,subject,message,ackdata = data
self.emit(SIGNAL("displayNewSentMessage(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"),toAddress,toLabel,fromAddress,subject,message,ackdata) self.emit(SIGNAL("displayNewSentMessage(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"),toAddress,fromLabel,fromAddress,subject,message,ackdata)
elif command == 'updateNetworkStatusTab':
streamNumber,count = data
self.emit(SIGNAL("updateNetworkStatusTab(PyQt_PyObject,PyQt_PyObject)"),streamNumber,count)
elif command == 'incrementNumberOfMessagesProcessed':
self.emit(SIGNAL("incrementNumberOfMessagesProcessed()"))
elif command == 'incrementNumberOfPubkeysProcessed':
self.emit(SIGNAL("incrementNumberOfPubkeysProcessed()"))
elif command == 'incrementNumberOfBroadcastsProcessed':
self.emit(SIGNAL("incrementNumberOfBroadcastsProcessed()"))
elif command == 'setStatusIcon':
self.emit(SIGNAL("setStatusIcon(PyQt_PyObject)"),data)
else:
sys.stderr.write('Command sent to UISignaler not recognized: %s\n' % command)
class iconGlossaryDialog(QtGui.QDialog):
def __init__(self,parent):
QtGui.QWidget.__init__(self, parent)
self.ui = Ui_iconGlossaryDialog()
self.ui.setupUi(self)
self.parent = parent
self.ui.labelPortNumber.setText('You are using TCP port ' + str(config.getint('bitmessagesettings', 'port')) + '. (This can be changed in the settings).')
QtGui.QWidget.resize(self,QtGui.QWidget.sizeHint(self))
class helpDialog(QtGui.QDialog): #In order for the time columns on the Inbox and Sent tabs to be sorted correctly (rather than alphabetically), we need to overload the < operator and use this class instead of QTableWidgetItem.
def __init__(self,parent): class myTableWidgetItem(QTableWidgetItem):
QtGui.QWidget.__init__(self, parent) def __lt__(self,other):
self.ui = Ui_helpDialog() return int(self.data(33).toPyObject()) < int(other.data(33).toPyObject())
self.ui.setupUi(self)
self.parent = parent
self.ui.labelHelpURI.setOpenExternalLinks(True)
QtGui.QWidget.resize(self,QtGui.QWidget.sizeHint(self))
class aboutDialog(QtGui.QDialog): ##cut from here
def __init__(self,parent):
QtGui.QWidget.__init__(self, parent)
self.ui = Ui_aboutDialog()
self.ui.setupUi(self)
self.parent = parent
self.ui.labelVersion.setText('version ' + softwareVersion)
class regenerateAddressesDialog(QtGui.QDialog):
def __init__(self,parent):
QtGui.QWidget.__init__(self, parent)
self.ui = Ui_regenerateAddressesDialog()
self.ui.setupUi(self)
self.parent = parent
QtGui.QWidget.resize(self,QtGui.QWidget.sizeHint(self))
class settingsDialog(QtGui.QDialog):
def __init__(self,parent):
QtGui.QWidget.__init__(self, parent)
self.ui = Ui_settingsDialog()
self.ui.setupUi(self)
self.parent = parent
self.ui.checkBoxStartOnLogon.setChecked(config.getboolean('bitmessagesettings', 'startonlogon'))
self.ui.checkBoxMinimizeToTray.setChecked(config.getboolean('bitmessagesettings', 'minimizetotray'))
self.ui.checkBoxShowTrayNotifications.setChecked(config.getboolean('bitmessagesettings', 'showtraynotifications'))
self.ui.checkBoxStartInTray.setChecked(config.getboolean('bitmessagesettings', 'startintray'))
if appdata == '':
self.ui.checkBoxPortableMode.setChecked(True)
if 'darwin' in sys.platform:
self.ui.checkBoxStartOnLogon.setDisabled(True)
self.ui.checkBoxMinimizeToTray.setDisabled(True)
self.ui.checkBoxShowTrayNotifications.setDisabled(True)
self.ui.checkBoxStartInTray.setDisabled(True)
self.ui.labelSettingsNote.setText('Options have been disabled because they either arn\'t applicable or because they haven\'t yet been implimented for your operating system.')
elif 'linux' in sys.platform:
self.ui.checkBoxStartOnLogon.setDisabled(True)
self.ui.checkBoxMinimizeToTray.setDisabled(True)
self.ui.checkBoxStartInTray.setDisabled(True)
self.ui.labelSettingsNote.setText('Options have been disabled because they either arn\'t applicable or because they haven\'t yet been implimented for your operating system.')
#On the Network settings tab:
self.ui.lineEditTCPPort.setText(str(config.get('bitmessagesettings', 'port')))
self.ui.checkBoxAuthentication.setChecked(config.getboolean('bitmessagesettings', 'socksauthentication'))
if str(config.get('bitmessagesettings', 'socksproxytype')) == 'none':
self.ui.comboBoxProxyType.setCurrentIndex(0)
self.ui.lineEditSocksHostname.setEnabled(False)
self.ui.lineEditSocksPort.setEnabled(False)
self.ui.lineEditSocksUsername.setEnabled(False)
self.ui.lineEditSocksPassword.setEnabled(False)
self.ui.checkBoxAuthentication.setEnabled(False)
elif str(config.get('bitmessagesettings', 'socksproxytype')) == 'SOCKS4a':
self.ui.comboBoxProxyType.setCurrentIndex(1)
self.ui.lineEditTCPPort.setEnabled(False)
elif str(config.get('bitmessagesettings', 'socksproxytype')) == 'SOCKS5':
self.ui.comboBoxProxyType.setCurrentIndex(2)
self.ui.lineEditTCPPort.setEnabled(False)
self.ui.lineEditSocksHostname.setText(str(config.get('bitmessagesettings', 'sockshostname')))
self.ui.lineEditSocksPort.setText(str(config.get('bitmessagesettings', 'socksport')))
self.ui.lineEditSocksUsername.setText(str(config.get('bitmessagesettings', 'socksusername')))
self.ui.lineEditSocksPassword.setText(str(config.get('bitmessagesettings', 'sockspassword')))
QtCore.QObject.connect(self.ui.comboBoxProxyType, QtCore.SIGNAL("currentIndexChanged(int)"), self.comboBoxProxyTypeChanged)
self.ui.lineEditTotalDifficulty.setText(str((float(config.getint('bitmessagesettings', 'defaultnoncetrialsperbyte'))/networkDefaultProofOfWorkNonceTrialsPerByte)))
self.ui.lineEditSmallMessageDifficulty.setText(str((float(config.getint('bitmessagesettings', 'defaultpayloadlengthextrabytes'))/networkDefaultPayloadLengthExtraBytes)))
QtGui.QWidget.resize(self,QtGui.QWidget.sizeHint(self))
def comboBoxProxyTypeChanged(self,comboBoxIndex):
if comboBoxIndex == 0:
self.ui.lineEditSocksHostname.setEnabled(False)
self.ui.lineEditSocksPort.setEnabled(False)
self.ui.lineEditSocksUsername.setEnabled(False)
self.ui.lineEditSocksPassword.setEnabled(False)
self.ui.checkBoxAuthentication.setEnabled(False)
self.ui.lineEditTCPPort.setEnabled(True)
elif comboBoxIndex == 1 or comboBoxIndex == 2:
self.ui.lineEditSocksHostname.setEnabled(True)
self.ui.lineEditSocksPort.setEnabled(True)
self.ui.checkBoxAuthentication.setEnabled(True)
if self.ui.checkBoxAuthentication.isChecked():
self.ui.lineEditSocksUsername.setEnabled(True)
self.ui.lineEditSocksPassword.setEnabled(True)
self.ui.lineEditTCPPort.setEnabled(False)
class SpecialAddressBehaviorDialog(QtGui.QDialog):
def __init__(self,parent):
QtGui.QWidget.__init__(self, parent)
self.ui = Ui_SpecialAddressBehaviorDialog()
self.ui.setupUi(self)
self.parent = parent
currentRow = parent.ui.tableWidgetYourIdentities.currentRow()
addressAtCurrentRow = str(parent.ui.tableWidgetYourIdentities.item(currentRow,1).text())
if safeConfigGetBoolean(addressAtCurrentRow,'mailinglist'):
self.ui.radioButtonBehaviorMailingList.click()
else:
self.ui.radioButtonBehaveNormalAddress.click()
try:
mailingListName = config.get(addressAtCurrentRow, 'mailinglistname')
except:
mailingListName = ''
self.ui.lineEditMailingListName.setText(unicode(mailingListName,'utf-8'))
QtGui.QWidget.resize(self,QtGui.QWidget.sizeHint(self))
class NewSubscriptionDialog(QtGui.QDialog):
def __init__(self,parent):
QtGui.QWidget.__init__(self, parent)
self.ui = Ui_NewSubscriptionDialog()
self.ui.setupUi(self)
self.parent = parent
QtCore.QObject.connect(self.ui.lineEditSubscriptionAddress, QtCore.SIGNAL("textChanged(QString)"), self.subscriptionAddressChanged)
def subscriptionAddressChanged(self,QString):
status,a,b,c = decodeAddress(str(QString))
if status == 'missingbm':
self.ui.labelSubscriptionAddressCheck.setText('The address should start with ''BM-''')
elif status == 'checksumfailed':
self.ui.labelSubscriptionAddressCheck.setText('The address is not typed or copied correctly (the checksum failed).')
elif status == 'versiontoohigh':
self.ui.labelSubscriptionAddressCheck.setText('The version number of this address is higher than this software can support. Please upgrade Bitmessage.')
elif status == 'invalidcharacters':
self.ui.labelSubscriptionAddressCheck.setText('The address contains invalid characters.')
elif status == 'ripetooshort':
self.ui.labelSubscriptionAddressCheck.setText('Some data encoded in the address is too short.')
elif status == 'ripetoolong':
self.ui.labelSubscriptionAddressCheck.setText('Some data encoded in the address is too long.')
elif status == 'success':
self.ui.labelSubscriptionAddressCheck.setText('Address is valid.')
class NewAddressDialog(QtGui.QDialog):
def __init__(self, parent):
QtGui.QWidget.__init__(self, parent)
self.ui = Ui_NewAddressDialog()
self.ui.setupUi(self)
self.parent = parent
row = 1
#Let's fill out the 'existing address' combo box with addresses from the 'Your Identities' tab.
while self.parent.ui.tableWidgetYourIdentities.item(row-1,1):
self.ui.radioButtonExisting.click()
#print self.parent.ui.tableWidgetYourIdentities.item(row-1,1).text()
self.ui.comboBoxExisting.addItem(self.parent.ui.tableWidgetYourIdentities.item(row-1,1).text())
row += 1
self.ui.groupBoxDeterministic.setHidden(True)
QtGui.QWidget.resize(self,QtGui.QWidget.sizeHint(self))
class MyForm(QtGui.QMainWindow): class MyForm(QtGui.QMainWindow):
@ -4065,8 +4037,8 @@ class MyForm(QtGui.QMainWindow):
if isEnabled: if isEnabled:
status,addressVersionNumber,streamNumber,hash = decodeAddress(addressInKeysFile) status,addressVersionNumber,streamNumber,hash = decodeAddress(addressInKeysFile)
self.sqlLookup = sqlThread() #self.sqlLookup = sqlThread()
self.sqlLookup.start() #self.sqlLookup.start()
reloadMyAddressHashes() reloadMyAddressHashes()
self.reloadBroadcastSendersForWhichImWatching() self.reloadBroadcastSendersForWhichImWatching()
@ -4275,43 +4247,38 @@ class MyForm(QtGui.QMainWindow):
self.rerenderComboBoxSendFrom() self.rerenderComboBoxSendFrom()
self.UISignalThread = UISignaler()
self.UISignalThread.start()
self.connectToStream(1) QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL("writeNewAddressToTable(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"), self.writeNewAddressToTable)
QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL("updateStatusBar(PyQt_PyObject)"), self.updateStatusBar)
self.singleListenerThread = singleListener() QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL("updateSentItemStatusByHash(PyQt_PyObject,PyQt_PyObject)"), self.updateSentItemStatusByHash)
self.singleListenerThread.start() QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL("updateSentItemStatusByAckdata(PyQt_PyObject,PyQt_PyObject)"), self.updateSentItemStatusByAckdata)
QtCore.QObject.connect(self.singleListenerThread, QtCore.SIGNAL("passObjectThrough(PyQt_PyObject)"), self.connectObjectToSignals) QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL("displayNewInboxMessage(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"), self.displayNewInboxMessage)
QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL("displayNewSentMessage(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"), self.displayNewSentMessage)
QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL("updateNetworkStatusTab(PyQt_PyObject,PyQt_PyObject)"), self.updateNetworkStatusTab)
QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL("incrementNumberOfMessagesProcessed()"), self.incrementNumberOfMessagesProcessed)
QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL("incrementNumberOfPubkeysProcessed()"), self.incrementNumberOfPubkeysProcessed)
QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL("incrementNumberOfBroadcastsProcessed()"), self.incrementNumberOfBroadcastsProcessed)
QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL("setStatusIcon(PyQt_PyObject)"), self.setStatusIcon)
self.singleCleanerThread = singleCleaner() #self.connectToStream(1)
self.singleCleanerThread.start()
QtCore.QObject.connect(self.singleCleanerThread, QtCore.SIGNAL("updateSentItemStatusByHash(PyQt_PyObject,PyQt_PyObject)"), self.updateSentItemStatusByHash)
QtCore.QObject.connect(self.singleCleanerThread, QtCore.SIGNAL("updateStatusBar(PyQt_PyObject)"), self.updateStatusBar)
self.workerThread = singleWorker() #self.singleListenerThread = singleListener()
self.workerThread.start() #self.singleListenerThread.start()
QtCore.QObject.connect(self.workerThread, QtCore.SIGNAL("updateSentItemStatusByHash(PyQt_PyObject,PyQt_PyObject)"), self.updateSentItemStatusByHash) #QtCore.QObject.connect(self.singleListenerThread, QtCore.SIGNAL("passObjectThrough(PyQt_PyObject)"), self.connectObjectToSignals)
QtCore.QObject.connect(self.workerThread, QtCore.SIGNAL("updateSentItemStatusByAckdata(PyQt_PyObject,PyQt_PyObject)"), self.updateSentItemStatusByAckdata)
QtCore.QObject.connect(self.workerThread, QtCore.SIGNAL("updateStatusBar(PyQt_PyObject)"), self.updateStatusBar)
if safeConfigGetBoolean('bitmessagesettings','apienabled'):
try: #self.singleCleanerThread = singleCleaner()
apiNotifyPath = config.get('bitmessagesettings','apinotifypath') #self.singleCleanerThread.start()
except: #QtCore.QObject.connect(self.singleCleanerThread, QtCore.SIGNAL("updateSentItemStatusByHash(PyQt_PyObject,PyQt_PyObject)"), self.updateSentItemStatusByHash)
apiNotifyPath = '' #QtCore.QObject.connect(self.singleCleanerThread, QtCore.SIGNAL("updateStatusBar(PyQt_PyObject)"), self.updateStatusBar)
if apiNotifyPath != '':
printLock.acquire() #self.workerThread = singleWorker()
print 'Trying to call', apiNotifyPath #self.workerThread.start()
printLock.release() #QtCore.QObject.connect(self.workerThread, QtCore.SIGNAL("updateSentItemStatusByHash(PyQt_PyObject,PyQt_PyObject)"), self.updateSentItemStatusByHash)
call([apiNotifyPath, "startingUp"]) #QtCore.QObject.connect(self.workerThread, QtCore.SIGNAL("updateSentItemStatusByAckdata(PyQt_PyObject,PyQt_PyObject)"), self.updateSentItemStatusByAckdata)
self.singleAPIThread = singleAPI() #QtCore.QObject.connect(self.workerThread, QtCore.SIGNAL("updateStatusBar(PyQt_PyObject)"), self.updateStatusBar)
self.singleAPIThread.start()
self.singleAPISignalHandlerThread = singleAPISignalHandler()
self.singleAPISignalHandlerThread.start()
QtCore.QObject.connect(self.singleAPISignalHandlerThread, QtCore.SIGNAL("updateStatusBar(PyQt_PyObject)"), self.updateStatusBar)
QtCore.QObject.connect(self.singleAPISignalHandlerThread, QtCore.SIGNAL("passAddressGeneratorObjectThrough(PyQt_PyObject)"), self.connectObjectToAddressGeneratorSignals)
QtCore.QObject.connect(self.singleAPISignalHandlerThread, QtCore.SIGNAL("displayNewSentMessage(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"), self.displayNewSentMessage)
def tableWidgetInboxKeyPressEvent(self,event): def tableWidgetInboxKeyPressEvent(self,event):
if event.key() == QtCore.Qt.Key_Delete: if event.key() == QtCore.Qt.Key_Delete:
@ -4345,11 +4312,12 @@ class MyForm(QtGui.QMainWindow):
else: else:
streamNumberForAddress = int(self.regenerateAddressesDialogInstance.ui.lineEditStreamNumber.text()) streamNumberForAddress = int(self.regenerateAddressesDialogInstance.ui.lineEditStreamNumber.text())
addressVersionNumber = int(self.regenerateAddressesDialogInstance.ui.lineEditAddressVersionNumber.text()) addressVersionNumber = int(self.regenerateAddressesDialogInstance.ui.lineEditAddressVersionNumber.text())
self.addressGenerator = addressGenerator() #self.addressGenerator = addressGenerator()
self.addressGenerator.setup(addressVersionNumber,streamNumberForAddress,"unused address",self.regenerateAddressesDialogInstance.ui.spinBoxNumberOfAddressesToMake.value(),self.regenerateAddressesDialogInstance.ui.lineEditPassphrase.text().toUtf8(),self.regenerateAddressesDialogInstance.ui.checkBoxEighteenByteRipe.isChecked()) #self.addressGenerator.setup(addressVersionNumber,streamNumberForAddress,"unused address",self.regenerateAddressesDialogInstance.ui.spinBoxNumberOfAddressesToMake.value(),self.regenerateAddressesDialogInstance.ui.lineEditPassphrase.text().toUtf8(),self.regenerateAddressesDialogInstance.ui.checkBoxEighteenByteRipe.isChecked())
QtCore.QObject.connect(self.addressGenerator, SIGNAL("writeNewAddressToTable(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"), self.writeNewAddressToTable) #QtCore.QObject.connect(self.addressGenerator, SIGNAL("writeNewAddressToTable(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"), self.writeNewAddressToTable)
QtCore.QObject.connect(self.addressGenerator, QtCore.SIGNAL("updateStatusBar(PyQt_PyObject)"), self.updateStatusBar) #QtCore.QObject.connect(self.addressGenerator, QtCore.SIGNAL("updateStatusBar(PyQt_PyObject)"), self.updateStatusBar)
self.addressGenerator.start() #self.addressGenerator.start()
addressGeneratorQueue.put((addressVersionNumber,streamNumberForAddress,"regenerated deterministic address",self.regenerateAddressesDialogInstance.ui.spinBoxNumberOfAddressesToMake.value(),self.regenerateAddressesDialogInstance.ui.lineEditPassphrase.text().toUtf8(),self.regenerateAddressesDialogInstance.ui.checkBoxEighteenByteRipe.isChecked()))
self.ui.tabWidget.setCurrentIndex(3) self.ui.tabWidget.setCurrentIndex(3)
def openKeysFile(self): def openKeysFile(self):
@ -4406,12 +4374,24 @@ class MyForm(QtGui.QMainWindow):
def updateNetworkStatusTab(self,streamNumber,connectionCount): def updateNetworkStatusTab(self,streamNumber,connectionCount):
global statusIconColor global statusIconColor
#print 'updating network status tab' #print 'updating network status tab'
totalNumberOfConnectionsFromAllStreams = 0 #One would think we could use len(sendDataQueues) for this, but sendData threads don't remove themselves from sendDataQueues fast enough for len(sendDataQueues) to be accurate here. totalNumberOfConnectionsFromAllStreams = 0 #One would think we could use len(sendDataQueues) for this but the number doesn't always match: just because we have a sendDataThread running doesn't mean that the connection has been fully established (with the exchange of version messages).
foundTheRowThatNeedsUpdating = False
for currentRow in range(self.ui.tableWidgetConnectionCount.rowCount()): for currentRow in range(self.ui.tableWidgetConnectionCount.rowCount()):
rowStreamNumber = int(self.ui.tableWidgetConnectionCount.item(currentRow,0).text()) rowStreamNumber = int(self.ui.tableWidgetConnectionCount.item(currentRow,0).text())
if streamNumber == rowStreamNumber: if streamNumber == rowStreamNumber:
foundTheRowThatNeedsUpdating = True
self.ui.tableWidgetConnectionCount.item(currentRow,1).setText(str(connectionCount)) self.ui.tableWidgetConnectionCount.item(currentRow,1).setText(str(connectionCount))
totalNumberOfConnectionsFromAllStreams += connectionCount totalNumberOfConnectionsFromAllStreams += connectionCount
if foundTheRowThatNeedsUpdating == False:
#Add a line to the table for this stream number and update its count with the current connection count.
self.ui.tableWidgetConnectionCount.insertRow(0)
newItem = QtGui.QTableWidgetItem(str(streamNumber))
newItem.setFlags( QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled )
self.ui.tableWidgetConnectionCount.setItem(0,0,newItem)
newItem = QtGui.QTableWidgetItem(str(connectionCount))
newItem.setFlags( QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled )
self.ui.tableWidgetConnectionCount.setItem(0,1,newItem)
totalNumberOfConnectionsFromAllStreams += connectionCount
self.ui.labelTotalConnections.setText('Total Connections: ' + str(totalNumberOfConnectionsFromAllStreams)) self.ui.labelTotalConnections.setText('Total Connections: ' + str(totalNumberOfConnectionsFromAllStreams))
if totalNumberOfConnectionsFromAllStreams > 0 and statusIconColor == 'red': #FYI: The 'singlelistener' thread sets the icon color to green when it receives an incoming connection, meaning that the user's firewall is configured correctly. if totalNumberOfConnectionsFromAllStreams > 0 and statusIconColor == 'red': #FYI: The 'singlelistener' thread sets the icon color to green when it receives an incoming connection, meaning that the user's firewall is configured correctly.
self.setStatusIcon('yellow') self.setStatusIcon('yellow')
@ -4594,7 +4574,7 @@ class MyForm(QtGui.QMainWindow):
if queryreturn <> []: if queryreturn <> []:
for row in queryreturn: for row in queryreturn:
toLabel, = row toLabel, = row
self.displayNewSentMessage(toAddress,toLabel,fromAddress, subject, message, ackdata) self.displayNewSentMessage(toAddress,toLabel,fromAddress, subject, message, ackdata)
workerQueue.put(('sendmessage',toAddress)) workerQueue.put(('sendmessage',toAddress))
@ -4693,27 +4673,7 @@ class MyForm(QtGui.QMainWindow):
else: else:
self.ui.comboBoxSendFrom.setCurrentIndex(0) self.ui.comboBoxSendFrom.setCurrentIndex(0)
def connectToStream(self,streamNumber):
self.listOfOutgoingSynSenderThreads = [] #if we don't maintain this list, the threads will get garbage-collected.
connectionsCount[streamNumber] = 0
selfInitiatedConnections[streamNumber] = {}
#Add a line to the Connection Count table on the Network Status tab with a 'zero' connection count. This will be updated as necessary by another function.
self.ui.tableWidgetConnectionCount.insertRow(0)
newItem = QtGui.QTableWidgetItem(str(streamNumber))
newItem.setFlags( QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled )
self.ui.tableWidgetConnectionCount.setItem(0,0,newItem)
newItem = QtGui.QTableWidgetItem('0')
newItem.setFlags( QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled )
self.ui.tableWidgetConnectionCount.setItem(0,1,newItem)
for i in range(32):
a = outgoingSynSender()
self.listOfOutgoingSynSenderThreads.append(a)
QtCore.QObject.connect(a, QtCore.SIGNAL("passObjectThrough(PyQt_PyObject)"), self.connectObjectToSignals)
QtCore.QObject.connect(a, QtCore.SIGNAL("updateStatusBar(PyQt_PyObject)"), self.updateStatusBar)
a.setup(streamNumber)
a.start()
def connectObjectToSignals(self,object): def connectObjectToSignals(self,object):
QtCore.QObject.connect(object, QtCore.SIGNAL("updateStatusBar(PyQt_PyObject)"), self.updateStatusBar) QtCore.QObject.connect(object, QtCore.SIGNAL("updateStatusBar(PyQt_PyObject)"), self.updateStatusBar)
@ -4835,7 +4795,7 @@ class MyForm(QtGui.QMainWindow):
newItem.setData(33,int(time.time())) newItem.setData(33,int(time.time()))
newItem.setFont(font) newItem.setFont(font)
self.ui.tableWidgetInbox.setItem(0,3,newItem) self.ui.tableWidgetInbox.setItem(0,3,newItem)
"""#If we have received this message from either a broadcast address or from someone in our address book, display as HTML """#If we have received this message from either a broadcast address or from someone in our address book, display as HTML
if decodeAddress(fromAddress)[3] in broadcastSendersForWhichImWatching or isAddressInMyAddressBook(fromAddress): if decodeAddress(fromAddress)[3] in broadcastSendersForWhichImWatching or isAddressInMyAddressBook(fromAddress):
self.ui.textEditInboxMessage.setText(self.ui.tableWidgetInbox.item(0,2).data(Qt.UserRole).toPyObject()) self.ui.textEditInboxMessage.setText(self.ui.tableWidgetInbox.item(0,2).data(Qt.UserRole).toPyObject())
@ -5013,7 +4973,7 @@ class MyForm(QtGui.QMainWindow):
if appdata == '' and not self.settingsDialogInstance.ui.checkBoxPortableMode.isChecked(): #If we ARE using portable mode now but the user selected that we shouldn't... if appdata == '' and not self.settingsDialogInstance.ui.checkBoxPortableMode.isChecked(): #If we ARE using portable mode now but the user selected that we shouldn't...
appdata = lookupAppdataFolder() appdata = lookupAppdataFolder()
if not os.path.exists(appdata): if not os.path.exists(appdata):
os.makedirs(appdata) os.makedirs(appdata)
config.set('bitmessagesettings','movemessagstoappdata','true') #Tells bitmessage to move the messages.dat file to the appdata directory the next time the program starts. config.set('bitmessagesettings','movemessagstoappdata','true') #Tells bitmessage to move the messages.dat file to the appdata directory the next time the program starts.
#Write the keys.dat file to disk in the new location #Write the keys.dat file to disk in the new location
with open(appdata + 'keys.dat', 'wb') as configfile: with open(appdata + 'keys.dat', 'wb') as configfile:
@ -5122,11 +5082,12 @@ class MyForm(QtGui.QMainWindow):
#User selected 'Use the same stream as an existing address.' #User selected 'Use the same stream as an existing address.'
streamNumberForAddress = addressStream(self.dialog.ui.comboBoxExisting.currentText()) streamNumberForAddress = addressStream(self.dialog.ui.comboBoxExisting.currentText())
self.addressGenerator = addressGenerator() #self.addressGenerator = addressGenerator()
self.addressGenerator.setup(3,streamNumberForAddress,str(self.dialog.ui.newaddresslabel.text().toUtf8()),1,"",self.dialog.ui.checkBoxEighteenByteRipe.isChecked()) #self.addressGenerator.setup(3,streamNumberForAddress,str(self.dialog.ui.newaddresslabel.text().toUtf8()),1,"",self.dialog.ui.checkBoxEighteenByteRipe.isChecked())
QtCore.QObject.connect(self.addressGenerator, SIGNAL("writeNewAddressToTable(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"), self.writeNewAddressToTable) #QtCore.QObject.connect(self.addressGenerator, SIGNAL("writeNewAddressToTable(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"), self.writeNewAddressToTable)
QtCore.QObject.connect(self.addressGenerator, QtCore.SIGNAL("updateStatusBar(PyQt_PyObject)"), self.updateStatusBar) #QtCore.QObject.connect(self.addressGenerator, QtCore.SIGNAL("updateStatusBar(PyQt_PyObject)"), self.updateStatusBar)
self.addressGenerator.start() #self.addressGenerator.start()
addressGeneratorQueue.put((3,streamNumberForAddress,str(self.dialog.ui.newaddresslabel.text().toUtf8()),1,"",self.dialog.ui.checkBoxEighteenByteRipe.isChecked()))
else: else:
if self.dialog.ui.lineEditPassphrase.text() != self.dialog.ui.lineEditPassphraseAgain.text(): if self.dialog.ui.lineEditPassphrase.text() != self.dialog.ui.lineEditPassphraseAgain.text():
QMessageBox.about(self, "Passphrase mismatch", "The passphrase you entered twice doesn\'t match. Try again.") QMessageBox.about(self, "Passphrase mismatch", "The passphrase you entered twice doesn\'t match. Try again.")
@ -5134,11 +5095,12 @@ class MyForm(QtGui.QMainWindow):
QMessageBox.about(self, "Choose a passphrase", "You really do need a passphrase.") QMessageBox.about(self, "Choose a passphrase", "You really do need a passphrase.")
else: else:
streamNumberForAddress = 1 #this will eventually have to be replaced by logic to determine the most available stream number. streamNumberForAddress = 1 #this will eventually have to be replaced by logic to determine the most available stream number.
self.addressGenerator = addressGenerator() #self.addressGenerator = addressGenerator()
self.addressGenerator.setup(3,streamNumberForAddress,"unused address",self.dialog.ui.spinBoxNumberOfAddressesToMake.value(),self.dialog.ui.lineEditPassphrase.text().toUtf8(),self.dialog.ui.checkBoxEighteenByteRipe.isChecked()) #self.addressGenerator.setup(3,streamNumberForAddress,"unused address",self.dialog.ui.spinBoxNumberOfAddressesToMake.value(),self.dialog.ui.lineEditPassphrase.text().toUtf8(),self.dialog.ui.checkBoxEighteenByteRipe.isChecked())
QtCore.QObject.connect(self.addressGenerator, SIGNAL("writeNewAddressToTable(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"), self.writeNewAddressToTable) #QtCore.QObject.connect(self.addressGenerator, SIGNAL("writeNewAddressToTable(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"), self.writeNewAddressToTable)
QtCore.QObject.connect(self.addressGenerator, QtCore.SIGNAL("updateStatusBar(PyQt_PyObject)"), self.updateStatusBar) #QtCore.QObject.connect(self.addressGenerator, QtCore.SIGNAL("updateStatusBar(PyQt_PyObject)"), self.updateStatusBar)
self.addressGenerator.start() #self.addressGenerator.start()
addressGeneratorQueue.put((3,streamNumberForAddress,"unused deterministic address",self.dialog.ui.spinBoxNumberOfAddressesToMake.value(),self.dialog.ui.lineEditPassphrase.text().toUtf8(),self.dialog.ui.checkBoxEighteenByteRipe.isChecked()))
else: else:
print 'new address dialog box rejected' print 'new address dialog box rejected'
@ -5151,42 +5113,11 @@ class MyForm(QtGui.QMainWindow):
event.accept() event.accept()
else: else:
event.ignore()''' event.ignore()'''
doCleanShutdown()
self.statusBar().showMessage('Bitmessage is stuck waiting for the knownNodesLock.')
knownNodesLock.acquire()
self.statusBar().showMessage('Saving the knownNodes list of peers to disk...')
output = open(appdata + 'knownnodes.dat', 'wb')
print 'finished opening knownnodes.dat. Now pickle.dump'
pickle.dump(knownNodes, output)
print 'done with pickle.dump. closing output'
output.close()
knownNodesLock.release()
print 'done closing knownnodes.dat output file.'
self.statusBar().showMessage('Done saving the knownNodes list of peers to disk.')
broadcastToSendDataQueues((0, 'shutdown', 'all'))
printLock.acquire()
print 'Closing. Flushing inventory in memory out to disk...'
printLock.release()
self.statusBar().showMessage('Flushing inventory in memory out to disk. This should normally only take a second...')
flushInventory()
#This one last useless query will guarantee that the previous query committed before we close the program.
sqlLock.acquire()
sqlSubmitQueue.put('SELECT address FROM subscriptions')
sqlSubmitQueue.put('')
sqlReturnQueue.get()
sqlLock.release()
self.trayIcon.hide() self.trayIcon.hide()
printLock.acquire()
print 'Done.'
printLock.release()
self.statusBar().showMessage('All done. Closing user interface...') self.statusBar().showMessage('All done. Closing user interface...')
event.accept() event.accept()
print 'done. (passed event.accept())' print 'Done. (passed event.accept())'
#raise SystemExit
os._exit(0) os._exit(0)
def on_action_InboxMessageForceHtml(self): def on_action_InboxMessageForceHtml(self):
@ -5280,7 +5211,7 @@ class MyForm(QtGui.QMainWindow):
#Send item on the Sent tab to trash #Send item on the Sent tab to trash
def on_action_SentTrash(self): def on_action_SentTrash(self):
while self.ui.tableWidgetSent.selectedIndexes() != []: while self.ui.tableWidgetSent.selectedIndexes() != []:
currentRow = self.ui.tableWidgetSent.selectedIndexes()[0].row() currentRow = self.ui.tableWidgetSent.selectedIndexes()[0].row()
ackdataToTrash = str(self.ui.tableWidgetSent.item(currentRow,3).data(Qt.UserRole).toPyObject()) ackdataToTrash = str(self.ui.tableWidgetSent.item(currentRow,3).data(Qt.UserRole).toPyObject())
t = (ackdataToTrash,) t = (ackdataToTrash,)
sqlLock.acquire() sqlLock.acquire()
@ -5296,7 +5227,7 @@ class MyForm(QtGui.QMainWindow):
self.ui.tableWidgetSent.selectRow(currentRow) self.ui.tableWidgetSent.selectRow(currentRow)
else: else:
self.ui.tableWidgetSent.selectRow(currentRow-1) self.ui.tableWidgetSent.selectRow(currentRow-1)
def on_action_SentClipboard(self): def on_action_SentClipboard(self):
currentRow = self.ui.tableWidgetSent.currentRow() currentRow = self.ui.tableWidgetSent.currentRow()
addressAtCurrentRow = str(self.ui.tableWidgetSent.item(currentRow,0).data(Qt.UserRole).toPyObject()) addressAtCurrentRow = str(self.ui.tableWidgetSent.item(currentRow,0).data(Qt.UserRole).toPyObject())
@ -5539,7 +5470,7 @@ class MyForm(QtGui.QMainWindow):
sqlReturnQueue.get() sqlReturnQueue.get()
sqlSubmitQueue.put('commit') sqlSubmitQueue.put('commit')
sqlLock.release() sqlLock.release()
def tableWidgetSentItemClicked(self): def tableWidgetSentItemClicked(self):
currentRow = self.ui.tableWidgetSent.currentRow() currentRow = self.ui.tableWidgetSent.currentRow()
if currentRow >= 0: if currentRow >= 0:
@ -5623,10 +5554,190 @@ class MyForm(QtGui.QMainWindow):
privEncryptionKey = hashlib.sha512(encodeVarint(addressVersionNumber)+encodeVarint(streamNumber)+hash).digest()[:32] privEncryptionKey = hashlib.sha512(encodeVarint(addressVersionNumber)+encodeVarint(streamNumber)+hash).digest()[:32]
MyECSubscriptionCryptorObjects[hash] = highlevelcrypto.makeCryptor(privEncryptionKey.encode('hex')) MyECSubscriptionCryptorObjects[hash] = highlevelcrypto.makeCryptor(privEncryptionKey.encode('hex'))
#In order for the time columns on the Inbox and Sent tabs to be sorted correctly (rather than alphabetically), we need to overload the < operator and use this class instead of QTableWidgetItem.
class myTableWidgetItem(QTableWidgetItem):
def __lt__(self,other): class helpDialog(QtGui.QDialog):
return int(self.data(33).toPyObject()) < int(other.data(33).toPyObject()) def __init__(self,parent):
QtGui.QWidget.__init__(self, parent)
self.ui = Ui_helpDialog()
self.ui.setupUi(self)
self.parent = parent
self.ui.labelHelpURI.setOpenExternalLinks(True)
QtGui.QWidget.resize(self,QtGui.QWidget.sizeHint(self))
class aboutDialog(QtGui.QDialog):
def __init__(self,parent):
QtGui.QWidget.__init__(self, parent)
self.ui = Ui_aboutDialog()
self.ui.setupUi(self)
self.parent = parent
self.ui.labelVersion.setText('version ' + softwareVersion)
class regenerateAddressesDialog(QtGui.QDialog):
def __init__(self,parent):
QtGui.QWidget.__init__(self, parent)
self.ui = Ui_regenerateAddressesDialog()
self.ui.setupUi(self)
self.parent = parent
QtGui.QWidget.resize(self,QtGui.QWidget.sizeHint(self))
class settingsDialog(QtGui.QDialog):
def __init__(self,parent):
QtGui.QWidget.__init__(self, parent)
self.ui = Ui_settingsDialog()
self.ui.setupUi(self)
self.parent = parent
self.ui.checkBoxStartOnLogon.setChecked(config.getboolean('bitmessagesettings', 'startonlogon'))
self.ui.checkBoxMinimizeToTray.setChecked(config.getboolean('bitmessagesettings', 'minimizetotray'))
self.ui.checkBoxShowTrayNotifications.setChecked(config.getboolean('bitmessagesettings', 'showtraynotifications'))
self.ui.checkBoxStartInTray.setChecked(config.getboolean('bitmessagesettings', 'startintray'))
if appdata == '':
self.ui.checkBoxPortableMode.setChecked(True)
if 'darwin' in sys.platform:
self.ui.checkBoxStartOnLogon.setDisabled(True)
self.ui.checkBoxMinimizeToTray.setDisabled(True)
self.ui.checkBoxShowTrayNotifications.setDisabled(True)
self.ui.checkBoxStartInTray.setDisabled(True)
self.ui.labelSettingsNote.setText('Options have been disabled because they either aren\'t applicable or because they haven\'t yet been implimented for your operating system.')
elif 'linux' in sys.platform:
self.ui.checkBoxStartOnLogon.setDisabled(True)
self.ui.checkBoxMinimizeToTray.setDisabled(True)
self.ui.checkBoxStartInTray.setDisabled(True)
self.ui.labelSettingsNote.setText('Options have been disabled because they either arn\'t applicable or because they haven\'t yet been implimented for your operating system.')
#On the Network settings tab:
self.ui.lineEditTCPPort.setText(str(config.get('bitmessagesettings', 'port')))
self.ui.checkBoxAuthentication.setChecked(config.getboolean('bitmessagesettings', 'socksauthentication'))
if str(config.get('bitmessagesettings', 'socksproxytype')) == 'none':
self.ui.comboBoxProxyType.setCurrentIndex(0)
self.ui.lineEditSocksHostname.setEnabled(False)
self.ui.lineEditSocksPort.setEnabled(False)
self.ui.lineEditSocksUsername.setEnabled(False)
self.ui.lineEditSocksPassword.setEnabled(False)
self.ui.checkBoxAuthentication.setEnabled(False)
elif str(config.get('bitmessagesettings', 'socksproxytype')) == 'SOCKS4a':
self.ui.comboBoxProxyType.setCurrentIndex(1)
self.ui.lineEditTCPPort.setEnabled(False)
elif str(config.get('bitmessagesettings', 'socksproxytype')) == 'SOCKS5':
self.ui.comboBoxProxyType.setCurrentIndex(2)
self.ui.lineEditTCPPort.setEnabled(False)
self.ui.lineEditSocksHostname.setText(str(config.get('bitmessagesettings', 'sockshostname')))
self.ui.lineEditSocksPort.setText(str(config.get('bitmessagesettings', 'socksport')))
self.ui.lineEditSocksUsername.setText(str(config.get('bitmessagesettings', 'socksusername')))
self.ui.lineEditSocksPassword.setText(str(config.get('bitmessagesettings', 'sockspassword')))
QtCore.QObject.connect(self.ui.comboBoxProxyType, QtCore.SIGNAL("currentIndexChanged(int)"), self.comboBoxProxyTypeChanged)
self.ui.lineEditTotalDifficulty.setText(str((float(config.getint('bitmessagesettings', 'defaultnoncetrialsperbyte'))/networkDefaultProofOfWorkNonceTrialsPerByte)))
self.ui.lineEditSmallMessageDifficulty.setText(str((float(config.getint('bitmessagesettings', 'defaultpayloadlengthextrabytes'))/networkDefaultPayloadLengthExtraBytes)))
QtGui.QWidget.resize(self,QtGui.QWidget.sizeHint(self))
def comboBoxProxyTypeChanged(self,comboBoxIndex):
if comboBoxIndex == 0:
self.ui.lineEditSocksHostname.setEnabled(False)
self.ui.lineEditSocksPort.setEnabled(False)
self.ui.lineEditSocksUsername.setEnabled(False)
self.ui.lineEditSocksPassword.setEnabled(False)
self.ui.checkBoxAuthentication.setEnabled(False)
self.ui.lineEditTCPPort.setEnabled(True)
elif comboBoxIndex == 1 or comboBoxIndex == 2:
self.ui.lineEditSocksHostname.setEnabled(True)
self.ui.lineEditSocksPort.setEnabled(True)
self.ui.checkBoxAuthentication.setEnabled(True)
if self.ui.checkBoxAuthentication.isChecked():
self.ui.lineEditSocksUsername.setEnabled(True)
self.ui.lineEditSocksPassword.setEnabled(True)
self.ui.lineEditTCPPort.setEnabled(False)
class SpecialAddressBehaviorDialog(QtGui.QDialog):
def __init__(self,parent):
QtGui.QWidget.__init__(self, parent)
self.ui = Ui_SpecialAddressBehaviorDialog()
self.ui.setupUi(self)
self.parent = parent
currentRow = parent.ui.tableWidgetYourIdentities.currentRow()
addressAtCurrentRow = str(parent.ui.tableWidgetYourIdentities.item(currentRow,1).text())
if safeConfigGetBoolean(addressAtCurrentRow,'mailinglist'):
self.ui.radioButtonBehaviorMailingList.click()
else:
self.ui.radioButtonBehaveNormalAddress.click()
try:
mailingListName = config.get(addressAtCurrentRow, 'mailinglistname')
except:
mailingListName = ''
self.ui.lineEditMailingListName.setText(unicode(mailingListName,'utf-8'))
QtGui.QWidget.resize(self,QtGui.QWidget.sizeHint(self))
class NewSubscriptionDialog(QtGui.QDialog):
def __init__(self,parent):
QtGui.QWidget.__init__(self, parent)
self.ui = Ui_NewSubscriptionDialog()
self.ui.setupUi(self)
self.parent = parent
QtCore.QObject.connect(self.ui.lineEditSubscriptionAddress, QtCore.SIGNAL("textChanged(QString)"), self.subscriptionAddressChanged)
def subscriptionAddressChanged(self,QString):
status,a,b,c = decodeAddress(str(QString))
if status == 'missingbm':
self.ui.labelSubscriptionAddressCheck.setText('The address should start with ''BM-''')
elif status == 'checksumfailed':
self.ui.labelSubscriptionAddressCheck.setText('The address is not typed or copied correctly (the checksum failed).')
elif status == 'versiontoohigh':
self.ui.labelSubscriptionAddressCheck.setText('The version number of this address is higher than this software can support. Please upgrade Bitmessage.')
elif status == 'invalidcharacters':
self.ui.labelSubscriptionAddressCheck.setText('The address contains invalid characters.')
elif status == 'ripetooshort':
self.ui.labelSubscriptionAddressCheck.setText('Some data encoded in the address is too short.')
elif status == 'ripetoolong':
self.ui.labelSubscriptionAddressCheck.setText('Some data encoded in the address is too long.')
elif status == 'success':
self.ui.labelSubscriptionAddressCheck.setText('Address is valid.')
class NewAddressDialog(QtGui.QDialog):
def __init__(self, parent):
QtGui.QWidget.__init__(self, parent)
self.ui = Ui_NewAddressDialog()
self.ui.setupUi(self)
self.parent = parent
row = 1
#Let's fill out the 'existing address' combo box with addresses from the 'Your Identities' tab.
while self.parent.ui.tableWidgetYourIdentities.item(row-1,1):
self.ui.radioButtonExisting.click()
#print self.parent.ui.tableWidgetYourIdentities.item(row-1,1).text()
self.ui.comboBoxExisting.addItem(self.parent.ui.tableWidgetYourIdentities.item(row-1,1).text())
row += 1
self.ui.groupBoxDeterministic.setHidden(True)
QtGui.QWidget.resize(self,QtGui.QWidget.sizeHint(self))
#The MySimpleXMLRPCRequestHandler class cannot emit signals (or at least I don't know how) because it is not a QT thread. It therefore puts data in a queue which this thread monitors and emits the signals on its behalf.
"""class singleAPISignalHandler(QThread):
def __init__(self, parent = None):
QThread.__init__(self, parent)
def run(self):
while True:
command, data = apiSignalQueue.get()
if command == 'updateStatusBar':
self.emit(SIGNAL("updateStatusBar(PyQt_PyObject)"),data)
elif command == 'createRandomAddress':
label, eighteenByteRipe = data
streamNumberForAddress = 1
#self.addressGenerator = addressGenerator()
#self.addressGenerator.setup(3,streamNumberForAddress,label,1,"",eighteenByteRipe)
#self.emit(SIGNAL("passAddressGeneratorObjectThrough(PyQt_PyObject)"),self.addressGenerator)
#self.addressGenerator.start()
addressGeneratorQueue.put((3,streamNumberForAddress,label,1,"",eighteenByteRipe))
elif command == 'createDeterministicAddresses':
passphrase, numberOfAddresses, addressVersionNumber, streamNumber, eighteenByteRipe = data
#self.addressGenerator = addressGenerator()
#self.addressGenerator.setup(addressVersionNumber,streamNumber,'unused API address',numberOfAddresses,passphrase,eighteenByteRipe)
#self.emit(SIGNAL("passAddressGeneratorObjectThrough(PyQt_PyObject)"),self.addressGenerator)
#self.addressGenerator.start()
addressGeneratorQueue.put((addressVersionNumber,streamNumber,'unused API address',numberOfAddresses,passphrase,eighteenByteRipe))
elif command == 'displayNewSentMessage':
toAddress,toLabel,fromAddress,subject,message,ackdata = data
self.emit(SIGNAL("displayNewSentMessage(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"),toAddress,toLabel,fromAddress,subject,message,ackdata)"""
selfInitiatedConnections = {} #This is a list of current connections (the thread pointers at least) selfInitiatedConnections = {} #This is a list of current connections (the thread pointers at least)
@ -5656,6 +5767,8 @@ successfullyDecryptMessageTimings = [] #A list of the amounts of time it took to
apiSignalQueue = Queue.Queue() #The singleAPI thread uses this queue to pass messages to a QT thread which can emit signals to do things like display a message in the UI. apiSignalQueue = Queue.Queue() #The singleAPI thread uses this queue to pass messages to a QT thread which can emit signals to do things like display a message in the UI.
apiAddressGeneratorReturnQueue = Queue.Queue() #The address generator thread uses this queue to get information back to the API thread. apiAddressGeneratorReturnQueue = Queue.Queue() #The address generator thread uses this queue to get information back to the API thread.
alreadyAttemptedConnectionsListResetTime = int(time.time()) #used to clear out the alreadyAttemptedConnectionsList periodically so that we will retry connecting to hosts to which we have already tried to connect. alreadyAttemptedConnectionsListResetTime = int(time.time()) #used to clear out the alreadyAttemptedConnectionsList periodically so that we will retry connecting to hosts to which we have already tried to connect.
UISignalQueue = Queue.Queue()
addressGeneratorQueue = Queue.Queue()
#These constants are not at the top because if changed they will cause particularly unexpected behavior: You won't be able to either send or receive messages because the proof of work you do (or demand) won't match that done or demanded by others. Don't change them! #These constants are not at the top because if changed they will cause particularly unexpected behavior: You won't be able to either send or receive messages because the proof of work you do (or demand) won't match that done or demanded by others. Don't change them!
networkDefaultProofOfWorkNonceTrialsPerByte = 320 #The amount of work that should be performed (and demanded) per byte of the payload. Double this number to double the work. networkDefaultProofOfWorkNonceTrialsPerByte = 320 #The amount of work that should be performed (and demanded) per byte of the payload. Double this number to double the work.
@ -5666,6 +5779,8 @@ if useVeryEasyProofOfWorkForTesting:
networkDefaultPayloadLengthExtraBytes = networkDefaultPayloadLengthExtraBytes / 7000 networkDefaultPayloadLengthExtraBytes = networkDefaultPayloadLengthExtraBytes / 7000
if __name__ == "__main__": if __name__ == "__main__":
signal.signal(signal.SIGINT, signal_handler)
#signal.signal(signal.SIGINT, signal.SIG_DFL)
# Check the Major version, the first element in the array # Check the Major version, the first element in the array
if sqlite3.sqlite_version_info[0] < 3: if sqlite3.sqlite_version_info[0] < 3:
print 'This program requires sqlite version 3 or higher because 2 and lower cannot store NULL values. I see version:', sqlite3.sqlite_version_info print 'This program requires sqlite version 3 or higher because 2 and lower cannot store NULL values. I see version:', sqlite3.sqlite_version_info
@ -5777,6 +5892,16 @@ if __name__ == "__main__":
print 'Bitmessage cannot read future versions of the keys file (keys.dat). Run the newer version of Bitmessage.' print 'Bitmessage cannot read future versions of the keys file (keys.dat). Run the newer version of Bitmessage.'
raise SystemExit raise SystemExit
if not safeConfigGetBoolean('bitmessagesettings','daemon'):
try:
#from PyQt4.QtCore import *
#from PyQt4.QtGui import *
pass
except Exception, err:
print 'PyBitmessage requires PyQt unless you want to run it as a daemon and interact with it using the API. You can download PyQt from http://www.riverbankcomputing.com/software/pyqt/download or by searching Google for \'PyQt Download\'. If you want to run in daemon mode, see https://bitmessage.org/wiki/Daemon'
print 'Error message:', err
sys.exit()
#DNS bootstrap. This could be programmed to use the SOCKS proxy to do the DNS lookup some day but for now we will just rely on the entries in defaultKnownNodes.py. Hopefully either they are up to date or the user has run Bitmessage recently without SOCKS turned on and received good bootstrap nodes using that method. #DNS bootstrap. This could be programmed to use the SOCKS proxy to do the DNS lookup some day but for now we will just rely on the entries in defaultKnownNodes.py. Hopefully either they are up to date or the user has run Bitmessage recently without SOCKS turned on and received good bootstrap nodes using that method.
if config.get('bitmessagesettings', 'socksproxytype') == 'none': if config.get('bitmessagesettings', 'socksproxytype') == 'none':
try: try:
@ -5794,21 +5919,73 @@ if __name__ == "__main__":
else: else:
print 'DNS bootstrap skipped because SOCKS is used.' print 'DNS bootstrap skipped because SOCKS is used.'
app = QtGui.QApplication(sys.argv) #Start the address generation thread
app.setStyleSheet("QStatusBar::item { border: 0px solid black }") addressGeneratorThread = addressGenerator()
myapp = MyForm() addressGeneratorThread.daemon = True # close the main program even if there are threads left
myapp.show() addressGeneratorThread.start()
if config.getboolean('bitmessagesettings', 'startintray'): #Start the thread that calculates POWs
myapp.hide() singleWorkerThread = singleWorker()
myapp.trayIcon.show() singleWorkerThread.daemon = True # close the main program even if there are threads left
#self.hidden = True singleWorkerThread.start()
#self.setWindowState(self.windowState() & QtCore.Qt.WindowMinimized)
#self.hide() #Start the SQL thread
if 'win32' in sys.platform or 'win64' in sys.platform: sqlLookup = sqlThread()
myapp.setWindowFlags(Qt.ToolTip) sqlLookup.daemon = False # DON'T close the main program even if there are threads left. The closeEvent should command this thread to exit gracefully.
sqlLookup.start()
#Start the cleanerThread
singleCleanerThread = singleCleaner()
singleCleanerThread.daemon = True # close the main program even if there are threads left
singleCleanerThread.start()
singleListenerThread = singleListener()
singleListenerThread.daemon = True # close the main program even if there are threads left
singleListenerThread.start()
if safeConfigGetBoolean('bitmessagesettings','apienabled'):
try:
apiNotifyPath = config.get('bitmessagesettings','apinotifypath')
except:
apiNotifyPath = ''
if apiNotifyPath != '':
printLock.acquire()
print 'Trying to call', apiNotifyPath
printLock.release()
call([apiNotifyPath, "startingUp"])
singleAPIThread = singleAPI()
singleAPIThread.daemon = True #close the main program even if there are threads left
singleAPIThread.start()
#self.singleAPISignalHandlerThread = singleAPISignalHandler()
#self.singleAPISignalHandlerThread.start()
#QtCore.QObject.connect(self.singleAPISignalHandlerThread, QtCore.SIGNAL("updateStatusBar(PyQt_PyObject)"), self.updateStatusBar)
#QtCore.QObject.connect(self.singleAPISignalHandlerThread, QtCore.SIGNAL("passAddressGeneratorObjectThrough(PyQt_PyObject)"), self.connectObjectToAddressGeneratorSignals)
#QtCore.QObject.connect(self.singleAPISignalHandlerThread, QtCore.SIGNAL("displayNewSentMessage(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"), self.displayNewSentMessage)
connectToStream(1)
if not safeConfigGetBoolean('bitmessagesettings','daemon'):
app = QtGui.QApplication(sys.argv)
app.setStyleSheet("QStatusBar::item { border: 0px solid black }")
myapp = MyForm()
myapp.show()
if config.getboolean('bitmessagesettings', 'startintray'):
myapp.hide()
myapp.trayIcon.show()
#self.hidden = True
#self.setWindowState(self.windowState() & QtCore.Qt.WindowMinimized)
#self.hide()
if 'win32' in sys.platform or 'win64' in sys.platform:
myapp.setWindowFlags(Qt.ToolTip)
sys.exit(app.exec_())
else:
print 'Running as a daemon. You can use Ctrl+C to exit.'
while True:
time.sleep(2)
print 'running still..'
sys.exit(app.exec_())
# So far, the Bitmessage protocol, this client, the Wiki, and the forums # So far, the Bitmessage protocol, this client, the Wiki, and the forums
# are all a one-man operation. Bitcoin tips are quite appreciated! # are all a one-man operation. Bitcoin tips are quite appreciated!