/ synthesizer / program / src / finalize / bytes.rs
bytes.rs
  1  // Copyright (c) 2019-2025 Alpha-Delta Network Inc.
  2  // This file is part of the deltavm 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  
 16  use super::*;
 17  
 18  impl<N: Network> FromBytes for FinalizeCore<N> {
 19      /// Reads the finalize from a buffer.
 20      #[inline]
 21      fn read_le<R: Read>(mut reader: R) -> IoResult<Self> {
 22          // Read the associated function name.
 23          let name = Identifier::<N>::read_le(&mut reader)?;
 24  
 25          // Read the inputs.
 26          let num_inputs = u16::read_le(&mut reader)?;
 27          if num_inputs > u16::try_from(N::MAX_INPUTS).map_err(error)? {
 28              return Err(error(format!("Failed to deserialize finalize: too many inputs ({num_inputs})")));
 29          }
 30          let mut inputs = Vec::with_capacity(num_inputs as usize);
 31          for _ in 0..num_inputs {
 32              inputs.push(Input::read_le(&mut reader)?);
 33          }
 34  
 35          // Read the commands.
 36          let num_commands = u16::read_le(&mut reader)?;
 37          if num_commands.is_zero() {
 38              return Err(error("Failed to deserialize finalize: needs at least one command".to_string()));
 39          }
 40          if num_commands > u16::try_from(N::MAX_COMMANDS).map_err(error)? {
 41              return Err(error(format!("Failed to deserialize finalize: too many commands ({num_commands})")));
 42          }
 43          let mut commands = Vec::with_capacity(num_commands as usize);
 44          for _ in 0..num_commands {
 45              commands.push(Command::read_le(&mut reader)?);
 46          }
 47  
 48          // Initialize a new finalize.
 49          let mut finalize = Self::new(name);
 50          inputs.into_iter().try_for_each(|input| finalize.add_input(input)).map_err(error)?;
 51          commands.into_iter().try_for_each(|command| finalize.add_command(command)).map_err(error)?;
 52  
 53          Ok(finalize)
 54      }
 55  }
 56  
 57  impl<N: Network> ToBytes for FinalizeCore<N> {
 58      /// Writes the finalize to a buffer.
 59      #[inline]
 60      fn write_le<W: Write>(&self, mut writer: W) -> IoResult<()> {
 61          // Write the associated function name.
 62          self.name.write_le(&mut writer)?;
 63  
 64          // Write the number of inputs for the finalize.
 65          let num_inputs = self.inputs.len();
 66          match num_inputs <= N::MAX_INPUTS {
 67              true => u16::try_from(num_inputs).map_err(error)?.write_le(&mut writer)?,
 68              false => return Err(error(format!("Failed to write {num_inputs} inputs as bytes"))),
 69          }
 70  
 71          // Write the inputs.
 72          for input in self.inputs.iter() {
 73              input.write_le(&mut writer)?;
 74          }
 75  
 76          // Write the number of commands for the finalize.
 77          let num_commands = self.commands.len();
 78          match 0 < num_commands && num_commands <= N::MAX_COMMANDS {
 79              true => u16::try_from(num_commands).map_err(error)?.write_le(&mut writer)?,
 80              false => return Err(error(format!("Failed to write {num_commands} commands as bytes"))),
 81          }
 82  
 83          // Write the commands.
 84          for command in self.commands.iter() {
 85              command.write_le(&mut writer)?;
 86          }
 87  
 88          Ok(())
 89      }
 90  }
 91  
 92  #[cfg(test)]
 93  mod tests {
 94      use super::*;
 95      use crate::Finalize;
 96      use console::network::MainnetV0;
 97  
 98      type CurrentNetwork = MainnetV0;
 99  
100      #[test]
101      fn test_finalize_bytes() -> Result<()> {
102          let finalize_string = r"
103  finalize main:
104      input r0 as field.public;
105      input r1 as field.public;
106      add r0 r1 into r2;
107      add r0 r1 into r3;
108      add r0 r1 into r4;
109      add r0 r1 into r5;
110      add r0 r1 into r6;
111      add r0 r1 into r7;
112      add r0 r1 into r8;
113      add r0 r1 into r9;
114      add r0 r1 into r10;
115      add r0 r1 into r11;
116      get accounts[r0] into r12;
117      get accounts[r1] into r13;";
118  
119          let expected = Finalize::<CurrentNetwork>::from_str(finalize_string)?;
120          let expected_bytes = expected.to_bytes_le()?;
121          println!("String size: {:?}, Bytecode size: {:?}", finalize_string.len(), expected_bytes.len());
122  
123          let candidate = Finalize::<CurrentNetwork>::from_bytes_le(&expected_bytes)?;
124          assert_eq!(expected.to_string(), candidate.to_string());
125          assert_eq!(expected_bytes, candidate.to_bytes_le()?);
126          Ok(())
127      }
128  }