/ ledger / block / src / 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 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  }