• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

ergoplatform / sigma-rust / 8953175335

04 May 2024 08:51PM UTC coverage: 80.473% (+0.1%) from 80.331%
8953175335

Pull #736

github

web-flow
Merge 0fdf2d258 into 57a105462
Pull Request #736: Transaction Validation

165 of 228 new or added lines in 15 files covered. (72.37%)

8 existing lines in 2 files now uncovered.

10723 of 13325 relevant lines covered (80.47%)

3.29 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

83.28
/ergotree-ir/src/serialization/types.rs
1
use super::op_code::OpCode;
2
use super::sigma_byte_writer::SigmaByteWrite;
3
use super::SigmaSerializationError;
4
use crate::serialization::SigmaSerializeResult;
5
use crate::serialization::{
6
    sigma_byte_reader::SigmaByteRead, SigmaParsingError, SigmaSerializable,
7
};
8
use crate::types::stuple;
9
use crate::types::stype::SType;
10
use crate::types::stype_param;
11
use num_derive::FromPrimitive;
12
use num_traits::FromPrimitive;
13
use std::convert::TryInto;
14

15
#[allow(non_camel_case_types)]
16
#[allow(clippy::upper_case_acronyms)] // to differentiate from similarly named SType enum variants
17
#[derive(Copy, Clone, Debug, PartialEq, Eq, FromPrimitive)]
18
#[repr(u8)]
19
pub enum TypeCode {
20
    SBOOLEAN = 1,
21
    SBYTE = 2,
22
    SSHORT = 3,
23
    SINT = 4,
24
    SLONG = 5,
25
    SBIGINT = 6,
26
    SGROUP_ELEMENT = 7,
27
    SSIGMAPROP = 8,
28

29
    COLL = (TypeCode::MAX_PRIM_TYPECODE + 1) * TypeCode::COLLECTION_CONSTR_ID, // 12 * 1
30
    COLL_BOOL = TypeCode::COLL as u8 + TypeCode::SBOOLEAN as u8,               // 13
31
    COLL_BYTE = TypeCode::COLL as u8 + TypeCode::SBYTE as u8,                  // 14
32
    COLL_SHORT = TypeCode::COLL as u8 + TypeCode::SSHORT as u8,                // 15
33
    COLL_INT = TypeCode::COLL as u8 + TypeCode::SINT as u8,                    // 16
34
    COLL_LONG = TypeCode::COLL as u8 + TypeCode::SLONG as u8,                  // 17
35
    COLL_BIGINT = TypeCode::COLL as u8 + TypeCode::SBIGINT as u8,              // 18
36
    COLL_GROUP_ELEMENT = TypeCode::COLL as u8 + TypeCode::SGROUP_ELEMENT as u8, // 19
37
    COLL_SIGMAPROP = TypeCode::COLL as u8 + TypeCode::SSIGMAPROP as u8,        // 20
38

39
    NESTED_COLL_BOOL = TypeCode::NESTED_COLL + TypeCode::SBOOLEAN as u8, // 25
40
    NESTED_COLL_BYTE = TypeCode::NESTED_COLL + TypeCode::SBYTE as u8,    // 26
41
    NESTED_COLL_SHORT = TypeCode::NESTED_COLL + TypeCode::SSHORT as u8,  // 27
42
    NESTED_COLL_INT = TypeCode::NESTED_COLL + TypeCode::SINT as u8,      // 28
43
    NESTED_COLL_LONG = TypeCode::NESTED_COLL + TypeCode::SLONG as u8,    // 29
44
    NESTED_COLL_BIGINT = TypeCode::NESTED_COLL + TypeCode::SBIGINT as u8, // 30
45
    NESTED_COLL_GROUP_ELEMENT = TypeCode::NESTED_COLL + TypeCode::SGROUP_ELEMENT as u8, // 31
46
    NESTED_COLL_SIGMAPROP = TypeCode::NESTED_COLL + TypeCode::SSIGMAPROP as u8, // 32
47

48
    OPTION = (TypeCode::MAX_PRIM_TYPECODE + 1) * TypeCode::OPTION_CONSTR_ID, // 12 * 3 = 36
49
    OPTION_BOOL = TypeCode::OPTION as u8 + TypeCode::SBOOLEAN as u8,         // 37
50
    OPTION_BYTE = TypeCode::OPTION as u8 + TypeCode::SBYTE as u8,            // 38
51
    OPTION_SHORT = TypeCode::OPTION as u8 + TypeCode::SSHORT as u8,          // 39
52
    OPTION_INT = TypeCode::OPTION as u8 + TypeCode::SINT as u8,              // 40
53
    OPTION_LONG = TypeCode::OPTION as u8 + TypeCode::SLONG as u8,            // 41
54
    OPTION_BIGINT = TypeCode::OPTION as u8 + TypeCode::SBIGINT as u8,        // 42
55
    OPTION_GROUP_ELEMENT = TypeCode::OPTION as u8 + TypeCode::SGROUP_ELEMENT as u8, // 43
56
    OPTION_SIGMAPROP = TypeCode::OPTION as u8 + TypeCode::SSIGMAPROP as u8,  // 44
57

58
    OPTION_COLL_BOOL = TypeCode::OPTION_COLLECTION + TypeCode::SBOOLEAN as u8, // 49
59
    OPTION_COLL_BYTE = TypeCode::OPTION_COLLECTION + TypeCode::SBYTE as u8,    // 50
60
    OPTION_COLL_SHORT = TypeCode::OPTION_COLLECTION + TypeCode::SSHORT as u8,  // 51
61
    OPTION_COLL_INT = TypeCode::OPTION_COLLECTION + TypeCode::SINT as u8,      // 52
62
    OPTION_COLL_LONG = TypeCode::OPTION_COLLECTION + TypeCode::SLONG as u8,    // 53
63
    OPTION_COLL_BIGINT = TypeCode::OPTION_COLLECTION + TypeCode::SBIGINT as u8, // 54
64
    OPTION_COLL_GROUP_ELEMENT = TypeCode::OPTION_COLLECTION + TypeCode::SGROUP_ELEMENT as u8, // 55
65
    OPTION_COLL_SIGMAPROP = TypeCode::OPTION_COLLECTION + TypeCode::SSIGMAPROP as u8, // 56
66

67
    TUPLE_PAIR1 = (TypeCode::MAX_PRIM_TYPECODE + 1) * TypeCode::TUPLE_PAIR1_CONSTR_ID, // 12 * 5 = 60
68
    TUPLE_PAIR1_BOOL = TypeCode::TUPLE_PAIR1 as u8 + TypeCode::SBOOLEAN as u8,         // 61
69
    TUPLE_PAIR1_BYTE = TypeCode::TUPLE_PAIR1 as u8 + TypeCode::SBYTE as u8,            // 62
70
    TUPLE_PAIR1_SHORT = TypeCode::TUPLE_PAIR1 as u8 + TypeCode::SSHORT as u8,          // 63
71
    TUPLE_PAIR1_INT = TypeCode::TUPLE_PAIR1 as u8 + TypeCode::SINT as u8,              // 64
72
    TUPLE_PAIR1_LONG = TypeCode::TUPLE_PAIR1 as u8 + TypeCode::SLONG as u8,            // 65
73
    TUPLE_PAIR1_BIGINT = TypeCode::TUPLE_PAIR1 as u8 + TypeCode::SBIGINT as u8,        // 66
74
    TUPLE_PAIR1_GROUP_ELEMENT = TypeCode::TUPLE_PAIR1 as u8 + TypeCode::SGROUP_ELEMENT as u8, // 67
75
    TUPLE_PAIR1_SIGMAPROP = TypeCode::TUPLE_PAIR1 as u8 + TypeCode::SSIGMAPROP as u8,  // 68
76

77
    TUPLE_TRIPLE = Self::TUPLE_PAIR2, // 72
78

79
    TUPLE_PAIR2_BOOL = TypeCode::TUPLE_PAIR2 + TypeCode::SBOOLEAN as u8, // 73
80
    TUPLE_PAIR2_BYTE = TypeCode::TUPLE_PAIR2 + TypeCode::SBYTE as u8,    // 74
81
    TUPLE_PAIR2_SHORT = TypeCode::TUPLE_PAIR2 + TypeCode::SSHORT as u8,  // 75
82
    TUPLE_PAIR2_INT = TypeCode::TUPLE_PAIR2 + TypeCode::SINT as u8,      // 76
83
    TUPLE_PAIR2_LONG = TypeCode::TUPLE_PAIR2 + TypeCode::SLONG as u8,    // 77
84
    TUPLE_PAIR2_BIGINT = TypeCode::TUPLE_PAIR2 + TypeCode::SBIGINT as u8, // 78
85
    TUPLE_PAIR2_GROUP_ELEMENT = TypeCode::TUPLE_PAIR2 + TypeCode::SGROUP_ELEMENT as u8, // 79
86
    TUPLE_PAIR2_SIGMAPROP = TypeCode::TUPLE_PAIR2 + TypeCode::SSIGMAPROP as u8, // 80
87

88
    TUPLE_QUADRUPLE = Self::TUPLE_PAIR_SYMMETRIC, // 84
89

90
    TUPLE_PAIR_SYMMETRIC_BOOL = TypeCode::TUPLE_PAIR_SYMMETRIC + TypeCode::SBOOLEAN as u8, // 85
91
    TUPLE_PAIR_SYMMETRIC_BYTE = TypeCode::TUPLE_PAIR_SYMMETRIC + TypeCode::SBYTE as u8,    // 86
92
    TUPLE_PAIR_SYMMETRIC_SHORT = TypeCode::TUPLE_PAIR_SYMMETRIC + TypeCode::SSHORT as u8,  // 87
93
    TUPLE_PAIR_SYMMETRIC_INT = TypeCode::TUPLE_PAIR_SYMMETRIC + TypeCode::SINT as u8,      // 88
94
    TUPLE_PAIR_SYMMETRIC_LONG = TypeCode::TUPLE_PAIR_SYMMETRIC + TypeCode::SLONG as u8,    // 89
95
    TUPLE_PAIR_SYMMETRIC_BIGINT = TypeCode::TUPLE_PAIR_SYMMETRIC + TypeCode::SBIGINT as u8, // 90
96
    TUPLE_PAIR_SYMMETRIC_GROUP_ELEMENT =
97
        TypeCode::TUPLE_PAIR_SYMMETRIC + TypeCode::SGROUP_ELEMENT as u8, // 91
98
    TUPLE_PAIR_SYMMETRIC_SIGMAPROP = TypeCode::TUPLE_PAIR_SYMMETRIC + TypeCode::SSIGMAPROP as u8, // 92
99

100
    TUPLE = (TypeCode::MAX_PRIM_TYPECODE + 1) * 8, // 12 * 8 = 96
101

102
    SANY = 97,
103
    SUNIT = 98,
104
    SBOX = 99,
105
    SAVL_TREE = 100,
106
    SCONTEXT = 101,
107
    // SSTRING = 102,
108
    STYPE_VAR = 103,
109
    SHEADER = 104,
110
    SPRE_HEADER = 105,
111
    SGLOBAL = 106,
112
}
113

