class_addressGenerator.py.bak
1 """ 2 A thread for creating addresses 3 """ 4 5 import time 6 from binascii import hexlify 7 8 from six.moves import configparser, queue 9 10 import defaults 11 import highlevelcrypto 12 import queues 13 import shared 14 import state 15 from addresses import decodeAddress, encodeAddress, encodeVarint 16 from bmconfigparser import config 17 from network import StoppableThread 18 from tr import _translate 19 20 21 class AddressGeneratorException(Exception): 22 '''Generic AddressGenerator exception''' 23 pass 24 25 26 class addressGenerator(StoppableThread): 27 """A thread for creating addresses""" 28 29 name = "addressGenerator" 30 31 def stopThread(self): 32 """Tell the thread to stop putting a special command to it's queue""" 33 try: 34 queues.addressGeneratorQueue.put(("stopThread", "data")) 35 except queue.Full: 36 self.logger.error('addressGeneratorQueue is Full') 37 38 super(addressGenerator, self).stopThread() 39 40 def run(self): 41 """ 42 Process the requests for addresses generation 43 from `.queues.addressGeneratorQueue` 44 """ 45 # pylint: disable=too-many-locals,too-many-branches,too-many-statements 46 # pylint: disable=too-many-nested-blocks 47 48 while state.shutdown == 0: 49 queueValue = queues.addressGeneratorQueue.get() 50 nonceTrialsPerByte = 0 51 payloadLengthExtraBytes = 0 52 live = True 53 if queueValue[0] == 'createChan': 54 command, addressVersionNumber, streamNumber, label, \ 55 deterministicPassphrase, live = queueValue 56 eighteenByteRipe = False 57 numberOfAddressesToMake = 1 58 numberOfNullBytesDemandedOnFrontOfRipeHash = 1 59 elif queueValue[0] == 'joinChan': 60 command, chanAddress, label, deterministicPassphrase, \ 61 live = queueValue 62 eighteenByteRipe = False 63 addressVersionNumber = decodeAddress(chanAddress)[1] 64 streamNumber = decodeAddress(chanAddress)[2] 65 numberOfAddressesToMake = 1 66 numberOfNullBytesDemandedOnFrontOfRipeHash = 1 67 elif len(queueValue) == 7: 68 command, addressVersionNumber, streamNumber, label, \ 69 numberOfAddressesToMake, deterministicPassphrase, \ 70 eighteenByteRipe = queueValue 71 72 numberOfNullBytesDemandedOnFrontOfRipeHash = \ 73 config.safeGetInt( 74 'bitmessagesettings', 75 'numberofnullbytesonaddress', 76 2 if eighteenByteRipe else 1 77 ) 78 elif len(queueValue) == 9: 79 command, addressVersionNumber, streamNumber, label, \ 80 numberOfAddressesToMake, deterministicPassphrase, \ 81 eighteenByteRipe, nonceTrialsPerByte, \ 82 payloadLengthExtraBytes = queueValue 83 84 numberOfNullBytesDemandedOnFrontOfRipeHash = \ 85 config.safeGetInt( 86 'bitmessagesettings', 87 'numberofnullbytesonaddress', 88 2 if eighteenByteRipe else 1 89 ) 90 elif queueValue[0] == 'stopThread': 91 break 92 else: 93 self.logger.error( 94 'Programming error: A structure with the wrong number' 95 ' of values was passed into the addressGeneratorQueue.' 96 ' Here is the queueValue: %r\n', queueValue) 97 if addressVersionNumber < 3 or addressVersionNumber > 4: 98 self.logger.error( 99 'Program error: For some reason the address generator' 100 ' queue has been given a request to create at least' 101 ' one version %s address which it cannot do.\n', 102 addressVersionNumber) 103 if nonceTrialsPerByte == 0: 104 nonceTrialsPerByte = config.getint( 105 'bitmessagesettings', 'defaultnoncetrialsperbyte') 106 if nonceTrialsPerByte < \ 107 defaults.networkDefaultProofOfWorkNonceTrialsPerByte: 108 nonceTrialsPerByte = \ 109 defaults.networkDefaultProofOfWorkNonceTrialsPerByte 110 if payloadLengthExtraBytes == 0: 111 payloadLengthExtraBytes = config.getint( 112 'bitmessagesettings', 'defaultpayloadlengthextrabytes') 113 if payloadLengthExtraBytes < \ 114 defaults.networkDefaultPayloadLengthExtraBytes: 115 payloadLengthExtraBytes = \ 116 defaults.networkDefaultPayloadLengthExtraBytes 117 if command == 'createRandomAddress': 118 queues.UISignalQueue.put(( 119 'updateStatusBar', 120 _translate( 121 "MainWindow", "Generating one new address") 122 )) 123 # This next section is a little bit strange. We're going 124 # to generate keys over and over until we find one 125 # that starts with either \x00 or \x00\x00. Then when 126 # we pack them into a Bitmessage address, we won't store 127 # the \x00 or \x00\x00 bytes thus making the address shorter. 128 startTime = time.time() 129 numberOfAddressesWeHadToMakeBeforeWeFoundOneWithTheCorrectRipePrefix = 0 130 privSigningKey, pubSigningKey = highlevelcrypto.random_keys() 131 while True: 132 numberOfAddressesWeHadToMakeBeforeWeFoundOneWithTheCorrectRipePrefix += 1 133 potentialPrivEncryptionKey, potentialPubEncryptionKey = \ 134 highlevelcrypto.random_keys() 135 ripe = highlevelcrypto.to_ripe( 136 pubSigningKey, potentialPubEncryptionKey) 137 if ( 138 ripe[:numberOfNullBytesDemandedOnFrontOfRipeHash] 139 == b'\x00' * numberOfNullBytesDemandedOnFrontOfRipeHash 140 ): 141 break 142 self.logger.info( 143 'Generated address with ripe digest: %s', hexlify(ripe)) 144 try: 145 self.logger.info( 146 'Address generator calculated %s addresses at %s' 147 ' addresses per second before finding one with' 148 ' the correct ripe-prefix.', 149 numberOfAddressesWeHadToMakeBeforeWeFoundOneWithTheCorrectRipePrefix, 150 numberOfAddressesWeHadToMakeBeforeWeFoundOneWithTheCorrectRipePrefix 151 / (time.time() - startTime)) 152 except ZeroDivisionError: 153 # The user must have a pretty fast computer. 154 # time.time() - startTime equaled zero. 155 pass 156 address = encodeAddress( 157 addressVersionNumber, streamNumber, ripe) 158 159 privSigningKeyWIF = highlevelcrypto.encodeWalletImportFormat( 160 privSigningKey) 161 privEncryptionKeyWIF = highlevelcrypto.encodeWalletImportFormat( 162 potentialPrivEncryptionKey) 163 164 config.add_section(address) 165 config.set(address, 'label', label) 166 config.set(address, 'enabled', 'true') 167 config.set(address, 'decoy', 'false') 168 config.set(address, 'noncetrialsperbyte', str( 169 nonceTrialsPerByte)) 170 config.set(address, 'payloadlengthextrabytes', str( 171 payloadLengthExtraBytes)) 172 config.set( 173 address, 'privsigningkey', privSigningKeyWIF.decode()) 174 config.set( 175 address, 'privencryptionkey', 176 privEncryptionKeyWIF.decode()) 177 config.save() 178 179 # The API and the join and create Chan functionality 180 # both need information back from the address generator. 181 queues.apiAddressGeneratorReturnQueue.put(address) 182 183 queues.UISignalQueue.put(( 184 'updateStatusBar', 185 _translate( 186 "MainWindow", 187 "Done generating address. Doing work necessary" 188 " to broadcast it...") 189 )) 190 queues.UISignalQueue.put(('writeNewAddressToTable', ( 191 label, address, streamNumber))) 192 shared.reloadMyAddressHashes() 193 if addressVersionNumber == 3: 194 queues.workerQueue.put(( 195 'sendOutOrStoreMyV3Pubkey', ripe)) 196 elif addressVersionNumber == 4: 197 queues.workerQueue.put(( 198 'sendOutOrStoreMyV4Pubkey', address)) 199 200 elif command in ( 201 'createDeterministicAddresses', 'createChan', 202 'getDeterministicAddress', 'joinChan' 203 ): 204 if not deterministicPassphrase: 205 self.logger.warning( 206 'You are creating deterministic' 207 ' address(es) using a blank passphrase.' 208 ' Bitmessage will do it but it is rather stupid.') 209 if command == 'createDeterministicAddresses': 210 queues.UISignalQueue.put(( 211 'updateStatusBar', 212 _translate( 213 "MainWindow", 214 "Generating %1 new addresses." 215 ).arg(str(numberOfAddressesToMake)) 216 )) 217 signingKeyNonce = 0 218 encryptionKeyNonce = 1 219 # We fill out this list no matter what although we only 220 # need it if we end up passing the info to the API. 221 listOfNewAddressesToSendOutThroughTheAPI = [] 222 223 for _ in range(numberOfAddressesToMake): 224 # This next section is a little bit strange. We're 225 # going to generate keys over and over until we find 226 # one that has a RIPEMD hash that starts with either 227 # \x00 or \x00\x00. Then when we pack them into a 228 # Bitmessage address, we won't store the \x00 or 229 # \x00\x00 bytes thus making the address shorter. 230 startTime = time.time() 231 numberOfAddressesWeHadToMakeBeforeWeFoundOneWithTheCorrectRipePrefix = 0 232 while True: 233 numberOfAddressesWeHadToMakeBeforeWeFoundOneWithTheCorrectRipePrefix += 1 234 potentialPrivSigningKey, potentialPubSigningKey = \ 235 highlevelcrypto.deterministic_keys( 236 deterministicPassphrase, 237 encodeVarint(signingKeyNonce)) 238 potentialPrivEncryptionKey, potentialPubEncryptionKey = \ 239 highlevelcrypto.deterministic_keys( 240 deterministicPassphrase, 241 encodeVarint(encryptionKeyNonce)) 242 243 signingKeyNonce += 2 244 encryptionKeyNonce += 2 245 ripe = highlevelcrypto.to_ripe( 246 potentialPubSigningKey, potentialPubEncryptionKey) 247 if ( 248 ripe[:numberOfNullBytesDemandedOnFrontOfRipeHash] 249 == b'\x00' * numberOfNullBytesDemandedOnFrontOfRipeHash 250 ): 251 break 252 253 self.logger.info( 254 'Generated address with ripe digest: %s', hexlify(ripe)) 255 try: 256 self.logger.info( 257 'Address generator calculated %s addresses' 258 ' at %s addresses per second before finding' 259 ' one with the correct ripe-prefix.', 260 numberOfAddressesWeHadToMakeBeforeWeFoundOneWithTheCorrectRipePrefix, 261 numberOfAddressesWeHadToMakeBeforeWeFoundOneWithTheCorrectRipePrefix 262 / (time.time() - startTime) 263 ) 264 except ZeroDivisionError: 265 # The user must have a pretty fast computer. 266 # time.time() - startTime equaled zero. 267 pass 268 address = encodeAddress( 269 addressVersionNumber, streamNumber, ripe) 270 271 saveAddressToDisk = True 272 # If we are joining an existing chan, let us check 273 # to make sure it matches the provided Bitmessage address 274 if command == 'joinChan': 275 if address != chanAddress: 276 listOfNewAddressesToSendOutThroughTheAPI.append( 277 'chan name does not match address') 278 saveAddressToDisk = False 279 if command == 'getDeterministicAddress': 280 saveAddressToDisk = False 281 282 if saveAddressToDisk and live: 283 privSigningKeyWIF = \ 284 highlevelcrypto.encodeWalletImportFormat( 285 potentialPrivSigningKey) 286 privEncryptionKeyWIF = \ 287 highlevelcrypto.encodeWalletImportFormat( 288 potentialPrivEncryptionKey) 289 290 try: 291 config.add_section(address) 292 addressAlreadyExists = False 293 except configparser.DuplicateSectionError: 294 addressAlreadyExists = True 295 296 if addressAlreadyExists: 297 self.logger.info( 298 '%s already exists. Not adding it again.', 299 address 300 ) 301 queues.UISignalQueue.put(( 302 'updateStatusBar', 303 _translate( 304 "MainWindow", 305 "%1 is already in 'Your Identities'." 306 " Not adding it again." 307 ).arg(address) 308 )) 309 else: 310 self.logger.debug('label: %s', label) 311 config.set(address, 'label', label) 312 config.set(address, 'enabled', 'true') 313 config.set(address, 'decoy', 'false') 314 if command in ('createChan', 'joinChan'): 315 config.set(address, 'chan', 'true') 316 config.set( 317 address, 'noncetrialsperbyte', 318 str(nonceTrialsPerByte)) 319 config.set( 320 address, 'payloadlengthextrabytes', 321 str(payloadLengthExtraBytes)) 322 config.set( 323 address, 'privsigningkey', 324 privSigningKeyWIF.decode()) 325 config.set( 326 address, 'privencryptionkey', 327 privEncryptionKeyWIF.decode()) 328 config.save() 329 330 queues.UISignalQueue.put(( 331 'writeNewAddressToTable', 332 (label, address, str(streamNumber)) 333 )) 334 listOfNewAddressesToSendOutThroughTheAPI.append( 335 address) 336 shared.myECCryptorObjects[ripe] = \ 337 highlevelcrypto.makeCryptor( 338 hexlify(potentialPrivEncryptionKey)) 339 shared.myAddressesByHash[ripe] = address 340 tag = highlevelcrypto.double_sha512( 341 encodeVarint(addressVersionNumber) 342 + encodeVarint(streamNumber) + ripe 343 )[32:] 344 shared.myAddressesByTag[tag] = address 345 if addressVersionNumber == 3: 346 # If this is a chan address, 347 # the worker thread won't send out 348 # the pubkey over the network. 349 queues.workerQueue.put(( 350 'sendOutOrStoreMyV3Pubkey', ripe)) 351 elif addressVersionNumber == 4: 352 queues.workerQueue.put(( 353 'sendOutOrStoreMyV4Pubkey', address)) 354 queues.UISignalQueue.put(( 355 'updateStatusBar', 356 _translate( 357 "MainWindow", "Done generating address") 358 )) 359 elif saveAddressToDisk and not live \ 360 and not config.has_section(address): 361 listOfNewAddressesToSendOutThroughTheAPI.append( 362 address) 363 364 # Done generating addresses. 365 if command in ( 366 'createDeterministicAddresses', 'createChan', 'joinChan' 367 ): 368 queues.apiAddressGeneratorReturnQueue.put( 369 listOfNewAddressesToSendOutThroughTheAPI) 370 elif command == 'getDeterministicAddress': 371 queues.apiAddressGeneratorReturnQueue.put(address) 372 else: 373 raise AddressGeneratorException( 374 "Error in the addressGenerator thread. Thread was" 375 + " given a command it could not understand: " + command) 376 queues.addressGeneratorQueue.task_done()