2
2
3
3
import asn1tools
4
4
import os .path
5
+ import sys
6
+
5
7
6
8
DIR = os .path .dirname (__file__ )
7
9
TEST_VECTORS_DIR = os .path .join (DIR , "../test-vectors" )
8
10
OUTPUT_NAME = "types"
9
- OUTPUT_DIR = os .path .join (TEST_VECTORS_DIR , "safrole" )
10
- SAFROLE_DIR = os .path .join (TEST_VECTORS_DIR , "jamtestvectors/safrole" )
11
- ARGS = ["validators-count" , "epoch-length" ]
12
- NS = "jam::test_vectors_safrole"
13
11
14
12
15
13
def flatten (aaa : list [list ]):
16
14
return [a for aa in aaa for a in aa ]
17
15
18
16
19
- def safrole_file (name : str ):
20
- return os .path .join (SAFROLE_DIR , name + ".asn" )
17
+ def asn_file (name : str ):
18
+ return os .path .join (TEST_VECTORS_DIR , "jamtestvectors" , name + ".asn" )
21
19
22
20
23
- def write (ext : str , lines : list [str ]):
24
- with open (os . path . join ( OUTPUT_DIR , OUTPUT_NAME + ext ) , "w" ) as f :
21
+ def write (path : str , lines : list [str ]):
22
+ with open (path , "w" ) as f :
25
23
f .writelines (line + "\n " for line in lines )
26
24
27
25
@@ -33,7 +31,7 @@ def c_struct(name: str, members):
33
31
return [
34
32
"struct %s {" % name ,
35
33
* ((" %s %s;" % (t , k ) for k , t in members )),
36
- " bool operator==(const %s &)const = default;" % name ,
34
+ " bool operator==(const %s &) const = default;" % name ,
37
35
"};" ,
38
36
]
39
37
@@ -49,19 +47,24 @@ def indent(lines):
49
47
50
48
51
49
class Type :
50
+ ignore_args = True
51
+
52
52
def __init__ (self , name : str ):
53
53
self .name = name
54
54
self .args : list [str ] = []
55
55
self .decl : list [str ] = []
56
56
self .scale : list [str ] = []
57
+ self .diff : list [str ] = []
57
58
58
59
def c_tdecl (self ):
59
- if not self .args :
60
+ if self . ignore_args or not self .args :
60
61
return []
61
- return ["template<%s>" % ", " .join ("uint32_t %s" % c_dash (x ) for x in self .args )]
62
+ return [
63
+ "template<%s>" % ", " .join ("uint32_t %s" % c_dash (x ) for x in self .args )
64
+ ]
62
65
63
66
def c_targs (self ):
64
- if not self .args :
67
+ if self . ignore_args or not self .args :
65
68
return ""
66
69
return "<%s>" % ", " .join (c_dash (x ) for x in self .args )
67
70
@@ -98,7 +101,7 @@ def deep(k: str):
98
101
return deps1 , deps2
99
102
100
103
101
- def asn_args (types : dict , deps2 : dict [str , set [str ]]):
104
+ def asn_args (ARGS : list [ str ], types : dict , deps2 : dict [str , set [str ]]):
102
105
args = {
103
106
k : {
104
107
s [0 ]
@@ -122,10 +125,11 @@ def c_scale(ty: Type, encode: list[str], decode: list[str]):
122
125
" return s;" ,
123
126
"}" ,
124
127
* ty .c_tdecl (),
125
- "inline scale::ScaleDecoderStream &operator>>(scale::ScaleDecoderStream &s, %s &v) {"
128
+ "scale::ScaleDecoderStream &operator>>(scale::ScaleDecoderStream &s, %s &) = delete;"
129
+ % ty .c_tname (),
130
+ "void decodeConfig(scale::ScaleDecoderStream &s, %s &v, const auto &config) {"
126
131
% ty .c_tname (),
127
132
* indent (decode ),
128
- " return s;" ,
129
133
"}" ,
130
134
]
131
135
@@ -134,13 +138,22 @@ def c_scale_struct(ty: Type, members: list[str]):
134
138
return c_scale (
135
139
ty ,
136
140
["s << v.%s;" % x for x in members ],
137
- ["s >> v.%s;" % x for x in members ],
141
+ ["decodeConfig(s, v.%s, config) ;" % x for x in members ],
138
142
)
139
143
140
144
141
- def parse_types (path : str ):
145
+ def c_diff (NS : str , ty : Type , lines : list [str ]):
146
+ return [
147
+ * ty .c_tdecl (),
148
+ "DIFF_F(%s::%s) {" % (NS , ty .c_tname ()),
149
+ * indent (lines ),
150
+ "}" ,
151
+ ]
152
+
153
+
154
+ def parse_types (NS : str , ARGS : list [str ], path : str , key : str ):
142
155
def asn_sequence_of (t ):
143
- (size ,) = t [ "size" ]
156
+ (size ,) = t . get ( "size" , ( None ,))
144
157
fixed = isinstance (size , (int , str ))
145
158
T = t ["element" ]["type" ]
146
159
assert T in asn_types
@@ -149,10 +162,14 @@ def asn_sequence_of(t):
149
162
return "qtils::BytesN<%s>" % c_dash (size )
150
163
return "qtils::Bytes"
151
164
if fixed :
165
+ if isinstance (size , str ):
166
+ return "jam::ConfigVec<%s, ConfigField::%s>" % (T , c_dash (size ))
152
167
return "std::array<%s, %s>" % (T , c_dash (size ))
153
168
return "std::vector<%s>" % T
154
169
155
170
def asn_member (t ):
171
+ if t ["type" ] == "OCTET STRING" :
172
+ t = dict (type = "SEQUENCE OF" , element = dict (type = "U8" ), size = t ["size" ])
156
173
if t ["type" ] == "SEQUENCE OF" :
157
174
r = asn_sequence_of (t )
158
175
elif t ["type" ] in asn_types :
@@ -163,10 +180,12 @@ def asn_member(t):
163
180
return "std::optional<%s>" % r
164
181
return r
165
182
166
- asn_types : dict = asn1tools .parse_files ([path ])["SafroleModule" ]["types" ]
183
+ asn_types : dict = asn1tools .parse_files ([path ])[key ]["types" ]
184
+ if "U8" not in asn_types :
185
+ asn_types ["U8" ] = dict (type = "INTEGER" )
167
186
deps1 , deps2 = asn_deps (asn_types )
168
187
types = {tname : Type (tname ) for tname in asn_types }
169
- for tname , args in asn_args (asn_types , deps2 ).items ():
188
+ for tname , args in asn_args (ARGS , asn_types , deps2 ).items ():
170
189
types [tname ].args = args
171
190
enum_trait = []
172
191
for tname , t in asn_types .items ():
@@ -177,7 +196,15 @@ def asn_member(t):
177
196
if tname == "U32" :
178
197
ty .decl = c_using (tname , "uint32_t" )
179
198
continue
199
+ if t ["type" ] == "NULL" :
200
+ t = dict (type = "SEQUENCE" , members = [])
180
201
if t ["type" ] == "CHOICE" :
202
+ if tname == "MmrPeak" :
203
+ assert [x ["name" ] for x in t ["members" ]] == ["none" , "some" ]
204
+ ty .decl = c_using (
205
+ tname , "std::optional<%s>" % asn_member (t ["members" ][1 ])
206
+ )
207
+ continue
181
208
ty .decl = c_struct (
182
209
tname ,
183
210
[
@@ -188,7 +215,7 @@ def asn_member(t):
188
215
)
189
216
],
190
217
)
191
- ty .scale . extend ( c_scale_struct (ty , ["v" ]) )
218
+ ty .scale += c_scale_struct (ty , ["v" ])
192
219
continue
193
220
if t ["type" ] == "ENUMERATED" :
194
221
values = [x [1 ] for x in t ["values" ]]
@@ -198,14 +225,13 @@ def asn_member(t):
198
225
* (" %s," % c_dash (x [0 ]) for x in t ["values" ]),
199
226
"};" ,
200
227
]
201
- ns = "%s::generic" % NS
202
228
enum_trait .append (
203
229
"SCALE_DEFINE_ENUM_VALUE_LIST(%s, %s, %s)"
204
230
% (
205
- ns ,
231
+ NS ,
206
232
ty .name ,
207
233
", " .join (
208
- "%s::%s::%s" % (ns , ty .name , c_dash (x [0 ])) for x in t ["values" ]
234
+ "%s::%s::%s" % (NS , ty .name , c_dash (x [0 ])) for x in t ["values" ]
209
235
),
210
236
)
211
237
)
@@ -214,8 +240,9 @@ def asn_member(t):
214
240
ty .decl = c_struct (
215
241
tname , [(c_dash (x ["name" ]), asn_member (x )) for x in t ["members" ]]
216
242
)
217
- ty .scale .extend (
218
- c_scale_struct (ty , [c_dash (x ["name" ]) for x in t ["members" ]])
243
+ ty .scale += c_scale_struct (ty , [c_dash (x ["name" ]) for x in t ["members" ]])
244
+ ty .diff = c_diff (
245
+ NS , ty , ["DIFF_M(%s);" % c_dash (x ["name" ]) for x in t ["members" ]]
219
246
)
220
247
continue
221
248
ty .decl = c_using (tname , asn_member (t ))
@@ -224,49 +251,94 @@ def asn_member(t):
224
251
return [types [k ] for k in order ], enum_trait
225
252
226
253
227
- def parse_const (path : str ):
228
- values : dict = asn1tools .parse_files ([path ])["SafroleConstants" ]["values" ]
254
+ def parse_const (path : str , key : str ):
255
+ values : dict = asn1tools .parse_files ([path ])[key ]["values" ]
229
256
assert all (v ["type" ] == "INTEGER" for v in values .values ())
230
257
return {k : v ["value" ] for k , v in values .items ()}
231
258
232
259
233
- types , enum_trait = parse_types (safrole_file ("safrole" ))
260
+ class Gen :
261
+ def __init__ (self , NS : str , ARGS : list [str ], path : str , key : str , configs ):
262
+ g_config = [
263
+ "struct ConfigField {" ,
264
+ * [" struct %s {};" % c_dash (a ) for a in ARGS ],
265
+ "};" ,
266
+ "struct Config {" ,
267
+ * [" uint32_t %s;" % c_dash (a ) for a in ARGS ],
268
+ * [
269
+ " auto get(ConfigField::%s) const { return %s; }"
270
+ % (c_dash (a ), c_dash (a ))
271
+ for a in ARGS
272
+ ],
273
+ "};" ,
274
+ ]
275
+ for name , args in configs :
276
+ g_config += [
277
+ "constexpr Config config_%s {" % name ,
278
+ * [" .%s = %s," % (c_dash (a ), args [a ]) for a in ARGS ],
279
+ "};" ,
280
+ ]
281
+ self .types , self .enum_trait = parse_types (NS , ARGS , path , key )
282
+ self .g_types = flatten ([* ty .c_tdecl (), * ty .decl ] for ty in self .types )
283
+ self .g_types = g_config + self .g_types
284
+ self .g_types = ["namespace %s {" % NS , * indent (self .g_types ), "}" ]
285
+ self .g_types = [
286
+ "#pragma once" ,
287
+ "#include <boost/variant.hpp>" ,
288
+ "#include <qtils/bytes.hpp>" ,
289
+ "#include <test-vectors/config-types.hpp>" ,
290
+ * self .g_types ,
291
+ ]
292
+ self .g_scale = flatten (ty .scale for ty in self .types )
293
+ self .g_scale = ["namespace %s {" % NS , * indent (self .g_scale ), "}" ]
294
+ self .g_scale = [
295
+ "#pragma once" ,
296
+ "#include <scale/scale.hpp>" ,
297
+ "#include <test-vectors/config-types-scale.hpp>" ,
298
+ '#include "%s.hpp"' % OUTPUT_NAME ,
299
+ * self .g_scale ,
300
+ * self .enum_trait ,
301
+ ]
302
+ self .g_diff = flatten (ty .diff for ty in self .types )
303
+ self .g_diff = [
304
+ "#pragma once" ,
305
+ "#include <test-vectors/diff.hpp>" ,
306
+ '#include "%s.hpp"' % OUTPUT_NAME ,
307
+ * self .g_diff ,
308
+ ]
309
+
310
+ def write (self , name : str ):
311
+ prefix = os .path .join (TEST_VECTORS_DIR , name , OUTPUT_NAME )
312
+ write (prefix + ".hpp" , self .g_types )
313
+ write (prefix + ".scale.hpp" , self .g_scale )
314
+ write (prefix + ".diff.hpp" , self .g_diff )
234
315
235
316
236
- g_types = flatten ([* ty .c_tdecl (), * ty .decl ] for ty in types )
237
- g_types = ["namespace %s::generic {" % NS , * indent (g_types ), "}" ]
238
- for name in ["tiny" , "full" ]:
239
- args = parse_const (safrole_file (name ))
240
- g_args = [
241
- * ["static constexpr uint32_t %s = %s;" % (c_dash (a ), args [a ]) for a in ARGS ],
242
- * flatten (
243
- c_using (ty .name , "%s::generic::%s" % (NS , ty .c_tname ())) for ty in types
244
- ),
245
- ]
246
- g_args = ["struct %s {" % name , * indent (g_args ), "};" ]
247
- g_types .extend (
317
+ def safrole ():
318
+ g = Gen (
319
+ "jam::test_vectors_safrole" ,
320
+ ["validators-count" , "epoch-length" ],
321
+ asn_file ("safrole/safrole" ),
322
+ "SafroleModule" ,
248
323
[
249
- "namespace %s {" % NS ,
250
- * indent (g_args ),
251
- "}" ,
252
- ]
324
+ (name , parse_const (asn_file ("safrole/%s" % name ), "Constants" ))
325
+ for name in ["tiny" , "full" ]
326
+ ],
327
+ )
328
+ g .write ("safrole" )
329
+
330
+
331
+ def history ():
332
+ g = Gen (
333
+ "jam::test_vectors_history" ,
334
+ [],
335
+ asn_file ("history/history" ),
336
+ "HistoryModule" ,
337
+ [],
253
338
)
254
- g_types = [
255
- "#pragma once" ,
256
- "#include <boost/variant.hpp>" ,
257
- "#include <qtils/bytes.hpp>" ,
258
- * g_types ,
259
- ]
260
-
261
- g_scale = flatten (ty .scale for ty in types )
262
- g_scale = ["namespace %s::generic {" % NS , * indent (g_scale ), "}" ]
263
- g_scale = [
264
- "#pragma once" ,
265
- "#include <scale/scale.hpp>" ,
266
- '#include "%s.hpp"' % OUTPUT_NAME ,
267
- * g_scale ,
268
- * enum_trait ,
269
- ]
270
-
271
- write (".hpp" , g_types )
272
- write (".scale.hpp" , g_scale )
339
+ g .write ("history" )
340
+
341
+
342
+ if __name__ == "__main__" :
343
+ for arg in sys .argv [1 :]:
344
+ dict (safrole = safrole , history = history )[arg ]()
0 commit comments