use super::*;
impl<N: Network> Transactions<N> {
pub fn to_finalize_root(&self, ratified_finalize_operations: Vec<FinalizeOperation<N>>) -> Result<Field<N>> {
let ratified_finalize_id = *N::merkle_tree_bhp::<FINALIZE_ID_DEPTH>(
&ratified_finalize_operations.iter().map(ToBits::to_bits_le).collect::<Vec<_>>(),
)?
.root();
let leaves = self
.iter()
.map(|tx| tx.to_finalize_id().map(|id| id.to_bits_le()))
.chain(std::iter::once(Ok(ratified_finalize_id.to_bits_le())))
.collect::<Result<Vec<_>>>()?;
Ok(*N::merkle_tree_bhp::<FINALIZE_OPERATIONS_DEPTH>(&leaves)?.root())
}
}
impl<N: Network> Transactions<N> {
pub fn to_transactions_root(&self) -> Result<Field<N>> {
Ok(*self.to_tree()?.root())
}
pub fn to_path(&self, transaction_id: N::TransactionID) -> Result<TransactionsPath<N>> {
match self.transactions.get_index_of(&transaction_id) {
Some(transaction_index) => self.to_tree()?.prove(transaction_index, &transaction_id.to_bits_le()),
None => bail!("The transaction '{transaction_id}' is not in the block transactions"),
}
}
pub fn to_tree(&self) -> Result<TransactionsTree<N>> {
Self::transactions_tree(&self.transactions)
}
fn transactions_tree(
transactions: &IndexMap<N::TransactionID, ConfirmedTransaction<N>>,
) -> Result<TransactionsTree<N>> {
ensure!(
transactions.len() <= Self::MAX_TRANSACTIONS,
"Block cannot exceed {} transactions, found {}",
Self::MAX_TRANSACTIONS,
transactions.len()
);
let leaves = transactions.values().map(|transaction| transaction.id().to_bits_le());
N::merkle_tree_bhp::<TRANSACTIONS_DEPTH>(&leaves.collect::<Vec<_>>())
}
}
#[cfg(test)]
mod tests {
use super::*;
use console::network::MainnetV0;
type CurrentNetwork = MainnetV0;
#[test]
fn test_transactions_depth() {
assert_eq!(
2usize.pow(TRANSACTIONS_DEPTH as u32).checked_sub(1).expect("Invalid depth"),
Transactions::<CurrentNetwork>::MAX_TRANSACTIONS
);
}
}