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)
def refresh(self) -> None: if not self.viewIfLoaded: return entry = utils.nspy_get_byname(self, 'entry') lbl = self.addressTit lbl.setText_withKerning_( _("Address"), utils._kern ) lbl = self.address lbl.text = str(entry.address) if entry.is_frozen: lbl.textColor = utils.uicolor_custom('frozen address text') else: lbl.textColor = utils.uicolor_custom('dark') lbl = self.scriptTypeTit lbl.setText_withKerning_( _("Script type"), utils._kern ) lbl = self.scriptType xtype = bitcoin.deserialize_privkey(entry.privkey)[0] lbl.text = xtype lbl = self.privKeyTit lbl.setText_withKerning_( _("Private key"), utils._kern ) tv = self.privKey tv.text = str(entry.privkey) lbl = self.redeemScriptTit lbl.setText_withKerning_( _("Redeem Script"), utils._kern ) tv = self.redeemScript tv.text = entry.address.to_script().hex()
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)
def generate_addresses(self, batch): addresses = [] for k in batch: k_type, private_key, compressed = deserialize_privkey(k) pubkey = public_key_from_private_key(private_key, compressed) address = Address.from_pubkey(pubkey) addresses.append(address) return addresses
def verify_signature_with_privkey(wif_privkey: str, message: str, signature: str) -> bool: try: sig = base64.b64decode(signature) except binascii.Error: return False keytype, pk, is_compressed = bitcoin.deserialize_privkey(wif_privkey) eck = bitcoin.EC_KEY(pk) try: eck.verify_message(sig, message.encode("utf-8")) except Exception: return False return True
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')
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)
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
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)
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
def sign_message(wif_privkey: str, message: str) -> bytes: keytype, pk, is_compressed = bitcoin.deserialize_privkey(wif_privkey) eck = bitcoin.EC_KEY(pk) return eck.sign_message(message, is_compressed)