Blocks

A block is a fundamental component of many blockchain systems, including the Tofuri blockchain. In simple terms, a block is a collection of data that is stored in a blockchain.

Filename: tofuri/block/src/lib.rs

use merkle_cbt::merkle_tree::Merge;
use merkle_cbt::CBMT as ExCBMT;
use serde::Deserialize;
use serde::Serialize;
use serde_big_array::BigArray;
use sha2::Digest;
use sha2::Sha256;
use std::fmt;
use tofuri_core::*;
use tofuri_key::Key;
use tofuri_stake::StakeA;
use tofuri_stake::StakeB;
use tofuri_transaction::TransactionA;
use tofuri_transaction::TransactionB;
#[derive(Debug)]
pub enum Error {
    Key(tofuri_key::Error),
    Transaction(tofuri_transaction::Error),
    Stake(tofuri_stake::Error),
}
pub trait Block {
    fn get_previous_hash(&self) -> &Hash;
    fn get_merkle_root_transaction(&self) -> MerkleRoot;
    fn get_merkle_root_stake(&self) -> MerkleRoot;
    fn get_timestamp(&self) -> u32;
    fn get_pi(&self) -> Π
    fn hash(&self) -> Hash;
    fn hash_input(&self) -> [u8; 181];
    fn beta(&self) -> Result<Beta, Error>;
}
impl Block for BlockA {
    fn get_previous_hash(&self) -> &Hash {
        &self.previous_hash
    }
    fn get_merkle_root_transaction(&self) -> MerkleRoot {
        merkle_root(&self.transaction_hashes())
    }
    fn get_merkle_root_stake(&self) -> MerkleRoot {
        merkle_root(&self.stake_hashes())
    }
    fn get_timestamp(&self) -> u32 {
        self.timestamp
    }
    fn get_pi(&self) -> &Pi {
        &self.pi
    }
    fn hash(&self) -> Hash {
        hash(self)
    }
    fn hash_input(&self) -> [u8; 181] {
        hash_input(self)
    }
    fn beta(&self) -> Result<Beta, Error> {
        beta(self)
    }
}
impl Block for BlockB {
    fn get_previous_hash(&self) -> &Hash {
        &self.previous_hash
    }
    fn get_merkle_root_transaction(&self) -> MerkleRoot {
        merkle_root(&self.transaction_hashes())
    }
    fn get_merkle_root_stake(&self) -> MerkleRoot {
        merkle_root(&self.stake_hashes())
    }
    fn get_timestamp(&self) -> u32 {
        self.timestamp
    }
    fn get_pi(&self) -> &Pi {
        &self.pi
    }
    fn hash(&self) -> Hash {
        hash(self)
    }
    fn hash_input(&self) -> [u8; 181] {
        hash_input(self)
    }
    fn beta(&self) -> Result<Beta, Error> {
        beta(self)
    }
}
#[derive(Serialize, Deserialize, Clone)]
pub struct BlockA {
    pub hash: Hash,
    pub previous_hash: Hash,
    pub timestamp: u32,
    pub beta: Beta,
    #[serde(with = "BigArray")]
    pub pi: Pi,
    #[serde(with = "BigArray")]
    pub input_public_key: PublicKeyBytes,
    #[serde(with = "BigArray")]
    pub signature: SignatureBytes,
    pub transactions: Vec<TransactionA>,
    pub stakes: Vec<StakeA>,
}
impl fmt::Debug for BlockA {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("BlockA")
            .field("hash", &hex::encode(&self.hash))
            .field("previous_hash", &hex::encode(&self.previous_hash))
            .field("timestamp", &self.timestamp)
            .field("beta", &hex::encode(self.beta))
            .field("pi", &hex::encode(&self.pi))
            .field("input_public_key", &hex::encode(&self.input_public_key))
            .field("signature", &hex::encode(&self.signature))
            .field("transactions", &self.transactions)
            .field("stakes", &self.stakes)
            .finish()
    }
}
#[derive(Serialize, Deserialize, Clone)]
pub struct BlockB {
    pub previous_hash: Hash,
    pub timestamp: u32,
    #[serde(with = "BigArray")]
    pub signature: SignatureBytes,
    #[serde(with = "BigArray")]
    pub pi: Pi,
    pub transactions: Vec<TransactionB>,
    pub stakes: Vec<StakeB>,
}
impl fmt::Debug for BlockB {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("BlockB")
            .field("previous_hash", &hex::encode(&self.previous_hash))
            .field("timestamp", &self.timestamp)
            .field("signature", &hex::encode(&self.signature))
            .field("pi", &hex::encode(&self.pi))
            .field("transactions", &self.transactions)
            .field("stakes", &self.stakes)
            .finish()
    }
}
#[derive(Serialize, Deserialize)]
pub struct BlockC {
    pub previous_hash: Hash,
    pub timestamp: u32,
    #[serde(with = "BigArray")]
    pub signature: SignatureBytes,
    #[serde(with = "BigArray")]
    pub pi: Pi,
    pub transaction_hashes: Vec<Hash>,
    pub stake_hashes: Vec<Hash>,
}
impl fmt::Debug for BlockC {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("BlockC")
            .field("previous_hash", &hex::encode(&self.previous_hash))
            .field("timestamp", &self.timestamp)
            .field("signature", &hex::encode(&self.signature))
            .field("pi", &hex::encode(&self.pi))
            .field(
                "transaction_hashes",
                &self
                    .transaction_hashes
                    .iter()
                    .map(hex::encode)
                    .collect::<Vec<_>>(),
            )
            .field(
                "stake_hashes",
                &self
                    .stake_hashes
                    .iter()
                    .map(hex::encode)
                    .collect::<Vec<_>>(),
            )
            .finish()
    }
}
impl BlockA {
    pub fn b(&self) -> BlockB {
        BlockB {
            previous_hash: self.previous_hash,
            timestamp: self.timestamp,
            signature: self.signature,
            pi: self.pi,
            transactions: self.transactions.iter().map(|x| x.b()).collect(),
            stakes: self.stakes.iter().map(|x| x.b()).collect(),
        }
    }
    pub fn sign(
        previous_hash: Hash,
        timestamp: u32,
        transactions: Vec<TransactionA>,
        stakes: Vec<StakeA>,
        key: &Key,
        previous_beta: &Beta,
    ) -> Result<BlockA, Error> {
        let pi = key.vrf_prove(previous_beta).map_err(Error::Key)?;
        let mut block_a = BlockA {
            hash: [0; 32],
            previous_hash,
            timestamp,
            beta: [0; 32],
            pi,
            input_public_key: [0; 33],
            signature: [0; 64],
            transactions,
            stakes,
        };
        block_a.beta = block_a.beta()?;
        block_a.hash = block_a.hash();
        block_a.signature = key.sign(&block_a.hash).map_err(Error::Key)?;
        block_a.input_public_key = key.public_key_bytes();
        Ok(block_a)
    }
    pub fn input_address(&self) -> AddressBytes {
        Key::address(&self.input_public_key)
    }
    pub fn reward(&self) -> u128 {
        self.fees() + COIN
    }
    fn fees(&self) -> u128 {
        let mut fees = 0;
        for transaction in self.transactions.iter() {
            fees += transaction.fee;
        }
        for stake in self.stakes.iter() {
            fees += stake.fee;
        }
        fees
    }
    fn transaction_hashes(&self) -> Vec<Hash> {
        self.transactions.iter().map(|x| x.hash()).collect()
    }
    fn stake_hashes(&self) -> Vec<Hash> {
        self.stakes.iter().map(|x| x.hash()).collect()
    }
}
impl BlockB {
    pub fn a(&self) -> Result<BlockA, Error> {
        let mut transactions = vec![];
        let mut stakes = vec![];
        for transaction in self.transactions.iter() {
            transactions.push(transaction.a(None).map_err(Error::Transaction)?)
        }
        for stake in self.stakes.iter() {
            stakes.push(stake.a(None).map_err(Error::Stake)?);
        }
        let block_a = BlockA {
            hash: self.hash(),
            previous_hash: self.previous_hash,
            timestamp: self.timestamp,
            beta: self.beta()?,
            pi: self.pi,
            input_public_key: self.input_public_key()?,
            signature: self.signature,
            transactions,
            stakes,
        };
        Ok(block_a)
    }
    pub fn c(&self) -> BlockC {
        BlockC {
            previous_hash: self.previous_hash,
            timestamp: self.timestamp,
            signature: self.signature,
            pi: self.pi,
            transaction_hashes: self.transaction_hashes(),
            stake_hashes: self.stake_hashes(),
        }
    }
    fn transaction_hashes(&self) -> Vec<Hash> {
        self.transactions.iter().map(|x| x.hash()).collect()
    }
    fn stake_hashes(&self) -> Vec<Hash> {
        self.stakes.iter().map(|x| x.hash()).collect()
    }
    fn input_public_key(&self) -> Result<PublicKeyBytes, Error> {
        Key::recover(&self.hash(), &self.signature).map_err(Error::Key)
    }
}
impl BlockC {
    pub fn a(
        &self,
        transactions: Vec<TransactionA>,
        stakes: Vec<StakeA>,
        beta: Option<[u8; 32]>,
        input_public_key: Option<PublicKeyBytes>,
    ) -> Result<BlockA, Error> {
        let block_b = self.b(
            transactions.iter().map(|x| x.b()).collect(),
            stakes.iter().map(|x| x.b()).collect(),
        );
        let beta = beta.unwrap_or(block_b.beta()?);
        let input_public_key = input_public_key.unwrap_or(block_b.input_public_key()?);
        let mut block_a = BlockA {
            hash: [0; 32],
            previous_hash: self.previous_hash,
            timestamp: self.timestamp,
            beta,
            pi: self.pi,
            input_public_key,
            signature: self.signature,
            transactions,
            stakes,
        };
        block_a.hash = block_a.hash();
        Ok(block_a)
    }
    pub fn b(&self, transactions: Vec<TransactionB>, stakes: Vec<StakeB>) -> BlockB {
        BlockB {
            previous_hash: self.previous_hash,
            timestamp: self.timestamp,
            signature: self.signature,
            pi: self.pi,
            transactions,
            stakes,
        }
    }
}
impl Default for BlockA {
    fn default() -> BlockA {
        BlockA {
            hash: [0; 32],
            previous_hash: [0; 32],
            timestamp: 0,
            beta: [0; 32],
            pi: [0; 81],
            input_public_key: [0; 33],
            signature: [0; 64],
            transactions: vec![],
            stakes: vec![],
        }
    }
}
impl Default for BlockB {
    fn default() -> BlockB {
        BlockB {
            previous_hash: [0; 32],
            timestamp: 0,
            signature: [0; 64],
            pi: [0; 81],
            transactions: vec![],
            stakes: vec![],
        }
    }
}
impl Default for BlockC {
    fn default() -> BlockC {
        BlockC {
            previous_hash: [0; 32],
            timestamp: 0,
            signature: [0; 64],
            pi: [0; 81],
            transaction_hashes: vec![],
            stake_hashes: vec![],
        }
    }
}
fn hash<T: Block>(block: &T) -> Hash {
    let mut hasher = Sha256::new();
    hasher.update(block.hash_input());
    hasher.finalize().into()
}
fn hash_input<T: Block>(block: &T) -> [u8; 181] {
    let mut bytes = [0; 181];
    bytes[0..32].copy_from_slice(block.get_previous_hash());
    bytes[32..64].copy_from_slice(&block.get_merkle_root_transaction());
    bytes[64..96].copy_from_slice(&block.get_merkle_root_stake());
    bytes[96..100].copy_from_slice(&block.get_timestamp().to_be_bytes());
    bytes[100..181].copy_from_slice(block.get_pi());
    bytes
}
fn merkle_root(hashes: &[Hash]) -> MerkleRoot {
    struct Hasher;
    impl Merge for Hasher {
        type Item = [u8; 32];
        fn merge(left: &Self::Item, right: &Self::Item) -> Self::Item {
            let mut hasher = Sha256::new();
            hasher.update(left);
            hasher.update(right);
            hasher.finalize().into()
        }
    }
    <ExCBMT<[u8; 32], Hasher>>::build_merkle_root(hashes)
}
fn beta<T: Block>(block: &T) -> Result<Beta, Error> {
    Key::vrf_proof_to_hash(block.get_pi()).map_err(Error::Key)
}
#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn test_hash() {
        assert_eq!(
            BlockB::default().hash(),
            [
                219, 36, 84, 162, 32, 189, 146, 241, 148, 53, 36, 177, 50, 142, 92, 103, 125, 225,
                26, 208, 20, 86, 5, 216, 113, 32, 54, 141, 75, 147, 221, 219
            ]
        );
    }
    #[test]
    fn test_genesis_beta() {
        assert_eq!(BlockA::default().beta, GENESIS_BLOCK_BETA);
    }
}
use merkle_cbt::merkle_tree::Merge;
use merkle_cbt::CBMT as ExCBMT;
use serde::Deserialize;
use serde::Serialize;
use serde_big_array::BigArray;
use sha2::Digest;
use sha2::Sha256;
use std::fmt;
use tofuri_core::*;
use tofuri_key::Key;
use tofuri_stake::StakeA;
use tofuri_stake::StakeB;
use tofuri_transaction::TransactionA;
use tofuri_transaction::TransactionB;
#[derive(Debug)]
pub enum Error {
    Key(tofuri_key::Error),
    Transaction(tofuri_transaction::Error),
    Stake(tofuri_stake::Error),
}
pub trait Block {
    fn get_previous_hash(&self) -> &Hash;
    fn get_merkle_root_transaction(&self) -> MerkleRoot;
    fn get_merkle_root_stake(&self) -> MerkleRoot;
    fn get_timestamp(&self) -> u32;
    fn get_pi(&self) -> &Pi;
    fn hash(&self) -> Hash;
    fn hash_input(&self) -> [u8; 181];
    fn beta(&self) -> Result<Beta, Error>;
}
impl Block for BlockA {
    fn get_previous_hash(&self) -> &Hash {
        &self.previous_hash
    }
    fn get_merkle_root_transaction(&self) -> MerkleRoot {
        merkle_root(&self.transaction_hashes())
    }
    fn get_merkle_root_stake(&self) -> MerkleRoot {
        merkle_root(&self.stake_hashes())
    }
    fn get_timestamp(&self) -> u32 {
        self.timestamp
    }
    fn get_pi(&self) -> &Pi {
        &self.pi
    }
    fn hash(&self) -> Hash {
        hash(self)
    }
    fn hash_input(&self) -> [u8; 181] {
        hash_input(self)
    }
    fn beta(&self) -> Result<Beta, Error> {
        beta(self)
    }
}
impl Block for BlockB {
    fn get_previous_hash(&self) -> &Hash {
        &self.previous_hash
    }
    fn get_merkle_root_transaction(&self) -> MerkleRoot {
        merkle_root(&self.transaction_hashes())
    }
    fn get_merkle_root_stake(&self) -> MerkleRoot {
        merkle_root(&self.stake_hashes())
    }
    fn get_timestamp(&self) -> u32 {
        self.timestamp
    }
    fn get_pi(&self) -> &Pi {
        &self.pi
    }
    fn hash(&self) -> Hash {
        hash(self)
    }
    fn hash_input(&self) -> [u8; 181] {
        hash_input(self)
    }
    fn beta(&self) -> Result<Beta, Error> {
        beta(self)
    }
}
#[derive(Serialize, Deserialize, Clone)]
pub struct BlockA {
    pub hash: Hash,
    pub previous_hash: Hash,
    pub timestamp: u32,
    pub beta: Beta,
    #[serde(with = "BigArray")]
    pub pi: Pi,
    #[serde(with = "BigArray")]
    pub input_public_key: PublicKeyBytes,
    #[serde(with = "BigArray")]
    pub signature: SignatureBytes,
    pub transactions: Vec<TransactionA>,
    pub stakes: Vec<StakeA>,
}
impl fmt::Debug for BlockA {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("BlockA")
            .field("hash", &hex::encode(&self.hash))
            .field("previous_hash", &hex::encode(&self.previous_hash))
            .field("timestamp", &self.timestamp)
            .field("beta", &hex::encode(self.beta))
            .field("pi", &hex::encode(&self.pi))
            .field("input_public_key", &hex::encode(&self.input_public_key))
            .field("signature", &hex::encode(&self.signature))
            .field("transactions", &self.transactions)
            .field("stakes", &self.stakes)
            .finish()
    }
}
#[derive(Serialize, Deserialize, Clone)]
pub struct BlockB {
    pub previous_hash: Hash,
    pub timestamp: u32,
    #[serde(with = "BigArray")]
    pub signature: SignatureBytes,
    #[serde(with = "BigArray")]
    pub pi: Pi,
    pub transactions: Vec<TransactionB>,
    pub stakes: Vec<StakeB>,
}
impl fmt::Debug for BlockB {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("BlockB")
            .field("previous_hash", &hex::encode(&self.previous_hash))
            .field("timestamp", &self.timestamp)
            .field("signature", &hex::encode(&self.signature))
            .field("pi", &hex::encode(&self.pi))
            .field("transactions", &self.transactions)
            .field("stakes", &self.stakes)
            .finish()
    }
}
#[derive(Serialize, Deserialize)]
pub struct BlockC {
    pub previous_hash: Hash,
    pub timestamp: u32,
    #[serde(with = "BigArray")]
    pub signature: SignatureBytes,
    #[serde(with = "BigArray")]
    pub pi: Pi,
    pub transaction_hashes: Vec<Hash>,
    pub stake_hashes: Vec<Hash>,
}
impl fmt::Debug for BlockC {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("BlockC")
            .field("previous_hash", &hex::encode(&self.previous_hash))
            .field("timestamp", &self.timestamp)
            .field("signature", &hex::encode(&self.signature))
            .field("pi", &hex::encode(&self.pi))
            .field(
                "transaction_hashes",
                &self
                    .transaction_hashes
                    .iter()
                    .map(hex::encode)
                    .collect::<Vec<_>>(),
            )
            .field(
                "stake_hashes",
                &self
                    .stake_hashes
                    .iter()
                    .map(hex::encode)
                    .collect::<Vec<_>>(),
            )
            .finish()
    }
}
impl BlockA {
    pub fn b(&self) -> BlockB {
        BlockB {
            previous_hash: self.previous_hash,
            timestamp: self.timestamp,
            signature: self.signature,
            pi: self.pi,
            transactions: self.transactions.iter().map(|x| x.b()).collect(),
            stakes: self.stakes.iter().map(|x| x.b()).collect(),
        }
    }
    pub fn sign(
        previous_hash: Hash,
        timestamp: u32,
        transactions: Vec<TransactionA>,
        stakes: Vec<StakeA>,
        key: &Key,
        previous_beta: &Beta,
    ) -> Result<BlockA, Error> {
        let pi = key.vrf_prove(previous_beta).map_err(Error::Key)?;
        let mut block_a = BlockA {
            hash: [0; 32],
            previous_hash,
            timestamp,
            beta: [0; 32],
            pi,
            input_public_key: [0; 33],
            signature: [0; 64],
            transactions,
            stakes,
        };
        block_a.beta = block_a.beta()?;
        block_a.hash = block_a.hash();
        block_a.signature = key.sign(&block_a.hash).map_err(Error::Key)?;
        block_a.input_public_key = key.public_key_bytes();
        Ok(block_a)
    }
    pub fn input_address(&self) -> AddressBytes {
        Key::address(&self.input_public_key)
    }
    pub fn reward(&self) -> u128 {
        self.fees() + COIN
    }
    fn fees(&self) -> u128 {
        let mut fees = 0;
        for transaction in self.transactions.iter() {
            fees += transaction.fee;
        }
        for stake in self.stakes.iter() {
            fees += stake.fee;
        }
        fees
    }
    fn transaction_hashes(&self) -> Vec<Hash> {
        self.transactions.iter().map(|x| x.hash()).collect()
    }
    fn stake_hashes(&self) -> Vec<Hash> {
        self.stakes.iter().map(|x| x.hash()).collect()
    }
}
impl BlockB {
    pub fn a(&self) -> Result<BlockA, Error> {
        let mut transactions = vec![];
        let mut stakes = vec![];
        for transaction in self.transactions.iter() {
            transactions.push(transaction.a(None).map_err(Error::Transaction)?)
        }
        for stake in self.stakes.iter() {
            stakes.push(stake.a(None).map_err(Error::Stake)?);
        }
        let block_a = BlockA {
            hash: self.hash(),
            previous_hash: self.previous_hash,
            timestamp: self.timestamp,
            beta: self.beta()?,
            pi: self.pi,
            input_public_key: self.input_public_key()?,
            signature: self.signature,
            transactions,
            stakes,
        };
        Ok(block_a)
    }
    pub fn c(&self) -> BlockC {
        BlockC {
            previous_hash: self.previous_hash,
            timestamp: self.timestamp,
            signature: self.signature,
            pi: self.pi,
            transaction_hashes: self.transaction_hashes(),
            stake_hashes: self.stake_hashes(),
        }
    }
    fn transaction_hashes(&self) -> Vec<Hash> {
        self.transactions.iter().map(|x| x.hash()).collect()
    }
    fn stake_hashes(&self) -> Vec<Hash> {
        self.stakes.iter().map(|x| x.hash()).collect()
    }
    fn input_public_key(&self) -> Result<PublicKeyBytes, Error> {
        Key::recover(&self.hash(), &self.signature).map_err(Error::Key)
    }
}
impl BlockC {
    pub fn a(
        &self,
        transactions: Vec<TransactionA>,
        stakes: Vec<StakeA>,
        beta: Option<[u8; 32]>,
        input_public_key: Option<PublicKeyBytes>,
    ) -> Result<BlockA, Error> {
        let block_b = self.b(
            transactions.iter().map(|x| x.b()).collect(),
            stakes.iter().map(|x| x.b()).collect(),
        );
        let beta = beta.unwrap_or(block_b.beta()?);
        let input_public_key = input_public_key.unwrap_or(block_b.input_public_key()?);
        let mut block_a = BlockA {
            hash: [0; 32],
            previous_hash: self.previous_hash,
            timestamp: self.timestamp,
            beta,
            pi: self.pi,
            input_public_key,
            signature: self.signature,
            transactions,
            stakes,
        };
        block_a.hash = block_a.hash();
        Ok(block_a)
    }
    pub fn b(&self, transactions: Vec<TransactionB>, stakes: Vec<StakeB>) -> BlockB {
        BlockB {
            previous_hash: self.previous_hash,
            timestamp: self.timestamp,
            signature: self.signature,
            pi: self.pi,
            transactions,
            stakes,
        }
    }
}
impl Default for BlockA {
    fn default() -> BlockA {
        BlockA {
            hash: [0; 32],
            previous_hash: [0; 32],
            timestamp: 0,
            beta: [0; 32],
            pi: [0; 81],
            input_public_key: [0; 33],
            signature: [0; 64],
            transactions: vec![],
            stakes: vec![],
        }
    }
}
impl Default for BlockB {
    fn default() -> BlockB {
        BlockB {
            previous_hash: [0; 32],
            timestamp: 0,
            signature: [0; 64],
            pi: [0; 81],
            transactions: vec![],
            stakes: vec![],
        }
    }
}
impl Default for BlockC {
    fn default() -> BlockC {
        BlockC {
            previous_hash: [0; 32],
            timestamp: 0,
            signature: [0; 64],
            pi: [0; 81],
            transaction_hashes: vec![],
            stake_hashes: vec![],
        }
    }
}
fn hash<T: Block>(block: &T) -> Hash {
    let mut hasher = Sha256::new();
    hasher.update(block.hash_input());
    hasher.finalize().into()
}
fn hash_input<T: Block>(block: &T) -> [u8; 181] {
    let mut bytes = [0; 181];
    bytes[0..32].copy_from_slice(block.get_previous_hash());
    bytes[32..64].copy_from_slice(&block.get_merkle_root_transaction());
    bytes[64..96].copy_from_slice(&block.get_merkle_root_stake());
    bytes[96..100].copy_from_slice(&block.get_timestamp().to_be_bytes());
    bytes[100..181].copy_from_slice(block.get_pi());
    bytes
}
fn merkle_root(hashes: &[Hash]) -> MerkleRoot {
    struct Hasher;
    impl Merge for Hasher {
        type Item = [u8; 32];
        fn merge(left: &Self::Item, right: &Self::Item) -> Self::Item {
            let mut hasher = Sha256::new();
            hasher.update(left);
            hasher.update(right);
            hasher.finalize().into()
        }
    }
    <ExCBMT<[u8; 32], Hasher>>::build_merkle_root(hashes)
}
fn beta<T: Block>(block: &T) -> Result<Beta, Error> {
    Key::vrf_proof_to_hash(block.get_pi()).map_err(Error::Key)
}
#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn test_hash() {
        assert_eq!(
            BlockB::default().hash(),
            [
                219, 36, 84, 162, 32, 189, 146, 241, 148, 53, 36, 177, 50, 142, 92, 103, 125, 225,
                26, 208, 20, 86, 5, 216, 113, 32, 54, 141, 75, 147, 221, 219
            ]
        );
    }
    #[test]
    fn test_genesis_beta() {
        assert_eq!(BlockA::default().beta, GENESIS_BLOCK_BETA);
    }
}
use merkle_cbt::merkle_tree::Merge;
use merkle_cbt::CBMT as ExCBMT;
use serde::Deserialize;
use serde::Serialize;
use serde_big_array::BigArray;
use sha2::Digest;
use sha2::Sha256;
use std::fmt;
use tofuri_core::*;
use tofuri_key::Key;
use tofuri_stake::StakeA;
use tofuri_stake::StakeB;
use tofuri_transaction::TransactionA;
use tofuri_transaction::TransactionB;
#[derive(Debug)]
pub enum Error {
    Key(tofuri_key::Error),
    Transaction(tofuri_transaction::Error),
    Stake(tofuri_stake::Error),
}
pub trait Block {
    fn get_previous_hash(&self) -> &Hash;
    fn get_merkle_root_transaction(&self) -> MerkleRoot;
    fn get_merkle_root_stake(&self) -> MerkleRoot;
    fn get_timestamp(&self) -> u32;
    fn get_pi(&self) -> &Pi;
    fn hash(&self) -> Hash;
    fn hash_input(&self) -> [u8; 181];
    fn beta(&self) -> Result<Beta, Error>;
}
impl Block for BlockA {
    fn get_previous_hash(&self) -> &Hash {
        &self.previous_hash
    }
    fn get_merkle_root_transaction(&self) -> MerkleRoot {
        merkle_root(&self.transaction_hashes())
    }
    fn get_merkle_root_stake(&self) -> MerkleRoot {
        merkle_root(&self.stake_hashes())
    }
    fn get_timestamp(&self) -> u32 {
        self.timestamp
    }
    fn get_pi(&self) -> &Pi {
        &self.pi
    }
    fn hash(&self) -> Hash {
        hash(self)
    }
    fn hash_input(&self) -> [u8; 181] {
        hash_input(self)
    }
    fn beta(&self) -> Result<Beta, Error> {
        beta(self)
    }
}
impl Block for BlockB {
    fn get_previous_hash(&self) -> &Hash {
        &self.previous_hash
    }
    fn get_merkle_root_transaction(&self) -> MerkleRoot {
        merkle_root(&self.transaction_hashes())
    }
    fn get_merkle_root_stake(&self) -> MerkleRoot {
        merkle_root(&self.stake_hashes())
    }
    fn get_timestamp(&self) -> u32 {
        self.timestamp
    }
    fn get_pi(&self) -> &Pi {
        &self.pi
    }
    fn hash(&self) -> Hash {
        hash(self)
    }
    fn hash_input(&self) -> [u8; 181] {
        hash_input(self)
    }
    fn beta(&self) -> Result<Beta, Error> {
        beta(self)
    }
}
#[derive(Serialize, Deserialize, Clone)]
pub struct BlockA {
    pub hash: Hash,
    pub previous_hash: Hash,
    pub timestamp: u32,
    pub beta: Beta,
    #[serde(with = "BigArray")]
    pub pi: Pi,
    #[serde(with = "BigArray")]
    pub input_public_key: PublicKeyBytes,
    #[serde(with = "BigArray")]
    pub signature: SignatureBytes,
    pub transactions: Vec<TransactionA>,
    pub stakes: Vec<StakeA>,
}
impl fmt::Debug for BlockA {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("BlockA")
            .field("hash", &hex::encode(&self.hash))
            .field("previous_hash", &hex::encode(&self.previous_hash))
            .field("timestamp", &self.timestamp)
            .field("beta", &hex::encode(self.beta))
            .field("pi", &hex::encode(&self.pi))
            .field("input_public_key", &hex::encode(&self.input_public_key))
            .field("signature", &hex::encode(&self.signature))
            .field("transactions", &self.transactions)
            .field("stakes", &self.stakes)
            .finish()
    }
}
#[derive(Serialize, Deserialize, Clone)]
pub struct BlockB {
    pub previous_hash: Hash,
    pub timestamp: u32,
    #[serde(with = "BigArray")]
    pub signature: SignatureBytes,
    #[serde(with = "BigArray")]
    pub pi: Pi,
    pub transactions: Vec<TransactionB>,
    pub stakes: Vec<StakeB>,
}
impl fmt::Debug for BlockB {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("BlockB")
            .field("previous_hash", &hex::encode(&self.previous_hash))
            .field("timestamp", &self.timestamp)
            .field("signature", &hex::encode(&self.signature))
            .field("pi", &hex::encode(&self.pi))
            .field("transactions", &self.transactions)
            .field("stakes", &self.stakes)
            .finish()
    }
}
#[derive(Serialize, Deserialize)]
pub struct BlockC {
    pub previous_hash: Hash,
    pub timestamp: u32,
    #[serde(with = "BigArray")]
    pub signature: SignatureBytes,
    #[serde(with = "BigArray")]
    pub pi: Pi,
    pub transaction_hashes: Vec<Hash>,
    pub stake_hashes: Vec<Hash>,
}
impl fmt::Debug for BlockC {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("BlockC")
            .field("previous_hash", &hex::encode(&self.previous_hash))
            .field("timestamp", &self.timestamp)
            .field("signature", &hex::encode(&self.signature))
            .field("pi", &hex::encode(&self.pi))
            .field(
                "transaction_hashes",
                &self
                    .transaction_hashes
                    .iter()
                    .map(hex::encode)
                    .collect::<Vec<_>>(),
            )
            .field(
                "stake_hashes",
                &self
                    .stake_hashes
                    .iter()
                    .map(hex::encode)
                    .collect::<Vec<_>>(),
            )
            .finish()
    }
}
impl BlockA {
    pub fn b(&self) -> BlockB {
        BlockB {
            previous_hash: self.previous_hash,
            timestamp: self.timestamp,
            signature: self.signature,
            pi: self.pi,
            transactions: self.transactions.iter().map(|x| x.b()).collect(),
            stakes: self.stakes.iter().map(|x| x.b()).collect(),
        }
    }
    pub fn sign(
        previous_hash: Hash,
        timestamp: u32,
        transactions: Vec<TransactionA>,
        stakes: Vec<StakeA>,
        key: &Key,
        previous_beta: &Beta,
    ) -> Result<BlockA, Error> {
        let pi = key.vrf_prove(previous_beta).map_err(Error::Key)?;
        let mut block_a = BlockA {
            hash: [0; 32],
            previous_hash,
            timestamp,
            beta: [0; 32],
            pi,
            input_public_key: [0; 33],
            signature: [0; 64],
            transactions,
            stakes,
        };
        block_a.beta = block_a.beta()?;
        block_a.hash = block_a.hash();
        block_a.signature = key.sign(&block_a.hash).map_err(Error::Key)?;
        block_a.input_public_key = key.public_key_bytes();
        Ok(block_a)
    }
    pub fn input_address(&self) -> AddressBytes {
        Key::address(&self.input_public_key)
    }
    pub fn reward(&self) -> u128 {
        self.fees() + COIN
    }
    fn fees(&self) -> u128 {
        let mut fees = 0;
        for transaction in self.transactions.iter() {
            fees += transaction.fee;
        }
        for stake in self.stakes.iter() {
            fees += stake.fee;
        }
        fees
    }
    fn transaction_hashes(&self) -> Vec<Hash> {
        self.transactions.iter().map(|x| x.hash()).collect()
    }
    fn stake_hashes(&self) -> Vec<Hash> {
        self.stakes.iter().map(|x| x.hash()).collect()
    }
}
impl BlockB {
    pub fn a(&self) -> Result<BlockA, Error> {
        let mut transactions = vec![];
        let mut stakes = vec![];
        for transaction in self.transactions.iter() {
            transactions.push(transaction.a(None).map_err(Error::Transaction)?)
        }
        for stake in self.stakes.iter() {
            stakes.push(stake.a(None).map_err(Error::Stake)?);
        }
        let block_a = BlockA {
            hash: self.hash(),
            previous_hash: self.previous_hash,
            timestamp: self.timestamp,
            beta: self.beta()?,
            pi: self.pi,
            input_public_key: self.input_public_key()?,
            signature: self.signature,
            transactions,
            stakes,
        };
        Ok(block_a)
    }
    pub fn c(&self) -> BlockC {
        BlockC {
            previous_hash: self.previous_hash,
            timestamp: self.timestamp,
            signature: self.signature,
            pi: self.pi,
            transaction_hashes: self.transaction_hashes(),
            stake_hashes: self.stake_hashes(),
        }
    }
    fn transaction_hashes(&self) -> Vec<Hash> {
        self.transactions.iter().map(|x| x.hash()).collect()
    }
    fn stake_hashes(&self) -> Vec<Hash> {
        self.stakes.iter().map(|x| x.hash()).collect()
    }
    fn input_public_key(&self) -> Result<PublicKeyBytes, Error> {
        Key::recover(&self.hash(), &self.signature).map_err(Error::Key)
    }
}
impl BlockC {
    pub fn a(
        &self,
        transactions: Vec<TransactionA>,
        stakes: Vec<StakeA>,
        beta: Option<[u8; 32]>,
        input_public_key: Option<PublicKeyBytes>,
    ) -> Result<BlockA, Error> {
        let block_b = self.b(
            transactions.iter().map(|x| x.b()).collect(),
            stakes.iter().map(|x| x.b()).collect(),
        );
        let beta = beta.unwrap_or(block_b.beta()?);
        let input_public_key = input_public_key.unwrap_or(block_b.input_public_key()?);
        let mut block_a = BlockA {
            hash: [0; 32],
            previous_hash: self.previous_hash,
            timestamp: self.timestamp,
            beta,
            pi: self.pi,
            input_public_key,
            signature: self.signature,
            transactions,
            stakes,
        };
        block_a.hash = block_a.hash();
        Ok(block_a)
    }
    pub fn b(&self, transactions: Vec<TransactionB>, stakes: Vec<StakeB>) -> BlockB {
        BlockB {
            previous_hash: self.previous_hash,
            timestamp: self.timestamp,
            signature: self.signature,
            pi: self.pi,
            transactions,
            stakes,
        }
    }
}
impl Default for BlockA {
    fn default() -> BlockA {
        BlockA {
            hash: [0; 32],
            previous_hash: [0; 32],
            timestamp: 0,
            beta: [0; 32],
            pi: [0; 81],
            input_public_key: [0; 33],
            signature: [0; 64],
            transactions: vec![],
            stakes: vec![],
        }
    }
}
impl Default for BlockB {
    fn default() -> BlockB {
        BlockB {
            previous_hash: [0; 32],
            timestamp: 0,
            signature: [0; 64],
            pi: [0; 81],
            transactions: vec![],
            stakes: vec![],
        }
    }
}
impl Default for BlockC {
    fn default() -> BlockC {
        BlockC {
            previous_hash: [0; 32],
            timestamp: 0,
            signature: [0; 64],
            pi: [0; 81],
            transaction_hashes: vec![],
            stake_hashes: vec![],
        }
    }
}
fn hash<T: Block>(block: &T) -> Hash {
    let mut hasher = Sha256::new();
    hasher.update(block.hash_input());
    hasher.finalize().into()
}
fn hash_input<T: Block>(block: &T) -> [u8; 181] {
    let mut bytes = [0; 181];
    bytes[0..32].copy_from_slice(block.get_previous_hash());
    bytes[32..64].copy_from_slice(&block.get_merkle_root_transaction());
    bytes[64..96].copy_from_slice(&block.get_merkle_root_stake());
    bytes[96..100].copy_from_slice(&block.get_timestamp().to_be_bytes());
    bytes[100..181].copy_from_slice(block.get_pi());
    bytes
}
fn merkle_root(hashes: &[Hash]) -> MerkleRoot {
    struct Hasher;
    impl Merge for Hasher {
        type Item = [u8; 32];
        fn merge(left: &Self::Item, right: &Self::Item) -> Self::Item {
            let mut hasher = Sha256::new();
            hasher.update(left);
            hasher.update(right);
            hasher.finalize().into()
        }
    }
    <ExCBMT<[u8; 32], Hasher>>::build_merkle_root(hashes)
}
fn beta<T: Block>(block: &T) -> Result<Beta, Error> {
    Key::vrf_proof_to_hash(block.get_pi()).map_err(Error::Key)
}
#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn test_hash() {
        assert_eq!(
            BlockB::default().hash(),
            [
                219, 36, 84, 162, 32, 189, 146, 241, 148, 53, 36, 177, 50, 142, 92, 103, 125, 225,
                26, 208, 20, 86, 5, 216, 113, 32, 54, 141, 75, 147, 221, 219
            ]
        );
    }
    #[test]
    fn test_genesis_beta() {
        assert_eq!(BlockA::default().beta, GENESIS_BLOCK_BETA);
    }
}

