#[cfg(feature = "utxo-commitments")]
use crate::storage::database::{Database, Tree};
#[cfg(feature = "utxo-commitments")]
use anyhow::Result;
#[cfg(feature = "utxo-commitments")]
use blvm_protocol::utxo_commitments::data_structures::UtxoCommitment;
#[cfg(feature = "utxo-commitments")]
use blvm_protocol::Hash;
#[cfg(feature = "utxo-commitments")]
use std::sync::Arc;
#[cfg(feature = "utxo-commitments")]
pub struct CommitmentStore {
#[allow(dead_code)]
db: Arc<dyn Database>,
commitments: Arc<dyn Tree>,
height_index: Arc<dyn Tree>, }
#[cfg(feature = "utxo-commitments")]
impl CommitmentStore {
pub fn new(db: Arc<dyn Database>) -> Result<Self> {
let commitments = Arc::from(db.open_tree("utxo_commitments")?);
let height_index = Arc::from(db.open_tree("commitment_height_index")?);
Ok(Self {
db,
commitments,
height_index,
})
}
pub fn store_commitment(
&self,
block_hash: &Hash,
height: u64,
commitment: &UtxoCommitment,
) -> Result<()> {
let commitment_data = bincode::serialize(commitment)?;
self.commitments
.insert(block_hash.as_slice(), &commitment_data)?;
let height_bytes = height.to_be_bytes();
self.height_index
.insert(&height_bytes, block_hash.as_slice())?;
Ok(())
}
pub fn get_commitment(&self, block_hash: &Hash) -> Result<Option<UtxoCommitment>> {
if let Some(data) = self.commitments.get(block_hash.as_slice())? {
let commitment: UtxoCommitment = bincode::deserialize(&data)?;
Ok(Some(commitment))
} else {
Ok(None)
}
}
pub fn get_commitment_by_height(&self, height: u64) -> Result<Option<UtxoCommitment>> {
let height_bytes = height.to_be_bytes();
if let Some(hash_data) = self.height_index.get(&height_bytes)? {
let mut block_hash = [0u8; 32];
block_hash.copy_from_slice(&hash_data);
self.get_commitment(&block_hash)
} else {
Ok(None)
}
}
pub fn has_commitment(&self, block_hash: &Hash) -> Result<bool> {
self.commitments.contains_key(block_hash.as_slice())
}
pub fn remove_commitment(&self, block_hash: &Hash, height: u64) -> Result<()> {
self.commitments.remove(block_hash.as_slice())?;
let height_bytes = height.to_be_bytes();
self.height_index.remove(&height_bytes)?;
Ok(())
}
pub fn get_commitments_by_height_range(
&self,
start: u64,
end: u64,
) -> Result<Vec<(u64, Hash, UtxoCommitment)>> {
let mut results = Vec::new();
for height in start..=end {
if let Some(commitment) = self.get_commitment_by_height(height)? {
let block_hash = commitment.block_hash;
results.push((height, block_hash, commitment));
}
}
Ok(results)
}
pub fn commitment_count(&self) -> Result<usize> {
self.commitments.len()
}
}
#[cfg(not(feature = "utxo-commitments"))]
pub struct CommitmentStore;
#[cfg(not(feature = "utxo-commitments"))]
impl CommitmentStore {
pub fn new(_db: Arc<dyn Database>) -> Result<Self> {
Err(anyhow::anyhow!("UTXO commitments feature not enabled"))
}
}