Ejemplo n.º 1
0
 def from_private_key(cls, priv_key, host, port, network, amount, fee,
                      addr_new, change):
     address, secret, compressed = deserialize_privkey(priv_key)
     sk = regenerate_key(secret)
     pubk = sk.get_public_key(compressed)
     return cls(host, port, network, amount, fee, sk, pubk, addr_new,
                change)
Ejemplo n.º 2
0
 def from_private_key(cls,
                      priv_key,
                      coin_hash,
                      host,
                      port,
                      network,
                      amount,
                      fee,
                      addr_new,
                      change,
                      ssl=False,
                      logger=None):
     address, secret, compressed = deserialize_privkey(priv_key)
     sk = regenerate_key(secret)
     pubk = sk.get_public_key(compressed)
     sks = {pubk: sk}
     inputs = {pubkey: [coin_hash]}
     return cls(host,
                port,
                network,
                coin_hash,
                amount,
                fee,
                sk,
                sks,
                inputs,
                pubk,
                addr_new,
                change,
                ssl=ssl,
                logger=logger)
Ejemplo n.º 3
0
 def checkd_data_sig(self,sig,pre,pk):
     sec, compressed = self.keypair.get(pk)
     pre_hash = Hash(pre)
     pkey = regenerate_key(sec)
     secexp = pkey.secret
     private_key = MySigningKey.from_secret_exponent(secexp, curve=ecdsa.SECP256k1)
     public_key = private_key.get_verifying_key()
     print("Data signature ok:")
     print(public_key.verify_digest(sig[:-1], pre_hash, sigdecode=ecdsa.util.sigdecode_der))
    def start_coinshuffle_protocol(self):
        print('protocol started')
        # from electroncash_plugins.coinshuffle.client import protocolThread
        from .client import protocolThread
        from electroncash.bitcoin import (regenerate_key, deserialize_privkey)
        from .shuffle import ConsoleLogger
        parent = self.window.top_level_window()
        password = None
        while self.window.wallet.has_password():
            password = self.window.password_dialog(parent=parent)
            if password is None:
                # User cancelled password input
                return
            try:
                self.window.wallet.check_password(password)
                break
            except Exception as e:
                self.window.show_error(str(e), parent=parent)
                continue
        try:
            server_params = self.window.config.get('coinshuffleserver').split(":")
            server = server_params[0]
            port = int(server_params[1])
            ssl = self.window.config.get('coinshufflessl')
        except:
            self.coinshuffle_text_output.setText('Wrong server connection string')
            return
        input_address = self.coinshuffle_inputs.get_input_address()
        change_address = self.coinshuffle_changes.get_change_address()
        output_address = self.coinshuffle_outputs.get_output_address()
        #disable inputs
        self.coinshuffle_start_button.setEnabled(False)
        self.coinshuffle_inputs.setEnabled(False)
        self.coinshuffle_changes.setEnabled(False)
        self.coinshuffle_outputs.setEnabled(False)
        self.coinshuffle_amount_radio.setEnabled(False)

        amount = self.coinshuffle_amount_radio.get_amount()
        fee = self.coinshuffle_fee_constant
        logger =  ConsoleLogger()
        logger.logUpdater.connect(lambda x: self.process_protocol_messages(x))
        priv_key = self.window.wallet.export_private_key(input_address, password)
        pub_key = self.window.wallet.get_public_key(input_address)
        sk = regenerate_key(deserialize_privkey(priv_key[0])[1])
        self.pThread = protocolThread(server, port, self.window.network, amount, fee, sk, pub_key, output_address, change_address, logger = logger, ssl = ssl)
        print('start thread')
        self.pThread.start()
        print('thread started')