BlockA is an expanded version of the block that contains all the information required for validating the block. It includes the block's hash, beta, input public key, digital signature, a list of transactions in TransactionA format, and a list of stakes in StakeA format. BlockA is designed for in-depth analysis and computation of the block data.

BlockB is a compressed version of the block that is optimized for network transmission.

BlockC is used primarily for database storage purposes. It contains the essential information required to store the blocks, transactions and stakes in separate columns of the database efficiently. BlockC is specifically designed to store only the hashes of transaction and stake blocks, rather than the actual data. These hashes can then be used to efficiently retrieve the corresponding data from the database when necessary.

Block size

Block size exists to limit the amount of data that can be included in a single block of a blockchain. This is important because larger blocks take longer to validate, propagate across the network, and store on individual nodes. By limiting the size of blocks, the blockchain network can maintain faster transaction processing times and prevent potential bottlenecks in the system.

Filename: tofuri/core/src/lib.rs

pub type AmountBytes = [u8; AMOUNT_BYTES];
pub type Hash = [u8; 32];
pub type Checksum = [u8; 4];
pub type MerkleRoot = [u8; 32];
pub type Beta = [u8; 32];
pub type Pi = [u8; 81];
pub type AddressBytes = [u8; 20];
pub type PublicKeyBytes = [u8; 33];
pub type SecretKeyBytes = [u8; 32];
pub type SignatureBytes = [u8; 64];
pub const PREFIX_ADDRESS: &str = "0x";
pub const PREFIX_SECRET_KEY: &str = "SECRETx";
pub const BLOCK_SIZE_LIMIT: usize = 57797;
pub const MAX_TRANSMIT_SIZE: usize = 100_000;
pub const PROTOCOL_VERSION: &str = "tofuri/1.0.0";
pub const PROTOCOL_NAME: &str = "/sync/1";
pub const DECIMAL_PLACES: usize = 18;
pub const COIN: u128 = 10_u128.pow(DECIMAL_PLACES as u32);
pub const BLOCK_TIME: u32 = 60;
pub const ELAPSED: u32 = 90;
pub const EXTENSION: &str = "tofuri";
pub const AMOUNT_BYTES: usize = 4;
pub const GENESIS_BLOCK_BETA: Beta = [0; 32];
pub const GENESIS_BLOCK_PREVIOUS_HASH: Hash = [0; 32];
pub const GENESIS_BLOCK_TIMESTAMP: u32 = 1680000000;
pub const GENESIS_BLOCK_HASH: Hash = [
    0x5c, 0x85, 0xa0, 0x30, 0x4e, 0x26, 0x58, 0xbb, 0x8d, 0xa9, 0x0b, 0xf3, 0xb3, 0xcf, 0xfa, 0x50,
    0x59, 0x08, 0xdb, 0xf7, 0xfa, 0xe8, 0x16, 0xd8, 0x48, 0xb7, 0x7b, 0xc4, 0xe5, 0x08, 0xca, 0x54,
];
pub const RECOVERY_ID: i32 = 0;
pub const P2P_RATELIMIT_REQUEST_TIMEOUT: u32 = 3600;
pub const P2P_RATELIMIT_RESPONSE_TIMEOUT: u32 = 3600;
pub const P2P_RATELIMIT_REQUEST: usize = 60 + 1;
pub const P2P_RATELIMIT_RESPONSE: usize = 60 + 1;
pub const P2P_RATELIMIT_GOSSIPSUB_MESSAGE_BLOCK: usize = 1 + 1;
pub const P2P_RATELIMIT_GOSSIPSUB_MESSAGE_TRANSACTION: usize = 60 * 100;
pub const P2P_RATELIMIT_GOSSIPSUB_MESSAGE_STAKE: usize = 60 * 100;
pub const P2P_RATELIMIT_GOSSIPSUB_MESSAGE_PEERS: usize = 1 + 1;
pub const SHARE_PEERS_MAX_LEN: usize = 100;

