snarkvm_synthesizer_program/function/
bytes.rs1use super::*;
17
18impl<N: Network> FromBytes for FunctionCore<N> {
19 #[inline]
21 fn read_le<R: Read>(mut reader: R) -> IoResult<Self> {
22 let name = Identifier::<N>::read_le(&mut reader)?;
24
25 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 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).min(1024));
43 for _ in 0..num_instructions {
44 instructions.push(Instruction::read_le(&mut reader)?);
45 }
46
47 let num_outputs = u16::read_le(&mut reader)?;
49 if num_outputs > u16::try_from(N::MAX_OUTPUTS).map_err(error)? {
50 return Err(error(format!("Failed to deserialize a function: too many outputs ({num_outputs})")));
51 }
52 let mut outputs = Vec::with_capacity(num_outputs as usize);
53 for _ in 0..num_outputs {
54 outputs.push(Output::read_le(&mut reader)?);
55 }
56
57 let variant = u8::read_le(&mut reader)?;
59 let finalize = match variant {
60 0 => None,
61 1 => Some(FinalizeCore::read_le(&mut reader)?),
62 _ => return Err(error(format!("Failed to deserialize a function: invalid finalize variant ({variant})"))),
63 };
64
65 let mut function = Self::new(name);
67 inputs.into_iter().try_for_each(|input| function.add_input(input)).map_err(error)?;
68 instructions.into_iter().try_for_each(|instruction| function.add_instruction(instruction)).map_err(error)?;
69 outputs.into_iter().try_for_each(|output| function.add_output(output)).map_err(error)?;
70 finalize.map(|finalize| function.add_finalize(finalize));
71
72 Ok(function)
73 }
74}
75
76impl<N: Network> ToBytes for FunctionCore<N> {
77 #[inline]
79 fn write_le<W: Write>(&self, mut writer: W) -> IoResult<()> {
80 self.name.write_le(&mut writer)?;
82
83 let num_inputs = self.inputs.len();
85 match num_inputs <= N::MAX_INPUTS {
86 true => u16::try_from(num_inputs).map_err(error)?.write_le(&mut writer)?,
87 false => return Err(error(format!("Failed to write {num_inputs} inputs as bytes"))),
88 }
89
90 for input in self.inputs.iter() {
92 input.write_le(&mut writer)?;
93 }
94
95 let num_instructions = self.instructions.len();
97 match num_instructions <= N::MAX_INSTRUCTIONS {
98 true => u32::try_from(num_instructions).map_err(error)?.write_le(&mut writer)?,
99 false => return Err(error(format!("Failed to write {num_instructions} instructions as bytes"))),
100 }
101
102 for instruction in self.instructions.iter() {
104 instruction.write_le(&mut writer)?;
105 }
106
107 let num_outputs = self.outputs.len();
109 match num_outputs <= N::MAX_OUTPUTS {
110 true => u16::try_from(num_outputs).map_err(error)?.write_le(&mut writer)?,
111 false => return Err(error(format!("Failed to write {num_outputs} outputs as bytes"))),
112 }
113
114 for output in self.outputs.iter() {
116 output.write_le(&mut writer)?;
117 }
118
119 match &self.finalize_logic {
121 None => 0u8.write_le(&mut writer)?,
122 Some(logic) => {
123 1u8.write_le(&mut writer)?;
124 logic.write_le(&mut writer)?;
126 }
127 }
128
129 Ok(())
130 }
131}
132
133#[cfg(test)]
134mod tests {
135 use super::*;
136 use crate::Function;
137 use console::network::MainnetV0;
138
139 type CurrentNetwork = MainnetV0;
140
141 #[test]
142 fn test_function_bytes() -> Result<()> {
143 let function_string = r"
144function main:
145 input r0 as field.public;
146 input r1 as field.private;
147 add r0 r1 into r2;
148 add r0 r1 into r3;
149 add r0 r1 into r4;
150 add r0 r1 into r5;
151 add r0 r1 into r6;
152 add r0 r1 into r7;
153 add r0 r1 into r8;
154 add r0 r1 into r9;
155 add r0 r1 into r10;
156 add r0 r1 into r11;
157 output r11 as field.private;";
158
159 let expected = Function::<CurrentNetwork>::from_str(function_string)?;
160 let expected_bytes = expected.to_bytes_le()?;
161 println!("String size: {:?}, Bytecode size: {:?}", function_string.len(), expected_bytes.len());
162
163 let candidate = Function::<CurrentNetwork>::from_bytes_le(&expected_bytes)?;
164 assert_eq!(expected.to_string(), candidate.to_string());
165 assert_eq!(expected_bytes, candidate.to_bytes_le()?);
166 Ok(())
167 }
168
169 #[test]
178 fn test_declared_instruction_count_without_the_instructions_is_rejected() {
179 let mut bytes = Vec::new();
180 1u8.write_le(&mut bytes).unwrap();
182 b'f'.write_le(&mut bytes).unwrap();
183 0u16.write_le(&mut bytes).unwrap();
185 u32::try_from(CurrentNetwork::MAX_INSTRUCTIONS).unwrap().write_le(&mut bytes).unwrap();
187
188 assert_eq!(bytes.len(), 8, "the whole input is eight bytes");
189 assert!(
190 Function::<CurrentNetwork>::read_le(&bytes[..]).is_err(),
191 "a function declaring {} instructions and carrying none must be rejected",
192 CurrentNetwork::MAX_INSTRUCTIONS
193 );
194 }
195}