Ejemplo n.º 5
0
    def start_coinshuffle_protocol(self):

        from .client import ProtocolThread
        from electroncash.bitcoin import (regenerate_key, deserialize_privkey)
        from .shuffle import ConsoleLogger
        parent = self.window.top_level_window()
        password = None
        while self.window.wallet.has_password():
            password = self.window.password_dialog(parent=parent)
            if password is None:
                # User cancelled password input
                return
            try:
                self.window.wallet.check_password(password)
                break
            except Exception as e:
                self.window.show_error(str(e), parent=parent)
                continue
        try:
            server_params = self.coinshuffle_servers.get_current_server()
            server = server_params['server']
            port = server_params['port']
            ssl = server_params.get('ssl', False)
        except:
            self.coinshuffle_text_output.setText('Wrong server connection string')
            return
        input_address = self.coinshuffle_inputs.get_input_address()
        possible_change_address = self.coinshuffle_changes.get_change_address()
        if possible_change_address:
            change_address = possible_change_address
        else:
            change_address = self.coinshuffle_inputs.get_input_address_as_string()
        output_address = self.coinshuffle_outputs.get_output_address()
        #disable inputs
        self.disable_coinshuffle_settings()
        self.coinshuffle_cancel_button.setEnabled(True)

        amount = self.coinshuffle_amount_radio.get_amount()
        fee = self.coinshuffle_fee_constant
        self.logger = ConsoleLogger()
        self.logger.logUpdater.connect(lambda x: self.process_protocol_messages(x))
        priv_key = self.window.wallet.export_private_key(input_address, password)
        pub_key = self.window.wallet.get_public_key(input_address)
        sk = regenerate_key(deserialize_privkey(priv_key)[1])
        self.pThread = ProtocolThread(server, port, self.window.network, amount, fee, sk, pub_key, output_address, change_address, logger = self.logger, ssl = ssl)
        self.pThread.start()
        self.timer.start(1000)
Ejemplo n.º 6
0
def keys_from_priv(priv_key):
    address, secret, compressed = deserialize_privkey(priv_key)
    sk = regenerate_key(secret)
    pubk = sk.get_public_key(compressed)
    return sk, pubk
