use std::{fmt::Debug, hash::Hash};
pub trait BlockId: Eq + Ord + Clone + Debug + Hash + Serialize + Deserialize {
fn zero() -> Self;
}
pub trait BlockDate: Eq + Ord + Clone {
fn from_epoch_slot_id(epoch: u32, slot_id: u32) -> Self;
}
pub trait ChainLength: Eq + Ord + Clone + Debug {
fn next(&self) -> Self;
}
pub trait TransactionId: Eq + Hash + Debug {}
pub trait Header: Serialize {
type Id: BlockId;
type Date: BlockDate;
type ChainLength: ChainLength;
type Version;
fn id(&self) -> Self::Id;
fn parent_id(&self) -> Self::Id;
fn date(&self) -> Self::Date;
fn version(&self) -> Self::Version;
fn chain_length(&self) -> Self::ChainLength;
}
pub trait Block: Serialize + Deserialize {
type Id: BlockId;
type Date: BlockDate;
type Version;
type ChainLength: ChainLength;
fn id(&self) -> Self::Id;
fn parent_id(&self) -> Self::Id;
fn date(&self) -> Self::Date;
fn version(&self) -> Self::Version;
fn chain_length(&self) -> Self::ChainLength;
}
pub trait HasHeader {
type Header: Header;
fn header(&self) -> Self::Header;
}
pub trait FragmentId: Eq + Hash + Clone + Debug + Serialize + Deserialize {}
pub trait Fragment: Serialize + Deserialize {
type Id: FragmentId;
fn id(&self) -> Self::Id;
}
pub trait HasFragments<'a> {
type Fragment: 'a + Fragment;
type Fragments: 'a + Iterator<Item = &'a Self::Fragment>;
fn fragments(self) -> Self::Fragments;
}
pub trait Transaction: Serialize + Deserialize {
type Input;
type Output;
type Inputs: ?Sized;
type Outputs: ?Sized;
fn inputs(&self) -> &Self::Inputs;
fn outputs(&self) -> &Self::Outputs;
}
pub trait State: Sized + Clone {
type Error: std::error::Error;
type Header: Header;
type Content: Fragment;
fn apply_block<'a, I>(&self, header: &Self::Header, contents: I) -> Result<Self, Self::Error>
where
I: IntoIterator<Item = &'a Self::Content>,
Self::Content: 'a;
fn apply_contents<'a, I>(&self, contents: I) -> Result<Self, Self::Error>
where
I: IntoIterator<Item = &'a Self::Content>,
Self::Content: 'a;
}
pub trait Ledger<T: Transaction>: Sized {
type Error: std::error::Error;
fn input<I>(
&self,
input: <T as Transaction>::Input,
) -> Result<&<T as Transaction>::Output, Self::Error>;
}
pub trait LeaderId: Eq + Clone + Hash + Debug {}
pub trait LeaderSelection {
type Block: Block;
type Error: std::error::Error;
type LeaderId: LeaderId;
type State: State;
fn retrieve(state: &Self::State) -> Self;
fn get_leader_at(
&self,
date: <Self::Block as Block>::Date,
) -> Result<Self::LeaderId, Self::Error>;
}
pub trait Settings {
type Block: Block;
fn tip(&self) -> <Self::Block as Block>::Id;
fn chain_length(&self) -> <Self::Block as Block>::ChainLength;
fn max_number_of_transactions_per_block(&self) -> u32;
fn block_version(&self) -> <Self::Block as Block>::Version;
}
pub trait Serialize {
type Error: std::error::Error + From<std::io::Error>;
fn serialize<W: std::io::Write>(&self, writer: W) -> Result<(), Self::Error>;
fn serialize_as_vec(&self) -> Result<Vec<u8>, Self::Error> {
let mut data = vec![];
self.serialize(&mut data)?;
Ok(data)
}
}
pub trait Deserialize: Sized {
type Error: std::error::Error + From<std::io::Error> + Send + Sync + 'static;
fn deserialize<R: std::io::BufRead>(reader: R) -> Result<Self, Self::Error>;
}
pub trait FromStr: Sized {
type Error: std::error::Error + Send + Sync + 'static;
fn from_str(s: &str) -> Result<Self, Self::Error>;
}
impl<T> FromStr for T
where
T: std::str::FromStr,
<T as std::str::FromStr>::Err: std::error::Error + Send + Sync + 'static,
{
type Error = <T as std::str::FromStr>::Err;
fn from_str(s: &str) -> Result<Self, Self::Error> {
std::str::FromStr::from_str(s)
}
}
impl<T: Serialize> Serialize for &T {
type Error = T::Error;
fn serialize<W: std::io::Write>(&self, writer: W) -> Result<(), T::Error> {
(**self).serialize(writer)
}
}
#[cfg(feature = "property-test-api")]
pub mod testing {
use super::super::mempack::{ReadBuf, Readable};
use super::*;
use quickcheck::{Arbitrary, TestResult};
pub fn serialization_bijection<T>(t: T) -> TestResult
where
T: Arbitrary + Serialize + Deserialize + Eq,
{
let vec = match t.serialize_as_vec() {
Err(error) => return TestResult::error(format!("serialization: {}", error)),
Ok(v) => v,
};
let decoded_t = match T::deserialize(&vec[..]) {
Err(error) => return TestResult::error(format!("deserialization: {}", error)),
Ok(v) => v,
};
TestResult::from_bool(decoded_t == t)
}
pub fn serialization_bijection_r<T>(t: T) -> TestResult
where
T: Arbitrary + Serialize + Readable + Eq,
{
let vec = match t.serialize_as_vec() {
Err(error) => return TestResult::error(format!("serialization: {}", error)),
Ok(v) => v,
};
let mut buf = ReadBuf::from(&vec);
let decoded_t = match T::read(&mut buf) {
Err(error) => {
return TestResult::error(format!("deserialization: {:?}\n{}", error, buf.debug()))
}
Ok(v) => v,
};
TestResult::from_bool(buf.expect_end().is_ok() && decoded_t == t)
}
}