eth-ssz-specs 0.0.1.dev1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,277 @@
1
+ Metadata-Version: 2.4
2
+ Name: eth-ssz-specs
3
+ Version: 0.0.1.dev1
4
+ Summary: Ethereum SSZ (Simple Serialize) specification and Merkleization
5
+ Project-URL: Homepage, https://github.com/ethereum/ssz-specs
6
+ Project-URL: Source, https://github.com/ethereum/ssz-specs
7
+ Project-URL: Issues, https://github.com/ethereum/ssz-specs/issues
8
+ Author-email: Ethereum Foundation <security@ethereum.org>
9
+ License: MIT License
10
+
11
+ Copyright (c) 2025 Ethereum Foundation
12
+
13
+ Permission is hereby granted, free of charge, to any person obtaining a copy
14
+ of this software and associated documentation files (the "Software"), to deal
15
+ in the Software without restriction, including without limitation the rights
16
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17
+ copies of the Software, and to permit persons to whom the Software is
18
+ furnished to do so, subject to the following conditions:
19
+
20
+ The above copyright notice and this permission notice shall be included in all
21
+ copies or substantial portions of the Software.
22
+
23
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29
+ SOFTWARE.
30
+ License-File: LICENSE
31
+ Keywords: ethereum,merkleization,simple-serialize,specifications,ssz
32
+ Classifier: License :: OSI Approved :: MIT License
33
+ Classifier: Programming Language :: Python :: 3
34
+ Classifier: Programming Language :: Python :: 3.12
35
+ Classifier: Programming Language :: Python :: 3.13
36
+ Classifier: Programming Language :: Python :: 3.14
37
+ Requires-Python: >=3.12
38
+ Requires-Dist: pydantic<3,>=2.12.0
39
+ Requires-Dist: typing-extensions>=4.4
40
+ Description-Content-Type: text/markdown
41
+
42
+ # SSZ Specs
43
+
44
+ Simple Serialize (SSZ) is a serialization and hashing scheme used by Ethereum.
45
+ This project is a reference implementation written in Python which serves as the
46
+ official specifications.
47
+
48
+ ## Development
49
+
50
+ This project uses [`uv`](https://docs.astral.sh/uv/) and
51
+ [`just`](https://just.systems/).
52
+
53
+ ```bash
54
+ just check # Run code quality checks
55
+ just fix # Run code quality fixers
56
+ just test # Run unit tests
57
+ just fill # Generate reference tests
58
+ ```
59
+
60
+ ## Tests
61
+
62
+ This project generates JSON reference tests, included in each release, that SSZ
63
+ implementations can run to ensure compliance with the specifications.
64
+
65
+ ## Releases
66
+
67
+ Each release ships the `eth-ssz-specs` package on PyPI and the reference tests on the
68
+ [releases page](https://github.com/leanEthereum/ssz-specs/releases), both built from
69
+ the tagged commit.
70
+
71
+ ```bash
72
+ pip install eth-ssz-specs
73
+ ```
74
+
75
+ ```bash
76
+ TAG=v0.1.0
77
+ curl -sSLO "https://github.com/leanEthereum/ssz-specs/releases/download/$TAG/ssz-test-vectors-$TAG.tar.gz"
78
+ curl -sSLO "https://github.com/leanEthereum/ssz-specs/releases/download/$TAG/ssz-test-vectors-$TAG.tar.gz.sha256"
79
+ sha256sum --check "ssz-test-vectors-$TAG.tar.gz.sha256"
80
+ tar -xzf "ssz-test-vectors-$TAG.tar.gz" # extracts fixtures/
81
+ ```
82
+
83
+ ## Types
84
+
85
+ ### `Boolean`
86
+
87
+ A true or false value.
88
+
89
+ ```python
90
+ Boolean(True)
91
+ ```
92
+
93
+ ### `Bit`
94
+
95
+ A zero or one value.
96
+
97
+ ```python
98
+ Bit(1)
99
+ ```
100
+
101
+ ### `Byte`
102
+
103
+ Eight bits of opaque data.
104
+
105
+ ```python
106
+ Byte(0xFF)
107
+ ```
108
+
109
+ ### `Uint8`
110
+
111
+ An 8-bit unsigned integer.
112
+
113
+ ```python
114
+ Uint8(0xFF)
115
+ ```
116
+
117
+ ### `Uint16`
118
+
119
+ A 16-bit unsigned integer.
120
+
121
+ ```python
122
+ Uint16(0xFFFF)
123
+ ```
124
+
125
+ ### `Uint32`
126
+
127
+ A 32-bit unsigned integer.
128
+
129
+ ```python
130
+ Uint32(0xFFFFFFFF)
131
+ ```
132
+
133
+ ### `Uint64`
134
+
135
+ A 64-bit unsigned integer.
136
+
137
+ ```python
138
+ Uint64(0xFFFFFFFFFFFFFFFF)
139
+ ```
140
+
141
+ ### `Uint128`
142
+
143
+ A 128-bit unsigned integer.
144
+
145
+ ```python
146
+ Uint128(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)
147
+ ```
148
+
149
+ ### `Uint256`
150
+
151
+ A 256-bit unsigned integer.
152
+
153
+ ```python
154
+ Uint256(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)
155
+ ```
156
+
157
+ ### `Vector`
158
+
159
+ A fixed number of elements.
160
+
161
+ ```python
162
+ class Color(Vector[Uint8]):
163
+ LENGTH = 3
164
+
165
+ Color(data=[255, 128, 0])
166
+ ```
167
+
168
+ ### `List`
169
+
170
+ A variable number of elements up to a limit.
171
+
172
+ ```python
173
+ class Scores(List[Uint64]):
174
+ LIMIT = 8
175
+
176
+ Scores(data=[10, 20, 30])
177
+ ```
178
+
179
+ ### `ByteVector`
180
+
181
+ A fixed number of bytes.
182
+
183
+ ```python
184
+ class Serial(ByteVector):
185
+ LENGTH = 4
186
+
187
+ Serial(b"\x01\x02\x03\x04")
188
+ ```
189
+
190
+ ### `ByteList`
191
+
192
+ A variable number of bytes up to a limit.
193
+
194
+ ```python
195
+ class Message(ByteList):
196
+ LIMIT = 32
197
+
198
+ Message(data=b"hello")
199
+ ```
200
+
201
+ ### `BitVector`
202
+
203
+ A fixed number of bits.
204
+
205
+ ```python
206
+ class Weekdays(BitVector):
207
+ LENGTH = 7
208
+
209
+ Weekdays(data=[1, 0, 0, 1, 0, 1, 0])
210
+ ```
211
+
212
+ ### `BitList`
213
+
214
+ A variable number of bits up to a limit.
215
+
216
+ ```python
217
+ class Answers(BitList):
218
+ LIMIT = 20
219
+
220
+ Answers(data=[1, 0, 1])
221
+ ```
222
+
223
+ ### `ProgressiveList`
224
+
225
+ A variable number of elements with no limit.
226
+
227
+ ```python
228
+ class Temperatures(ProgressiveList[Uint16]):
229
+ pass
230
+
231
+ Temperatures(data=[20, 21, 19])
232
+ ```
233
+
234
+ ### `ProgressiveBitList`
235
+
236
+ A variable number of bits with no limit.
237
+
238
+ ```python
239
+ ProgressiveBitList(data=[1, 0, 1])
240
+ ```
241
+
242
+ ### `Container`
243
+
244
+ A fixed set of named fields.
245
+
246
+ ```python
247
+ class Point(Container):
248
+ x: Uint64
249
+ y: Uint64
250
+
251
+ Point(x=1, y=2)
252
+ ```
253
+
254
+ ### `ProgressiveContainer`
255
+
256
+ Named fields that keep their positions as the set changes.
257
+
258
+ ```python
259
+ class Square(ProgressiveContainer):
260
+ ACTIVE_FIELDS = active_fields(width=3, gaps=(1,))
261
+
262
+ side: Uint16 # position 0
263
+ color: Uint8 # position 2
264
+
265
+ Square(side=0x1234, color=0x42)
266
+ ```
267
+
268
+ ### `CompatibleUnion`
269
+
270
+ A choice between options that share one tree shape.
271
+
272
+ ```python
273
+ class Shape(CompatibleUnion):
274
+ OPTIONS = {1: Square, 2: Circle}
275
+
276
+ Shape(selector=1, data=Square(side=0x1234, color=0x42))
277
+ ```
@@ -0,0 +1,17 @@
1
+ ssz/__init__.py,sha256=GNyR-JMAOVW32wIFhEMSSLd9hFtB_SnVeYvisEF4-JE,2606
2
+ ssz/base.py,sha256=SfSWgUILQ0ykHm3kuBGumxA1j0T--Gpicbix1TdFzuk,535
3
+ ssz/bitfields.py,sha256=PPWF58iyO9AQd1j9VYo13-NDugtSnxY5SKmqU0b-Lis,21778
4
+ ssz/boolean.py,sha256=d6Z3yH-_ANDBcoL54zewHkg3csMa2xYC__5e4bsqW4A,8926
5
+ ssz/byte_arrays.py,sha256=BO4kZghk2s4v4RIFeSUp6bVGZZSAnPlNFSwTuDaw8ac,16360
6
+ ssz/collections.py,sha256=B0gQQu5-W9m0cBIYunSc-Gi4MKyvZ9fURYKkMbnDyOM,30739
7
+ ssz/container.py,sha256=WljEQJGutLqW9_LwEXwGZ3UMzHOWABSPWjLQax7FyLs,16198
8
+ ssz/exceptions.py,sha256=fwdY4_HsENMDz8cx7g9308AgurjEd4zsJbg9CZjxgAw,5222
9
+ ssz/merkleization.py,sha256=JhkQLtFjLutqzQaj-S2EUoLrk38uWTUDGnOA1IY5teo,22648
10
+ ssz/proofs.py,sha256=fDGCcHkA8pP-wgFqJrCWp6DnPLPsIzp2yTV41RKvoKs,23377
11
+ ssz/ssz_base.py,sha256=TsBJdnTOq9hT7Z2O2_BY8XS6rnWLBL87Ye-8PHIfU7A,15921
12
+ ssz/uint.py,sha256=CppS_JeP8IMeUpulcrWVuQnvplfKQFqVCyTYfLSPrjU,16327
13
+ ssz/union.py,sha256=9w0rrRokUaMoe4jqdtWxOL-gHJRp67-aYCP5OK7D5Ro,17461
14
+ eth_ssz_specs-0.0.1.dev1.dist-info/METADATA,sha256=ULu62WTqjFfQgugVeWPchViIhbUde7NT-d_ziAegZLs,5808
15
+ eth_ssz_specs-0.0.1.dev1.dist-info/WHEEL,sha256=lCkmxWfQsSc9CfIClYeavTdQeEX2toPqufh9gI35EQA,87
16
+ eth_ssz_specs-0.0.1.dev1.dist-info/licenses/LICENSE,sha256=z8-I9X573urgoCse0cLjILiOv-Un_SW1I3t9yCnHYgw,1076
17
+ eth_ssz_specs-0.0.1.dev1.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.31.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Ethereum Foundation
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
ssz/__init__.py ADDED
@@ -0,0 +1,116 @@
1
+ """SSZ primitive types and (de)serialization for Ethereum."""
2
+
3
+ from ssz.bitfields import BitList, BitVector, ProgressiveBitList
4
+ from ssz.boolean import Bit, Boolean
5
+ from ssz.byte_arrays import (
6
+ ByteList,
7
+ ByteVector,
8
+ )
9
+ from ssz.collections import List, ProgressiveList, Vector
10
+ from ssz.container import Container, ProgressiveContainer, active_fields
11
+ from ssz.exceptions import (
12
+ SSZActiveFieldsError,
13
+ SSZDefaultError,
14
+ SSZDefinitionError,
15
+ SSZError,
16
+ SSZFixedSizeError,
17
+ SSZLengthError,
18
+ SSZLimitError,
19
+ SSZRangeError,
20
+ SSZScopeError,
21
+ SSZSerializationError,
22
+ SSZTypeError,
23
+ SSZTypeMismatch,
24
+ SSZUnionOptionsError,
25
+ SSZValueError,
26
+ )
27
+ from ssz.merkleization import ZERO_ROOT, Chunk, Root
28
+ from ssz.proofs import (
29
+ ACTIVE_FIELDS_KEY,
30
+ LENGTH_KEY,
31
+ SELECTOR_KEY,
32
+ calculate_merkle_root,
33
+ calculate_multi_merkle_root,
34
+ chunk_count,
35
+ chunk_position,
36
+ element_type,
37
+ get_branch_indices,
38
+ get_generalized_index,
39
+ get_helper_indices,
40
+ get_path_indices,
41
+ gindex_bit,
42
+ gindex_child,
43
+ gindex_concat,
44
+ gindex_length,
45
+ gindex_parent,
46
+ gindex_sibling,
47
+ item_length,
48
+ verify_merkle_multiproof,
49
+ verify_merkle_proof,
50
+ )
51
+ from ssz.ssz_base import SSZType
52
+ from ssz.uint import Byte, Uint8, Uint16, Uint32, Uint64, Uint128, Uint256
53
+ from ssz.union import CompatibleUnion
54
+
55
+ __all__ = [
56
+ "ACTIVE_FIELDS_KEY",
57
+ "Bit",
58
+ "BitList",
59
+ "BitVector",
60
+ "Boolean",
61
+ "Byte",
62
+ "ByteList",
63
+ "ByteVector",
64
+ "Chunk",
65
+ "CompatibleUnion",
66
+ "Container",
67
+ "LENGTH_KEY",
68
+ "List",
69
+ "ProgressiveBitList",
70
+ "ProgressiveContainer",
71
+ "ProgressiveList",
72
+ "Root",
73
+ "SELECTOR_KEY",
74
+ "SSZActiveFieldsError",
75
+ "SSZDefaultError",
76
+ "SSZDefinitionError",
77
+ "SSZError",
78
+ "SSZFixedSizeError",
79
+ "SSZLengthError",
80
+ "SSZLimitError",
81
+ "SSZRangeError",
82
+ "SSZScopeError",
83
+ "SSZSerializationError",
84
+ "SSZType",
85
+ "SSZTypeError",
86
+ "SSZTypeMismatch",
87
+ "SSZUnionOptionsError",
88
+ "SSZValueError",
89
+ "Uint128",
90
+ "Uint16",
91
+ "Uint256",
92
+ "Uint32",
93
+ "Uint64",
94
+ "Uint8",
95
+ "Vector",
96
+ "ZERO_ROOT",
97
+ "active_fields",
98
+ "calculate_merkle_root",
99
+ "calculate_multi_merkle_root",
100
+ "chunk_count",
101
+ "chunk_position",
102
+ "element_type",
103
+ "get_branch_indices",
104
+ "get_generalized_index",
105
+ "get_helper_indices",
106
+ "get_path_indices",
107
+ "gindex_bit",
108
+ "gindex_child",
109
+ "gindex_concat",
110
+ "gindex_length",
111
+ "gindex_parent",
112
+ "gindex_sibling",
113
+ "item_length",
114
+ "verify_merkle_multiproof",
115
+ "verify_merkle_proof",
116
+ ]
ssz/base.py ADDED
@@ -0,0 +1,21 @@
1
+ """Reusable, strict base model for SSZ types."""
2
+
3
+ from pydantic import BaseModel, ConfigDict
4
+
5
+
6
+ class StrictBaseModel(BaseModel):
7
+ """
8
+ Immutable, strict base model for all SSZ types.
9
+
10
+ - Frozen: attribute assignment after construction raises
11
+ - Extra forbidden: unknown fields rejected at construction
12
+ - Strict: no implicit type coercion
13
+ """
14
+
15
+ model_config = ConfigDict(
16
+ validate_default=True,
17
+ arbitrary_types_allowed=True,
18
+ extra="forbid",
19
+ frozen=True,
20
+ strict=True,
21
+ )