Merge pull request #163 from Atheros1/master

Added new deterministic address and subscription-related commands
This commit is contained in:
Jonathan Warren 2013-05-24 14:08:11 -07:00
commit 9148ff4c6e
8 changed files with 193 additions and 110 deletions

View File

@ -1,5 +1,5 @@
APP=pybitmessage APP=pybitmessage
VERSION=0.3.0 VERSION=0.3.1
DEST_SHARE=/usr/share DEST_SHARE=/usr/share
DEST_APP=$(DEST_SHARE)/$(APP) DEST_APP=$(DEST_SHARE)/$(APP)

View File

@ -7,7 +7,7 @@
#!/bin/bash #!/bin/bash
APP=pybitmessage APP=pybitmessage
VERSION=0.3.0 VERSION=0.3.1
ARCH_TYPE=all ARCH_TYPE=all
# Create a source archive # Create a source archive

View File

@ -25,7 +25,7 @@ print jsonAddresses
print 'Now that we have our address data in a nice Python data structure, let\'s look at the first address (index 0) and print its label:' print 'Now that we have our address data in a nice Python data structure, let\'s look at the first address (index 0) and print its label:'
print jsonAddresses['addresses'][0]['label'] print jsonAddresses['addresses'][0]['label']
print 'Uncomment the next two lines to create a new random address with slightly a slightly higher difficulty setting than normal.' print 'Uncomment the next two lines to create a new random address with a slightly higher difficulty setting than normal.'
#addressLabel = 'new address label'.encode('base64') #addressLabel = 'new address label'.encode('base64')
#print api.createRandomAddress(addressLabel,False,1.05,1.1111) #print api.createRandomAddress(addressLabel,False,1.05,1.1111)
@ -35,6 +35,15 @@ print 'Uncomment these next four lines to create new deterministic addresses.'
#print jsonDeterministicAddresses #print jsonDeterministicAddresses
#print json.loads(jsonDeterministicAddresses) #print json.loads(jsonDeterministicAddresses)
#print 'Uncomment this next line to print the first deterministic address that would be generated with the given passphrase. This will Not add it to the Bitmessage interface or the keys.dat file.'
#print api.getDeterministicAddress('asdfasdfqwser'.encode('base64'),3,1)
#print 'Uncomment this line to subscribe to an address. (You must use your own address, this one is invalid).'
#print api.addSubscription('2D94G5d8yp237GGqAheoecBYpdehdT3dha','test sub'.encode('base64'))
#print 'Uncomment this line to unsubscribe from an address.'
#print api.deleteSubscription('2D94G5d8yp237GGqAheoecBYpdehdT3dha')
print 'Let\'s now print all of our inbox messages:' print 'Let\'s now print all of our inbox messages:'
print api.getAllInboxMessages() print api.getAllInboxMessages()
inboxMessages = json.loads(api.getAllInboxMessages()) inboxMessages = json.loads(api.getAllInboxMessages())

View File

