use std::collections::HashSet;
use std::path::Path;
pub mod rocksdb;
use anyhow::Result;
use node_data::ledger::{
Block, Fault, Header, Label, SpendingId, SpentTransaction, Transaction,
};
use node_data::message::{payload, ConsensusHeader};
use serde::{Deserialize, Serialize};
pub struct LightBlock {
pub header: Header,
pub transactions_ids: Vec<[u8; 32]>,
pub faults_ids: Vec<[u8; 32]>,
}
pub trait DB: Send + Sync + 'static {
type P<'a>: Persist;
fn create_or_open<T>(path: T, opts: DatabaseOptions) -> Self
where
T: AsRef<Path>;
fn view<F, T>(&self, f: F) -> T
where
F: for<'a> FnOnce(&Self::P<'a>) -> T;
fn update<F, T>(&self, f: F) -> Result<T>
where
F: for<'a> FnOnce(&mut Self::P<'a>) -> Result<T>;
fn update_dry_run<F, T>(&self, dry_run: bool, f: F) -> Result<T>
where
F: for<'a> FnOnce(&mut Self::P<'a>) -> Result<T>;
fn close(&mut self);
}
pub trait Ledger {
fn store_block(
&mut self,
header: &Header,
txs: &[SpentTransaction],
faults: &[Fault],
label: Label,
) -> Result<usize>;
fn delete_block(&mut self, b: &Block) -> Result<()>;
fn block_header(&self, hash: &[u8]) -> Result<Option<Header>>;
fn light_block(&self, hash: &[u8]) -> Result<Option<LightBlock>>;
fn block(&self, hash: &[u8]) -> Result<Option<Block>>;
fn block_hash_by_height(&self, height: u64) -> Result<Option<[u8; 32]>>;
fn block_by_height(&self, height: u64) -> Result<Option<Block>>;
fn block_exists(&self, hash: &[u8]) -> Result<bool>;
fn ledger_tx(&self, tx_id: &[u8]) -> Result<Option<SpentTransaction>>;
fn ledger_tx_exists(&self, tx_id: &[u8]) -> Result<bool>;
fn block_label_by_height(
&self,
height: u64,
) -> Result<Option<([u8; 32], Label)>>;
fn store_block_label(
&mut self,
height: u64,
hash: &[u8; 32],
label: Label,
) -> Result<()>;
fn faults_by_block(&self, start_height: u64) -> Result<Vec<Fault>>;
fn faults(&self, faults_ids: &[[u8; 32]]) -> Result<Vec<Fault>>;
}
pub trait ConsensusStorage {
fn store_candidate(&mut self, cm: Block) -> Result<()>;
fn candidate(&self, hash: &[u8]) -> Result<Option<Block>>;
fn candidate_by_iteration(
&self,
ch: &ConsensusHeader,
) -> Result<Option<Block>>;
fn clear_candidates(&mut self) -> Result<()>;
fn delete_candidate<F>(&mut self, closure: F) -> Result<()>
where
F: FnOnce(u64) -> bool + std::marker::Copy;
fn count_candidates(&self) -> usize;
fn store_validation_result(
&mut self,
ch: &ConsensusHeader,
vr: &payload::ValidationResult,
) -> Result<()>;
fn validation_result(
&self,
ch: &ConsensusHeader,
) -> Result<Option<payload::ValidationResult>>;
fn clear_validation_results(&mut self) -> Result<()>;
fn delete_validation_results<F>(&mut self, closure: F) -> Result<()>
where
F: FnOnce([u8; 32]) -> bool + std::marker::Copy;
fn count_validation_results(&self) -> usize;
}
pub trait Mempool {
fn store_mempool_tx(
&mut self,
tx: &Transaction,
timestamp: u64,
) -> Result<()>;
fn mempool_tx(&self, tx_id: [u8; 32]) -> Result<Option<Transaction>>;
fn mempool_tx_exists(&self, tx_id: [u8; 32]) -> Result<bool>;
fn delete_mempool_tx(
&mut self,
tx_id: [u8; 32],
cascade: bool,
) -> Result<Vec<[u8; 32]>>;
fn mempool_txs_by_spendable_ids(
&self,
n: &[SpendingId],
) -> HashSet<[u8; 32]>;
fn mempool_txs_sorted_by_fee(
&self,
) -> Result<Box<dyn Iterator<Item = Transaction> + '_>>;
fn mempool_txs_ids_sorted_by_fee(
&self,
) -> Result<Box<dyn Iterator<Item = (u64, [u8; 32])> + '_>>;
fn mempool_txs_ids_sorted_by_low_fee(
&self,
) -> Result<Box<dyn Iterator<Item = (u64, [u8; 32])> + '_>>;
fn mempool_txs_ids(&self) -> Result<Vec<[u8; 32]>>;
fn mempool_expired_txs(&self, timestamp: u64) -> Result<Vec<[u8; 32]>>;
fn mempool_txs_count(&self) -> usize;
}
pub trait Metadata {
fn op_write<T: AsRef<[u8]>>(&mut self, key: &[u8], value: T) -> Result<()>;
fn op_read(&self, key: &[u8]) -> Result<Option<Vec<u8>>>;
}
pub trait Persist:
Ledger + ConsensusStorage + Mempool + Metadata + core::fmt::Debug
{
fn clear_database(&mut self) -> Result<()>;
fn commit(self) -> Result<()>;
fn rollback(self) -> Result<()>;
}
pub fn into_array<const N: usize>(value: &[u8]) -> [u8; N] {
let mut res = [0u8; N];
res.copy_from_slice(&value[0..N]);
res
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct DatabaseOptions {
pub blocks_cf_max_write_buffer_size: usize,
pub blocks_cf_disable_block_cache: bool,
pub mempool_cf_max_write_buffer_size: usize,
pub enable_debug: bool,
}
impl Default for DatabaseOptions {
fn default() -> Self {
Self {
blocks_cf_max_write_buffer_size: 1024 * 1024, mempool_cf_max_write_buffer_size: 10 * 1024 * 1024, blocks_cf_disable_block_cache: true,
enable_debug: false,
}
}
}