@ -286,37 +285,23 @@ class receiveDataThread(QThread):
self.sendgetdata(objectHash)
delself.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
printLock.acquire()
print'within processData, length of objectsThatWeHaveYetToGet is now',len(self.objectsThatWeHaveYetToGet)
#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.
'''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()
print'Starting a new getaddrSender thread'
printLock.release()
bar=getaddrSender((self.sock,self.addr))
bar.daemon=True
self.getaddrthreadalreadycreated=1#we're about to start it
whileTrue:#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:
print'Checksum incorrect. Clearing messages and waiting for new data.'
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.
ifconnectionsCount[self.streamNumber]>150:
print'We are connected to too many people. Closing connection.'
self.sock.close()
@ -374,27 +361,31 @@ class receiveDataThread(QThread):
payload+=hash
numberOfObjectsInInvMessage+=1
ifnumberOfObjectsInInvMessage>=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.
#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
iflen(ackData)<24:
print'The length of Ackdata is unreasonably short. Not sending ackData.'
ackDataValidThusFar=False
ifackData[0:4]!='\xe9\xbe\xb4\xd9':
print'Ackdata magic bytes were wrong. Not sending ackData.'
ackDataValidThusFar=False
ifackDataValidThusFar:
ackDataPayloadLength,=unpack('>L',ackData[16:20])
iflen(ackData)-24!=ackDataPayloadLength:
print'ackData payload length doesn\'t match the payload length specified in the header. Not sending ackdata.'
#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)'
#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)'
#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)'
#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)'
#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)'
#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)'
#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)'
#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 'POW value in getpubkey message is insufficient. Ignoring it.'
# return
ifnotself.isProofOfWorkSufficient():
print'Proof of work in getpubkey message insufficient.'
return
#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])
@ -889,11 +907,13 @@ class receiveDataThread(QThread):
nonce=0
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.
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.
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={}
#These constants are not at the top because if changed they will cause particularly unexpected behavior
averageProofOfWorkNonceTrialsPerByte= 2 #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.
#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=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.
if__name__=="__main__":
major,minor,revision=sqlite3.sqlite_version_info
@ -3471,4 +3501,8 @@ if __name__ == "__main__":
if'win'insys.platform:
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!