Esempio n. 1
0
 async def process_host_command(self, stream, show_screen):
     platform.delete_recursively(self.tempdir)
     cmd, stream = self.parse_stream(stream)
     if cmd == SIGN_PSBT:
         encoding = BASE64_STREAM
         if stream.read(5) == b"psbt\xff":
             encoding = RAW_STREAM
         stream.seek(-5, 1)
         res = await self.sign_psbt(stream, show_screen, encoding)
         if res is not None:
             obj = {
                 "title": "Transaction is signed!",
                 "message": "Scan it with your wallet",
             }
             return res, obj
         return
     if cmd == SIGN_BCUR:
         # move to the end of UR:BYTES/
         stream.seek(9, 1)
         # move to the end of hash if it's there
         d = stream.read(70)
         if b"/" in d:
             pos = d.index(b"/")
             stream.seek(pos - len(d) + 1, 1)
         else:
             stream.seek(-len(d), 1)
         with open(self.tempdir + "/raw", "wb") as f:
             bcur_decode_stream(stream, f)
         gc.collect()
         with open(self.tempdir + "/raw", "rb") as f:
             res = await self.sign_psbt(f, show_screen, encoding=RAW_STREAM)
         platform.delete_recursively(self.tempdir)
         if res is not None:
             data, hsh = bcur_encode(res.read(), upper=True)
             bcur_res = (b"UR:BYTES/" + hsh + "/" + data)
             obj = {
                 "title": "Transaction is signed!",
                 "message": "Scan it with your wallet",
             }
             gc.collect()
             return BytesIO(bcur_res), obj
         return
     elif cmd == ADD_WALLET:
         # read content, it's small
         desc = stream.read().decode().strip()
         w = self.parse_wallet(desc)
         res = await self.confirm_new_wallet(w, show_screen)
         if res:
             self.add_wallet(w)
         return
     elif cmd == VERIFY_ADDRESS:
         data = stream.read().decode().replace("bitcoin:", "")
         # should be of the form addr?index=N or similar
         if "index=" not in data or "?" not in data:
             raise WalletError("Can't verify address with unknown index")
         addr, rest = data.split("?")
         args = rest.split("&")
         idx = None
         for arg in args:
             if arg.startswith("index="):
                 idx = int(arg[6:])
                 break
         w, _ = self.find_wallet_from_address(addr, index=idx)
         await show_screen(WalletScreen(w, self.network, idx))
         return
     elif cmd == DERIVE_ADDRESS:
         arr = stream.read().split(b" ")
         redeem_script = None
         if len(arr) == 2:
             script_type, path = arr
         elif len(arr) == 3:
             script_type, path, redeem_script = arr
         else:
             raise WalletError("Too many arguments")
         paths = [p.decode() for p in path.split(b",")]
         if len(paths) == 0:
             raise WalletError("Invalid path argument")
         res = await self.showaddr(paths,
                                   script_type,
                                   redeem_script,
                                   show_screen=show_screen)
         return BytesIO(res), {}
     else:
         raise WalletError("Unknown command")
Esempio n. 2
0
 async def process_host_command(self, stream, show_screen):
     platform.delete_recursively(self.tempdir)
     cmd, stream = self.parse_stream(stream)
     if cmd == SIGN_PSBT:
         magic = stream.read(len(self.PSBTViewClass.MAGIC))
         if magic == self.PSBTViewClass.MAGIC:
             encoding = RAW_STREAM
         elif magic.startswith(self.B64PSBT_PREFIX):
             encoding = BASE64_STREAM
         else:
             raise WalletError("Invalid PSBT magic!")
         stream.seek(-len(magic), 1)
         res = await self.sign_psbt(stream, show_screen, encoding)
         if res is not None:
             obj = {
                 "title": "Transaction is signed!",
                 "message": "Scan it with your wallet",
             }
             return res, obj
         return
     if cmd == SIGN_BCUR:
         # move to the end of UR:BYTES/
         stream.seek(9, 1)
         # move to the end of hash if it's there
         d = stream.read(70)
         if b"/" in d:
             pos = d.index(b"/")
             stream.seek(pos-len(d)+1, 1)
         else:
             stream.seek(-len(d), 1)
         with open(self.tempdir+"/raw", "wb") as f:
             bcur_decode_stream(stream, f)
         gc.collect()
         with open(self.tempdir+"/raw", "rb") as f:
             res = await self.sign_psbt(f, show_screen, encoding=RAW_STREAM)
         if res is not None:
             # bcur-encode to temp data file
             with open(self.tempdir+"/bcur_data", "wb") as fout:
                 if isinstance(res, str):
                     with open(res, "rb") as fin:
                         l, hsh = bcur_encode_stream(fin, fout, upper=True)
                 else:
                     l, hsh = bcur_encode_stream(res, fout, upper=True)
             # add prefix and hash
             with open(self.tempdir+"/bcur_full", "wb") as fout:
                 fout.write(b"UR:BYTES/")
                 fout.write(hsh)
                 fout.write(b"/")
                 with open(self.tempdir+"/bcur_data", "rb") as fin:
                     b = bytearray(100)
                     while True:
                         l = fin.readinto(b)
                         if l == 0:
                             break
                         fout.write(b, l)
             obj = {
                 "title": "Transaction is signed!",
                 "message": "Scan it with your wallet",
             }
             gc.collect()
             return self.tempdir+"/bcur_full", obj
         return
     elif cmd == LIST_WALLETS:
         wnames = json.dumps([w.name for w in self.wallets])
         return BytesIO(wnames.encode()), {}
     elif cmd == ADD_WALLET:
         # read content, it's small
         desc = stream.read().decode().strip()
         w = self.parse_wallet(desc)
         res = await self.confirm_new_wallet(w, show_screen)
         if res:
             self.add_wallet(w)
         return
     elif cmd == VERIFY_ADDRESS:
         data = stream.read().decode().replace("bitcoin:", "")
         # should be of the form addr?index=N or similar
         if "index=" not in data or "?" not in data:
             raise WalletError("Can't verify address with unknown index")
         addr, rest = data.split("?")
         args = rest.split("&")
         idx = None
         for arg in args:
             if arg.startswith("index="):
                 idx = int(arg[6:])
                 break
         w, _ = self.find_wallet_from_address(addr, index=idx)
         await show_screen(WalletScreen(w, self.network, idx))
         return
     elif cmd == DERIVE_ADDRESS:
         arr = stream.read().split(b" ")
         redeem_script = None
         if len(arr) == 2:
             script_type, path = arr
         elif len(arr) == 3:
             script_type, path, redeem_script = arr
         else:
             raise WalletError("Too many arguments")
         paths = [p.decode() for p in path.split(b",")]
         if len(paths) == 0:
             raise WalletError("Invalid path argument")
         res = await self.showaddr(
             paths, script_type, redeem_script, show_screen=show_screen
         )
         return BytesIO(res), {}
     else:
         raise WalletError("Unknown command")