tx.completed: new legacy_fmt_chk() method

See dd714815, 852cdeda

Reject Ethereum transaction files with double-encoded serialized data as well.
This commit is contained in:
The MMGen Project 2026-09-09 18:33:59 +00:00
commit 650f1902f8
Signed by: mmgen
GPG key ID: 3F8B1861E32B7DA2
7 changed files with 33 additions and 10 deletions

View file

@ -272,7 +272,9 @@ class Autosign:
except Exception as e:
ymsg('An error occurred with {} ‘{}’:\n {}: ‘{}’'.format(
target.desc, f.name, type(e).__name__, e))
if type(e).__name__ == 'LegacyTxSignRequestError':
if type(e).__name__ == 'TxFileVersionError':
self.do_umount()
self.led.set('on')
raise
except:
ymsg('An error occurred with {} ‘{}’'.format(target.desc, f.name))

View file

@ -86,7 +86,7 @@ class WalletFileError(Exception): mmcode = 3
class HexadecimalStringError(Exception): mmcode = 3
class SeedLengthError(Exception): mmcode = 3
class PrivateKeyError(Exception): mmcode = 3
class LegacyTxSignRequestError(Exception):mmcode = 3
class TxFileVersionError(Exception): mmcode = 3
class MMGenCalledProcessError(Exception): mmcode = 3
class TestSuiteFatalException(Exception): mmcode = 3

View file

@ -30,6 +30,7 @@ class Unsigned(VmUnsigned, Completed, TxBase.Unsigned):
if isinstance(self.serialized, dict):
d = self.serialized
else:
self.legacy_fmt_chk('double-encoded serialized data')
d = json.loads(self.serialized)
o = {

View file

@ -12,6 +12,7 @@
tx.completed: completed transaction class
"""
from ..cfg import gc
from ..util import msg, ymsg, die
from .base import Base
@ -102,9 +103,25 @@ class Completed(Base):
if self.is_swap:
raise ValueError('missing or invalid memo in swap transaction')
def die_on_version_error(self, errmsg): # overridden by test.overlay.fakemods
die('TxFileVersionError', errmsg)
def legacy_fmt_chk(self, desc):
if 'sign' in gc.prog_name:
a, b = ('sign', 'Has your online installation been compromised?')
elif 'send' in gc.prog_name:
a, b = ('send', 'Is your offline installation out of date?')
else:
return
fs = f'Request to {{}} legacy-format transaction ({desc}). {{}}'
self.die_on_version_error(fs.format(a, b))
class DummyCompleted: # required by MMGenTxFile.get_proto()
desc = 'dummy transaction'
def __init__(self, cfg):
self.cfg = cfg
die_on_version_error = Completed.die_on_version_error
legacy_fmt_chk = Completed.legacy_fmt_chk

View file

@ -22,7 +22,6 @@ tx.file: Transaction file operations for the MMGen suite
import os, json
from ..cfg import gc
from ..util import ymsg, make_chksum_6, die
from ..obj import MMGenObject, HexStr, MMGenTxID, CoinTxID, MMGenTxComment
@ -134,12 +133,7 @@ class MMGenTxFile(MMGenObject):
tx = self.tx
tx.file_format = 'legacy'
if 'sign' in gc.prog_name:
m = 'Request to sign legacy-format transaction. Has your online installation been compromised?'
if tx.cfg.test_suite:
ymsg(m)
else:
die('LegacyTxSignRequestError', m)
tx.legacy_fmt_chk('non-JSON')
def deserialize(raw_data, *, desc):
from ast import literal_eval

View file

@ -930,7 +930,7 @@ class CmdTestAutosign(CmdTestAutosignBase):
if exc_exit_val:
return do_return()
t.expect('compromised')
t.expect('legacy-format')
t.expect(
f'{self.tx_count} {tx_desc}{suf(self.tx_count)} signed' if self.tx_count else

View file

@ -0,0 +1,9 @@
from .completed_orig import *
class overlay_fake_Completed(Completed):
def die_on_version_error(self, errmsg):
ymsg(errmsg)
Completed.die_on_version_error = overlay_fake_Completed.die_on_version_error
DummyCompleted.die_on_version_error = overlay_fake_Completed.die_on_version_error