@ -18,7 +18,6 @@ useVeryEasyProofOfWorkForTesting = False #If you set this to True while on the n
encryptedBroadcastSwitchoverTime = 1369735200 encryptedBroadcastSwitchoverTime = 1369735200
import sys import sys
import ConfigParser import ConfigParser
import Queue import Queue
from addresses import * from addresses import *
@ -3220,10 +3219,10 @@ class addressGenerator(threading.Thread):
queueValue = shared.addressGeneratorQueue.get() queueValue = shared.addressGeneratorQueue.get()
nonceTrialsPerByte = 0 nonceTrialsPerByte = 0
payloadLengthExtraBytes = 0 payloadLengthExtraBytes = 0
if len(queueValue) == 6: if len(queueValue) == 7:
addressVersionNumber,streamNumber,label,numberOfAddressesToMake,deterministicPassphrase,eighteenByteRipe = queueValue command,addressVersionNumber,streamNumber,label,numberOfAddressesToMake,deterministicPassphrase,eighteenByteRipe = queueValue
elif len(queueValue) == 8: elif len(queueValue) == 9:
addressVersionNumber,streamNumber,label,numberOfAddressesToMake,deterministicPassphrase,eighteenByteRipe,nonceTrialsPerByte,payloadLengthExtraBytes = queueValue command,addressVersionNumber,streamNumber,label,numberOfAddressesToMake,deterministicPassphrase,eighteenByteRipe,nonceTrialsPerByte,payloadLengthExtraBytes = queueValue
else: else:
sys.stderr.write('Programming error: A structure with the wrong number of values was passed into the addressGeneratorQueue. Here is the queueValue: %s\n' % queueValue) sys.stderr.write('Programming error: A structure with the wrong number of values was passed into the addressGeneratorQueue. Here is the queueValue: %s\n' % queueValue)
if addressVersionNumber < 3 or addressVersionNumber > 3: if addressVersionNumber < 3 or addressVersionNumber > 3:
@ -3237,7 +3236,7 @@ class addressGenerator(threading.Thread):
if payloadLengthExtraBytes < shared.networkDefaultPayloadLengthExtraBytes: if payloadLengthExtraBytes < shared.networkDefaultPayloadLengthExtraBytes:
payloadLengthExtraBytes = shared.networkDefaultPayloadLengthExtraBytes payloadLengthExtraBytes = shared.networkDefaultPayloadLengthExtraBytes
if addressVersionNumber == 3: #currently the only one supported. if addressVersionNumber == 3: #currently the only one supported.
if deterministicPassphrase == "": if command == 'createRandomAddress':
shared.UISignalQueue.put(('updateStatusBar','Generating one new address')) shared.UISignalQueue.put(('updateStatusBar','Generating one new address'))
#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 starts with either \x00 or \x00\x00. Then when we pack them into a Bitmessage address, #find one that starts with either \x00 or \x00\x00. Then when we pack them into a Bitmessage address,
@ -3300,10 +3299,12 @@ class addressGenerator(threading.Thread):
shared.reloadMyAddressHashes() shared.reloadMyAddressHashes()
shared.workerQueue.put(('doPOWForMyV3Pubkey',ripe.digest())) shared.workerQueue.put(('doPOWForMyV3Pubkey',ripe.digest()))
else: #There is something in the deterministicPassphrase variable thus we are going to do this deterministically. elif command == 'createDeterministicAddresses' or command == 'getDeterministicAddress':
statusbar = 'Generating '+str(numberOfAddressesToMake) + ' new addresses.' if len(deterministicPassphrase) == 0:
#self.emit(SIGNAL("updateStatusBar(PyQt_PyObject)"),statusbar) sys.stderr.write('WARNING: You are creating deterministic address(es) using a blank passphrase. Bitmessage will do it but it is rather stupid.')
shared.UISignalQueue.put(('updateStatusBar',statusbar)) if command == 'createDeterministicAddresses':
statusbar = 'Generating '+str(numberOfAddressesToMake) + ' new addresses.'
shared.UISignalQueue.put(('updateStatusBar',statusbar))
signingKeyNonce = 0 signingKeyNonce = 0
encryptionKeyNonce = 1 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. listOfNewAddressesToSendOutThroughTheAPI = [] #We fill out this list no matter what although we only need it if we end up passing the info to the API.
@ -3339,44 +3340,49 @@ class addressGenerator(threading.Thread):
print 'ripe.digest', ripe.digest().encode('hex') print 'ripe.digest', ripe.digest().encode('hex')
print 'Address generator calculated', numberOfAddressesWeHadToMakeBeforeWeFoundOneWithTheCorrectRipePrefix, 'addresses at', numberOfAddressesWeHadToMakeBeforeWeFoundOneWithTheCorrectRipePrefix/(time.time()-startTime),'keys per second.' print 'Address generator calculated', numberOfAddressesWeHadToMakeBeforeWeFoundOneWithTheCorrectRipePrefix, 'addresses at', numberOfAddressesWeHadToMakeBeforeWeFoundOneWithTheCorrectRipePrefix/(time.time()-startTime),'keys per second.'
address = encodeAddress(3,streamNumber,ripe.digest()) 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. if command == 'createDeterministicAddresses':
#https://en.bitcoin.it/wiki/Wallet_import_format #An excellent way for us to store our keys is in Wallet Import Format. Let us convert now.
privSigningKey = '\x80'+potentialPrivSigningKey #https://en.bitcoin.it/wiki/Wallet_import_format
checksum = hashlib.sha256(hashlib.sha256(privSigningKey).digest()).digest()[0:4] privSigningKey = '\x80'+potentialPrivSigningKey
privSigningKeyWIF = arithmetic.changebase(privSigningKey + checksum,256,58) checksum = hashlib.sha256(hashlib.sha256(privSigningKey).digest()).digest()[0:4]
privSigningKeyWIF = arithmetic.changebase(privSigningKey + checksum,256,58)
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)
try: try:
shared.config.add_section(address) shared.config.add_section(address)
print 'label:', label print 'label:', label
shared.config.set(address,'label',label) shared.config.set(address,'label',label)
shared.config.set(address,'enabled','true') shared.config.set(address,'enabled','true')
shared.config.set(address,'decoy','false') shared.config.set(address,'decoy','false')
shared.config.set(address,'noncetrialsperbyte',str(nonceTrialsPerByte)) shared.config.set(address,'noncetrialsperbyte',str(nonceTrialsPerByte))
shared.config.set(address,'payloadlengthextrabytes',str(payloadLengthExtraBytes)) shared.config.set(address,'payloadlengthextrabytes',str(payloadLengthExtraBytes))
shared.config.set(address,'privSigningKey',privSigningKeyWIF) shared.config.set(address,'privSigningKey',privSigningKeyWIF)
shared.config.set(address,'privEncryptionKey',privEncryptionKeyWIF) shared.config.set(address,'privEncryptionKey',privEncryptionKeyWIF)
with open(shared.appdata + 'keys.dat', 'wb') as configfile: with open(shared.appdata + 'keys.dat', 'wb') as configfile:
shared.config.write(configfile) shared.config.write(configfile)
#self.emit(SIGNAL("writeNewAddressToTable(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"),self.label,address,str(self.streamNumber)) #self.emit(SIGNAL("writeNewAddressToTable(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"),self.label,address,str(self.streamNumber))
shared.UISignalQueue.put(('writeNewAddressToTable',(label,address,str(streamNumber)))) shared.UISignalQueue.put(('writeNewAddressToTable',(label,address,str(streamNumber))))
listOfNewAddressesToSendOutThroughTheAPI.append(address) listOfNewAddressesToSendOutThroughTheAPI.append(address)
if eighteenByteRipe: if eighteenByteRipe:
shared.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. shared.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: except:
print address,'already exists. Not adding it again.' print address,'already exists. Not adding it again.'
#Done generating addresses.
#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. #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) if command == 'createDeterministicAddresses':
#self.emit(SIGNAL("updateStatusBar(PyQt_PyObject)"),'Done generating address') apiAddressGeneratorReturnQueue.put(listOfNewAddressesToSendOutThroughTheAPI)
shared.UISignalQueue.put(('updateStatusBar','Done generating address')) shared.UISignalQueue.put(('updateStatusBar','Done generating address'))
shared.reloadMyAddressHashes() shared.reloadMyAddressHashes()
elif command == 'getDeterministicAddress':
apiAddressGeneratorReturnQueue.put(address)
else:
raise Exception("Error in the addressGenerator thread. Thread was given a command it could not understand: "+command)
#This is one of several classes that constitute the API #This is one of several classes that constitute the API
#This class was written by Vaibhav Bhatia. Modified by Jonathan Warren (Atheros). #This class was written by Vaibhav Bhatia. Modified by Jonathan Warren (Atheros).
@ -3511,7 +3517,7 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
label = label.decode('base64') label = label.decode('base64')
apiAddressGeneratorReturnQueue.queue.clear() apiAddressGeneratorReturnQueue.queue.clear()
streamNumberForAddress = 1 streamNumberForAddress = 1
shared.addressGeneratorQueue.put((3,streamNumberForAddress,label,1,"",eighteenByteRipe,nonceTrialsPerByte,payloadLengthExtraBytes)) shared.addressGeneratorQueue.put(('createRandomAddress',3,streamNumberForAddress,label,1,"",eighteenByteRipe,nonceTrialsPerByte,payloadLengthExtraBytes))
return apiAddressGeneratorReturnQueue.get() return apiAddressGeneratorReturnQueue.get()
elif method == 'createDeterministicAddresses': elif method == 'createDeterministicAddresses':
if len(params) == 0: if len(params) == 0:
@ -3562,7 +3568,7 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
if addressVersionNumber == 0: #0 means "just use the proper addressVersionNumber" if addressVersionNumber == 0: #0 means "just use the proper addressVersionNumber"
addressVersionNumber = 3 addressVersionNumber = 3
if addressVersionNumber != 3: if addressVersionNumber != 3:
return 'API Error 0002: The address version number currently must be 3 (or 0 which means auto-select).', addressVersionNumber,' isn\'t supported.' return 'API Error 0002: The address version number currently must be 3 (or 0 which means auto-select). '+ addressVersionNumber+' isn\'t supported.'
if streamNumber == 0: #0 means "just use the most available stream" if streamNumber == 0: #0 means "just use the most available stream"
streamNumber = 1 streamNumber = 1
if streamNumber != 1: if streamNumber != 1:
@ -3573,7 +3579,7 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
return 'API Error 0005: You have (accidentally?) specified too many addresses to make. Maximum 999. 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 (accidentally?) specified too many addresses to make. Maximum 999. 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 'Requesting that the addressGenerator create', numberOfAddresses, 'addresses.' print 'Requesting that the addressGenerator create', numberOfAddresses, 'addresses.'
shared.addressGeneratorQueue.put((addressVersionNumber,streamNumber,'unused API address',numberOfAddresses,passphrase,eighteenByteRipe,nonceTrialsPerByte,payloadLengthExtraBytes)) shared.addressGeneratorQueue.put(('createDeterministicAddresses',addressVersionNumber,streamNumber,'unused API address',numberOfAddresses,passphrase,eighteenByteRipe,nonceTrialsPerByte,payloadLengthExtraBytes))
data = '{"addresses":[' data = '{"addresses":['
queueReturn = apiAddressGeneratorReturnQueue.get() queueReturn = apiAddressGeneratorReturnQueue.get()
for item in queueReturn: for item in queueReturn:
@ -3582,6 +3588,23 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
data += "\""+item+ "\"" data += "\""+item+ "\""
data += ']}' data += ']}'
return data return data
elif method == 'getDeterministicAddress':
if len(params) != 3:
return 'API Error 0000: I need exactly 3 parameters.'
passphrase, addressVersionNumber, streamNumber = params
numberOfAddresses = 1
eighteenByteRipe = False
if len(passphrase) == 0:
return 'API Error 0001: The specified passphrase is blank.'
passphrase = passphrase.decode('base64')
if addressVersionNumber != 3:
return 'API Error 0002: The address version number currently must be 3. '+ addressVersionNumber +' isn\'t supported.'
if streamNumber != 1:
return 'API Error 0003: The stream number must be 1. Others aren\'t supported.'
apiAddressGeneratorReturnQueue.queue.clear()
print 'Requesting that the addressGenerator create', numberOfAddresses, 'addresses.'
shared.addressGeneratorQueue.put(('getDeterministicAddress',addressVersionNumber,streamNumber,'unused API address',numberOfAddresses,passphrase,eighteenByteRipe))
return apiAddressGeneratorReturnQueue.get()
elif method == 'getAllInboxMessages': elif method == 'getAllInboxMessages':
shared.sqlLock.acquire() shared.sqlLock.acquire()
shared.sqlSubmitQueue.put('''SELECT msgid, toaddress, fromaddress, subject, received, message FROM inbox where folder='inbox' ORDER BY received''') shared.sqlSubmitQueue.put('''SELECT msgid, toaddress, fromaddress, subject, received, message FROM inbox where folder='inbox' ORDER BY received''')
@ -3632,6 +3655,7 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
return 'API Error 0009: Invalid characters in address: '+ toAddress return 'API Error 0009: Invalid characters in address: '+ toAddress
if status == 'versiontoohigh': if status == 'versiontoohigh':
return 'API Error 0010: Address version number too high (or zero) in address: ' + toAddress return 'API Error 0010: Address version number too high (or zero) in address: ' + toAddress
return 'API Error 0007: Could not decode address: ' + toAddress+ ' : '+ status
if addressVersionNumber < 2 or addressVersionNumber > 3: if addressVersionNumber < 2 or addressVersionNumber > 3:
return 'API Error 0011: The address version number currently must be 2 or 3. Others aren\'t supported. Check the toAddress.' return 'API Error 0011: The address version number currently must be 2 or 3. Others aren\'t supported. Check the toAddress.'
if streamNumber != 1: if streamNumber != 1:
@ -3647,6 +3671,7 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
return 'API Error 0009: Invalid characters in address: '+ fromAddress return 'API Error 0009: Invalid characters in address: '+ fromAddress
if status == 'versiontoohigh': if status == 'versiontoohigh':
return 'API Error 0010: Address version number too high (or zero) in address: ' + fromAddress return 'API Error 0010: Address version number too high (or zero) in address: ' + fromAddress
return 'API Error 0007: Could not decode address: ' + fromAddress+ ' : '+ status
if addressVersionNumber < 2 or addressVersionNumber > 3: if addressVersionNumber < 2 or addressVersionNumber > 3:
return 'API Error 0011: The address version number currently must be 2 or 3. Others aren\'t supported. Check the fromAddress.' return 'API Error 0011: The address version number currently must be 2 or 3. Others aren\'t supported. Check the fromAddress.'
if streamNumber != 1: if streamNumber != 1:
@ -3710,6 +3735,7 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
return 'API Error 0009: Invalid characters in address: '+ fromAddress return 'API Error 0009: Invalid characters in address: '+ fromAddress
if status == 'versiontoohigh': if status == 'versiontoohigh':
return 'API Error 0010: Address version number too high (or zero) in address: ' + fromAddress return 'API Error 0010: Address version number too high (or zero) in address: ' + fromAddress
return 'API Error 0007: Could not decode address: ' + fromAddress+ ' : '+ status
if addressVersionNumber < 2 or addressVersionNumber > 3: if addressVersionNumber < 2 or addressVersionNumber > 3:
return 'API Error 0011: the address version number currently must be 2 or 3. Others aren\'t supported. Check the fromAddress.' return 'API Error 0011: the address version number currently must be 2 or 3. Others aren\'t supported. Check the fromAddress.'
if streamNumber != 1: if streamNumber != 1:
@ -3763,6 +3789,75 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
return 'ackReceived' return 'ackReceived'
else: else:
return 'otherStatus: '+status return 'otherStatus: '+status
elif method == 'addSubscription':
if len(params) == 0:
return 'API Error 0000: I need parameters!'
if len(params) == 1:
address, = params
label == ''
if len(params) == 2:
address, label = params
label = label.decode('base64')
try:
label.decode('utf-8')
except UnicodeDecodeError:
return 'API Error 0017: Label is not valid UTF-8 data.'
if len(params) >2:
return 'API Error 0000: I need either 1 or 2 parameters!'
address = addBMIfNotPresent(address)
status,addressVersionNumber,streamNumber,toRipe = decodeAddress(address)
if status <> 'success':
shared.printLock.acquire()
print 'API Error 0007: Could not decode address:', address, ':', status
shared.printLock.release()
if status == 'checksumfailed':
return 'API Error 0008: Checksum failed for address: ' + address
if status == 'invalidcharacters':
return 'API Error 0009: Invalid characters in address: '+ address
if status == 'versiontoohigh':
return 'API Error 0010: Address version number too high (or zero) in address: ' + address
return 'API Error 0007: Could not decode address: ' + address+ ' : '+ status
if addressVersionNumber < 2 or addressVersionNumber > 3:
return 'API Error 0011: The address version number currently must be 2 or 3. Others aren\'t supported.'
if streamNumber != 1:
return 'API Error 0012: The stream number must be 1. Others aren\'t supported.'
#First we must check to see if the address is already in the subscriptions list.
shared.sqlLock.acquire()
t = (address,)
shared.sqlSubmitQueue.put('''select * from subscriptions where address=?''')
shared.sqlSubmitQueue.put(t)
queryreturn = shared.sqlReturnQueue.get()
shared.sqlLock.release()
if queryreturn != []:
return 'API Error 0016: You are already subscribed to that address.'
t = (label,address,True)
shared.sqlLock.acquire()
shared.sqlSubmitQueue.put('''INSERT INTO subscriptions VALUES (?,?,?)''')
shared.sqlSubmitQueue.put(t)
queryreturn = shared.sqlReturnQueue.get()
shared.sqlSubmitQueue.put('commit')
shared.sqlLock.release()
shared.reloadBroadcastSendersForWhichImWatching()
shared.UISignalQueue.put(('rerenderInboxFromLabels',''))
shared.UISignalQueue.put(('rerenderSubscriptions',''))
return 'Added subscription.'
elif method == 'deleteSubscription':
if len(params) != 1:
return 'API Error 0000: I need 1 parameter!'
address, = params
address = addBMIfNotPresent(address)
t = (address,)
shared.sqlLock.acquire()
shared.sqlSubmitQueue.put('''DELETE FROM subscriptions WHERE address=?''')
shared.sqlSubmitQueue.put(t)
shared.sqlReturnQueue.get()
shared.sqlSubmitQueue.put('commit')
shared.sqlLock.release()
shared.reloadBroadcastSendersForWhichImWatching()
shared.UISignalQueue.put(('rerenderInboxFromLabels',''))
shared.UISignalQueue.put(('rerenderSubscriptions',''))
return 'Deleted subscription if it existed.'
else: else:
return 'Invalid Method: %s'%method return 'Invalid Method: %s'%method
@ -3776,37 +3871,6 @@ class singleAPI(threading.Thread):
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):
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()
shared.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()
shared.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)
alreadyAttemptedConnectionsList = {} #This is a list of nodes to which we have already attempted a connection alreadyAttemptedConnectionsList = {} #This is a list of nodes to which we have already attempted a connection
ackdataForWhichImWatching = {} ackdataForWhichImWatching = {}

