From 68792a7392ec375b7a904d1c567e205fe2aee334 Mon Sep 17 00:00:00 2001 From: scgbckbone Date: Tue, 3 Jun 2025 09:58:00 +0200 Subject: [PATCH] move OP_RETURN ux rendition from chains to render_output --- shared/auth.py | 26 ++++++++++++++++++++------ shared/chains.py | 19 +++++-------------- testing/test_sign.py | 16 ++++++++++++---- 3 files changed, 37 insertions(+), 24 deletions(-) diff --git a/shared/auth.py b/shared/auth.py index 12bb0758..b877d103 100644 --- a/shared/auth.py +++ b/shared/auth.py @@ -302,12 +302,26 @@ class ApproveTransaction(UserAuthorizedAction): # check for OP_RETURN data = self.chain.op_return(o.scriptPubKey) - if data: - data_hex, data_ascii = data - to_ret = '%s\n - OP_RETURN -\n%s' % (val, data_hex) - if data_ascii: - to_ret += " (ascii: %s)" % data_ascii - return to_ret + "\n", data_hex + if data is not None: + base = '%s\n - OP_RETURN -\n%s' + if not data: + return base % (val, "null-data\n"), "" + else: + data_ascii = None + if len(data) > 200: + # completely arbitrary limit, prevents huge stories + data_hex = b2a_hex(data[:100]).decode() + "\n ⋯\n" + b2a_hex(data[-100:]).decode() + else: + data_hex = b2a_hex(data).decode() + if (min(data) >= 32) and (max(data) < 127): # printable & not huge + try: + data_ascii = data.decode("ascii") + except: pass + + to_ret = base % (val, data_hex) + if data_ascii: + to_ret += " (ascii: %s)" % data_ascii + return to_ret + "\n", data_hex # Handle future things better: allow them to happen at least. dest = B2A(o.scriptPubKey) diff --git a/shared/chains.py b/shared/chains.py index e69acb02..9c0279b6 100644 --- a/shared/chains.py +++ b/shared/chains.py @@ -286,21 +286,12 @@ class ChainsBase: try: data = next(gen)[0] - if data is None: raise RuntimeError - except (RuntimeError, StopIteration): - return "null-data", "" + if data: + return data + except StopIteration: + pass - data_ascii = None - if len(data) > 200: - # completely arbitrary limit, prevents huge stories - data_hex = b2a_hex(data[:100]).decode() + "\n ⋯\n" + b2a_hex(data[-100:]).decode() - else: - data_hex = b2a_hex(data).decode() - if min(data) >= 32 and max(data) < 127: # printable - try: - data_ascii = data.decode("ascii") - except: pass - return data_hex, data_ascii + return b"" @classmethod def possible_address_fmt(cls, addr): diff --git a/testing/test_sign.py b/testing/test_sign.py index 751a3859..cdf363e4 100644 --- a/testing/test_sign.py +++ b/testing/test_sign.py @@ -3029,6 +3029,7 @@ def test_txout_explorer(chain, data, fake_txn, start_sign, settings_set, txout_e @pytest.mark.parametrize("data", [ [(1, b"Coinkite"), (0, b"Mk1 Mk2 Mk3 Mk4 Q"), (100, b"binarywatch.org"), (100, b"a" * 75)], [(0, b"a" * 300), (10, b"x" * 1000), (0, b"anchor output")], + [(0, b""), (10, b"")], ]) def test_txout_explorer_op_return(finalize, data, fake_txn, start_sign, cap_story, is_q1, need_keypress, press_cancel, press_select, end_sign): @@ -3067,7 +3068,7 @@ def test_txout_explorer_op_return(finalize, data, fake_txn, start_sign, cap_stor need_keypress(KEY_QR if is_q1 else "4") qr_list = [] for _ in range(len(data)): - qr = cap_screen_qr().decode('ascii') + qr = cap_screen_qr().decode() qr_list.append(qr) need_keypress(KEY_RIGHT if is_q1 else "9") time.sleep(.5) @@ -3083,14 +3084,21 @@ def test_txout_explorer_op_return(finalize, data, fake_txn, start_sign, cap_stor val, name, dd0, _, dd1 = sb.split("\n") assert "OP_RETURN" in name assert f'{amount / 100000000:.8f} XTN' == val - if dd: + if dd == "null-data": + assert qr_list[i - 20] == "" + elif dd: hex_str, ascii_str = dd.split(" ", 1) assert hex_str == qr_list[i-20] assert f"(ascii: {data.decode()})" == ascii_str assert data.hex() == hex_str else: - assert data.hex()[:200] == dd0 - assert data.hex()[-200:] == dd1 + s = data[:100].hex() + e = data[-100:].hex() + assert s == dd0 + assert e == dd1 + qr = qr_list[i - 20] + assert qr.startswith(s) + assert qr.endswith(e) press_cancel() # exit txn out explorer end_sign(finalize=finalize)