114
impl TypeCode {
115
    /// SFunc types occupy remaining space of byte values [FirstFuncType .. 255]
116
    #[allow(dead_code)]
117
    const FIRST_FUNC_TYPE: u8 = OpCode::LAST_DATA_TYPE.value();
118
    #[allow(dead_code)]
119
    const LAST_FUNC_TYPE: u8 = 255;
120

121
    /// Type code of the last valid prim type so that (1 to LastPrimTypeCode) is a range of valid codes.
122
    #[allow(dead_code)]
123
    const LAST_PRIM_TYPECODE: u8 = 8;
124

125
    /// Upper limit of the interval of valid type codes for primitive types
126
    const MAX_PRIM_TYPECODE: u8 = 11;
127

128
    const COLLECTION_CONSTR_ID: u8 = 1;
129

130
    const NESTED_COLLECTION_CONSTS_ID: u8 = 2;
131
    const NESTED_COLL: u8 =
132
        (TypeCode::MAX_PRIM_TYPECODE + 1) * TypeCode::NESTED_COLLECTION_CONSTS_ID; // 12 * 2 = 24
133

134
    const OPTION_CONSTR_ID: u8 = 3;
135
    const OPTION_COLLECTION_TYPE_CONSTR_ID: u8 = 4;
136
    const OPTION_COLLECTION: u8 =
137
        (TypeCode::MAX_PRIM_TYPECODE + 1) * TypeCode::OPTION_COLLECTION_TYPE_CONSTR_ID; // 12 * 4 = 48
138

139
    const TUPLE_PAIR1_CONSTR_ID: u8 = 5;
140

141
    const TUPLE_PAIR2_CONSTR_ID: u8 = 6;
142
    const TUPLE_PAIR2: u8 = (TypeCode::MAX_PRIM_TYPECODE + 1) * TypeCode::TUPLE_PAIR2_CONSTR_ID; // 12 * 6 = 72
143

144
    const TUPLE_PAIR_SYMMETRIC_TYPE_CONSTR_ID: u8 = 7;
145
    const TUPLE_PAIR_SYMMETRIC: u8 =
146
        (TypeCode::MAX_PRIM_TYPECODE + 1) * TypeCode::TUPLE_PAIR_SYMMETRIC_TYPE_CONSTR_ID; // 12 * 7 = 84
147

148
    /// Parse type code from byte
149
    pub(crate) fn parse(b: u8) -> Result<Self, SigmaParsingError> {
9✔
150
        match FromPrimitive::from_u8(b) {
5✔
151
            Some(t) => Ok(t),
9✔
152
            None => Err(SigmaParsingError::InvalidTypeCode(b)),
1✔
153
        }
154
    }
155

156
    pub(crate) const fn value(&self) -> u8 {
11✔
157
        *self as u8
10✔
158
    }
159
}
160