Ejemplo n.º 7
0
    def _make_protocol_thread(self, scale, coins):
        def get_coin_for_shuffling(scale, coins):
            if not getattr(self.wallet, "is_coin_shuffled", None):
                raise RuntimeWarning('Wallet lacks is_coin_shuffled method!')
            unshuffled_coins = [coin for coin in coins
                                # Note: the 'is False' is intentional -- we are interested in coins that we know for SURE are not shuffled.
                                # is_coin_shuffled() also returns None in cases where the tx isn't in the history (a rare occurrence)
                                if self.wallet.is_coin_shuffled(coin) is False]
            upper_amount = min(scale*10 + self.FEE, self.UPPER_BOUND)
            lower_amount = scale + self.FEE
            unshuffled_coins_on_scale = [coin for coin in unshuffled_coins
                                         # exclude coins out of range and 'done' coins still in history
                                         # also exclude coinbase coins (see issue #64)
                                         if coin['value'] < upper_amount and coin['value'] >= lower_amount and get_name(coin) not in self.done_utxos and not coin['coinbase']]
            unshuffled_coins_on_scale.sort(key=lambda x: (x['value'], -x['height']))  # sort by value, preferring older coins on tied value
            if unshuffled_coins_on_scale:
                return unshuffled_coins_on_scale[-1]  # take the largest,oldest on the scale
            return None
        # /
        coin = get_coin_for_shuffling(scale, coins)
        if not coin:
            return
        try:
            private_key = self.wallet.export_private_key(coin['address'], self.get_password())
        except InvalidPassword:
            # This shouldn't normally happen but can if the user JUST changed their password in the GUI thread
            # and we didn't yet get informed of the new password.  In which case we give up for now and 10 seconds later
            # (the next 'period' time), this coin will be picked up again.
            raise RuntimeWarning('Invalid Password caught when trying to export a private key -- if this keeps happening tell the devs!')
        utxo_name = get_name(coin)
        self.wallet.set_frozen_coin_state([utxo_name], True)
        self._coins_busy_shuffling.add(utxo_name)
        self.wallet.storage.put(COINS_FROZEN_BY_SHUFFLING, list(self._coins_busy_shuffling))
        inputs = {}
        sks = {}
        public_key = self.wallet.get_public_key(coin['address'])
        sk = regenerate_key(deserialize_privkey(private_key)[1])
        inputs[public_key] = [utxo_name]
        sks[public_key] = sk
        id_sk = generate_random_sk()
        id_pub = id_sk.GetPubKey(True).hex()

        output = None
        for address in self.wallet.get_unused_addresses():
            if address not in self.wallet._addresses_cashshuffle_reserved:
                output = address
                break
        while not output:
            address = self.wallet.create_new_address(for_change = False)
            if address not in self.wallet._addresses_cashshuffle_reserved:
                output = address
        # Reserve the output address so other threads don't use it
        self.wallet._addresses_cashshuffle_reserved.add(output)   # NB: only modify this when holding wallet locks
        # Check if we will really use the change address. We won't be receving to it if the change is below dust threshold (see #67)
        will_receive_change = coin['value'] - scale - self.FEE >= dust_threshold(Network.get_instance())
        if will_receive_change:
            change = self.wallet.cashshuffle_get_new_change_address(for_shufflethread=True)
            # We anticipate using the change address in the shuffle tx, so reserve this address
            self.wallet._addresses_cashshuffle_reserved.add(change)
        else:
            # We still have to specify a change address to the protocol even if it won't be used. :/
            # We'll just take whatever address. The leftover dust amount will go to fee.
            change = self.wallet.get_change_addresses()[0]
        self.print_error("Scale {} Coin {} OutAddr {} {} {} make_protocol_thread".format(scale, utxo_name, output.to_storage_string(), "Change" if will_receive_change else "FakeChange",change.to_storage_string()))
        #self.print_error("Reserved addresses:", self.wallet._addresses_cashshuffle_reserved)
        ctimeout = 12.5 if (Network.get_instance() and Network.get_instance().get_proxies()) else 5.0 # allow for 12.5 second connection timeouts if using a proxy server
        thr = ProtocolThread(host=self.host, port=self.port, ssl=self.ssl,
                             comm_timeout=self.timeout, ctimeout=ctimeout,  # comm timeout and connect timeout
                             coin=utxo_name,
                             amount=scale, fee=self.FEE, total_amount=coin['value'],
                             addr_new_addr=output, change_addr=change, fake_change=not will_receive_change,
                             sk=id_sk, sks=sks, inputs=inputs, pubk=id_pub,
                             logger=None)
        thr.logger = ChannelSendLambda(lambda msg: self.protocol_thread_callback(thr, msg))
        self.threads[scale] = thr
        coins.remove(coin)
        thr.start()
        return True
    def start_coinshuffle_protocol(self):
        from .client import ProtocolThread
        from electroncash.bitcoin import (regenerate_key, deserialize_privkey)
        from .shuffle import ConsoleLogger
        parent = self.window.top_level_window()
        password = None
        while self.window.wallet.has_password():
            password = self.window.password_dialog(parent=parent)
            if password is None:
                # User cancelled password input
                return
            try:
                self.window.wallet.check_password(password)
                break
            except Exception as e:
                self.window.show_error(str(e), parent=parent)
                continue
        try:
            server_params = self.coinshuffle_servers.get_current_server()
            server = server_params['server']
            port = server_params['port']
            ssl = server_params.get('ssl', False)
        except:
            self.coinshuffle_text_output.setText(
                'Wrong server connection string')
            return

        inputs_utxos = self.coinshuffle_inputs_list.get_checked_utxos()
        possible_change_address = self.coinshuffle_changes.get_change_address()
        if possible_change_address:
            change_address = possible_change_address
        else:
            change_address = inputs_utxos[0]['address'].to_string(
                Address.FMT_LEGACY)
        if self.coinshuffle_use_external_output.isChecked():
            output_address = self.coinshuffle_external_output.text()
        else:
            output_address = self.coinshuffle_outputs.get_output_address()
        #disable inputs
        self.disable_coinshuffle_settings()
        self.coinshuffle_cancel_button.setEnabled(True)
        #
        amount = self.coinshuffle_amount_radio.get_amount()
        fee = self.coinshuffle_fee_constant
        self.logger = ConsoleLogger()
        self.logger.logUpdater.connect(
            lambda x: self.process_protocol_messages(x))
        sks = {}
        inputs = {}
        for utxo in inputs_utxos:
            public_key = self.window.wallet.get_public_key(utxo['address'])
            priv_key = self.window.wallet.export_private_key(
                utxo['address'], password)
            sks[public_key] = regenerate_key(deserialize_privkey(priv_key)[1])
            if not public_key in inputs:
                inputs[public_key] = []
            inputs[public_key].append(utxo['prevout_hash'] + ":" +
                                      str(utxo['prevout_n']))
        pub_key = list(inputs.keys())[0]
        sk = sks[pub_key]
        self.pThread = ProtocolThread(server,
                                      port,
                                      self.window.network,
                                      amount,
                                      fee,
                                      sk,
                                      sks,
                                      inputs,
                                      pub_key,
                                      output_address,
                                      change_address,
                                      logger=self.logger,
                                      ssl=ssl)
        self.pThread.start()
        self.timer.start(1000)
