コード例 #1
0
ファイル: auth.py プロジェクト: Coldcard/firmware
    async def failure(self, msg, exc=None, title='Failure'):
        self.failed = msg
        self.done()

        # show line number and/or simple text about error
        if exc:
            print("%s:" % msg)
            sys.print_exception(exc)

            msg += '\n\n'
            em = str(exc)
            if em:
                msg += em
                msg += '\n\n'
            msg += problem_file_line(exc)
        
        from glob import hsm_active, dis

        # do nothing more for HSM case: msg will be available over USB
        if hsm_active:
            dis.progress_bar(1)     # finish the Validating... or whatever was up
            return

        # may be a user-abort waiting, but we want to see error msg; so clear it
        ux_clear_keys(True)

        return await ux_show_story(msg, title)
コード例 #2
0
ファイル: auth.py プロジェクト: laffed/firmware
    async def interact(self):
        # Just show the address... no real confirmation needed.
        from glob import hsm_active, dis

        if not hsm_active:
            msg = self.get_msg()
            msg += '\n\nCompare this payment address to the one shown on your other, less-trusted, software.'
            if version.has_fatram:
                msg += ' Press 4 to view QR Code.'

            while 1:
                ch = await ux_show_story(msg, title=self.title, escape='4')

                if ch == '4' and version.has_fatram:
                    q = ux.QRDisplay([self.address], (self.addr_fmt & AFC_BECH32))
                    await q.interact_bare()
                    continue

                break
        else:
            # finish the Wait...
            dis.progress_bar(1)     

        self.done()
        UserAuthorizedAction.cleanup()      # because no results to store
コード例 #3
0
ファイル: selftest.py プロジェクト: ramsemune/firmware
async def test_sflash():
    dis.clear()
    dis.text(None, 18, 'Serial Flash')
    dis.show()

    from sflash import SF
    from ustruct import pack
    import ngu

    msize = 1024 * 1024
    SF.chip_erase()

    for phase in [0, 1]:
        steps = 7 * 4
        for i in range(steps):
            dis.progress_bar(i / steps)
            dis.show()
            await sleep_ms(250)
            if not SF.is_busy(): break

        assert not SF.is_busy()  # "didn't finish"

        # leave chip blank
        if phase == 1: break

        buf = bytearray(32)
        for addr in range(0, msize, 1024):
            SF.read(addr, buf)
            assert set(buf) == {255}  # "not blank"

            rnd = ngu.hash.sha256s(pack('I', addr))
            SF.write(addr, rnd)
            SF.read(addr, buf)
            assert buf == rnd  #  "write failed"

            dis.progress_bar_show(addr / msize)

        # check no aliasing, also right size part
        for addr in range(0, msize, 1024):
            expect = ngu.hash.sha256s(pack('I', addr))
            SF.read(addr, buf)
            assert buf == expect  # "readback failed"

            dis.progress_bar_show(addr / msize)