View File

@ -393,23 +393,7 @@ class MyForm(QtGui.QMainWindow):
self.ui.tableWidgetAddressBook.setItem(0,1,newItem) self.ui.tableWidgetAddressBook.setItem(0,1,newItem)
#Initialize the Subscriptions #Initialize the Subscriptions
shared.sqlLock.acquire() self.rerenderSubscriptions()
shared.sqlSubmitQueue.put('SELECT label, address, enabled FROM subscriptions')
shared.sqlSubmitQueue.put('')
queryreturn = shared.sqlReturnQueue.get()
shared.sqlLock.release()
for row in queryreturn:
label, address, enabled = row
self.ui.tableWidgetSubscriptions.insertRow(0)
newItem = QtGui.QTableWidgetItem(unicode(label,'utf-8'))
if not enabled:
newItem.setTextColor(QtGui.QColor(128,128,128))
self.ui.tableWidgetSubscriptions.setItem(0,0,newItem)
newItem = QtGui.QTableWidgetItem(address)
newItem.setFlags( QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled )
if not enabled:
newItem.setTextColor(QtGui.QColor(128,128,128))
self.ui.tableWidgetSubscriptions.setItem(0,1,newItem)
#Initialize the Blacklist or Whitelist #Initialize the Blacklist or Whitelist
if shared.config.get('bitmessagesettings', 'blackwhitelist') == 'black': if shared.config.get('bitmessagesettings', 'blackwhitelist') == 'black':
@ -447,6 +431,8 @@ class MyForm(QtGui.QMainWindow):
QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL("incrementNumberOfPubkeysProcessed()"), self.incrementNumberOfPubkeysProcessed) 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("incrementNumberOfBroadcastsProcessed()"), self.incrementNumberOfBroadcastsProcessed)
QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL("setStatusIcon(PyQt_PyObject)"), self.setStatusIcon) QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL("setStatusIcon(PyQt_PyObject)"), self.setStatusIcon)
QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL("rerenderInboxFromLabels()"), self.rerenderInboxFromLabels)
QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL("rerenderSubscriptions()"), self.rerenderSubscriptions)
self.UISignalThread.start() self.UISignalThread.start()
#Below this point, it would be good if all of the necessary global data structures were initialized. #Below this point, it would be good if all of the necessary global data structures were initialized.
@ -795,7 +781,7 @@ class MyForm(QtGui.QMainWindow):
#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()
shared.addressGeneratorQueue.put((addressVersionNumber,streamNumberForAddress,"regenerated deterministic address",self.regenerateAddressesDialogInstance.ui.spinBoxNumberOfAddressesToMake.value(),self.regenerateAddressesDialogInstance.ui.lineEditPassphrase.text().toUtf8(),self.regenerateAddressesDialogInstance.ui.checkBoxEighteenByteRipe.isChecked())) shared.addressGeneratorQueue.put(('createDeterministicAddresses',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):
@ -1031,6 +1017,26 @@ class MyForm(QtGui.QMainWindow):
toLabel, = row toLabel, = row
self.ui.tableWidgetSent.item(i,0).setText(unicode(toLabel,'utf-8')) self.ui.tableWidgetSent.item(i,0).setText(unicode(toLabel,'utf-8'))
def rerenderSubscriptions(self):
self.ui.tableWidgetSubscriptions.setRowCount(0)
shared.sqlLock.acquire()
shared.sqlSubmitQueue.put('SELECT label, address, enabled FROM subscriptions')
shared.sqlSubmitQueue.put('')
queryreturn = shared.sqlReturnQueue.get()
shared.sqlLock.release()
for row in queryreturn:
label, address, enabled = row
self.ui.tableWidgetSubscriptions.insertRow(0)
newItem = QtGui.QTableWidgetItem(unicode(label,'utf-8'))
if not enabled:
newItem.setTextColor(QtGui.QColor(128,128,128))
self.ui.tableWidgetSubscriptions.setItem(0,0,newItem)
newItem = QtGui.QTableWidgetItem(address)
newItem.setFlags( QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled )
if not enabled:
newItem.setTextColor(QtGui.QColor(128,128,128))
self.ui.tableWidgetSubscriptions.setItem(0,1,newItem)
def click_pushButtonSend(self): def click_pushButtonSend(self):
self.statusBar().showMessage('') self.statusBar().showMessage('')
toAddresses = str(self.ui.lineEditTo.text()) toAddresses = str(self.ui.lineEditTo.text())
@ -1358,7 +1364,7 @@ class MyForm(QtGui.QMainWindow):
if self.NewSubscriptionDialogInstance.exec_(): if self.NewSubscriptionDialogInstance.exec_():
if self.NewSubscriptionDialogInstance.ui.labelSubscriptionAddressCheck.text() == 'Address is valid.': if self.NewSubscriptionDialogInstance.ui.labelSubscriptionAddressCheck.text() == 'Address is valid.':
#First we must check to see if the address is already in the address book. The user cannot add it again or else it will cause problems when updating and deleting the entry. #First we must check to see if the address is already in the subscriptions list. The user cannot add it again or else it will cause problems when updating and deleting the entry.
shared.sqlLock.acquire() shared.sqlLock.acquire()
t = (addBMIfNotPresent(str(self.NewSubscriptionDialogInstance.ui.lineEditSubscriptionAddress.text())),) t = (addBMIfNotPresent(str(self.NewSubscriptionDialogInstance.ui.lineEditSubscriptionAddress.text())),)
shared.sqlSubmitQueue.put('''select * from subscriptions where address=?''') shared.sqlSubmitQueue.put('''select * from subscriptions where address=?''')
@ -1605,7 +1611,7 @@ class MyForm(QtGui.QMainWindow):
#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()
shared.addressGeneratorQueue.put((3,streamNumberForAddress,str(self.dialog.ui.newaddresslabel.text().toUtf8()),1,"",self.dialog.ui.checkBoxEighteenByteRipe.isChecked())) shared.addressGeneratorQueue.put(('createRandomAddress',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.")
@ -1618,7 +1624,7 @@ class MyForm(QtGui.QMainWindow):
#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()
shared.addressGeneratorQueue.put((3,streamNumberForAddress,"unused deterministic address",self.dialog.ui.spinBoxNumberOfAddressesToMake.value(),self.dialog.ui.lineEditPassphrase.text().toUtf8(),self.dialog.ui.checkBoxEighteenByteRipe.isChecked())) shared.addressGeneratorQueue.put(('createDeterministicAddresses',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'
@ -2287,6 +2293,10 @@ class UISignaler(QThread):
self.emit(SIGNAL("incrementNumberOfBroadcastsProcessed()")) self.emit(SIGNAL("incrementNumberOfBroadcastsProcessed()"))
elif command == 'setStatusIcon': elif command == 'setStatusIcon':
self.emit(SIGNAL("setStatusIcon(PyQt_PyObject)"),data) self.emit(SIGNAL("setStatusIcon(PyQt_PyObject)"),data)
elif command == 'rerenderInboxFromLabels':
self.emit(SIGNAL("rerenderInboxFromLabels()"))
elif command == 'rerenderSubscriptions':
self.emit(SIGNAL("rerenderSubscriptions()"))
else: else:
sys.stderr.write('Command sent to UISignaler not recognized: %s\n' % command) sys.stderr.write('Command sent to UISignaler not recognized: %s\n' % command)

View File

@ -2,7 +2,7 @@
# Form implementation generated from reading ui file 'bitmessageui.ui' # Form implementation generated from reading ui file 'bitmessageui.ui'
# #
# Created: Tue May 21 14:09:58 2013 # Created: Fri May 24 16:22:22 2013
# by: PyQt4 UI code generator 4.9.4 # by: PyQt4 UI code generator 4.9.4
# #
# WARNING! All changes made in this file will be lost! # WARNING! All changes made in this file will be lost!
@ -500,7 +500,7 @@ class Ui_MainWindow(object):
item.setText(QtGui.QApplication.translate("MainWindow", "Stream", None, QtGui.QApplication.UnicodeUTF8)) item.setText(QtGui.QApplication.translate("MainWindow", "Stream", None, QtGui.QApplication.UnicodeUTF8))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.youridentities), QtGui.QApplication.translate("MainWindow", "Your Identities", None, QtGui.QApplication.UnicodeUTF8)) self.tabWidget.setTabText(self.tabWidget.indexOf(self.youridentities), QtGui.QApplication.translate("MainWindow", "Your Identities", None, QtGui.QApplication.UnicodeUTF8))
self.label_5.setText(QtGui.QApplication.translate("MainWindow", "Here you can subscribe to \'broadcast messages\' that are sent by other users. Messages will appear in your Inbox. Addresses here override those on the Blacklist tab.", None, QtGui.QApplication.UnicodeUTF8)) self.label_5.setText(QtGui.QApplication.translate("MainWindow", "Here you can subscribe to \'broadcast messages\' that are sent by other users. Messages will appear in your Inbox. Addresses here override those on the Blacklist tab.", None, QtGui.QApplication.UnicodeUTF8))
self.pushButtonAddSubscription.setText(QtGui.QApplication.translate("MainWindow", "Add", None, QtGui.QApplication.UnicodeUTF8)) self.pushButtonAddSubscription.setText(QtGui.QApplication.translate("MainWindow", "Add new Subscription", None, QtGui.QApplication.UnicodeUTF8))
self.tableWidgetSubscriptions.setSortingEnabled(True) self.tableWidgetSubscriptions.setSortingEnabled(True)
item = self.tableWidgetSubscriptions.horizontalHeaderItem(0) item = self.tableWidgetSubscriptions.horizontalHeaderItem(0)
item.setText(QtGui.QApplication.translate("MainWindow", "Label", None, QtGui.QApplication.UnicodeUTF8)) item.setText(QtGui.QApplication.translate("MainWindow", "Label", None, QtGui.QApplication.UnicodeUTF8))
@ -508,7 +508,7 @@ class Ui_MainWindow(object):
item.setText(QtGui.QApplication.translate("MainWindow", "Address", None, QtGui.QApplication.UnicodeUTF8)) item.setText(QtGui.QApplication.translate("MainWindow", "Address", None, QtGui.QApplication.UnicodeUTF8))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.subscriptions), QtGui.QApplication.translate("MainWindow", "Subscriptions", None, QtGui.QApplication.UnicodeUTF8)) self.tabWidget.setTabText(self.tabWidget.indexOf(self.subscriptions), QtGui.QApplication.translate("MainWindow", "Subscriptions", None, QtGui.QApplication.UnicodeUTF8))
self.label_6.setText(QtGui.QApplication.translate("MainWindow", "The Address book is useful for adding names or labels to other people\'s Bitmessage addresses so that you can recognize them more easily in your inbox. You can add entries here using the \'Add\' button, or from your inbox by right-clicking on a message.", None, QtGui.QApplication.UnicodeUTF8)) self.label_6.setText(QtGui.QApplication.translate("MainWindow", "The Address book is useful for adding names or labels to other people\'s Bitmessage addresses so that you can recognize them more easily in your inbox. You can add entries here using the \'Add\' button, or from your inbox by right-clicking on a message.", None, QtGui.QApplication.UnicodeUTF8))
self.pushButtonAddAddressBook.setText(QtGui.QApplication.translate("MainWindow", "Add", None, QtGui.QApplication.UnicodeUTF8)) self.pushButtonAddAddressBook.setText(QtGui.QApplication.translate("MainWindow", "Add new entry", None, QtGui.QApplication.UnicodeUTF8))
self.tableWidgetAddressBook.setSortingEnabled(True) self.tableWidgetAddressBook.setSortingEnabled(True)
item = self.tableWidgetAddressBook.horizontalHeaderItem(0) item = self.tableWidgetAddressBook.horizontalHeaderItem(0)
item.setText(QtGui.QApplication.translate("MainWindow", "Name or Label", None, QtGui.QApplication.UnicodeUTF8)) item.setText(QtGui.QApplication.translate("MainWindow", "Name or Label", None, QtGui.QApplication.UnicodeUTF8))
@ -517,7 +517,7 @@ class Ui_MainWindow(object):
self.tabWidget.setTabText(self.tabWidget.indexOf(self.addressbook), QtGui.QApplication.translate("MainWindow", "Address Book", None, QtGui.QApplication.UnicodeUTF8)) self.tabWidget.setTabText(self.tabWidget.indexOf(self.addressbook), QtGui.QApplication.translate("MainWindow", "Address Book", None, QtGui.QApplication.UnicodeUTF8))
self.radioButtonBlacklist.setText(QtGui.QApplication.translate("MainWindow", "Use a Blacklist (Allow all incoming messages except those on the Blacklist)", None, QtGui.QApplication.UnicodeUTF8)) self.radioButtonBlacklist.setText(QtGui.QApplication.translate("MainWindow", "Use a Blacklist (Allow all incoming messages except those on the Blacklist)", None, QtGui.QApplication.UnicodeUTF8))
self.radioButtonWhitelist.setText(QtGui.QApplication.translate("MainWindow", "Use a Whitelist (Block all incoming messages except those on the Whitelist)", None, QtGui.QApplication.UnicodeUTF8)) self.radioButtonWhitelist.setText(QtGui.QApplication.translate("MainWindow", "Use a Whitelist (Block all incoming messages except those on the Whitelist)", None, QtGui.QApplication.UnicodeUTF8))
self.pushButtonAddBlacklist.setText(QtGui.QApplication.translate("MainWindow", "Add", None, QtGui.QApplication.UnicodeUTF8)) self.pushButtonAddBlacklist.setText(QtGui.QApplication.translate("MainWindow", "Add new entry", None, QtGui.QApplication.UnicodeUTF8))
self.tableWidgetBlacklist.setSortingEnabled(True) self.tableWidgetBlacklist.setSortingEnabled(True)
item = self.tableWidgetBlacklist.horizontalHeaderItem(0) item = self.tableWidgetBlacklist.horizontalHeaderItem(0)
item.setText(QtGui.QApplication.translate("MainWindow", "Name or Label", None, QtGui.QApplication.UnicodeUTF8)) item.setText(QtGui.QApplication.translate("MainWindow", "Name or Label", None, QtGui.QApplication.UnicodeUTF8))

View File

@ -500,7 +500,7 @@ p, li { white-space: pre-wrap; }
<item row="1" column="0"> <item row="1" column="0">
<widget class="QPushButton" name="pushButtonAddSubscription"> <widget class="QPushButton" name="pushButtonAddSubscription">
<property name="text"> <property name="text">
<string>Add</string> <string>Add new Subscription</string>
</property> </property>
</widget> </widget>
</item> </item>
@ -585,7 +585,7 @@ p, li { white-space: pre-wrap; }
<item row="1" column="0"> <item row="1" column="0">
<widget class="QPushButton" name="pushButtonAddAddressBook"> <widget class="QPushButton" name="pushButtonAddAddressBook">
<property name="text"> <property name="text">
<string>Add</string> <string>Add new entry</string>
</property> </property>
</widget> </widget>
</item> </item>
@ -674,7 +674,7 @@ p, li { white-space: pre-wrap; }
<item row="2" column="0"> <item row="2" column="0">
<widget class="QPushButton" name="pushButtonAddBlacklist"> <widget class="QPushButton" name="pushButtonAddBlacklist">
<property name="text"> <property name="text">
<string>Add</string> <string>Add new entry</string>
</property> </property>
</widget> </widget>
</item> </item>

View File

@ -1,4 +1,4 @@
softwareVersion = '0.3.0' softwareVersion = '0.3.1'
import threading import threading
import sys import sys