Block rewards

Block rewards are a way to compensate stakers for their efforts in validating transactions and maintaining the network's security. The rewards are typically a portion of the transaction fees and newly minted coins that are added to the network through the creation of new blocks.

Filename: tofuri/core/src/lib.rs

pub type AmountBytes = [u8; AMOUNT_BYTES];
pub type Hash = [u8; 32];
pub type Checksum = [u8; 4];
pub type MerkleRoot = [u8; 32];
pub type Beta = [u8; 32];
pub type Pi = [u8; 81];
pub type AddressBytes = [u8; 20];
pub type PublicKeyBytes = [u8; 33];
pub type SecretKeyBytes = [u8; 32];
pub type SignatureBytes = [u8; 64];
pub const PREFIX_ADDRESS: &str = "0x";
pub const PREFIX_SECRET_KEY: &str = "SECRETx";
pub const BLOCK_SIZE_LIMIT: usize = 57797;
pub const MAX_TRANSMIT_SIZE: usize = 100_000;
pub const PROTOCOL_VERSION: &str = "tofuri/1.0.0";
pub const PROTOCOL_NAME: &str = "/sync/1";
pub const DECIMAL_PLACES: usize = 18;
pub const COIN: u128 = 10_u128.pow(DECIMAL_PLACES as u32);
pub const BLOCK_TIME: u32 = 60;
pub const ELAPSED: u32 = 90;
pub const EXTENSION: &str = "tofuri";
pub const AMOUNT_BYTES: usize = 4;
pub const GENESIS_BLOCK_BETA: Beta = [0; 32];
pub const GENESIS_BLOCK_PREVIOUS_HASH: Hash = [0; 32];
pub const GENESIS_BLOCK_TIMESTAMP: u32 = 1680000000;
pub const GENESIS_BLOCK_HASH: Hash = [
    0x5c, 0x85, 0xa0, 0x30, 0x4e, 0x26, 0x58, 0xbb, 0x8d, 0xa9, 0x0b, 0xf3, 0xb3, 0xcf, 0xfa, 0x50,
    0x59, 0x08, 0xdb, 0xf7, 0xfa, 0xe8, 0x16, 0xd8, 0x48, 0xb7, 0x7b, 0xc4, 0xe5, 0x08, 0xca, 0x54,
];
pub const RECOVERY_ID: i32 = 0;
pub const P2P_RATELIMIT_REQUEST_TIMEOUT: u32 = 3600;
pub const P2P_RATELIMIT_RESPONSE_TIMEOUT: u32 = 3600;
pub const P2P_RATELIMIT_REQUEST: usize = 60 + 1;
pub const P2P_RATELIMIT_RESPONSE: usize = 60 + 1;
pub const P2P_RATELIMIT_GOSSIPSUB_MESSAGE_BLOCK: usize = 1 + 1;
pub const P2P_RATELIMIT_GOSSIPSUB_MESSAGE_TRANSACTION: usize = 60 * 100;
pub const P2P_RATELIMIT_GOSSIPSUB_MESSAGE_STAKE: usize = 60 * 100;
pub const P2P_RATELIMIT_GOSSIPSUB_MESSAGE_PEERS: usize = 1 + 1;
pub const SHARE_PEERS_MAX_LEN: usize = 100;

