use crate::storage::{DataMap, Map, MapId, Storage};
use snarkvm::dpc::prelude::*;
use anyhow::{anyhow, Result};
use std::path::Path;
#[derive(Debug)]
pub struct ProverState<N: Network> {
coinbase: CoinbaseState<N>,
}
impl<N: Network> ProverState<N> {
pub fn open_writer<S: Storage, P: AsRef<Path>>(path: P) -> Result<Self> {
let context = N::NETWORK_ID;
let is_read_only = false;
let storage = S::open(path, context, is_read_only)?;
let prover = Self {
coinbase: CoinbaseState::open(storage)?,
};
info!("Prover successfully initialized");
Ok(prover)
}
pub fn contains_coinbase_record(&self, commitment: &N::Commitment) -> Result<bool> {
self.coinbase.contains_record(commitment)
}
pub fn to_coinbase_records(&self) -> Vec<(u32, Record<N>)> {
self.coinbase.to_records()
}
pub fn get_coinbase_record(&self, commitment: &N::Commitment) -> Result<(u32, Record<N>)> {
self.coinbase.get_record(commitment)
}
pub fn add_coinbase_record(&self, block_height: u32, record: Record<N>) -> Result<()> {
self.coinbase.add_record(block_height, record)
}
pub fn remove_coinbase_record(&self, commitment: &N::Commitment) -> Result<()> {
self.coinbase.remove_record(commitment)
}
}
#[derive(Clone, Debug)]
#[allow(clippy::type_complexity)]
struct CoinbaseState<N: Network> {
records: DataMap<N::Commitment, (u32, Record<N>)>,
}
impl<N: Network> CoinbaseState<N> {
fn open<S: Storage>(storage: S) -> Result<Self> {
Ok(Self {
records: storage.open_map(MapId::Records)?,
})
}
fn contains_record(&self, commitment: &N::Commitment) -> Result<bool> {
self.records.contains_key(commitment)
}
fn to_records(&self) -> Vec<(u32, Record<N>)> {
self.records.values().collect()
}
fn get_record(&self, commitment: &N::Commitment) -> Result<(u32, Record<N>)> {
match self.records.get(commitment)? {
Some((block_height, record)) => Ok((block_height, record)),
None => return Err(anyhow!("Record with commitment {} does not exist in storage", commitment)),
}
}
fn add_record(&self, block_height: u32, record: Record<N>) -> Result<()> {
let commitment = record.commitment();
if self.records.contains_key(&commitment)? {
Err(anyhow!("Record with commitment {} already exists in storage", commitment))
} else {
self.records.insert(&commitment, &(block_height, record))?;
Ok(())
}
}
fn remove_record(&self, commitment: &N::Commitment) -> Result<()> {
self.records.remove(commitment)?;
Ok(())
}
}