From 5f2a9620a8c16d1b00b2ce84d0303857b258b3aa Mon Sep 17 00:00:00 2001 From: highlander Date: Tue, 8 Sep 2026 12:28:22 -0600 Subject: [PATCH 1/4] test: correct EOS updateauth zero-wait signing vector --- tests/test_msg_eos_signtx.py | 3 +- tests/unit/test_eos_updateauth_vector.py | 38 ++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 tests/unit/test_eos_updateauth_vector.py diff --git a/tests/test_msg_eos_signtx.py b/tests/test_msg_eos_signtx.py index f04c990d..ba692315 100644 --- a/tests/test_msg_eos_signtx.py +++ b/tests/test_msg_eos_signtx.py @@ -568,7 +568,8 @@ def test_updateauth(self): num_actions=1), [self.action_updateauth(True)]) - self.assertEqual(binascii.hexlify(res.hash), "fb936ef1be4bda680d93bd10b6d062357d8dd7272038a706dc0d61a91f39c5ee") + # One account and zero waits: do not serialize a phantom six-byte wait. + self.assertEqual(binascii.hexlify(res.hash), "5938294e65cf9e8b5dd5f2b204503b4825f277e6f4a2d5ab7a55a31065a23af1") def test_deleteauth(self): self.requires_fullFeature() diff --git a/tests/unit/test_eos_updateauth_vector.py b/tests/unit/test_eos_updateauth_vector.py new file mode 100644 index 00000000..21d84dd5 --- /dev/null +++ b/tests/unit/test_eos_updateauth_vector.py @@ -0,0 +1,38 @@ +"""Independent EOS updateauth wire vector; no emulator or protobuf required. + +Public key: test mnemonic from common.py, path m/48'/4'/1'/0'/0'. +The legacy firmware serialized one zero wait because it used accounts_count +instead of waits_count. Both digests below prove the exact discrepancy. +""" +import hashlib +import struct +import unittest + +pub = bytes.fromhex("037eca30dbc22ecc6d38d95a7e4b49f6b77fa87be608250319b75e2564ccb60143") + +def name(s): + alphabet='.12345abcdefghijklmnopqrstuvwxyz';value=0 + for x in range(13):value=(value << (5 if x<12 else 4)) | (alphabet.index(s[x]) if x=128:b.append((x&127)|128);x>>=7 + b.append(x);return bytes(b) +auth=struct.pack(' Date: Tue, 8 Sep 2026 13:00:43 -0600 Subject: [PATCH 2/4] test: make EOS vector field boundaries auditable --- tests/unit/test_eos_updateauth_vector.py | 40 +++++++++++++++++------- 1 file changed, 29 insertions(+), 11 deletions(-) diff --git a/tests/unit/test_eos_updateauth_vector.py b/tests/unit/test_eos_updateauth_vector.py index 21d84dd5..c6126087 100644 --- a/tests/unit/test_eos_updateauth_vector.py +++ b/tests/unit/test_eos_updateauth_vector.py @@ -11,18 +11,36 @@ pub = bytes.fromhex("037eca30dbc22ecc6d38d95a7e4b49f6b77fa87be608250319b75e2564ccb60143") def name(s): - alphabet='.12345abcdefghijklmnopqrstuvwxyz';value=0 - for x in range(13):value=(value << (5 if x<12 else 4)) | (alphabet.index(s[x]) if x=128:b.append((x&127)|128);x>>=7 - b.append(x);return bytes(b) -auth=struct.pack('= 128: + b.append((x & 127) | 128) + x >>= 7 + b.append(x) + return bytes(b) + + +auth = ( + struct.pack(' Date: Tue, 8 Sep 2026 13:06:55 -0600 Subject: [PATCH 3/4] test: label corrected and legacy EOS vector cases --- tests/unit/test_eos_updateauth_vector.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tests/unit/test_eos_updateauth_vector.py b/tests/unit/test_eos_updateauth_vector.py index c6126087..f3e574a2 100644 --- a/tests/unit/test_eos_updateauth_vector.py +++ b/tests/unit/test_eos_updateauth_vector.py @@ -44,13 +44,15 @@ def var(x): class UpdateAuthVector(unittest.TestCase): def test_zero_waits(self): + phantom_wait = struct.pack(" Date: Tue, 8 Sep 2026 13:11:21 -0600 Subject: [PATCH 4/4] docs: explain independent legacy EOS preimage construction --- tests/unit/test_eos_updateauth_vector.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/unit/test_eos_updateauth_vector.py b/tests/unit/test_eos_updateauth_vector.py index f3e574a2..6762f8c8 100644 --- a/tests/unit/test_eos_updateauth_vector.py +++ b/tests/unit/test_eos_updateauth_vector.py @@ -1,8 +1,10 @@ """Independent EOS updateauth wire vector; no emulator or protobuf required. Public key: test mnemonic from common.py, path m/48'/4'/1'/0'/0'. -The legacy firmware serialized one zero wait because it used accounts_count -instead of waits_count. Both digests below prove the exact discrepancy. +The authority contains one account and zero waits. The corrected case hashes +that authority unchanged; the legacy case appends one six-byte zero wait +(wait_sec=0, weight=0) and updates the action-data length. This models the old +firmware using accounts_count instead of waits_count for wait serialization. """ import hashlib import struct