/ ledger / src / helpers / bft.rs
bft.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  #![allow(clippy::type_complexity)]
17  
18  use deltavm_ledger_block::{Ratify, Transaction};
19  use deltavm_ledger_narwhal::{Transmission, TransmissionID};
20  use deltavm_ledger_puzzle::Solution;
21  use console::network::Network;
22  
23  use anyhow::{Result, bail, ensure};
24  use std::collections::HashSet;
25  
26  /// Takes in an iterator of transmissions and returns a tuple of ratifications, solutions, and transactions.
27  ///
28  /// This method ensures each transmission ID corresponds to its given transmission.
29  /// This method guarantees that the output is 1) order-preserving, and 2) unique.
30  pub fn decouple_transmissions<N: Network>(
31      transmissions: impl Iterator<Item = (TransmissionID<N>, Transmission<N>)>,
32  ) -> Result<(Vec<Ratify<N>>, Vec<Solution<N>>, Vec<Transaction<N>>)> {
33      // Initialize a list for the ratifications.
34      let ratifications = Vec::new();
35      // Initialize a list for the solutions.
36      let mut solutions = Vec::new();
37      // Initialize a list for the transactions.
38      let mut transactions = Vec::new();
39  
40      // Initialize a set to ensure the transmissions are unique.
41      let mut unique = HashSet::new();
42  
43      // Iterate over the transmissions.
44      for (transmission_id, transmission) in transmissions {
45          // Ensure the transmission ID is unique.
46          ensure!(unique.insert(transmission_id), "Found a duplicate transmission ID - {transmission_id}");
47          // Deserialize and store the transmission.
48          match (transmission_id, transmission) {
49              (TransmissionID::Ratification, Transmission::Ratification) => (),
50              (TransmissionID::Solution(commitment, checksum), Transmission::Solution(solution)) => {
51                  // Ensure the transmission checksum corresponds to the solution.
52                  ensure!(checksum == solution.to_checksum::<N>()?, "Mismatching transmission checksum (solution)");
53                  // Deserialize the solution.
54                  let solution = solution.deserialize_blocking()?;
55                  // Ensure the transmission ID corresponds to the solution.
56                  ensure!(commitment == solution.id(), "Mismatching transmission ID (solution)");
57                  // Insert the solution into the list.
58                  solutions.push(solution);
59              }
60              (TransmissionID::Transaction(transaction_id, checksum), Transmission::Transaction(transaction)) => {
61                  // Ensure the transmission checksum corresponds to the transaction.
62                  ensure!(checksum == transaction.to_checksum::<N>()?, "Mismatching transmission checksum (transaction)");
63                  // Deserialize the transaction.
64                  let transaction = transaction.deserialize_blocking()?;
65                  // Ensure the transmission ID corresponds to the transaction.
66                  ensure!(transaction_id == transaction.id(), "Mismatching transmission ID (transaction)");
67                  // Insert the transaction into the list.
68                  transactions.push(transaction);
69              }
70              _ => bail!("Mismatching (transmission ID, transmission) entry"),
71          }
72      }
73      // Return the ratifications, solutions, and transactions.
74      Ok((ratifications, solutions, transactions))
75  }