/ synthesizer / program / src / function / bytes.rs
bytes.rs
  1  // Copyright (c) 2025 ADnet Contributors
  2  // This file is part of the AlphaVM 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 FunctionCore<N> {
 19      /// Reads the function from a buffer.
 20      #[inline]
 21      fn read_le<R: Read>(mut reader: R) -> IoResult<Self> {
 22          // Read the 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 a function: 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 instructions.
 36          let num_instructions = u32::read_le(&mut reader)?;
 37          if num_instructions > u32::try_from(N::MAX_INSTRUCTIONS).map_err(error)? {
 38              return Err(error(format!("Failed to deserialize a function: too many instructions ({num_instructions})")));
 39          }
 40          let mut instructions = Vec::with_capacity(num_instructions as usize);
 41          for _ in 0..num_instructions {
 42              instructions.push(Instruction::read_le(&mut reader)?);
 43          }
 44  
 45          // Read the outputs.
 46          let num_outputs = u16::read_le(&mut reader)?;
 47          if num_outputs > u16::try_from(N::MAX_OUTPUTS).map_err(error)? {
 48              return Err(error(format!("Failed to deserialize a function: too many outputs ({num_outputs})")));
 49          }
 50          let mut outputs = Vec::with_capacity(num_outputs as usize);
 51          for _ in 0..num_outputs {
 52              outputs.push(Output::read_le(&mut reader)?);
 53          }
 54  
 55          // Determine if there is a finalize scope.
 56          let variant = u8::read_le(&mut reader)?;
 57          let finalize = match variant {
 58              0 => None,
 59              1 => Some(FinalizeCore::read_le(&mut reader)?),
 60              _ => return Err(error(format!("Failed to deserialize a function: invalid finalize variant ({variant})"))),
 61          };
 62  
 63          // Initialize a new function.
 64          let mut function = Self::new(name);
 65          inputs.into_iter().try_for_each(|input| function.add_input(input)).map_err(error)?;
 66          instructions.into_iter().try_for_each(|instruction| function.add_instruction(instruction)).map_err(error)?;
 67          outputs.into_iter().try_for_each(|output| function.add_output(output)).map_err(error)?;
 68          finalize.map(|finalize| function.add_finalize(finalize));
 69  
 70          Ok(function)
 71      }
 72  }
 73  
 74  impl<N: Network> ToBytes for FunctionCore<N> {
 75      /// Writes the function to a buffer.
 76      #[inline]
 77      fn write_le<W: Write>(&self, mut writer: W) -> IoResult<()> {
 78          // Write the function name.
 79          self.name.write_le(&mut writer)?;
 80  
 81          // Write the number of inputs for the function.
 82          let num_inputs = self.inputs.len();
 83          match num_inputs <= N::MAX_INPUTS {
 84              true => u16::try_from(num_inputs).map_err(error)?.write_le(&mut writer)?,
 85              false => return Err(error(format!("Failed to write {num_inputs} inputs as bytes"))),
 86          }
 87  
 88          // Write the inputs.
 89          for input in self.inputs.iter() {
 90              input.write_le(&mut writer)?;
 91          }
 92  
 93          // Write the number of instructions for the function.
 94          let num_instructions = self.instructions.len();
 95          match num_instructions <= N::MAX_INSTRUCTIONS {
 96              true => u32::try_from(num_instructions).map_err(error)?.write_le(&mut writer)?,
 97              false => return Err(error(format!("Failed to write {num_instructions} instructions as bytes"))),
 98          }
 99  
100          // Write the instructions.
101          for instruction in self.instructions.iter() {
102              instruction.write_le(&mut writer)?;
103          }
104  
105          // Write the number of outputs for the function.
106          let num_outputs = self.outputs.len();
107          match num_outputs <= N::MAX_OUTPUTS {
108              true => u16::try_from(num_outputs).map_err(error)?.write_le(&mut writer)?,
109              false => return Err(error(format!("Failed to write {num_outputs} outputs as bytes"))),
110          }
111  
112          // Write the outputs.
113          for output in self.outputs.iter() {
114              output.write_le(&mut writer)?;
115          }
116  
117          // If the finalize scope exists, write it.
118          match &self.finalize_logic {
119              None => 0u8.write_le(&mut writer)?,
120              Some(logic) => {
121                  1u8.write_le(&mut writer)?;
122                  // Write the finalize scope logic.
123                  logic.write_le(&mut writer)?;
124              }
125          }
126  
127          Ok(())
128      }
129  }
130  
131  #[cfg(test)]
132  mod tests {
133      use super::*;
134      use crate::Function;
135      use console::network::MainnetV0;
136  
137      type CurrentNetwork = MainnetV0;
138  
139      #[test]
140      fn test_function_bytes() -> Result<()> {
141          let function_string = r"
142  function main:
143      input r0 as field.public;
144      input r1 as field.private;
145      add r0 r1 into r2;
146      add r0 r1 into r3;
147      add r0 r1 into r4;
148      add r0 r1 into r5;
149      add r0 r1 into r6;
150      add r0 r1 into r7;
151      add r0 r1 into r8;
152      add r0 r1 into r9;
153      add r0 r1 into r10;
154      add r0 r1 into r11;
155      output r11 as field.private;";
156  
157          let expected = Function::<CurrentNetwork>::from_str(function_string)?;
158          let expected_bytes = expected.to_bytes_le()?;
159          println!("String size: {:?}, Bytecode size: {:?}", function_string.len(), expected_bytes.len());
160  
161          let candidate = Function::<CurrentNetwork>::from_bytes_le(&expected_bytes)?;
162          assert_eq!(expected.to_string(), candidate.to_string());
163          assert_eq!(expected_bytes, candidate.to_bytes_le()?);
164          Ok(())
165      }
166  }