tezos_smart_rollup_encoding/
michelson.rs

1// SPDX-FileCopyrightText: 2022-2023 TriliTech <contact@trili.tech>
2// SPDX-FileCopyrightText: 2023 Nomadic Labs <contact@nomadic-labs.com>
3// SPDX-License-Identifier: MIT
4
5//! Definitions & tezos-encodings for *michelson* data.
6use nom::branch::alt;
7use nom::combinator::map;
8use std::fmt::Debug;
9use tezos_data_encoding::enc::{self, BinResult, BinWriter};
10use tezos_data_encoding::encoding::{Encoding, HasEncoding};
11use tezos_data_encoding::nom::{self as nom_read, NomReader, NomResult};
12use tezos_data_encoding::types::Zarith;
13
14mod micheline;
15#[cfg(feature = "alloc")]
16pub mod ticket;
17
18use super::contract::Contract;
19use micheline::{
20    bin_write_micheline_bytes, bin_write_micheline_int, bin_write_micheline_string,
21    bin_write_prim_1_arg_no_annots, bin_write_prim_2_args_no_annots,
22    bin_write_prim_no_args_no_annots, nom_read_micheline_bytes, nom_read_micheline_int,
23    nom_read_micheline_string, MichelinePrim1ArgNoAnnots, MichelinePrim2ArgsNoAnnots,
24    MichelinePrimNoArgsNoAnnots,
25};
26use v1_primitives as prim;
27
28pub mod v1_primitives {
29    //! Encoding of [michelson_v1_primitives].
30    //!
31    //! [michelson_v1_primitives]: <https://gitlab.com/tezos/tezos/-/blob/9028b797894a5d9db38bc61a20abb793c3778316/src/proto_alpha/lib_protocol/michelson_v1_primitives.ml>
32
33    /// `("Left", D_Left)` case tag.
34    pub const LEFT_TAG: u8 = 5;
35
36    /// `("None", D_None)` case tag.
37    pub const NONE_TAG: u8 = 6;
38
39    /// `("Pair", D_PAIR)` case tag.
40    pub const PAIR_TAG: u8 = 7;
41
42    /// `("Right", D_Right)` case tag.
43    pub const RIGHT_TAG: u8 = 8;
44
45    /// `("Some", D_Some)` case tag.
46    pub const SOME_TAG: u8 = 9;
47
48    /// unit encoding case tag.
49    pub const UNIT_TAG: u8 = 11;
50}
51
52/// marker trait for michelson encoding
53pub trait Michelson:
54    HasEncoding + BinWriter + NomReader + Debug + PartialEq + Eq
55{
56}
57
58impl Michelson for MichelsonUnit {}
59impl Michelson for MichelsonContract {}
60impl Michelson for MichelsonInt {}
61impl Michelson for MichelsonString {}
62impl Michelson for MichelsonBytes {}
63impl<Arg0, Arg1> Michelson for MichelsonPair<Arg0, Arg1>
64where
65    Arg0: Michelson,
66    Arg1: Michelson,
67{
68}
69impl<Arg0, Arg1> Michelson for MichelsonOr<Arg0, Arg1>
70where
71    Arg0: Michelson,
72    Arg1: Michelson,
73{
74}
75impl<Arg> Michelson for MichelsonOption<Arg> where Arg: Michelson {}
76
77/// Michelson *unit* encoding.
78#[derive(Debug, PartialEq, Eq)]
79pub struct MichelsonUnit;
80
81/// Michelson *contract* encoding.
82///
83#[derive(Debug, PartialEq, Eq)]
84pub struct MichelsonContract(pub Contract);
85
86/// Michelson *pair* encoding.
87#[derive(Debug, PartialEq, Eq)]
88pub struct MichelsonPair<Arg0, Arg1>(pub Arg0, pub Arg1)
89where
90    Arg0: Debug + PartialEq + Eq,
91    Arg1: Debug + PartialEq + Eq;
92
93/// Michelson *or* encoding.
94#[derive(Debug, PartialEq, Eq)]
95pub enum MichelsonOr<Arg0, Arg1>
96where
97    Arg0: Debug + PartialEq + Eq,
98    Arg1: Debug + PartialEq + Eq,
99{
100    /// The *Left* case
101    Left(Arg0),
102    /// The *Right* case
103    Right(Arg1),
104}
105
106/// Michelson *option* encoding.  #[derive(Debug, PartialEq, Eq)] pub
107#[derive(Debug, PartialEq, Eq)]
108pub struct MichelsonOption<Arg>(pub Option<Arg>)
109where
110    Arg: Debug + PartialEq + Eq;
111
112/// Michelson String encoding.
113#[derive(Debug, PartialEq, Eq)]
114pub struct MichelsonString(pub String);
115
116/// Michelson Bytes encoding.
117#[derive(Debug, PartialEq, Eq)]
118pub struct MichelsonBytes(pub Vec<u8>);
119
120/// Michelson Int encoding.
121#[derive(Debug, PartialEq, Eq)]
122pub struct MichelsonInt(pub Zarith);
123
124// ----------
125// CONVERSION
126// ----------
127impl From<String> for MichelsonString {
128    fn from(str: String) -> MichelsonString {
129        MichelsonString(str)
130    }
131}
132
133impl From<Vec<u8>> for MichelsonBytes {
134    fn from(b: Vec<u8>) -> MichelsonBytes {
135        MichelsonBytes(b)
136    }
137}
138
139impl From<Zarith> for MichelsonInt {
140    fn from(value: Zarith) -> MichelsonInt {
141        MichelsonInt(value)
142    }
143}
144
145impl From<i32> for MichelsonInt {
146    fn from(value: i32) -> MichelsonInt {
147        MichelsonInt(Zarith(value.into()))
148    }
149}
150
151// --------
152// ENCODING
153// --------
154impl HasEncoding for MichelsonContract {
155    fn encoding() -> Encoding {
156        Encoding::Custom
157    }
158}
159
160impl HasEncoding for MichelsonUnit {
161    fn encoding() -> Encoding {
162        Encoding::Custom
163    }
164}
165
166impl<Arg0, Arg1> HasEncoding for MichelsonPair<Arg0, Arg1>
167where
168    Arg0: Debug + PartialEq + Eq,
169    Arg1: Debug + PartialEq + Eq,
170{
171    fn encoding() -> Encoding {
172        Encoding::Custom
173    }
174}
175
176impl<Arg0, Arg1> HasEncoding for MichelsonOr<Arg0, Arg1>
177where
178    Arg0: Debug + PartialEq + Eq,
179    Arg1: Debug + PartialEq + Eq,
180{
181    fn encoding() -> Encoding {
182        Encoding::Custom
183    }
184}
185
186impl<Arg> HasEncoding for MichelsonOption<Arg>
187where
188    Arg: Debug + PartialEq + Eq,
189{
190    fn encoding() -> Encoding {
191        Encoding::Custom
192    }
193}
194
195impl HasEncoding for MichelsonString {
196    fn encoding() -> Encoding {
197        Encoding::Custom
198    }
199}
200
201impl HasEncoding for MichelsonBytes {
202    fn encoding() -> Encoding {
203        Encoding::Custom
204    }
205}
206
207impl HasEncoding for MichelsonInt {
208    fn encoding() -> Encoding {
209        Encoding::Custom
210    }
211}
212
213// --------
214// DECODING
215// --------
216impl NomReader for MichelsonContract {
217    fn nom_read(input: &[u8]) -> NomResult<Self> {
218        map(
219            nom_read_micheline_bytes(Contract::nom_read),
220            MichelsonContract,
221        )(input)
222    }
223}
224
225impl NomReader for MichelsonUnit {
226    fn nom_read(input: &[u8]) -> NomResult<Self> {
227        map(
228            MichelinePrimNoArgsNoAnnots::<{ prim::UNIT_TAG }>::nom_read,
229            |_prim| MichelsonUnit,
230        )(input)
231    }
232}
233
234impl<Arg0, Arg1> NomReader for MichelsonPair<Arg0, Arg1>
235where
236    Arg0: NomReader + Debug + PartialEq + Eq,
237    Arg1: NomReader + Debug + PartialEq + Eq,
238{
239    fn nom_read(input: &[u8]) -> NomResult<Self> {
240        map(
241            MichelinePrim2ArgsNoAnnots::<_, _, { prim::PAIR_TAG }>::nom_read,
242            Into::into,
243        )(input)
244    }
245}
246
247impl<Arg0, Arg1> NomReader for MichelsonOr<Arg0, Arg1>
248where
249    Arg0: NomReader + Debug + PartialEq + Eq,
250    Arg1: NomReader + Debug + PartialEq + Eq,
251{
252    fn nom_read(input: &[u8]) -> NomResult<Self> {
253        alt((
254            map(
255                MichelinePrim1ArgNoAnnots::<_, { prim::LEFT_TAG }>::nom_read,
256                |MichelinePrim1ArgNoAnnots { arg }| Self::Left(arg),
257            ),
258            map(
259                MichelinePrim1ArgNoAnnots::<_, { prim::RIGHT_TAG }>::nom_read,
260                |MichelinePrim1ArgNoAnnots { arg }| Self::Right(arg),
261            ),
262        ))(input)
263    }
264}
265
266impl<Arg> NomReader for MichelsonOption<Arg>
267where
268    Arg: NomReader + Debug + PartialEq + Eq,
269{
270    fn nom_read(input: &[u8]) -> NomResult<Self> {
271        alt((
272            map(
273                MichelinePrimNoArgsNoAnnots::<{ prim::NONE_TAG }>::nom_read,
274                |_prim| Self(None),
275            ),
276            map(
277                MichelinePrim1ArgNoAnnots::<_, { prim::SOME_TAG }>::nom_read,
278                |MichelinePrim1ArgNoAnnots { arg }| Self(Some(arg)),
279            ),
280        ))(input)
281    }
282}
283
284impl NomReader for MichelsonString {
285    fn nom_read(input: &[u8]) -> NomResult<Self> {
286        map(nom_read_micheline_string, MichelsonString)(input)
287    }
288}
289
290impl NomReader for MichelsonBytes {
291    fn nom_read(input: &[u8]) -> NomResult<Self> {
292        map(nom_read_micheline_bytes(nom_read::bytes), MichelsonBytes)(input)
293    }
294}
295
296impl NomReader for MichelsonInt {
297    fn nom_read(input: &[u8]) -> NomResult<Self> {
298        map(nom_read_micheline_int, MichelsonInt)(input)
299    }
300}
301
302// --------
303// ENCODING
304// --------
305impl BinWriter for MichelsonContract {
306    fn bin_write(&self, output: &mut Vec<u8>) -> BinResult {
307        bin_write_micheline_bytes(Contract::bin_write)(&self.0, output)
308    }
309}
310
311impl BinWriter for MichelsonUnit {
312    fn bin_write(&self, output: &mut Vec<u8>) -> BinResult {
313        bin_write_prim_no_args_no_annots(prim::UNIT_TAG, output)
314    }
315}
316
317impl<Arg0, Arg1> BinWriter for MichelsonPair<Arg0, Arg1>
318where
319    Arg0: BinWriter + Debug + PartialEq + Eq,
320    Arg1: BinWriter + Debug + PartialEq + Eq,
321{
322    fn bin_write(&self, output: &mut Vec<u8>) -> BinResult {
323        bin_write_prim_2_args_no_annots(prim::PAIR_TAG, &self.0, &self.1, output)
324    }
325}
326
327impl<Arg0, Arg1> From<MichelinePrim2ArgsNoAnnots<Arg0, Arg1, { prim::PAIR_TAG }>>
328    for MichelsonPair<Arg0, Arg1>
329where
330    Arg0: Debug + PartialEq + Eq,
331    Arg1: Debug + PartialEq + Eq,
332{
333    fn from(
334        micheline: MichelinePrim2ArgsNoAnnots<Arg0, Arg1, { prim::PAIR_TAG }>,
335    ) -> Self {
336        Self(micheline.arg1, micheline.arg2)
337    }
338}
339
340impl<Arg0, Arg1> From<MichelsonPair<Arg0, Arg1>>
341    for MichelinePrim2ArgsNoAnnots<Arg0, Arg1, { prim::PAIR_TAG }>
342where
343    Arg0: Debug + PartialEq + Eq,
344    Arg1: Debug + PartialEq + Eq,
345{
346    fn from(michelson: MichelsonPair<Arg0, Arg1>) -> Self {
347        Self {
348            arg1: michelson.0,
349            arg2: michelson.1,
350        }
351    }
352}
353
354impl<Arg0, Arg1> BinWriter for MichelsonOr<Arg0, Arg1>
355where
356    Arg0: BinWriter + Debug + PartialEq + Eq,
357    Arg1: BinWriter + Debug + PartialEq + Eq,
358{
359    fn bin_write(&self, output: &mut Vec<u8>) -> BinResult {
360        match self {
361            MichelsonOr::Left(left) => {
362                bin_write_prim_1_arg_no_annots(prim::LEFT_TAG, left, output)
363            }
364            MichelsonOr::Right(right) => {
365                bin_write_prim_1_arg_no_annots(prim::RIGHT_TAG, right, output)
366            }
367        }
368    }
369}
370
371impl<Arg0, Arg1> From<MichelinePrim1ArgNoAnnots<Arg0, { prim::LEFT_TAG }>>
372    for MichelsonOr<Arg0, Arg1>
373where
374    Arg0: Debug + PartialEq + Eq,
375    Arg1: Debug + PartialEq + Eq,
376{
377    fn from(micheline: MichelinePrim1ArgNoAnnots<Arg0, { prim::LEFT_TAG }>) -> Self {
378        Self::Left(micheline.arg)
379    }
380}
381
382impl<Arg0, Arg1> From<MichelinePrim1ArgNoAnnots<Arg1, { prim::RIGHT_TAG }>>
383    for MichelsonOr<Arg0, Arg1>
384where
385    Arg0: Debug + PartialEq + Eq,
386    Arg1: Debug + PartialEq + Eq,
387{
388    fn from(micheline: MichelinePrim1ArgNoAnnots<Arg1, { prim::RIGHT_TAG }>) -> Self {
389        Self::Right(micheline.arg)
390    }
391}
392
393impl<Arg> BinWriter for MichelsonOption<Arg>
394where
395    Arg: BinWriter + Debug + PartialEq + Eq,
396{
397    fn bin_write(&self, output: &mut Vec<u8>) -> BinResult {
398        match self {
399            MichelsonOption(None) => {
400                bin_write_prim_no_args_no_annots(prim::NONE_TAG, output)
401            }
402            MichelsonOption(Some(arg)) => {
403                bin_write_prim_1_arg_no_annots(prim::SOME_TAG, arg, output)
404            }
405        }
406    }
407}
408
409impl BinWriter for MichelsonString {
410    fn bin_write(&self, output: &mut Vec<u8>) -> BinResult {
411        bin_write_micheline_string(&self.0, output)
412    }
413}
414
415impl BinWriter for MichelsonBytes {
416    fn bin_write(&self, output: &mut Vec<u8>) -> BinResult {
417        bin_write_micheline_bytes(enc::bytes)(self.0.as_slice(), output)
418    }
419}
420
421impl BinWriter for MichelsonInt {
422    fn bin_write(&self, output: &mut Vec<u8>) -> BinResult {
423        bin_write_micheline_int(&self.0, output)
424    }
425}