From a19365ac4ef9e85fd7fd69a2cd654441bc121afa Mon Sep 17 00:00:00 2001 From: Matt Hauff Date: Fri, 9 Jan 2026 10:08:18 -1000 Subject: [PATCH] [LABS-394] Add a streamable hack to force `ConditionValidTimes` serialization order (#20383) Add a streamable hack to force `ConditionValidTimes` serialization order --- chia/util/streamable.py | 4 ++-- chia/wallet/conditions.py | 23 ++++++++++++++++++++++- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/chia/util/streamable.py b/chia/util/streamable.py index 667203a686..7cfc9c199b 100644 --- a/chia/util/streamable.py +++ b/chia/util/streamable.py @@ -668,12 +668,12 @@ class Streamable: def parse(cls, f: BinaryIO) -> Self: # Create the object without calling __init__() to avoid unnecessary post-init checks in strictdataclass obj: Self = object.__new__(cls) - for field in cls._streamable_fields: + for field in cls.streamable_fields(): object.__setattr__(obj, field.name, field.parse_function(f)) return obj def stream(self, f: BinaryIO) -> None: - for field in self._streamable_fields: + for field in self.streamable_fields(): field.stream_function(getattr(self, field.name), f) def get_hash(self) -> bytes32: diff --git a/chia/wallet/conditions.py b/chia/wallet/conditions.py index a6d90338c2..a54d6d4c84 100644 --- a/chia/wallet/conditions.py +++ b/chia/wallet/conditions.py @@ -14,7 +14,7 @@ from chia.types.blockchain_format.program import Program from chia.types.condition_opcodes import ConditionOpcode from chia.util.casts import int_from_bytes, int_to_bytes from chia.util.hash import std_hash -from chia.util.streamable import Streamable, streamable +from chia.util.streamable import Streamable, StreamableFields, streamable _T_Condition = TypeVar("_T_Condition", bound="Condition") @@ -1433,6 +1433,27 @@ class ConditionValidTimes(ConditionValidTimesAbsolute): max_secs_after_created: uint64 | None = None # ASSERT_BEFORE_SECONDS_RELATIVE max_blocks_after_created: uint32 | None = None # ASSERT_BEFORE_HEIGHT_RELATIVE + @classmethod + def streamable_fields(cls) -> StreamableFields: + # A hack to serialize the fields in the order before this was inherited + order_map = { + name: i + for i, name in enumerate( + [ + "min_secs_since_created", + "min_time", + "min_blocks_since_created", + "min_height", + "max_secs_after_created", + "max_time", + "max_blocks_after_created", + "max_height", + ] + ) + } + + return tuple(sorted(cls._streamable_fields, key=lambda item: order_map[item.name])) + def to_conditions(self) -> list[Condition]: final_condition_list = super().to_conditions() if self.min_secs_since_created is not None: