Merge pull request #2 from Atheros1/master

Fixed POW, changed checksum, other minor changes
This commit is contained in:
Jonathan Warren 2012-11-23 00:29:26 -08:00
commit 9054847a9f
14 changed files with 167 additions and 150 deletions

View File

@ -123,8 +123,6 @@ class singleListener(QThread):
while True: while True:
#for i in range(0,1): #uncomment this line and comment the line above this to accept only one connection. #for i in range(0,1): #uncomment this line and comment the line above this to accept only one connection.
rd = receiveDataThread() rd = receiveDataThread()
a,(HOST,PORT) = sock.accept() a,(HOST,PORT) = sock.accept()
while HOST in connectedHostsList: while HOST in connectedHostsList:
@ -136,7 +134,6 @@ class singleListener(QThread):
print self, 'connected to', HOST,'during INCOMING request.' print self, 'connected to', HOST,'during INCOMING request.'
rd.start() rd.start()
sd = sendDataThread() sd = sendDataThread()
sd.setup(a,HOST,PORT,-1) sd.setup(a,HOST,PORT,-1)
sd.start() sd.start()
@ -181,13 +178,13 @@ class receiveDataThread(QThread):
break break
except Exception, err: except Exception, err:
printLock.acquire() printLock.acquire()
print 'Error receiving data. Closing receiveData thread.' print 'sock.recv error. Closing receiveData thread.'
printLock.release() printLock.release()
break break
#print 'Received', repr(self.data) #print 'Received', repr(self.data)
if self.data == "": if self.data == "":
printLock.acquire() printLock.acquire()
print 'Socket timeout.' print 'Connection closed.'
printLock.release() printLock.release()
break break
else: else:
@ -233,14 +230,16 @@ class receiveDataThread(QThread):
else: else:
self.payloadLength, = unpack('>L',self.data[16:20]) self.payloadLength, = unpack('>L',self.data[16:20])
if len(self.data) >= self.payloadLength: #check if the whole message has arrived yet. If it has,... if len(self.data) >= self.payloadLength: #check if the whole message has arrived yet. If it has,...
if self.data[20:24] == hashlib.sha512(hashlib.sha512(self.data[24:self.payloadLength+24]).digest()).digest()[0:4]:#test the checksum in the message. If it is correct... if self.data[20:24] == hashlib.sha512(self.data[24:self.payloadLength+24]).digest()[0:4]:#test the checksum in the message. If it is correct...
#print 'message checksum is correct' #print 'message checksum is correct'
#The time we've last seen this node is obviously right now since we just received valid data from it. So update the knownNodes list so that other peers can be made aware of its existance. #The time we've last seen this node is obviously right now since we just received valid data from it. So update the knownNodes list so that other peers can be made aware of its existance.
if self.initiatedConnection: #The remote port is only something we should share with others if it is the remote node's incoming port (rather than some random operating-system-assigned outgoing port). if self.initiatedConnection: #The remote port is only something we should share with others if it is the remote node's incoming port (rather than some random operating-system-assigned outgoing port).
knownNodes[self.streamNumber][self.HOST] = (self.PORT,int(time.time())) knownNodes[self.streamNumber][self.HOST] = (self.PORT,int(time.time()))
remoteCommand = self.data[4:16] remoteCommand = self.data[4:16]
if verbose >= 2: if verbose >= 2:
printLock.acquire()
print 'remoteCommand ', remoteCommand, 'from', self.HOST print 'remoteCommand ', remoteCommand, 'from', self.HOST
printLock.release()
if remoteCommand == 'version\x00\x00\x00\x00\x00': if remoteCommand == 'version\x00\x00\x00\x00\x00':
self.recversion() self.recversion()
elif remoteCommand == 'verack\x00\x00\x00\x00\x00\x00': elif remoteCommand == 'verack\x00\x00\x00\x00\x00\x00':
@ -286,37 +285,23 @@ class receiveDataThread(QThread):
self.sendgetdata(objectHash) self.sendgetdata(objectHash)
del self.objectsThatWeHaveYetToGet[objectHash] #It is possible that the remote node doesn't respond with the object. In that case, we'll very likely get it from someone else anyway. del self.objectsThatWeHaveYetToGet[objectHash] #It is possible that the remote node doesn't respond with the object. In that case, we'll very likely get it from someone else anyway.
break break
print 'within processData, length of objectsThatWeHaveYetToGet is now', len(self.objectsThatWeHaveYetToGet)
self.processData()
#if self.versionSent == 0:
# self.sendversion()
'''if (self.versionRec == 1) and (self.getaddrthreadalreadycreated == 0):
while (threading.activeCount() > maxGlobalThreads):#If there too many open threads, just wait. This includes full and half-open.
time.sleep(0.1)
printLock.acquire() printLock.acquire()
print 'Starting a new getaddrSender thread' print 'within processData, length of objectsThatWeHaveYetToGet is now', len(self.objectsThatWeHaveYetToGet)
printLock.release() printLock.release()
bar = getaddrSender((self.sock,self.addr)) self.processData()
bar.daemon = True
self.getaddrthreadalreadycreated = 1 #we're about to start it
while True: #My goal is to try bar.start() until it succeedes
while (threading.activeCount() > maxGlobalThreads):#If there too many open threads, just wait. This includes full and half-open.
time.sleep(0.1)
try:
bar.start()
except:
maxGlobalThreads = maxGlobalThreads - 20
sys.stderr.write('Problem! Your OS did not allow the starting of another thread. Reducing the number of threads to %s and trying again.\n' % maxGlobalThreads)
continue #..the while loop again right now
break '''
else: else:
print 'Checksum incorrect. Clearing messages and waiting for new data.' print 'Checksum incorrect. Clearing this message.'
self.data = '' self.data = self.data[self.payloadLength+24:]
def isProofOfWorkSufficient(self):
POW, = unpack('>Q',hashlib.sha512(hashlib.sha512(self.data[24:32]+ hashlib.sha512(self.data[32:24+self.payloadLength]).digest()).digest()).digest()[0:8])
print 'POW:', POW
#Notice that I have divided the averageProofOfWorkNonceTrialsPerByte by two. This makes the POW requirement easier. This gives us wiggle-room: if we decide that we want to make the POW easier, the change won't obsolete old clients because they already expect a lower POW. If we decide that the current work done by clients feels approperate then we can remove this division by 2 and make the requirement match what is actually done by a sending node. If we want to raise the POW requirement then old nodes will HAVE to upgrade no matter what.
return POW < 2**64 / ((self.payloadLength+payloadLengthExtraBytes) * (averageProofOfWorkNonceTrialsPerByte/2))
def sendpong(self): def sendpong(self):
print 'Sending pong' print 'Sending pong'
self.sock.sendall('\xE9\xBE\xB4\xD9\x70\x6F\x6E\x67\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x82\x6D\xf0\x68') self.sock.sendall('\xE9\xBE\xB4\xD9\x70\x6F\x6E\x67\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xcf\x83\xe1\x35')
def recverack(self): def recverack(self):
print 'verack received' print 'verack received'
@ -334,11 +319,13 @@ class receiveDataThread(QThread):
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])
connectionsCountLock.release() connectionsCountLock.release()
self.sendaddr()
remoteNodeIncomingPort, remoteNodeSeenTime = knownNodes[self.streamNumber][self.HOST] remoteNodeIncomingPort, remoteNodeSeenTime = knownNodes[self.streamNumber][self.HOST]
print 'within connectionFullyEstablished, self.HOST and remoteNodeIncomingPort:', self.HOST, remoteNodeIncomingPort printLock.acquire()
print 'Connection fully established with', self.HOST, remoteNodeIncomingPort
print 'broadcasting addr from within connectionFullyEstablished function.' print 'broadcasting addr from within connectionFullyEstablished function.'
self.broadcastaddr([(int(time.time()), self.streamNumber, 1, self.HOST, remoteNodeIncomingPort)]) printLock.release()
self.broadcastaddr([(int(time.time()), self.streamNumber, 1, self.HOST, remoteNodeIncomingPort)]) #This lets all of our peers know about this new node.
self.sendaddr() #This is one addr message to this one peer.
if connectionsCount[self.streamNumber] > 150: if connectionsCount[self.streamNumber] > 150:
print 'We are connected to too many people. Closing connection.' print 'We are connected to too many people. Closing connection.'
self.sock.close() self.sock.close()
@ -374,27 +361,31 @@ class receiveDataThread(QThread):
payload += hash payload += hash
numberOfObjectsInInvMessage += 1 numberOfObjectsInInvMessage += 1
if numberOfObjectsInInvMessage >= 50000: #We can only send a max of 50000 items per inv message but we may have more objects to advertise. They must be split up into multiple inv messages. if numberOfObjectsInInvMessage >= 50000: #We can only send a max of 50000 items per inv message but we may have more objects to advertise. They must be split up into multiple inv messages.
sendinvMessageToJustThisOnePeer(numberOfObjectsInInvMessage,payload,) sendinvMessageToJustThisOnePeer(numberOfObjectsInInvMessage,payload)
payload = '' payload = ''
numberOfObjectsInInvMessage = 0 numberOfObjectsInInvMessage = 0
if numberOfObjectsInInvMessage > 0: if numberOfObjectsInInvMessage > 0:
self.sendinvMessageToJustThisOnePeer(numberOfObjectsInInvMessage,payload,) self.sendinvMessageToJustThisOnePeer(numberOfObjectsInInvMessage,payload)
#Notice that there is also a broadcastinv function for broadcasting invs to everyone in our stream. #Self explanatory. Notice that there is also a broadcastinv function for broadcasting invs to everyone in our stream.
def sendinvMessageToJustThisOnePeer(self,numberOfObjects,payload,destination): def sendinvMessageToJustThisOnePeer(self,numberOfObjects,payload):
payload = encodeVarint(numberOfObjects) + payload payload = encodeVarint(numberOfObjects) + payload
headerData = '\xe9\xbe\xb4\xd9' #magic bits, slighly different from Bitcoin's magic bits. 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 + 'inv\x00\x00\x00\x00\x00\x00\x00\x00\x00'
headerData = headerData + pack('>L',len(payload)) headerData = headerData + pack('>L',len(payload))
headerData = headerData + hashlib.sha512(hashlib.sha512(payload).digest()).digest()[:4] headerData = headerData + hashlib.sha512(payload).digest()[:4]
print 'Sending inv message to just this one peer'
self.sock.send(headerData + payload) self.sock.send(headerData + payload)
#We have received a broadcast message #We have received a broadcast message
def recbroadcast(self): def recbroadcast(self):
#First we must check to make sure the proof of work is sufficient. #First we must check to make sure the proof of work is sufficient.
POW, = unpack('>Q',hashlib.sha512(hashlib.sha512(self.data[24:24+self.payloadLength]).digest()).digest()[4:12]) #POW, = unpack('>Q',hashlib.sha512(self.data[24:24+self.payloadLength]).digest()[4:12])
if POW > 2**64 / ((self.payloadLength+payloadLengthExtraBytes) * averageProofOfWorkNonceTrialsPerByte): #if POW > 2**64 / ((self.payloadLength+payloadLengthExtraBytes) * averageProofOfWorkNonceTrialsPerByte):
print 'The proof of work in this broadcast message is insufficient. Ignoring message.' # print 'The proof of work in this broadcast message is insufficient. Ignoring message.'
# return
if not self.isProofOfWorkSufficient():
print 'Proof of work in broadcast message insufficient.'
return return
embeddedTime, = unpack('>I',self.data[32:36]) embeddedTime, = unpack('>I',self.data[32:36])
if embeddedTime > (int(time.time())+10800): #prevent funny business if embeddedTime > (int(time.time())+10800): #prevent funny business
@ -510,17 +501,16 @@ class receiveDataThread(QThread):
#We have received a msg message. #We have received a msg message.
def recmsg(self): def recmsg(self):
#First we must check to make sure the proof of work is sufficient. #First we must check to make sure the proof of work is sufficient.
'''sha = hashlib.new('sha512') #POW, = unpack('>Q',hashlib.sha512(self.data[24:24+self.payloadLength]).digest()[4:12])
sha.update(self.data[24:24+self.payloadLength]) #print 'POW:', POW
sha2 = hashlib.new('sha512')
sha2.update(sha.digest())''' #if POW > 2**64 / ((self.payloadLength+payloadLengthExtraBytes) * averageProofOfWorkNonceTrialsPerByte):
POW, = unpack('>Q',hashlib.sha512(hashlib.sha512(self.data[24:24+self.payloadLength]).digest()).digest()[4:12]) # print 'Proof of work in msg message insufficient.'
print 'POW:', POW # return
initialDecryptionSuccessful = False if not self.isProofOfWorkSufficient():
if POW > 2**64 / ((self.payloadLength+payloadLengthExtraBytes) * averageProofOfWorkNonceTrialsPerByte):
print 'Proof of work in msg message insufficient.' print 'Proof of work in msg message insufficient.'
return return
initialDecryptionSuccessful = False
readPosition = 32 readPosition = 32
embeddedTime, = unpack('>I',self.data[readPosition:readPosition+4]) embeddedTime, = unpack('>I',self.data[readPosition:readPosition+4])
if embeddedTime > int(time.time())+10800: if embeddedTime > int(time.time())+10800:
@ -551,7 +541,7 @@ class receiveDataThread(QThread):
#Let's check whether this is a message acknowledgement bound for us. #Let's check whether this is a message acknowledgement bound for us.
if self.data[readPosition:24+self.payloadLength] in ackdataForWhichImWatching: if self.data[readPosition:24+self.payloadLength] in ackdataForWhichImWatching:
printLock.acquire() printLock.acquire()
print 'This msg is an acknowledgement bound for me.' print 'This msg IS an acknowledgement bound for me.'
printLock.release() printLock.release()
del ackdataForWhichImWatching[self.data[readPosition:24+self.payloadLength]] del ackdataForWhichImWatching[self.data[readPosition:24+self.payloadLength]]
t = ('ackreceived',self.data[readPosition:24+self.payloadLength]) t = ('ackreceived',self.data[readPosition:24+self.payloadLength])
@ -565,8 +555,8 @@ class receiveDataThread(QThread):
return return
else: else:
printLock.acquire() printLock.acquire()
print 'This was NOT an acknowledgement bound for me. Msg potential ack data:', repr(self.data[readPosition:24+self.payloadLength]) print 'This was NOT an acknowledgement bound for me.' #Msg potential ack data:', repr(self.data[readPosition:24+self.payloadLength])
print 'ackdataForWhichImWatching', ackdataForWhichImWatching #print 'ackdataForWhichImWatching', ackdataForWhichImWatching
printLock.release() printLock.release()
#This is not an acknowledgement bound for me. See if it is a message bound for me by trying to decrypt it with my private keys. #This is not an acknowledgement bound for me. See if it is a message bound for me by trying to decrypt it with my private keys.
@ -727,37 +717,52 @@ class receiveDataThread(QThread):
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's send the acknowledgement
POW, = unpack('>Q',hashlib.sha512(hashlib.sha512(ackData[24:]).digest()).digest()[4:12]) #POW, = unpack('>Q',hashlib.sha512(hashlib.sha512(ackData[24:]).digest()).digest()[4:12])
if POW <= 2**64 / ((len(ackData[24:])+payloadLengthExtraBytes) * averageProofOfWorkNonceTrialsPerByte): #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.' #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.) #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) #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
if len(ackData) < 24:
print 'The length of Ackdata is unreasonably short. Not sending ackData.'
ackDataValidThusFar = False
if ackData[0:4] != '\xe9\xbe\xb4\xd9':
print 'Ackdata magic bytes were wrong. Not sending ackData.'
ackDataValidThusFar = False
if ackDataValidThusFar:
ackDataPayloadLength, = unpack('>L',ackData[16:20])
if len(ackData)-24 != ackDataPayloadLength:
print 'ackData payload length doesn\'t match the payload length specified in the header. Not sending ackdata.'
ackDataValidThusFar = False
if ackDataValidThusFar:
print 'ackData is valid. Will process it.'
self.data = self.data[:self.payloadLength+24] + ackData + self.data[self.payloadLength+24:] self.data = self.data[:self.payloadLength+24] + ackData + self.data[self.payloadLength+24:]
#print 'self.data after:', repr(self.data) #print 'self.data after:', repr(self.data)
'''if ackData[4:16] == 'msg\x00\x00\x00\x00\x00\x00\x00\x00\x00': '''if ackData[4:16] == 'msg\x00\x00\x00\x00\x00\x00\x00\x00\x00':
inventoryHash = calculateInventoryHash(ackData[24:]) inventoryHash = calculateInventoryHash(ackData[24:])
#objectType = 'msg' #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. #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)' #print 'sending the inv for the msg which is actually an acknowledgement (within sendmsg function)'
#self.broadcastinv(inventoryHash) #self.broadcastinv(inventoryHash)
self.data[:payloadLength+24] + ackData + self.data[payloadLength+24:] self.data[:payloadLength+24] + ackData + self.data[payloadLength+24:]
elif ackData[4:16] == 'getpubkey\x00\x00\x00': elif ackData[4:16] == 'getpubkey\x00\x00\x00':
#objectType = 'getpubkey' #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. #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)' #print 'sending the inv for the getpubkey which is actually an acknowledgement (within sendmsg function)'
self.data[:payloadLength+24] + ackData + self.data[payloadLength+24:] self.data[:payloadLength+24] + ackData + self.data[payloadLength+24:]
elif ackData[4:16] == 'pubkey\x00\x00\x00\x00\x00\x00': elif ackData[4:16] == 'pubkey\x00\x00\x00\x00\x00\x00':
#objectType = 'pubkey' #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. #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)' #print 'sending the inv for a pubkey which is actually an acknowledgement (within sendmsg function)'
self.data[:payloadLength+24] + ackData + self.data[payloadLength+24:] self.data[:payloadLength+24] + ackData + self.data[payloadLength+24:]
elif ackData[4:16] == 'broadcast\x00\x00\x00': elif ackData[4:16] == 'broadcast\x00\x00\x00':
#objectType = 'broadcast' #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. #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)' #print 'sending the inv for a broadcast which is actually an acknowledgement (within sendmsg function)'
self.data[:payloadLength+24] + ackData + self.data[payloadLength+24:]''' self.data[:payloadLength+24] + ackData + self.data[payloadLength+24:]'''
else: #else:
print 'ACK POW not strong enough to be accepted by the Bitmessage network.' #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.'
@ -780,16 +785,22 @@ class receiveDataThread(QThread):
if inventoryHash in inventory: if inventoryHash in inventory:
print 'We have already received this pubkey. Ignoring it.' print 'We have already received this pubkey. Ignoring it.'
return return
elif isInSqlInventory(inventoryHash):
print 'We have already received this pubkey (it is stored on disk in the SQL inventory). Ignoring it.'
return
#We must check to make sure the proof of work is sufficient. #We must check to make sure the proof of work is sufficient.
POW, = unpack('>Q',hashlib.sha512(hashlib.sha512(self.data[24:24+self.payloadLength]).digest()).digest()[4:12]) #POW, = unpack('>Q',hashlib.sha512(hashlib.sha512(self.data[24:24+self.payloadLength]).digest()).digest()[4:12])
print 'POW:', POW #print 'POW:', POW
if POW > 2**64 / ((self.payloadLength+payloadLengthExtraBytes) * averageProofOfWorkNonceTrialsPerByte): #if POW > 2**64 / ((self.payloadLength+payloadLengthExtraBytes) * averageProofOfWorkNonceTrialsPerByte):
printLock.acquire() # printLock.acquire()
print 'The Proof of Work in the pubkey message is insufficient. Ignoring it.' # print 'The Proof of Work in the pubkey message is insufficient. Ignoring it.'
print 'pubkey payload length:', len(self.data[24:self.payloadLength+24]) # print 'pubkey payload length:', len(self.data[24:self.payloadLength+24])
print repr(self.data[24:self.payloadLength+24]) # print repr(self.data[24:self.payloadLength+24])
printLock.release() # printLock.release()
# return
if not self.isProofOfWorkSufficient():
print 'Proof of work in pubkey message insufficient.'
return return
objectType = 'pubkey' objectType = 'pubkey'
@ -848,10 +859,13 @@ class receiveDataThread(QThread):
objectType = 'pubkeyrequest' objectType = 'pubkeyrequest'
inventory[inventoryHash] = (objectType, self.streamNumber, self.data[24:self.payloadLength+24], int(time.time())) inventory[inventoryHash] = (objectType, self.streamNumber, self.data[24:self.payloadLength+24], int(time.time()))
#First we must check to make sure the proof of work is sufficient. #First we must check to make sure the proof of work is sufficient.
POW, = unpack('>Q',hashlib.sha512(hashlib.sha512(self.data[24:24+self.payloadLength]).digest()).digest()[4:12]) #POW, = unpack('>Q',hashlib.sha512(hashlib.sha512(self.data[24:24+self.payloadLength]).digest()).digest()[4:12])
print 'POW:', POW #print 'POW:', POW
if POW > 2**64 / ((self.payloadLength+payloadLengthExtraBytes) * averageProofOfWorkNonceTrialsPerByte): #if POW > 2**64 / ((self.payloadLength+payloadLengthExtraBytes) * averageProofOfWorkNonceTrialsPerByte):
print 'POW value in getpubkey message is insufficient. Ignoring it.' # print 'POW value in getpubkey message is insufficient. Ignoring it.'
# return
if not self.isProofOfWorkSufficient():
print 'Proof of work in getpubkey message insufficient.'
return return
#Now let us make sure that the getpubkey request isn't too old or with a fake (future) time. #Now let us make sure that the getpubkey request isn't too old or with a fake (future) time.
embeddedTime, = unpack('>I',self.data[32:36]) embeddedTime, = unpack('>I',self.data[32:36])
@ -892,12 +906,14 @@ class receiveDataThread(QThread):
payload += eString payload += eString
nonce = 0 nonce = 0
trialValue = 99999999999999999 trialValue = 99999999999999999999
target = 2**64 / ((len(payload)+payloadLengthExtraBytes+8) * averageProofOfWorkNonceTrialsPerByte) #The 108 added to the payload length is 8 for the size of the nonce + 50 as an extra penalty simply for having this seperate message exist. target = 2**64 / ((len(payload)+payloadLengthExtraBytes+8) * averageProofOfWorkNonceTrialsPerByte)
print '(For pubkey message) Doing proof of work...' print '(For pubkey message) Doing proof of work...'
initialHash = hashlib.sha512(payload).digest()
while trialValue > target: while trialValue > target:
nonce += 1 nonce += 1
trialValue, = unpack('>Q',hashlib.sha512(hashlib.sha512(pack('>Q',nonce) + payload).digest()).digest()[4:12]) 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 print '(For pubkey message) Found proof of work', trialValue, 'Nonce:', nonce
payload = pack('>Q',nonce) + payload payload = pack('>Q',nonce) + payload
@ -981,11 +997,7 @@ class receiveDataThread(QThread):
headerData = '\xe9\xbe\xb4\xd9' #magic bits, slighly different from Bitcoin's magic bits. headerData = '\xe9\xbe\xb4\xd9' #magic bits, slighly different from Bitcoin's magic bits.
headerData = headerData + 'getdata\x00\x00\x00\x00\x00' headerData = headerData + 'getdata\x00\x00\x00\x00\x00'
headerData = headerData + pack('>L',len(payload)) #payload length. Note that we add an extra 8 for the nonce. headerData = headerData + pack('>L',len(payload)) #payload length. Note that we add an extra 8 for the nonce.
'''sha = hashlib.new('sha512') headerData = headerData + hashlib.sha512(payload).digest()[:4]
sha.update(payload)
sha2 = hashlib.new('sha512')
sha2.update(sha.digest())'''
headerData = headerData + hashlib.sha512(hashlib.sha512(payload).digest()).digest()[:4]
self.sock.send(headerData + payload) self.sock.send(headerData + payload)
#We have received a getdata request from our peer #We have received a getdata request from our peer
@ -1025,35 +1037,35 @@ class receiveDataThread(QThread):
headerData = '\xe9\xbe\xb4\xd9' #magic bits, slighly different from Bitcoin's magic bits. headerData = '\xe9\xbe\xb4\xd9' #magic bits, slighly different from Bitcoin's magic bits.
headerData = headerData + 'pubkey\x00\x00\x00\x00\x00\x00' headerData = headerData + 'pubkey\x00\x00\x00\x00\x00\x00'
headerData = headerData + pack('>L',len(payload)) #payload length. Note that we add an extra 8 for the nonce. headerData = headerData + pack('>L',len(payload)) #payload length. Note that we add an extra 8 for the nonce.
headerData = headerData + hashlib.sha512(hashlib.sha512(payload).digest()).digest()[:4] headerData = headerData + hashlib.sha512(payload).digest()[:4]
self.sock.send(headerData + payload) self.sock.send(headerData + payload)
elif objectType == 'pubkeyrequest': elif objectType == 'pubkeyrequest':
print 'sending pubkeyrequest' print 'sending pubkeyrequest'
headerData = '\xe9\xbe\xb4\xd9' #magic bits, slighly different from Bitcoin's magic bits. headerData = '\xe9\xbe\xb4\xd9' #magic bits, slighly different from Bitcoin's magic bits.
headerData = headerData + 'getpubkey\x00\x00\x00' headerData = headerData + 'getpubkey\x00\x00\x00'
headerData = headerData + pack('>L',len(payload)) #payload length. Note that we add an extra 8 for the nonce. headerData = headerData + pack('>L',len(payload)) #payload length. Note that we add an extra 8 for the nonce.
headerData = headerData + hashlib.sha512(hashlib.sha512(payload).digest()).digest()[:4] headerData = headerData + hashlib.sha512(payload).digest()[:4]
self.sock.send(headerData + payload) self.sock.send(headerData + payload)
elif objectType == 'msg': elif objectType == 'msg':
print 'sending msg' print 'sending msg'
headerData = '\xe9\xbe\xb4\xd9' #magic bits, slighly different from Bitcoin's magic bits. headerData = '\xe9\xbe\xb4\xd9' #magic bits, slighly different from Bitcoin's magic bits.
headerData = headerData + 'msg\x00\x00\x00\x00\x00\x00\x00\x00\x00' headerData = headerData + 'msg\x00\x00\x00\x00\x00\x00\x00\x00\x00'
headerData = headerData + pack('>L',len(payload)) #payload length. Note that we add an extra 8 for the nonce. headerData = headerData + pack('>L',len(payload)) #payload length. Note that we add an extra 8 for the nonce.
headerData = headerData + hashlib.sha512(hashlib.sha512(payload).digest()).digest()[:4] headerData = headerData + hashlib.sha512(payload).digest()[:4]
self.sock.send(headerData + payload) self.sock.send(headerData + payload)
elif objectType == 'broadcast': elif objectType == 'broadcast':
print 'sending broadcast' print 'sending broadcast'
headerData = '\xe9\xbe\xb4\xd9' #magic bits, slighly different from Bitcoin's magic bits. headerData = '\xe9\xbe\xb4\xd9' #magic bits, slighly different from Bitcoin's magic bits.
headerData = headerData + 'broadcast\x00\x00\x00' headerData = headerData + 'broadcast\x00\x00\x00'
headerData = headerData + pack('>L',len(payload)) #payload length. Note that we add an extra 8 for the nonce. headerData = headerData + pack('>L',len(payload)) #payload length. Note that we add an extra 8 for the nonce.
headerData = headerData + hashlib.sha512(hashlib.sha512(payload).digest()).digest()[:4] headerData = headerData + hashlib.sha512(payload).digest()[:4]
self.sock.send(headerData + payload) self.sock.send(headerData + payload)
elif objectType == 'getpubkey': elif objectType == 'getpubkey':
print 'sending getpubkey' print 'sending getpubkey'
headerData = '\xe9\xbe\xb4\xd9' #magic bits, slighly different from Bitcoin's magic bits. headerData = '\xe9\xbe\xb4\xd9' #magic bits, slighly different from Bitcoin's magic bits.
headerData = headerData + 'getpubkey\x00\x00\x00' #version command headerData = headerData + 'getpubkey\x00\x00\x00' #version command
headerData = headerData + pack('>L',len(payload)) #payload length headerData = headerData + pack('>L',len(payload)) #payload length
headerData = headerData + hashlib.sha512(hashlib.sha512(payload).digest()).digest()[0:4] headerData = headerData + hashlib.sha512(payload).digest()[0:4]
self.sock.send(headerData + payload) self.sock.send(headerData + payload)
else: else:
sys.stderr.write('Error: sendData has been asked to send a strange objectType: %s\n' % str(objectType)) sys.stderr.write('Error: sendData has been asked to send a strange objectType: %s\n' % str(objectType))
@ -1066,11 +1078,7 @@ class receiveDataThread(QThread):
headerData = '\xe9\xbe\xb4\xd9' #magic bits, slighly different from Bitcoin's magic bits. 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 + 'inv\x00\x00\x00\x00\x00\x00\x00\x00\x00'
headerData = headerData + pack('>L',len(payload)) headerData = headerData + pack('>L',len(payload))
'''sha = hashlib.new('sha512') headerData = headerData + hashlib.sha512(payload).digest()[:4]
sha.update(payload)
sha2 = hashlib.new('sha512')
sha2.update(sha.digest())'''
headerData = headerData + hashlib.sha512(hashlib.sha512(payload).digest()).digest()[:4]
#self.sock.send(headerData + payload) #self.sock.send(headerData + payload)
broadcastToSendDataQueues((self.streamNumber, 'send', headerData + payload)) broadcastToSendDataQueues((self.streamNumber, 'send', headerData + payload))
print 'broadcasting inv with hash:', repr(hash) print 'broadcasting inv with hash:', repr(hash)
@ -1168,7 +1176,7 @@ class receiveDataThread(QThread):
payload = encodeVarint(numberOfAddressesInAddrMessage) + payload payload = encodeVarint(numberOfAddressesInAddrMessage) + payload
datatosend = '\xE9\xBE\xB4\xD9addr\x00\x00\x00\x00\x00\x00\x00\x00' datatosend = '\xE9\xBE\xB4\xD9addr\x00\x00\x00\x00\x00\x00\x00\x00'
datatosend = datatosend + pack('>L',len(payload)) #payload length datatosend = datatosend + pack('>L',len(payload)) #payload length
datatosend = datatosend + hashlib.sha512(hashlib.sha512(payload).digest()).digest()[0:4] datatosend = datatosend + hashlib.sha512(payload).digest()[0:4]
datatosend = datatosend + payload datatosend = datatosend + payload
if verbose >= 2: if verbose >= 2:
@ -1236,12 +1244,7 @@ class receiveDataThread(QThread):
payload = encodeVarint(numberOfAddressesInAddrMessage) + payload payload = encodeVarint(numberOfAddressesInAddrMessage) + payload
datatosend = '\xE9\xBE\xB4\xD9addr\x00\x00\x00\x00\x00\x00\x00\x00' datatosend = '\xE9\xBE\xB4\xD9addr\x00\x00\x00\x00\x00\x00\x00\x00'
datatosend = datatosend + pack('>L',len(payload)) #payload length datatosend = datatosend + pack('>L',len(payload)) #payload length
'''sha = hashlib.new('sha512') datatosend = datatosend + hashlib.sha512(payload).digest()[0:4]
sha.update(payload)
sha2 = hashlib.new('sha512')
sha2.update(sha.digest())'''
datatosend = datatosend + hashlib.sha512(hashlib.sha512(payload).digest()).digest()[0:4]
datatosend = datatosend + payload datatosend = datatosend + payload
if verbose >= 2: if verbose >= 2:
@ -1314,7 +1317,7 @@ class receiveDataThread(QThread):
payload += pack('>H',self.remoteNodeIncomingPort)#remote port payload += pack('>H',self.remoteNodeIncomingPort)#remote port
datatosend = '\xE9\xBE\xB4\xD9addr\x00\x00\x00\x00\x00\x00\x00\x00' datatosend = '\xE9\xBE\xB4\xD9addr\x00\x00\x00\x00\x00\x00\x00\x00'
datatosend += pack('>L',len(payload)) #payload length datatosend += pack('>L',len(payload)) #payload length
datatosend += hashlib.sha512(hashlib.sha512(payload).digest()).digest()[0:4] datatosend += hashlib.sha512(payload).digest()[0:4]
datatosend += payload datatosend += payload
broadcastToSendDataQueues((self.streamNumber, 'send', datatosend))''' broadcastToSendDataQueues((self.streamNumber, 'send', datatosend))'''
@ -1345,7 +1348,7 @@ class receiveDataThread(QThread):
datatosend = '\xe9\xbe\xb4\xd9' #magic bits, slighly different from Bitcoin's magic bits. datatosend = '\xe9\xbe\xb4\xd9' #magic bits, slighly different from Bitcoin's magic bits.
datatosend = datatosend + 'version\x00\x00\x00\x00\x00' #version command datatosend = datatosend + 'version\x00\x00\x00\x00\x00' #version command
datatosend = datatosend + pack('>L',len(payload)) #payload length datatosend = datatosend + pack('>L',len(payload)) #payload length
datatosend = datatosend + hashlib.sha512(hashlib.sha512(payload).digest()).digest()[0:4] datatosend = datatosend + hashlib.sha512(payload).digest()[0:4]
datatosend = datatosend + payload datatosend = datatosend + payload
printLock.acquire() printLock.acquire()
@ -1357,7 +1360,8 @@ class receiveDataThread(QThread):
#Sends a verack message #Sends a verack message
def sendverack(self): def sendverack(self):
print 'Sending verack' print 'Sending verack'
self.sock.sendall('\xE9\xBE\xB4\xD9\x76\x65\x72\x61\x63\x6B\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x82\x6D\xf0\x68') self.sock.sendall('\xE9\xBE\xB4\xD9\x76\x65\x72\x61\x63\x6B\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xcf\x83\xe1\x35')
#cf 83 e1 35
self.verackSent = True self.verackSent = True
if self.verackReceived == True: if self.verackReceived == True:
self.connectionFullyEstablished() self.connectionFullyEstablished()
@ -1408,7 +1412,7 @@ class sendDataThread(QThread):
datatosend = '\xe9\xbe\xb4\xd9' #magic bits, slighly different from Bitcoin's magic bits. datatosend = '\xe9\xbe\xb4\xd9' #magic bits, slighly different from Bitcoin's magic bits.
datatosend = datatosend + 'version\x00\x00\x00\x00\x00' #version command datatosend = datatosend + 'version\x00\x00\x00\x00\x00' #version command
datatosend = datatosend + pack('>L',len(payload)) #payload length datatosend = datatosend + pack('>L',len(payload)) #payload length
datatosend = datatosend + hashlib.sha512(hashlib.sha512(payload).digest()).digest()[0:4] datatosend = datatosend + hashlib.sha512(payload).digest()[0:4]
datatosend = datatosend + payload datatosend = datatosend + payload
printLock.acquire() printLock.acquire()
@ -1423,14 +1427,14 @@ class sendDataThread(QThread):
while True: while True:
deststream,command,data = self.mailbox.get() deststream,command,data = self.mailbox.get()
printLock.acquire() printLock.acquire()
print 'within a sendDataThread, destream:', deststream,', Command:', command, self print 'sendDataThread, destream:', deststream, ', Command:', command, ', ID:',id(self), ', HOST:', self.HOST
printLock.release() printLock.release()
if deststream == self.streamNumber or deststream == 0: if deststream == self.streamNumber or deststream == 0:
if command == 'shutdown': if command == 'shutdown':
if data == self.HOST or data == 'all': if data == self.HOST or data == 'all':
printLock.acquire() printLock.acquire()
print 'sendDataThread thread (associated with', self.HOST,')', self, 'shutting down now.' print 'sendDataThread thread (associated with', self.HOST,') ID:',id(self), 'shutting down now.'
self.sock.close() self.sock.close()
sendDataQueues.remove(self.mailbox) sendDataQueues.remove(self.mailbox)
print 'len of sendDataQueues', len(sendDataQueues) print 'len of sendDataQueues', len(sendDataQueues)
@ -1440,7 +1444,7 @@ class sendDataThread(QThread):
hostInMessage, specifiedStreamNumber = data hostInMessage, specifiedStreamNumber = data
if hostInMessage == self.HOST: if hostInMessage == self.HOST:
printLock.acquire() printLock.acquire()
print 'setting the stream number in the sendData thread to', specifiedStreamNumber, self print 'setting the stream number in the sendData thread (ID:',id(self), ') to', specifiedStreamNumber
printLock.release() printLock.release()
self.streamNumber = specifiedStreamNumber self.streamNumber = specifiedStreamNumber
elif command == 'send': elif command == 'send':
@ -1461,7 +1465,7 @@ class sendDataThread(QThread):
#Send out a pong message to keep the connection alive. #Send out a pong message to keep the connection alive.
print 'Sending pong to', self.HOST, 'to keep connection alive.' print 'Sending pong to', self.HOST, 'to keep connection alive.'
try: try:
self.sock.sendall('\xE9\xBE\xB4\xD9\x70\x6F\x6E\x67\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x82\x6D\xf0\x68') self.sock.sendall('\xE9\xBE\xB4\xD9\x70\x6F\x6E\x67\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xcf\x83\xe1\x35')
self.lastTimeISentData = int(time.time()) self.lastTimeISentData = int(time.time())
except: except:
print 'self.sock.send pong failed' print 'self.sock.send pong failed'
@ -1767,12 +1771,13 @@ class singleWorker(QThread):
print 'eString', repr(eString) print 'eString', repr(eString)
nonce = 0 nonce = 0
trialValue = 99999999999999999 trialValue = 99999999999999999999
target = 2**64 / ((len(payload)+payloadLengthExtraBytes+8) * averageProofOfWorkNonceTrialsPerByte) target = 2**64 / ((len(payload)+payloadLengthExtraBytes+8) * averageProofOfWorkNonceTrialsPerByte)
print '(For broadcast message) Doing proof of work...' print '(For broadcast message) Doing proof of work...'
initialHash = hashlib.sha512(payload).digest()
while trialValue > target: while trialValue > target:
nonce += 1 nonce += 1
trialValue, = unpack('>Q',hashlib.sha512(hashlib.sha512(pack('>Q',nonce) + payload).digest()).digest()[4:12]) trialValue, = unpack('>Q',hashlib.sha512(hashlib.sha512(pack('>Q',nonce) + initialHash).digest()).digest()[0:8])
print '(For broadcast message) Found proof of work', trialValue, 'Nonce:', nonce print '(For broadcast message) Found proof of work', trialValue, 'Nonce:', nonce
payload = pack('>Q',nonce) + payload payload = pack('>Q',nonce) + payload
@ -1785,7 +1790,7 @@ class singleWorker(QThread):
headerData = '\xe9\xbe\xb4\xd9' #magic bits, slighly different from Bitcoin's magic bits. 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 + 'inv\x00\x00\x00\x00\x00\x00\x00\x00\x00'
headerData = headerData + pack('>L',len(payload)) #payload length. Note that we add an extra 8 for the nonce. headerData = headerData + pack('>L',len(payload)) #payload length. Note that we add an extra 8 for the nonce.
headerData = headerData + hashlib.sha512(hashlib.sha512(payload).digest()).digest()[:4] headerData = headerData + hashlib.sha512(payload).digest()[:4]
broadcastToSendDataQueues((streamNumber, 'send', headerData + payload)) broadcastToSendDataQueues((streamNumber, 'send', headerData + payload))
self.emit(SIGNAL("updateSentItemStatusByAckdata(PyQt_PyObject,PyQt_PyObject)"),ackdata,'Broadcast sent at '+strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(time.time())))) self.emit(SIGNAL("updateSentItemStatusByAckdata(PyQt_PyObject,PyQt_PyObject)"),ackdata,'Broadcast sent at '+strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(time.time()))))
@ -1882,19 +1887,20 @@ class singleWorker(QThread):
outfile.close() outfile.close()
nonce = 0 nonce = 0
trialValue = 99999999999999999 trialValue = 99999999999999999999
embeddedTime = pack('>I',(int(time.time()))) embeddedTime = pack('>I',(int(time.time())))
encodedStreamNumber = encodeVarint(toStreamNumber) encodedStreamNumber = encodeVarint(toStreamNumber)
#We are now dropping the unencrypted data in payload since it has already been encrypted and replacing it with the encrypted payload that we will send out. #We are now dropping the unencrypted data in payload since it has already been encrypted and replacing it with the encrypted payload that we will send out.
payload = embeddedTime + encodedStreamNumber + encrypted payload = embeddedTime + encodedStreamNumber + encrypted
target = 2**64 / ((len(payload)+payloadLengthExtraBytes+8) * averageProofOfWorkNonceTrialsPerByte) target = 2**64 / ((len(payload)+payloadLengthExtraBytes+8) * averageProofOfWorkNonceTrialsPerByte)
print '(For msg message) Doing proof of work...' print '(For msg message) Doing proof of work. Target:', target
print 'target', target powStartTime = time.time()
initialHash = hashlib.sha512(payload).digest()
while trialValue > target: while trialValue > target:
nonce += 1 nonce += 1
trialValue, = unpack('>Q',hashlib.sha512(hashlib.sha512(pack('>Q',nonce) + payload).digest()).digest()[4:12]) trialValue, = unpack('>Q',hashlib.sha512(hashlib.sha512(pack('>Q',nonce) + initialHash).digest()).digest()[0:8])
print '(For msg message) Found proof of work', trialValue, 'Nonce:', nonce print '(For msg message) Found proof of work', trialValue, 'Nonce:', nonce
print 'POW took', int(time.time()-powStartTime), 'seconds.', nonce/(time.time()-powStartTime), 'nonce trials per second.'
payload = pack('>Q',nonce) + payload payload = pack('>Q',nonce) + payload
inventoryHash = calculateInventoryHash(payload) inventoryHash = calculateInventoryHash(payload)
@ -1906,7 +1912,7 @@ class singleWorker(QThread):
headerData = '\xe9\xbe\xb4\xd9' #magic bits, slighly different from Bitcoin's magic bits. 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 + 'inv\x00\x00\x00\x00\x00\x00\x00\x00\x00'
headerData = headerData + pack('>L',len(payload)) #payload length. Note that we add an extra 8 for the nonce. headerData = headerData + pack('>L',len(payload)) #payload length. Note that we add an extra 8 for the nonce.
headerData = headerData + hashlib.sha512(hashlib.sha512(payload).digest()).digest()[:4] headerData = headerData + hashlib.sha512(payload).digest()[:4]
broadcastToSendDataQueues((toStreamNumber, 'send', headerData + payload)) broadcastToSendDataQueues((toStreamNumber, 'send', headerData + payload))
#Update the status of the message in the 'sent' table to have a 'sent' status #Update the status of the message in the 'sent' table to have a 'sent' status
@ -1931,16 +1937,17 @@ class singleWorker(QThread):
payload += encodeVarint(streamNumber) payload += encodeVarint(streamNumber)
payload += ripe payload += ripe
nonce = 0 nonce = 0
trialValue = 99999999999999999 trialValue = 99999999999999999999
#print 'trial value', trialValue #print 'trial value', trialValue
statusbar = 'Doing the computations necessary to request the recipient''s public key. (Doing the proof-of-work.)' statusbar = 'Doing the computations necessary to request the recipient''s public key. (Doing the proof-of-work.)'
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.') self.emit(SIGNAL("updateSentItemStatusByHash(PyQt_PyObject,PyQt_PyObject)"),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)+payloadLengthExtraBytes+8) * averageProofOfWorkNonceTrialsPerByte) target = 2**64 / ((len(payload)+payloadLengthExtraBytes+8) * averageProofOfWorkNonceTrialsPerByte)
initialHash = hashlib.sha512(payload).digest()
while trialValue > target: while trialValue > target:
nonce += 1 nonce += 1
trialValue, = unpack('>Q',hashlib.sha512(hashlib.sha512(pack('>Q',nonce) + payload).digest()).digest()[4:12]) trialValue, = unpack('>Q',hashlib.sha512(hashlib.sha512(pack('>Q',nonce) + initialHash).digest()).digest()[0:8])
print 'Found proof of work', trialValue, 'Nonce:', nonce print 'Found proof of work', trialValue, 'Nonce:', nonce
payload = pack('>Q',nonce) + payload payload = pack('>Q',nonce) + payload
@ -1953,7 +1960,7 @@ class singleWorker(QThread):
headerData = '\xe9\xbe\xb4\xd9' #magic bits, slighly different from Bitcoin's magic bits. 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 + 'inv\x00\x00\x00\x00\x00\x00\x00\x00\x00'
headerData = headerData + pack('>L',len(payload)) headerData = headerData + pack('>L',len(payload))
headerData = headerData + hashlib.sha512(hashlib.sha512(payload).digest()).digest()[:4] headerData = headerData + hashlib.sha512(payload).digest()[:4]
broadcastToSendDataQueues((streamNumber, 'send', headerData + payload)) broadcastToSendDataQueues((streamNumber, 'send', headerData + payload))
self.emit(SIGNAL("updateStatusBar(PyQt_PyObject)"),'Broacasting the public key request. The recipient''s software must be on. This program will auto-retry if they are offline.') self.emit(SIGNAL("updateStatusBar(PyQt_PyObject)"),'Broacasting the public key request. The recipient''s software must be on. This program will auto-retry if they are offline.')
@ -1962,21 +1969,28 @@ class singleWorker(QThread):
def generateFullAckMessage(self,ackdata,toStreamNumber): def generateFullAckMessage(self,ackdata,toStreamNumber):
nonce = 0 nonce = 0
trialValue = 99999999999999999 trialValue = 99999999999999999999
embeddedTime = pack('>I',(int(time.time()))) embeddedTime = pack('>I',(int(time.time())))
encodedStreamNumber = encodeVarint(toStreamNumber) encodedStreamNumber = encodeVarint(toStreamNumber)
payload = embeddedTime + encodedStreamNumber + ackdata payload = embeddedTime + encodedStreamNumber + ackdata
target = 2**64 / ((len(payload)+payloadLengthExtraBytes+8) * averageProofOfWorkNonceTrialsPerByte) target = 2**64 / ((len(payload)+payloadLengthExtraBytes+8) * averageProofOfWorkNonceTrialsPerByte)
printLock.acquire()
print '(For ack message) Doing proof of work...' print '(For ack message) Doing proof of work...'
printLock.release()
powStartTime = time.time()
initialHash = hashlib.sha512(payload).digest()
while trialValue > target: while trialValue > target:
nonce += 1 nonce += 1
trialValue, = unpack('>Q',hashlib.sha512(hashlib.sha512(pack('>Q',nonce) + payload).digest()).digest()[4:12]) trialValue, = unpack('>Q',hashlib.sha512(hashlib.sha512(pack('>Q',nonce) + initialHash).digest()).digest()[0:8])
printLock.acquire()
print '(For ack message) Found proof of work', trialValue, 'Nonce:', nonce print '(For ack message) Found proof of work', trialValue, 'Nonce:', nonce
print 'POW took', int(time.time()-powStartTime), 'seconds.', nonce/(time.time()-powStartTime), 'nonce trials per second.'
printLock.release()
payload = pack('>Q',nonce) + payload payload = pack('>Q',nonce) + payload
headerData = '\xe9\xbe\xb4\xd9' #magic bits, slighly different from Bitcoin's magic bits. headerData = '\xe9\xbe\xb4\xd9' #magic bits, slighly different from Bitcoin's magic bits.
headerData = headerData + 'msg\x00\x00\x00\x00\x00\x00\x00\x00\x00' headerData = headerData + 'msg\x00\x00\x00\x00\x00\x00\x00\x00\x00'
headerData = headerData + pack('>L',len(payload)) headerData = headerData + pack('>L',len(payload))
headerData = headerData + hashlib.sha512(hashlib.sha512(payload).digest()).digest()[:4] headerData = headerData + hashlib.sha512(payload).digest()[:4]
return headerData + payload return headerData + payload
class addressGenerator(QThread): class addressGenerator(QThread):
@ -2525,7 +2539,7 @@ 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 sendData threads don't remove themselves from sendDataQueues fast enough for len(sendDataQueues) to be accurate here.
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())
@ -2540,7 +2554,7 @@ class MyForm(QtGui.QMainWindow):
def setStatusIcon(self,color): def setStatusIcon(self,color):
global statusIconColor global statusIconColor
print 'setting status icon color' #print 'setting status icon color'
if color == 'red': if color == 'red':
self.ui.pushButtonStatusIcon.setIcon(QIcon(":/newPrefix/images/redicon.png")) self.ui.pushButtonStatusIcon.setIcon(QIcon(":/newPrefix/images/redicon.png"))
statusIconColor = 'red' statusIconColor = 'red'
@ -2670,7 +2684,6 @@ class MyForm(QtGui.QMainWindow):
random.seed() random.seed()
ackdata += pack('>Q',random.randrange(1, 18446744073709551615)) ackdata += pack('>Q',random.randrange(1, 18446744073709551615))
ackdataForWhichImWatching[ackdata] = 0 ackdataForWhichImWatching[ackdata] = 0
print 'ackdataForWhichImWatching within pushButtonSend', repr(ackdataForWhichImWatching)
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 (?,?,?,?,?,?,?,?,?,?,?,?)''')
@ -3408,9 +3421,9 @@ eightBytesOfRandomDataUsedToDetectConnectionsToSelf = pack('>Q',random.randrange
connectedHostsList = {} #List of hosts to which we are connected. Used to guarantee that the outgoingSynSender thread won't connect to the same remote node twice. connectedHostsList = {} #List of hosts to which we are connected. Used to guarantee that the outgoingSynSender thread won't connect to the same remote node twice.
neededPubkeys = {} neededPubkeys = {}
#These constants are not at the top because if changed they will cause particularly unexpected behavior #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!
averageProofOfWorkNonceTrialsPerByte = 2 #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 = 1 #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 __name__ == "__main__": if __name__ == "__main__":
major, minor, revision = sqlite3.sqlite_version_info major, minor, revision = sqlite3.sqlite_version_info
@ -3488,4 +3501,8 @@ if __name__ == "__main__":
if 'win' in sys.platform: if 'win' in sys.platform:
myapp.setWindowFlags(Qt.ToolTip) myapp.setWindowFlags(Qt.ToolTip)
sys.exit(app.exec_()) sys.exit(app.exec_())
# So far, the Bitmessage protocol, this client, the Wiki, and the forums
# are all a one-man operation. Bitcoin tips are quite appreciated!
# 1H5XaDA6fYENLbknwZyjiYXYPQaFjjLX2u

View File

@ -67,7 +67,7 @@ if __name__ == "__main__":
appdata = path.expanduser(path.join("~", "." + APPNAME + "/")) appdata = path.expanduser(path.join("~", "." + APPNAME + "/"))
#print 'New list of all known nodes:', createDefaultKnownNodes(appdata) print 'New list of all known nodes:', createDefaultKnownNodes(appdata)
readDefaultKnownNodes(appdata) readDefaultKnownNodes(appdata)

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.