async def sign_psbt_buf_OLD(psbt_buf): # sign a PSBT string from common import dis from sram4 import tmp_buf from utils import HexStreamer, Base64Streamer, HexWriter, Base64Writer UserAuthorizedAction.cleanup() # Determine encoding used psbt_len = len(psbt_buf) taste = psbt_buf[0:10] print('sign_psbt_buf: 1') if taste[0:5] == b'psbt\xff': print('sign_psbt_buf: 2') print("sign 1") decoder = None def output_encoder(x): return x elif taste[0:10] == b'70736274ff': print("sign 2") decoder = HexStreamer() output_encoder = HexWriter psbt_len //= 2 elif taste[0:6] == b'cHNidP': print("sign 3") decoder = Base64Streamer() output_encoder = Base64Writer psbt_len = (psbt_len * 3 // 4) + 10 print('sign_psbt_buf: 3') async def done(psbt): if psbt.is_complete(): psbt.finalize(fd) else: psbt.serialize(fd) ch = await ux_show_signed_transaction() await ux_show_story(msg, title='PSBT Signed') UserAuthorizedAction.cleanup() print('sign_psbt_buf: 4') UserAuthorizedAction.active_request = ApproveTransaction( psbt_len, approved_cb=done, psbt_buf=psbt_buf) print('sign_psbt_buf: 5') # Kill any menu stack, and put our thing at the top abort_and_goto(UserAuthorizedAction.active_request) print('sign_psbt_buf: 6')
def sign_psbt_file(filename): # sign a PSBT file found on a MicroSD card from files import CardSlot, CardMissingError, securely_blank_file from main import dis from sram2 import tmp_buf from utils import HexStreamer, Base64Streamer, HexWriter, Base64Writer UserAuthorizedAction.cleanup() #print("sign: %s" % filename) # copy file into our spiflash # - can't work in-place on the card because we want to support writing out to different card # - accepts hex or base64 encoding, but binary prefered with CardSlot() as card: with open(filename, 'rb') as fd: dis.fullscreen('Reading...') # see how long it is psbt_len = fd.seek(0, 2) fd.seek(0) # determine encoding used, altho we prefer binary taste = fd.read(10) fd.seek(0) if taste[0:5] == b'psbt\xff': decoder = None output_encoder = lambda x: x elif taste[0:10] == b'70736274ff': decoder = HexStreamer() output_encoder = HexWriter psbt_len //= 2 elif taste[0:6] == b'cHNidP': decoder = Base64Streamer() output_encoder = Base64Writer psbt_len = (psbt_len * 3 // 4) + 10 total = 0 with SFFile(TXN_INPUT_OFFSET, max_size=psbt_len) as out: # blank flash await out.erase() while 1: n = fd.readinto(tmp_buf) if not n: break if n == len(tmp_buf): abuf = tmp_buf else: abuf = memoryview(tmp_buf)[0:n] if not decoder: out.write(abuf) total += n else: for here in decoder.more(abuf): out.write(here) total += len(here) dis.progress_bar_show(total / psbt_len) # might have been whitespace inflating initial estimate of PSBT size assert total <= psbt_len psbt_len = total async def done(psbt): orig_path, basename = filename.rsplit('/', 1) orig_path += '/' base = basename.rsplit('.', 1)[0] out2_fn = None out_fn = None txid = None from main import settings import os del_after = settings.get('del', 0) while 1: # try to put back into same spot, but also do top-of-card is_comp = psbt.is_complete() if not is_comp: # keep the filename under control during multiple passes target_fname = base.replace('-part', '')+'-part.psbt' else: # add -signed to end. We won't offer to sign again. target_fname = base+'-signed.psbt' for path in [orig_path, None]: try: with CardSlot() as card: out_full, out_fn = card.pick_filename(target_fname, path) out_path = path if out_full: break except CardMissingError: prob = 'Missing card.\n\n' out_fn = None if not out_fn: # need them to insert a card prob = '' else: # attempt write-out try: with CardSlot() as card: if is_comp and del_after: # don't write signed PSBT if we'd just delete it anyway out_fn = None else: with output_encoder(open(out_full, 'wb')) as fd: # save as updated PSBT psbt.serialize(fd) if is_comp: # write out as hex too, if it's final out2_full, out2_fn = card.pick_filename( base+'-final.txn' if not del_after else 'tmp.txn', out_path) if out2_full: with HexWriter(open(out2_full, 'w+t')) as fd: # save transaction, in hex txid = psbt.finalize(fd) if del_after: # rename it now that we know the txid after_full, out2_fn = card.pick_filename( txid+'.txn', out_path, overwrite=True) os.rename(out2_full, after_full) if del_after: # this can do nothing if they swapped SDCard between steps, which is ok, # but if the original file is still there, this blows it away. # - if not yet final, the foo-part.psbt file stays try: securely_blank_file(filename) except: pass # success and done! break except OSError as exc: prob = 'Failed to write!\n\n%s\n\n' % exc sys.print_exception(exc) # fall thru to try again # prompt them to input another card? ch = await ux_show_story(prob+"Please insert an SDCard to receive signed transaction, " "and press OK.", title="Need Card") if ch == 'x': await ux_aborted() return # done. if out_fn: msg = "Updated PSBT is:\n\n%s" % out_fn if out2_fn: msg += '\n\n' else: # del_after is probably set msg = '' if out2_fn: msg += 'Finalized transaction (ready for broadcast):\n\n%s' % out2_fn if txid and not del_after: msg += '\n\nFinal TXID:\n'+txid await ux_show_story(msg, title='PSBT Signed') UserAuthorizedAction.cleanup() UserAuthorizedAction.active_request = ApproveTransaction(psbt_len, approved_cb=done) # kill any menu stack, and put our thing at the top abort_and_goto(UserAuthorizedAction.active_request)
def sign_psbt_buf(psbt_buf): # sign a PSBT file found on a microSD card from uio import BytesIO from common import dis from sram4 import tmp_buf from utils import HexStreamer, Base64Streamer, HexWriter, Base64Writer UserAuthorizedAction.cleanup() # copy buffer into SPI Flash # - accepts hex or base64 encoding, but binary prefered with BytesIO(psbt_buf) as fd: dis.fullscreen('Reading...') # see how long it is psbt_len = fd.seek(0, 2) fd.seek(0) # determine encoding used, altho we prefer binary taste = fd.read(10) fd.seek(0) if taste[0:5] == b'psbt\xff': print('tastes like text PSBT') decoder = None def output_encoder(x): return x elif taste[0:10] == b'70736274ff': print('tastes like binary PSBT') decoder = HexStreamer() output_encoder = HexWriter psbt_len //= 2 elif taste[0:6] == b'cHNidP': print('tastes like Base64 PSBT') decoder = Base64Streamer() output_encoder = Base64Writer psbt_len = (psbt_len * 3 // 4) + 10 else: return total = 0 with SFFile(TXN_INPUT_OFFSET, max_size=psbt_len) as out: print('sign 1') # blank flash await out.erase() print('sign 2') while 1: n = fd.readinto(tmp_buf) print('sign copy to SPI flash 1: n={}'.format(n)) if not n: break if n == len(tmp_buf): abuf = tmp_buf else: abuf = memoryview(tmp_buf)[0:n] if not decoder: out.write(abuf) total += n else: for here in decoder.more(abuf): out.write(here) total += len(here) print('sign copy to SPI flash 2: {}/{} = {}'.format(total, psbt_len, total/psbt_len)) dis.progress_bar_show(total / psbt_len) print('sign 3') # might have been whitespace inflating initial estimate of PSBT size assert total <= psbt_len psbt_len = total print('sign 4') # Create a new BytesIO() to hold the result async def done(psbt): print('sign 5: done') signed_bytes = None with BytesIO() as bfd: with output_encoder(bfd) as fd: print('sign 6: done') if psbt.is_complete(): print('sign 7: done') psbt.finalize(fd) print('sign 8: done') else: print('sign 9: done') psbt.serialize(fd) print('sign 10: done') bfd.seek(0) signed_bytes = bfd.read() print('signed_bytes={}'.format(signed_bytes)) print('sign 11: done') gc.collect() from ur1.encode_ur import encode_ur from ubinascii import hexlify signed_str = hexlify(signed_bytes) print('signed_str={}'.format(signed_str)) from ux import DisplayURCode o = DisplayURCode('Signed Txn', 'Scan to Wallet', signed_str) await o.interact_bare() UserAuthorizedAction.cleanup() print('sign 12: done') UserAuthorizedAction.active_request = ApproveTransaction(psbt_len, approved_cb=done) print('sign 13: done') # kill any menu stack, and put our thing at the top abort_and_goto(UserAuthorizedAction.active_request) print('sign 14: done')