161
impl SigmaSerializable for TypeCode {
162
    fn sigma_serialize<W: SigmaByteWrite>(&self, w: &mut W) -> SigmaSerializeResult {
10✔
163
        w.put_u8(self.value())?;
10✔
164
        Ok(())
11✔
165
    }
166

167
    fn sigma_parse<R: SigmaByteRead>(r: &mut R) -> Result<Self, SigmaParsingError> {
9✔
168
        let b = r.get_u8()?;
13✔
169
        Self::parse(b)
9✔
170
    }
171
}
172

173
impl SType {
174
    /// Parse type from byte stream. This function should be used instead of
175
    /// `sigma_parse` when type code is already read for look-ahead
176
    pub(crate) fn parse_with_type_code<R: SigmaByteRead>(
13✔
177
        r: &mut R,
178
        c: TypeCode,
179
    ) -> Result<Self, SigmaParsingError> {
180
        use SType::*;
181
        Ok(match c {
18✔
182
            TypeCode::SBOOLEAN => SBoolean,
7✔
183
            TypeCode::SBYTE => SByte,
7✔
184
            TypeCode::SSHORT => SShort,
6✔
185
            TypeCode::SINT => SInt,
12✔
186
            TypeCode::SLONG => SLong,
10✔
187
            TypeCode::SBIGINT => SBigInt,
11✔
188
            TypeCode::SGROUP_ELEMENT => SGroupElement,
7✔
189
            TypeCode::SSIGMAPROP => SSigmaProp,
7✔
190

191
            TypeCode::COLL => SColl(SType::sigma_parse(r)?.into()),
4✔
192
            TypeCode::COLL_BOOL => SColl(SBoolean.into()),
6✔
193
            TypeCode::COLL_BYTE => SColl(SByte.into()),
8✔
194
            TypeCode::COLL_SHORT => SColl(SShort.into()),
6✔
195
            TypeCode::COLL_INT => SColl(SInt.into()),
6✔
196
            TypeCode::COLL_LONG => SColl(SLong.into()),
7✔
197
            TypeCode::COLL_BIGINT => SColl(SBigInt.into()),
6✔
198
            TypeCode::COLL_GROUP_ELEMENT => SColl(SGroupElement.into()),
6✔
199
            TypeCode::COLL_SIGMAPROP => SColl(SSigmaProp.into()),
6✔
200

201
            TypeCode::NESTED_COLL_BOOL => SColl(SColl(SBoolean.into()).into()),
1✔
202
            TypeCode::NESTED_COLL_BYTE => SColl(SColl(SByte.into()).into()),
6✔
UNCOV
203
            TypeCode::NESTED_COLL_SHORT => SColl(SColl(SShort.into()).into()),
×
204
            TypeCode::NESTED_COLL_INT => SColl(SColl(SInt.into()).into()),
1✔
205
            TypeCode::NESTED_COLL_LONG => SColl(SColl(SLong.into()).into()),
1✔
206
            TypeCode::NESTED_COLL_BIGINT => SColl(SColl(SBigInt.into()).into()),
1✔
207
            TypeCode::NESTED_COLL_GROUP_ELEMENT => SColl(SColl(SGroupElement.into()).into()),
1✔
208
            TypeCode::NESTED_COLL_SIGMAPROP => SColl(SColl(SSigmaProp.into()).into()),
1✔
209

210
            TypeCode::OPTION => SOption(SType::sigma_parse(r)?.into()),
2✔
211
            TypeCode::OPTION_BOOL => SOption(SBoolean.into()),
1✔
212
            TypeCode::OPTION_BYTE => SOption(SByte.into()),
1✔
213
            TypeCode::OPTION_SHORT => SOption(SShort.into()),
1✔
214
            TypeCode::OPTION_INT => SOption(SInt.into()),
1✔
215
            TypeCode::OPTION_LONG => SOption(SLong.into()),
1✔
216
            TypeCode::OPTION_BIGINT => SOption(SBigInt.into()),
1✔
217
            TypeCode::OPTION_GROUP_ELEMENT => SOption(SGroupElement.into()),
1✔
218
            TypeCode::OPTION_SIGMAPROP => SOption(SSigmaProp.into()),
1✔
219

UNCOV
220
            TypeCode::OPTION_COLL_BOOL => SOption(SColl(SBoolean.into()).into()),
×
221
            TypeCode::OPTION_COLL_BYTE => SOption(SColl(SByte.into()).into()),
×
222
            TypeCode::OPTION_COLL_SHORT => SOption(SColl(SShort.into()).into()),
1✔
223
            TypeCode::OPTION_COLL_INT => SOption(SColl(SInt.into()).into()),
×
UNCOV
224
            TypeCode::OPTION_COLL_LONG => SOption(SColl(SLong.into()).into()),
×
225
            TypeCode::OPTION_COLL_BIGINT => SOption(SColl(SBigInt.into()).into()),
1✔
226
            TypeCode::OPTION_COLL_GROUP_ELEMENT => SOption(SColl(SGroupElement.into()).into()),
1✔
227
            TypeCode::OPTION_COLL_SIGMAPROP => SOption(SColl(SSigmaProp.into()).into()),
1✔
228

229
            TypeCode::TUPLE_PAIR1 => STuple(stuple::STuple::pair(
12✔
230
                SType::sigma_parse(r)?,
12✔
231
                SType::sigma_parse(r)?,
12✔
232
            )),
233
            TypeCode::TUPLE_PAIR1_BOOL => {
×
234
                STuple(stuple::STuple::pair(SBoolean, SType::sigma_parse(r)?))
6✔
235
            }
236
            TypeCode::TUPLE_PAIR1_BYTE => {
×
237
                STuple(stuple::STuple::pair(SByte, SType::sigma_parse(r)?))
6✔
238
            }
239
            TypeCode::TUPLE_PAIR1_SHORT => {
×
240
                STuple(stuple::STuple::pair(SShort, SType::sigma_parse(r)?))
6✔
241
            }
242
            TypeCode::TUPLE_PAIR1_INT => STuple(stuple::STuple::pair(SInt, SType::sigma_parse(r)?)),
6✔
243
            TypeCode::TUPLE_PAIR1_LONG => {
×
244
                STuple(stuple::STuple::pair(SLong, SType::sigma_parse(r)?))
7✔
245
            }
246
            TypeCode::TUPLE_PAIR1_BIGINT => {
×
247
                STuple(stuple::STuple::pair(SBigInt, SType::sigma_parse(r)?))
7✔
248
            }
249
            TypeCode::TUPLE_PAIR1_GROUP_ELEMENT => {
×
250
                STuple(stuple::STuple::pair(SGroupElement, SType::sigma_parse(r)?))
6✔
251
            }
252
            TypeCode::TUPLE_PAIR1_SIGMAPROP => {
×
253
                STuple(stuple::STuple::pair(SSigmaProp, SType::sigma_parse(r)?))
5✔
254
            }
255

256
            TypeCode::TUPLE_TRIPLE => STuple(stuple::STuple::triple(
12✔
257
                SType::sigma_parse(r)?,
12✔
258
                SType::sigma_parse(r)?,
12✔
259
                SType::sigma_parse(r)?,
12✔
260
            )),
261

262
            TypeCode::TUPLE_PAIR2_BOOL => {
×
263
                STuple(stuple::STuple::pair(SType::sigma_parse(r)?, SBoolean))
10✔
264
            }
265
            TypeCode::TUPLE_PAIR2_BYTE => {
×
266
                STuple(stuple::STuple::pair(SType::sigma_parse(r)?, SByte))
11✔
267
            }
268
            TypeCode::TUPLE_PAIR2_SHORT => {
×
269
                STuple(stuple::STuple::pair(SType::sigma_parse(r)?, SShort))
10✔
270
            }
271
            TypeCode::TUPLE_PAIR2_INT => STuple(stuple::STuple::pair(SType::sigma_parse(r)?, SInt)),
10✔
272
            TypeCode::TUPLE_PAIR2_LONG => {
×
273
                STuple(stuple::STuple::pair(SType::sigma_parse(r)?, SLong))
12✔
274
            }
275
            TypeCode::TUPLE_PAIR2_BIGINT => {
×
276
                STuple(stuple::STuple::pair(SType::sigma_parse(r)?, SBigInt))
8✔
277
            }
278
            TypeCode::TUPLE_PAIR2_GROUP_ELEMENT => {
×
279
                STuple(stuple::STuple::pair(SType::sigma_parse(r)?, SGroupElement))
10✔
280
            }
281
            TypeCode::TUPLE_PAIR2_SIGMAPROP => {
×
282
                STuple(stuple::STuple::pair(SType::sigma_parse(r)?, SSigmaProp))
10✔
283
            }
284

285
            TypeCode::TUPLE_QUADRUPLE => STuple(stuple::STuple::quadruple(
12✔
286
                SType::sigma_parse(r)?,
12✔
287
                SType::sigma_parse(r)?,
12✔
288
                SType::sigma_parse(r)?,
12✔
289
                SType::sigma_parse(r)?,
12✔
290
            )),
291

292
            TypeCode::TUPLE_PAIR_SYMMETRIC_BOOL => STuple(stuple::STuple::pair(SBoolean, SBoolean)),
3✔
293
            TypeCode::TUPLE_PAIR_SYMMETRIC_BYTE => STuple(stuple::STuple::pair(SByte, SByte)),
3✔
294
            TypeCode::TUPLE_PAIR_SYMMETRIC_SHORT => STuple(stuple::STuple::pair(SShort, SShort)),
×
295
            TypeCode::TUPLE_PAIR_SYMMETRIC_INT => STuple(stuple::STuple::pair(SInt, SInt)),
7✔
296
            TypeCode::TUPLE_PAIR_SYMMETRIC_LONG => STuple(stuple::STuple::pair(SLong, SLong)),
4✔
297
            TypeCode::TUPLE_PAIR_SYMMETRIC_BIGINT => STuple(stuple::STuple::pair(SBigInt, SBigInt)),
3✔
298
            TypeCode::TUPLE_PAIR_SYMMETRIC_GROUP_ELEMENT => {
×
299
                STuple(stuple::STuple::pair(SGroupElement, SGroupElement))
4✔
300
            }
301
            TypeCode::TUPLE_PAIR_SYMMETRIC_SIGMAPROP => {
×
302
                STuple(stuple::STuple::pair(SSigmaProp, SSigmaProp))
5✔
303
            }
304

305
            TypeCode::TUPLE => {
×
306
                let len = r.get_u8()?;
2✔
307
                let mut items = Vec::with_capacity(len as usize);
1✔
308
                for _ in 0..len {
2✔
309
                    items.push(SType::sigma_parse(r)?);
2✔
310
                }
311
                SType::STuple(
1✔
312
                    items
2✔
313
                        .try_into()
×
314
                        .map_err(|_| SigmaParsingError::TupleItemsOutOfBounds(len as usize))?,
1✔
315
                )
316
            }
317

318
            TypeCode::SANY => SAny,
2✔
319
            TypeCode::SUNIT => SUnit,
1✔
320
            TypeCode::SBOX => SBox,
5✔
321
            TypeCode::SAVL_TREE => SAvlTree,
2✔
322
            TypeCode::SCONTEXT => SContext,
1✔
323
            TypeCode::STYPE_VAR => STypeVar(stype_param::STypeVar::sigma_parse(r)?),
2✔
324
            TypeCode::SHEADER => SHeader,
1✔
325
            TypeCode::SPRE_HEADER => SPreHeader,
1✔
326
            TypeCode::SGLOBAL => SGlobal,
1✔
327
        })
328
    }
329
}
330

