use ex3_canister_types::range::ReportRange;
use ex3_crypto::sha256;
use ex3_deposit_detector_public_types::ConsumedDepositShardingSubReport;
use ex3_node_types::range::CandidRange;
use ex3_node_types::transaction::EncodedTransaction;
use ex3_node_types::BlockHeight;
use ex3_node_types::MerkleNode;
use rs_merkle::algorithms::Sha256;
use rs_merkle::MerkleTree;
use crate::{BlockBuilder, SnapshotVaultIndex};
impl BlockBuilder {
pub(crate) fn generate_consumed_deposit_sharding_sub_reports(
&self,
consumed_deposit_txs: Vec<(EncodedTransaction, usize)>,
txs_merkle_tree: &MerkleTree<Sha256>,
) -> Vec<ConsumedDepositShardingSubReport> {
let mut sharding_sub_reports = vec![];
let mut consumed_deposit_txs = consumed_deposit_txs;
let total_tx_count = txs_merkle_tree.leaves_len();
if consumed_deposit_txs.is_empty() {
return vec![];
}
let full_range = CandidRange {
start: 0u32,
end: consumed_deposit_txs.len().try_into().unwrap(),
};
loop {
let mut deposit_txs = vec![];
for _ in 0..self.max_consumed_deposit_per_sharding_sub_report {
if consumed_deposit_txs.len() == 0 {
break;
}
let tx = consumed_deposit_txs.remove(0);
deposit_txs.push(tx);
}
if deposit_txs.is_empty() {
break;
}
let (txs, indexes) = deposit_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 = sharding_sub_reports.len()
* self
.max_core_registry_update_tx_per_sharding_sub_report
.clone();
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 = ConsumedDepositShardingSubReport {
merkle_proof: merkle_proof.to_bytes(),
range: ReportRange {
total_count: total_tx_count.clone().try_into().unwrap(),
sharding_range: full_range.clone(),
report_range,
},
deposit_txs: txs,
deposit_tx_indexes: indexes.into_iter().map(|i| i.try_into().unwrap()).collect(),
};
sharding_sub_reports.push(report);
}
sharding_sub_reports
}
pub(crate) fn generate_deposit_detector_data_integrity(
&self,
current_block_height: &BlockHeight,
consumed_deposits_sharding_sub_reports: &Vec<ConsumedDepositShardingSubReport>,
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.deposit_detector_canister_id;
data_buffer.extend(canister_id.as_slice());
let total_consumed_deposit_count: u32 = consumed_deposits_sharding_sub_reports
.iter()
.fold(0usize, |acc, report| acc + report.deposit_txs.len())
.try_into()
.unwrap();
data_buffer.extend(total_consumed_deposit_count.to_le_bytes());
data_buffer.extend(total_merkle_node_count.to_le_bytes());
data_buffer.extend(
snapshot_vault_index
.get_deposit_detector_index()
.to_le_bytes(),
);
consumed_deposits_sharding_sub_reports
.iter()
.for_each(|report| {
data_buffer.extend(report.merkle_proof.as_slice());
});
let core_registry_data_integrity: MerkleNode = sha256(data_buffer);
core_registry_data_integrity
}
}