Example #1
0
 def get_xpub(self, bip32_path):
     self.checkDevice()
     # bip32_path is of the form 44'/5'/1'
     # S-L-O-W - we don't handle the fingerprint directly, so compute
     # it manually from the previous node
     # This only happens once so it's bearable
     #self.get_client() # prompt for the PIN before displaying the dialog if necessary
     #self.handler.show_message("Computing master public key")
     try:
         splitPath = bip32_path.split('/')
         if splitPath[0] == 'm':
             splitPath = splitPath[1:]
             bip32_path = bip32_path[2:]
         fingerprint = 0
         if len(splitPath) > 1:
             prevPath = "/".join(splitPath[0:len(splitPath) - 1])
             nodeData = self.dongleObject.getWalletPublicKey(prevPath)
             publicKey = compress_public_key(nodeData['publicKey'])
             h = hashlib.new('ripemd160')
             h.update(hashlib.sha256(publicKey).digest())
             fingerprint = unpack(">I", h.digest()[0:4])[0]
         nodeData = self.dongleObject.getWalletPublicKey(bip32_path)
         publicKey = compress_public_key(nodeData['publicKey'])
         depth = len(splitPath)
         lastChild = splitPath[len(splitPath) - 1].split('\'')
         if len(lastChild) == 1:
             childnum = int(lastChild[0])
         else:
             childnum = 0x80000000 | int(lastChild[0])
         xpub = bitcoin.serialize_xpub(0, str(nodeData['chainCode']), str(publicKey), depth, self.i4b(fingerprint), self.i4b(childnum))
         return xpub
     except Exception as e:
         print_error(e)
         return None
def parse_proposals_subscription_result(results):
    """Parse the proposals subscription response."""
    proposals = []
    for k, result in results.items():
        kwargs = {
            'proposal_name': result['Name'],
            'proposal_url': result['URL'],
            'start_block': int(result['BlockStart']),
            'end_block': int(result['BlockEnd']),
            'payment_amount': result['MonthlyPayment'],
            'address': result['PaymentAddress']
        }

        fee_txid_key = 'FeeTXHash' if result.get('FeeTXHash') else 'FeeHash'
        kwargs['fee_txid'] = result[fee_txid_key]
        yes_count_key = 'YesCount' if result.get('YesCount') else 'Yeas'
        kwargs['yes_count'] = result[yes_count_key]
        no_count_key = 'NoCount' if result.get('NoCount') else 'Nays'
        kwargs['no_count'] = result[no_count_key]

        payment_amount = Decimal(str(kwargs['payment_amount']))
        kwargs['payment_amount'] = pow(10, 8) * payment_amount
        proposals.append(BudgetProposal.from_dict(kwargs))

    print_error('Received updated budget proposal information (%d proposals)' %
                len(proposals))
    return proposals
Example #3
0
 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)
