def start_new_window(self, path, uri): '''Raises the window for the wallet if it is open. Otherwise opens the wallet and creates a new window for it''' try: wallet = self.daemon.load_wallet(path, None) except BaseException as e: traceback.print_exc(file=sys.stdout) d = QMessageBox(QMessageBox.Warning, _('Error'), _('Cannot load wallet') + ' (1):\n' + str(e)) d.exec_() return if not wallet: storage = WalletStorage(path, manual_upgrades=True) wizard = InstallWizard(self.config, self.app, self.plugins, storage) try: wallet = wizard.run_and_get_wallet(self.daemon.get_wallet) except UserCancelled: pass except GoBack as e: print_error('[start_new_window] Exception caught (GoBack)', e) except (WalletFileException, BitcoinException) as e: traceback.print_exc(file=sys.stderr) d = QMessageBox(QMessageBox.Warning, _('Error'), _('Cannot load wallet') + ' (2):\n' + str(e)) d.exec_() return finally: wizard.terminate() if not wallet: return if not self.daemon.get_wallet(wallet.storage.path): # wallet was not in memory wallet.start_threads(self.daemon.network) self.daemon.add_wallet(wallet) try: for w in self.windows: if w.wallet.storage.path == wallet.storage.path: w.bring_to_top() return w = self.create_window_for_wallet(wallet) except BaseException as e: traceback.print_exc(file=sys.stdout) d = QMessageBox( QMessageBox.Warning, _('Error'), _('Cannot create window for wallet') + ':\n' + str(e)) d.exec_() return if uri: w.pay_to_URI(uri) w.bring_to_top() w.setWindowState(w.windowState() & ~QtCore.Qt.WindowMinimized | QtCore.Qt.WindowActive) # this will activate the window w.activateWindow() return w
def give_error(self, message, clear_client=False): print_error(message) if not self.signing: self.handler.show_error(message) else: self.signing = False if clear_client: self.client = None raise Exception(message)
def hid_send_encrypt(self, msg): reply = "" try: secret = Hash(self.password) msg = EncodeAES(secret, msg) reply = self.hid_send_plain(msg) if 'ciphertext' in reply: reply = DecodeAES(secret, ''.join(reply["ciphertext"])) reply = to_string(reply, 'utf8') reply = json.loads(reply) if 'error' in reply: self.password = None except Exception as e: print_error('Exception caught ' + str(e)) return reply
def use_tor_proxy(self, use_it): if not use_it: self.proxy_cb.setChecked(False) else: socks5_mode_index = self.proxy_mode.findText('SOCKS5') if socks5_mode_index == -1: print_error("[network_dialog] can't find proxy_mode 'SOCKS5'") return self.proxy_mode.setCurrentIndex(socks5_mode_index) self.proxy_host.setText("127.0.0.1") self.proxy_port.setText(str(self.tor_proxy[1])) self.proxy_user.setText("") self.proxy_password.setText("") self.tor_cb.setChecked(True) self.proxy_cb.setChecked(True) self.check_disable_proxy(use_it) self.set_proxy()
def hid_send_plain(self, msg): reply = "" try: serial_number = self.dbb_hid.get_serial_number_string() if "v2.0." in serial_number or "v1." in serial_number: hidBufSize = 4096 self.dbb_hid.write('\0' + msg + '\0' * (hidBufSize - len(msg))) r = bytearray() while len(r) < hidBufSize: r += bytearray(self.dbb_hid.read(hidBufSize)) else: self.hid_send_frame(msg) r = self.hid_read_frame() r = r.rstrip(b' \t\r\n\0') r = r.replace(b"\0", b'') r = to_string(r, 'utf8') reply = json.loads(r) except Exception as e: print_error('Exception caught ' + str(e)) return reply
def update_status(self, b): print_error('trezor status', b)
def sign_transaction(self, tx, password): if tx.is_complete(): return try: p2pkhTransaction = True derivations = self.get_tx_derivations(tx) inputhasharray = [] hasharray = [] pubkeyarray = [] # Build hasharray from inputs for i, txin in enumerate(tx.inputs()): if txin['type'] == 'coinbase': self.give_error( "Coinbase not supported") # should never happen if txin['type'] != 'p2pkh': p2pkhTransaction = False for x_pubkey in txin['x_pubkeys']: if x_pubkey in derivations: index = derivations.get(x_pubkey) inputPath = "%s/%d/%d" % (self.get_derivation(), index[0], index[1]) inputHash = Hash( binascii.unhexlify(tx.serialize_preimage(i))) hasharray_i = { 'hash': to_hexstr(inputHash), 'keypath': inputPath } hasharray.append(hasharray_i) inputhasharray.append(inputHash) break else: self.give_error("No matching x_key for sign_transaction" ) # should never happen # Build pubkeyarray from outputs for _type, address, amount in tx.outputs(): assert _type == TYPE_ADDRESS info = tx.output_info.get(address) if info is not None: index, xpubs, m = info changePath = self.get_derivation() + "/%d/%d" % index changePubkey = self.derive_pubkey(index[0], index[1]) pubkeyarray_i = { 'pubkey': changePubkey, 'keypath': changePath } pubkeyarray.append(pubkeyarray_i) # Special serialization of the unsigned transaction for # the mobile verification app. # At the moment, verification only works for p2pkh transactions. if p2pkhTransaction: class CustomTXSerialization(Transaction): @classmethod def input_script(self, txin, estimate_size=False): if txin['type'] == 'p2pkh': return Transaction.get_preimage_script(txin) if txin['type'] == 'p2sh': # Multisig verification has partial support, but is disabled. This is the # expected serialization though, so we leave it here until we activate it. return '00' + push_script( Transaction.get_preimage_script(txin)) raise Exception("unsupported type %s" % txin['type']) tx_dbb_serialized = CustomTXSerialization( tx.serialize()).serialize() else: # We only need this for the signing echo / verification. tx_dbb_serialized = None # Build sign command dbb_signatures = [] steps = math.ceil(1.0 * len(hasharray) / self.maxInputs) for step in range(int(steps)): hashes = hasharray[step * self.maxInputs:(step + 1) * self.maxInputs] msg = { "sign": { "data": hashes, "checkpub": pubkeyarray, }, } if tx_dbb_serialized is not None: msg["sign"]["meta"] = to_hexstr(Hash(tx_dbb_serialized)) msg = json.dumps(msg).encode('ascii') dbb_client = self.plugin.get_client(self) if not dbb_client.is_paired(): raise Exception("Could not sign transaction.") reply = dbb_client.hid_send_encrypt(msg) if 'error' in reply: raise Exception(reply['error']['message']) if 'echo' not in reply: raise Exception("Could not sign transaction.") if self.plugin.is_mobile_paired( ) and tx_dbb_serialized is not None: reply['tx'] = tx_dbb_serialized self.plugin.comserver_post_notification(reply) if steps > 1: self.handler.show_message( _("Signing large transaction. Please be patient ...") + "\n\n" + _("To continue, touch the Digital Bitbox's blinking light for 3 seconds." ) + " " + _("(Touch {} of {})").format((step + 1), steps) + "\n\n" + _("To cancel, briefly touch the blinking light or wait for the timeout." ) + "\n\n") else: self.handler.show_message( _("Signing transaction...") + "\n\n" + _("To continue, touch the Digital Bitbox's blinking light for 3 seconds." ) + "\n\n" + _("To cancel, briefly touch the blinking light or wait for the timeout." )) # Send twice, first returns an echo for smart verification reply = dbb_client.hid_send_encrypt(msg) self.handler.finished() if 'error' in reply: if reply["error"].get('code') in (600, 601): # aborted via LED short touch or timeout raise UserCancelled() raise Exception(reply['error']['message']) if 'sign' not in reply: raise Exception("Could not sign transaction.") dbb_signatures.extend(reply['sign']) # Fill signatures if len(dbb_signatures) != len(tx.inputs()): raise Exception("Incorrect number of transactions signed." ) # Should never occur for i, txin in enumerate(tx.inputs()): num = txin['num_sig'] for pubkey in txin['pubkeys']: signatures = list(filter(None, txin['signatures'])) if len(signatures) == num: break # txin is complete ii = txin['pubkeys'].index(pubkey) signed = dbb_signatures[i] if 'recid' in signed: # firmware > v2.1.1 recid = int(signed['recid'], 16) s = binascii.unhexlify(signed['sig']) h = inputhasharray[i] pk = MyVerifyingKey.from_signature(s, recid, h, curve=SECP256k1) pk = to_hexstr(point_to_ser(pk.pubkey.point, True)) elif 'pubkey' in signed: # firmware <= v2.1.1 pk = signed['pubkey'] if pk != pubkey: continue sig_r = int(signed['sig'][:64], 16) sig_s = int(signed['sig'][64:], 16) sig = sigencode_der(sig_r, sig_s, generator_secp256k1.order()) txin['signatures'][ii] = to_hexstr(sig) + '01' tx._inputs[i] = txin except UserCancelled: raise except BaseException as e: self.give_error(e, True) else: print_error("Transaction is_complete", tx.is_complete()) tx.raw = tx.serialize()
import platform from electrum_zclassic.plugins import BasePlugin, hook from electrum_zclassic_gui.qt.util import WaitingDialog, EnterButton, WindowModalDialog from electrum_zclassic.util import print_msg, print_error from electrum_zclassic.i18n import _ from PyQt5.QtGui import * from PyQt5.QtCore import * from PyQt5.QtWidgets import (QComboBox, QGridLayout, QLabel, QPushButton) try: import amodem.audio import amodem.main import amodem.config print_error('Audio MODEM is available.') amodem.log.addHandler(amodem.logging.StreamHandler(sys.stderr)) amodem.log.setLevel(amodem.logging.INFO) except ImportError: amodem = None print_error('Audio MODEM is not found.') class Plugin(BasePlugin): def __init__(self, parent, config, name): BasePlugin.__init__(self, parent, config, name) if self.is_available(): self.modem_config = amodem.config.slowest() self.library_name = { 'Linux': 'libportaudio.so'
def check_tx_slp(wallet, tx, *, coins_to_burn=None, require_tx_in_wallet=True): # Step 1) Double check all input transactions have been added to wallet._slp_txo if require_tx_in_wallet: for txo in tx.inputs(): addr = txo['address'] prev_out = txo['prevout_hash'] prev_n = txo['prevout_n'] with wallet.lock: try: input_tx = wallet.transactions[prev_out] except KeyError: raise Exception( 'Wallet has not downloaded this transaction') else: try: slp_msg = slp.SlpMessage.parseSlpOutputScript( input_tx.outputs()[0][1]) except SlpInvalidOutputMessage: pass except SlpUnsupportedSlpTokenType: raise UnsupportedSlpTokenType('Transaction contains an unsupported SLP' \ + ' input type') else: if slp_msg.transaction_type == 'SEND': if prev_n >= len( slp_msg. op_return_fields['token_output']): continue elif slp_msg.transaction_type in [ 'GENESIS', 'MINT' ]: if slp_msg.op_return_fields['mint_baton_vout'] and \ prev_n not in [1, slp_msg.op_return_fields['mint_baton_vout']]: continue elif not slp_msg.op_return_fields[ 'mint_baton_vout'] and prev_n != 1: continue elif slp_msg.transaction_type == 'MINT' and \ prev_n == 1 and \ slp_msg.op_return_fields['additional_token_quantity'] == 0: continue try: with wallet.lock: assert wallet._slp_txo[addr][prev_out][ prev_n] except (KeyError, AssertionError): raise SlpMissingInputRecord('Transaction contains an SLP input that is' \ + ' unknown to this wallet (missing from slp_txo).') # Step 2) Get SLP metadata in current transaction try: slp_msg = slp.SlpMessage.parseSlpOutputScript(tx.outputs()[0][1]) except SlpParsingError: slp_msg = None # Step 3a) If non-SLP check for SLP inputs (only allow # spending slp inputs specified in 'coins_to_burn') if not slp_msg: for txo in tx.inputs(): addr = txo['address'] prev_out = txo['prevout_hash'] prev_n = txo['prevout_n'] slp_txo = None with wallet.lock: try: slp_txo = wallet._slp_txo[addr][prev_out][prev_n] except KeyError: pass if slp_txo: is_burn_allowed = False if coins_to_burn: for c in coins_to_burn: if c['prevout_hash'] == prev_out and c[ 'prevout_n'] == prev_n: is_burn_allowed = True c['is_in_txn'] = True if not is_burn_allowed: print_error("SLP check failed for non-SLP transaction" \ + " which contains SLP inputs.") raise NonSlpTransactionHasSlpInputs( 'Non-SLP transaction contains unspecified SLP inputs.' ) # Check that all coins within 'coins_to_burn' are included in burn transaction if coins_to_burn: for coin in coins_to_burn: try: if coin['is_in_txn']: continue except KeyError: raise MissingCoinToBeBurned('Transaction is missing SLP required inputs that were' \ + ' for this burn transaction.') # Step 3b) If SLP, check quantities and token id of inputs match output requirements elif slp_msg: if slp_msg.transaction_type == 'SEND': tid = slp_msg.op_return_fields['token_id_hex'] # raise an Exception if: # - [X] input quantity is greater than output quanitity (except if 'coins_to_burn') # - [X] input quantity is less than output quanitity # - [X] slp input does not match tokenId # - [X] make sure outpoint is provided for every slp output and is P2PKH or P2SH # - [ ] the proper token type is not respected in the output op_return message slp_outputs = slp_msg.op_return_fields['token_output'] input_slp_qty = 0 for txo in tx.inputs(): addr = txo['address'] prev_out = txo['prevout_hash'] prev_n = txo['prevout_n'] with wallet.lock: try: slp_input = wallet._slp_txo[addr][prev_out][prev_n] except KeyError: pass else: input_slp_qty += slp_input['qty'] if slp_input['token_id'] != tid: print_error("SLP check failed for SEND due to incorrect" \ + " tokenId in txn input") raise SlpWrongTokenID('Transaction contains SLP inputs' \ + ' with incorrect token id.') if input_slp_qty < sum(slp_outputs): print_error( "SLP check failed for SEND due to insufficient SLP inputs" ) raise SlpInputsTooLow( 'Transaction SLP outputs exceed SLP inputs') elif not coins_to_burn and input_slp_qty > sum(slp_outputs): print_error( "SLP check failed for SEND due to SLP inputs too high") raise SlpInputsTooHigh( 'Transaction SLP inputs exceed SLP outputs.') for i, out in enumerate( slp_msg.op_return_fields['token_output']): try: out = tx.outputs()[i] except IndexError: print_error("Transaction is missing vout for MINT operation" \ + " token receiver") raise MissingTokenReceiverOutpoint('Transaction is missing' \ + ' a required SLP output.') else: if i == 0: assert out[0] == 2 elif out[1].kind not in [ Address.ADDR_P2PKH, Address.ADDR_P2SH ]: print_error( "Transaction token receiver vout is not P2PKH or P2SH" ) raise BadSlpOutpointType('Tranaction SLP output must be p2pkh' \ + ' or p2sh output type.') elif slp_msg.transaction_type == 'MINT': tid = slp_msg.op_return_fields['token_id_hex'] # raise an Exception if: # - [X] Any non-baton SLP input is found # - [X] Baton has wrong token ID # - [ ] Minting transaction is being made from NFT child type baton for txo in tx.inputs(): addr = txo['address'] prev_out = txo['prevout_hash'] prev_n = txo['prevout_n'] with wallet.lock: try: slp_input = wallet._slp_txo[addr][prev_out][prev_n] except KeyError: pass else: if slp_input['qty'] != 'MINT_BATON': print_error( "Non-baton SLP input found in MINT") raise SlpNonMintInput( 'MINT transaction contains non-baton SLP input.' ) if slp_input['token_id'] != tid: print_error("SLP check failed for MINT due to incorrect" \ + " tokenId in baton") raise SlpWrongTokenID('MINT transaction contains baton with incorrect' \ + ' token id.') elif slp_msg.transaction_type == 'GENESIS': # raise an Exception if: # - [ ] NFT Child has quantity that is !== 1 # - [ ] Allow 0x01 or 0x81 qty == 0 # - [ ] NFT Child has minting baton vout specified # - [ ] NFT Child does not grant exception for burning a coin in vin=0 # - [ ] NFT Child does not have a valid Type 0x81 coin in vin=0 for txo in tx.inputs(): addr = txo['address'] prev_out = txo['prevout_hash'] prev_n = txo['prevout_n'] with wallet.lock: try: slp_input = wallet._slp_txo[addr][prev_out][prev_n] except KeyError: pass else: is_burn_allowed = False if coins_to_burn: for c in coins_to_burn: if c['prevout_hash'] == prev_out and c[ 'prevout_n'] == prev_n: is_burn_allowed = True c['is_in_txn'] = True if not is_burn_allowed: print_error("SLP check failed for SLP GENESIS transaction" \ + " which contains SLP inputs.") raise NonSlpTransactionHasSlpInputs( 'Genesis transaction contains unspecified SLP inputs.' ) if slp_msg.transaction_type in ['GENESIS', 'MINT']: # raise an Exception if: # - [X] New baton outpoint is not P2PKH or P2SH type for Genesis or Mint # - [X] Mint receiver has outpoint and is p2pkh or p2sh if slp_msg.op_return_fields['mint_baton_vout']: try: out = tx.outputs()[ slp_msg.op_return_fields['mint_baton_vout']] except IndexError: print_error( "Transaction is missing baton vout for MINT operation" ) raise MissingMintBatonOutpoint('Transaction is missing baton' \ + ' vout for MINT operation') else: if out[1].kind not in [ Address.ADDR_P2PKH, Address.ADDR_P2SH ]: print_error( "Transaction baton receiver vout is not P2PKH or P2SH" ) raise BadSlpOutpointType('Transaction baton receiver vout is not P2PKH' \ + ' or P2SH output type') try: out = tx.outputs()[1] except IndexError: print_error( "Transaction is missing vout for MINT operation token receiver" ) raise MissingTokenReceiverOutpoint('Transaction is missing vout for MINT' \ + ' operation token receiver') else: if out[1].kind not in [ Address.ADDR_P2PKH, Address.ADDR_P2SH ]: print_error( "Transaction token receiver vout is not P2PKH or P2SH" ) raise BadSlpOutpointType('Transaction token receiver vout is not P2PKH' \ + ' or P2SH output type') # return True if this check passes print_error("Final SLP check passed") return True '''