#Notice that I have divided the networkDefaultAverageProofOfWorkNonceTrialsPerByte 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.
#Notice that I have divided the networkDefaultProofOfWorkNonceTrialsPerByte 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.
@ -635,9 +638,9 @@ class receiveDataThread(QThread):
#Let's store the public key in case we want to reply to this person.
#We don't have the correct nonce or time (which would let us send out a pubkey message) so we'll just fill it with 1's. We won't be able to send this pubkey to others (without doing the proof of work ourselves, which this program is programmed to not do.)
print'Sender\'s address version number',sendersAddressVersionNumber,'not yet supported. Ignoring message.'
print'Sender\'s address version number',sendersAddressVersionNumber,'not yet supported. Ignoring message.'
return
iflen(unencryptedData)<170:
print'Length of the unencrypted data is unreasonably short. Sanity check failed. Ignoring message.'
@ -879,9 +882,9 @@ class receiveDataThread(QThread):
ripe.update(sha.digest())
#Let's store the public key in case we want to reply to this person.
#We don't have the correct nonce or time (which would let us send out a pubkey message) so we'll just fill it with 1's. We won't be able to send this pubkey to others (without doing the proof of work ourselves, which this program is programmed to not do.)
@ -1172,9 +1173,6 @@ class receiveDataThread(QThread):
#Is it possible for a public key to be invalid such that trying to encrypt or sign with it will cause an error? If it is, we should probably test these keys here.
# The hash is the RIPEMD160 hash that is encoded in the Bitmessage address.
# If you or someone else did the POW for this pubkey, then havecorrectnonce will be true. If you received the pubkey in a msg message then havecorrectnonce will be false. You won't have the correct nonce and won't be able to send the message to peers if they request the pubkey.
# transmitdata is literally the data that was included in the Bitmessage pubkey message when it arrived, except for the 24 byte protocol header- ie, it starts with the POW nonce.
# time is the time that the pubkey was broadcast on the network same as with every other type of Bitmessage object.
# usedpersonally is set to "yes" if we have used the key personally. This keeps us from deleting it because we may want to reply to a message in the future. This field is not a bool because we may need more flexability in the future and it doesn't take up much more space anyway.
self.cur.execute('''CREATE TABLE pubkeys (hash blob, havecorrectnonce bool, transmitdata blob, time blob, usedpersonally text, UNIQUE(hash, havecorrectnonce) ON CONFLICT REPLACE)''')
self.cur.execute('''CREATE TABLE pubkeys (hash blob, transmitdata blob, time int, usedpersonally text, UNIQUE(hash) ON CONFLICT REPLACE)''')
self.cur.execute('''CREATE TABLE knownnodes (timelastseen int, stream int, services blob, host blob, port blob, UNIQUE(host, stream, port) ON CONFLICT REPLACE)''')#This table isn't used in the program yet but I have a feeling that we'll need it.
self.cur.execute('''INSERT INTO subscriptions VALUES('Bitmessage new releases/announcements','BM-BbkPSZbzPwpVcYZpU4yHwf9ZPEapN5Zx',1)''')
self.cur.execute('''CREATE TABLE settings (key blob, value blob, UNIQUE(key) ON CONFLICT REPLACE)''')
self.cur.execute('''INSERT INTO settings VALUES('version','1')''')
#From now on, let us keep a 'version' embedded in the messages.dat file so that when we make changes to the database, the database version we are on can stay embedded in the messages.dat file. Let us check to see if the settings table exists yet.
item='''SELECT name FROM sqlite_master WHERE type='table' AND name='settings';'''
parameters=''
self.cur.execute(item,parameters)
ifself.cur.fetchall()==[]:
#The settings table doesn't exist. We need to make it.
print'In messages.dat database, creating new \'settings\' table.'
self.cur.execute('''CREATE TABLE settings (key text, value blob, UNIQUE(key) ON CONFLICT REPLACE)''')
self.cur.execute('''INSERT INTO settings VALUES('version','1')''')
print'In messages.dat database, removing an obsolete field from the pubkeys table.'
self.cur.execute('''CREATE TEMPORARY TABLE pubkeys_backup(hash blob, transmitdata blob, time int, usedpersonally text, UNIQUE(hash) ON CONFLICT REPLACE);''')
self.cur.execute('''INSERT INTO pubkeys_backup SELECT hash, transmitdata, time, usedpersonally FROM pubkeys;''')
self.cur.execute('''DROP TABLE pubkeys''')
self.cur.execute('''CREATE TABLE pubkeys (hash blob, transmitdata blob, time int, usedpersonally text, UNIQUE(hash) ON CONFLICT REPLACE)''')
self.cur.execute('''INSERT INTO pubkeys SELECT hash, transmitdata, time, usedpersonally FROM pubkeys_backup;''')
embeddedTime=int(time.time()+random.randrange(-300,300))#the current time plus or minus five minutes
@ -2513,8 +2528,8 @@ class singleWorker(QThread):
payload+=pubSigningKey[1:]
payload+=pubEncryptionKey[1:]
payload+=encodeVarint(networkDefaultAverageProofOfWorkNonceTrialsPerByte)#this is where we would multiply networkDefaultAverageProofOfWorkNonceTrialsPerByte by some difficulty set by the user.
payload+=encodeVarint(networkDefaultPayloadLengthExtraBytes)#this is where we would multiply networkDefaultPayloadLengthExtraBytes by some difficulty set by the user.
print'(For broadcast message) Doing proof of work...'
self.emit(SIGNAL("updateSentItemStatusByAckdata(PyQt_PyObject,PyQt_PyObject)"),ackdata,'Doing work necessary to send broadcast...')
initialHash=hashlib.sha512(payload).digest()
@ -2624,7 +2639,7 @@ class singleWorker(QThread):
sqlLock.release()
else:
printLock.acquire()
print'In the singleWorker thread, the sendBroadcast function doesn\'t understand the address version'
sys.stderr.write('Error: In the singleWorker thread, the sendBroadcast function doesn\'t understand the address version.\n')
printLock.release()
defsendMsg(self,toRipe):
@ -2708,8 +2723,8 @@ class singleWorker(QThread):
payload+=pubSigningKey[1:]#The \x04 on the beginning of the public keys are not sent. This way there is only one acceptable way to encode and send a public key.
payload+=pubEncryptionKey[1:]
payload+=encodeVarint(networkDefaultAverageProofOfWorkNonceTrialsPerByte)#this is where we would multiply networkDefaultAverageProofOfWorkNonceTrialsPerByte by some difficulty we demand others meet.
payload+=encodeVarint(networkDefaultPayloadLengthExtraBytes)#this is where we would multiply networkDefaultPayloadLengthExtraBytes by some difficulty set by some difficulty we demand others meet.
payload+=encodeVarint(config.getint(fromaddress,'noncetrialsperbyte'))#todo: check and see whether the addressee is in our address book, subscription list, or whitelist and set lower POW requirement if yes.
payload+=toHash#This hash will be checked by the receiver of the message to verify that toHash belongs to them. This prevents a Surreptitious Forwarding Attack.
payload+='\x02'#Type 2 is simple UTF-8 message encoding as specified on the Protocol Specification on the Bitmessage Wiki.
@ -2753,15 +2768,15 @@ class singleWorker(QThread):
ifrequiredAverageProofOfWorkNonceTrialsPerByte<networkDefaultAverageProofOfWorkNonceTrialsPerByte:#We still have to meet a minimum POW difficulty regardless of what they say is allowed in order to get our message to propagate through the network.
ifrequiredAverageProofOfWorkNonceTrialsPerByte<networkDefaultProofOfWorkNonceTrialsPerByte:#We still have to meet a minimum POW difficulty regardless of what they say is allowed in order to get our message to propagate through the network.
@ -2773,7 +2788,13 @@ class singleWorker(QThread):
#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.
@ -5309,8 +5339,7 @@ selfInitiatedConnections = {} #This is a list of current connections (the thread
alreadyAttemptedConnectionsList={}#This is a list of nodes to which we have already attempted a connection
sendDataQueues=[]#each sendData thread puts its queue in this list.
myECCryptorObjects={}
myAddressesByHash={}#The key in this dictionary is the hash encoded in an address and value is the address itself.
#myPrivateKeys = {}
myAddressesByHash={}#The key in this dictionary is the RIPE hash which is encoded in an address and value is the address itself.
inventory={}#of objects (like msg payloads and pubkey payloads) Does not include protocol headers (the first 24 bytes of each packet).
workerQueue=Queue.Queue()
sqlSubmitQueue=Queue.Queue()#SQLITE3 is so thread-unsafe that they won't even let you call it from different threads using your own locks. SQL objects can only be called from one thread.
alreadyAttemptedConnectionsListResetTime=int(time.time())#used to clear out the alreadyAttemptedConnectionsList periodically so that we will retry connecting to hosts to which we have already tried to connect.
#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!
networkDefaultAverageProofOfWorkNonceTrialsPerByte =320#The amount of work that should be performed (and demanded) per byte of the payload. Double this number to double the work.
networkDefaultProofOfWorkNonceTrialsPerByte =320#The amount of work that should be performed (and demanded) per byte of the payload. Double this number to double the work.
networkDefaultPayloadLengthExtraBytes=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.
self.label_8.setText(QtGui.QApplication.translate("settingsDialog","When someone sends you a message, their computer must first complete some work. The difficulty of this work, by default, is 1. You may raise this default for new addresses you create by changing the values here. Any new addresses you create will require senders to meet the higher difficulty. There is one exeption: if you add a friend or aquaintance to your address book, Bitmessage will automatically notify them when you next send a message that they need only complete the minimum amount of work: difficulty 1. ",None,QtGui.QApplication.UnicodeUTF8))
self.label_12.setText(QtGui.QApplication.translate("settingsDialog","The \'Small message difficulty\' mostly only affects the difficulty of sending small messages. Doubling this value makes it almost twice as difficult to send a small message but doesn\'t really affect large messages.",None,QtGui.QApplication.UnicodeUTF8))
self.label_10.setText(QtGui.QApplication.translate("settingsDialog","The \'Total difficulty\' affects the absolute amount of work the sender must complete. Doubling this value doubles the amount of work.",None,QtGui.QApplication.UnicodeUTF8))
<string>When someone sends you a message, their computer must first complete some work. The difficulty of this work, by default, is 1. You may raise this default for new addresses you create by changing the values here. Any new addresses you create will require senders to meet the higher difficulty. There is one exeption: if you add a friend or aquaintance to your address book, Bitmessage will automatically notify them when you next send a message that they need only complete the minimum amount of work: difficulty 1. </string>
<string>The 'Small message difficulty' mostly only affects the difficulty of sending small messages. Doubling this value makes it almost twice as difficult to send a small message but doesn't really affect large messages.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="0" colspan="3">
<widget class="QLabel" name="label_10">
<property name="text">
<string>The 'Total difficulty' affects the absolute amount of work the sender must complete. Doubling this value doubles the amount of work.</string>