コード例 #4
0
ファイル: auth.py プロジェクト: Coldcard/firmware
    async def interact(self):
        # Prompt user w/ details and get approval
        from glob import dis, hsm_active

        # step 1: parse PSBT from sflash into in-memory objects.

        try:
            dis.fullscreen("Reading...")
            with SFFile(TXN_INPUT_OFFSET, length=self.psbt_len) as fd:
                self.psbt = psbtObject.read_psbt(fd)
        except BaseException as exc:
            if isinstance(exc, MemoryError):
                msg = "Transaction is too complex"
                exc = None
            else:
                msg = "PSBT parse failed"

            return await self.failure(msg, exc)

        dis.fullscreen("Validating...")

        # Do some analysis/ validation
        try:
            await self.psbt.validate()      # might do UX: accept multisig import
            self.psbt.consider_inputs()
            self.psbt.consider_keys()
            self.psbt.consider_outputs()
        except FraudulentChangeOutput as exc:
            print('FraudulentChangeOutput: ' + exc.args[0])
            return await self.failure(exc.args[0], title='Change Fraud')
        except FatalPSBTIssue as exc:
            print('FatalPSBTIssue: ' + exc.args[0])
            return await self.failure(exc.args[0])
        except BaseException as exc:
            del self.psbt
            gc.collect()

            if isinstance(exc, MemoryError):
                msg = "Transaction is too complex"
                exc = None
            else:
                msg = "Invalid PSBT"

            return await self.failure(msg, exc)

        # step 2: figure out what we are approving, so we can get sign-off
        # - outputs, amounts
        # - fee 
        #
        # notes: 
        # - try to handle lots of outputs
        # - cannot calc fee as sat/byte, only as percent
        # - somethings are 'warnings':
        #       - fee too big
        #       - inputs we can't sign (no key)
        #
        try:
            msg = uio.StringIO()

            # mention warning at top
            wl= len(self.psbt.warnings)
            if wl == 1:
                msg.write('(1 warning below)\n\n')
            elif wl >= 2:
                msg.write('(%d warnings below)\n\n' % wl)

            self.output_summary_text(msg)
            gc.collect()

            fee = self.psbt.calculate_fee()
            if fee is not None:
                msg.write("\nNetwork fee:\n%s %s\n" % self.chain.render_value(fee))

            # NEW: show where all the change outputs are going
            self.output_change_text(msg)
            gc.collect()

            if self.psbt.warnings:
                msg.write('\n---WARNING---\n\n')

                for label, m in self.psbt.warnings:
                    msg.write('- %s: %s\n\n' % (label, m))

            if self.do_visualize:
                # stop here and just return the text of approval message itself
                self.result = await self.save_visualization(msg, (self.stxn_flags & STXN_SIGNED))
                del self.psbt
                self.done()

                return

            if not hsm_active:
                msg.write("\nPress OK to approve and sign transaction. X to abort.")
                ch = await ux_show_story(msg, title="OK TO SEND?")
            else:
                ch = await hsm_active.approve_transaction(self.psbt, self.psbt_sha, msg.getvalue())
                dis.progress_bar(1)     # finish the Validating...

        except MemoryError:
            # recovery? maybe.
            try:
                del self.psbt
                del msg
            except: pass        # might be NameError since we don't know how far we got
            gc.collect()

            msg = "Transaction is too complex"
            return await self.failure(msg)

        if ch != 'y':
            # they don't want to!
            self.refused = True

            await ux_dramatic_pause("Refused.", 1)

            del self.psbt

            self.done()
            return

        # do the actual signing.
        try:
            dis.fullscreen('Wait...')
            gc.collect()           # visible delay causes by this but also sign_it() below
            self.psbt.sign_it()
        except FraudulentChangeOutput as exc:
            return await self.failure(exc.args[0], title='Change Fraud')
        except MemoryError:
            msg = "Transaction is too complex"
            return await self.failure(msg)
        except BaseException as exc:
            return await self.failure("Signing failed late", exc)

        if self.approved_cb:
            # for micro sd case
            await self.approved_cb(self.psbt)
            self.done()
            return

        txid = None
        try:
            # re-serialize the PSBT back out
            with SFFile(TXN_OUTPUT_OFFSET, max_size=MAX_TXN_LEN, message="Saving...") as fd:
                await fd.erase()

                if self.do_finalize:
                    txid = self.psbt.finalize(fd)
                else:
                    self.psbt.serialize(fd)

                self.result = (fd.tell(), fd.checksum.digest())

            self.done(redraw=(not txid))

        except BaseException as exc:
            return await self.failure("PSBT output failed", exc)

        if self.do_finalize and txid and not hsm_active:
            # Show txid when we can; advisory
            # - maybe even as QR, hex-encoded in alnum mode
            tmsg = txid

            if version.has_fatram:
                tmsg += '\n\nPress 1 for QR Code of TXID.'

            ch = await ux_show_story(tmsg, "Final TXID", escape='1')

            if version.has_fatram and ch=='1':
                await show_qr_code(txid, True)