/ console / program / src / data / literal / from_bits.rs
from_bits.rs
  1  // Copyright (c) 2025-2026 ACDC Network
  2  // This file is part of the alphavm library.
  3  //
  4  // Alpha Chain | Delta Chain Protocol
  5  // International Monetary Graphite.
  6  //
  7  // Derived from Aleo (https://aleo.org) and ProvableHQ (https://provable.com).
  8  // They built world-class ZK infrastructure. We installed the EASY button.
  9  // Their cryptography: elegant. Our modifications: bureaucracy-compatible.
 10  // Original brilliance: theirs. Robert's Rules: ours. Bugs: definitely ours.
 11  //
 12  // Original Aleo/ProvableHQ code subject to Apache 2.0 https://www.apache.org/licenses/LICENSE-2.0
 13  // All modifications and new work: CC0 1.0 Universal Public Domain Dedication.
 14  // No rights reserved. No permission required. No warranty. No refunds.
 15  //
 16  // https://creativecommons.org/publicdomain/zero/1.0/
 17  // SPDX-License-Identifier: CC0-1.0
 18  
 19  use super::*;
 20  
 21  impl<N: Network> Literal<N> {
 22      /// Initializes a new literal from a list of little-endian bits *without* trailing zeros.
 23      pub fn from_bits_le(variant: u8, bits_le: &[bool]) -> Result<Self> {
 24          let literal = bits_le;
 25          let literal = match variant {
 26              0 => Literal::Address(Address::new(Group::from_x_coordinate(Field::<N>::from_bits_le(literal)?)?)),
 27              1 => match bits_le.len() {
 28                  1 => Literal::Boolean(Boolean::new(literal[0])),
 29                  _ => bail!("Expected a boolean literal, but found a list of {} bits.", bits_le.len()),
 30              },
 31              2 => Literal::Field(Field::from_bits_le(literal)?),
 32              3 => Literal::Group(Group::from_bits_le(literal)?),
 33              4 => Literal::I8(I8::from_bits_le(literal)?),
 34              5 => Literal::I16(I16::from_bits_le(literal)?),
 35              6 => Literal::I32(I32::from_bits_le(literal)?),
 36              7 => Literal::I64(I64::from_bits_le(literal)?),
 37              8 => Literal::I128(I128::from_bits_le(literal)?),
 38              9 => Literal::U8(U8::from_bits_le(literal)?),
 39              10 => Literal::U16(U16::from_bits_le(literal)?),
 40              11 => Literal::U32(U32::from_bits_le(literal)?),
 41              12 => Literal::U64(U64::from_bits_le(literal)?),
 42              13 => Literal::U128(U128::from_bits_le(literal)?),
 43              14 => Literal::Scalar(Scalar::from_bits_le(literal)?),
 44              15 => Literal::Signature(Box::new(Signature::from_bits_le(literal)?)),
 45              16 => {
 46                  let buffer = Vec::<u8>::from_bits_le(literal)?;
 47                  match buffer.len() <= N::MAX_STRING_BYTES as usize {
 48                      true => {
 49                          let string = String::from_utf8(buffer).map_err(|e| error(format!("{e}")))?;
 50                          Self::String(StringType::new(&string))
 51                      }
 52                      false => bail!("String literal exceeds maximum length of {} bytes.", N::MAX_STRING_BYTES),
 53                  }
 54              }
 55              17.. => bail!("Failed to initialize literal variant {variant} from bits (LE)"),
 56          };
 57          Ok(literal)
 58      }
 59  
 60      /// Initializes a new literal from a list of big-endian bits *without* leading zeros.
 61      pub fn from_bits_be(variant: u8, bits_be: &[bool]) -> Result<Self> {
 62          let literal = bits_be;
 63          let literal = match variant {
 64              0 => Literal::Address(Address::new(Group::from_x_coordinate(Field::from_bits_be(literal)?)?)),
 65              1 => match bits_be.len() {
 66                  1 => Literal::Boolean(Boolean::new(literal[0])),
 67                  _ => bail!("Expected a boolean literal, but found a list of {} bits.", bits_be.len()),
 68              },
 69              2 => Literal::Field(Field::from_bits_be(literal)?),
 70              3 => Literal::Group(Group::from_bits_be(literal)?),
 71              4 => Literal::I8(I8::from_bits_be(literal)?),
 72              5 => Literal::I16(I16::from_bits_be(literal)?),
 73              6 => Literal::I32(I32::from_bits_be(literal)?),
 74              7 => Literal::I64(I64::from_bits_be(literal)?),
 75              8 => Literal::I128(I128::from_bits_be(literal)?),
 76              9 => Literal::U8(U8::from_bits_be(literal)?),
 77              10 => Literal::U16(U16::from_bits_be(literal)?),
 78              11 => Literal::U32(U32::from_bits_be(literal)?),
 79              12 => Literal::U64(U64::from_bits_be(literal)?),
 80              13 => Literal::U128(U128::from_bits_be(literal)?),
 81              14 => Literal::Scalar(Scalar::from_bits_be(literal)?),
 82              15 => Literal::Signature(Box::new(Signature::from_bits_be(literal)?)),
 83              16 => {
 84                  let buffer = Vec::<u8>::from_bits_be(literal)?;
 85                  match buffer.len() <= N::MAX_STRING_BYTES as usize {
 86                      true => {
 87                          let string = String::from_utf8(buffer).map_err(|e| error(format!("{e}")))?;
 88                          Self::String(StringType::new(&string))
 89                      }
 90                      false => bail!("String literal exceeds maximum length of {} bytes.", N::MAX_STRING_BYTES),
 91                  }
 92              }
 93              17.. => bail!("Failed to initialize literal variant {variant} from bits (BE)"),
 94          };
 95          Ok(literal)
 96      }
 97  }
 98  
 99  #[cfg(test)]
