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.
This commit is contained in:
@@ -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
|
||||
@@ -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))
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"]
|
||||
|
||||
Reference in New Issue
Block a user