snarkvm_circuit_program/data/literal/
from_bits.rs

1// Copyright (c) 2019-2025 Provable Inc.
2// This file is part of the snarkVM library.
3
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at:
7
8// http://www.apache.org/licenses/LICENSE-2.0
9
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15
16use super::*;
17
18impl<A: Aleo> Literal<A> {
19    /// Initializes a new literal from a list of little-endian bits *without* trailing zeros.
20    pub fn from_bits_le(variant: &U8<A>, bits_le: &[Boolean<A>]) -> Self {
21        let literal = bits_le;
22        match *variant.eject_value() {
23            0 => Literal::Address(Address::from_bits_le(literal)),
24            1 => Literal::Boolean(Boolean::from_bits_le(literal)),
25            2 => Literal::Field(Field::from_bits_le(literal)),
26            3 => Literal::Group(Group::from_bits_le(literal)),
27            4 => Literal::I8(I8::from_bits_le(literal)),
28            5 => Literal::I16(I16::from_bits_le(literal)),
29            6 => Literal::I32(I32::from_bits_le(literal)),
30            7 => Literal::I64(I64::from_bits_le(literal)),
31            8 => Literal::I128(I128::from_bits_le(literal)),
32            9 => Literal::U8(U8::from_bits_le(literal)),
33            10 => Literal::U16(U16::from_bits_le(literal)),
34            11 => Literal::U32(U32::from_bits_le(literal)),
35            12 => Literal::U64(U64::from_bits_le(literal)),
36            13 => Literal::U128(U128::from_bits_le(literal)),
37            14 => Literal::Scalar(Scalar::from_bits_le(literal)),
38            15 => Literal::Signature(Box::new(Signature::from_bits_le(literal))),
39            16 => Literal::String(StringType::from_bits_le(literal)),
40            17.. => A::halt(format!("Failed to initialize literal variant {} from bits (LE)", variant.eject_value())),
41        }
42    }
43
44    /// Initializes a new literal from a list of big-endian bits *without* leading zeros.
45    pub fn from_bits_be(variant: &U8<A>, bits_be: &[Boolean<A>]) -> Self {
46        let literal = bits_be;
47        match *variant.eject_value() {
48            0 => Literal::Address(Address::from_bits_be(literal)),
49            1 => Literal::Boolean(Boolean::from_bits_be(literal)),
50            2 => Literal::Field(Field::from_bits_be(literal)),
51            3 => Literal::Group(Group::from_bits_be(literal)),
52            4 => Literal::I8(I8::from_bits_be(literal)),
53            5 => Literal::I16(I16::from_bits_be(literal)),
54            6 => Literal::I32(I32::from_bits_be(literal)),
55            7 => Literal::I64(I64::from_bits_be(literal)),
56            8 => Literal::I128(I128::from_bits_be(literal)),
57            9 => Literal::U8(U8::from_bits_be(literal)),
58            10 => Literal::U16(U16::from_bits_be(literal)),
59            11 => Literal::U32(U32::from_bits_be(literal)),
60            12 => Literal::U64(U64::from_bits_be(literal)),
61            13 => Literal::U128(U128::from_bits_be(literal)),
62            14 => Literal::Scalar(Scalar::from_bits_be(literal)),
63            15 => Literal::Signature(Box::new(Signature::from_bits_be(literal))),
64            16 => Literal::String(StringType::from_bits_be(literal)),
65            17.. => A::halt(format!("Failed to initialize literal variant {} from bits (BE))", variant.eject_value())),
66        }
67    }
68}
69
70#[cfg(test)]
71mod tests {
72    use super::*;
73    use crate::Circuit;
74    use console::{TestRng, Uniform};
75
76    const ITERATIONS: u32 = 1000;
77
78    fn check_serialization(expected: Literal<Circuit>) {
79        // Success cases.
80        assert_eq!(
81            expected.eject_value(),
82            Literal::from_bits_le(&expected.variant(), &expected.to_bits_le()).eject_value()
83        );
84        assert_eq!(
85            expected.eject_value(),
86            Literal::from_bits_be(&expected.variant(), &expected.to_bits_be()).eject_value()
87        );
88
89        // // Failure cases.
90        // assert!(std::panic::catch_unwind(|| Literal::from_bits_le(&expected.variant(), &expected.to_bits_be()).eject_value()).is_err());
91        // Circuit::reset();
92        // assert!(std::panic::catch_unwind(|| Literal::from_bits_be(&expected.variant(), &expected.to_bits_le()).eject_value()).is_err());
93        Circuit::reset();
94    }
95
96    fn run_serialization_test(mode: Mode) {
97        let rng = &mut TestRng::default();
98
99        for _ in 0..ITERATIONS {
100            // Address
101            check_serialization(Literal::<Circuit>::Address(Address::new(mode, console::Address::rand(rng))));
102            // Boolean
103            check_serialization(Literal::<Circuit>::Boolean(Boolean::new(mode, Uniform::rand(rng))));
104            // Field
105            check_serialization(Literal::<Circuit>::Field(Field::new(mode, Uniform::rand(rng))));
106            // Group
107            check_serialization(Literal::<Circuit>::Group(Group::new(mode, Uniform::rand(rng))));
108            // I8
109            check_serialization(Literal::<Circuit>::I8(I8::new(mode, Uniform::rand(rng))));
110            // I16
111            check_serialization(Literal::<Circuit>::I16(I16::new(mode, Uniform::rand(rng))));
112            // I32
113            check_serialization(Literal::<Circuit>::I32(I32::new(mode, Uniform::rand(rng))));
114            // I64
115            check_serialization(Literal::<Circuit>::I64(I64::new(mode, Uniform::rand(rng))));
116            // I128
117            check_serialization(Literal::<Circuit>::I128(I128::new(mode, Uniform::rand(rng))));
118            // U8
119            check_serialization(Literal::<Circuit>::U8(U8::new(mode, Uniform::rand(rng))));
120            // U16
121            check_serialization(Literal::<Circuit>::U16(U16::new(mode, Uniform::rand(rng))));
122            // U32
123            check_serialization(Literal::<Circuit>::U32(U32::new(mode, Uniform::rand(rng))));
124            // U64
125            check_serialization(Literal::<Circuit>::U64(U64::new(mode, Uniform::rand(rng))));
126            // U128
127            check_serialization(Literal::<Circuit>::U128(U128::new(mode, Uniform::rand(rng))));
128            // Scalar
129            check_serialization(Literal::<Circuit>::Scalar(Scalar::new(mode, Uniform::rand(rng))));
130            // Signature
131            check_serialization(Literal::new(mode, console::Literal::sample(LiteralType::Signature, rng)));
132            // String
133            // Sample a random string. Take 1/4th to ensure we fit for all code points.
134            let string = rng.next_string(Circuit::MAX_STRING_BYTES / 4, false);
135            check_serialization(Literal::<Circuit>::String(StringType::new(mode, console::StringType::new(&string))));
136        }
137    }
138
139    #[test]
140    fn test_serialization_constant() {
141        run_serialization_test(Mode::Constant);
142    }
143
144    #[test]
145    fn test_serialization_public() {
146        run_serialization_test(Mode::Public);
147    }
148
149    #[test]
150    fn test_serialization_private() {
151        run_serialization_test(Mode::Private);
152    }
153}