@@ -180,7 +180,7 @@ class XmssKeyManager:
180180
181181 - Raw JSON (lightweight hex strings, ~2.7 KB per validator)
182182 - Deserialized public keys only (avoids the heavy secret key objects)
183- - Advanced secret key state as compact SSZ bytes
183+ - Advanced secret key state as live Python objects
184184 """
185185
186186 __slots__ = (
@@ -267,10 +267,8 @@ def __init__(
267267 # Populated lazily on first directory scan.
268268 self ._available_indices : set [ValidatorIndex ] | None = None
269269
270- # Advanced secret key state cached as raw SSZ bytes.
271- # Raw bytes (~2.7 KB each) instead of deserialized objects (~370 MB each)
272- # to avoid holding massive Pydantic model trees in memory.
273- self ._secret_state : dict [tuple [ValidatorIndex , KeyRole ], bytes ] = {}
270+ # Advanced secret-key state held as live Python objects.
271+ self ._secret_state : dict [tuple [ValidatorIndex , KeyRole ], SecretKey ] = {}
274272
275273 def _scan_indices (self ) -> set [ValidatorIndex ]:
276274 """
@@ -413,9 +411,9 @@ def _sign_with_secret(
413411
414412 Memory strategy:
415413
416- 1. Deserialize the secret key from cached bytes or disk
417- 2. Advance and sign (only one full key object in memory)
418- 3. Re-serialize to compact bytes (~2.7 KB) for caching
414+ 1. On cache miss, deserialize the key once from disk
415+ 2. Advance and sign
416+ 3. Keep the advanced object for the next sign
419417
420418 Args:
421419 validator_id: Which validator's key to use.
@@ -428,9 +426,11 @@ def _sign_with_secret(
428426 """
429427 cache_key = (validator_id , role )
430428
431- # Deserialize the secret key from either the byte cache or disk.
429+ # Reuse the cached object directly when present, else decode from disk.
430+ # Holding the object avoids the bytes-to-object round-trip on every sign.
431+ # That round-trip dominated prod-scheme runtime under the compact-bytes cache.
432432 if cache_key in self ._secret_state :
433- sk = SecretKey . decode_bytes ( self ._secret_state [cache_key ])
433+ sk = self ._secret_state [cache_key ]
434434 else :
435435 sk = self ._get_secret_key (validator_id , role )
436436
@@ -452,9 +452,8 @@ def _sign_with_secret(
452452 # Produce the signature for the target slot.
453453 signature = self .scheme .sign (sk , slot , message )
454454
455- # Re-serialize the advanced key state to compact bytes for caching.
456- # This drops the full Python object tree from memory immediately.
457- self ._secret_state [cache_key ] = sk .encode_bytes ()
455+ # Park the advanced object back in the cache for the next sign.
456+ self ._secret_state [cache_key ] = sk
458457
459458 return signature
460459
0 commit comments