100  mod tests {
101      use super::*;
102      use alphavm_console_network::MainnetV0;
103  
104      type CurrentNetwork = MainnetV0;
105  
106      const ITERATIONS: u32 = 1000;
107  
108      fn check_serialization(expected: Literal<CurrentNetwork>) -> Result<()> {
109          println!("{expected}");
110          assert_eq!(expected, Literal::from_bits_le(expected.variant(), &expected.to_bits_le())?);
111          assert_eq!(expected, Literal::from_bits_be(expected.variant(), &expected.to_bits_be())?);
112          Ok(())
113      }
114  
115      #[test]
116      fn test_from_bits() -> Result<()> {
117          let rng = &mut TestRng::default();
118  
119          for _ in 0..ITERATIONS {
120              let private_key = alphavm_console_account::PrivateKey::<CurrentNetwork>::new(rng)?;
121  
122              // Address
123              check_serialization(Literal::<CurrentNetwork>::Address(Address::try_from(private_key)?))?;
124              // Boolean
125              check_serialization(Literal::<CurrentNetwork>::Boolean(Boolean::new(Uniform::rand(rng))))?;
126              // Field
127              check_serialization(Literal::<CurrentNetwork>::Field(Uniform::rand(rng)))?;
128              // Group
129              check_serialization(Literal::<CurrentNetwork>::Group(Uniform::rand(rng)))?;
130              // I8
131              check_serialization(Literal::<CurrentNetwork>::I8(I8::new(Uniform::rand(rng))))?;
132              // I16
133              check_serialization(Literal::<CurrentNetwork>::I16(I16::new(Uniform::rand(rng))))?;
134              // I32
135              check_serialization(Literal::<CurrentNetwork>::I32(I32::new(Uniform::rand(rng))))?;
136              // I64
137              check_serialization(Literal::<CurrentNetwork>::I64(I64::new(Uniform::rand(rng))))?;
138              // I128
139              check_serialization(Literal::<CurrentNetwork>::I128(I128::new(Uniform::rand(rng))))?;
140              // U8
141              check_serialization(Literal::<CurrentNetwork>::U8(U8::new(Uniform::rand(rng))))?;
142              // U16
143              check_serialization(Literal::<CurrentNetwork>::U16(U16::new(Uniform::rand(rng))))?;
144              // U32
145              check_serialization(Literal::<CurrentNetwork>::U32(U32::new(Uniform::rand(rng))))?;
146              // U64
147              check_serialization(Literal::<CurrentNetwork>::U64(U64::new(Uniform::rand(rng))))?;
148              // U128
149              check_serialization(Literal::<CurrentNetwork>::U128(U128::new(Uniform::rand(rng))))?;
150              // Scalar
151              check_serialization(Literal::<CurrentNetwork>::Scalar(Uniform::rand(rng)))?;
152              // Signature
153              check_serialization(Literal::sample(LiteralType::Signature, rng))?;
154              // String
155              // Sample a random string. Take 1/4th to ensure we fit for all code points.
156              let string = rng.next_string(CurrentNetwork::MAX_STRING_BYTES / 4, false);
157              check_serialization(Literal::<CurrentNetwork>::String(StringType::new(&string)))?;
158          }
159          Ok(())
160      }
161  }