Ejemplo n.º 9
0
    def _make_protocol_thread(self, scale, coins, scale_lower_bound, scale_upper_bound):
        def get_coin_for_shuffling(scale, coins, scale_lower_bound, scale_upper_bound):
            upper_bound = min(scale_upper_bound, self.UPPER_BOUND)
            lower_bound = max(scale_lower_bound, self.LOWER_BOUND)
            unshuffled_coins_on_scale = [coin for coin in coins
                                         # exclude coins out of range and 'done' coins still in history
                                         # also exclude coinbase coins (see issue #64)
                                         if (coin['value'] < upper_bound
                                             and coin['value'] >= lower_bound) ]
            unshuffled_coins_on_scale.sort(key=lambda x: (x['value'], -x['height']))  # sort by value, preferring older coins on tied value
            if unshuffled_coins_on_scale:
                return unshuffled_coins_on_scale[-1]  # take the largest,oldest on the scale
            return None
        # /
        coin = get_coin_for_shuffling(scale, coins, scale_lower_bound, scale_upper_bound)
        if not coin:
            return
        try:
            private_key = self.wallet.export_private_key(coin['address'], self.get_password())
        except InvalidPassword:
            # This shouldn't normally happen but can if the user JUST changed their password in the GUI thread
            # and we didn't yet get informed of the new password.  In which case we give up for now and 10 seconds later
            # (the next 'period' time), this coin will be picked up again.
            raise RuntimeWarning('Invalid Password caught when trying to export a private key -- if this keeps happening tell the devs!')
        utxo_name = CoinUtils.get_name(coin)
        self.wallet.set_frozen_coin_state([utxo_name], True)
        self._coins_busy_shuffling.add(utxo_name)
        self.wallet.storage.put(ConfKeys.PerWallet.COINS_FROZEN_BY_SHUFFLING, list(self._coins_busy_shuffling))
        inputs = {}
        sks = {}
        public_key = self.wallet.get_public_key(coin['address'])
        sk = regenerate_key(deserialize_privkey(private_key)[1])
        inputs[public_key] = [utxo_name]
        sks[public_key] = sk
        id_sk = self.generate_random_sk()
        id_pub = id_sk.GetPubKey(True).hex()

        output = self.wallet.cashshuffle_get_new_change_address(for_shufflethread=2)
        # Check if we will really use the change address. We definitely won't
        # be receving to it if the change is below dust threshold (see #67).
        # Furthermore, we may not receive change even if this check predicts we
        # will due to #68.
        may_receive_change = coin['value'] - scale - self.FEE >= dust_threshold(Network.get_instance())
        if may_receive_change:
            # We anticipate (maybe) using the change address in the shuffle tx,
            # so reserve this address. Note that due to "smallest player raises
            # shuffle amount" rules in version=200+ (#68) we WON'T necessarily
            # USE this change address. (In that case it will be freed up later
            # after shuffling anyway so no address leaking occurs).
            # We just reserve it if we think we MAY need it.
            change = self.wallet.cashshuffle_get_new_change_address(for_shufflethread=1)
        else:
            # We *definitely* won't receive any change no matter who
            # participates because we are very close to scale.
            # (The leftover dust amount will go to fee.)
            # We still have to specify a change address to the protocol even if
            # it definitely won't be used. :/
            # We'll just take a hard-coded address whose private key is the
            # number 1337 (we do it this way so we don't leak anything
            # identifying every time we shuffle).
            # Don't worry: It's 100% guaranteed we won't be using this address.
            change = self._dummy_address
        self.print_error("Scale {} Coin {} OutAddr {} {} {} make_protocol_thread".format(scale, utxo_name, output.to_storage_string(), "Change" if may_receive_change else "FakeChange", change.to_storage_string()))
        #self.print_error("Reserved addresses:", self.wallet._addresses_cashshuffle_reserved)
        ctimeout = 12.5 if (Network.get_instance() and Network.get_instance().get_proxies()) else 5.0 # allow for 12.5 second connection timeouts if using a proxy server
        thr = ProtocolThread(host=self.host, port=self.port, ssl=self.ssl,
                             comm_timeout=self.timeout, ctimeout=ctimeout,  # comm timeout and connect timeout
                             coin=utxo_name,
                             scale=scale, fee=self.FEE, coin_value=coin['value'],
                             addr_new_addr=output, change_addr=change,
                             sk=id_sk, sks=sks, inputs=inputs, pubk=id_pub,
                             logger=None, version=self.version, typ=self.type)
        thr.logger = ChannelSendLambda(lambda msg: self.protocol_thread_callback(thr, msg))
        cls = type(self)
        cls.latest_shuffle_settings = cls.ShuffleSettings(thr.type, Messages.TYPE_NAME_DICT[thr.type], thr.version, scale, coin['value'], self.FEE)
        self.threads[scale] = thr
        coins.remove(coin)
        thr.start()
        return True