Example #4
0
 def submit_thread():
     for i, (proposal_name,
             txid) in enumerate(self.unsubmitted_proposals):
         errmsg, success = self.parent.masternode_manager.submit_proposal(
             proposal_name, save=False)
         results[i] = (proposal_name, errmsg, success)
         if success:
             print_error('Sucessfully submitted proposal "%s"' %
                         proposal_name)
         else:
             print_error('Failed to submit proposal "%s": %s' %
                         (proposal_name, errmsg))
     return results
 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 = json.loads(reply)
         if 'error' in reply:
             self.password = None
     except Exception as e:
         print_error('Exception caught ' + str(e))
     return reply
    def create_proposal_tx(self, proposal_name, password, save=True):
        """Create a fee transaction for proposal_name."""
        proposal = self.get_proposal(proposal_name)
        if proposal.fee_txid:
            print_error('Warning: Proposal "%s" already has a fee tx: %s' %
                        (proposal_name, proposal.fee_txid))
        if proposal.submitted:
            raise Exception('Proposal has already been submitted')

        h = bitcoin.hash_decode(proposal.get_hash()).encode('hex')
        script = '6a20' + h  # OP_RETURN hash
        outputs = [(bitcoin.TYPE_SCRIPT, script.decode('hex'), BUDGET_FEE_TX)]
        tx = self.wallet.mktx(outputs, password, self.config)
        proposal.fee_txid = tx.hash()
        if save:
            self.save()
        return tx
    def masternode_subscription_response(self, response):
        """Callback for when a masternode's status changes."""
        collateral = response['params'][0]
        mn = None
        for masternode in self.masternodes:
            if masternode.get_collateral_str() == collateral:
                mn = masternode
                break

        if not mn:
            return

        status = response['result']
        if status is None:
            status = False
        print_error('Received updated status for masternode %s: "%s"' %
                    (mn.alias, status))
        self.masternode_statuses[collateral] = status
 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' + bytearray(msg) + '\0' *
                                (hidBufSize - len(msg)))
             r = []
             while len(r) < hidBufSize:
                 r = r + self.dbb_hid.read(hidBufSize)
         else:
             self.hid_send_frame(msg)
             r = self.hid_read_frame()
         r = str(bytearray(r)).rstrip(' \t\r\n\0')
         r = r.replace("\0", '')
         reply = json.loads(r)
     except Exception as e:
         print_error('Exception caught ' + str(e))
     return reply
    def import_masternode_conf_lines(self, conf_lines, password):
        """Import a list of MasternodeConfLine."""
        def already_have(line):
            for masternode in self.masternodes:
                # Don't let aliases collide.
                if masternode.alias == line.alias:
                    return True
                # Don't let outputs collide.
                if masternode.vin.get(
                        'prevout_hash') == line.txid and masternode.vin.get(
                            'prevout_n') == line.output_index:
                    return True
            return False

        num_imported = 0
        for conf_line in conf_lines:
            if already_have(conf_line):
                continue
            # Import delegate WIF key for signing last_ping.
            self.import_masternode_delegate(conf_line.wif)
            public_key = bitcoin.public_key_from_private_key(conf_line.wif)

            addr = conf_line.addr.split(':')
            addr = NetworkAddress(ip=addr[0], port=int(addr[1]))
            vin = {
                'prevout_hash': conf_line.txid,
                'prevout_n': conf_line.output_index
            }
            mn = MasternodeAnnounce(alias=conf_line.alias,
                                    vin=vin,
                                    delegate_key=public_key,
                                    addr=addr)
            self.add_masternode(mn)
            try:
                self.populate_masternode_output(mn.alias)
            except Exception as e:
                print_error(str(e))
            num_imported += 1

        return num_imported
    def sign_transaction(self, tx, password):
        if tx.is_complete():
            return

        try:
            p2shTransaction = False
            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'] in ['p2sh']:
                    p2shTransaction = True

                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(
                            tx.serialize_preimage(i).decode('hex'))
                        hasharray_i = {
                            'hash': inputHash.encode('hex'),
                            'keypath': inputPath
                        }
                        hasharray.append(hasharray_i)
                        inputhasharray.append(inputHash)
                        break
                else:
                    self.give_error("No matching x_key for sign_transaction"
                                    )  # should never happen

            # Sanity check
            if p2shTransaction:
                for txinput in tx.inputs():
                    if txinput['type'] != 'p2sh':
                        self.give_error(
                            "P2SH / regular input mixed in same transaction not supported"
                        )  # should never happen

            # Build pubkeyarray from outputs (unused because echo for smart verification not implemented)
            if not p2shTransaction:
                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)

            # 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": {"meta":"%s", "data":%s, "checkpub":%s} }' % \
                       (Hash(tx.serialize()).encode('hex'), json.dumps(hashes), json.dumps(pubkeyarray))

                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 steps > 1:
                    self.handler.show_message(_("Signing large transaction. Please be patient ...\r\n\r\n" \
                                                "To continue, touch the Digital Bitbox's blinking light for 3 seconds. " \
                                                "(Touch " + str(step + 1) + " of " + str(int(steps)) + ")\r\n\r\n" \
                                                "To cancel, briefly touch the blinking light or wait for the timeout.\r\n\r\n"))
                else:
                    self.handler.show_message(_("Signing transaction ...\r\n\r\n" \
                                                "To continue, touch the Digital Bitbox's blinking light for 3 seconds.\r\n\r\n" \
                                                "To cancel, briefly touch the blinking light or wait for the timeout."))

                reply = dbb_client.hid_send_encrypt(
                    msg
                )  # Send twice, first returns an echo for smart verification (not implemented)
                self.handler.clear_dialog()

                if 'error' in reply:
                    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 = 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 = signed['sig'].decode('hex')
                        h = inputhasharray[i]
                        pk = MyVerifyingKey.from_signature(s,
                                                           recid,
                                                           h,
                                                           curve=SECP256k1)
                        pk = point_to_ser(pk.pubkey.point, True).encode('hex')
                    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] = sig.encode('hex') + '01'
                    tx._inputs[i] = txin

        except BaseException as e:
            self.give_error(e, True)
        else:
            print_error("Transaction is_complete", tx.is_complete())
            tx.raw = tx.serialize()
Example #11
0
import sys
import platform

from electrum_zaap.plugins import BasePlugin, hook
from electrum_zaap_gui.qt.util import WaitingDialog, EnterButton, WindowModalDialog
from electrum_zaap.util import print_msg, print_error
from electrum_zaap.i18n import _

from PyQt4.QtGui import *
from PyQt4.QtCore import *

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'
Example #12
0
 def sign_done(proposal, tx):
     print_error('proposal tx sign done: %s' % proposal.proposal_name)
     if tx:
         label = _('Budget Proposal Tx: ') + proposal.proposal_name
         self.parent.broadcast_transaction(tx, label)
         self.parent.masternode_manager.save()