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 Block<N> { 19 /// Read the block either with or without checking the data. 20 fn read_le_with_unchecked<R: Read>(mut reader: R, unchecked: bool) -> IoResult<Self> { 21 // Read the version. 22 let version = u8::read_le(&mut reader)?; 23 // Ensure the version is valid. 24 if version != 1 { 25 return Err(error("Invalid block version")); 26 } 27 28 // Read the block hash. 29 let block_hash: N::BlockHash = FromBytes::read_le_with_unchecked(&mut reader, unchecked)?; 30 // Read the previous block hash. 31 let previous_hash = FromBytes::read_le_with_unchecked(&mut reader, unchecked)?; 32 // Read the header. 33 let header = FromBytes::read_le_with_unchecked(&mut reader, unchecked)?; 34 35 // Read the authority. 36 let authority = Authority::<N>::read_le_with_unchecked(&mut reader, unchecked)?; 37 38 // Read the ratifications. 39 let ratifications = Ratifications::read_le_with_unchecked(&mut reader, unchecked)?; 40 41 // Read the solutions. 42 let solutions: Solutions<N> = FromBytes::read_le_with_unchecked(&mut reader, unchecked)?; 43 44 // Read the number of aborted solution IDs. 45 let num_aborted_solutions = u32::read_le(&mut reader)?; 46 // Ensure the number of aborted solutions IDs is within bounds (this is an early safety check). 47 if num_aborted_solutions as usize > Solutions::<N>::max_aborted_solutions().map_err(error)? { 48 return Err(error("Invalid number of aborted solutions IDs in the block")); 49 } 50 // Read the aborted solution IDs. 51 let mut aborted_solution_ids = Vec::with_capacity(num_aborted_solutions as usize); 52 for _ in 0..num_aborted_solutions { 53 aborted_solution_ids.push(FromBytes::read_le_with_unchecked(&mut reader, unchecked)?); 54 } 55 56 // Read the transactions. 57 let transactions = FromBytes::read_le_with_unchecked(&mut reader, unchecked)?; 58 59 // Read the number of aborted transaction IDs. 60 let num_aborted_transactions = u32::read_le(&mut reader)?; 61 // Ensure the number of aborted transaction IDs is within bounds (this is an early safety check). 62 if num_aborted_transactions as usize > Transactions::<N>::max_aborted_transactions().map_err(error)? { 63 return Err(error("Invalid number of aborted transaction IDs in the block")); 64 } 65 // Read the aborted transaction IDs. 66 let mut aborted_transaction_ids = Vec::with_capacity(num_aborted_transactions as usize); 67 for _ in 0..num_aborted_transactions { 68 aborted_transaction_ids.push(FromBytes::read_le_with_unchecked(&mut reader, unchecked)?); 69 } 70 71 // Construct the block. 72 let block = if unchecked { 73 Self::from_unchecked( 74 block_hash, 75 previous_hash, 76 header, 77 authority, 78 ratifications, 79 solutions, 80 aborted_solution_ids, 81 transactions, 82 aborted_transaction_ids, 83 ) 84 } else { 85 Self::from( 86 previous_hash, 87 header, 88 authority, 89 ratifications, 90 solutions, 91 aborted_solution_ids, 92 transactions, 93 aborted_transaction_ids, 94 ) 95 } 96 .map_err(error)?; 97 98 // Ensure the block hash matches. 99 match block_hash == block.hash() { 100 true => Ok(block), 101 false => Err(error("Mismatching block hash, possible data corruption")), 102 } 103 } 104 105 /// Reads the block from the buffer. 106 fn read_le<R: Read>(reader: R) -> IoResult<Self> { 107 Self::read_le_with_unchecked(reader, false) 108 } 109 110 // Reads the block from the buffer without any checks on the data. 111 fn read_le_unchecked<R: Read>(reader: R) -> IoResult<Self> { 112 Self::read_le_with_unchecked(reader, true) 113 } 114 } 115 116 impl<N: Network> ToBytes for Block<N> { 117 /// Writes the block to the buffer. 118 #[inline] 119 fn write_le<W: Write>(&self, mut writer: W) -> IoResult<()> { 120 // Write the version. 121 1u8.write_le(&mut writer)?; 122 123 // Write the block hash. 124 self.block_hash.write_le(&mut writer)?; 125 // Write the previous block hash. 126 self.previous_hash.write_le(&mut writer)?; 127 // Write the header. 128 self.header.write_le(&mut writer)?; 129 130 // Write the authority. 131 self.authority.write_le(&mut writer)?; 132 133 // Write the ratifications. 134 self.ratifications.write_le(&mut writer)?; 135 136 // Write the solutions. 137 self.solutions.write_le(&mut writer)?; 138 139 // Write the aborted solution IDs. 140 (u32::try_from(self.aborted_solution_ids.len()).map_err(error))?.write_le(&mut writer)?; 141 self.aborted_solution_ids.write_le(&mut writer)?; 142 143 // Write the transactions. 144 self.transactions.write_le(&mut writer)?; 145 146 // Write the aborted transaction IDs. 147 (u32::try_from(self.aborted_transaction_ids.len()).map_err(error))?.write_le(&mut writer)?; 148 self.aborted_transaction_ids.write_le(&mut writer) 149 } 150 } 151 152 #[cfg(test)] 153 mod tests { 154 use super::*; 155 use console::network::MainnetV0; 156 157 type CurrentNetwork = MainnetV0; 158 159 #[test] 160 fn test_bytes() -> Result<()> { 161 let rng = &mut TestRng::default(); 162 163 for expected in [crate::test_helpers::sample_genesis_block(rng)].into_iter() { 164 // Check the byte representation. 165 let expected_bytes = expected.to_bytes_le()?; 166 assert_eq!(expected, Block::read_le(&expected_bytes[..])?); 167 assert_eq!(expected, Block::read_le_unchecked(&expected_bytes[..])?); 168 } 169 Ok(()) 170 } 171 172 #[test] 173 fn test_genesis_bytes() -> Result<()> { 174 // Load the genesis block. 175 let genesis_block = Block::<CurrentNetwork>::read_le(CurrentNetwork::genesis_bytes()).unwrap(); 176 177 // Check the byte representation. 178 let expected_bytes = genesis_block.to_bytes_le()?; 179 assert_eq!(genesis_block, Block::read_le(&expected_bytes[..])?); 180 assert_eq!(genesis_block, Block::read_le_unchecked(&expected_bytes[..])?); 181 182 Ok(()) 183 } 184 185 #[test] 186 fn test_bincode() -> Result<()> { 187 // Load the genesis block. 188 let genesis_block = Block::<CurrentNetwork>::read_le(CurrentNetwork::genesis_bytes()).unwrap(); 189 190 let bincode_data = bincode::serialize(&genesis_block)?; 191 let block = bincode::deserialize(&bincode_data)?; 192 193 assert_eq!(genesis_block, block); 194 195 Ok(()) 196 } 197 }