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 }