diff --git a/src/bitmessagekivy/kv/payment.kv b/src/bitmessagekivy/kv/payment.kv index 9223c4ed..a5cb1047 100644 --- a/src/bitmessagekivy/kv/payment.kv +++ b/src/bitmessagekivy/kv/payment.kv @@ -93,10 +93,10 @@ size: self.size size: dp(app.window_size[0] - 2*self.parent.parent.padding[0]) - 10 , 1 height: dp(40) - on_press: root.move_to_pay_option(py2.text) + on_press: root.create_hidden_payment_address(self) MDLabel: font_style: 'H6' - text: 'Get Monthly Credits' + text: 'Buy 100 Credits' font_size: '13sp' color: (0,0,0,1) halign: 'center' @@ -139,10 +139,10 @@ size: self.size size: dp(app.window_size[0] - 2*self.parent.parent.padding[0]) - 10 , 1 height: dp(40) - on_press: root.move_to_pay_option(py3.text) + on_press: root.create_hidden_payment_address(self) MDLabel: font_style: 'H6' - text: 'Get Yearly Credits' + text: 'Buy 500 Credits' font_size: '13sp' color: (0,0,0,1) halign: 'center' \ No newline at end of file diff --git a/src/bitmessagekivy/mpybit.py b/src/bitmessagekivy/mpybit.py index 8da4314c..6813b8de 100644 --- a/src/bitmessagekivy/mpybit.py +++ b/src/bitmessagekivy/mpybit.py @@ -891,9 +891,19 @@ class Payment(Screen): state.kivyapp.root.ids.sc18.ids.cred.text = '{0}'.format( state.availabe_credit) - def move_to_pay_option(self, amount): # pylint: disable=no-self-use - """Option move to pay""" - pass + def create_hidden_payment_address(self, instance): + if BMConfigParser().paymentaddress(): + toast('hidden payment address already exist for buying subscription...') + else: + streamNumberForAddress = 1 + eighteenByteRipe = False + nonceTrialsPerByte = 1000 + payloadLengthExtraBytes = 1000 + queues.addressGeneratorQueue.put(( + 'createPaymentAddress', 4, streamNumberForAddress, '', 1, + "", eighteenByteRipe, nonceTrialsPerByte, + payloadLengthExtraBytes)) + toast('hidden payment address Creating for buying subscription....') class Credits(Screen): diff --git a/src/bmconfigparser.py b/src/bmconfigparser.py index 5431d0b8..c19db688 100644 --- a/src/bmconfigparser.py +++ b/src/bmconfigparser.py @@ -56,21 +56,23 @@ class BMConfigParser(configparser.ConfigParser): raise ValueError("Invalid value %s" % value) return configparser.ConfigParser.set(self, section, option, value) - def get(self, section, option, raw=False, variables=None): + def get(self, section, option, raw=False, vars=None): + # import pdb;pdb.set_trace() # pylint: disable=unused-argument + # import pdb; pdb.set_trace() try: if section == "bitmessagesettings" and option == "timeformat": return configparser.ConfigParser.get( - self, section, option, raw=True, vars=variables) + self, section, option, raw=True, vars=vars) try: return self._temp[section][option] except KeyError: pass return configparser.ConfigParser.get( - self, section, option, raw=True, vars=variables) + self, section, option, raw=True, vars=vars) except configparser.InterpolationError: return configparser.ConfigParser.get( - self, section, option, raw=True, vars=variables) + self, section, option, raw=True, vars=vars) except (configparser.NoSectionError, configparser.NoOptionError) as e: try: return BMConfigDefaults[section][option] @@ -86,12 +88,13 @@ class BMConfigParser(configparser.ConfigParser): def safeGetBoolean(self, section, field): """Return value as boolean, False on exceptions""" - config = configparser.ConfigParser() try: # Used in the python2.7 # return self.getboolean(section, field) # Used in the python3.5.2 - return config.getboolean(section, field) + # print(config, section, field) + return self.getboolean(section, field) + # return config.getboolean(section, field) except (configparser.NoSectionError, configparser.NoOptionError, ValueError, AttributeError): return False @@ -122,9 +125,14 @@ class BMConfigParser(configparser.ConfigParser): but override the "raw" argument to always True""" return configparser.ConfigParser.items(self, section, True, variables) - def addresses(self): + def addresses(self, hidden=False): + """Return a list of local bitmessage addresses (from section labels)""" - return [x for x in BMConfigParser().sections() if x.startswith('BM-')] + return [x for x in BMConfigParser().sections() if x.startswith('BM-') and (hidden or not BMConfigParser().safeGetBoolean(x, 'hidden'))] + + def paymentaddress(self): + """Return a list of local payment addresses (from section labels)""" + return ''.join([x for x in BMConfigParser().sections() if x.startswith('BM-') and BMConfigParser().safeGetBoolean(x, 'payment')]) def read(self, filenames): configparser.ConfigParser.read(self, filenames) diff --git a/src/class_addressGenerator.py b/src/class_addressGenerator.py index 5a1c0ac4..73095c8a 100644 --- a/src/class_addressGenerator.py +++ b/src/class_addressGenerator.py @@ -206,9 +206,98 @@ class addressGenerator(StoppableThread): queues.workerQueue.put(( 'sendOutOrStoreMyV4Pubkey', address)) - # elif command == 'createDeterministicAddresses' \ - # or command == 'getDeterministicAddress' \ - # or command == 'createChan' or command == 'joinChan': + elif command == 'createPaymentAddress': + queues.UISignalQueue.put(( + 'updateStatusBar', "" + )) + # This next section is a little bit strange. We're going + # to generate keys over and over until we find one + # that starts with either \x00 or \x00\x00. Then when + # we pack them into a Bitmessage address, we won't store + # the \x00 or \x00\x00 bytes thus making the address shorter. + startTime = time.time() + numberOfAddressesWeHadToMakeBeforeWeFoundOneWithTheCorrectRipePrefix = 0 + potentialPrivSigningKey = OpenSSL.rand(32) + potentialPubSigningKey = highlevelcrypto.pointMult( + potentialPrivSigningKey) + while True: + numberOfAddressesWeHadToMakeBeforeWeFoundOneWithTheCorrectRipePrefix += 1 + potentialPrivEncryptionKey = OpenSSL.rand(32) + potentialPubEncryptionKey = highlevelcrypto.pointMult( + potentialPrivEncryptionKey) + sha = hashlib.new('sha512') + sha.update( + potentialPubSigningKey + potentialPubEncryptionKey) + ripe = RIPEMD160Hash(sha.digest()).digest() + if ( + ripe[:numberOfNullBytesDemandedOnFrontOfRipeHash] == + '\x00'.encode('utf-8') * numberOfNullBytesDemandedOnFrontOfRipeHash + ): + break + self.logger.info( + 'Generated address with ripe digest: %s', hexlify(ripe)) + try: + self.logger.info( + 'Address generator calculated %s addresses at %s' + ' addresses per second before finding one with' + ' the correct ripe-prefix.', + numberOfAddressesWeHadToMakeBeforeWeFoundOneWithTheCorrectRipePrefix, + numberOfAddressesWeHadToMakeBeforeWeFoundOneWithTheCorrectRipePrefix + / (time.time() - startTime)) + except ZeroDivisionError: + # The user must have a pretty fast computer. + # time.time() - startTime equaled zero. + pass + + address = encodeAddress( + addressVersionNumber, streamNumber, ripe) + + # An excellent way for us to store our keys + # is in Wallet Import Format. Let us convert now. + # https://en.bitcoin.it/wiki/Wallet_import_format + privSigningKey = '\x80'.encode('utf-8')[1:] + potentialPrivSigningKey + checksum = hashlib.sha256(hashlib.sha256( + privSigningKey).digest()).digest()[0:4] + privSigningKeyWIF = arithmetic.changebase( + privSigningKey + checksum, 256, 58) + + privEncryptionKey = '\x80'.encode('utf-8')[1:] + potentialPrivEncryptionKey + checksum = hashlib.sha256(hashlib.sha256( + privEncryptionKey).digest()).digest()[0:4] + privEncryptionKeyWIF = arithmetic.changebase( + privEncryptionKey + checksum, 256, 58) + BMConfigParser().add_section(address) + # BMConfigParser().set(address, 'label', label) + BMConfigParser().set(address, 'enabled', 'true') + BMConfigParser().set(address, 'decoy', 'false') + BMConfigParser().set(address, 'noncetrialsperbyte', str( + nonceTrialsPerByte)) + BMConfigParser().set(address, 'payloadlengthextrabytes', str( + payloadLengthExtraBytes)) + BMConfigParser().set( + address, 'privsigningkey', privSigningKeyWIF) + BMConfigParser().set( + address, 'privencryptionkey', privEncryptionKeyWIF) + BMConfigParser().set(address, 'hidden', 'true') + BMConfigParser().set(address, 'payment', 'true') + BMConfigParser().save() + + # The API and the join and create Chan functionality + # both need information back from the address generator. + queues.apiAddressGeneratorReturnQueue.put(address) + queues.UISignalQueue.put(( + 'updateStatusBar', "" + )) + queues.UISignalQueue.put(('writeNewAddressToTable', ( + label, address, streamNumber))) + shared.reloadMyAddressHashes() + if addressVersionNumber == 3: + queues.workerQueue.put(( + 'sendOutOrStoreMyV3Pubkey', ripe)) + elif addressVersionNumber == 4: + queues.workerQueue.put(( + 'sendOutOrStoreMyV4Pubkey', address)) + elif command in ( 'createDeterministicAddresses', 'getDeterministicAddress', diff --git a/src/helper_startup.py b/src/helper_startup.py index 997e58e3..e4371400 100644 --- a/src/helper_startup.py +++ b/src/helper_startup.py @@ -215,7 +215,7 @@ def updateConfig(): # Adjust the required POW values for each of this user's addresses # to conform to protocol v3 norms. if settingsversion == 9: - for addressInKeysFile in config.addresses(): + for addressInKeysFile in config.addresses(hidden=True): try: previousTotalDifficulty = float( config.getint( diff --git a/src/shared.py b/src/shared.py index d84e7be6..469af38d 100644 --- a/src/shared.py +++ b/src/shared.py @@ -142,7 +142,7 @@ def reloadMyAddressHashes(): keyfileSecure = checkSensitiveFilePermissions(os.path.join( state.appdata, 'keys.dat')) hasEnabledKeys = False - for addressInKeysFile in BMConfigParser().addresses(): + for addressInKeysFile in BMConfigParser().addresses(hidden=True): isEnabled = BMConfigParser().safeGet(addressInKeysFile, 'enabled') if isEnabled: hasEnabledKeys = True