331
/// Each SType is serialized to array of bytes by:
332
/// - emitting typeCode of each node (see special case for collections below)
333
/// - then recursively serializing subtrees from left to right on each level
334
/// - for each collection of primitive type there is special type code to emit single byte instead of two bytes
335
/// Types code intervals
336
/// - (1 .. MaxPrimTypeCode)  // primitive types
337
/// - (CollectionTypeCode .. CollectionTypeCode + MaxPrimTypeCode) // collections of primitive types
338
/// - (MaxCollectionTypeCode ..)  // Other types
339
/// Collection of non-primitive type is serialized as (CollectionTypeCode, serialize(elementType))
340
impl SigmaSerializable for SType {
341
    fn sigma_serialize<W: SigmaByteWrite>(&self, w: &mut W) -> SigmaSerializeResult {
9✔
342
        // for reference see http://github.com/ScorexFoundation/sigmastate-interpreter/blob/25251c1313b0131835f92099f02cef8a5d932b5e/sigmastate/src/main/scala/sigmastate/serialization/TypeSerializer.scala#L25-L25
343
        use SType::*;
344
        match self {
10✔
345
            SType::SFunc(_) => Err(SigmaSerializationError::NotSupported(
×
346
                "SFunc serialization is no supported".to_string(),
×
347
            )),
348
            SType::SAny => TypeCode::SANY.sigma_serialize(w),
1✔
349
            SType::SUnit => TypeCode::SUNIT.sigma_serialize(w),
×
350
            SType::SBoolean => TypeCode::SBOOLEAN.sigma_serialize(w),
5✔
351
            SType::SByte => TypeCode::SBYTE.sigma_serialize(w),
5✔
352
            SType::SShort => TypeCode::SSHORT.sigma_serialize(w),
5✔
353
            SType::SInt => TypeCode::SINT.sigma_serialize(w),
9✔
354
            SType::SLong => TypeCode::SLONG.sigma_serialize(w),
9✔
355
            SType::SBigInt => TypeCode::SBIGINT.sigma_serialize(w),
9✔
356
            SType::SGroupElement => TypeCode::SGROUP_ELEMENT.sigma_serialize(w),
5✔
357
            SType::SSigmaProp => TypeCode::SSIGMAPROP.sigma_serialize(w),
5✔
358
            SType::SBox => TypeCode::SBOX.sigma_serialize(w),
3✔
359
            SType::SAvlTree => TypeCode::SAVL_TREE.sigma_serialize(w),
1✔
360
            SType::SContext => TypeCode::SCONTEXT.sigma_serialize(w),
1✔
361
            SType::SHeader => TypeCode::SHEADER.sigma_serialize(w),
1✔
362
            SType::SPreHeader => TypeCode::SPRE_HEADER.sigma_serialize(w),
1✔
363
            SType::SGlobal => TypeCode::SGLOBAL.sigma_serialize(w),
1✔
364
            SOption(elem_type) => match &**elem_type {
1✔
365
                SBoolean => TypeCode::OPTION_BOOL.sigma_serialize(w),
1✔
366
                SByte => TypeCode::OPTION_BYTE.sigma_serialize(w),
1✔
367
                SShort => TypeCode::OPTION_SHORT.sigma_serialize(w),
1✔
368
                SInt => TypeCode::OPTION_INT.sigma_serialize(w),
1✔
369
                SLong => TypeCode::OPTION_LONG.sigma_serialize(w),
1✔
370
                SBigInt => TypeCode::OPTION_BIGINT.sigma_serialize(w),
1✔
371
                SGroupElement => TypeCode::OPTION_GROUP_ELEMENT.sigma_serialize(w),
1✔
372
                SSigmaProp => TypeCode::OPTION_SIGMAPROP.sigma_serialize(w),
1✔
373
                SColl(inner_elem_type) => match &**inner_elem_type {
1✔
UNCOV
374
                    SBoolean => TypeCode::OPTION_COLL_BOOL.sigma_serialize(w),
×
375
                    SByte => TypeCode::OPTION_COLL_BYTE.sigma_serialize(w),
×
376
                    SShort => TypeCode::OPTION_COLL_SHORT.sigma_serialize(w),
1✔
377
                    SInt => TypeCode::OPTION_COLL_INT.sigma_serialize(w),
×
UNCOV
378
                    SLong => TypeCode::OPTION_COLL_LONG.sigma_serialize(w),
×
379
                    SBigInt => TypeCode::OPTION_COLL_BIGINT.sigma_serialize(w),
1✔
380
                    SGroupElement => TypeCode::OPTION_COLL_GROUP_ELEMENT.sigma_serialize(w),
1✔
381
                    SSigmaProp => TypeCode::OPTION_COLL_SIGMAPROP.sigma_serialize(w),
1✔
382
                    STypeVar(_) | SAny | SUnit | SBox | SAvlTree | SOption(_) | SColl(_)
×
383
                    | STuple(_) | SFunc(_) | SContext | SHeader | SPreHeader | SGlobal => {
×
384
                        // if not "embeddable" type fallback to generic Option type code following
385
                        // elem type code
386
                        TypeCode::OPTION.sigma_serialize(w)?;
1✔
387
                        elem_type.sigma_serialize(w)
1✔
388
                    }
389
                },
390
                STypeVar(_) | SAny | SUnit | SBox | SAvlTree | SOption(_) | STuple(_)
×
391
                | SFunc(_) | SContext | SHeader | SPreHeader | SGlobal => {
×
392
                    // if not "embeddable" type fallback to generic Option type code following
393
                    // elem type code
394
                    TypeCode::OPTION.sigma_serialize(w)?;
1✔
395
                    elem_type.sigma_serialize(w)
1✔
396
                }
397
            },
398

399
            SType::SColl(elem_type) => match &**elem_type {
6✔
400
                SBoolean => TypeCode::COLL_BOOL.sigma_serialize(w),
5✔
401
                SByte => TypeCode::COLL_BYTE.sigma_serialize(w),
5✔
402
                SShort => TypeCode::COLL_SHORT.sigma_serialize(w),
5✔
403
                SInt => TypeCode::COLL_INT.sigma_serialize(w),
5✔
404
                SLong => TypeCode::COLL_LONG.sigma_serialize(w),
5✔
405
                SBigInt => TypeCode::COLL_BIGINT.sigma_serialize(w),
5✔
406
                SGroupElement => TypeCode::COLL_GROUP_ELEMENT.sigma_serialize(w),
5✔
407
                SSigmaProp => TypeCode::COLL_SIGMAPROP.sigma_serialize(w),
5✔
408
                SColl(inner_elem_type) => match &**inner_elem_type {
5✔
409
                    SBoolean => TypeCode::NESTED_COLL_BOOL.sigma_serialize(w),
1✔
410
                    SByte => TypeCode::NESTED_COLL_BYTE.sigma_serialize(w),
5✔
UNCOV
411
                    SShort => TypeCode::NESTED_COLL_SHORT.sigma_serialize(w),
×
412
                    SInt => TypeCode::NESTED_COLL_INT.sigma_serialize(w),
1✔
413
                    SLong => TypeCode::NESTED_COLL_LONG.sigma_serialize(w),
1✔
414
                    SBigInt => TypeCode::NESTED_COLL_BIGINT.sigma_serialize(w),
1✔
415
                    SGroupElement => TypeCode::NESTED_COLL_GROUP_ELEMENT.sigma_serialize(w),
1✔
416
                    SSigmaProp => TypeCode::NESTED_COLL_SIGMAPROP.sigma_serialize(w),
1✔
417
                    STypeVar(_) | SAny | SUnit | SBox | SAvlTree | SOption(_) | SColl(_)
×
418
                    | STuple(_) | SFunc(_) | SContext | SHeader | SPreHeader | SGlobal => {
×
419
                        // if not "embeddable" type fallback to generic Coll type code following
420
                        // elem type code
421
                        TypeCode::COLL.sigma_serialize(w)?;
1✔
422
                        elem_type.sigma_serialize(w)
1✔
423
                    }
424
                },
425
                STypeVar(_) | SAny | SUnit | SBox | SAvlTree | SOption(_) | STuple(_)
×
426
                | SFunc(_) | SContext | SHeader | SPreHeader | SGlobal => {
×
427
                    // if not "embeddable" type fallback to generic Coll type code following
428
                    // elem type code
429
                    TypeCode::COLL.sigma_serialize(w)?;
1✔
430
                    elem_type.sigma_serialize(w)
1✔
431
                }
432
            },
433
            SType::STuple(stuple::STuple { items }) => match items.clone().as_slice() {
5✔
434
                [t1, t2] => match (t1, t2) {
20✔
435
                    (SBoolean, SBoolean) => TypeCode::TUPLE_PAIR_SYMMETRIC_BOOL.sigma_serialize(w),
6✔
436
                    (SByte, SByte) => TypeCode::TUPLE_PAIR_SYMMETRIC_BYTE.sigma_serialize(w),
6✔
437
                    (SInt, SInt) => TypeCode::TUPLE_PAIR_SYMMETRIC_INT.sigma_serialize(w),
8✔
438
                    (SLong, SLong) => TypeCode::TUPLE_PAIR_SYMMETRIC_LONG.sigma_serialize(w),
6✔
439
                    (SBigInt, SBigInt) => TypeCode::TUPLE_PAIR_SYMMETRIC_BIGINT.sigma_serialize(w),
6✔
440
                    (SGroupElement, SGroupElement) => {
×
441
                        TypeCode::TUPLE_PAIR_SYMMETRIC_GROUP_ELEMENT.sigma_serialize(w)
8✔
442
                    }
443
                    (SSigmaProp, SSigmaProp) => {
×
444
                        TypeCode::TUPLE_PAIR_SYMMETRIC_SIGMAPROP.sigma_serialize(w)
6✔
445
                    }
446

447
                    (SBoolean, t2) => {
5✔
448
                        TypeCode::TUPLE_PAIR1_BOOL.sigma_serialize(w)?;
10✔
449
                        t2.sigma_serialize(w)
10✔
450
                    }
451
                    (SByte, t2) => {
5✔
452
                        TypeCode::TUPLE_PAIR1_BYTE.sigma_serialize(w)?;
10✔
453
                        t2.sigma_serialize(w)
10✔
454
                    }
455
                    (SShort, t2) => {
5✔
456
                        TypeCode::TUPLE_PAIR1_SHORT.sigma_serialize(w)?;
10✔
457
                        t2.sigma_serialize(w)
10✔
458
                    }
459
                    (SInt, t2) => {
5✔
460
                        TypeCode::TUPLE_PAIR1_INT.sigma_serialize(w)?;
10✔
461
                        t2.sigma_serialize(w)
10✔
462
                    }
463
                    (SLong, t2) => {
4✔
464
                        TypeCode::TUPLE_PAIR1_LONG.sigma_serialize(w)?;
8✔
465
                        t2.sigma_serialize(w)
8✔
466
                    }
467
                    (SBigInt, t2) => {
6✔
468
                        TypeCode::TUPLE_PAIR1_BIGINT.sigma_serialize(w)?;
12✔
469
                        t2.sigma_serialize(w)
12✔
470
                    }
471
                    (SGroupElement, t2) => {
5✔
472
                        TypeCode::TUPLE_PAIR1_GROUP_ELEMENT.sigma_serialize(w)?;
10✔
473
                        t2.sigma_serialize(w)
10✔
474
                    }
475
                    (SSigmaProp, t2) => {
5✔
476
                        TypeCode::TUPLE_PAIR1_SIGMAPROP.sigma_serialize(w)?;
10✔
477
                        t2.sigma_serialize(w)
10✔
478
                    }
479

480
                    (t1, SBoolean) => {
4✔
481
                        TypeCode::TUPLE_PAIR2_BOOL.sigma_serialize(w)?;
8✔
482
                        t1.sigma_serialize(w)
8✔
483
                    }
484
                    (t1, SByte) => {
4✔
485
                        TypeCode::TUPLE_PAIR2_BYTE.sigma_serialize(w)?;
8✔
486
                        t1.sigma_serialize(w)
8✔
487
                    }
488
                    (t1, SShort) => {
4✔
489
                        TypeCode::TUPLE_PAIR2_SHORT.sigma_serialize(w)?;
8✔
490
                        t1.sigma_serialize(w)
8✔
491
                    }
492
                    (t1, SInt) => {
4✔
493
                        TypeCode::TUPLE_PAIR2_INT.sigma_serialize(w)?;
8✔
494
                        t1.sigma_serialize(w)
8✔
495
                    }
496
                    (t1, SLong) => {
4✔
497
                        TypeCode::TUPLE_PAIR2_LONG.sigma_serialize(w)?;
8✔
498
                        t1.sigma_serialize(w)
8✔
499
                    }
500
                    (t1, SBigInt) => {
3✔
501
                        TypeCode::TUPLE_PAIR2_BIGINT.sigma_serialize(w)?;
6✔
502
                        t1.sigma_serialize(w)
6✔
503
                    }
504
                    (t1, SGroupElement) => {
4✔
505
                        TypeCode::TUPLE_PAIR2_GROUP_ELEMENT.sigma_serialize(w)?;
8✔
506
                        t1.sigma_serialize(w)
8✔
507
                    }
508
                    (t1, SSigmaProp) => {
4✔
509
                        TypeCode::TUPLE_PAIR2_SIGMAPROP.sigma_serialize(w)?;
8✔
510
                        t1.sigma_serialize(w)
8✔
511
                    }
512
                    (
3✔
513
                        STypeVar(_) | SAny | SUnit | SBox | SAvlTree | SOption(_) | SColl(_)
×
514
                        | STuple(_) | SFunc(_) | SContext | SHeader | SPreHeader | SGlobal,
×
515
                        STypeVar(_) | SAny | SUnit | SBox | SAvlTree | SOption(_) | SColl(_)
×
516
                        | STuple(_) | SFunc(_) | SContext | SHeader | SPreHeader | SGlobal,
×
517
                    ) => {
×
518
                        // Pair of non-primitive types (`(SBox, SAvlTree)`, `((Int, Byte), (Boolean,Box))`, etc.)
519
                        TypeCode::TUPLE_PAIR1.sigma_serialize(w)?;
3✔
520
                        t1.sigma_serialize(w)?;
6✔
521
                        t2.sigma_serialize(w)
6✔
522
                    }
523
                },
524
                [t1, t2, t3] => {
10✔
525
                    TypeCode::TUPLE_TRIPLE.sigma_serialize(w)?;
10✔
526
                    t1.sigma_serialize(w)?;
11✔
527
                    t2.sigma_serialize(w)?;
11✔
528
                    t3.sigma_serialize(w)
11✔
529
                }
530
                [t1, t2, t3, t4] => {
10✔
531
                    TypeCode::TUPLE_QUADRUPLE.sigma_serialize(w)?;
10✔
532
                    t1.sigma_serialize(w)?;
10✔
533
                    t2.sigma_serialize(w)?;
10✔
534
                    t3.sigma_serialize(w)?;
10✔
535
                    t4.sigma_serialize(w)
10✔
536
                }
537
                _ => {
×
538
                    TypeCode::TUPLE.sigma_serialize(w)?;
2✔
539
                    w.put_u8(items.len() as u8)?;
2✔
540
                    items.iter().try_for_each(|i| i.sigma_serialize(w))
4✔
541
                }
542
            },
543

544
            SType::STypeVar(tv) => {
1✔
545
                TypeCode::STYPE_VAR.sigma_serialize(w)?;
10✔
546
                tv.sigma_serialize(w)
1✔
547
            }
548
        }
549
    }
550

551
    fn sigma_parse<R: SigmaByteRead>(r: &mut R) -> Result<Self, SigmaParsingError> {
10✔
552
        // for reference see http://github.com/ScorexFoundation/sigmastate-interpreter/blob/25251c1313b0131835f92099f02cef8a5d932b5e/sigmastate/src/main/scala/sigmastate/serialization/TypeSerializer.scala#L118-L118
553
        let c = TypeCode::sigma_parse(r)?;
8✔
554
        Self::parse_with_type_code(r, c)
10✔
555
    }
556
}
557

558
#[cfg(test)]
559
#[cfg(feature = "arbitrary")]
560
#[allow(clippy::panic)]
561
mod tests {
562
    use super::*;
563
    use crate::serialization::sigma_serialize_roundtrip;
564
    use proptest::prelude::*;
565

566
    proptest! {
567

568
        #[test]
569
        fn ser_roundtrip(v in any::<SType>()) {
570
            prop_assert_eq![sigma_serialize_roundtrip(&v), v];
571
        }
572
    }
573
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc