conflict fix
This commit is contained in:
commit
b3fa3a6fe7
|
@ -12,7 +12,7 @@ lengthOfTimeToLeaveObjectsInInventory = 237600 #Equals two days and 18 hours. Th
|
||||||
maximumAgeOfObjectsThatIAdvertiseToOthers = 216000 #Equals two days and 12 hours
|
maximumAgeOfObjectsThatIAdvertiseToOthers = 216000 #Equals two days and 12 hours
|
||||||
maximumAgeOfNodesThatIAdvertiseToOthers = 10800 #Equals three hours
|
maximumAgeOfNodesThatIAdvertiseToOthers = 10800 #Equals three hours
|
||||||
storeConfigFilesInSameDirectoryAsProgram = False
|
storeConfigFilesInSameDirectoryAsProgram = False
|
||||||
userVeryEasyProofOfWorkForTesting = False #If you set this to True while on the normal network, you won't be able to send or sometimes receive messages.
|
useVeryEasyProofOfWorkForTesting = False #If you set this to True while on the normal network, you won't be able to send or sometimes receive messages.
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
try:
|
try:
|
||||||
|
@ -688,6 +688,9 @@ class receiveDataThread(QThread):
|
||||||
print 'Length of the unencrypted data is unreasonably short. Sanity check failed. Ignoring message.'
|
print 'Length of the unencrypted data is unreasonably short. Sanity check failed. Ignoring message.'
|
||||||
return
|
return
|
||||||
sendersStreamNumber, sendersStreamNumberLength = decodeVarint(data[readPosition:readPosition+10])
|
sendersStreamNumber, sendersStreamNumberLength = decodeVarint(data[readPosition:readPosition+10])
|
||||||
|
if sendersStreamNumber == 0:
|
||||||
|
print 'sender\'s stream number is 0. Ignoring message.'
|
||||||
|
return
|
||||||
readPosition += sendersStreamNumberLength
|
readPosition += sendersStreamNumberLength
|
||||||
behaviorBitfield = data[readPosition:readPosition+4]
|
behaviorBitfield = data[readPosition:readPosition+4]
|
||||||
readPosition += 4
|
readPosition += 4
|
||||||
|
@ -876,6 +879,9 @@ class receiveDataThread(QThread):
|
||||||
if sendersAddressVersionNumber == 1:
|
if sendersAddressVersionNumber == 1:
|
||||||
readPosition += sendersAddressVersionNumberLength
|
readPosition += sendersAddressVersionNumberLength
|
||||||
sendersStreamNumber, sendersStreamNumberLength = decodeVarint(data[readPosition:readPosition+10])
|
sendersStreamNumber, sendersStreamNumberLength = decodeVarint(data[readPosition:readPosition+10])
|
||||||
|
if sendersStreamNumber == 0:
|
||||||
|
print 'sendersStreamNumber = 0. Ignoring message'
|
||||||
|
else:
|
||||||
readPosition += sendersStreamNumberLength
|
readPosition += sendersStreamNumberLength
|
||||||
|
|
||||||
sendersNLength, sendersNLengthLength = decodeVarint(data[readPosition:readPosition+10])
|
sendersNLength, sendersNLengthLength = decodeVarint(data[readPosition:readPosition+10])
|
||||||
|
@ -977,6 +983,7 @@ class receiveDataThread(QThread):
|
||||||
toLabel = config.get(addressInKeysFile, 'label')
|
toLabel = config.get(addressInKeysFile, 'label')
|
||||||
if toLabel == '':
|
if toLabel == '':
|
||||||
toLabel = addressInKeysFile
|
toLabel = addressInKeysFile
|
||||||
|
break
|
||||||
|
|
||||||
if messageEncodingType == 2:
|
if messageEncodingType == 2:
|
||||||
bodyPositionIndex = string.find(message,'\nBody:')
|
bodyPositionIndex = string.find(message,'\nBody:')
|
||||||
|
@ -1003,13 +1010,8 @@ class receiveDataThread(QThread):
|
||||||
sqlReturnQueue.get()
|
sqlReturnQueue.get()
|
||||||
sqlLock.release()
|
sqlLock.release()
|
||||||
self.emit(SIGNAL("displayNewMessage(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"),inventoryHash,toAddress,fromAddress,subject,body)
|
self.emit(SIGNAL("displayNewMessage(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"),inventoryHash,toAddress,fromAddress,subject,body)
|
||||||
#Now let's send the acknowledgement
|
#Now let us worry about the acknowledgement data
|
||||||
#POW, = unpack('>Q',hashlib.sha512(hashlib.sha512(ackData[24:]).digest()).digest()[4:12])
|
#We'll need to make sure that our client will properly process the ackData; if the packet is malformed, it might cause us to clear out self.data and an attacker could use that behavior to determine that we decoded this message.
|
||||||
#if POW <= 2**64 / ((len(ackData[24:])+payloadLengthExtraBytes) * averageProofOfWorkNonceTrialsPerByte):
|
|
||||||
#print 'The POW is strong enough that this ackdataPayload will be accepted by the Bitmessage network.'
|
|
||||||
#Currently PyBitmessage only supports sending a message with the acknowledgement in the form of a msg message. But future versions, and other clients, could send any object and this software will relay them. This can be used to relay identifying information, like your public key, through another Bitmessage host in case you believe that your Internet connection is being individually watched. You may pick a random address, hope its owner is online, and send a message with encoding type 0 so that they ignore the message but send your acknowledgement data over the network. If you send and receive many messages, it would also be clever to take someone else's acknowledgement data and use it for your own. Assuming that your message is delivered successfully, both will be acknowledged simultaneously (though if it is not delivered successfully, you will be in a pickle.)
|
|
||||||
#print 'self.data before:', repr(self.data)
|
|
||||||
#We'll need to make sure that our client will properly process the ackData; if the packet is malformed, we could clear out self.data and an attacker could use that behavior to determine that we were capable of decoding this message.
|
|
||||||
ackDataValidThusFar = True
|
ackDataValidThusFar = True
|
||||||
if len(ackData) < 24:
|
if len(ackData) < 24:
|
||||||
print 'The length of ackData is unreasonably short. Not sending ackData.'
|
print 'The length of ackData is unreasonably short. Not sending ackData.'
|
||||||
|
@ -1019,46 +1021,18 @@ class receiveDataThread(QThread):
|
||||||
ackDataValidThusFar = False
|
ackDataValidThusFar = False
|
||||||
if ackDataValidThusFar:
|
if ackDataValidThusFar:
|
||||||
ackDataPayloadLength, = unpack('>L',ackData[16:20])
|
ackDataPayloadLength, = unpack('>L',ackData[16:20])
|
||||||
if len(ackData)-24 != ackDataPayloadLength:
|
if len(ackData)-24 != ackDataPayloadLength: #This ackData includes the protocol header which is not counted in the payload length.
|
||||||
print 'ackData payload length doesn\'t match the payload length specified in the header. Not sending ackdata.'
|
print 'ackData payload length doesn\'t match the payload length specified in the header. Not sending ackdata.'
|
||||||
ackDataValidThusFar = False
|
ackDataValidThusFar = False
|
||||||
if ackDataValidThusFar:
|
if ackDataValidThusFar:
|
||||||
print 'ackData is valid. Will process it.'
|
print 'ackData is valid. Will process it.'
|
||||||
#self.data = self.data[:self.payloadLength+24] + ackData + self.data[self.payloadLength+24:]
|
|
||||||
self.ackDataThatWeHaveYetToSend.append(ackData) #When we have processed all data, the processData function will pop the ackData out and process it as if it is a message received from our peer.
|
self.ackDataThatWeHaveYetToSend.append(ackData) #When we have processed all data, the processData function will pop the ackData out and process it as if it is a message received from our peer.
|
||||||
#print 'self.data after:', repr(self.data)
|
|
||||||
'''if ackData[4:16] == 'msg\x00\x00\x00\x00\x00\x00\x00\x00\x00':
|
|
||||||
inventoryHash = calculateInventoryHash(ackData[24:])
|
|
||||||
#objectType = 'msg'
|
|
||||||
#inventory[inventoryHash] = (objectType, self.streamNumber, ackData[24:], embeddedTime) #We should probably be storing the embeddedTime of the ackData, not the embeddedTime of the original incoming msg message, but this is probably close enough.
|
|
||||||
#print 'sending the inv for the msg which is actually an acknowledgement (within sendmsg function)'
|
|
||||||
#self.broadcastinv(inventoryHash)
|
|
||||||
self.data[:payloadLength+24] + ackData + self.data[payloadLength+24:]
|
|
||||||
elif ackData[4:16] == 'getpubkey\x00\x00\x00':
|
|
||||||
#objectType = 'getpubkey'
|
|
||||||
#inventory[inventoryHash] = (objectType, self.streamNumber, ackData[24:], embeddedTime) #We should probably be storing the embeddedTime of the ackData, not the embeddedTime of the original incoming msg message, but this is probably close enough.
|
|
||||||
#print 'sending the inv for the getpubkey which is actually an acknowledgement (within sendmsg function)'
|
|
||||||
self.data[:payloadLength+24] + ackData + self.data[payloadLength+24:]
|
|
||||||
elif ackData[4:16] == 'pubkey\x00\x00\x00\x00\x00\x00':
|
|
||||||
#objectType = 'pubkey'
|
|
||||||
#inventory[inventoryHash] = (objectType, self.streamNumber, ackData[24:], embeddedTime) #We should probably be storing the embeddedTime of the ackData, not the embeddedTime of the original incoming msg message, but this is probably close enough.
|
|
||||||
#print 'sending the inv for a pubkey which is actually an acknowledgement (within sendmsg function)'
|
|
||||||
self.data[:payloadLength+24] + ackData + self.data[payloadLength+24:]
|
|
||||||
elif ackData[4:16] == 'broadcast\x00\x00\x00':
|
|
||||||
#objectType = 'broadcast'
|
|
||||||
#inventory[inventoryHash] = (objectType, self.streamNumber, ackData[24:], embeddedTime) #We should probably be storing the embeddedTime of the ackData, not the embeddedTime of the original incoming msg message, but this is probably close enough.
|
|
||||||
#print 'sending the inv for a broadcast which is actually an acknowledgement (within sendmsg function)'
|
|
||||||
self.data[:payloadLength+24] + ackData + self.data[payloadLength+24:]'''
|
|
||||||
#else:
|
|
||||||
#print 'ACK POW not strong enough to be accepted by the Bitmessage network.'
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
print 'This program cannot decode messages from addresses with versions higher than 1. Ignoring.'
|
print 'This program cannot decode messages from addresses with versions higher than 1. Ignoring.'
|
||||||
statusbar = 'This program cannot decode messages from addresses with versions higher than 1. Ignoring it.'
|
statusbar = 'This program cannot decode messages from addresses with versions higher than 1. Ignoring it.'
|
||||||
self.emit(SIGNAL("updateStatusBar(PyQt_PyObject)"),statusbar)
|
self.emit(SIGNAL("updateStatusBar(PyQt_PyObject)"),statusbar)
|
||||||
else:
|
else:
|
||||||
print 'Error: Cannot decode incoming msg versions higher than 1. Assuming the sender isn\' being silly, you should upgrade Bitmessage because this message shall be ignored.'
|
statusbar = 'Error: Cannot decode incoming msg versions higher than 1. Assuming the sender isn\' being silly, you should upgrade Bitmessage. Ignoring message.'
|
||||||
statusbar = 'Error: Cannot decode incoming msg versions higher than 1. Assuming the sender isn\' being silly, you should upgrade Bitmessage because this message shall be ignored.'
|
|
||||||
self.emit(SIGNAL("updateStatusBar(PyQt_PyObject)"),statusbar)
|
self.emit(SIGNAL("updateStatusBar(PyQt_PyObject)"),statusbar)
|
||||||
else:
|
else:
|
||||||
printLock.acquire()
|
printLock.acquire()
|
||||||
|
@ -1087,8 +1061,6 @@ class receiveDataThread(QThread):
|
||||||
inventoryLock.release()
|
inventoryLock.release()
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
readPosition = 24 #for the message header
|
readPosition = 24 #for the message header
|
||||||
readPosition += 8 #for the nonce
|
readPosition += 8 #for the nonce
|
||||||
#bitfieldBehaviors = self.data[readPosition:readPosition+4] The bitfieldBehaviors used to be here
|
#bitfieldBehaviors = self.data[readPosition:readPosition+4] The bitfieldBehaviors used to be here
|
||||||
|
@ -1231,91 +1203,38 @@ class receiveDataThread(QThread):
|
||||||
print 'The addressVersionNumber of the pubkey request is too high. Can\'t understand. Ignoring it.'
|
print 'The addressVersionNumber of the pubkey request is too high. Can\'t understand. Ignoring it.'
|
||||||
return
|
return
|
||||||
print 'the hash requested in this getpubkey request is:', self.data[36+addressVersionLength+streamNumberLength:56+addressVersionLength+streamNumberLength].encode('hex')
|
print 'the hash requested in this getpubkey request is:', self.data[36+addressVersionLength+streamNumberLength:56+addressVersionLength+streamNumberLength].encode('hex')
|
||||||
if self.data[36+addressVersionLength+streamNumberLength:56+addressVersionLength+streamNumberLength] in myECAddressHashes: #if this address hash is one of mine
|
|
||||||
print 'Found getpubkey requested hash in my list of EC hashes.'
|
sqlLock.acquire()
|
||||||
#check to see whether we have already calculated the nonce and transmitted this key before
|
|
||||||
sqlLock.acquire()#released at the bottom of this payload generation section
|
|
||||||
t = (self.data[36+addressVersionLength+streamNumberLength:56+addressVersionLength+streamNumberLength],) #this prevents SQL injection
|
t = (self.data[36+addressVersionLength+streamNumberLength:56+addressVersionLength+streamNumberLength],) #this prevents SQL injection
|
||||||
sqlSubmitQueue.put('SELECT * FROM pubkeys WHERE hash=?')
|
sqlSubmitQueue.put('''SELECT hash, transmitdata, time FROM pubkeys WHERE hash=? AND havecorrectnonce=1''')
|
||||||
sqlSubmitQueue.put(t)
|
sqlSubmitQueue.put(t)
|
||||||
queryreturn = sqlReturnQueue.get()
|
queryreturn = sqlReturnQueue.get()
|
||||||
#print 'queryreturn', queryreturn
|
|
||||||
if queryreturn == []:
|
|
||||||
print 'pubkey request is for me but the pubkey is not in our database of pubkeys. Making it.'
|
|
||||||
payload = pack('>I',(int(time.time())+random.randrange(-300, 300))) #the current time plus or minus five minutes
|
|
||||||
payload += encodeVarint(2) #Address version number
|
|
||||||
payload += encodeVarint(streamNumber)
|
|
||||||
payload += '\x00\x00\x00\x01' #bitfield of features supported by me (see the wiki).
|
|
||||||
|
|
||||||
privSigningKeyBase58 = config.get(encodeAddress(addressVersionNumber,streamNumber,self.data[36+addressVersionLength+streamNumberLength:56+addressVersionLength+streamNumberLength]), 'privsigningkey')
|
|
||||||
privEncryptionKeyBase58 = config.get(encodeAddress(addressVersionNumber,streamNumber,self.data[36+addressVersionLength+streamNumberLength:56+addressVersionLength+streamNumberLength]), 'privencryptionkey')
|
|
||||||
|
|
||||||
privSigningKeyHex = decodeWalletImportFormat(privSigningKeyBase58).encode('hex')
|
|
||||||
privEncryptionKeyHex = decodeWalletImportFormat(privEncryptionKeyBase58).encode('hex')
|
|
||||||
pubSigningKey = highlevelcrypto.privToPub(privSigningKeyHex).decode('hex')
|
|
||||||
pubEncryptionKey = highlevelcrypto.privToPub(privEncryptionKeyHex).decode('hex')
|
|
||||||
|
|
||||||
#print 'within recgetpubkey'
|
|
||||||
#print 'pubSigningKey in hex:', pubSigningKey.encode('hex')
|
|
||||||
#print 'pubEncryptionKey in hex:', pubEncryptionKey.encode('hex')
|
|
||||||
|
|
||||||
payload += pubSigningKey[1:]
|
|
||||||
payload += pubEncryptionKey[1:]
|
|
||||||
|
|
||||||
#Time to do the POW for this pubkey message
|
|
||||||
nonce = 0
|
|
||||||
trialValue = 99999999999999999999
|
|
||||||
target = 2**64 / ((len(payload)+payloadLengthExtraBytes+8) * averageProofOfWorkNonceTrialsPerByte)
|
|
||||||
print '(For pubkey message) Doing proof of work...'
|
|
||||||
initialHash = hashlib.sha512(payload).digest()
|
|
||||||
while trialValue > target:
|
|
||||||
nonce += 1
|
|
||||||
trialValue, = unpack('>Q',hashlib.sha512(hashlib.sha512(pack('>Q',nonce) + initialHash).digest()).digest()[0:8])
|
|
||||||
#trialValue, = unpack('>Q',hashlib.sha512(hashlib.sha512(pack('>Q',nonce) + payload).digest()).digest()[4:12])
|
|
||||||
print '(For pubkey message) Found proof of work', trialValue, 'Nonce:', nonce
|
|
||||||
|
|
||||||
payload = pack('>Q',nonce) + payload
|
|
||||||
t = (self.data[36+addressVersionLength+streamNumberLength:56+addressVersionLength+streamNumberLength],True,payload,int(time.time())+1209600) #after two weeks (1,209,600 seconds), we may remove our own pub key from our database. It will be regenerated and put back in the database if it is requested.
|
|
||||||
sqlSubmitQueue.put('''INSERT INTO pubkeys VALUES (?,?,?,?)''')
|
|
||||||
sqlSubmitQueue.put(t)
|
|
||||||
queryreturn = sqlReturnQueue.get()
|
|
||||||
|
|
||||||
#Now that we have the full pubkey message ready either from making it just now or making it earlier, we can send it out.
|
|
||||||
t = (self.data[36+addressVersionLength+streamNumberLength:56+addressVersionLength+streamNumberLength],) #this prevents SQL injection
|
|
||||||
sqlSubmitQueue.put('''SELECT * FROM pubkeys WHERE hash=? AND havecorrectnonce=1''')
|
|
||||||
sqlSubmitQueue.put(t)
|
|
||||||
queryreturn = sqlReturnQueue.get()
|
|
||||||
if queryreturn == []:
|
|
||||||
sys.stderr.write('Error: pubkey which we just put in our pubkey database suddenly is not there. Is the database malfunctioning?')
|
|
||||||
sqlLock.release()
|
sqlLock.release()
|
||||||
return
|
if queryreturn != []:
|
||||||
for row in queryreturn:
|
for row in queryreturn:
|
||||||
hash, havecorrectnonce, payload, timeLastRequested = row
|
hash, payload, timeLastRequested = row
|
||||||
if timeLastRequested < int(time.time())+604800: #if the last time anyone asked about this hash was this week, extend the time.
|
if timeLastRequested < int(time.time())+604800: #if the last time anyone asked about this hash was this week, extend the time.
|
||||||
|
sqlLock.acquire()
|
||||||
t = (int(time.time())+604800,hash)
|
t = (int(time.time())+604800,hash)
|
||||||
sqlSubmitQueue.put('''UPDATE pubkeys set time=? WHERE hash=?''')
|
sqlSubmitQueue.put('''UPDATE pubkeys set time=? WHERE hash=?''')
|
||||||
sqlSubmitQueue.put(t)
|
sqlSubmitQueue.put(t)
|
||||||
queryreturn = sqlReturnQueue.get()
|
queryreturn = sqlReturnQueue.get()
|
||||||
|
|
||||||
sqlLock.release()
|
sqlLock.release()
|
||||||
|
|
||||||
inventoryHash = calculateInventoryHash(payload)
|
inventoryHash = calculateInventoryHash(payload)
|
||||||
objectType = 'pubkey'
|
objectType = 'pubkey'
|
||||||
inventory[inventoryHash] = (objectType, self.streamNumber, payload, int(time.time()))
|
inventory[inventoryHash] = (objectType, self.streamNumber, payload, int(time.time()))
|
||||||
self.broadcastinv(inventoryHash)
|
self.broadcastinv(inventoryHash)
|
||||||
|
else: #the pubkey is not in our database of pubkeys. Let's check if the requested key is ours (which would mean we should do the POW, put it in the pubkey table, and broadcast out the pubkey.
|
||||||
|
|
||||||
|
if self.data[36+addressVersionLength+streamNumberLength:56+addressVersionLength+streamNumberLength] in myECAddressHashes: #if this address hash is one of mine
|
||||||
|
print 'Found getpubkey-requested-hash in my list of EC hashes. Telling Worker thread to do the POW for a pubkey message and send it out.'
|
||||||
|
myAddress = encodeAddress(addressVersionNumber,streamNumber,self.data[36+addressVersionLength+streamNumberLength:56+addressVersionLength+streamNumberLength])
|
||||||
|
workerQueue.put(('doPOWForMyV2Pubkey',myAddress))
|
||||||
|
|
||||||
|
|
||||||
elif self.data[36+addressVersionLength+streamNumberLength:56+addressVersionLength+streamNumberLength] in myRSAAddressHashes:
|
elif self.data[36+addressVersionLength+streamNumberLength:56+addressVersionLength+streamNumberLength] in myRSAAddressHashes:
|
||||||
print 'Found getpubkey requested hash in my list of RSA hashes.'
|
print 'Found getpubkey requested hash in my list of RSA hashes.'
|
||||||
#check to see whether we have already calculated the nonce and transmitted this key before
|
|
||||||
sqlLock.acquire()#released at the bottom of this payload generation section
|
|
||||||
t = (self.data[36+addressVersionLength+streamNumberLength:56+addressVersionLength+streamNumberLength],) #this prevents SQL injection
|
|
||||||
sqlSubmitQueue.put('SELECT * FROM pubkeys WHERE hash=?')
|
|
||||||
sqlSubmitQueue.put(t)
|
|
||||||
queryreturn = sqlReturnQueue.get()
|
|
||||||
#print 'queryreturn', queryreturn
|
|
||||||
|
|
||||||
if queryreturn == []:
|
|
||||||
print 'pubkey request is for me but the pubkey is not in our database of pubkeys. Making it.'
|
|
||||||
payload = '\x00\x00\x00\x01' #bitfield of features supported by me (see the wiki).
|
payload = '\x00\x00\x00\x01' #bitfield of features supported by me (see the wiki).
|
||||||
payload += self.data[36:36+addressVersionLength+streamNumberLength]
|
payload += self.data[36:36+addressVersionLength+streamNumberLength]
|
||||||
#print int(config.get(encodeAddress(addressVersionNumber,streamNumber,self.data[36+addressVersionLength+streamNumberLength:56+addressVersionLength+streamNumberLength]), 'n'))
|
#print int(config.get(encodeAddress(addressVersionNumber,streamNumber,self.data[36+addressVersionLength+streamNumberLength:56+addressVersionLength+streamNumberLength]), 'n'))
|
||||||
|
@ -1338,18 +1257,12 @@ class receiveDataThread(QThread):
|
||||||
|
|
||||||
payload = pack('>Q',nonce) + payload
|
payload = pack('>Q',nonce) + payload
|
||||||
t = (self.data[36+addressVersionLength+streamNumberLength:56+addressVersionLength+streamNumberLength],True,payload,int(time.time())+1209600) #after two weeks (1,209,600 seconds), we may remove our own pub key from our database. It will be regenerated and put back in the database if it is requested.
|
t = (self.data[36+addressVersionLength+streamNumberLength:56+addressVersionLength+streamNumberLength],True,payload,int(time.time())+1209600) #after two weeks (1,209,600 seconds), we may remove our own pub key from our database. It will be regenerated and put back in the database if it is requested.
|
||||||
|
sqlLock.acquire()
|
||||||
sqlSubmitQueue.put('''INSERT INTO pubkeys VALUES (?,?,?,?)''')
|
sqlSubmitQueue.put('''INSERT INTO pubkeys VALUES (?,?,?,?)''')
|
||||||
sqlSubmitQueue.put(t)
|
sqlSubmitQueue.put(t)
|
||||||
queryreturn = sqlReturnQueue.get()
|
queryreturn = sqlReturnQueue.get()
|
||||||
|
|
||||||
#Now that we have the full pubkey message ready either from making it just now or making it earlier, we can send it out.
|
|
||||||
t = (self.data[36+addressVersionLength+streamNumberLength:56+addressVersionLength+streamNumberLength],) #this prevents SQL injection
|
|
||||||
sqlSubmitQueue.put('''SELECT * FROM pubkeys WHERE hash=? AND havecorrectnonce=1''')
|
|
||||||
sqlSubmitQueue.put(t)
|
|
||||||
queryreturn = sqlReturnQueue.get()
|
|
||||||
if queryreturn == []:
|
|
||||||
sys.stderr.write('Error: pubkey which we just put in our pubkey database suddenly is not there. Is the database malfunctioning?')
|
|
||||||
sqlLock.release()
|
sqlLock.release()
|
||||||
|
<<<<<<< HEAD
|
||||||
return
|
return
|
||||||
for row in queryreturn:
|
for row in queryreturn:
|
||||||
hash, havecorrectnonce, payload, timeLastRequested = row
|
hash, havecorrectnonce, payload, timeLastRequested = row
|
||||||
|
@ -1367,32 +1280,17 @@ class receiveDataThread(QThread):
|
||||||
self.broadcastinv(inventoryHash)
|
self.broadcastinv(inventoryHash)
|
||||||
|
|
||||||
else: #The requested hash is not for any of my keys but we might have received it previously from someone else and could send it now.
|
else: #The requested hash is not for any of my keys but we might have received it previously from someone else and could send it now.
|
||||||
|
=======
|
||||||
|
>>>>>>> 3df7a16540e37e937f4505523a20d5518d94f6f4
|
||||||
|
|
||||||
#This section hasn't been tested yet. Criteria for success: Alice sends Bob a message. Three days later, Charlie who is completely new to Bitmessage runs the client for the first time then sends a message to Bob and accomplishes this without Bob having to redo the POW for a pubkey message.
|
inventoryHash = calculateInventoryHash(payload)
|
||||||
|
|
||||||
print 'Hash in getpubkey request is not for any of my keys.'
|
|
||||||
#..but lets see if we have it stored from when it came in from someone else.
|
|
||||||
t = (self.data[36+addressVersionLength+streamNumberLength:56+addressVersionLength+streamNumberLength],) #this prevents SQL injection
|
|
||||||
sqlLock.acquire()
|
|
||||||
sqlSubmitQueue.put('''SELECT hash, transmitdata, time FROM pubkeys WHERE hash=? AND havecorrectnonce=1''')
|
|
||||||
sqlSubmitQueue.put(t)
|
|
||||||
queryreturn = sqlReturnQueue.get()
|
|
||||||
sqlLock.release()
|
|
||||||
print 'queryreturn', queryreturn
|
|
||||||
if queryreturn <> []:
|
|
||||||
print '...but we have the public key from when it came in from someone else. sending it.'
|
|
||||||
#We have it. Let's send it.
|
|
||||||
for row in queryreturn:
|
|
||||||
hash, transmitdata, timeLastRequested = row
|
|
||||||
if timeLastRequested < int(time.time())+604800: #if the last time anyone asked about this hash was this week, extend the time.
|
|
||||||
t = (int(time.time())+604800,hash)
|
|
||||||
sqlSubmitQueue.put('''UPDATE pubkeys set time=? WHERE hash=? ''')
|
|
||||||
sqlSubmitQueue.put(t)
|
|
||||||
queryreturn = sqlReturnQueue.get()
|
|
||||||
inventoryHash = calculateInventoryHash(transmitdata)
|
|
||||||
objectType = 'pubkey'
|
objectType = 'pubkey'
|
||||||
inventory[inventoryHash] = (objectType, self.streamNumber, transmitdata, int(time.time()))
|
inventory[inventoryHash] = (objectType, self.streamNumber, payload, int(time.time()))
|
||||||
self.broadcastinv(inventoryHash)
|
self.broadcastinv(inventoryHash)
|
||||||
|
else:
|
||||||
|
printLock.acquire()
|
||||||
|
print 'This getpubkey request is not for any of my keys.'
|
||||||
|
printLock.release()
|
||||||
|
|
||||||
|
|
||||||
#We have received an inv message
|
#We have received an inv message
|
||||||
|
@ -1694,13 +1592,14 @@ class receiveDataThread(QThread):
|
||||||
#print 'self.data[96:104]', repr(self.data[96:104])
|
#print 'self.data[96:104]', repr(self.data[96:104])
|
||||||
#print 'eightBytesOfRandomDataUsedToDetectConnectionsToSelf', repr(eightBytesOfRandomDataUsedToDetectConnectionsToSelf)
|
#print 'eightBytesOfRandomDataUsedToDetectConnectionsToSelf', repr(eightBytesOfRandomDataUsedToDetectConnectionsToSelf)
|
||||||
useragentLength, lengthOfUseragentVarint = decodeVarint(self.data[104:108])
|
useragentLength, lengthOfUseragentVarint = decodeVarint(self.data[104:108])
|
||||||
readPosition = 104 + lengthOfUseragentVarint + useragentLength
|
readPosition = 104 + lengthOfUseragentVarint
|
||||||
#Note that PyBitmessage curreutnly currentl supports a single stream per connection.
|
useragent = self.data[readPosition:readPosition+useragentLength]
|
||||||
|
readPosition += useragentLength
|
||||||
numberOfStreamsInVersionMessage, lengthOfNumberOfStreamsInVersionMessage = decodeVarint(self.data[readPosition:])
|
numberOfStreamsInVersionMessage, lengthOfNumberOfStreamsInVersionMessage = decodeVarint(self.data[readPosition:])
|
||||||
readPosition += lengthOfNumberOfStreamsInVersionMessage
|
readPosition += lengthOfNumberOfStreamsInVersionMessage
|
||||||
self.streamNumber, lengthOfRemoteStreamNumber = decodeVarint(self.data[readPosition:])
|
self.streamNumber, lengthOfRemoteStreamNumber = decodeVarint(self.data[readPosition:])
|
||||||
printLock.acquire()
|
printLock.acquire()
|
||||||
print 'Remote node stream number:', self.streamNumber
|
print 'Remote node useragent:', useragent, ' stream number:', self.streamNumber
|
||||||
printLock.release()
|
printLock.release()
|
||||||
#If this was an incoming connection, then the sendData thread doesn't know the stream. We have to set it.
|
#If this was an incoming connection, then the sendData thread doesn't know the stream. We have to set it.
|
||||||
if not self.initiatedConnection:
|
if not self.initiatedConnection:
|
||||||
|
@ -1768,7 +1667,7 @@ class receiveDataThread(QThread):
|
||||||
datatosend = datatosend + payload
|
datatosend = datatosend + payload
|
||||||
|
|
||||||
printLock.acquire()
|
printLock.acquire()
|
||||||
print 'Sending version packet: ', repr(datatosend)
|
print 'Sending version message'
|
||||||
printLock.release()
|
printLock.release()
|
||||||
self.sock.send(datatosend)
|
self.sock.send(datatosend)
|
||||||
#self.versionSent = 1
|
#self.versionSent = 1
|
||||||
|
@ -2216,7 +2115,8 @@ class singleWorker(QThread):
|
||||||
print 'Within WorkerThread, processing sendbroadcast command.'
|
print 'Within WorkerThread, processing sendbroadcast command.'
|
||||||
fromAddress,subject,message = data
|
fromAddress,subject,message = data
|
||||||
self.sendBroadcast()
|
self.sendBroadcast()
|
||||||
|
elif command == 'doPOWForMyV2Pubkey':
|
||||||
|
self.doPOWForMyV2Pubkey(data)
|
||||||
elif command == 'newpubkey':
|
elif command == 'newpubkey':
|
||||||
toAddressVersion,toStreamNumber,toRipe = data
|
toAddressVersion,toStreamNumber,toRipe = data
|
||||||
if toRipe in neededPubkeys:
|
if toRipe in neededPubkeys:
|
||||||
|
@ -2228,6 +2128,62 @@ class singleWorker(QThread):
|
||||||
|
|
||||||
workerQueue.task_done()
|
workerQueue.task_done()
|
||||||
|
|
||||||
|
def doPOWForMyV2Pubkey(self,myAddress): #This function also broadcasts out the pubkey message once it is done with the POW
|
||||||
|
status,addressVersionNumber,streamNumber,hash = decodeAddress(myAddress)
|
||||||
|
payload = pack('>I',(int(time.time())+random.randrange(-300, 300))) #the current time plus or minus five minutes
|
||||||
|
payload += encodeVarint(2) #Address version number
|
||||||
|
payload += encodeVarint(streamNumber)
|
||||||
|
payload += '\x00\x00\x00\x01' #bitfield of features supported by me (see the wiki).
|
||||||
|
|
||||||
|
privSigningKeyBase58 = config.get(myAddress, 'privsigningkey')
|
||||||
|
privEncryptionKeyBase58 = config.get(myAddress, 'privencryptionkey')
|
||||||
|
|
||||||
|
privSigningKeyHex = decodeWalletImportFormat(privSigningKeyBase58).encode('hex')
|
||||||
|
privEncryptionKeyHex = decodeWalletImportFormat(privEncryptionKeyBase58).encode('hex')
|
||||||
|
pubSigningKey = highlevelcrypto.privToPub(privSigningKeyHex).decode('hex')
|
||||||
|
pubEncryptionKey = highlevelcrypto.privToPub(privEncryptionKeyHex).decode('hex')
|
||||||
|
|
||||||
|
#print 'within recgetpubkey'
|
||||||
|
#print 'pubSigningKey in hex:', pubSigningKey.encode('hex')
|
||||||
|
#print 'pubEncryptionKey in hex:', pubEncryptionKey.encode('hex')
|
||||||
|
|
||||||
|
payload += pubSigningKey[1:]
|
||||||
|
payload += pubEncryptionKey[1:]
|
||||||
|
|
||||||
|
#Time to do the POW for this pubkey message
|
||||||
|
nonce = 0
|
||||||
|
trialValue = 99999999999999999999
|
||||||
|
target = 2**64 / ((len(payload)+payloadLengthExtraBytes+8) * averageProofOfWorkNonceTrialsPerByte)
|
||||||
|
print '(For pubkey message) Doing proof of work...'
|
||||||
|
initialHash = hashlib.sha512(payload).digest()
|
||||||
|
while trialValue > target:
|
||||||
|
nonce += 1
|
||||||
|
trialValue, = unpack('>Q',hashlib.sha512(hashlib.sha512(pack('>Q',nonce) + initialHash).digest()).digest()[0:8])
|
||||||
|
#trialValue, = unpack('>Q',hashlib.sha512(hashlib.sha512(pack('>Q',nonce) + payload).digest()).digest()[4:12])
|
||||||
|
print '(For pubkey message) Found proof of work', trialValue, 'Nonce:', nonce
|
||||||
|
|
||||||
|
payload = pack('>Q',nonce) + payload
|
||||||
|
t = (hash,True,payload,int(time.time())+1209600) #after two weeks (1,209,600 seconds), we may remove our own pub key from our database. It will be regenerated and put back in the database if it is requested.
|
||||||
|
sqlLock.acquire()
|
||||||
|
sqlSubmitQueue.put('''INSERT INTO pubkeys VALUES (?,?,?,?)''')
|
||||||
|
sqlSubmitQueue.put(t)
|
||||||
|
queryreturn = sqlReturnQueue.get()
|
||||||
|
sqlLock.release()
|
||||||
|
|
||||||
|
inventoryHash = calculateInventoryHash(payload)
|
||||||
|
objectType = 'pubkey'
|
||||||
|
inventory[inventoryHash] = (objectType, streamNumber, payload, int(time.time()))
|
||||||
|
|
||||||
|
payload = '\x01' + inventoryHash
|
||||||
|
headerData = '\xe9\xbe\xb4\xd9' #magic bits, slighly different from Bitcoin's magic bits.
|
||||||
|
headerData = headerData + 'inv\x00\x00\x00\x00\x00\x00\x00\x00\x00'
|
||||||
|
headerData = headerData + pack('>L',len(payload))
|
||||||
|
headerData = headerData + hashlib.sha512(payload).digest()[:4]
|
||||||
|
printLock.acquire()
|
||||||
|
print 'broadcasting inv with hash:', hash.encode('hex')
|
||||||
|
printLock.release()
|
||||||
|
broadcastToSendDataQueues((streamNumber, 'send', headerData + payload))
|
||||||
|
|
||||||
def sendBroadcast(self):
|
def sendBroadcast(self):
|
||||||
sqlLock.acquire()
|
sqlLock.acquire()
|
||||||
t = ('broadcastpending',)
|
t = ('broadcastpending',)
|
||||||
|
@ -3447,12 +3403,12 @@ class MyForm(QtGui.QMainWindow):
|
||||||
else:
|
else:
|
||||||
toAddress = addBMIfNotPresent(toAddress)
|
toAddress = addBMIfNotPresent(toAddress)
|
||||||
self.statusBar().showMessage('')
|
self.statusBar().showMessage('')
|
||||||
|
try:
|
||||||
if connectionsCount[streamNumber] == 0:
|
if connectionsCount[streamNumber] == 0:
|
||||||
self.statusBar().showMessage('Warning: You are currently not connected. Bitmessage will do the work necessary to send the message but it won\'t send until you connect.')
|
self.statusBar().showMessage('Warning: You are currently not connected. Bitmessage will do the work necessary to send the message but it won\'t send until you connect.')
|
||||||
ackdata = ''
|
except:
|
||||||
for i in range(4): #This will make 32 bytes of random data.
|
self.statusBar().showMessage('Warning: The address uses a stream number currently not supported by this Bitmessage version. Perhaps upgrade.')
|
||||||
random.seed()
|
ackdata = OpenSSL.rand(32)
|
||||||
ackdata += pack('>Q',random.randrange(1, 18446744073709551615))
|
|
||||||
sqlLock.acquire()
|
sqlLock.acquire()
|
||||||
t = ('',toAddress,ripe,fromAddress,subject,message,ackdata,int(time.time()),'findingpubkey',1,1,'sent')
|
t = ('',toAddress,ripe,fromAddress,subject,message,ackdata,int(time.time()),'findingpubkey',1,1,'sent')
|
||||||
sqlSubmitQueue.put('''INSERT INTO sent VALUES (?,?,?,?,?,?,?,?,?,?,?,?)''')
|
sqlSubmitQueue.put('''INSERT INTO sent VALUES (?,?,?,?,?,?,?,?,?,?,?,?)''')
|
||||||
|
@ -4212,7 +4168,7 @@ neededPubkeys = {}
|
||||||
averageProofOfWorkNonceTrialsPerByte = 320 #The amount of work that should be performed (and demanded) per byte of the payload. Double this number to double the work.
|
averageProofOfWorkNonceTrialsPerByte = 320 #The amount of work that should be performed (and demanded) per byte of the payload. Double this number to double the work.
|
||||||
payloadLengthExtraBytes = 14000 #To make sending short messages a little more difficult, this value is added to the payload length for use in calculating the proof of work target.
|
payloadLengthExtraBytes = 14000 #To make sending short messages a little more difficult, this value is added to the payload length for use in calculating the proof of work target.
|
||||||
|
|
||||||
if userVeryEasyProofOfWorkForTesting:
|
if useVeryEasyProofOfWorkForTesting:
|
||||||
averageProofOfWorkNonceTrialsPerByte = averageProofOfWorkNonceTrialsPerByte / 10
|
averageProofOfWorkNonceTrialsPerByte = averageProofOfWorkNonceTrialsPerByte / 10
|
||||||
payloadLengthExtraBytes = payloadLengthExtraBytes / 10
|
payloadLengthExtraBytes = payloadLengthExtraBytes / 10
|
||||||
|
|
||||||
|
|
|
@ -302,6 +302,19 @@ The 'Random Number' option is selected by default but deterministic addresses ha
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
|
<tabstops>
|
||||||
|
<tabstop>radioButtonRandomAddress</tabstop>
|
||||||
|
<tabstop>radioButtonDeterministicAddress</tabstop>
|
||||||
|
<tabstop>newaddresslabel</tabstop>
|
||||||
|
<tabstop>radioButtonMostAvailable</tabstop>
|
||||||
|
<tabstop>radioButtonExisting</tabstop>
|
||||||
|
<tabstop>comboBoxExisting</tabstop>
|
||||||
|
<tabstop>lineEditPassphrase</tabstop>
|
||||||
|
<tabstop>lineEditPassphraseAgain</tabstop>
|
||||||
|
<tabstop>spinBoxNumberOfAddressesToMake</tabstop>
|
||||||
|
<tabstop>checkBoxEighteenByteRipe</tabstop>
|
||||||
|
<tabstop>buttonBox</tabstop>
|
||||||
|
</tabstops>
|
||||||
<resources/>
|
<resources/>
|
||||||
<connections>
|
<connections>
|
||||||
<connection>
|
<connection>
|
||||||
|
|
Reference in New Issue
Block a user