Filename: tofuri/block/src/lib.rs

use merkle_cbt::merkle_tree::Merge;
use merkle_cbt::CBMT as ExCBMT;
use serde::Deserialize;
use serde::Serialize;
use serde_big_array::BigArray;
use sha2::Digest;
use sha2::Sha256;
use std::fmt;
use tofuri_core::*;
use tofuri_key::Key;
use tofuri_stake::StakeA;
use tofuri_stake::StakeB;
use tofuri_transaction::TransactionA;
use tofuri_transaction::TransactionB;
#[derive(Debug)]
pub enum Error {
    Key(tofuri_key::Error),
    Transaction(tofuri_transaction::Error),
    Stake(tofuri_stake::Error),
}
pub trait Block {
    fn get_previous_hash(&self) -> &Hash;
    fn get_merkle_root_transaction(&self) -> MerkleRoot;
    fn get_merkle_root_stake(&self) -> MerkleRoot;
    fn get_timestamp(&self) -> u32;
    fn get_pi(&self) -> &Pi;
    fn hash(&self) -> Hash;
    fn hash_input(&self) -> [u8; 181];
    fn beta(&self) -> Result<Beta, Error>;
}
impl Block for BlockA {
    fn get_previous_hash(&self) -> &Hash {
        &self.previous_hash
    }
    fn get_merkle_root_transaction(&self) -> MerkleRoot {
        merkle_root(&self.transaction_hashes())
    }
    fn get_merkle_root_stake(&self) -> MerkleRoot {
        merkle_root(&self.stake_hashes())
    }
    fn get_timestamp(&self) -> u32 {
        self.timestamp
    }
    fn get_pi(&self) -> &Pi {
        &self.pi
    }
    fn hash(&self) -> Hash {
        hash(self)
    }
    fn hash_input(&self) -> [u8; 181] {
        hash_input(self)
    }
    fn beta(&self) -> Result<Beta, Error> {
        beta(self)
    }
}
impl Block for BlockB {
    fn get_previous_hash(&self) -> &Hash {
        &self.previous_hash
    }
    fn get_merkle_root_transaction(&self) -> MerkleRoot {
        merkle_root(&self.transaction_hashes())
    }
    fn get_merkle_root_stake(&self) -> MerkleRoot {
        merkle_root(&self.stake_hashes())
    }
    fn get_timestamp(&self) -> u32 {
        self.timestamp
    }
    fn get_pi(&self) -> &Pi {
        &self.pi
    }
    fn hash(&self) -> Hash {
        hash(self)
    }
    fn hash_input(&self) -> [u8; 181] {
        hash_input(self)
    }
    fn beta(&self) -> Result<Beta, Error> {
        beta(self)
    }
}
#[derive(Serialize, Deserialize, Clone)]
pub struct BlockA {
    pub hash: Hash,
    pub previous_hash: Hash,
    pub timestamp: u32,
    pub beta: Beta,
    #[serde(with = "BigArray")]
    pub pi: Pi,
    #[serde(with = "BigArray")]
    pub input_public_key: PublicKeyBytes,
    #[serde(with = "BigArray")]
    pub signature: SignatureBytes,
    pub transactions: Vec<TransactionA>,
    pub stakes: Vec<StakeA>,
}
impl fmt::Debug for BlockA {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("BlockA")
            .field("hash", &hex::encode(&self.hash))
            .field("previous_hash", &hex::encode(&self.previous_hash))
            .field("timestamp", &self.timestamp)
            .field("beta", &hex::encode(self.beta))
            .field("pi", &hex::encode(&self.pi))
            .field("input_public_key", &hex::encode(&self.input_public_key))
            .field("signature", &hex::encode(&self.signature))
            .field("transactions", &self.transactions)
            .field("stakes", &self.stakes)
            .finish()
    }
}
#[derive(Serialize, Deserialize, Clone)]
pub struct BlockB {
    pub previous_hash: Hash,
    pub timestamp: u32,
    #[serde(with = "BigArray")]
    pub signature: SignatureBytes,
    #[serde(with = "BigArray")]
    pub pi: Pi,
    pub transactions: Vec<TransactionB>,
    pub stakes: Vec<StakeB>,
}
impl fmt::Debug for BlockB {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("BlockB")
            .field("previous_hash", &hex::encode(&self.previous_hash))
            .field("timestamp", &self.timestamp)
            .field("signature", &hex::encode(&self.signature))
            .field("pi", &hex::encode(&self.pi))
            .field("transactions", &self.transactions)
            .field("stakes", &self.stakes)
            .finish()
    }
}
#[derive(Serialize, Deserialize)]
pub struct BlockC {
    pub previous_hash: Hash,
    pub timestamp: u32,
    #[serde(with = "BigArray")]
    pub signature: SignatureBytes,
    #[serde(with = "BigArray")]
    pub pi: Pi,
    pub transaction_hashes: Vec<Hash>,
    pub stake_hashes: Vec<Hash>,
}
impl fmt::Debug for BlockC {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("BlockC")
            .field("previous_hash", &hex::encode(&self.previous_hash))
            .field("timestamp", &self.timestamp)
            .field("signature", &hex::encode(&self.signature))
            .field("pi", &hex::encode(&self.pi))
            .field(
                "transaction_hashes",
                &self
                    .transaction_hashes
                    .iter()
                    .map(hex::encode)
                    .collect::<Vec<_>>(),
            )
            .field(
                "stake_hashes",
                &self
                    .stake_hashes
                    .iter()
                    .map(hex::encode)
                    .collect::<Vec<_>>(),
            )
            .finish()
    }
}
impl BlockA {
    pub fn b(&self) -> BlockB {
        BlockB {
            previous_hash: self.previous_hash,
            timestamp: self.timestamp,
            signature: self.signature,
            pi: self.pi,
            transactions: self.transactions.iter().map(|x| x.b()).collect(),
            stakes: self.stakes.iter().map(|x| x.b()).collect(),
        }
    }
    pub fn sign(
        previous_hash: Hash,
        timestamp: u32,
        transactions: Vec<TransactionA>,
        stakes: Vec<StakeA>,
        key: &Key,
        previous_beta: &Beta,
    ) -> Result<BlockA, Error> {
        let pi = key.vrf_prove(previous_beta).map_err(Error::Key)?;
        let mut block_a = BlockA {
            hash: [0; 32],
            previous_hash,
            timestamp,
            beta: [0; 32],
            pi,
            input_public_key: [0; 33],
            signature: [0; 64],
            transactions,
            stakes,
        };
        block_a.beta = block_a.beta()?;
        block_a.hash = block_a.hash();
        block_a.signature = key.sign(&block_a.hash).map_err(Error::Key)?;
        block_a.input_public_key = key.public_key_bytes();
        Ok(block_a)
    }
    pub fn input_address(&self) -> AddressBytes {
        Key::address(&self.input_public_key)
    }
    pub fn reward(&self) -> u128 {
        self.fees() + COIN
    }
    fn fees(&self) -> u128 {
        let mut fees = 0;
        for transaction in self.transactions.iter() {
            fees += transaction.fee;
        }
        for stake in self.stakes.iter() {
            fees += stake.fee;
        }
        fees
    }
    fn transaction_hashes(&self) -> Vec<Hash> {
        self.transactions.iter().map(|x| x.hash()).collect()
    }
    fn stake_hashes(&self) -> Vec<Hash> {
        self.stakes.iter().map(|x| x.hash()).collect()
    }
}
impl BlockB {
    pub fn a(&self) -> Result<BlockA, Error> {
        let mut transactions = vec![];
        let mut stakes = vec![];
        for transaction in self.transactions.iter() {
            transactions.push(transaction.a(None).map_err(Error::Transaction)?)
        }
        for stake in self.stakes.iter() {
            stakes.push(stake.a(None).map_err(Error::Stake)?);
        }
        let block_a = BlockA {
            hash: self.hash(),
            previous_hash: self.previous_hash,
            timestamp: self.timestamp,
            beta: self.beta()?,
            pi: self.pi,
            input_public_key: self.input_public_key()?,
            signature: self.signature,
            transactions,
            stakes,
        };
        Ok(block_a)
    }
    pub fn c(&self) -> BlockC {
        BlockC {
            previous_hash: self.previous_hash,
            timestamp: self.timestamp,
            signature: self.signature,
            pi: self.pi,
            transaction_hashes: self.transaction_hashes(),
            stake_hashes: self.stake_hashes(),
        }
    }
    fn transaction_hashes(&self) -> Vec<Hash> {
        self.transactions.iter().map(|x| x.hash()).collect()
    }
    fn stake_hashes(&self) -> Vec<Hash> {
        self.stakes.iter().map(|x| x.hash()).collect()
    }
    fn input_public_key(&self) -> Result<PublicKeyBytes, Error> {
        Key::recover(&self.hash(), &self.signature).map_err(Error::Key)
    }
}
impl BlockC {
    pub fn a(
        &self,
        transactions: Vec<TransactionA>,
        stakes: Vec<StakeA>,
        beta: Option<[u8; 32]>,
        input_public_key: Option<PublicKeyBytes>,
    ) -> Result<BlockA, Error> {
        let block_b = self.b(
            transactions.iter().map(|x| x.b()).collect(),
            stakes.iter().map(|x| x.b()).collect(),
        );
        let beta = beta.unwrap_or(block_b.beta()?);
        let input_public_key = input_public_key.unwrap_or(block_b.input_public_key()?);
        let mut block_a = BlockA {
            hash: [0; 32],
            previous_hash: self.previous_hash,
            timestamp: self.timestamp,
            beta,
            pi: self.pi,
            input_public_key,
            signature: self.signature,
            transactions,
            stakes,
        };
        block_a.hash = block_a.hash();
        Ok(block_a)
    }
    pub fn b(&self, transactions: Vec<TransactionB>, stakes: Vec<StakeB>) -> BlockB {
        BlockB {
            previous_hash: self.previous_hash,
            timestamp: self.timestamp,
            signature: self.signature,
            pi: self.pi,
            transactions,
            stakes,
        }
    }
}
impl Default for BlockA {
    fn default() -> BlockA {
        BlockA {
            hash: [0; 32],
            previous_hash: [0; 32],
            timestamp: 0,
            beta: [0; 32],
            pi: [0; 81],
            input_public_key: [0; 33],
            signature: [0; 64],
            transactions: vec![],
            stakes: vec![],
        }
    }
}
impl Default for BlockB {
    fn default() -> BlockB {
        BlockB {
            previous_hash: [0; 32],
            timestamp: 0,
            signature: [0; 64],
            pi: [0; 81],
            transactions: vec![],
            stakes: vec![],
        }
    }
}
impl Default for BlockC {
    fn default() -> BlockC {
        BlockC {
            previous_hash: [0; 32],
            timestamp: 0,
            signature: [0; 64],
            pi: [0; 81],
            transaction_hashes: vec![],
            stake_hashes: vec![],
        }
    }
}
fn hash<T: Block>(block: &T) -> Hash {
    let mut hasher = Sha256::new();
    hasher.update(block.hash_input());
    hasher.finalize().into()
}
fn hash_input<T: Block>(block: &T) -> [u8; 181] {
    let mut bytes = [0; 181];
    bytes[0..32].copy_from_slice(block.get_previous_hash());
    bytes[32..64].copy_from_slice(&block.get_merkle_root_transaction());
    bytes[64..96].copy_from_slice(&block.get_merkle_root_stake());
    bytes[96..100].copy_from_slice(&block.get_timestamp().to_be_bytes());
    bytes[100..181].copy_from_slice(block.get_pi());
    bytes
}
fn merkle_root(hashes: &[Hash]) -> MerkleRoot {
    struct Hasher;
    impl Merge for Hasher {
        type Item = [u8; 32];
        fn merge(left: &Self::Item, right: &Self::Item) -> Self::Item {
            let mut hasher = Sha256::new();
            hasher.update(left);
            hasher.update(right);
            hasher.finalize().into()
        }
    }
    <ExCBMT<[u8; 32], Hasher>>::build_merkle_root(hashes)
}
fn beta<T: Block>(block: &T) -> Result<Beta, Error> {
    Key::vrf_proof_to_hash(block.get_pi()).map_err(Error::Key)
}
#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn test_hash() {
        assert_eq!(
            BlockB::default().hash(),
            [
                219, 36, 84, 162, 32, 189, 146, 241, 148, 53, 36, 177, 50, 142, 92, 103, 125, 225,
                26, 208, 20, 86, 5, 216, 113, 32, 54, 141, 75, 147, 221, 219
            ]
        );
    }
    #[test]
    fn test_genesis_beta() {
        assert_eq!(BlockA::default().beta, GENESIS_BLOCK_BETA);
    }
}