From 9deaebb7005000c698e55eafc36f2b58f1218773 Mon Sep 17 00:00:00 2001 From: Stepan Snigirev Date: Wed, 16 Nov 2022 01:47:57 +0100 Subject: [PATCH] psbt: check if all inputs are already signed --- src/apps/wallets/liquid/manager.py | 3 +++ src/apps/wallets/manager.py | 32 ++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/src/apps/wallets/liquid/manager.py b/src/apps/wallets/liquid/manager.py index 34e3ef2..2106f0b 100644 --- a/src/apps/wallets/liquid/manager.py +++ b/src/apps/wallets/liquid/manager.py @@ -249,6 +249,8 @@ def preprocess_psbt(self, stream, fout): # compress = True flag will make sure large fields won't be loaded to RAM psbtv = self.PSBTViewClass.view(stream, compress=True) + signed_inputs = self.check_signed_inputs(psbtv) + # Start with global fields of PSBT # On Liquid we check if txseed is provided (for deterministic blinding) @@ -273,6 +275,7 @@ def preprocess_psbt(self, stream, fout): "inputs": [{} for i in range(psbtv.num_inputs)], "outputs": [{} for i in range(psbtv.num_outputs)], "issuance": False, "reissuance": False, + "signed_inputs": signed_inputs, } fingerprint = self.keystore.fingerprint diff --git a/src/apps/wallets/manager.py b/src/apps/wallets/manager.py index 62babdf..582a8d2 100644 --- a/src/apps/wallets/manager.py +++ b/src/apps/wallets/manager.py @@ -331,6 +331,19 @@ async def confirm_transaction(self, wallets, meta, show_screen): if sighash == False: return + if meta.get("signed_inputs", 0) == len(meta.get("inputs", [])): + scr = Prompt( + "Warning!", + "\nThe transaction is already signed!\n\n\n" + "All inputs in this transaction\n" + "contain final witness or scriptsig.\n\n\n" + "There is no need to add any extra signatures.\n\n\n" + "Proceed anyway?", + ) + proceed = await show_screen(scr) + if not proceed: + return + # ask if we want to continue with unknown wallets if not await self.confirm_wallets(wallets, show_screen): return @@ -579,6 +592,21 @@ def fill_zero_fingerprint(self, scope): if self.keystore.get_xpub(scope.bip32_derivations[pub].derivation).key == pub: scope.bip32_derivations[pub].fingerprint = self.keystore.fingerprint + def check_signed_inputs(self, psbtv): + """Goes through all input scopes and checks if they are already signed""" + signed_inputs = 0 + for i in range(psbtv.num_inputs): + psbtv.seek_to_scope(i) + off = psbtv.seek_to_value(b"\x07", from_current=True) # final scriptsig + if off is not None: + signed_inputs += 1 + continue + psbtv.seek_to_scope(i) + off = psbtv.seek_to_value(b"\x08", from_current=True) # final scriptwitness + if off is not None: + signed_inputs += 1 + continue + return signed_inputs def preprocess_psbt(self, stream, fout): """ @@ -592,6 +620,9 @@ def preprocess_psbt(self, stream, fout): # compress = True flag will make sure large fields won't be loaded to RAM psbtv = self.PSBTViewClass.view(stream, compress=True) + # check if inputs are already signed + signed_inputs = self.check_signed_inputs(psbtv) + # Write global scope first psbtv.stream.seek(psbtv.offset) res = read_write(psbtv.stream, fout, psbtv.first_scope-psbtv.offset) @@ -606,6 +637,7 @@ def preprocess_psbt(self, stream, fout): "inputs": [{} for i in range(psbtv.num_inputs)], "outputs": [{} for i in range(psbtv.num_outputs)], "default_asset": "BTC" if self.network == "main" else "tBTC", + "signed_inputs": signed_inputs, } fingerprint = self.keystore.fingerprint