use ex3_canister_types::range::ReportRange;
use ex3_core_registry_public_types::CoreRegistryUpdateTxShardingSubReport;
use ex3_crypto::sha256;
use ex3_node_types::range::CandidRange;
use ex3_node_types::transaction::EncodedTransaction;
use ex3_node_types::BlockHeight;
use ex3_node_types::MerkleNode;
use std::collections::VecDeque;
use rs_merkle::algorithms::Sha256;
use rs_merkle::MerkleTree;
use crate::{BlockBuilder, SnapshotVaultIndex};
impl BlockBuilder {
pub(crate) fn generate_core_registry_update_tx_sharding_sub_reports(
&self,
txs: Vec<(EncodedTransaction, usize)>,
txs_merkle_tree: &MerkleTree<Sha256>,
) -> Vec<CoreRegistryUpdateTxShardingSubReport> {
let mut core_registry_tx_sharding_sub_reports = vec![];
let mut txs_mut: VecDeque<_> = txs.into();
let total_tx_count = txs_merkle_tree.leaves_len();
if txs_mut.is_empty() {
return vec![];
}
let full_range = CandidRange {
start: 0u32,
end: txs_mut.len().try_into().unwrap(),
};
loop {
let mut txs = vec![];
for _ in 0..self.max_core_registry_update_tx_per_sharding_sub_report {
if let Some(tx) = txs_mut.pop_front() {
txs.push(tx);
} else {
break;
}
}
if txs.is_empty() {
break;
}
let (txs, indexes) =
txs.into_iter()
.map(|(tx, index)| (tx, index.clone()))
.unzip::<EncodedTransaction, usize, Vec<EncodedTransaction>, Vec<usize>>();
let merkle_proof = txs_merkle_tree.proof(&indexes);
let report_start = core_registry_tx_sharding_sub_reports.len()
* self
.max_core_registry_update_tx_per_sharding_sub_report
.clone() as usize;
let report_end = report_start.clone() + txs.len();
let report_range = CandidRange {
start: report_start.try_into().unwrap(),
end: report_end.try_into().unwrap(),
};
let report = CoreRegistryUpdateTxShardingSubReport {
merkle_proof: merkle_proof.to_bytes(),
range: ReportRange {
total_count: total_tx_count.clone().try_into().unwrap(),
sharding_range: full_range.clone(),
report_range,
},
txs,
update_tx_indexes: indexes.into_iter().map(|i| i.try_into().unwrap()).collect(),
};
core_registry_tx_sharding_sub_reports.push(report);
}
core_registry_tx_sharding_sub_reports
}
pub(crate) fn generate_core_registry_data_integrity(
&self,
current_block_height: &BlockHeight,
core_register_tx_sharding_sub_reports: &Vec<CoreRegistryUpdateTxShardingSubReport>,
snapshot_vault_index: &SnapshotVaultIndex,
) -> MerkleNode {
let total_merkle_node_count = snapshot_vault_index.get_total_merkle_node_count();
let mut data_buffer = vec![];
data_buffer.extend(current_block_height.0.to_bytes_le());
let canister_id = self.core_registry_canister_id;
data_buffer.extend(canister_id.as_slice());
let total_update_tx_count: u32 = core_register_tx_sharding_sub_reports
.iter()
.fold(0, |acc, report| acc + report.txs.len())
.try_into()
.unwrap();
data_buffer.extend(total_update_tx_count.to_le_bytes());
data_buffer.extend(total_merkle_node_count.to_le_bytes());
data_buffer.extend(snapshot_vault_index.get_core_registry_index().to_le_bytes());
core_register_tx_sharding_sub_reports
.iter()
.for_each(|report| data_buffer.extend(&report.merkle_proof));
let core_registry_data_integrity: MerkleNode = sha256(&data_buffer);
core_registry_data_integrity
}
}