URI: 
       taccept base43-encoded tx in Qt "Load transaction" - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit eb04551f9ad11d367310592ab260895eb48bcb90
   DIR parent 8f5ca40d10e921f87f1faf6162d81a62d114f1d7
  HTML Author: SomberNight <somber.night@protonmail.com>
       Date:   Tue,  5 Mar 2019 17:27:53 +0100
       
       accept base43-encoded tx in Qt "Load transaction"
       
       When encoding transactions as QR codes, we encode the tx bytes as base43
       first. This makes it easier to load a transaction if the user manually
       decodes the QR code.
       
       Diffstat:
         M electrum/tests/test_transaction.py  |      19 ++++++++++++++++++-
         M electrum/transaction.py             |      23 +++++++++++++++--------
       
       2 files changed, 33 insertions(+), 9 deletions(-)
       ---
   DIR diff --git a/electrum/tests/test_transaction.py b/electrum/tests/test_transaction.py
       t@@ -1,5 +1,5 @@
        from electrum import transaction
       -from electrum.transaction import TxOutputForUI
       +from electrum.transaction import TxOutputForUI, tx_from_str
        from electrum.bitcoin import TYPE_ADDRESS
        from electrum.keystore import xpubkey_to_address
        from electrum.util import bh2u, bfh
       t@@ -171,6 +171,23 @@ class TestTransaction(SequentialTestCase):
                tx = transaction.Transaction(v2_blob)
                self.assertEqual(tx.txid(), "b97f9180173ab141b61b9f944d841e60feec691d6daab4d4d932b24dd36606fe")
        
       +    def test_tx_from_str(self):
       +        # json dict
       +        self.assertEqual('020000000001012005273af813ba23b0c205e4b145e525c280dd876e061f35bff7db9b2e0043640100000000fdffffff02d885010000000000160014e73f444b8767c84afb46ef4125d8b81d2542a53d00e1f5050000000017a914052ed032f5c74a636ed5059611bb90012d40316c870247304402200c628917673d75f05db893cc377b0a69127f75e10949b35da52aa1b77a14c350022055187adf9a668fdf45fc09002726ba7160e713ed79dddcd20171308273f1a2f1012103cb3e00561c3439ccbacc033a72e0513bcfabff8826de0bc651d661991ade6171049e1600',
       +                         tx_from_str("""{
       +                                        "complete": true,
       +                                        "final": false,
       +                                        "hex": "020000000001012005273af813ba23b0c205e4b145e525c280dd876e061f35bff7db9b2e0043640100000000fdffffff02d885010000000000160014e73f444b8767c84afb46ef4125d8b81d2542a53d00e1f5050000000017a914052ed032f5c74a636ed5059611bb90012d40316c870247304402200c628917673d75f05db893cc377b0a69127f75e10949b35da52aa1b77a14c350022055187adf9a668fdf45fc09002726ba7160e713ed79dddcd20171308273f1a2f1012103cb3e00561c3439ccbacc033a72e0513bcfabff8826de0bc651d661991ade6171049e1600"
       +                                    }
       +                                    """)
       +        )
       +        # raw hex
       +        self.assertEqual('020000000001012005273af813ba23b0c205e4b145e525c280dd876e061f35bff7db9b2e0043640100000000fdffffff02d885010000000000160014e73f444b8767c84afb46ef4125d8b81d2542a53d00e1f5050000000017a914052ed032f5c74a636ed5059611bb90012d40316c870247304402200c628917673d75f05db893cc377b0a69127f75e10949b35da52aa1b77a14c350022055187adf9a668fdf45fc09002726ba7160e713ed79dddcd20171308273f1a2f1012103cb3e00561c3439ccbacc033a72e0513bcfabff8826de0bc651d661991ade6171049e1600',
       +                         tx_from_str('020000000001012005273af813ba23b0c205e4b145e525c280dd876e061f35bff7db9b2e0043640100000000fdffffff02d885010000000000160014e73f444b8767c84afb46ef4125d8b81d2542a53d00e1f5050000000017a914052ed032f5c74a636ed5059611bb90012d40316c870247304402200c628917673d75f05db893cc377b0a69127f75e10949b35da52aa1b77a14c350022055187adf9a668fdf45fc09002726ba7160e713ed79dddcd20171308273f1a2f1012103cb3e00561c3439ccbacc033a72e0513bcfabff8826de0bc651d661991ade6171049e1600'))
       +        # base43
       +        self.assertEqual('020000000001012005273af813ba23b0c205e4b145e525c280dd876e061f35bff7db9b2e0043640100000000fdffffff02d885010000000000160014e73f444b8767c84afb46ef4125d8b81d2542a53d00e1f5050000000017a914052ed032f5c74a636ed5059611bb90012d40316c870247304402200c628917673d75f05db893cc377b0a69127f75e10949b35da52aa1b77a14c350022055187adf9a668fdf45fc09002726ba7160e713ed79dddcd20171308273f1a2f1012103cb3e00561c3439ccbacc033a72e0513bcfabff8826de0bc651d661991ade6171049e1600',
       +                         tx_from_str('64XF-8+PM6*4IYN-QWW$B2QLNW+:C8-$I$-+T:L.6DKXTSWSFFONDP1J/MOS3SPK0-SYVW38U9.3+A1/*2HTHQTJGP79LVEK-IITQJ1H.C/X$NSOV$8DWR6JAFWXD*LX4-EN0.BDOF+PPYPH16$NM1H.-MAA$V1SCP0Q.6Y5FR822S6K-.5K5F.Z4Q:0SDRG-4GEBLAO4W9Z*H-$1-KDYAFOGF675W0:CK5M1LT92IG:3X60P3GKPM:X2$SP5A7*LT9$-TTEG0/DRZYV$7B4ADL9CVS5O7YG.J64HLZ24MVKO/-GV:V.T/L$D3VQ:MR8--44HK8W'))
       +
            def test_get_address_from_output_script(self):
                # the inverse of this test is in test_bitcoin: test_address_to_script
                addr_from_script = lambda script: transaction.get_address_from_output_script(bfh(script))
   DIR diff --git a/electrum/transaction.py b/electrum/transaction.py
       t@@ -39,7 +39,7 @@ from .bitcoin import (TYPE_ADDRESS, TYPE_PUBKEY, TYPE_SCRIPT, hash_160,
                              hash160_to_p2sh, hash160_to_p2pkh, hash_to_segwit_addr,
                              hash_encode, var_int, TOTAL_COIN_SUPPLY_LIMIT_IN_BTC, COIN,
                              push_script, int_to_hex, push_script, b58_address_to_hash160,
       -                      opcodes, add_number_to_script)
       +                      opcodes, add_number_to_script, base_decode)
        from .crypto import sha256d
        from .keystore import xpubkey_to_address, xpubkey_to_pubkey
        
       t@@ -1185,19 +1185,26 @@ class Transaction:
                return out
        
        
       -def tx_from_str(txt):
       -    "json or raw hexadecimal"
       -    import json
       +def tx_from_str(txt: str) -> str:
       +    """Sanitizes tx-describing input (json or raw hex or base43) into
       +    raw hex transaction."""
       +    assert isinstance(txt, str), f"txt must be str, not {type(txt)}"
            txt = txt.strip()
            if not txt:
                raise ValueError("empty string")
       +    # try hex
            try:
                bfh(txt)
       -        is_hex = True
       -    except:
       -        is_hex = False
       -    if is_hex:
                return txt
       +    except:
       +        pass
       +    # try base43
       +    try:
       +        return base_decode(txt, length=None, base=43).hex()
       +    except:
       +        pass
       +    # try json
       +    import json
            tx_dict = json.loads(str(txt))
            assert "hex" in tx_dict.keys()
            return tx_dict["hex"]