From e6aeae64eaa3cc241c952a04d1e3ccd0695a6ca0 Mon Sep 17 00:00:00 2001 From: Matthew Howard Date: Tue, 17 Jun 2025 14:09:43 +0100 Subject: [PATCH 01/11] initial commit --- README.md | 4 +++- clvm/serialize.py | 33 ++++++++++++++++++++++++--------- 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 178cb609..48a01d80 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,8 @@ See docs/clvm.org or https://chialisp.com/ for more info. Testing ======= + $ python3 -m venv venv + $ . ./venv/bin/activate $ pip install -e '.[dev]' - $ py.test tests + $ pytest tests diff --git a/clvm/serialize.py b/clvm/serialize.py index 9d0eb265..261ea2ac 100644 --- a/clvm/serialize.py +++ b/clvm/serialize.py @@ -17,6 +17,7 @@ import io import typing +from typing import Optional from .read_cache_lookup import ReadCacheLookup from .object_cache import ObjectCache, treehash, serialized_length @@ -26,6 +27,8 @@ BACK_REFERENCE = 0xFE CONS_BOX_MARKER = 0xFF +MAX_SAFE_BYTES = 2_000_000 + T = typing.TypeVar("T") _T_CLVMStorage = typing.TypeVar("_T_CLVMStorage", bound=CLVMStorage) @@ -44,12 +47,17 @@ OpStackType = typing.List[OpCallable[T]] +def decrement_counter(count: Optional[int], amount: int): + if count is not None: + count -= amount + if count <= 0: + raise ValueError("SExp too big") def sexp_to_byte_iterator( - sexp: CLVMStorage, *, allow_backrefs: bool = False + sexp: CLVMStorage, *, allow_backrefs: bool = False, max_size: Optional[int] = None ) -> typing.Iterator[bytes]: if allow_backrefs: - yield from sexp_to_byte_iterator_with_backrefs(sexp) + yield from sexp_to_byte_iterator_with_backrefs(sexp, max_size=max_size) return todo_stack = [sexp] @@ -58,14 +66,15 @@ def sexp_to_byte_iterator( pair = sexp.pair if pair: yield bytes([CONS_BOX_MARKER]) + decrement_counter(max_size, 1) todo_stack.append(pair[1]) todo_stack.append(pair[0]) else: assert sexp.atom is not None - yield from atom_to_byte_iterator(sexp.atom) + yield from atom_to_byte_iterator(sexp.atom, max_size=max_size) -def sexp_to_byte_iterator_with_backrefs(sexp: CLVMStorage) -> typing.Iterator[bytes]: +def sexp_to_byte_iterator_with_backrefs(sexp: CLVMStorage, max_size: Optional[int] = None) -> typing.Iterator[bytes]: # in `read_op_stack`: # "P" = "push" # "C" = "pop two objects, create and push a new cons with them" @@ -90,11 +99,13 @@ def sexp_to_byte_iterator_with_backrefs(sexp: CLVMStorage) -> typing.Iterator[by path = read_cache_lookup.find_path(node_tree_hash, node_serialized_length) if path: yield bytes([BACK_REFERENCE]) - yield from atom_to_byte_iterator(path) + decrement_counter(max_size, 1) + yield from atom_to_byte_iterator(path, max_size=max_size) read_cache_lookup.push(node_tree_hash) elif node_to_write.pair: left, right = node_to_write.pair yield bytes([CONS_BOX_MARKER]) + decrement_counter(max_size, 1) write_stack.append(right) write_stack.append(left) read_op_stack.append("C") @@ -103,7 +114,7 @@ def sexp_to_byte_iterator_with_backrefs(sexp: CLVMStorage) -> typing.Iterator[by else: atom = node_to_write.atom assert atom is not None - yield from atom_to_byte_iterator(atom) + yield from atom_to_byte_iterator(atom, max_size=max_size) read_cache_lookup.push(node_tree_hash) while read_op_stack[-1:] == ["C"]: @@ -111,14 +122,16 @@ def sexp_to_byte_iterator_with_backrefs(sexp: CLVMStorage) -> typing.Iterator[by read_cache_lookup.pop2_and_cons() -def atom_to_byte_iterator(as_atom: bytes) -> typing.Iterator[bytes]: +def atom_to_byte_iterator(as_atom: bytes, max_size: Optional[int] = None) -> typing.Iterator[bytes]: size = len(as_atom) if size == 0: yield b"\x80" + decrement_counter(max_size, 1) return if size == 1: if as_atom[0] <= MAX_SINGLE_BYTE: yield as_atom + decrement_counter(max_size, size) return if size < 0x40: size_blob = bytes([0x80 | size]) @@ -149,13 +162,15 @@ def atom_to_byte_iterator(as_atom: bytes) -> typing.Iterator[bytes]: raise ValueError(f"sexp too long {as_atom!r}") yield size_blob + decrement_counter(max_size, size_blob) yield as_atom + decrement_counter(max_size, as_atom) def sexp_to_stream( - sexp: CLVMStorage, f: typing.BinaryIO, *, allow_backrefs: bool = False + sexp: CLVMStorage, f: typing.BinaryIO, *, allow_backrefs: bool = False, max_size: Optional[int] = None ) -> None: - for b in sexp_to_byte_iterator(sexp, allow_backrefs=allow_backrefs): + for b in sexp_to_byte_iterator(sexp, allow_backrefs=allow_backrefs, max_size=max_size): f.write(b) From 43abe20ffe15bed5225daf456065a3fa94266568 Mon Sep 17 00:00:00 2001 From: Matthew Howard Date: Tue, 17 Jun 2025 14:45:27 +0100 Subject: [PATCH 02/11] flake8 --- clvm/serialize.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/clvm/serialize.py b/clvm/serialize.py index 261ea2ac..105aee4f 100644 --- a/clvm/serialize.py +++ b/clvm/serialize.py @@ -47,12 +47,14 @@ OpStackType = typing.List[OpCallable[T]] + def decrement_counter(count: Optional[int], amount: int): if count is not None: count -= amount if count <= 0: raise ValueError("SExp too big") + def sexp_to_byte_iterator( sexp: CLVMStorage, *, allow_backrefs: bool = False, max_size: Optional[int] = None ) -> typing.Iterator[bytes]: From 5ae8299c99321101604f5bb75e53db8c59edb342 Mon Sep 17 00:00:00 2001 From: Matthew Howard Date: Tue, 17 Jun 2025 17:06:47 +0100 Subject: [PATCH 03/11] simplify code and add test --- clvm/serialize.py | 28 +++++++++++----------------- tests/serialize_test.py | 12 ++++++++++++ 2 files changed, 23 insertions(+), 17 deletions(-) diff --git a/clvm/serialize.py b/clvm/serialize.py index 105aee4f..6cd4b557 100644 --- a/clvm/serialize.py +++ b/clvm/serialize.py @@ -51,15 +51,15 @@ def decrement_counter(count: Optional[int], amount: int): if count is not None: count -= amount - if count <= 0: - raise ValueError("SExp too big") + if count < 0: + raise ValueError("SExp exceeds maximum size") def sexp_to_byte_iterator( - sexp: CLVMStorage, *, allow_backrefs: bool = False, max_size: Optional[int] = None + sexp: CLVMStorage, *, allow_backrefs: bool = False ) -> typing.Iterator[bytes]: if allow_backrefs: - yield from sexp_to_byte_iterator_with_backrefs(sexp, max_size=max_size) + yield from sexp_to_byte_iterator_with_backrefs(sexp) return todo_stack = [sexp] @@ -68,15 +68,14 @@ def sexp_to_byte_iterator( pair = sexp.pair if pair: yield bytes([CONS_BOX_MARKER]) - decrement_counter(max_size, 1) todo_stack.append(pair[1]) todo_stack.append(pair[0]) else: assert sexp.atom is not None - yield from atom_to_byte_iterator(sexp.atom, max_size=max_size) + yield from atom_to_byte_iterator(sexp.atom) -def sexp_to_byte_iterator_with_backrefs(sexp: CLVMStorage, max_size: Optional[int] = None) -> typing.Iterator[bytes]: +def sexp_to_byte_iterator_with_backrefs(sexp: CLVMStorage) -> typing.Iterator[bytes]: # in `read_op_stack`: # "P" = "push" # "C" = "pop two objects, create and push a new cons with them" @@ -101,13 +100,11 @@ def sexp_to_byte_iterator_with_backrefs(sexp: CLVMStorage, max_size: Optional[in path = read_cache_lookup.find_path(node_tree_hash, node_serialized_length) if path: yield bytes([BACK_REFERENCE]) - decrement_counter(max_size, 1) - yield from atom_to_byte_iterator(path, max_size=max_size) + yield from atom_to_byte_iterator(path) read_cache_lookup.push(node_tree_hash) elif node_to_write.pair: left, right = node_to_write.pair yield bytes([CONS_BOX_MARKER]) - decrement_counter(max_size, 1) write_stack.append(right) write_stack.append(left) read_op_stack.append("C") @@ -116,7 +113,7 @@ def sexp_to_byte_iterator_with_backrefs(sexp: CLVMStorage, max_size: Optional[in else: atom = node_to_write.atom assert atom is not None - yield from atom_to_byte_iterator(atom, max_size=max_size) + yield from atom_to_byte_iterator(atom) read_cache_lookup.push(node_tree_hash) while read_op_stack[-1:] == ["C"]: @@ -124,16 +121,14 @@ def sexp_to_byte_iterator_with_backrefs(sexp: CLVMStorage, max_size: Optional[in read_cache_lookup.pop2_and_cons() -def atom_to_byte_iterator(as_atom: bytes, max_size: Optional[int] = None) -> typing.Iterator[bytes]: +def atom_to_byte_iterator(as_atom: bytes) -> typing.Iterator[bytes]: size = len(as_atom) if size == 0: yield b"\x80" - decrement_counter(max_size, 1) return if size == 1: if as_atom[0] <= MAX_SINGLE_BYTE: yield as_atom - decrement_counter(max_size, size) return if size < 0x40: size_blob = bytes([0x80 | size]) @@ -164,15 +159,14 @@ def atom_to_byte_iterator(as_atom: bytes, max_size: Optional[int] = None) -> typ raise ValueError(f"sexp too long {as_atom!r}") yield size_blob - decrement_counter(max_size, size_blob) yield as_atom - decrement_counter(max_size, as_atom) def sexp_to_stream( sexp: CLVMStorage, f: typing.BinaryIO, *, allow_backrefs: bool = False, max_size: Optional[int] = None ) -> None: - for b in sexp_to_byte_iterator(sexp, allow_backrefs=allow_backrefs, max_size=max_size): + for b in sexp_to_byte_iterator(sexp, allow_backrefs=allow_backrefs): + decrement_counter(max_size, 1) f.write(b) diff --git a/tests/serialize_test.py b/tests/serialize_test.py index 0f2e8521..bef84c57 100644 --- a/tests/serialize_test.py +++ b/tests/serialize_test.py @@ -3,6 +3,8 @@ import unittest from typing import Optional +import pytest + from clvm import to_sexp_f from clvm.SExp import CastableType, SExp from clvm.serialize import ( @@ -10,6 +12,7 @@ sexp_from_stream, sexp_buffer_from_stream, atom_to_byte_iterator, + sexp_to_stream, ) @@ -54,6 +57,7 @@ class SerializeTest(unittest.TestCase): def check_serde(self, s: CastableType) -> bytes: v = to_sexp_f(s) b = v.as_bin() + f = io.BytesIO() v1 = sexp_from_stream(io.BytesIO(b), to_sexp_f) if v != v1: print("%s: %d %r %s" % (v, len(b), b, v1)) @@ -61,6 +65,9 @@ def check_serde(self, s: CastableType) -> bytes: b = v.as_bin() v1 = sexp_from_stream(io.BytesIO(b), to_sexp_f) self.assertEqual(v, v1) + sexp_to_stream(v1, f) + length = len(f.getvalue()) + assert f.getbuffer() == b # this copies the bytes that represent a single s-expression, just to # know where the message ends. It doesn't build a python representaion # of it @@ -85,6 +92,11 @@ def check_serde(self, s: CastableType) -> bytes: self.assertEqual(v2, s) b3 = v2.as_bin() self.assertEqual(b, b3) + with pytest.raises(ValueError): + f = io.BytesIO() + sexp_to_stream(v1, f, max_size=length-5000) + f = io.BytesIO() + sexp_to_stream(v1, f, max_size=length) return b2 def test_zero(self) -> None: From 26125435f69a685f882e8d5d68c896300f3a469d Mon Sep 17 00:00:00 2001 From: Matthew Howard Date: Tue, 17 Jun 2025 17:17:57 +0100 Subject: [PATCH 04/11] mypy fixes --- clvm/more_ops.py | 4 +++- clvm/serialize.py | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/clvm/more_ops.py b/clvm/more_ops.py index fd68d07b..fff5a303 100644 --- a/clvm/more_ops.py +++ b/clvm/more_ops.py @@ -242,7 +242,9 @@ def op_point_add(items: _T_SExp) -> typing.Tuple[int, _T_SExp]: if _.pair: raise EvalError("point_add on list", _) try: - p += G1Element.from_bytes(_.as_atom()) + atom = _.as_atom() + assert atom is not None + p += G1Element.from_bytes(atom) cost += POINT_ADD_COST_PER_ARG except Exception as ex: raise EvalError("point_add expects blob, got %s: %s" % (_, ex), items) diff --git a/clvm/serialize.py b/clvm/serialize.py index 6cd4b557..2466209c 100644 --- a/clvm/serialize.py +++ b/clvm/serialize.py @@ -48,7 +48,7 @@ OpStackType = typing.List[OpCallable[T]] -def decrement_counter(count: Optional[int], amount: int): +def decrement_counter(count: Optional[int], amount: int) -> None: if count is not None: count -= amount if count < 0: From 571cee1bf5c96b3a554ec25e18e7695d041b616b Mon Sep 17 00:00:00 2001 From: Matthew Howard Date: Tue, 17 Jun 2025 17:43:01 +0100 Subject: [PATCH 05/11] inline and fix byte counting --- clvm/serialize.py | 13 +++++-------- tests/serialize_test.py | 2 +- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/clvm/serialize.py b/clvm/serialize.py index 2466209c..e2697ee2 100644 --- a/clvm/serialize.py +++ b/clvm/serialize.py @@ -48,13 +48,6 @@ OpStackType = typing.List[OpCallable[T]] -def decrement_counter(count: Optional[int], amount: int) -> None: - if count is not None: - count -= amount - if count < 0: - raise ValueError("SExp exceeds maximum size") - - def sexp_to_byte_iterator( sexp: CLVMStorage, *, allow_backrefs: bool = False ) -> typing.Iterator[bytes]: @@ -165,8 +158,12 @@ def atom_to_byte_iterator(as_atom: bytes) -> typing.Iterator[bytes]: def sexp_to_stream( sexp: CLVMStorage, f: typing.BinaryIO, *, allow_backrefs: bool = False, max_size: Optional[int] = None ) -> None: + remaining = max_size for b in sexp_to_byte_iterator(sexp, allow_backrefs=allow_backrefs): - decrement_counter(max_size, 1) + if remaining is not None: + remaining -= len(b) + if remaining < 0: + raise ValueError("SExp exceeds maximum size") f.write(b) diff --git a/tests/serialize_test.py b/tests/serialize_test.py index bef84c57..262dcc69 100644 --- a/tests/serialize_test.py +++ b/tests/serialize_test.py @@ -94,7 +94,7 @@ def check_serde(self, s: CastableType) -> bytes: self.assertEqual(b, b3) with pytest.raises(ValueError): f = io.BytesIO() - sexp_to_stream(v1, f, max_size=length-5000) + sexp_to_stream(v1, f, max_size=length-1) f = io.BytesIO() sexp_to_stream(v1, f, max_size=length) return b2 From 883c984ca98d2f90d270fa8153786e6172ded5ff Mon Sep 17 00:00:00 2001 From: matt-o-how <48453825+matt-o-how@users.noreply.github.com> Date: Tue, 17 Jun 2025 23:46:58 +0100 Subject: [PATCH 06/11] Update tests/serialize_test.py Co-authored-by: Arvid Norberg --- tests/serialize_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/serialize_test.py b/tests/serialize_test.py index 262dcc69..3e250dfd 100644 --- a/tests/serialize_test.py +++ b/tests/serialize_test.py @@ -92,7 +92,7 @@ def check_serde(self, s: CastableType) -> bytes: self.assertEqual(v2, s) b3 = v2.as_bin() self.assertEqual(b, b3) - with pytest.raises(ValueError): + with pytest.raises(ValueError, matches="SExp exceeds maximum size"): f = io.BytesIO() sexp_to_stream(v1, f, max_size=length-1) f = io.BytesIO() From e8f9d4cfca976233aea30d1a7c12395237f85216 Mon Sep 17 00:00:00 2001 From: Matthew Howard Date: Wed, 18 Jun 2025 00:06:16 +0100 Subject: [PATCH 07/11] add default max size and fix tests that go above the max --- clvm/serialize.py | 10 ++++------ tests/serialize_test.py | 26 ++++++++++++++++++-------- 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/clvm/serialize.py b/clvm/serialize.py index e2697ee2..c2232115 100644 --- a/clvm/serialize.py +++ b/clvm/serialize.py @@ -156,14 +156,12 @@ def atom_to_byte_iterator(as_atom: bytes) -> typing.Iterator[bytes]: def sexp_to_stream( - sexp: CLVMStorage, f: typing.BinaryIO, *, allow_backrefs: bool = False, max_size: Optional[int] = None + sexp: CLVMStorage, f: typing.BinaryIO, *, allow_backrefs: bool = False, max_size: int = MAX_SAFE_BYTES ) -> None: - remaining = max_size for b in sexp_to_byte_iterator(sexp, allow_backrefs=allow_backrefs): - if remaining is not None: - remaining -= len(b) - if remaining < 0: - raise ValueError("SExp exceeds maximum size") + max_size -= len(b) + if max_size < 0: + raise ValueError("SExp exceeds maximum size") f.write(b) diff --git a/tests/serialize_test.py b/tests/serialize_test.py index 3e250dfd..0444e0b3 100644 --- a/tests/serialize_test.py +++ b/tests/serialize_test.py @@ -92,7 +92,7 @@ def check_serde(self, s: CastableType) -> bytes: self.assertEqual(v2, s) b3 = v2.as_bin() self.assertEqual(b, b3) - with pytest.raises(ValueError, matches="SExp exceeds maximum size"): + with pytest.raises(ValueError, match="SExp exceeds maximum size"): f = io.BytesIO() sexp_to_stream(v1, f, max_size=length-1) f = io.BytesIO() @@ -146,10 +146,18 @@ def test_very_long_blobs(self) -> None: count = size // len(TEXT) text = TEXT * count assert len(text) < size - self.check_serde(text) + if len(text) >= 134217688: + with pytest.raises(ValueError, match="SExp exceeds maximum size"): + self.check_serde(text) + else: + self.check_serde(text) text = TEXT * (count + 1) assert len(text) > size - self.check_serde(text) + if len(text) >= 134217688: + with pytest.raises(ValueError, match="SExp exceeds maximum size"): + self.check_serde(text) + else: + self.check_serde(text) def test_very_deep_tree(self) -> None: blob = b"a" @@ -222,14 +230,16 @@ def make_bomb(depth: int) -> SExp: self.assertEqual(len(b10_2), 75) bomb_20 = make_bomb(20) - b20_1 = bomb_20.as_bin(allow_backrefs=False) - b20_2 = bomb_20.as_bin(allow_backrefs=True) - self.assertEqual(len(b20_1), 48234495) - self.assertEqual(len(b20_2), 105) + with pytest.raises(ValueError, match="SExp exceeds maximum size"): + b20_1 = bomb_20.as_bin(allow_backrefs=False) + b20_2 = bomb_20.as_bin(allow_backrefs=True) + # self.assertEqual(len(b20_1), 48234495) + # self.assertEqual(len(b20_2), 105) bomb_30 = make_bomb(30) # do not uncomment the next line unless you want to run out of memory - # b30_1 = bomb_30.as_bin(allow_backrefs=False) + with pytest.raises(ValueError, match="SExp exceeds maximum size"): + b30_1 = bomb_30.as_bin(allow_backrefs=False) b30_2 = bomb_30.as_bin(allow_backrefs=True) # self.assertEqual(len(b30_1), 1) From 6f8ca97f59b6879019dcc9984a62c5d785bf23d4 Mon Sep 17 00:00:00 2001 From: Matthew Howard Date: Wed, 18 Jun 2025 00:10:45 +0100 Subject: [PATCH 08/11] flake8 fixes --- clvm/serialize.py | 1 - tests/serialize_test.py | 10 ++++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/clvm/serialize.py b/clvm/serialize.py index c2232115..3d4a4bae 100644 --- a/clvm/serialize.py +++ b/clvm/serialize.py @@ -17,7 +17,6 @@ import io import typing -from typing import Optional from .read_cache_lookup import ReadCacheLookup from .object_cache import ObjectCache, treehash, serialized_length diff --git a/tests/serialize_test.py b/tests/serialize_test.py index 0444e0b3..aca415a8 100644 --- a/tests/serialize_test.py +++ b/tests/serialize_test.py @@ -231,15 +231,17 @@ def make_bomb(depth: int) -> SExp: bomb_20 = make_bomb(20) with pytest.raises(ValueError, match="SExp exceeds maximum size"): - b20_1 = bomb_20.as_bin(allow_backrefs=False) - b20_2 = bomb_20.as_bin(allow_backrefs=True) + # b20_1 = bomb_20.as_bin(allow_backrefs=False) + bomb_20.as_bin(allow_backrefs=False) + b20_2 = bomb_20.as_bin(allow_backrefs=True) # self.assertEqual(len(b20_1), 48234495) - # self.assertEqual(len(b20_2), 105) + self.assertEqual(len(b20_2), 105) bomb_30 = make_bomb(30) # do not uncomment the next line unless you want to run out of memory with pytest.raises(ValueError, match="SExp exceeds maximum size"): - b30_1 = bomb_30.as_bin(allow_backrefs=False) + # b30_1 = bomb_30.as_bin(allow_backrefs=False) + bomb_30.as_bin(allow_backrefs=False) b30_2 = bomb_30.as_bin(allow_backrefs=True) # self.assertEqual(len(b30_1), 1) From c49df309529e0d2255e8b18de9e9dcc6479b92b8 Mon Sep 17 00:00:00 2001 From: Matthew Howard Date: Fri, 20 Jun 2025 12:16:34 +0100 Subject: [PATCH 09/11] remove commented lines --- tests/serialize_test.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tests/serialize_test.py b/tests/serialize_test.py index aca415a8..a8d11814 100644 --- a/tests/serialize_test.py +++ b/tests/serialize_test.py @@ -231,20 +231,16 @@ def make_bomb(depth: int) -> SExp: bomb_20 = make_bomb(20) with pytest.raises(ValueError, match="SExp exceeds maximum size"): - # b20_1 = bomb_20.as_bin(allow_backrefs=False) bomb_20.as_bin(allow_backrefs=False) b20_2 = bomb_20.as_bin(allow_backrefs=True) - # self.assertEqual(len(b20_1), 48234495) self.assertEqual(len(b20_2), 105) bomb_30 = make_bomb(30) # do not uncomment the next line unless you want to run out of memory with pytest.raises(ValueError, match="SExp exceeds maximum size"): - # b30_1 = bomb_30.as_bin(allow_backrefs=False) bomb_30.as_bin(allow_backrefs=False) b30_2 = bomb_30.as_bin(allow_backrefs=True) - # self.assertEqual(len(b30_1), 1) self.assertEqual(len(b30_2), 135) def test_specific_tree(self) -> None: From 4dd7596f62ee12361a5b09777bac01a3ebc36ae1 Mon Sep 17 00:00:00 2001 From: Matthew Howard Date: Mon, 23 Jun 2025 09:39:44 +0100 Subject: [PATCH 10/11] remove deprecated comment --- tests/serialize_test.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/serialize_test.py b/tests/serialize_test.py index a8d11814..d73fb16f 100644 --- a/tests/serialize_test.py +++ b/tests/serialize_test.py @@ -236,7 +236,6 @@ def make_bomb(depth: int) -> SExp: self.assertEqual(len(b20_2), 105) bomb_30 = make_bomb(30) - # do not uncomment the next line unless you want to run out of memory with pytest.raises(ValueError, match="SExp exceeds maximum size"): bomb_30.as_bin(allow_backrefs=False) b30_2 = bomb_30.as_bin(allow_backrefs=True) From fb601771367d1e392925fa7bcdc882288fdcaac0 Mon Sep 17 00:00:00 2001 From: Matthew Howard Date: Mon, 23 Jun 2025 09:47:24 +0100 Subject: [PATCH 11/11] use non-magic number for tests --- tests/serialize_test.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/serialize_test.py b/tests/serialize_test.py index d73fb16f..06ccee8f 100644 --- a/tests/serialize_test.py +++ b/tests/serialize_test.py @@ -8,6 +8,7 @@ from clvm import to_sexp_f from clvm.SExp import CastableType, SExp from clvm.serialize import ( + MAX_SAFE_BYTES, _atom_from_stream, sexp_from_stream, sexp_buffer_from_stream, @@ -146,14 +147,14 @@ def test_very_long_blobs(self) -> None: count = size // len(TEXT) text = TEXT * count assert len(text) < size - if len(text) >= 134217688: + if len(text) >= MAX_SAFE_BYTES: with pytest.raises(ValueError, match="SExp exceeds maximum size"): self.check_serde(text) else: self.check_serde(text) text = TEXT * (count + 1) assert len(text) > size - if len(text) >= 134217688: + if len(text) >= MAX_SAFE_BYTES: with pytest.raises(ValueError, match="SExp exceeds maximum size"): self.check_serde(text) else: