use std::{sync::Arc, time::Instant};
use crate::core::core::hash::Hash;
use crate::core::core::pmmr::ReadablePMMR;
use crate::core::core::{BlockHeader, OutputIdentifier, Segment, SegmentIdentifier, TxKernel};
use crate::error::Error;
use crate::txhashset::{BitmapAccumulator, BitmapChunk, TxHashSet};
use crate::util::secp::pedersen::RangeProof;
use crate::util::RwLock;
#[derive(Clone)]
pub struct Segmenter {
txhashset: Arc<RwLock<TxHashSet>>,
bitmap_snapshot: Arc<BitmapAccumulator>,
header: BlockHeader,
}
impl Segmenter {
pub fn new(
txhashset: Arc<RwLock<TxHashSet>>,
bitmap_snapshot: Arc<BitmapAccumulator>,
header: BlockHeader,
) -> Segmenter {
Segmenter {
txhashset,
bitmap_snapshot,
header,
}
}
pub fn header(&self) -> &BlockHeader {
&self.header
}
pub fn kernel_segment(&self, id: SegmentIdentifier) -> Result<Segment<TxKernel>, Error> {
let now = Instant::now();
let txhashset = self.txhashset.read();
let kernel_pmmr = txhashset.kernel_pmmr_at(&self.header);
let segment = Segment::from_pmmr(id, &kernel_pmmr, false)?;
debug!(
"kernel_segment: id: ({}, {}), leaves: {}, hashes: {}, proof hashes: {}, took {}ms",
segment.id().height,
segment.id().idx,
segment.leaf_iter().count(),
segment.hash_iter().count(),
segment.proof().size(),
now.elapsed().as_millis()
);
Ok(segment)
}
fn output_root(&self) -> Result<Hash, Error> {
let txhashset = self.txhashset.read();
let pmmr = txhashset.output_pmmr_at(&self.header);
let root = pmmr.root().map_err(&Error::TxHashSetErr)?;
Ok(root)
}
fn bitmap_root(&self) -> Result<Hash, Error> {
let pmmr = self.bitmap_snapshot.readonly_pmmr();
let root = pmmr.root().map_err(&Error::TxHashSetErr)?;
Ok(root)
}
pub fn bitmap_segment(
&self,
id: SegmentIdentifier,
) -> Result<(Segment<BitmapChunk>, Hash), Error> {
let now = Instant::now();
let bitmap_pmmr = self.bitmap_snapshot.readonly_pmmr();
let segment = Segment::from_pmmr(id, &bitmap_pmmr, false)?;
let output_root = self.output_root()?;
debug!(
"bitmap_segment: id: ({}, {}), leaves: {}, hashes: {}, proof hashes: {}, took {}ms",
segment.id().height,
segment.id().idx,
segment.leaf_iter().count(),
segment.hash_iter().count(),
segment.proof().size(),
now.elapsed().as_millis()
);
Ok((segment, output_root))
}
pub fn output_segment(
&self,
id: SegmentIdentifier,
) -> Result<(Segment<OutputIdentifier>, Hash), Error> {
let now = Instant::now();
let txhashset = self.txhashset.read();
let output_pmmr = txhashset.output_pmmr_at(&self.header);
let segment = Segment::from_pmmr(id, &output_pmmr, true)?;
let bitmap_root = self.bitmap_root()?;
debug!(
"output_segment: id: ({}, {}), leaves: {}, hashes: {}, proof hashes: {}, took {}ms",
segment.id().height,
segment.id().idx,
segment.leaf_iter().count(),
segment.hash_iter().count(),
segment.proof().size(),
now.elapsed().as_millis()
);
Ok((segment, bitmap_root))
}
pub fn rangeproof_segment(&self, id: SegmentIdentifier) -> Result<Segment<RangeProof>, Error> {
let now = Instant::now();
let txhashset = self.txhashset.read();
let pmmr = txhashset.rangeproof_pmmr_at(&self.header);
let segment = Segment::from_pmmr(id, &pmmr, true)?;
debug!(
"rangeproof_segment: id: ({}, {}), leaves: {}, hashes: {}, proof hashes: {}, took {}ms",
segment.id().height,
segment.id().idx,
segment.leaf_iter().count(),
segment.hash_iter().count(),
segment.proof().size(),
now.elapsed().as_millis()
);
Ok(segment)
}
}