use serde::{Deserialize, Serialize};
use crate::{
chain::Chain,
crypto::*,
data::{Metadata, Nonce, Position, Timestamp},
io::{DataBaseError, SerdeError},
merkle::MerkleTree,
};
use crate::{SqliteBlock, SqliteChain};
use super::{
chain::ChainError,
record::{Record, SignedRecord},
};
pub trait Block {
type RecordType: Record;
fn records(&self) -> Result<Box<[SignedRecord<Self::RecordType>]>, BlockError>;
fn prev_hash(&self) -> Result<Hash, BlockError>;
fn position(&self) -> Result<Position, BlockError>;
fn hash(&self) -> Result<Hash, BlockError>;
fn merkle_root(&self) -> Result<Hash, BlockError>;
fn timestamp(&self) -> Result<Timestamp, BlockError>;
fn nonce(&self) -> Result<Nonce, BlockError>;
}
#[derive(Debug, Clone)]
pub enum BlockError {
SerdeError(SerdeError),
DataBaseError(DataBaseError),
NotValid(BlockData),
Unspecified,
}
#[derive(Debug, Clone)]
pub enum BlockData {
Hash,
PrevHash,
MerkleRoot,
Timestamp,
Nonce,
Position,
}
impl std::error::Error for BlockError {}
impl std::fmt::Display for BlockError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Debug::fmt(self, f)
}
}
impl From<ChainError> for BlockError {
fn from(value: ChainError) -> Self {
match value {
ChainError::SerdeError(v) => BlockError::SerdeError(v),
ChainError::DataBaseError(u) => BlockError::DataBaseError(u),
ChainError::Unspecified => BlockError::Unspecified,
ChainError::AbsentValue => unimplemented!(),
}
}
}
pub trait ChainedInstance<C: Chain> {
fn block(self, chain: &C) -> Result<C::BlockType, ChainError>;
}
impl<R: Record + Serialize + for<'d> Deserialize<'d> + 'static> ChainedInstance<SqliteChain<R>>
for PositionInstance
{
fn block(self, chain: &SqliteChain<R>) -> Result<SqliteBlock<R>, ChainError> {
let block = chain.block_at(self.pos)?;
Ok(block)
}
}
pub struct PositionInstance {
pub pos: Position,
}
impl PositionInstance {
pub fn new(pos: Position) -> Self {
Self { pos }
}
}
#[derive(Serialize, Debug, Deserialize, Clone)]
pub struct UnchainedInstance<R> {
records: Vec<SignedRecord<R>>,
merkle: merkle::MerkleTree,
metadata: Metadata,
nonce: Nonce,
}
impl<R> UnchainedInstance<R> {
pub fn new(metadata: Metadata, nonce: u64) -> Self {
Self {
records: vec![],
merkle: MerkleTree::new(),
metadata,
nonce: nonce.into(),
}
}
pub fn merkle_root(&self) -> &Hash {
&self.merkle.merkle_root()
}
pub fn records(&self) -> &Vec<SignedRecord<R>> {
&self.records
}
pub fn nonce(&self) -> Nonce {
self.nonce
}
}
impl<R: Record> UnchainedInstance<R> {
pub fn push(&mut self, item: SignedRecord<R>) {
let hash = item.hash();
self.merkle.push(hash);
self.records.push(item);
}
}